[PATCH 3/3] shell32: Don't allow binding to files in any ShellFolder implementation.

David Hedberg dhedberg at codeweavers.com
Sun Nov 7 17:22:12 CST 2010


---
 dlls/shell32/shfldr_unixfs.c   |    4 +
 dlls/shell32/shlfolder.c       |    3 +
 dlls/shell32/tests/shlfolder.c |  204 ++++++++++++++++++++++++++++++++++++----
 3 files changed, 194 insertions(+), 17 deletions(-)

diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index 01811d8..e02399a 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -951,6 +951,10 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_BindToObject(IShellFolder2* iface
     if (_ILIsEmpty(pidl))
         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)) {
         /* Children of FolderShortcuts are ShellFSFolders on Windows. 
          * Unixfs' counterpart is UnixDosFolder. */
diff --git a/dlls/shell32/shlfolder.c b/dlls/shell32/shlfolder.c
index 9ab34a9..f905b70 100644
--- a/dlls/shell32/shlfolder.c
+++ b/dlls/shell32/shlfolder.c
@@ -281,6 +281,9 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
     if ((clsid = _ILGetGUIDPointer (pidlChild))) {
         /* virtual folder */
         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 {
         /* file system folder */
         CLSID clsidFolder = CLSID_ShellFSFolder;
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index e061dc4..67a9630 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -41,6 +41,7 @@
 
 #include <initguid.h>
 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;
 
@@ -150,6 +151,26 @@ static void init_function_pointers(void)
     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)
 {
     HRESULT hr;
@@ -395,12 +416,19 @@ static void test_BindToObject(void)
     UINT cChars;
     IShellFolder *psfDesktop, *psfChild, *psfMyComputer, *psfSystemDir;
     SHITEMID emptyitem = { 0, { 0 } };
-    LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidlEmpty = (LPITEMIDLIST)&emptyitem;
+    LPITEMIDLIST pidlMyComputer, pidlSystemDir, pidl, pidlEmpty = (LPITEMIDLIST)&emptyitem;
     WCHAR wszSystemDir[MAX_PATH];
     char szSystemDir[MAX_PATH];
+    char buf[MAX_PATH];
+    WCHAR cwd[MAX_PATH];
+    WCHAR path[MAX_PATH];
+    HANDLE hfile;
     WCHAR wszMyComputer[] = { 
         ':',':','{','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 };
+    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
      * with an empty pidl. This is tested for Desktop, MyComputer and the FS ShellFolder
@@ -472,26 +500,169 @@ if (0)
 }
 
     IShellFolder_Release(psfSystemDir);
-}
 
-/* Based on PathAddBackslashW from dlls/shlwapi/path.c */
-static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
-{
-  size_t iLen;
+    GetCurrentDirectoryA(MAX_PATH, buf);
+    if(!lstrlenA(buf))
+    {
+        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)
-    return NULL;
+    SHGetDesktopFolder(&psfDesktop);
 
-  if (iLen)
-  {
-    lpszPath += iLen;
-    if (lpszPath[-1] != '\\')
+    /* Attempt BindToObject on files. */
+
+    /* .html */
+    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++ = '\\';
-      *lpszPath = '\0';
+        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 == 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);
     }
-  }
-  return lpszPath;
+    else
+        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)
@@ -582,7 +753,6 @@ static void test_GetDisplayName(void)
     /* 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);
-    todo_wine
     ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
         hr == E_NOTIMPL || /* Vista */
         broken(hr == S_OK), /* Win9x, W2K */
-- 
1.7.3.2




More information about the wine-patches mailing list