- Move target folder initialization to a dedicated function.
- Use this function in BindToObject (should be faster). - Special handling for FolderShortcut objects in Initialize method. - Removed a todo_wine from a no longer failing unit test.
This commit is contained in:
parent
828086ef93
commit
329f4edefc
|
@ -190,8 +190,8 @@ typedef struct _UnixFolder {
|
|||
const IPersistPropertyBagVtbl *lpIPersistPropertyBagVtbl;
|
||||
const ISFHelperVtbl *lpISFHelperVtbl;
|
||||
LONG m_cRef;
|
||||
CHAR *m_pszPath;
|
||||
LPITEMIDLIST m_pidlLocation;
|
||||
CHAR *m_pszPath; /* Target path of the shell folder */
|
||||
LPITEMIDLIST m_pidlLocation; /* Location in the shell namespace */
|
||||
DWORD m_dwPathMode;
|
||||
DWORD m_dwAttributes;
|
||||
const CLSID *m_pCLSID;
|
||||
|
@ -581,6 +581,71 @@ static BOOL UNIXFS_path_to_pidl(UnixFolder *pUnixFolder, const WCHAR *path, LPIT
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* UNIXFS_initialize_target_folder [Internal]
|
||||
*
|
||||
* Initialize the m_pszPath member of an UnixFolder, given an absolute unix
|
||||
* base path and a relative ITEMIDLIST. Leave the m_pidlLocation member, which
|
||||
* specifies the location in the shell namespace alone.
|
||||
*
|
||||
* PARAMS
|
||||
* This [IO] The UnixFolder, whose target path is to be initialized
|
||||
* szBasePath [I] The absolute base path
|
||||
* pidlSubFolder [I] Relative part of the path, given as an ITEMIDLIST
|
||||
* dwAttributes [I] Attributes to add to the Folders m_dwAttributes member
|
||||
* (Used to pass the SFGAO_FILESYSTEM flag down the path)
|
||||
* RETURNS
|
||||
* Success: S_OK,
|
||||
* Failure: E_FAIL
|
||||
*/
|
||||
static HRESULT UNIXFS_initialize_target_folder(UnixFolder *This, const char *szBasePath,
|
||||
LPCITEMIDLIST pidlSubFolder, DWORD dwAttributes)
|
||||
{
|
||||
LPCITEMIDLIST current = pidlSubFolder;
|
||||
DWORD dwPathLen = strlen(szBasePath)+1;
|
||||
struct stat statPrefix;
|
||||
char *pNextDir;
|
||||
|
||||
/* Determine the path's length bytes */
|
||||
while (current && current->mkid.cb) {
|
||||
dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
|
||||
current = ILGetNext(current);
|
||||
};
|
||||
|
||||
/* Build the path and compute the attributes*/
|
||||
This->m_dwAttributes =
|
||||
dwAttributes|SFGAO_FOLDER|SFGAO_HASSUBFOLDER|SFGAO_FILESYSANCESTOR|SFGAO_CANRENAME;
|
||||
This->m_pszPath = pNextDir = SHAlloc(dwPathLen);
|
||||
if (!This->m_pszPath) {
|
||||
WARN("SHAlloc failed!\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
current = pidlSubFolder;
|
||||
strcpy(pNextDir, szBasePath);
|
||||
pNextDir += strlen(szBasePath);
|
||||
if (This->m_dwPathMode == PATHMODE_UNIX || IsEqualCLSID(&CLSID_MyDocuments, This->m_pCLSID))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
|
||||
*pNextDir = '\0';
|
||||
if (!stat(This->m_pszPath, &statPrefix) && UNIXFS_is_dos_device(&statPrefix))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
}
|
||||
while (current && current->mkid.cb) {
|
||||
memcpy(pNextDir, _ILGetTextPointer(current), NAME_LEN_FROM_LPSHITEMID(current));
|
||||
pNextDir += NAME_LEN_FROM_LPSHITEMID(current);
|
||||
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
|
||||
*pNextDir = '\0';
|
||||
if (!stat(This->m_pszPath, &statPrefix) && UNIXFS_is_dos_device(&statPrefix))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
}
|
||||
*pNextDir++ = '/';
|
||||
current = ILGetNext(current);
|
||||
}
|
||||
*pNextDir='\0';
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* UnixFolder
|
||||
*
|
||||
|
@ -707,23 +772,33 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface
|
|||
UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
|
||||
IPersistFolder3 *persistFolder;
|
||||
HRESULT hr;
|
||||
const CLSID *clsidChild;
|
||||
|
||||
TRACE("(iface=%p, pidl=%p, pbcReserver=%p, riid=%p, ppvOut=%p)\n",
|
||||
iface, pidl, pbcReserved, riid, ppvOut);
|
||||
|
||||
if (!pidl || !pidl->mkid.cb)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = CreateUnixFolder(NULL, &IID_IPersistFolder3, (void**)&persistFolder, This->m_pCLSID);
|
||||
|
||||
if (IsEqualCLSID(This->m_pCLSID, &CLSID_FolderShortcut)) {
|
||||
/* Children of FolderShortcuts are ShellFSFolders on Windows.
|
||||
* Unixfs' counterpart is UnixDosFolder. */
|
||||
clsidChild = &CLSID_UnixDosFolder;
|
||||
} else {
|
||||
clsidChild = This->m_pCLSID;
|
||||
}
|
||||
|
||||
hr = CreateUnixFolder(NULL, &IID_IPersistFolder3, (void**)&persistFolder, clsidChild);
|
||||
if (!SUCCEEDED(hr)) return hr;
|
||||
hr = IPersistFolder_QueryInterface(persistFolder, riid, (void**)ppvOut);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPITEMIDLIST pidlSubFolder = ILCombine(This->m_pidlLocation, pidl);
|
||||
hr = IPersistFolder3_Initialize(persistFolder, pidlSubFolder);
|
||||
ILFree(pidlSubFolder);
|
||||
}
|
||||
|
||||
UnixFolder *subfolder = ADJUST_THIS(UnixFolder, IPersistFolder3, persistFolder);
|
||||
subfolder->m_pidlLocation = ILCombine(This->m_pidlLocation, pidl);
|
||||
hr = UNIXFS_initialize_target_folder(subfolder, This->m_pszPath, pidl,
|
||||
This->m_dwAttributes & SFGAO_FILESYSTEM);
|
||||
}
|
||||
|
||||
IPersistFolder3_Release(persistFolder);
|
||||
|
||||
return hr;
|
||||
|
@ -1221,10 +1296,8 @@ static HRESULT WINAPI UnixFolder_IPersistFolder3_GetClassID(IPersistFolder3* ifa
|
|||
static HRESULT WINAPI UnixFolder_IPersistFolder3_Initialize(IPersistFolder3* iface, LPCITEMIDLIST pidl)
|
||||
{
|
||||
UnixFolder *This = ADJUST_THIS(UnixFolder, IPersistFolder3, iface);
|
||||
struct stat statPrefix;
|
||||
LPCITEMIDLIST current = pidl, root;
|
||||
DWORD dwPathLen;
|
||||
char *pNextDir, szBasePath[FILENAME_MAX] = "/";
|
||||
LPCITEMIDLIST current = pidl;
|
||||
char szBasePath[FILENAME_MAX] = "/";
|
||||
|
||||
TRACE("(iface=%p, pidl=%p)\n", iface, pidl);
|
||||
|
||||
|
@ -1243,11 +1316,8 @@ static HRESULT WINAPI UnixFolder_IPersistFolder3_Initialize(IPersistFolder3* ifa
|
|||
PathAddBackslashW(wszMyDocumentsPath);
|
||||
if (!UNIXFS_get_unix_path(wszMyDocumentsPath, szBasePath))
|
||||
return E_FAIL;
|
||||
dwPathLen = strlen(szBasePath) + 1;
|
||||
} else {
|
||||
dwPathLen = 2; /* For the '/' prefix and the terminating '\0' */
|
||||
}
|
||||
root = current = ILGetNext(current);
|
||||
}
|
||||
current = ILGetNext(current);
|
||||
} else if (_ILIsDesktop(pidl) || _ILIsValue(pidl) || _ILIsFolder(pidl)) {
|
||||
/* Path rooted at Desktop */
|
||||
WCHAR wszDesktopPath[MAX_PATH];
|
||||
|
@ -1256,52 +1326,21 @@ static HRESULT WINAPI UnixFolder_IPersistFolder3_Initialize(IPersistFolder3* ifa
|
|||
PathAddBackslashW(wszDesktopPath);
|
||||
if (!UNIXFS_get_unix_path(wszDesktopPath, szBasePath))
|
||||
return E_FAIL;
|
||||
dwPathLen = strlen(szBasePath) + 1;
|
||||
root = current = pidl;
|
||||
current = pidl;
|
||||
} else if (IsEqualCLSID(This->m_pCLSID, &CLSID_FolderShortcut)) {
|
||||
/* FolderShortcuts' Initialize method only sets the ITEMIDLIST, which
|
||||
* specifies the location in the shell namespace, but leaves the
|
||||
* target folder (m_pszPath) alone. See unit tests in tests/shlfolder.c */
|
||||
This->m_pidlLocation = ILClone(pidl);
|
||||
return S_OK;
|
||||
} else {
|
||||
ERR("Unknown pidl type!\n");
|
||||
pdump(pidl);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
/* Determine the path's length bytes */
|
||||
while (current && current->mkid.cb) {
|
||||
dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
|
||||
current = ILGetNext(current);
|
||||
};
|
||||
|
||||
/* Build the path */
|
||||
This->m_dwAttributes = SFGAO_FOLDER|SFGAO_HASSUBFOLDER|SFGAO_FILESYSANCESTOR|SFGAO_CANRENAME;
|
||||
|
||||
This->m_pidlLocation = ILClone(pidl);
|
||||
This->m_pszPath = pNextDir = SHAlloc(dwPathLen);
|
||||
if (!This->m_pszPath || !This->m_pidlLocation) {
|
||||
WARN("SHAlloc failed!\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
current = root;
|
||||
strcpy(pNextDir, szBasePath);
|
||||
pNextDir += strlen(szBasePath);
|
||||
if (This->m_dwPathMode == PATHMODE_UNIX || IsEqualCLSID(&CLSID_MyDocuments, This->m_pCLSID))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
|
||||
*pNextDir = '\0';
|
||||
if (!stat(This->m_pszPath, &statPrefix) && UNIXFS_is_dos_device(&statPrefix))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
}
|
||||
while (current && current->mkid.cb) {
|
||||
memcpy(pNextDir, _ILGetTextPointer(current), NAME_LEN_FROM_LPSHITEMID(current));
|
||||
pNextDir += NAME_LEN_FROM_LPSHITEMID(current);
|
||||
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
|
||||
*pNextDir = '\0';
|
||||
if (!stat(This->m_pszPath, &statPrefix) && UNIXFS_is_dos_device(&statPrefix))
|
||||
This->m_dwAttributes |= SFGAO_FILESYSTEM;
|
||||
}
|
||||
*pNextDir++ = '/';
|
||||
current = ILGetNext(current);
|
||||
}
|
||||
*pNextDir='\0';
|
||||
|
||||
return S_OK;
|
||||
return UNIXFS_initialize_target_folder(This, szBasePath, current, 0);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI UnixFolder_IPersistFolder3_GetCurFolder(IPersistFolder3* iface, LPITEMIDLIST* ppidl)
|
||||
|
@ -1336,7 +1375,9 @@ static HRESULT WINAPI UnixFolder_IPersistFolder3_InitializeEx(IPersistFolder3 *i
|
|||
return E_FAIL;
|
||||
}
|
||||
} else if (*ppfti->szTargetParsingName) {
|
||||
if (!UNIXFS_get_unix_path(ppfti->szTargetParsingName, szTargetPath)) {
|
||||
lstrcpyW(wszTargetDosPath, ppfti->szTargetParsingName);
|
||||
PathAddBackslashW(wszTargetDosPath);
|
||||
if (!UNIXFS_get_unix_path(wszTargetDosPath, szTargetPath)) {
|
||||
return E_FAIL;
|
||||
}
|
||||
} else if (ppfti->pidlTargetFolder) {
|
||||
|
|
|
@ -876,7 +876,9 @@ void test_FolderShortcut(void) {
|
|||
':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
|
||||
'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
|
||||
WCHAR wszSomeSubFolder[] = { 'S','u','b','F','o','l','d','e','r', 0};
|
||||
|
||||
static const GUID CLSID_UnixDosFolder =
|
||||
{0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
|
||||
|
||||
if (!pSHGetSpecialFolderPathW || !pStrRetToBufW) return;
|
||||
|
||||
/* These tests basically show, that CLSID_FolderShortcuts are initialized
|
||||
|
@ -945,7 +947,7 @@ void test_FolderShortcut(void) {
|
|||
if (FAILED(hr)) return;
|
||||
|
||||
hr = IPersistFolder3_Initialize(pPersistFolder3, pidlWineTestFolder);
|
||||
todo_wine { ok (SUCCEEDED(hr), "IPersistFolder3::Initialize failed! hr = %08lx\n", hr); }
|
||||
ok (SUCCEEDED(hr), "IPersistFolder3::Initialize failed! hr = %08lx\n", hr);
|
||||
if (FAILED(hr)) {
|
||||
IPersistFolder3_Release(pPersistFolder3);
|
||||
ILFree(pidlWineTestFolder);
|
||||
|
@ -985,7 +987,7 @@ void test_FolderShortcut(void) {
|
|||
|
||||
hr = IShellFolder_ParseDisplayName(pShellFolder, NULL, NULL, wszSomeSubFolder, NULL,
|
||||
&pidlSubFolder, NULL);
|
||||
RemoveDirectoryW(wszSomeSubFolder);
|
||||
RemoveDirectoryW(wszDesktopPath);
|
||||
ok (SUCCEEDED(hr), "IShellFolder::ParseDisplayName failed! hr = %08lx\n", hr);
|
||||
if (FAILED(hr)) {
|
||||
IShellFolder_Release(pShellFolder);
|
||||
|
@ -1000,9 +1002,12 @@ void test_FolderShortcut(void) {
|
|||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
/* On windows, we expect CLSID_ShellFSFolder. On wine we relax this constraint
|
||||
* a little bit and also allow CLSID_UnixDosFolder. */
|
||||
hr = IPersistFolder3_GetClassID(pPersistFolder3, &clsid);
|
||||
ok(SUCCEEDED(hr), "IPersistFolder3_GetClassID failed! hr=0x%08lx\n", hr);
|
||||
ok(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder), "Unexpected CLSID!\n");
|
||||
ok(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder) || IsEqualCLSID(&clsid, &CLSID_UnixDosFolder),
|
||||
"IPersistFolder3::GetClassID returned unexpected CLSID!\n");
|
||||
|
||||
IPersistFolder3_Release(pPersistFolder3);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue