mguyott@eriador.prime.com (03/15/91)
I'm wondering if anyone else has had a problem with the Windows GlobalUnlock() function? I began experiencing an unexpected problem so I wrote the following test code and went into CVW to see what was happening: HANDLE hMem; LPSTR pMem; if ((hMem = GlobalAlloc((GMEM_FIXED | GMEM_ZEROINIT), 64L)) == NULL) { MessageBox(NULL, "GlobalAlloc( ) failed!", // Message. "Error in GlobalAlloc( )!", // Caption. MB_ICONHAND | MB_SYSTEMMODAL | MB_OK); return(NULL); } if ((pMem = (void FAR *)GlobalLock(hMem)) == NULL) { MessageBox(NULL, "GlobalLock( ) failed!", // Message. "Error in GlobalLock( )!", // Caption. MB_ICONHAND | MB_SYSTEMMODAL | MB_OK); return(NULL); } if (GlobalUnlock(hMem)) != NULL) { MessageBox(NULL, "GlobalUnlock( ) failed!", // Message. "Error in GlobalUnlock( )!", // Caption. MB_ICONHAND | MB_SYSTEMMODAL | MB_OK); return; } if (GlobalFree(hMem) != NULL) { MessageBox(NULL, "GlobalFree( ) failed!", // Message. "Error in GlobalFree( )!", // Caption. MB_ICONHAND | MB_SYSTEMMODAL | MB_OK); return; } It turns out that if you call GlobalUnlock() in this case it returns the value passed in (i.e. hMem). According to the documentation for GlobalUnlock() (page 4-247 and 4-248 Ref. Vol. 1): "The return value specifies the outcome of the function. It is ZERO (my emphasis) if the block's lock count was decreased to zero. Otherwise, the return value is nonzero." So I thought that perhaps the block was mysteriously being locked somewhere else in my progarm so I put the unlock call into a loop so that it was called until it returned zero. My program hung in an infinite loop. When I went into CVW I traced through the loop 50 times before I gave up. It seems that the return value has nothing to do with the lock count in this case. In fact, if I ignore the return value, unlock the handle once, and then call GlobalFree(), GlobalFree() will return SUCCESS (i.e. zero). And it seems that everyone is happy. I then tried changing the GMEM_FIXED flag to GMEM_MOVEABLE. Everything now worked fine. So it seems that calling GlobalUnlock() for memory that was allocated with the GMEM_FIXED flag will always return failure (actually it returns the handle that you passed to it). This is especially annoying if you are trying to be a good Windows programmer and do things "correctly". To do things correctly you have to call GlobalLock() to get a pointer from the memory handle returned by GlobalAlloc(). On page 16-27 of the Guide to Programming it states that "You must still call GlobalUnlock in protected mode when you no longer need the pointer returned by GlobalLock." Even though calling GlobalLock() did not increment the lock count for that pointer. If I wasn't trying to do things "correctly" I could just use the non-standard shortcuts for global memory allocation/deallocation: pMem = (LPSTR)MAKELONG(0, GlobalAlloc((GMEM_FIXED | GMEM_ZEROINIT), 64L)); GlobalFree((GLOBALHANDLE)HIWORD((LONG)pMem)); then I would have no problems. So is this a bug that MS knows about? Is this a bug or is this an ommission in the documentation? Marc ---- Two of the worst things we teach our children are that a knowledge of science is nice but not necessary, and a knowledge of sex is necessary but not nice. Marc Guyott Constellation Software, Inc. (508) 620-2800 Framingham, Mass. 01701 USA Ext. 3135 mguyott@primerd.prime.com ...!{uunet, decwrl}!primerd.prime.com!mguyott