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