Re: GlobalAlloc GlobalReAlloc problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Jan 04, 2003 at 02:54:12AM +0100, Michael Stefaniuc wrote:
> Do we want to mimic the GlobalAlloc/GlobalReAlloc behaviour of Windows
> (the DiMage Viewer dosn't corrupt the images at least on Win98 and it's
> the same binary for Win2000 too)? Could be that some other broken, real
> life programs are dependent of that behaviour).
> At a quick glance i don't know how to fix GlobalAlloc/GlobalReAlloc
> without breaking it. I'll do a bugzilla report but want to save me the
> work if it will get anyway a WONTFIX resolution.
Well, it wasn't so hard to fix as I first thought. And the patch isn't
too intrusive, it aligns only the storage needed for the HGLOBAL on an
8byte boundary. The only disatvantage is we waste 1 byte per memory
region allocated with GMEM_MOVEABLE but this should be realy tolerable.
Alexandre, i could replace the definition of HGLOBAL_STORAGE with
something like:
#define HGLOBAL_STORAGE		ROUND_SIZE(sizeof(HGOBAL))
and use the ROUND_SIZE macro from dlls/ntdll/heap.c . The two magics
"-2" in the patch could be also replaced by HGLOBAL_STORAGE/sizeof(HGOBAL)

License: LGPL, X11
Changelog:
	Michael Stefaniuc <mstefani@redhat.com>
	- the Minolta DiMAGE Image Viewer relies on Global{,Re}Alloc
	  called with the GMEM_MOVEABLE flag set, to allocate the exact
	  specified size and no byte more when size = 8*k, where k=1,2,3,4.... . 
	  To achieve this allign the storage needed for the HGLOBAL in
	  the heap to 8byte boundary.

bye
	michael

P.S.: I'll redo the dlls/kernel/tests/alloc.c to have a test case
-- 
Michael Stefaniuc               Tel.: +49-711-96437-199
System Administration           Fax.: +49-711-96437-111
Red Hat GmbH                    Email: mstefani@redhat.com
Hauptstaetterstr. 58            http://www.redhat.de/
D-70178 Stuttgart
Index: memory/global.c
===================================================================
RCS file: /home/wine/wine/memory/global.c,v
retrieving revision 1.74
diff -u -u -r1.74 global.c
--- memory/global.c	2 Jan 2003 17:59:47 -0000	1.74
+++ memory/global.c	4 Jan 2003 03:50:32 -0000
@@ -1023,9 +1023,15 @@
 #define GLOBAL_LOCK_MAX   0xFF
 #define HANDLE_TO_INTERN(h)  ((PGLOBAL32_INTERN)(((char *)(h))-2))
 #define INTERN_TO_HANDLE(i)  ((HGLOBAL) &((i)->Pointer))
-#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-1))
+#define POINTER_TO_HANDLE(p) (*(((HGLOBAL *)(p))-2))
 #define ISHANDLE(h)          (((DWORD)(h)&2)!=0)
 #define ISPOINTER(h)         (((DWORD)(h)&2)==0)
+/* allign the storage needed for the HGLOBAL on an 8byte boundary thus
+ * GlobalAlloc/GlobalReAlloc'ing with GMEM_MOVEABLE of memory with
+ * size = 8*k, where k=1,2,3,... alloc's exactly the given size.
+ * The Minolta DiMAGE Image Viewer heavily relies on this, corrupting
+ * the output jpeg's > 1 MB if not */
+#define HGLOBAL_STORAGE      8	/* sizeof(HGLOBAL)*2 */
 
 typedef struct __GLOBAL32_INTERN
 {
@@ -1070,12 +1076,12 @@
       if (!pintern) return 0;
       if(size)
       {
-	 if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+sizeof(HGLOBAL)))) {
+	 if (!(palloc=HeapAlloc(GetProcessHeap(), hpflags, size+HGLOBAL_STORAGE))) {
 	    HeapFree(GetProcessHeap(), 0, pintern);
 	    return 0;
 	 }
 	 *(HGLOBAL *)palloc=INTERN_TO_HANDLE(pintern);
-	 pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
+	 pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
       }
       else
 	 pintern->Pointer=NULL;
@@ -1211,7 +1217,7 @@
         maybe_intern = HANDLE_TO_INTERN( handle );
         if (maybe_intern->Magic == MAGIC_GLOBAL_USED) {
             test = maybe_intern->Pointer;
-            if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-1 ) && /* obj(-handle) valid arena? */
+            if (HeapValidate( GetProcessHeap(), 0, ((HGLOBAL *)test)-2 ) && /* obj(-handle) valid arena? */
                 HeapValidate( GetProcessHeap(), 0, maybe_intern ))  /* intern valid arena? */
                 break;  /* valid moveable block */
         }
@@ -1306,25 +1312,25 @@
 	    if(pintern->Pointer)
 	    {
 	       if((palloc = HeapReAlloc(GetProcessHeap(), heap_flags,
-				   (char *) pintern->Pointer-sizeof(HGLOBAL),
-				   size+sizeof(HGLOBAL))) == NULL)
+				   (char *) pintern->Pointer-HGLOBAL_STORAGE,
+				   size+HGLOBAL_STORAGE)) == NULL)
 		   return 0; /* Block still valid */
-	       pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
+	       pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
 	    }
 	    else
 	    {
-	        if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+sizeof(HGLOBAL)))
+	        if((palloc=HeapAlloc(GetProcessHeap(), heap_flags, size+HGLOBAL_STORAGE))
 		   == NULL)
 		    return 0;
 	       *(HGLOBAL *)palloc=hmem;
-	       pintern->Pointer=(char *) palloc+sizeof(HGLOBAL);
+	       pintern->Pointer=(char *) palloc+HGLOBAL_STORAGE;
 	    }
 	 }
 	 else
 	 {
 	    if(pintern->Pointer)
 	    {
-	       HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-sizeof(HGLOBAL));
+	       HeapFree(GetProcessHeap(), 0, (char *) pintern->Pointer-HGLOBAL_STORAGE);
 	       pintern->Pointer=NULL;
 	    }
 	 }
@@ -1368,7 +1374,7 @@
                 /*    SetLastError(ERROR_INVALID_HANDLE);  */
 
                 if(pintern->Pointer)
-                    if(!HeapFree(GetProcessHeap(), 0, (char *)(pintern->Pointer)-sizeof(HGLOBAL)))
+                    if(!HeapFree(GetProcessHeap(), 0, (char *)(pintern->Pointer)-HGLOBAL_STORAGE))
                         hreturned=hmem;
                 if(!HeapFree(GetProcessHeap(), 0, pintern))
                     hreturned=hmem;
@@ -1413,7 +1419,7 @@
         if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */
             return 0;
 	 retval=HeapSize(GetProcessHeap(), 0,
-	                 (char *)(pintern->Pointer)-sizeof(HGLOBAL))-4;
+	                 (char *)(pintern->Pointer)-HGLOBAL_STORAGE)-HGLOBAL_STORAGE;
 	 if (retval == 0xffffffff-4) retval = 0;
       }
       else

Attachment: pgp00086.pgp
Description: PGP signature


[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux