[shell32,shlwapi] Implement the IShellLinkDataList interface

Thomas Weidenmueller wine-patches at reactsoft.com
Sun Apr 23 15:24:01 CDT 2006


The following patch reads and write the data lists appended by shortcuts
created with windows. Fixes the "Last word was not zero" error message
when reading such a .lnk file.

- Implement IShellLinkDataList::AddDataBlock(),
IShellLinkDataList::CopyDataBlock() and
IShellLinkDataList::RemoveDataBlock()
- Read the data list appended to .lnk files
- Write list size for empty lists in SHWriteDataBlockList()

- Thomas

-- 
P.S.: Please let me know if there's something wrong with this patch or
tell me why it was rejected. Otherwise I'm going to assume the fixes
aren't appreciated or necessary because the implementation is considered
mature and stable.
-------------- next part --------------
Index: dlls/shell32/shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.114
diff -u -r1.114 shelllink.c
--- dlls/shell32/shelllink.c	10 Nov 2005 12:14:58 -0000	1.114
+++ dlls/shell32/shelllink.c	23 Apr 2006 19:43:23 -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;
 }
 
 /************************************************************************
@@ -2248,46 +2248,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.29
diff -u -r1.29 undocshell.h
--- dlls/shell32/undocshell.h	24 Jul 2005 16:17:29 -0000	1.29
+++ dlls/shell32/undocshell.h	23 Apr 2006 19:41:07 -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) */
Index: dlls/shlwapi/clist.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/clist.c,v
retrieving revision 1.11
diff -u -r1.11 clist.c
--- dlls/shlwapi/clist.c	13 Sep 2005 15:00:32 -0000	1.11
+++ dlls/shlwapi/clist.c	23 Apr 2006 19:49:15 -0000
@@ -29,6 +29,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
+#include "pshpack1.h"
+
 /* DataBlock list element (ordinals 17-22) */
 typedef struct tagSHLWAPI_CLIST
 {
@@ -37,6 +39,8 @@
   /* Item data (or a contained SHLWAPI_CLIST) follows...         */
 } SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
 
+#include "poppack.h"
+
 typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
 
 /* ulId for contained SHLWAPI_CLIST items */
@@ -96,12 +100,13 @@
 HRESULT WINAPI SHWriteDataBlockList(IStream* lpStream, LPSHLWAPI_CLIST lpList)
 {
   ULONG ulSize;
-  HRESULT hRet = E_FAIL;
+  HRESULT hRet = S_OK;
 
   TRACE("(%p,%p)\n", lpStream, lpList);
 
   if(lpList)
   {
+    hRet = E_FAIL;
     while (lpList->ulSize)
     {
       LPSHLWAPI_CLIST lpItem = lpList;


More information about the wine-patches mailing list