SHELL32: rewrite shelllink vtable handling

Mike McCormack mike at codeweavers.com
Fri May 27 07:14:13 CDT 2005


This patch eliminates duplicate implementations of AddRef, Release and 
QueryInterface for the 4 interfaces currently defined by the ShellLink 
object.  It reduces the size of shelllink.c by about 100 lines.

There are more than 10 interface in the Windows 2000 implementation of 
the same object, so hopefully this technique can save us writing a 
significant amount of tedious code.

The idea is to store the of the vtable into the object offset with each 
vtable, so that the object pointer can be calculated without having to 
known which interface we're being called from.  The down side is that it 
uses a bit of casting...

Mike


ChangeLog:
* rewrite shelllink vtable handling
-------------- next part --------------
Index: dlls/shell32/shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.92
diff -u -p -r1.92 shelllink.c
--- dlls/shell32/shelllink.c	13 May 2005 13:59:15 -0000	1.92
+++ dlls/shell32/shelllink.c	27 May 2005 12:08:49 -0000
@@ -112,22 +112,17 @@ typedef struct volume_info_t
 
 #include "poppack.h"
 
-static IShellLinkAVtbl		slvt;
-static IShellLinkWVtbl		slvtw;
-static IPersistFileVtbl	pfvt;
-static IPersistStreamVtbl	psvt;
 
 /* IShellLink Implementation */
 
 typedef struct
 {
-	IShellLinkAVtbl    *lpVtbl;
+	const IShellLinkAVtbl    *lpVtbl;
+	const IShellLinkWVtbl    *lpvtblw;
+	const IPersistFileVtbl   *lpvtblPersistFile;
+	const IPersistStreamVtbl *lpvtblPersistStream;
 	DWORD               ref;
 
-	IShellLinkWVtbl    *lpvtblw;
-	IPersistFileVtbl   *lpvtblPersistFile;
-	IPersistStreamVtbl *lpvtblPersistStream;
-
 	/* data structures according to the informations in the link */
 	LPITEMIDLIST	pPidl;
 	WORD		wHotKey;
@@ -150,14 +145,11 @@ typedef struct
 	BOOL		bDirty;
 } IShellLinkImpl;
 
-#define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw)))
-#define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset)
-
-#define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile)))
-#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset)
-
-#define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream)))
-#define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset)
+static inline IShellLinkImpl *get_shelllink_impl( void *obj )
+{
+    DWORD **ppoffset = obj;
+    return (IShellLinkImpl *) &ppoffset[ -ppoffset[0][-1] ];
+}
 
 static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath);
 
@@ -172,53 +164,9 @@ inline static LPWSTR HEAP_strdupAtoW( HA
     return p;
 }
 
-/**************************************************************************
- *  IPersistFile_QueryInterface
- */
-static HRESULT WINAPI IPersistFile_fnQueryInterface(
-	IPersistFile* iface,
-	REFIID riid,
-	LPVOID *ppvObj)
-{
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-
-	TRACE("(%p)\n",This);
-
-	return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
-}
-
-/******************************************************************************
- * IPersistFile_AddRef
- */
-static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface)
-{
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-
-	TRACE("(%p)->(count=%lu)\n",This,This->ref);
-
-	return IShellLinkA_AddRef((IShellLinkA*)This);
-}
-/******************************************************************************
- * IPersistFile_Release
- */
-static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface)
-{
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-
-	TRACE("(%p)->(count=%lu)\n",This,This->ref);
-
-	return IShellLinkA_Release((IShellLinkA*)This);
-}
-
-static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile* iface, CLSID *pClassID)
-{
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-	FIXME("(%p)\n",This);
-	return NOERROR;
-}
 static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile* iface)
 {
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
+	IShellLinkImpl *This = get_shelllink_impl( iface );
 
 	TRACE("(%p)\n",This);
 
@@ -227,9 +175,10 @@ static HRESULT WINAPI IPersistFile_fnIsD
 
 	return S_FALSE;
 }
+
 static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
 {
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
+	IShellLinkImpl *This = get_shelllink_impl( iface );
 	IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream;
         HRESULT r;
         IStream *stm;
@@ -283,7 +232,7 @@ static BOOL StartLinkProcessor( LPCOLEST
 
 static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember)
 {
-    _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream;
     HRESULT r;
     IStream *stm;
@@ -317,89 +266,37 @@ static HRESULT WINAPI IPersistFile_fnSav
 
 static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
 {
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-	FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName));
-	return NOERROR;
-}
-static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName)
-{
-	_ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
-	FIXME("(%p)\n",This);
-	return NOERROR;
-}
-
-static IPersistFileVtbl pfvt =
-{
-	IPersistFile_fnQueryInterface,
-	IPersistFile_fnAddRef,
-	IPersistFile_fnRelease,
-	IPersistFile_fnGetClassID,
-	IPersistFile_fnIsDirty,
-	IPersistFile_fnLoad,
-	IPersistFile_fnSave,
-	IPersistFile_fnSaveCompleted,
-	IPersistFile_fnGetCurFile
-};
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-/************************************************************************
- * IPersistStream_QueryInterface
- */
-static HRESULT WINAPI IPersistStream_fnQueryInterface(
-	IPersistStream* iface,
-	REFIID     riid,
-	VOID**     ppvoid)
-{
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
-
-	TRACE("(%p)\n",This);
-
-	return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvoid);
-}
-
-/************************************************************************
- * IPersistStream_Release
- */
-static ULONG WINAPI IPersistStream_fnRelease(
-	IPersistStream* iface)
-{
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
-
-	TRACE("(%p)\n",This);
-
-	return IShellLinkA_Release((IShellLinkA*)This);
+    FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName));
+    return NOERROR;
 }
-
-/************************************************************************
- * IPersistStream_AddRef
- */
-static ULONG WINAPI IPersistStream_fnAddRef(
-	IPersistStream* iface)
+static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName)
 {
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
-
-	TRACE("(%p)\n",This);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	return IShellLinkA_AddRef((IShellLinkA*)This);
+    FIXME("(%p)\n",This);
+    return NOERROR;
 }
 
 /************************************************************************
  * IPersistStream_GetClassID
  *
  */
