Make the root of the shell extension map to the root of the unix

filesystem.
This commit is contained in:
Michael Jung 2005-05-07 12:17:02 +00:00 committed by Alexandre Julliard
parent 9e40b70d90
commit fc40dcf985
2 changed files with 57 additions and 86 deletions

View File

@ -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 */
}; };

View File

@ -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,