shell32: Support SHGFI_USEFILEATTRIBUTES | SHGFI_ICONLOCATION for SHGetFileInfo

Thomas Weidenmueller thomas at reactsoft.com
Sat Aug 26 14:56:06 CDT 2006


The attached patch adds support for the combination of the
SHGFI_USEFILEATTRIBUTES and SHGFI_ICONLOCATION flags. Some Inno Setups
(ie. the ClamAV installer) use this, which currently causes a crash due
to a NULL pointer dereference.

- Thomas
-------------- next part --------------
Index: dlls/shell32/shell32_main.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.c,v
retrieving revision 1.162
diff -u -r1.162 shell32_main.c
--- dlls/shell32/shell32_main.c	21 Jun 2006 13:03:32 -0000	1.162
+++ dlls/shell32/shell32_main.c	26 Aug 2006 19:48:06 -0000
@@ -509,23 +509,62 @@
     /* get the iconlocation */
     if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
     {
-        UINT uDummy,uFlags;
+        if (!(flags & SHGFI_USEFILEATTRIBUTES))
+        {
+            UINT uDummy,uFlags;
 
-        hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
-               (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW,
-               &uDummy, (LPVOID*)&pei);
-        if (SUCCEEDED(hr))
-        {
-            hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
-                    szLocation, MAX_PATH, &iIndex, &uFlags);
-            psfi->iIcon = iIndex;
+            hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
+                   (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconA,
+                   &uDummy, (LPVOID*)&pei);
+            if (SUCCEEDED(hr))
+            {
+                hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
+                        szLocation, MAX_PATH, &iIndex, &uFlags);
+                psfi->iIcon = iIndex;
+
+                if (!(uFlags & GIL_NOTFILENAME))
+                    lstrcpyW (psfi->szDisplayName, szLocation);
+                else
+                    ret = FALSE;
 
-            if (!(uFlags & GIL_NOTFILENAME))
-                lstrcpyW (psfi->szDisplayName, szLocation);
+                IExtractIconA_Release(pei);
+            }
+        }
+        else
+        {
+            if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+            {
+                strcpyW(psfi->szDisplayName, swShell32Name);
+                psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
+            }
             else
-                ret = FALSE;
+            {
+                static const WCHAR p1W[] = {'%','1',0};
+                WCHAR sTemp [MAX_PATH];
+                WCHAR * szExt;
+                DWORD dwNr = 0;
 
-            IExtractIconW_Release(pei);
+                lstrcpynW(sTemp, szFullPath, MAX_PATH);
+
+                psfi->iIcon = 0;
+                szExt = (LPWSTR) PathFindExtensionW(sTemp);
+                if ( szExt &&
+                     HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
+                     HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &dwNr))
+                {
+                    if (!lstrcmpW(p1W, sTemp))
+                        psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_EXE, 0);
+                    else
+                    {
+                        psfi->iIcon = SIC_GetIconIndex(psfi->szDisplayName, dwNr, 0);
+                        if (psfi->iIcon == -1)
+                            psfi->iIcon = 0;
+                    }
+                }
+
+                /* return an empty file name for everything other than a directory */
+                psfi->szDisplayName[0] = '\0';
+            }
         }
     }
 
Index: dlls/shell32/shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.116
diff -u -r1.116 shelllink.c
--- dlls/shell32/shelllink.c	9 Aug 2006 15:38:25 -0000	1.116
+++ dlls/shell32/shelllink.c	22 Aug 2006 18:22:25 -0000
@@ -161,6 +161,7 @@
 	BOOL          bDirty;
         INT           iIdOpen;  /* id of the "Open" entry in the context menu */
 	IUnknown      *site;
+	LPSHLWAPI_CLIST pDataList;
 } IShellLinkImpl;
 
 static inline IShellLinkImpl *impl_from_IShellLinkW( IShellLinkW *iface )
@@ -305,6 +306,9 @@
     HeapFree(GetProcessHeap(), 0, This->sDescription);
     HeapFree(GetProcessHeap(),0,This->sPath);
 
+    if (This->pDataList)
+        SHFreeDataBlockList(This->pDataList);
+
     if (This->site)
         IUnknown_Release( This->site );
 
@@ -782,7 +786,6 @@
     ULONG    dwBytesRead;
     BOOL     unicode;
     HRESULT  r;
-    DWORD    zero;
 
     IShellLinkImpl *This = impl_from_IPersistStream(iface);
 
@@ -915,9 +918,9 @@
     if( FAILED( r ) )
         goto end;
 
-    r = IStream_Read(stm, &zero, sizeof zero, &dwBytesRead);
-    if( FAILED( r ) || zero || dwBytesRead != sizeof zero )
-        ERR("Last word was not zero\n");
+    r = SHReadDataBlockList( stm, &This->pDataList);
+    if( FAILED( r ) )
+        goto end;
 
     TRACE("OK\n");
 
@@ -1054,7 +1057,6 @@
     LINK_HEADER header;
     WCHAR   exePath[MAX_PATH];
     ULONG   count;
