Make the root of the shell extension map to the root of the unix
filesystem.
This commit is contained in:
parent
9e40b70d90
commit
fc40dcf985
|
@ -70,6 +70,7 @@ struct regsvr_coclass
|
||||||
|
|
||||||
/* flags for regsvr_coclass.flags */
|
/* flags for regsvr_coclass.flags */
|
||||||
#define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
|
#define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
|
||||||
|
#define SHELLFOLDER_WANTSFORPARSING 0x00000002
|
||||||
|
|
||||||
static HRESULT register_coclasses(struct regsvr_coclass const *list);
|
static HRESULT register_coclasses(struct regsvr_coclass const *list);
|
||||||
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
|
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
|
||||||
|
@ -102,10 +103,13 @@ static WCHAR const progid_keyname[7] = {
|
||||||
'P', 'r', 'o', 'g', 'I', 'D', 0 };
|
'P', 'r', 'o', 'g', 'I', 'D', 0 };
|
||||||
static WCHAR const shellex_keyname[8] = {
|
static WCHAR const shellex_keyname[8] = {
|
||||||
's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
|
's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
|
||||||
|
static WCHAR const shellfolder_keyname[12] = {
|
||||||
|
'S', 'h', 'e', 'l', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
|
||||||
static WCHAR const mcdm_keyname[21] = {
|
static WCHAR const mcdm_keyname[21] = {
|
||||||
'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
|
'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
|
||||||
'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
|
'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
|
||||||
static char const tmodel_valuename[] = "ThreadingModel";
|
static char const tmodel_valuename[] = "ThreadingModel";
|
||||||
|
static char const wfparsing_valuename[] = "WantsFORPARSING";
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* static helper functions
|
* static helper functions
|
||||||
|
@ -281,6 +285,19 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list)
|
||||||
RegCloseKey(mcdm_key);
|
RegCloseKey(mcdm_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (list->flags & SHELLFOLDER_WANTSFORPARSING) {
|
||||||
|
HKEY shellfolder_key;
|
||||||
|
|
||||||
|
res = RegCreateKeyExW(clsid_key, shellfolder_keyname, 0, NULL, 0,
|
||||||
|
KEY_READ | KEY_WRITE, NULL,
|
||||||
|
&shellfolder_key, NULL);
|
||||||
|
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||||
|
res = RegSetValueExA(shellfolder_key, wfparsing_valuename, 0, REG_SZ,
|
||||||
|
"", 1);
|
||||||
|
RegCloseKey(shellfolder_key);
|
||||||
|
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||||
|
}
|
||||||
|
|
||||||
if (list->clsid_str) {
|
if (list->clsid_str) {
|
||||||
res = register_key_defvalueA(clsid_key, clsid_keyname,
|
res = register_key_defvalueA(clsid_key, clsid_keyname,
|
||||||
list->clsid_str);
|
list->clsid_str);
|
||||||
|
@ -503,10 +520,11 @@ static struct regsvr_coclass const coclass_list[] = {
|
||||||
"Apartment",
|
"Apartment",
|
||||||
},
|
},
|
||||||
{ &CLSID_UnixFolder,
|
{ &CLSID_UnixFolder,
|
||||||
"My UNIX Filesystem",
|
"/",
|
||||||
NULL,
|
NULL,
|
||||||
"shell32.dll",
|
"shell32.dll",
|
||||||
"Apartment"
|
"Apartment",
|
||||||
|
SHELLFOLDER_WANTSFORPARSING
|
||||||
},
|
},
|
||||||
{ NULL } /* list terminator */
|
{ NULL } /* list terminator */
|
||||||
};
|
};
|
||||||
|
|
|
@ -172,17 +172,20 @@ static char* UNIXFS_build_shitemid(char *name, struct stat *pStat, void *buffer)
|
||||||
static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
|
static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
|
||||||
LPITEMIDLIST pidl;
|
LPITEMIDLIST pidl;
|
||||||
struct stat fileStat;
|
struct stat fileStat;
|
||||||
int cSubDirs, cPidlLen;
|
int cSubDirs, cPidlLen, res;
|
||||||
char *pSlash, swap;
|
char *pSlash;
|
||||||
|
|
||||||
TRACE("path=%s, ppidl=%p", debugstr_a(path), ppidl);
|
TRACE("path=%s, ppidl=%p", debugstr_a(path), ppidl);
|
||||||
|
|
||||||
/* Fail, if no absolute path given */
|
/* Fail, if no absolute path given */
|
||||||
if (!ppidl || !path || path[0] != '/') return FALSE;
|
if (!ppidl || !path || path[0] != '/') return FALSE;
|
||||||
|
|
||||||
|
/* Skip the '/' prefix */
|
||||||
|
path++;
|
||||||
|
|
||||||
/* Count the number of sub-directories in the path */
|
/* Count the number of sub-directories in the path */
|
||||||
cSubDirs = 0;
|
cSubDirs = 0;
|
||||||
pSlash = path;
|
pSlash = strchr(path, '/');
|
||||||
while (pSlash) {
|
while (pSlash) {
|
||||||
cSubDirs++;
|
cSubDirs++;
|
||||||
pSlash = strchr(pSlash+1, '/');
|
pSlash = strchr(pSlash+1, '/');
|
||||||
|
@ -195,26 +198,19 @@ static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
|
||||||
if (!pidl) return FALSE;
|
if (!pidl) return FALSE;
|
||||||
|
|
||||||
/* Concatenate the SHITEMIDs of the sub-directories. */
|
/* Concatenate the SHITEMIDs of the sub-directories. */
|
||||||
pSlash = path; /* First character of path is guaranteed to be '/' */
|
|
||||||
while (*path) {
|
while (*path) {
|
||||||
|
pSlash = strchr(path, '/');
|
||||||
if (pSlash) {
|
if (pSlash) {
|
||||||
/* For the stat call, we temporarily replace the char
|
*pSlash = '\0';
|
||||||
* after the next '/' with a '\0'. */
|
res = stat(path, &fileStat);
|
||||||
swap = pSlash[1];
|
*pSlash = '/';
|
||||||
pSlash[1] = '\0';
|
if (res) return FALSE;
|
||||||
if (stat(path, &fileStat)) {
|
|
||||||
pSlash[1] = swap;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
pSlash[1] = swap;
|
|
||||||
} else {
|
} else {
|
||||||
/* We are at the last item in path. */
|
|
||||||
if (stat(path, &fileStat)) return FALSE;
|
if (stat(path, &fileStat)) return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = UNIXFS_build_shitemid(path, &fileStat, pidl);
|
path = UNIXFS_build_shitemid(path, &fileStat, pidl);
|
||||||
pidl = ILGetNext(pidl);
|
pidl = ILGetNext(pidl);
|
||||||
pSlash = strchr(path, '/');
|
|
||||||
}
|
}
|
||||||
pidl->mkid.cb = 0; /* Terminate the ITEMIDLIST */
|
pidl->mkid.cb = 0; /* Terminate the ITEMIDLIST */
|
||||||
|
|
||||||
|
@ -250,12 +246,10 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
|
||||||
if (pData->type == PT_GUID && IsEqualIID(&CLSID_UnixFolder, &pData->u.guid.guid)) break;
|
if (pData->type == PT_GUID && IsEqualIID(&CLSID_UnixFolder, &pData->u.guid.guid)) break;
|
||||||
current = ILGetNext(current);
|
current = ILGetNext(current);
|
||||||
}
|
}
|
||||||
if (!current->mkid.cb) return FALSE;
|
root = current = ILGetNext(current);
|
||||||
root = ILGetNext(current);
|
|
||||||
|
|
||||||
/* Determine the path's length bytes */
|
/* Determine the path's length bytes */
|
||||||
dwPathLen = 1; /* For the terminating '\0' */
|
dwPathLen = 2; /* For the '/' prefix and the terminating '\0' */
|
||||||
current = root;
|
|
||||||
while (current->mkid.cb) {
|
while (current->mkid.cb) {
|
||||||
dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
|
dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
|
||||||
current = ILGetNext(current);
|
current = ILGetNext(current);
|
||||||
|
@ -268,6 +262,7 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
current = root;
|
current = root;
|
||||||
|
*pNextDir++ = '/';
|
||||||
while (current->mkid.cb) {
|
while (current->mkid.cb) {
|
||||||
memcpy(pNextDir, _ILGetTextPointer(current), NAME_LEN_FROM_LPSHITEMID(current));
|
memcpy(pNextDir, _ILGetTextPointer(current), NAME_LEN_FROM_LPSHITEMID(current));
|
||||||
pNextDir += NAME_LEN_FROM_LPSHITEMID(current);
|
pNextDir += NAME_LEN_FROM_LPSHITEMID(current);
|
||||||
|
@ -312,28 +307,6 @@ static BOOL UNIXFS_build_subfolder_pidls(const char *path, LPITEMIDLIST **apidl,
|
||||||
*apidl = NULL;
|
*apidl = NULL;
|
||||||
*pCount = 0;
|
*pCount = 0;
|
||||||
|
|
||||||
/* Special case for 'My UNIX Filesystem' shell folder:
|
|
||||||
* The unix root directory is the only child of 'My UNIX Filesystem'.
|
|
||||||
*/
|
|
||||||
if (!strlen(path)) {
|
|
||||||
LPSHITEMID pid;
|
|
||||||
|
|
||||||
if (stat("/", &fileStat)) return FALSE;
|
|
||||||
pid = (LPSHITEMID)SHAlloc(SHITEMID_LEN_FROM_NAME_LEN(0)+sizeof(USHORT));
|
|
||||||
UNIXFS_build_shitemid("", &fileStat, pid);
|
|
||||||
memset(((PBYTE)pid)+pid->cb, 0, sizeof(USHORT));
|
|
||||||
|
|
||||||
*apidl = SHAlloc(sizeof(LPITEMIDLIST));
|
|
||||||
if (!apidl) {
|
|
||||||
WARN("SHAlloc failed!\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
(*apidl)[0] = (LPITEMIDLIST)pid;
|
|
||||||
*pCount = 1;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = opendir(path);
|
dir = opendir(path);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
WARN("Failed to open directory '%s'.\n", path);
|
WARN("Failed to open directory '%s'.\n", path);
|
||||||
|
@ -774,54 +747,34 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* ifac
|
||||||
static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* iface,
|
static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* iface,
|
||||||
LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET* lpName)
|
LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET* lpName)
|
||||||
{
|
{
|
||||||
char *pszFileName;
|
UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
TRACE("(iface=%p, pidl=%p, uFlags=%lx, lpName=%p)\n", iface, pidl, uFlags, lpName);
|
TRACE("(iface=%p, pidl=%p, uFlags=%lx, lpName=%p)\n", iface, pidl, uFlags, lpName);
|
||||||
|
|
||||||
lpName->uType = STRRET_CSTR;
|
if ((GET_SHGDN_FOR(uFlags) == SHGDN_FORPARSING) &&
|
||||||
if (!pidl->mkid.cb) {
|
(GET_SHGDN_RELATION(uFlags) != SHGDN_INFOLDER))
|
||||||
strcpy(lpName->u.cStr, "");
|
{
|
||||||
return S_OK;
|
if (!pidl->mkid.cb) {
|
||||||
}
|
lpName->uType = STRRET_CSTR;
|
||||||
|
strcpy(lpName->u.cStr, This->m_pszPath);
|
||||||
|
} else {
|
||||||
|
IShellFolder *pSubFolder;
|
||||||
|
USHORT emptyIDL = 0;
|
||||||
|
|
||||||
pszFileName = _ILGetTextPointer(pidl);
|
hr = IShellFolder_BindToObject(iface, pidl, NULL, &IID_IShellFolder, (void**)&pSubFolder);
|
||||||
|
if (!SUCCEEDED(hr)) return hr;
|
||||||
|
|
||||||
if ((uFlags & SHGDN_FORPARSING) && !(uFlags & SHGDN_INFOLDER)) {
|
hr = IShellFolder_GetDisplayNameOf(pSubFolder, (LPITEMIDLIST)&emptyIDL, uFlags, lpName);
|
||||||
STRRET strSubfolderName;
|
IShellFolder_Release(pSubFolder);
|
||||||
IShellFolder *pSubFolder;
|
|
||||||
HRESULT hr;
|
|
||||||
LPITEMIDLIST pidlFirst;
|
|
||||||
|
|
||||||
pidlFirst = ILCloneFirst(pidl);
|
|
||||||
if (!pidlFirst) {
|
|
||||||
WARN("ILCloneFirst failed!\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IShellFolder_BindToObject(iface, pidlFirst, NULL, &IID_IShellFolder,
|
|
||||||
(void**)&pSubFolder);
|
|
||||||
if (!SUCCEEDED(hr)) {
|
|
||||||
WARN("BindToObject failed!\n");
|
|
||||||
ILFree(pidlFirst);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ILFree(pidlFirst);
|
|
||||||
|
|
||||||
hr = IShellFolder_GetDisplayNameOf(pSubFolder, ILGetNext(pidl), uFlags, &strSubfolderName);
|
|
||||||
if (!SUCCEEDED(hr)) {
|
|
||||||
WARN("GetDisplayNameOf failed!\n");
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(lpName->u.cStr, MAX_PATH, "%s/%s", pszFileName, strSubfolderName.u.cStr);
|
|
||||||
|
|
||||||
IShellFolder_Release(pSubFolder);
|
|
||||||
} else {
|
} else {
|
||||||
strcpy(lpName->u.cStr, *pszFileName ? pszFileName : "/");
|
char *pszFileName = _ILGetTextPointer(pidl);
|
||||||
|
lpName->uType = STRRET_CSTR;
|
||||||
|
strcpy(lpName->u.cStr, pszFileName ? pszFileName : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* This, HWND hwnd,
|
static HRESULT WINAPI UnixFolder_IShellFolder2_SetNameOf(IShellFolder2* This, HWND hwnd,
|
||||||
|
|
Loading…
Reference in New Issue