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