From: Gabriel Ivăncescu gabrielopcode@gmail.com
Besides PathGetDriveNumber being dangerous and having a completely messed up result with \?\ prefix, a backslash is not required anymore on newer Windows versions. So e.g. C: should succeed to be parsed.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/shell32/shfldr_desktop.c | 5 +++-- dlls/shell32/shfldr_mycomp.c | 20 ++++++++++++-------- dlls/shell32/tests/shfldr_special.c | 2 -- dlls/shell32/tests/shlfolder.c | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c index f8672836da9..f8870d58103 100644 --- a/dlls/shell32/shfldr_desktop.c +++ b/dlls/shell32/shfldr_desktop.c @@ -150,7 +150,7 @@ static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface, DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) { IDesktopFolderImpl *This = impl_from_IShellFolder2(iface); - WCHAR szElement[MAX_PATH]; + WCHAR c, szElement[MAX_PATH]; LPCWSTR szNext = NULL; LPITEMIDLIST pidlTemp = NULL; PARSEDURLW urldata; @@ -178,7 +178,8 @@ static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface, SHCLSIDFromStringW (szElement + 2, &clsid); pidlTemp = _ILCreateGuid (PT_GUID, &clsid); } - else if (PathGetDriveNumberW (lpszDisplayName) >= 0) + /* we can't use PathGetDriveNumberW because we can't have the \?\ prefix */ + else if ((c = towupper(lpszDisplayName[0])) >= 'A' && c <= 'Z' && lpszDisplayName[1] == ':') { /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */ pidlTemp = _ILCreateMyComputer (); diff --git a/dlls/shell32/shfldr_mycomp.c b/dlls/shell32/shfldr_mycomp.c index 5b90458e145..2f4ebd580c1 100644 --- a/dlls/shell32/shfldr_mycomp.c +++ b/dlls/shell32/shfldr_mycomp.c @@ -189,7 +189,7 @@ static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface, IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface); HRESULT hr = E_INVALIDARG; LPCWSTR szNext = NULL; - WCHAR szElement[MAX_PATH]; + WCHAR c, szElement[MAX_PATH]; LPITEMIDLIST pidlTemp = NULL; CLSID clsid;
@@ -209,13 +209,17 @@ static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface, SHCLSIDFromStringW (szElement + 2, &clsid); pidlTemp = _ILCreateGuid (PT_GUID, &clsid); } - /* do we have an absolute path name ? */ - else if (PathGetDriveNumberW (lpszDisplayName) >= 0 && - lpszDisplayName[2] == (WCHAR) '\') + /* we can't use PathGetDriveNumberW because we can't have the \?\ prefix */ + else if ((c = towupper(lpszDisplayName[0])) >= 'A' && c <= 'Z' && + lpszDisplayName[1] == ':' && + (lpszDisplayName[2] == '\' || lpszDisplayName[2] == '\0')) { - szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - /* make drive letter uppercase to enable PIDL comparison */ - szElement[0] = toupper(szElement[0]); + /* drive letter has to be uppercase to enable PIDL comparison */ + szElement[0] = c; + szElement[1] = ':'; + szElement[2] = '\'; + szElement[3] = '\0'; + szNext = &lpszDisplayName[2] + (lpszDisplayName[2] == '\'); pidlTemp = _ILCreateDrive (szElement); }
@@ -224,7 +228,7 @@ static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface, hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); } - else + else if (pidlTemp) { if (pdwAttributes && *pdwAttributes) SHELL32_GetItemAttributes (&This->IShellFolder2_iface, pidlTemp, pdwAttributes); diff --git a/dlls/shell32/tests/shfldr_special.c b/dlls/shell32/tests/shfldr_special.c index 99d6e8c62a4..22749c231f3 100644 --- a/dlls/shell32/tests/shfldr_special.c +++ b/dlls/shell32/tests/shfldr_special.c @@ -85,7 +85,6 @@ static void test_parse_for_my_computer(void) pidl = NULL; eaten = 0xdeadbeef; hr = IShellFolder_ParseDisplayName(mycomp, NULL, NULL, path, &eaten, &pidl, NULL); - todo_wine ok(hr == E_INVALIDARG, "IShellFolder::ParseDisplayName should have failed with E_INVALIDARG, got 0x%08lx\n", hr); todo_wine ok(eaten == 0xdeadbeef, "eaten should not have been set to %lu\n", eaten); @@ -101,7 +100,6 @@ static void test_parse_for_my_computer(void) "IShellFolder::ParseDisplayName failed with error 0x%lx\n", hr); todo_wine ok(eaten == 0xdeadbeef, "eaten should not have been set to %lu\n", eaten); - todo_wine ok(pidl != NULL || broken(!pidl) /* WinXP */, "pidl is NULL\n"); ILFree(pidl);
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 02a5c0dfb2d..248fbd1df62 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -199,8 +199,8 @@ static struct {{'c',':','\',0}, S_OK}, {{'c',':','\','\',0}, E_INVALIDARG, 1}, {{'c',':','\','f','a','k','e',0}, 0x80070002}, /* ERROR_FILE_NOT_FOUND */ - {{'c',':','f','a','k','e',0}, E_INVALIDARG, 1}, - {{'c',':','/',0}, E_INVALIDARG, 1}, + {{'c',':','f','a','k','e',0}, E_INVALIDARG}, + {{'c',':','/',0}, E_INVALIDARG}, {{'c',':','\','w','i','n','d','o','w','s',0}, S_OK}, {{'c',':','\','w','i','n','d','o','w','s','\',0}, S_OK}, {{'c',':','\','w','i','n','d','o','w','s','\','.',0}, E_INVALIDARG, 1},