-static HRESULT WINAPI IPersistStream_fnGetClassID(
+static HRESULT WINAPI ShellLink_GetClassID(
 	IPersistStream* iface,
 	CLSID* pClassID)
 {
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	TRACE("(%p)\n", This);
+    TRACE("(%p)\n", This);
 
-	if (pClassID==0)
-	  return E_POINTER;
+    if (pClassID==0)
+        return E_POINTER;
 
 /*	memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */
 
-	return S_OK;
+    return S_OK;
 }
 
 /************************************************************************
@@ -408,11 +305,11 @@ static HRESULT WINAPI IPersistStream_fnG
 static HRESULT WINAPI IPersistStream_fnIsDirty(
 	IPersistStream*  iface)
 {
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	TRACE("(%p)\n", This);
+    TRACE("(%p)\n", This);
 
-	return S_OK;
+    return S_OK;
 }
 
 
@@ -647,14 +544,13 @@ static HRESULT WINAPI IPersistStream_fnL
     IPersistStream*  iface,
     IStream*         stm)
 {
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     LINK_HEADER hdr;
     ULONG    dwBytesRead;
     BOOL     unicode;
     HRESULT  r;
     DWORD    zero;
 
-    _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
-
     TRACE("%p %p\n", This, stm);
 
     if( !stm )
@@ -909,6 +805,7 @@ static HRESULT WINAPI IPersistStream_fnS
 	IStream*         stm,
 	BOOL             fClearDirty)
 {
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     static const WCHAR wOpen[] = {'o','p','e','n',0};
 
     LINK_HEADER header;
@@ -917,8 +814,6 @@ static HRESULT WINAPI IPersistStream_fnS
     DWORD   zero;
     HRESULT r;
 
-    _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
-
     TRACE("%p %p %x\n", This, stm, fClearDirty);
 
     *exePath = '\0';
@@ -1023,68 +918,13 @@ static HRESULT WINAPI IPersistStream_fnG
 	IPersistStream*  iface,
 	ULARGE_INTEGER*  pcbSize)
 {
-	_ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	TRACE("(%p)\n", This);
+    TRACE("(%p)\n", This);
 
-	return E_NOTIMPL;
+    return E_NOTIMPL;
 }
 
-static IPersistStreamVtbl psvt =
-{
-	IPersistStream_fnQueryInterface,
-	IPersistStream_fnAddRef,
-	IPersistStream_fnRelease,
-	IPersistStream_fnGetClassID,
-	IPersistStream_fnIsDirty,
-	IPersistStream_fnLoad,
-	IPersistStream_fnSave,
-	IPersistStream_fnGetSizeMax
-};
-
-/**************************************************************************
- *	  IShellLink_Constructor
- */
-HRESULT WINAPI IShellLink_Constructor( IUnknown *pUnkOuter,
-               REFIID riid, LPVOID *ppv )
-{
-	IShellLinkImpl * sl;
-
-	TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
-
-	*ppv = NULL;
-
-	if (pUnkOuter)
-            return CLASS_E_NOAGGREGATION;
-	sl = LocalAlloc(LMEM_ZEROINIT,sizeof(IShellLinkImpl));
-	if (!sl)
-            return E_OUTOFMEMORY;
-
-	sl->ref = 1;
-	sl->lpVtbl = &slvt;
-	sl->lpvtblw = &slvtw;
-	sl->lpvtblPersistFile = &pfvt;
-	sl->lpvtblPersistStream = &psvt;
-	sl->iShowCmd = SW_SHOWNORMAL;
-	sl->bDirty = FALSE;
-
-	TRACE("(%p)->()\n",sl);
-
-	if (IsEqualIID(riid, &IID_IUnknown) ||
-	    IsEqualIID(riid, &IID_IShellLinkA))
-	    *ppv = sl;
-	else if (IsEqualIID(riid, &IID_IShellLinkW))
-	    *ppv = &(sl->lpvtblw);
-	else {
-	    LocalFree((HLOCAL)sl);
-	    ERR("E_NOINTERFACE\n");
-	    return E_NOINTERFACE;
-	}
-
-	return S_OK;
-}
-
-
 static BOOL SHELL_ExistsFileW(LPCWSTR path)
 {
     if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(path))
@@ -1181,89 +1021,10 @@ HRESULT WINAPI IShellLink_ConstructFromF
     return hr;
 }
 
-/**************************************************************************
- *  IShellLinkA_QueryInterface
- */
-static HRESULT WINAPI IShellLinkA_fnQueryInterface( IShellLinkA * iface, REFIID riid,  LPVOID *ppvObj)
-{
-	IShellLinkImpl *This = (IShellLinkImpl *)iface;
-
-	TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
-
-	*ppvObj = NULL;
-
-	if(IsEqualIID(riid, &IID_IUnknown) ||
-	   IsEqualIID(riid, &IID_IShellLinkA))
-	{
-	  *ppvObj = This;
-	}
-	else if(IsEqualIID(riid, &IID_IShellLinkW))
-	{
-	  *ppvObj = (IShellLinkW *)&(This->lpvtblw);
-	}
-	else if(IsEqualIID(riid, &IID_IPersistFile))
-	{
-	  *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile);
-	}
-	else if(IsEqualIID(riid, &IID_IPersistStream))
-	{
-	  *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream);
-	}
-
-	if(*ppvObj)
-	{
-	  IUnknown_AddRef((IUnknown*)(*ppvObj));
-	  TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
-	  return S_OK;
-	}
-	TRACE("-- Interface: E_NOINTERFACE\n");
-	return E_NOINTERFACE;
-}
-/******************************************************************************
- * IShellLinkA_AddRef
- */
-static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface)
-{
-	IShellLinkImpl *This = (IShellLinkImpl *)iface;
-	ULONG refCount = InterlockedIncrement(&This->ref);
-
-	TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
-
-	return refCount;
-}
-/******************************************************************************
- *	IShellLinkA_Release
- */
-static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface)
-{
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
-    ULONG refCount = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
-
-    if (refCount)
-        return refCount;
-
-    TRACE("-- destroying IShellLink(%p)\n",This);
-
-    HeapFree(GetProcessHeap(), 0, This->sIcoPath);
-    HeapFree(GetProcessHeap(), 0, This->sArgs);
-    HeapFree(GetProcessHeap(), 0, This->sWorkDir);
-    HeapFree(GetProcessHeap(), 0, This->sDescription);
-    HeapFree(GetProcessHeap(),0,This->sPath);
-
-    if (This->pPidl)
-        ILFree(This->pPidl);
-
-    LocalFree((HANDLE)This);
-
-    return 0;
-}
-
 static HRESULT WINAPI IShellLinkA_fnGetPath(IShellLinkA * iface, LPSTR pszFile,
                   INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",
           This, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(This->sPath));
@@ -1284,7 +1045,7 @@ static HRESULT WINAPI IShellLinkA_fnGetP
 
 static HRESULT WINAPI IShellLinkA_fnGetIDList(IShellLinkA * iface, LPITEMIDLIST * ppidl)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(ppidl=%p)\n",This, ppidl);
 
@@ -1293,7 +1054,7 @@ static HRESULT WINAPI IShellLinkA_fnGetI
 
 static HRESULT WINAPI IShellLinkA_fnSetIDList(IShellLinkA * iface, LPCITEMIDLIST pidl)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(pidl=%p)\n",This, pidl);
 
@@ -1307,7 +1068,7 @@ static HRESULT WINAPI IShellLinkA_fnSetI
 
 static HRESULT WINAPI IShellLinkA_fnGetDescription(IShellLinkA * iface, LPSTR pszName,INT cchMaxName)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
 
@@ -1319,9 +1080,10 @@ static HRESULT WINAPI IShellLinkA_fnGetD
 
     return S_OK;
 }
+
 static HRESULT WINAPI IShellLinkA_fnSetDescription(IShellLinkA * iface, LPCSTR pszName)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(pName=%s)\n", This, pszName);
 
@@ -1352,7 +1114,7 @@ static HRESULT WINAPI IShellLinkA_fnGetW
 
 static HRESULT WINAPI IShellLinkA_fnSetWorkingDirectory(IShellLinkA * iface, LPCSTR pszDir)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(dir=%s)\n",This, pszDir);
 
@@ -1368,7 +1130,7 @@ static HRESULT WINAPI IShellLinkA_fnSetW
 
 static HRESULT WINAPI IShellLinkA_fnGetArguments(IShellLinkA * iface, LPSTR pszArgs,INT cchMaxPath)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
 
@@ -1383,7 +1145,7 @@ static HRESULT WINAPI IShellLinkA_fnGetA
 
 static HRESULT WINAPI IShellLinkA_fnSetArguments(IShellLinkA * iface, LPCSTR pszArgs)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(args=%s)\n",This, pszArgs);
 
@@ -1399,30 +1161,30 @@ static HRESULT WINAPI IShellLinkA_fnSetA
 
 static HRESULT WINAPI IShellLinkA_fnGetHotkey(IShellLinkA * iface, WORD *pwHotkey)
 {
-	IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey);
+    TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey);
 
-	*pwHotkey = This->wHotKey;
+    *pwHotkey = This->wHotKey;
 
-	return S_OK;
+    return S_OK;
 }
 
 static HRESULT WINAPI IShellLinkA_fnSetHotkey(IShellLinkA * iface, WORD wHotkey)
 {
-	IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
-	TRACE("(%p)->(hotkey=%x)\n",This, wHotkey);
+    TRACE("(%p)->(hotkey=%x)\n",This, wHotkey);
 
-	This->wHotKey = wHotkey;
-	This->bDirty = TRUE;
+    This->wHotKey = wHotkey;
+    This->bDirty = TRUE;
 
-	return S_OK;
+    return S_OK;
 }
 
 static HRESULT WINAPI IShellLinkA_fnGetShowCmd(IShellLinkA * iface, INT *piShowCmd)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p)\n",This, piShowCmd);
     *piShowCmd = This->iShowCmd;
@@ -1431,7 +1193,7 @@ static HRESULT WINAPI IShellLinkA_fnGetS
 
 static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p) %d\n",This, iShowCmd);
 
@@ -1466,7 +1228,7 @@ static HRESULT SHELL_PidlGeticonLocation
 
 static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
 
@@ -1517,7 +1279,7 @@ static HRESULT WINAPI IShellLinkA_fnGetI
 
 static HRESULT WINAPI IShellLinkA_fnSetIconLocation(IShellLinkA * iface, LPCSTR pszIconPath,INT iIcon)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon);
 
@@ -1534,7 +1296,7 @@ static HRESULT WINAPI IShellLinkA_fnSetI
 
 static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR pszPathRel, DWORD dwReserved)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved);
 
@@ -1547,7 +1309,7 @@ static HRESULT WINAPI IShellLinkA_fnSetR
 
 static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags)
 {
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags);
 
@@ -1556,9 +1318,9 @@ static HRESULT WINAPI IShellLinkA_fnReso
 
 static HRESULT WINAPI IShellLinkA_fnSetPath(IShellLinkA * iface, LPCSTR pszFile)
 {
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     HRESULT r;
     LPWSTR str;
-    IShellLinkImpl *This = (IShellLinkImpl *)iface;
 
     TRACE("(%p)->(path=%s)\n",This, pszFile);
 
@@ -1573,73 +1335,12 @@ static HRESULT WINAPI IShellLinkA_fnSetP
 }
 
 /**************************************************************************
-* IShellLink Implementation
+* IShellLinkW Implementation
 */
 
-static IShellLinkAVtbl slvt =
-{
-	IShellLinkA_fnQueryInterface,
-	IShellLinkA_fnAddRef,
-	IShellLinkA_fnRelease,
-	IShellLinkA_fnGetPath,
-	IShellLinkA_fnGetIDList,
-	IShellLinkA_fnSetIDList,
-	IShellLinkA_fnGetDescription,
-	IShellLinkA_fnSetDescription,
-	IShellLinkA_fnGetWorkingDirectory,
-	IShellLinkA_fnSetWorkingDirectory,
-	IShellLinkA_fnGetArguments,
-	IShellLinkA_fnSetArguments,
-	IShellLinkA_fnGetHotkey,
-	IShellLinkA_fnSetHotkey,
-	IShellLinkA_fnGetShowCmd,
-	IShellLinkA_fnSetShowCmd,
-	IShellLinkA_fnGetIconLocation,
-	IShellLinkA_fnSetIconLocation,
-	IShellLinkA_fnSetRelativePath,
-	IShellLinkA_fnResolve,
-	IShellLinkA_fnSetPath
-};
-
-
-/**************************************************************************
- *  IShellLinkW_fnQueryInterface
- */
-static HRESULT WINAPI IShellLinkW_fnQueryInterface(
-  IShellLinkW * iface, REFIID riid, LPVOID *ppvObj)
-{
-	_ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
-
-	return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
-}
-
-/******************************************************************************
- * IShellLinkW_fnAddRef
- */
-static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface)
-{
-	_ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
-
-	TRACE("(%p)->(count=%lu)\n",This,This->ref);
-
-	return IShellLinkA_AddRef((IShellLinkA*)This);
-}
-/******************************************************************************
- * IShellLinkW_fnRelease
- */
-
-static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface)
-{
-	_ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
-
-	TRACE("(%p)->(count=%lu)\n",This,This->ref);
-
-	return IShellLinkA_Release((IShellLinkA*)This);
-}
-
 static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",
           This, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(This->sPath));
@@ -1659,7 +1360,7 @@ static HRESULT WINAPI IShellLinkW_fnGetP
 
 static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(ppidl=%p)\n",This, ppidl);
 
@@ -1671,7 +1372,7 @@ static HRESULT WINAPI IShellLinkW_fnGetI
 
 static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(pidl=%p)\n",This, pidl);
 
@@ -1688,7 +1389,7 @@ static HRESULT WINAPI IShellLinkW_fnSetI
 
 static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
 
@@ -1701,7 +1402,7 @@ static HRESULT WINAPI IShellLinkW_fnGetD
 
 static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(desc=%s)\n",This, debugstr_w(pszName));
 
@@ -1719,7 +1420,7 @@ static HRESULT WINAPI IShellLinkW_fnSetD
 
 static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len %u)\n", This, pszDir, cchMaxPath);
 
@@ -1733,7 +1434,7 @@ static HRESULT WINAPI IShellLinkW_fnGetW
 
 static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(dir=%s)\n",This, debugstr_w(pszDir));
 
@@ -1750,7 +1451,7 @@ static HRESULT WINAPI IShellLinkW_fnSetW
 
 static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
 
@@ -1764,7 +1465,7 @@ static HRESULT WINAPI IShellLinkW_fnGetA
 
 static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(args=%s)\n",This, debugstr_w(pszArgs));
 
@@ -1781,7 +1482,7 @@ static HRESULT WINAPI IShellLinkW_fnSetA
 
 static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p)\n",This, pwHotkey);
 
@@ -1792,7 +1493,7 @@ static HRESULT WINAPI IShellLinkW_fnGetH
 
 static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(hotkey=%x)\n",This, wHotkey);
 
@@ -1804,7 +1505,7 @@ static HRESULT WINAPI IShellLinkW_fnSetH
 
 static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p)\n",This, piShowCmd);
 
@@ -1815,7 +1516,7 @@ static HRESULT WINAPI IShellLinkW_fnGetS
 
 static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     This->iShowCmd = iShowCmd;
     This->bDirty = TRUE;
@@ -1848,7 +1549,7 @@ static HRESULT SHELL_PidlGeticonLocation
 
 static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
 
@@ -1899,7 +1600,7 @@ static HRESULT WINAPI IShellLinkW_fnGetI
 
 static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon);
 
@@ -1918,7 +1619,7 @@ static HRESULT WINAPI IShellLinkW_fnSetI
 
 static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
 
     TRACE("(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved);
 
@@ -1935,10 +1636,9 @@ static HRESULT WINAPI IShellLinkW_fnSetR
 
 static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)
 {
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     HRESULT hr = S_OK;
 
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
-
     TRACE("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags);
 
     /*FIXME: use IResolveShellLink interface */
@@ -2073,7 +1773,7 @@ static BOOL ShellLink_GetVolumeInfo(LPWS
 
 static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile)
 {
-    _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
+    IShellLinkImpl *This = get_shelllink_impl( iface );
     WCHAR buffer[MAX_PATH];
     LPWSTR fname;
     HRESULT hr = S_OK;
@@ -2114,31 +1814,221 @@ static HRESULT WINAPI IShellLinkW_fnSetP
     return hr;
 }
 
-/**************************************************************************
-* IShellLinkW Implementation
-*/
+/******************************************************************************
+ *  ShellLink_QueryInterface
+ */
+static HRESULT WINAPI ShellLink_QueryInterface( IShellLinkA * iface, REFIID riid,  LPVOID *ppvObj)
+{
+    IShellLinkImpl *This = get_shelllink_impl( iface );
+
+    TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
+
+    *ppvObj = NULL;
+
+    if(IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IShellLinkA))
+    {
+        *ppvObj = This;
+    }
+    else if(IsEqualIID(riid, &IID_IShellLinkW))
+    {
+        *ppvObj = (IShellLinkW *)&(This->lpvtblw);
+    }
+    else if(IsEqualIID(riid, &IID_IPersistFile))
+    {
+        *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile);
+    }
+    else if(IsEqualIID(riid, &IID_IPersistStream))
+    {
+        *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream);
+    }
+
+    if (*ppvObj)
+    {
+        IUnknown_AddRef((IUnknown*)(*ppvObj));
+        TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
+        return S_OK;
+    }
+    TRACE("-- Interface: E_NOINTERFACE\n");
+    return E_NOINTERFACE;
+}
+
+/******************************************************************************
+ *  ShellLink_AddRef
+ */
+static ULONG WINAPI ShellLink_AddRef(IShellLinkA * iface)
+{
+    IShellLinkImpl *This = get_shelllink_impl( iface );
+    ULONG refCount = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
+
+    return refCount;
+}
+
+/******************************************************************************
+ *  ShellLink_Release
+ */
+static ULONG WINAPI ShellLink_Release(IShellLinkA * iface)
+{
+    IShellLinkImpl *This = get_shelllink_impl( iface );
+    ULONG refCount = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p)->(count=%lu)\n", This, refCount + 1);
+
+    if (refCount)
+        return refCount;
+
+    TRACE("-- destroying IShellLink(%p)\n",This);
+
+    HeapFree(GetProcessHeap(), 0, This->sIcoPath);
+    HeapFree(GetProcessHeap(), 0, This->sArgs);
+    HeapFree(GetProcessHeap(), 0, This->sWorkDir);
+    HeapFree(GetProcessHeap(), 0, This->sDescription);
+    HeapFree(GetProcessHeap(),0,This->sPath);
+
+    if (This->pPidl)
+        ILFree(This->pPidl);
+
+    HeapFree( GetProcessHeap(), 0, This );
+
+    return 0;
+}
+
+
+/******************************************************************************
+ *	vtables
+ */
 
-static IShellLinkWVtbl slvtw =
+#define DECLARE_VTABLE_OFFSET(vtbl) \
+    struct vtbl##_ofs {             \
+        DWORD offset;               \
+        vtbl vtable;                \
+    };                                   
+
+DECLARE_VTABLE_OFFSET( IShellLinkAVtbl );
+DECLARE_VTABLE_OFFSET( IShellLinkWVtbl );
+DECLARE_VTABLE_OFFSET( IPersistFileVtbl );
+DECLARE_VTABLE_OFFSET( IPersistStreamVtbl );
+
+const static struct IShellLinkAVtbl_ofs slvt =
+{
+    0,
+    {
+        (void*)ShellLink_QueryInterface,  /* IUnknown */
+        (void*)ShellLink_AddRef,
+        (void*)ShellLink_Release,
+        IShellLinkA_fnGetPath,
+        IShellLinkA_fnGetIDList,
+        IShellLinkA_fnSetIDList,
+        IShellLinkA_fnGetDescription,
+        IShellLinkA_fnSetDescription,
+        IShellLinkA_fnGetWorkingDirectory,
+        IShellLinkA_fnSetWorkingDirectory,
+        IShellLinkA_fnGetArguments,
+        IShellLinkA_fnSetArguments,
+        IShellLinkA_fnGetHotkey,
+        IShellLinkA_fnSetHotkey,
+        IShellLinkA_fnGetShowCmd,
+        IShellLinkA_fnSetShowCmd,
+        IShellLinkA_fnGetIconLocation,
+        IShellLinkA_fnSetIconLocation,
+        IShellLinkA_fnSetRelativePath,
+        IShellLinkA_fnResolve,
+        IShellLinkA_fnSetPath
+    }
+};
+
+const static struct IShellLinkWVtbl_ofs slvtw =
 {
-	IShellLinkW_fnQueryInterface,
-	IShellLinkW_fnAddRef,
-	IShellLinkW_fnRelease,
-	IShellLinkW_fnGetPath,
-	IShellLinkW_fnGetIDList,
-	IShellLinkW_fnSetIDList,
-	IShellLinkW_fnGetDescription,
-	IShellLinkW_fnSetDescription,
-	IShellLinkW_fnGetWorkingDirectory,
-	IShellLinkW_fnSetWorkingDirectory,
-	IShellLinkW_fnGetArguments,
-	IShellLinkW_fnSetArguments,
-	IShellLinkW_fnGetHotkey,
-	IShellLinkW_fnSetHotkey,
-	IShellLinkW_fnGetShowCmd,
-	IShellLinkW_fnSetShowCmd,
-	IShellLinkW_fnGetIconLocation,
-	IShellLinkW_fnSetIconLocation,
-	IShellLinkW_fnSetRelativePath,
-	IShellLinkW_fnResolve,
-	IShellLinkW_fnSetPath
+    1,
+    {
+        (void*)ShellLink_QueryInterface,  /* IUnknown */
+        (void*)ShellLink_AddRef,
+        (void*)ShellLink_Release,
+        IShellLinkW_fnGetPath,
+        IShellLinkW_fnGetIDList,
+        IShellLinkW_fnSetIDList,
+        IShellLinkW_fnGetDescription,
+        IShellLinkW_fnSetDescription,
+        IShellLinkW_fnGetWorkingDirectory,
+        IShellLinkW_fnSetWorkingDirectory,
+        IShellLinkW_fnGetArguments,
+        IShellLinkW_fnSetArguments,
+        IShellLinkW_fnGetHotkey,
+        IShellLinkW_fnSetHotkey,
+        IShellLinkW_fnGetShowCmd,
+        IShellLinkW_fnSetShowCmd,
+        IShellLinkW_fnGetIconLocation,
+        IShellLinkW_fnSetIconLocation,
+        IShellLinkW_fnSetRelativePath,
+        IShellLinkW_fnResolve,
+        IShellLinkW_fnSetPath
+    }
 };
+
+const static struct IPersistFileVtbl_ofs pfvt =
+{
+    2,
+    {
+        (void*)ShellLink_QueryInterface,  /* IUnknown */
+        (void*)ShellLink_AddRef,
+        (void*)ShellLink_Release,
+        (void*)ShellLink_GetClassID,      /* IPersist */
+        IPersistFile_fnIsDirty,
+        IPersistFile_fnLoad,
+        IPersistFile_fnSave,
+        IPersistFile_fnSaveCompleted,
+        IPersistFile_fnGetCurFile
+    }
+};
+
+const static struct IPersistStreamVtbl_ofs psvt =
+{
+    3,
+    {
+        (void*)ShellLink_QueryInterface,  /* IUnknown */
+        (void*)ShellLink_AddRef,
+        (void*)ShellLink_Release,
+        (void*)ShellLink_GetClassID,
+        IPersistStream_fnIsDirty,
+        IPersistStream_fnLoad,
+        IPersistStream_fnSave,
+        IPersistStream_fnGetSizeMax
+    }
+};
+
+/**************************************************************************
+ *	  IShellLink_Constructor
+ */
+HRESULT WINAPI IShellLink_Constructor( IUnknown *pUnkOuter,
+               REFIID riid, LPVOID *ppv )
+{
+    IShellLinkImpl * sl;
+    HRESULT r;
+
+    TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
+
+    *ppv = NULL;
+
+    if (pUnkOuter)
+        return CLASS_E_NOAGGREGATION;
+    sl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (*sl) );
+    if (!sl)
+        return E_OUTOFMEMORY;
+
+    sl->ref = 1;
+    sl->lpVtbl = &slvt.vtable;
+    sl->lpvtblw = &slvtw.vtable;
+    sl->lpvtblPersistFile = &pfvt.vtable;
+    sl->lpvtblPersistStream = &psvt.vtable;
+    sl->iShowCmd = SW_SHOWNORMAL;
+    sl->bDirty = FALSE;
+
+    TRACE("(%p)->()\n",sl);
+
+    r = IUnknown_QueryInterface( (IUnknown*) sl, riid, ppv );
+    IUnknown_Release( (IUnknown*) sl );
+
+    return r;
+}


More information about the wine-patches mailing list