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 */
|
||||
#define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
|
||||
#define SHELLFOLDER_WANTSFORPARSING 0x00000002
|
||||
|
||||
static HRESULT register_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 };
|
||||
static WCHAR const shellex_keyname[8] = {
|
||||
'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] = {
|
||||
'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
|
||||
'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
|
||||
static char const tmodel_valuename[] = "ThreadingModel";
|
||||
static char const wfparsing_valuename[] = "WantsFORPARSING";
|
||||
|
||||
/***********************************************************************
|
||||
* static helper functions
|
||||
|
@ -281,6 +285,19 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list)
|
|||
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) {
|
||||
res = register_key_defvalueA(clsid_key, clsid_keyname,
|
||||
list->clsid_str);
|
||||
|
@ -503,10 +520,11 @@ static struct regsvr_coclass const coclass_list[] = {
|
|||
"Apartment",
|
||||
},
|
||||
{ &CLSID_UnixFolder,
|
||||
"My UNIX Filesystem",
|
||||
"/",
|
||||
NULL,
|
||||
"shell32.dll",
|
||||
"Apartment"
|
||||
"Apartment",
|
||||
SHELLFOLDER_WANTSFORPARSING
|
||||
},
|
||||
{ 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) {
|
||||
LPITEMIDLIST pidl;
|
||||
struct stat fileStat;
|
||||
int cSubDirs, cPidlLen;
|
||||
char *pSlash, swap;
|
||||
int cSubDirs, cPidlLen, res;
|
||||
char *pSlash;
|
||||
|
||||
TRACE("path=%s, ppidl=%p", debugstr_a(path), ppidl);
|
||||
|
||||
/* Fail, if no absolute path given */
|
||||
if (!ppidl || !path || path[0] != '/') return FALSE;
|
||||
|
||||
/* Skip the '/' prefix */
|
||||
path++;
|
||||
|
||||
/* Count the number of sub-directories in the path */
|
||||
cSubDirs = 0;
|
||||
pSlash = path;
|
||||
pSlash = strchr(path, '/');
|
||||
while (pSlash) {
|
||||
cSubDirs++;
|
||||
pSlash = strchr(pSlash+1, '/');
|
||||
|
@ -195,26 +198,19 @@ static BOOL UNIXFS_path_to_pidl(char *path, LPITEMIDLIST *ppidl) {
|
|||
if (!pidl) return FALSE;
|
||||
|
||||
/* Concatenate the SHITEMIDs of the sub-directories. */
|
||||
pSlash = path; /* First character of path is guaranteed to be '/' */
|
||||
while (*path) {
|
||||
pSlash = strchr(path, '/');
|
||||
if (pSlash) {
|
||||
/* For the stat call, we temporarily replace the char
|
||||
* after the next '/' with a '\0'. */
|
||||
swap = pSlash[1];
|
||||
pSlash[1] = '\0';
|
||||
if (stat(path, &fileStat)) {
|
||||
pSlash[1] = swap;
|
||||
return FALSE;
|
||||
}
|
||||
pSlash[1] = swap;
|
||||
*pSlash = '\0';
|
||||
res = stat(path, &fileStat);
|
||||
*pSlash = '/';
|
||||
if (res) return FALSE;
|
||||
} else {
|
||||
/* We are at the last item in path. */
|
||||
if (stat(path, &fileStat)) return FALSE;
|
||||
}
|
||||
|
||||
path = UNIXFS_build_shitemid(path, &fileStat, pidl);
|
||||
pidl = ILGetNext(pidl);
|
||||
pSlash = strchr(path, '/');
|
||||
}
|
||||
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;
|
||||
current = ILGetNext(current);
|
||||
}
|
||||
if (!current->mkid.cb) return FALSE;
|
||||
root = ILGetNext(current);
|
||||
root = current = ILGetNext(current);
|
||||
|
||||
/* Determine the path's length bytes */
|
||||
dwPathLen = 1; /* For the terminating '\0' */
|
||||
current = root;
|
||||
dwPathLen = 2; /* For the '/' prefix and the terminating '\0' */
|
||||
while (current->mkid.cb) {
|
||||
dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
|
||||
current = ILGetNext(current);
|
||||
|
@ -268,6 +262,7 @@ static BOOL UNIXFS_pidl_to_path(LPCITEMIDLIST pidl, PSZ *path) {
|
|||
return FALSE;
|
||||
}
|
||||
current = root;
|
||||
*pNextDir++ = '/';
|
||||
while (current->mkid.cb) {
|
||||
memcpy(pNextDir, _ILGetTextPointer(current), 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;
|
||||
*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);
|
||||
if (!dir) {
|
||||
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,
|
||||
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);
|
||||
|
||||
lpName->uType = STRRET_CSTR;
|
||||
if (!pidl->mkid.cb) {
|
||||
strcpy(lpName->u.cStr, "");
|
||||
return S_OK;
|
||||
}
|
||||
if ((GET_SHGDN_FOR(uFlags) == SHGDN_FORPARSING) &&
|
||||
(GET_SHGDN_RELATION(uFlags) != SHGDN_INFOLDER))
|
||||
{
|
||||
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)) {
|
||||
STRRET strSubfolderName;
|
||||
IShellFolder *pSubFolder;
|
||||
HRESULT hr;
|
||||
LPITEMIDLIST pidlFirst;
|
||||
|
||||
pidlFirst = ILCloneFirst(pidl);
|
||||
if (!pidlFirst) {
|
||||
WARN("ILCloneFirst failed!\n");
|
||||
return E_FAIL;
|
||||
hr = IShellFolder_GetDisplayNameOf(pSubFolder, (LPITEMIDLIST)&emptyIDL, uFlags, lpName);
|
||||
IShellFolder_Release(pSubFolder);
|
||||
}
|
||||
|
||||
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 {
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue