SHAllocShared fixes

Francois Gouget fgouget at free.fr
Mon Aug 30 22:15:15 CDT 2004


On Mon, 30 Aug 2004, Alexandre Julliard wrote:

> Francois Gouget <fgouget at free.fr> writes:
>
> > This actually calls for two more notes:
> >  * This looks very much what one would get by calling the corresponding
> > functions in shlwapi (which seems much more complete). However in
> > shell32 there is talk of sending messages around (WM_USER+2) so maybe
> > it's the same concept but a different implementation?
>
> The WM_USER+2 thing is something a specific caller was doing, it's not
> part of the function itself.

Yes that would make more sense. The same is probably true of the pidl
thingy.


> I think the shell32 functions should simply forward to the shlwapi
> ones.

Ok. Done.

I also moved the conformance test to the shlwapi dll since the
implementation is there. Compiling and running this test on Windows also
turned up a bug in the prototype of shlwapi.SHAllocShared.


Changelog:

 * dlls/shell32/shell32.spec
   dlls/shell32/shellord.c
   dlls/shell32/undocshell.h
   dlls/shlwapi/ordinal.c
   dlls/shlwapi/shlwapi.spec
   dlls/shlwapi/tests/Makefile.in
   dlls/shlwapi/tests/alloc.c

   Don't export the shell32 SHAllocShared functions by name.
   Implement them by calling out their shlwapi equivalent (which had a
much more complete implementation anyway).
   Fix the prototype of shlwapi's SHAllocShared().
   Don't crash if lpvData is NULL in SHAllocShared().
   Add a conformance test to shlwapi.


-- 
Francois Gouget         fgouget at free.fr        http://fgouget.free.fr/
                          La terre est une b\xEAta...
-------------- next part --------------
Index: dlls/shell32/shell32.spec
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shell32.spec,v
retrieving revision 1.85
diff -u -r1.85 shell32.spec
--- dlls/shell32/shell32.spec	9 Jul 2004 22:51:19 -0000	1.85
+++ dlls/shell32/shell32.spec	30 Aug 2004 22:29:31 -0000
@@ -278,10 +278,10 @@
  511 stdcall SHRegQueryValueExW (long wstr ptr ptr ptr ptr)
  512 stdcall SHRegDeleteKeyW (long wstr)
 
- 520 stdcall SHAllocShared (long long long)
- 521 stdcall SHLockShared (long long)
- 522 stdcall SHUnlockShared (long)
- 523 stdcall SHFreeShared (long long)
+ 520 stdcall @(long long long) SHAllocShared
+ 521 stdcall @(long long) SHLockShared
+ 522 stdcall @(long) SHUnlockShared
+ 523 stdcall @(long long) SHFreeShared
  524 stdcall RealDriveType (long long)
  525 stub RealDriveTypeFlags
 
Index: dlls/shell32/shellord.c
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/shellord.c,v
retrieving revision 1.124
diff -u -r1.124 shellord.c
--- dlls/shell32/shellord.c	22 Aug 2004 22:27:31 -0000	1.124
+++ dlls/shell32/shellord.c	30 Aug 2004 22:57:39 -0000
@@ -69,6 +69,25 @@
 extern INT    WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
 extern INT    WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
 
