Commit 10c0c4a8 authored by David Hedberg's avatar David Hedberg Committed by Alexandre Julliard

shell32: Don't allow binding to files in any ShellFolder implementation.

parent a6a946b2
...@@ -951,6 +951,10 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface ...@@ -951,6 +951,10 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface
if (_ILIsEmpty(pidl)) if (_ILIsEmpty(pidl))
return E_INVALIDARG; return E_INVALIDARG;
/* Don't bind to files */
if (_ILIsValue(ILFindLastID(pidl)))
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
if (IsEqualCLSID(This->m_pCLSID, &CLSID_FolderShortcut)) { if (IsEqualCLSID(This->m_pCLSID, &CLSID_FolderShortcut)) {
/* Children of FolderShortcuts are ShellFSFolders on Windows. /* Children of FolderShortcuts are ShellFSFolders on Windows.
* Unixfs' counterpart is UnixDosFolder. */ * Unixfs' counterpart is UnixDosFolder. */
......
...@@ -281,6 +281,9 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, ...@@ -281,6 +281,9 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
if ((clsid = _ILGetGUIDPointer (pidlChild))) { if ((clsid = _ILGetGUIDPointer (pidlChild))) {
/* virtual folder */ /* virtual folder */
hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, (LPVOID *)&pSF); hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, (LPVOID *)&pSF);
} else if (_ILIsValue(pidlChild)) {
/* Don't bind to files */
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
} else { } else {
/* file system folder */ /* file system folder */
CLSID clsidFolder = CLSID_ShellFSFolder; CLSID clsidFolder = CLSID_ShellFSFolder;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <initguid.h> #include <initguid.h>
DEFINE_GUID(IID_IParentAndItem, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36); DEFINE_GUID(IID_IParentAndItem, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
DEFINE_GUID(CLSID_ShellDocObjView, 0xe7e4bc40, 0xe76a, 0x11ce, 0xa9,0xbb, 0x00,0xaa,0x00,0x4a,0xe8,0x37);
static IMalloc *ppM; static IMalloc *ppM;
...@@ -150,6 +151,26 @@ static void init_function_pointers(void) ...@@ -150,6 +151,26 @@ static void init_function_pointers(void)
ok(hr == S_OK, "SHGetMalloc failed %08x\n", hr); ok(hr == S_OK, "SHGetMalloc failed %08x\n", hr);
} }
/* Based on PathAddBackslashW from dlls/shlwapi/path.c */
static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
{
size_t iLen;
if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
return NULL;
if (iLen)
{
lpszPath += iLen;
if (lpszPath[-1] != '\\')
{
*lpszPath++ = '\\';
*lpszPath = '\0';
}
}
return lpszPath;
}
static void test_ParseDisplayName(void) static void test_ParseDisplayName(void)
{ {
HRESULT hr; HRESULT hr;
...@@ -395,12 +416,19 @@ static void test_BindToObject(void) ...@@ -395,12 +416,19 @@ static void test_BindToObject(void)
UINT cChars; UINT cChars;
IShellFolder *psfDesktop, *psfChild, *psfMyComputer, *psfSystemDir; IShellFolder *psfDesktop, *psfChild, *psfMyComputer, *psfSystemDir;
SHITEMID emptyitem = { 0, { 0 } }; SHITEMID emptyitem = { 0, { 0 } };
LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidlEmpty = (LPITEMIDLIST)&emptyitem; LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidl, pidlEmpty = (LPITEMIDLIST)&emptyitem;
WCHAR wszSystemDir[MAX_PATH]; WCHAR wszSystemDir[MAX_PATH];
char szSystemDir[MAX_PATH]; char szSystemDir[MAX_PATH];
char buf[MAX_PATH];
WCHAR cwd[MAX_PATH];
WCHAR path[MAX_PATH];
HANDLE hfile;
WCHAR wszMyComputer[] = { WCHAR wszMyComputer[] = {
':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-', ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 }; 'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
static const WCHAR filename_html[] = {'w','i','n','e','t','e','s','t','.','h','t','m','l',0};
static const WCHAR filename_txt[] = {'w','i','n','e','t','e','s','t','.','t','x','t',0};
static const WCHAR filename_foo[] = {'w','i','n','e','t','e','s','t','.','f','o','o',0};
/* The following tests shows that BindToObject should fail with E_INVALIDARG if called /* The following tests shows that BindToObject should fail with E_INVALIDARG if called
* with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
...@@ -472,26 +500,169 @@ if (0) ...@@ -472,26 +500,169 @@ if (0)
} }
IShellFolder_Release(psfSystemDir); IShellFolder_Release(psfSystemDir);
}
/* Based on PathAddBackslashW from dlls/shlwapi/path.c */ GetCurrentDirectoryA(MAX_PATH, buf);
static LPWSTR myPathAddBackslashW( LPWSTR lpszPath ) if(!lstrlenA(buf))
{ {
size_t iLen; skip("Failed to get current directory, skipping tests.\n");
return;
}
MultiByteToWideChar(CP_ACP, 0, buf, -1, cwd, MAX_PATH);
if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH) SHGetDesktopFolder(&psfDesktop);
return NULL;
if (iLen) /* Attempt BindToObject on files. */
{
lpszPath += iLen; /* .html */
if (lpszPath[-1] != '\\') lstrcpyW(path, cwd);
myPathAddBackslashW(path);
lstrcatW(path, filename_html);
hfile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hfile != (HANDLE)INVALID_FILE_ATTRIBUTES)
{ {
*lpszPath++ = '\\'; CloseHandle(hfile);
*lpszPath = '\0'; hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
ok(hr == S_OK ||
broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Win98SE */ ||
broken(hr == E_FAIL) /* Win95 */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
ok(hr == S_OK /* Win 7 */ || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* WinXP */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
IPersist *pp;
hr = IShellFolder_QueryInterface(psfChild, &IID_IPersist, (void**)&pp);
ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* W2K */, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
CLSID id;
hr = IPersist_GetClassID(pp, &id);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(IsEqualIID(&id, &CLSID_ShellDocObjView), "Unexpected classid\n");
IPersist_Release(pp);
}
IShellFolder_Release(psfChild);
}
pILFree(pidl);
}
DeleteFileW(path);
} }
} else
return lpszPath; win_skip("Failed to create .html testfile.\n");
/* .txt */
lstrcpyW(path, cwd);
myPathAddBackslashW(path);
lstrcatW(path, filename_txt);
hfile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hfile != (HANDLE)INVALID_FILE_ATTRIBUTES)
{
CloseHandle(hfile);
hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
ok(hr == S_OK ||
broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Win98SE */ ||
broken(hr == E_FAIL) /* Win95 */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
|| broken(hr == S_OK) /* W2K */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
pILFree(pidl);
}
DeleteFileW(path);
}
else
win_skip("Failed to create .txt testfile.\n");
/* .foo */
lstrcpyW(path, cwd);
myPathAddBackslashW(path);
lstrcatW(path, filename_foo);
hfile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hfile != (HANDLE)INVALID_FILE_ATTRIBUTES)
{
CloseHandle(hfile);
hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
ok(hr == S_OK ||
broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Win98SE */ ||
broken(hr == E_FAIL) /* Win95 */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
|| broken(hr == S_OK) /* W2K */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
pILFree(pidl);
}
DeleteFileW(path);
}
else
win_skip("Failed to create .foo testfile.\n");
/* And on the desktop */
if(pSHGetSpecialFolderPathW)
{
pSHGetSpecialFolderPathW(NULL, path, CSIDL_DESKTOP, FALSE);
myPathAddBackslashW(path);
lstrcatW(path, filename_html);
hfile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hfile != (HANDLE)INVALID_FILE_ATTRIBUTES)
{
CloseHandle(hfile);
hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
ok(hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Win98SE */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
ok(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
pILFree(pidl);
}
if(!DeleteFileW(path))
trace("Failed to delete: %d\n", GetLastError());
}
else
win_skip("Failed to create .html testfile.\n");
pSHGetSpecialFolderPathW(NULL, path, CSIDL_DESKTOP, FALSE);
myPathAddBackslashW(path);
lstrcatW(path, filename_foo);
hfile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hfile != (HANDLE)INVALID_FILE_ATTRIBUTES)
{
CloseHandle(hfile);
hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, path, NULL, &pidl, NULL);
ok(hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Win98SE */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
|| broken(hr == S_OK) /* W2K */,
"Got 0x%08x\n", hr);
if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
pILFree(pidl);
}
DeleteFileW(path);
}
else
win_skip("Failed to create .foo testfile.\n");
}
IShellFolder_Release(psfDesktop);
} }
static void test_GetDisplayName(void) static void test_GetDisplayName(void)
...@@ -582,7 +753,6 @@ static void test_GetDisplayName(void) ...@@ -582,7 +753,6 @@ static void test_GetDisplayName(void)
/* It seems as if we cannot bind to regular files on windows, but only directories. /* It seems as if we cannot bind to regular files on windows, but only directories.
*/ */
hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile); hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile);
todo_wine
ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
hr == E_NOTIMPL || /* Vista */ hr == E_NOTIMPL || /* Vista */
broken(hr == S_OK), /* Win9x, W2K */ broken(hr == S_OK), /* Win9x, W2K */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment