3 * Win32 Global/Local heap functions (GlobalXXX, LocalXXX).
4 * These functions included in Win32 for compatibility with 16 bit Windows
5 * Especially the moveable blocks and handles are oldish.
6 * But the ability to directly allocate memory with GPTR and LPTR is widely
11 * NOTE: Only fixed memory is implemented!!
17 #include <kernel32/kernel32.h>
20 #define MAGIC_GLOBAL_USED 0x5342BEEF
21 #define GLOBAL_LOCK_MAX 0xFF
23 typedef struct __GLOBAL_LOCAL_HANDLE
29 } GLOBAL_HANDLE, LOCAL_HANDLE, *PGLOBAL_HANDLE, *PLOCAL_HANDLE;
32 /* FUNCTIONS ***************************************************************/
35 GlobalAlloc(UINT uFlags,
39 PGLOBAL_HANDLE phandle;
43 DPRINT("GlobalAlloc( 0x%X, 0x%lX )\n", uFlags, dwBytes);
45 if ((uFlags & GMEM_MOVEABLE)==0) /* POINTER */
47 if ((uFlags & GMEM_ZEROINIT)==0)
48 return ((HGLOBAL)RtlAllocateHeap(hProcessHeap, 0, dwBytes));
50 return ((HGLOBAL)RtlAllocateHeap(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes));
55 HeapLock(__ProcessHeap);
58 phandle=__HeapAllocFragment(__ProcessHeap, 0, sizeof(GLOBAL_HANDLE));
61 palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE));
62 *(PHANDLE)palloc=(HANDLE) &(phandle->Pointer);
63 phandle->Pointer=palloc+sizeof(HANDLE);
66 phandle->Pointer=NULL;
67 phandle->Magic=MAGIC_GLOBAL_USED;
68 phandle->Flags=uFlags>>8;
70 HeapUnlock(__ProcessHeap);
72 return (HGLOBAL) &(phandle->Pointer);
80 GlobalCompact(DWORD dwMinFree)
82 return RtlCompactHeap(hProcessHeap, 0);
87 GlobalFix(HGLOBAL hMem)
89 if (hMem != INVALID_HANDLE_VALUE)
95 GlobalFlags(HGLOBAL hMem)
99 PGLOBAL_HANDLE phandle;
102 DPRINT("GlobalFlags( 0x%lX )\n", (ULONG)hMem);
105 if(((ULONG)hmem%8)==0)
111 HeapLock(__ProcessHeap);
112 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
113 if(phandle->Magic==MAGIC_GLOBAL_USED)
115 retval=phandle->LockCount + (phandle->Flags<<8);
116 if(phandle->Pointer==0)
117 retval|= LMEM_DISCARDED;
121 DPRINT("GlobalSize: invalid handle\n");
124 HeapUnlock(__ProcessHeap);
134 GlobalFree(HGLOBAL hMem)
137 PGLOBAL_HANDLE phandle;
140 DPRINT("GlobalFree( 0x%lX )\n", (ULONG)hMem);
142 if (((ULONG)hMem % 4) == 0) /* POINTER */
144 RtlFreeHeap(hProcessHeap, 0, (PVOID)hMem);
149 HeapLock(__ProcessHeap);
150 phandle=(PGLOBAL_HANDLE)(((LPVOID) hMem)-4);
151 if(phandle->Magic==MAGIC_GLOBAL_USED)
153 HeapLock(__ProcessHeap);
154 if(phandle->LockCount!=0)
155 SetLastError(ERROR_INVALID_HANDLE);
157 HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE));
158 __HeapFreeFragment(__ProcessHeap, 0, phandle);
160 HeapUnlock(__ProcessHeap);
169 GlobalHandle(LPCVOID pMem)
171 DPRINT("GlobalHandle( 0x%lX )\n", (ULONG)pMem);
174 if(((ULONG)pmem%8)==0) /* FIXED */
175 return (HGLOBAL) pmem;
177 return (HGLOBAL) *(LPVOID *)(pmem-sizeof(HANDLE));
180 return (HGLOBAL)pMem;
185 GlobalLock(HGLOBAL hMem)
188 PGLOBAL_HANDLE phandle;
192 DPRINT("GlobalLock( 0x%lX )\n", (ULONG)hMem);
195 if(((ULONG)hmem%8)==0)
196 return (LPVOID) hmem;
198 HeapLock(__ProcessHeap);
199 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
200 if(phandle->Magic==MAGIC_GLOBAL_USED)
202 if(phandle->LockCount<GLOBAL_LOCK_MAX)
203 phandle->LockCount++;
204 palloc=phandle->Pointer;
208 DPRINT("GlobalLock: invalid handle\n");
209 palloc=(LPVOID) hmem;
211 HeapUnlock(__ProcessHeap);
220 GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer)
223 SYSTEM_PERFORMANCE_INFO Spi;
226 PIMAGE_NT_HEADERS ImageNtHeader;
228 RtlZeroMemory (lpBuffer, sizeof (MEMORYSTATUS));
229 lpBuffer->dwLength = sizeof (MEMORYSTATUS);
230 Status = NtQuerySystemInformation (
231 SystemPerformanceInformation,
236 /* FIXME: perform computations and fill lpBuffer fields */
237 Status = NtQueryInformationProcess (
244 /* FIXME: perform computations and fill lpBuffer fields */
245 Status = NtQueryInformationProcess (
252 /* FIXME: perform computations and fill lpBuffer fields */
253 ImageNtHeader = RtlImageNtHeader ((PVOID)NtCurrentPeb()->ImageBaseAddress);
254 /* FIXME: perform computations and fill lpBuffer fields */
259 GlobalReAlloc(HGLOBAL hMem,
266 PGLOBAL_HANDLE phandle;
269 DPRINT("GlobalReAlloc( 0x%lX, 0x%lX, 0x%X )\n", (ULONG)hMem, dwBytes, uFlags);
273 HeapLock(__ProcessHeap);
274 if(flags & GMEM_MODIFY) /* modify flags */
276 if( (((ULONG)hmem%8)==0) && (flags & GMEM_MOVEABLE))
278 /* make a fixed block moveable
279 * actually only NT is able to do this. And it's soo simple
281 size=HeapSize(__ProcessHeap, 0, (LPVOID) hmem);
282 hnew=GlobalAlloc( flags, size);
283 palloc=GlobalLock(hnew);
284 memcpy(palloc, (LPVOID) hmem, size);
286 GlobalHeapFree(GetProcessHeap(),0,hmem);
288 else if((((ULONG)hmem%8) != 0)&&(flags & GMEM_DISCARDABLE))
290 /* change the flags to make our block "discardable" */
291 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
292 phandle->Flags = phandle->Flags | (GMEM_DISCARDABLE >> 8);
297 SetLastError(ERROR_INVALID_PARAMETER);
303 if(((ULONG)hmem%8)!=0)
305 /* reallocate fixed memory */
306 hnew=(HANDLE)HeapReAlloc(__ProcessHeap, 0, (LPVOID) hmem, size);
310 /* reallocate a moveable block */
311 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
312 if(phandle->LockCount!=0)
313 SetLastError(ERROR_INVALID_HANDLE);
319 palloc=HeapReAlloc(__ProcessHeap, 0,
320 phandle->Pointer-sizeof(HANDLE),
321 size+sizeof(HANDLE) );
322 phandle->Pointer=palloc+sizeof(HANDLE);
326 palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE));
327 *(PHANDLE)palloc=hmem;
328 phandle->Pointer=palloc+sizeof(HANDLE);
335 HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE));
336 phandle->Pointer=NULL;
341 HeapUnlock(__ProcessHeap);
344 return ((HGLOBAL)RtlReAllocateHeap(hProcessHeap, uFlags, (LPVOID)hMem, dwBytes));
350 GlobalSize(HGLOBAL hMem)
354 PGLOBAL_HANDLE phandle;
357 DPRINT("GlobalSize( 0x%lX )\n", (ULONG)hMem);
359 if(((ULONG)hMem % 4) == 0)
361 retval = RtlSizeHeap(hProcessHeap, 0, hMem);
366 HeapLock(__ProcessHeap);
367 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
368 if(phandle->Magic==MAGIC_GLOBAL_USED)
370 retval=HeapSize(__ProcessHeap, 0, (phandle->Pointer)-sizeof(HANDLE))-4;
374 DPRINT("GlobalSize: invalid handle\n");
377 HeapUnlock(__ProcessHeap);
386 GlobalUnfix(HGLOBAL hMem)
388 if (hMem != INVALID_HANDLE_VALUE)
394 GlobalUnlock(HGLOBAL hMem)
397 PGLOBAL_HANDLE phandle;
401 DPRINT("GlobalUnlock( 0x%lX )\n", (ULONG)hMem);
404 if(((ULONG)hmem%8)==0)
407 HeapLock(__ProcessHeap);
408 phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4);
409 if(phandle->Magic==MAGIC_GLOBAL_USED)
411 if((phandle->LockCount<GLOBAL_LOCK_MAX)&&(phandle->LockCount>0))
412 phandle->LockCount--;
414 locked=(phandle->LockCount==0) ? TRUE : FALSE;
418 DPRINT("GlobalUnlock: invalid handle\n");
421 HeapUnlock(__ProcessHeap);
430 GlobalUnWire(HGLOBAL hMem)
432 return GlobalUnlock(hMem);
437 GlobalWire(HGLOBAL hMem)
439 return GlobalLock(hMem);