+
+/* Get a function pointer from a DLL handle */
+#define GET_FUNC(func, module, name, fail) \
+  do { \
+    if (!func) { \
+      if (!SHELL32_h##module && !(SHELL32_h##module = LoadLibraryA(#module ".dll"))) return fail; \
+      func = (void*)GetProcAddress(SHELL32_h##module, name); \
+      if (!func) return fail; \
+    } \
+  } while (0)
+
+/* Function pointers for GET_FUNC macro */
+static HMODULE SHELL32_hshlwapi=NULL;
+static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
+static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
+static BOOL   (WINAPI *pSHUnlockShared)(LPVOID);
+static BOOL   (WINAPI *pSHFreeShared)(HANDLE,DWORD);
+
+
 /*************************************************************************
  * ParseFieldA					[internal]
  *
@@ -1189,70 +1208,45 @@
 /*************************************************************************
  * SHAllocShared				[SHELL32.520]
  *
- * NOTES
- *  parameter1 is return value from HeapAlloc
- *  parameter2 is equal to the size allocated with HeapAlloc
- *  parameter3 is return value from GetCurrentProcessId
- *
- *  the return value is posted as lParam with 0x402 (WM_USER+2) to somewhere
- *  WM_USER+2 could be the undocumented CWM_SETPATH
- *  the allocated memory contains a pidl
- */
-HGLOBAL WINAPI SHAllocShared(LPVOID psrc, DWORD size, DWORD procID)
-{	HGLOBAL hmem;
-	LPVOID pmem;
-
-	TRACE("ptr=%p size=0x%04lx procID=0x%04lx\n",psrc,size,procID);
-	hmem = GlobalAlloc(GMEM_FIXED, size);
-	if (!hmem)
-	  return 0;
-
-	pmem =  GlobalLock (hmem);
-
-	if (! pmem)
-	  return 0;
-
-	memcpy (pmem, psrc, size);
-	GlobalUnlock(hmem);
-	return hmem;
+ * See shlwapi.SHAllocShared
+ */
+HANDLE WINAPI SHAllocShared(LPVOID lpvData, DWORD dwSize, DWORD dwProcId)
+{
+    GET_FUNC(pSHAllocShared, shlwapi, (char*)7, NULL);
+    return pSHAllocShared(lpvData, dwSize, dwProcId);
 }
+
 /*************************************************************************
- * SHLockShared					[SHELL32.521]
+ * @ [SHELL32.521]
  *
- * NOTES
- *  parameter1 is return value from SHAllocShared
- *  parameter2 is return value from GetCurrentProcessId
- *  the receiver of (WM_USER+2) tries to lock the HANDLE (?)
- *  the return value seems to be a memory address
+ * See shlwapi.SHLockShared
  */
-LPVOID WINAPI SHLockShared(HANDLE hmem, DWORD procID)
-{	TRACE("handle=%p procID=0x%04lx\n",hmem,procID);
-	return GlobalLock(hmem);
+LPVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
+{
+    GET_FUNC(pSHLockShared, shlwapi, (char*)8, NULL);
+    return pSHLockShared(hShared, dwProcId);
 }
+
 /*************************************************************************
- * SHUnlockShared				[SHELL32.522]
+ * @ [SHELL32.522]
  *
- * NOTES
- *  parameter1 is return value from SHLockShared
+ * See shlwapi.SHUnlockShared
  */
-BOOL WINAPI SHUnlockShared(LPVOID pv)
+BOOL WINAPI SHUnlockShared(LPVOID lpView)
 {
-	TRACE("%p\n",pv);
-	return GlobalUnlock((HANDLE)pv);
+    GET_FUNC(pSHUnlockShared, shlwapi, (char*)9, FALSE);
+    return pSHUnlockShared(lpView);
 }
+
 /*************************************************************************
- * SHFreeShared					[SHELL32.523]
+ * @ [SHELL32.523]
  *
- * NOTES
- *  parameter1 is return value from SHAllocShared
- *  parameter2 is return value from GetCurrentProcessId
+ * See shlwapi.SHFreeShared
  */
-BOOL WINAPI SHFreeShared(
-	HANDLE hMem,
-	DWORD pid)
+BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
 {
-	TRACE("handle=%p 0x%04lx\n",hMem,pid);
-	return (BOOL)GlobalFree(hMem);
+    GET_FUNC(pSHFreeShared, shlwapi, (char*)10, FALSE);
+    return pSHFreeShared(hShared, dwProcId);
 }
 
 /*************************************************************************
Index: dlls/shell32/undocshell.h
===================================================================
RCS file: /var/cvs/wine/dlls/shell32/undocshell.h,v
retrieving revision 1.25
diff -u -r1.25 undocshell.h
--- dlls/shell32/undocshell.h	22 Aug 2004 22:27:31 -0000	1.25
+++ dlls/shell32/undocshell.h	30 Aug 2004 14:35:57 -0000
@@ -154,6 +154,11 @@
  * Memory Routines
  */
 
+/* The Platform SDK's shlobj.h header defines similar functions with a
+ * leading underscore. However those are unusable because of the leading
+ * underscore, because they have an incorrect calling convention, and
+ * because these functions are not exported by name anyway.
+ */
 HANDLE WINAPI SHAllocShared(
 	LPVOID pv,
 	ULONG cb,
Index: dlls/shlwapi/ordinal.c
===================================================================
RCS file: /var/cvs/wine/dlls/shlwapi/ordinal.c,v
retrieving revision 1.93
diff -u -r1.93 ordinal.c
--- dlls/shlwapi/ordinal.c	22 Aug 2004 21:38:46 -0000	1.93
+++ dlls/shlwapi/ordinal.c	30 Aug 2004 22:56:15 -0000
@@ -77,8 +77,6 @@
 
 extern DWORD SHLWAPI_ThreadRef_index;
 
-typedef HANDLE HSHARED; /* Shared memory */
-
 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
@@ -145,7 +143,7 @@
  for unicode functions to provide these functions on systems without
  unicode functions eg. win95/win98. Since we have such functions we just
  call these. If running Wine with native DLL's, some late bound calls may
- fail. However, its better to implement the functions in the forward DLL
+ fail. However, it is better to implement the functions in the forward DLL
  and recommend the builtin rather than reimplementing the calls here!
 */
 
@@ -155,15 +153,15 @@
  * Internal implemetation of SHLWAPI_11.
  */
 static
-HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
+HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
                                        DWORD dwSrcProcId, DWORD dwAccess,
                                        DWORD dwOptions)
 {
   HANDLE hDst, hSrc;
   DWORD dwMyProcId = GetCurrentProcessId();
-  HSHARED hRet = (HSHARED)NULL;
+  HANDLE hRet = NULL;
 
-  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
+  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
         dwAccess, dwOptions);
 
   /* Get dest process handle */
@@ -183,9 +181,9 @@
     if (hSrc)
     {
       /* Make handle available to dest process */
-      if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
+      if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
-        hRet = (HSHARED)NULL;
+        hRet = NULL;
 
       if (dwSrcProcId != dwMyProcId)
         CloseHandle(hSrc);
@@ -195,7 +193,7 @@
       CloseHandle(hDst);
   }
 
-  TRACE("Returning handle %p\n", (PVOID)hRet);
+  TRACE("Returning handle %p\n", hRet);
   return hRet;
 }
 
@@ -205,9 +203,9 @@
  * Create a block of sharable memory and initialise it with data.
  *
  * PARAMS
- * dwProcId [I] ID of process owning data
  * lpvData  [I] Pointer to data to write
  * dwSize   [I] Size of data
+ * dwProcId [I] ID of process owning data
  *
  * RETURNS
  * Success: A shared memory handle
@@ -221,13 +219,13 @@
  * the view pointer returned by this size.
  *
  */
-HSHARED WINAPI SHAllocShared(DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
+HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
 {
   HANDLE hMap;
   LPVOID pMapped;
-  HSHARED hRet = (HSHARED)NULL;
+  HANDLE hRet = NULL;
 
-  TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
+  TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
 
   /* Create file mapping of the correct length */
   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
@@ -242,12 +240,12 @@
   {
     /* Write size of data, followed by the data, to the view */
     *((DWORD*)pMapped) = dwSize;
-    if (dwSize)
+    if (lpvData)
       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
 
     /* Release view. All further views mapped will be opaque */
     UnmapViewOfFile(pMapped);
-    hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
+    hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
                                    DUPLICATE_SAME_ACCESS);
   }
@@ -270,18 +268,18 @@
  * Failure: NULL
  *
  */
-PVOID WINAPI SHLockShared(HSHARED hShared, DWORD dwProcId)
+PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
 {
-  HSHARED hDup;
+  HANDLE hDup;
   LPVOID pMapped;
 
-  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
+  TRACE("(%p %ld)\n", hShared, dwProcId);
 
   /* Get handle to shared memory for current process */
   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
                                  FILE_MAP_ALL_ACCESS, 0);
   /* Get View */
-  pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+  pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
   CloseHandle(hDup);
 
   if (pMapped)
@@ -322,17 +320,17 @@
  * Failure: FALSE
  *
  */
-BOOL WINAPI SHFreeShared(HSHARED hShared, DWORD dwProcId)
+BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
 {
-  HSHARED hClose;
+  HANDLE hClose;
 
-  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
+  TRACE("(%p %ld)\n", hShared, dwProcId);
 
   /* Get a copy of the handle for our process, closing the source handle */
   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
   /* Close local copy */
-  return CloseHandle((HANDLE)hClose);
+  return CloseHandle(hClose);
 }
 
 /*************************************************************************
@@ -352,10 +350,10 @@
  * Failure: A NULL handle.
  *
  */
-HSHARED WINAPI SHMapHandle(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
+HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
                           DWORD dwAccess, DWORD dwOptions)
 {
-  HSHARED hRet;
+  HANDLE hRet;
 
   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
                                  dwAccess, dwOptions);
Index: dlls/shlwapi/shlwapi.spec
===================================================================
RCS file: /var/cvs/wine/dlls/shlwapi/shlwapi.spec,v
retrieving revision 1.93
diff -u -r1.93 shlwapi.spec
--- dlls/shlwapi/shlwapi.spec	19 Jul 2004 19:32:51 -0000	1.93
+++ dlls/shlwapi/shlwapi.spec	30 Aug 2004 22:56:47 -0000
@@ -4,7 +4,7 @@
 4   stdcall -noname PathFileExistsDefExtW(wstr long)
 5   stdcall -noname PathFindOnPathExA(str ptr long)
 6   stdcall -noname PathFindOnPathExW(wstr ptr long)
-7   stdcall -noname SHAllocShared(long long ptr)
+7   stdcall -noname SHAllocShared(ptr long long)
 8   stdcall -noname SHLockShared(long long)
 9   stdcall -noname SHUnlockShared(ptr)
 10  stdcall -noname SHFreeShared(long long)
Index: dlls/shlwapi/tests/Makefile.in
===================================================================
RCS file: /var/cvs/wine/dlls/shlwapi/tests/Makefile.in,v
retrieving revision 1.6
diff -u -r1.6 Makefile.in
--- dlls/shlwapi/tests/Makefile.in	22 Mar 2004 20:40:03 -0000	1.6
+++ dlls/shlwapi/tests/Makefile.in	30 Aug 2004 22:38:59 -0000
@@ -6,6 +6,7 @@
 IMPORTS   = shlwapi advapi32 ole32 oleaut32
 
 CTESTS = \
+	alloc.c \
 	clist.c \
 	clsid.c \
 	generated.c \
--- /dev/null	2004-08-10 11:44:31.000000000 +0200
+++ dlls/shlwapi/tests/alloc.c	2004-08-31 00:52:11.000000000 +0200
@@ -0,0 +1,73 @@
+/*
+ * Unit test of the SHFileOperation function.
+ *
+ * Copyright 2004 Francois Gouget
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+ 
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/test.h"
+
+HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
+LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
+BOOL   (WINAPI *pSHUnlockShared)(LPVOID);
+BOOL   (WINAPI *pSHFreeShared)(HANDLE,DWORD);
+
+
+void test_alloc_shared()
+{
+    DWORD procid;
+    HANDLE hmem;
+    int val;
+    int* p;
+
+    procid=GetCurrentProcessId();
+    hmem=pSHAllocShared(NULL,10,procid);
+    ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError());
+    ok(pSHFreeShared(hmem, procid),
+       "SHFreeShared failed: %ld\n", GetLastError());
+
+    val=0x12345678;
+    hmem=pSHAllocShared(&val,4,procid);
+    ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %ld\n", GetLastError());
+
+    p=(int*)pSHLockShared(hmem,procid);
+    ok(p!=NULL,"SHLockShared failed: %ld\n", GetLastError());
+    if (p!=NULL)
+        ok(*p==val,"Wrong value in shared memory: %d instead of %d\n",*p,val);
+    ok(pSHUnlockShared(p),"SHUnlockShared failed: %ld\n", GetLastError());
+
+    ok(pSHFreeShared(hmem, procid),
+       "SHFreeShared failed: %ld\n", GetLastError());
+}
+
+START_TEST(alloc)
+{
+    HMODULE hdll;
+
+    /* These functions are not exported by name */
+    hdll=GetModuleHandle("shlwapi");
+    pSHAllocShared=(void*)GetProcAddress(hdll,(char*)7);
+    pSHLockShared=(void*)GetProcAddress(hdll,(char*)8);
+    pSHUnlockShared=(void*)GetProcAddress(hdll,(char*)9);
+    pSHFreeShared=(void*)GetProcAddress(hdll,(char*)10);
+
+    test_alloc_shared();
+}


More information about the wine-patches mailing list