-    DWORD   zero;
     HRESULT r;
 
     IShellLinkImpl *This = impl_from_IPersistStream(iface);
@@ -1149,11 +1151,9 @@
     if( This->sComponent )
         r = Stream_WriteAdvertiseInfo( stm, This->sComponent, EXP_DARWIN_ID_SIG );
 
-    /* the last field is a single zero dword */
-    zero = 0;
-    r = IStream_Write( stm, &zero, sizeof zero, &count );
+    r = SHWriteDataBlockList (stm, This->pDataList );
 
-    return S_OK;
+    return r;
 }
 
 /************************************************************************
@@ -2263,46 +2263,57 @@
 static HRESULT WINAPI
 ShellLink_AddDataBlock( IShellLinkDataList* iface, void* pDataBlock )
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    IShellLinkImpl *This = impl_from_IShellLinkDataList(iface);
+    HRESULT hr;
+
+    hr = SHAddDataBlock(&This->pDataList, (LPCSHLWAPI_CLIST)pDataBlock);
+    if (SUCCEEDED(hr))
+        This->bDirty = TRUE;
+
+    return hr;
 }
 
 static HRESULT WINAPI
 ShellLink_CopyDataBlock( IShellLinkDataList* iface, DWORD dwSig, void** ppDataBlock )
 {
     IShellLinkImpl *This = impl_from_IShellLinkDataList(iface);
-    LPVOID block = NULL;
-    HRESULT r = E_FAIL;
-
-    TRACE("%p %08lx %p\n", iface, dwSig, ppDataBlock );
+    LPSHLWAPI_CLIST pdbh;
+    HRESULT hr = S_OK;
 
-    switch (dwSig)
+    pdbh = SHFindDataBlock(This->pDataList, dwSig);
+    if (pdbh)
     {
-    case EXP_DARWIN_ID_SIG:
-        if (!This->sComponent)
-            break;
-        block = shelllink_build_darwinid( This->sComponent, dwSig );
-        r = S_OK;
-        break;
-    case EXP_SZ_LINK_SIG:
-    case NT_CONSOLE_PROPS_SIG:
-    case NT_FE_CONSOLE_PROPS_SIG:
-    case EXP_SPECIAL_FOLDER_SIG:
-    case EXP_SZ_ICON_SIG:
-        FIXME("valid but unhandled datablock %08lx\n", dwSig);
-        break;
-    default:
-        ERR("unknown datablock %08lx\n", dwSig);
+        *ppDataBlock = LocalAlloc(LPTR, pdbh->ulSize);
+        if (*ppDataBlock)
+        {
+            CopyMemory(*ppDataBlock,
+                       pdbh,
+                       pdbh->ulSize);
+        }
+        else
+            hr = E_OUTOFMEMORY;
     }
-    *ppDataBlock = block;
-    return r;
+    else
+    {
+        *ppDataBlock = NULL;
+        hr = E_FAIL;
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI
 ShellLink_RemoveDataBlock( IShellLinkDataList* iface, DWORD dwSig )
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    IShellLinkImpl *This = impl_from_IShellLinkDataList(iface);
+    HRESULT hr = S_OK;
+
+    if (SHRemoveDataBlock(&This->pDataList, dwSig))
+        This->bDirty = TRUE;
+    else
+        hr = E_FAIL;
+
+    return hr;
 }
 
 static HRESULT WINAPI
Index: dlls/shell32/undocshell.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/undocshell.h,v
retrieving revision 1.30
diff -u -r1.30 undocshell.h
--- dlls/shell32/undocshell.h	23 May 2006 12:48:39 -0000	1.30
+++ dlls/shell32/undocshell.h	24 May 2006 17:23:15 -0000
@@ -566,6 +566,29 @@
 /* policy functions */
 BOOL WINAPI SHInitRestricted(LPCVOID unused, LPCVOID inpRegKey);
 
+/* CLIST functions */
+
+#include "pshpack1.h"
+
+/* DataBlock list element (ordinals 17-22) */
+typedef struct tagSHLWAPI_CLIST
+{
+  ULONG ulSize;        /* Size of this list element and its data */
+  ULONG ulId;          /* If 0xFFFFFFFF, The real element follows        */
+  /* Item data (or a contained SHLWAPI_CLIST) follows...         */
+} SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
+
+#include "poppack.h"
+
+typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
+
+HRESULT WINAPI SHWriteDataBlockList(IStream*,LPSHLWAPI_CLIST);
+HRESULT WINAPI SHReadDataBlockList(IStream*,LPSHLWAPI_CLIST*);
+VOID WINAPI SHFreeDataBlockList(LPSHLWAPI_CLIST);
+HRESULT WINAPI SHAddDataBlock(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST);
+BOOL WINAPI SHRemoveDataBlock(LPSHLWAPI_CLIST*,ULONG);
+LPSHLWAPI_CLIST WINAPI SHFindDataBlock(LPSHLWAPI_CLIST,ULONG);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* defined(__cplusplus) */


More information about the wine-patches mailing list