Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenheapmem.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Win32 Base API 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: dll/win32/kernel32/mem/heap.c 00005 * PURPOSE: Heap Memory APIs (wrappers for RtlHeap*) 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <k32.h> 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS ********************************************************************/ 00017 00018 RTL_HANDLE_TABLE BaseHeapHandleTable; 00019 HANDLE BaseHeap; 00020 ULONG_PTR SystemRangeStart; 00021 00022 /* PRIVATE FUNCTIONS **********************************************************/ 00023 00024 VOID 00025 NTAPI 00026 BaseDllInitializeMemoryManager(VOID) 00027 { 00028 BaseHeap = RtlGetProcessHeap(); 00029 RtlInitializeHandleTable(0xFFFF, 00030 sizeof(BASE_HEAP_HANDLE_ENTRY), 00031 &BaseHeapHandleTable); 00032 NtQuerySystemInformation(SystemRangeStartInformation, 00033 &SystemRangeStart, 00034 sizeof(SystemRangeStart), 00035 NULL); 00036 } 00037 00038 /* PUBLIC FUNCTIONS ***********************************************************/ 00039 00040 /* 00041 * @implemented 00042 */ 00043 HANDLE 00044 WINAPI 00045 HeapCreate(DWORD flOptions, 00046 SIZE_T dwInitialSize, 00047 SIZE_T dwMaximumSize) 00048 { 00049 HANDLE hRet; 00050 ULONG Flags; 00051 00052 /* Remove non-Win32 flags and tag this allocation */ 00053 Flags = (flOptions & (HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE)) | 00054 HEAP_CLASS_1; 00055 00056 /* Check if heap is growable and ensure max size is correct */ 00057 if (dwMaximumSize == 0) 00058 Flags |= HEAP_GROWABLE; 00059 else if (dwMaximumSize < BaseStaticServerData->SysInfo.PageSize && 00060 dwInitialSize > dwMaximumSize) 00061 { 00062 /* Max size is non-zero but less than page size which can't be correct. 00063 Fix it up by bumping it to the initial size whatever it is. */ 00064 dwMaximumSize = dwInitialSize; 00065 } 00066 00067 /* Call RTL Heap */ 00068 hRet = RtlCreateHeap(Flags, 00069 NULL, 00070 dwMaximumSize, 00071 dwInitialSize, 00072 NULL, 00073 NULL); 00074 00075 /* Set the last error if we failed, and return the pointer */ 00076 if (!hRet) SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00077 return hRet; 00078 } 00079 00080 /* 00081 * @implemented 00082 */ 00083 BOOL 00084 WINAPI 00085 HeapDestroy(HANDLE hHeap) 00086 { 00087 /* Return TRUE if the heap was destroyed */ 00088 if (!RtlDestroyHeap(hHeap)) return TRUE; 00089 00090 /* Otherwise, we got the handle back, so fail */ 00091 SetLastError(ERROR_INVALID_HANDLE); 00092 return FALSE; 00093 } 00094 00095 /* 00096 * @implemented 00097 */ 00098 HANDLE 00099 WINAPI 00100 GetProcessHeap(VOID) 00101 { 00102 /* Call the RTL API */ 00103 return RtlGetProcessHeap(); 00104 } 00105 00106 /* 00107 * @implemented 00108 */ 00109 DWORD 00110 WINAPI 00111 GetProcessHeaps(DWORD NumberOfHeaps, 00112 PHANDLE ProcessHeaps) 00113 { 00114 /* Call the RTL API */ 00115 return RtlGetProcessHeaps(NumberOfHeaps, ProcessHeaps); 00116 } 00117 00118 /* 00119 * @implemented 00120 */ 00121 BOOL 00122 WINAPI 00123 HeapLock(HANDLE hHeap) 00124 { 00125 /* Call the RTL API */ 00126 return RtlLockHeap(hHeap); 00127 } 00128 00129 /* 00130 * @implemented 00131 */ 00132 BOOL 00133 WINAPI 00134 HeapUnlock(HANDLE hHeap) 00135 { 00136 /* Call the RTL API */ 00137 return RtlUnlockHeap(hHeap); 00138 } 00139 00140 /* 00141 * @implemented 00142 */ 00143 SIZE_T 00144 WINAPI 00145 HeapCompact(HANDLE hHeap, DWORD dwFlags) 00146 { 00147 /* Call the RTL API */ 00148 return RtlCompactHeap(hHeap, dwFlags); 00149 } 00150 00151 /* 00152 * @implemented 00153 */ 00154 BOOL 00155 WINAPI 00156 HeapValidate(HANDLE hHeap, 00157 DWORD dwFlags, 00158 LPCVOID lpMem) 00159 { 00160 /* Call the RTL API */ 00161 return RtlValidateHeap(hHeap, dwFlags, (PVOID)lpMem); 00162 } 00163 00164 /* 00165 * @implemented 00166 */ 00167 DWORD 00168 WINAPI 00169 HeapCreateTagsW(HANDLE hHeap, 00170 DWORD dwFlags, 00171 PWSTR lpTagName, 00172 PWSTR lpTagSubName) 00173 { 00174 /* Call the RTL API */ 00175 return RtlCreateTagHeap(hHeap, 00176 dwFlags, 00177 lpTagName, 00178 lpTagSubName); 00179 } 00180 00181 /* 00182 * @implemented 00183 */ 00184 DWORD 00185 WINAPI 00186 HeapExtend(HANDLE hHeap, 00187 DWORD dwFlags, 00188 PVOID BaseAddress, 00189 DWORD dwBytes) 00190 { 00191 NTSTATUS Status; 00192 00193 /* Call the RTL API. Gone in Vista, so commented out. */ 00194 Status = STATUS_NOT_IMPLEMENTED; //RtlExtendHeap(hHeap, dwFlags, BaseAddress, dwBytes); 00195 if (!NT_SUCCESS(Status)) 00196 { 00197 /* We failed */ 00198 BaseSetLastNTError(Status); 00199 return FALSE; 00200 } 00201 00202 /* Return success */ 00203 return TRUE; 00204 } 00205 00206 /* 00207 * @implemented 00208 */ 00209 PWSTR 00210 WINAPI 00211 HeapQueryTagW(HANDLE hHeap, 00212 DWORD dwFlags, 00213 WORD wTagIndex, 00214 BOOL bResetCounters, 00215 PVOID lpTagInfo) 00216 { 00217 /* Call the RTL API */ 00218 return RtlQueryTagHeap(hHeap, 00219 dwFlags, 00220 wTagIndex, 00221 (BOOLEAN)bResetCounters, 00222 lpTagInfo); 00223 } 00224 00225 /* 00226 * @implemented 00227 */ 00228 BOOL 00229 WINAPI 00230 HeapSummary(HANDLE hHeap, 00231 DWORD dwFlags, 00232 PVOID Summary) 00233 { 00234 NTSTATUS Status; 00235 RTL_HEAP_USAGE Usage; 00236 00237 /* Fill in the length information */ 00238 Usage.Length = sizeof(Usage); 00239 00240 /* Call RTL. Gone in Vista, so commented out */ 00241 Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); 00242 if (!NT_SUCCESS(Status)) 00243 { 00244 /* We failed */ 00245 BaseSetLastNTError(Status); 00246 return FALSE; 00247 } 00248 00249 /* FIXME: Summary == Usage?! */ 00250 RtlCopyMemory(Summary, &Usage, sizeof(Usage)); 00251 return TRUE; 00252 } 00253 00254 /* 00255 * @implemented 00256 */ 00257 BOOL 00258 WINAPI 00259 HeapUsage(HANDLE hHeap, 00260 DWORD dwFlags, 00261 DWORD Unknown, 00262 DWORD Unknown2, 00263 IN PVOID Usage) 00264 { 00265 NTSTATUS Status; 00266 00267 /* Call RTL. Gone in Vista, so commented out */ 00268 Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); 00269 if (!NT_SUCCESS(Status)) 00270 { 00271 /* We failed */ 00272 BaseSetLastNTError(Status); 00273 return FALSE; 00274 } 00275 else if (Status == STATUS_MORE_ENTRIES) 00276 { 00277 /* There are still more entries to parse */ 00278 return TRUE; 00279 } 00280 00281 /* Otherwise, we're completely done, so we return FALSE, but NO_ERROR */ 00282 SetLastError(NO_ERROR); 00283 return FALSE; 00284 } 00285 00286 /* 00287 * @implemented 00288 */ 00289 BOOL 00290 WINAPI 00291 HeapWalk(HANDLE hHeap, 00292 LPPROCESS_HEAP_ENTRY lpEntry) 00293 { 00294 NTSTATUS Status; 00295 00296 DPRINT1("Warning, HeapWalk is calling RtlWalkHeap with Win32 parameters\n"); 00297 00298 Status = RtlWalkHeap(hHeap, lpEntry); 00299 00300 if (!NT_SUCCESS(Status)) 00301 { 00302 SetLastError(RtlNtStatusToDosError(Status)); 00303 return FALSE; 00304 } 00305 00306 return TRUE; 00307 } 00308 00309 /* 00310 * @implemented 00311 */ 00312 BOOL 00313 WINAPI 00314 HeapQueryInformation(HANDLE HeapHandle, 00315 HEAP_INFORMATION_CLASS HeapInformationClass, 00316 PVOID HeapInformation OPTIONAL, 00317 SIZE_T HeapInformationLength OPTIONAL, 00318 PSIZE_T ReturnLength OPTIONAL) 00319 { 00320 NTSTATUS Status; 00321 00322 Status = RtlQueryHeapInformation(HeapHandle, 00323 HeapInformationClass, 00324 HeapInformation, 00325 HeapInformationLength, 00326 ReturnLength); 00327 00328 if (!NT_SUCCESS(Status)) 00329 { 00330 BaseSetLastNTError(Status); 00331 return FALSE; 00332 } 00333 00334 return TRUE; 00335 } 00336 00337 /* 00338 * @implemented 00339 */ 00340 BOOL 00341 WINAPI 00342 HeapSetInformation(HANDLE HeapHandle, 00343 HEAP_INFORMATION_CLASS HeapInformationClass, 00344 PVOID HeapInformation OPTIONAL, 00345 SIZE_T HeapInformationLength OPTIONAL) 00346 { 00347 NTSTATUS Status; 00348 00349 Status = RtlSetHeapInformation(HeapHandle, 00350 HeapInformationClass, 00351 HeapInformation, 00352 HeapInformationLength); 00353 00354 if (!NT_SUCCESS(Status)) 00355 { 00356 BaseSetLastNTError(Status); 00357 return FALSE; 00358 } 00359 00360 return TRUE; 00361 } 00362 00363 /* 00364 * @implemented 00365 */ 00366 HGLOBAL 00367 NTAPI 00368 GlobalAlloc(UINT uFlags, 00369 SIZE_T dwBytes) 00370 { 00371 ULONG Flags = 0; 00372 PVOID Ptr = NULL; 00373 HANDLE hMemory; 00374 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 00375 BASE_TRACE_ALLOC(dwBytes, uFlags); 00376 ASSERT(BaseHeap); 00377 00378 /* Make sure the flags are valid */ 00379 if (uFlags & ~GMEM_VALID_FLAGS) 00380 { 00381 /* They aren't, fail */ 00382 BASE_TRACE_FAILURE(); 00383 SetLastError(ERROR_INVALID_PARAMETER); 00384 return NULL; 00385 } 00386 00387 /* Convert ZEROINIT */ 00388 if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; 00389 00390 /* Check if we're not movable, which means pointer-based heap */ 00391 if (!(uFlags & GMEM_MOVEABLE)) 00392 { 00393 /* Check if this is DDESHARE (deprecated) */ 00394 if (uFlags & GMEM_DDESHARE) Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE; 00395 00396 /* Allocate heap for it */ 00397 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes ? dwBytes : 1); 00398 if (!Ptr) SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00399 BASE_TRACE_ALLOC2(Ptr); 00400 return Ptr; 00401 } 00402 00403 /* This is heap based, so lock it in first */ 00404 RtlLockHeap(BaseHeap); 00405 00406 /* 00407 * Disable locking, enable custom flags, and write the 00408 * movable flag (deprecated) 00409 */ 00410 Flags |= HEAP_NO_SERIALIZE | 00411 HEAP_SETTABLE_USER_VALUE | 00412 BASE_HEAP_FLAG_MOVABLE; 00413 00414 /* Allocate the handle */ 00415 HandleEntry = BaseHeapAllocEntry(); 00416 if (!HandleEntry) 00417 { 00418 /* Fail */ 00419 hMemory = NULL; 00420 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00421 BASE_TRACE_FAILURE(); 00422 } 00423 else 00424 { 00425 /* Get the object and make sure we have size */ 00426 hMemory = &HandleEntry->Object; 00427 if (dwBytes) 00428 { 00429 /* Allocate the actual memory for it */ 00430 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes); 00431 BASE_TRACE_PTR(HandleEntry, Ptr); 00432 if (!Ptr) 00433 { 00434 /* We failed, manually set the allocate flag and free the handle */ 00435 HandleEntry->Flags = RTL_HANDLE_VALID; 00436 BaseHeapFreeEntry(HandleEntry); 00437 00438 /* For the cleanup case */ 00439 HandleEntry = NULL; 00440 } 00441 else 00442 { 00443 /* All worked well, save our heap entry */ 00444 RtlSetUserValueHeap(BaseHeap, HEAP_NO_SERIALIZE, Ptr, hMemory); 00445 } 00446 } 00447 } 00448 00449 /* Cleanup! First unlock the heap */ 00450 RtlUnlockHeap(BaseHeap); 00451 00452 /* Check if a handle was allocated */ 00453 if (HandleEntry) 00454 { 00455 /* Set the pointer and allocated flag */ 00456 HandleEntry->Object = Ptr; 00457 HandleEntry->Flags = RTL_HANDLE_VALID; 00458 if (!Ptr) 00459 { 00460 /* We don't have a valid pointer, but so reuse this handle */ 00461 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; 00462 } 00463 00464 /* Check if the handle is discardable */ 00465 if (uFlags & GMEM_DISCARDABLE) 00466 { 00467 /* Save it in the handle entry */ 00468 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; 00469 } 00470 00471 /* Check if the handle is moveable */ 00472 if (uFlags & GMEM_MOVEABLE) 00473 { 00474 /* Save it in the handle entry */ 00475 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE; 00476 } 00477 00478 /* Check if the handle is DDE Shared */ 00479 if (uFlags & GMEM_DDESHARE) 00480 { 00481 /* Save it in the handle entry */ 00482 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE; 00483 } 00484 00485 /* Set the pointer */ 00486 Ptr = hMemory; 00487 } 00488 00489 /* Return the pointer */ 00490 return Ptr; 00491 } 00492 00493 /* 00494 * @implemented 00495 */ 00496 SIZE_T 00497 NTAPI 00498 GlobalCompact(DWORD dwMinFree) 00499 { 00500 /* Call the RTL Heap Manager */ 00501 return RtlCompactHeap(BaseHeap, 0); 00502 } 00503 00504 /* 00505 * @implemented 00506 */ 00507 VOID 00508 NTAPI 00509 GlobalFix(HGLOBAL hMem) 00510 { 00511 /* Lock the memory if it the handle is valid */ 00512 if (INVALID_HANDLE_VALUE != hMem) GlobalLock(hMem); 00513 } 00514 00515 /* 00516 * @implemented 00517 */ 00518 UINT 00519 NTAPI 00520 GlobalFlags(HGLOBAL hMem) 00521 { 00522 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 00523 HANDLE Handle = NULL; 00524 ULONG Flags = 0; 00525 UINT uFlags = GMEM_INVALID_HANDLE; 00526 00527 /* Start by locking the heap */ 00528 RtlLockHeap(BaseHeap); 00529 _SEH2_TRY 00530 { 00531 /* Check if this is a simple RTL Heap Managed block */ 00532 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 00533 { 00534 /* Then we'll query RTL Heap */ 00535 RtlGetUserInfoHeap(BaseHeap, Flags, hMem, &Handle, &Flags); 00536 BASE_TRACE_PTR(Handle, hMem); 00537 00538 /* 00539 * Check if RTL Heap didn't find a handle associated with us or 00540 * said that this heap isn't movable, which means something we're 00541 * really not a handle-based heap. 00542 */ 00543 if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) 00544 { 00545 /* Then set the flags to 0 */ 00546 uFlags = 0; 00547 } 00548 else 00549 { 00550 /* Otherwise we're handle-based, so get the internal handle */ 00551 hMem = Handle; 00552 } 00553 } 00554 00555 /* Check if the handle is actually an entry in our table */ 00556 if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) 00557 { 00558 /* Then get the entry */ 00559 HandleEntry = BaseHeapGetEntry(hMem); 00560 BASE_TRACE_HANDLE(HandleEntry, hMem); 00561 00562 /* Make sure it's a valid handle */ 00563 if (BaseHeapValidateEntry(HandleEntry)) 00564 { 00565 /* Get the lock count first */ 00566 uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT; 00567 00568 /* Now check if it's discardable */ 00569 if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE) 00570 { 00571 /* Set the Win32 Flag */ 00572 uFlags |= GMEM_DISCARDABLE; 00573 } 00574 00575 /* Check if it's DDE Shared */ 00576 if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE) 00577 { 00578 /* Set the Win32 Flag */ 00579 uFlags |= GMEM_DDESHARE; 00580 } 00581 00582 /* Now check if it's discarded */ 00583 if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE) 00584 { 00585 /* Set the Win32 Flag */ 00586 uFlags |= GMEM_DISCARDED; 00587 } 00588 } 00589 } 00590 00591 /* Check if by now, we still haven't gotten any useful flags */ 00592 if (uFlags == GMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE); 00593 } 00594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00595 { 00596 /* Set the exception code */ 00597 BaseSetLastNTError(_SEH2_GetExceptionCode()); 00598 } 00599 _SEH2_END; 00600 00601 /* All done! Unlock heap and return Win32 Flags */ 00602 RtlUnlockHeap(BaseHeap); 00603 return uFlags; 00604 } 00605 00606 /* 00607 * @implemented 00608 */ 00609 HGLOBAL 00610 NTAPI 00611 GlobalFree(HGLOBAL hMem) 00612 { 00613 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 00614 LPVOID Ptr; 00615 BASE_TRACE_DEALLOC(hMem); 00616 00617 /* Check if this was a simple allocated heap entry */ 00618 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 00619 { 00620 /* Free it with the RTL Heap Manager */ 00621 if (RtlFreeHeap(BaseHeap, 0, hMem)) 00622 { 00623 /* Return NULL since there's no handle */ 00624 return NULL; 00625 } 00626 else 00627 { 00628 /* Otherwise fail */ 00629 BASE_TRACE_FAILURE(); 00630 SetLastError(ERROR_INVALID_HANDLE); 00631 return hMem; 00632 } 00633 } 00634 00635 /* It's a handle probably, so lock the heap */ 00636 RtlLockHeap(BaseHeap); 00637 _SEH2_TRY 00638 { 00639 /* Make sure that this is an entry in our handle database */ 00640 if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) 00641 { 00642 /* Get the entry */ 00643 HandleEntry = BaseHeapGetEntry(hMem); 00644 BASE_TRACE_HANDLE(HandleEntry, hMem); 00645 00646 /* Make sure the handle is valid */ 00647 if (!BaseHeapValidateEntry(HandleEntry)) 00648 { 00649 /* It's not, fail */ 00650 SetLastError(ERROR_INVALID_HANDLE); 00651 Ptr = NULL; 00652 } 00653 else 00654 { 00655 /* It's valid, so get the pointer */ 00656 Ptr = HandleEntry->Object; 00657 00658 /* Free this handle */ 00659 BaseHeapFreeEntry(HandleEntry); 00660 00661 /* If the pointer is 0, then we don't have a handle either */ 00662 if (!Ptr) hMem = NULL; 00663 } 00664 } 00665 else 00666 { 00667 /* Otherwise, reuse the handle as a pointer */ 00668 BASE_TRACE_FAILURE(); 00669 Ptr = hMem; 00670 } 00671 00672 /* Check if we got here with a valid heap pointer */ 00673 if (Ptr) 00674 { 00675 /* Free it with the RTL Heap Manager */ 00676 if (RtlFreeHeap(BaseHeap, HEAP_NO_SERIALIZE, Ptr)) 00677 { 00678 /* Everything worked */ 00679 hMem = NULL; 00680 } 00681 else 00682 { 00683 /* This wasn't a real heap handle */ 00684 SetLastError(ERROR_INVALID_HANDLE); 00685 } 00686 } 00687 } 00688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00689 { 00690 /* Set the exception code */ 00691 BaseSetLastNTError(_SEH2_GetExceptionCode()); 00692 } 00693 _SEH2_END; 00694 00695 /* We're done, so unlock the heap and return the handle */ 00696 RtlUnlockHeap(BaseHeap); 00697 return hMem; 00698 } 00699 00700 /* 00701 * @implemented 00702 */ 00703 HGLOBAL 00704 NTAPI 00705 GlobalHandle(LPCVOID pMem) 00706 { 00707 HANDLE Handle = NULL; 00708 ULONG Flags; 00709 00710 /* Lock the heap */ 00711 RtlLockHeap(BaseHeap); 00712 _SEH2_TRY 00713 { 00714 /* Query RTL Heap */ 00715 if (!RtlGetUserInfoHeap(BaseHeap, 00716 HEAP_NO_SERIALIZE, 00717 (PVOID)pMem, 00718 &Handle, 00719 &Flags)) 00720 { 00721 /* RTL Heap Manager does not know about this heap */ 00722 SetLastError(ERROR_INVALID_HANDLE); 00723 } 00724 else 00725 { 00726 /* 00727 * Check if RTL Heap didn't find a handle for us or said that 00728 * this heap isn't movable. 00729 */ 00730 BASE_TRACE_PTR(Handle, pMem); 00731 if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) 00732 { 00733 /* We're actually handle-based, so the pointer is a handle */ 00734 Handle = (HANDLE)pMem; 00735 } 00736 } 00737 } 00738 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00739 { 00740 /* Set the exception code */ 00741 BaseSetLastNTError(_SEH2_GetExceptionCode()); 00742 } 00743 _SEH2_END; 00744 00745 /* All done, unlock the heap and return the handle */ 00746 RtlUnlockHeap(BaseHeap); 00747 return Handle; 00748 } 00749 00750 /* 00751 * @implemented 00752 */ 00753 LPVOID 00754 NTAPI 00755 GlobalLock(HGLOBAL hMem) 00756 { 00757 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 00758 LPVOID Ptr; 00759 00760 /* Check if this was a simple allocated heap entry */ 00761 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 00762 { 00763 /* Make sure it's not a kernel or invalid address */ 00764 if ((hMem >= (HGLOBAL)SystemRangeStart) || (IsBadReadPtr(hMem, 1))) 00765 { 00766 /* Signal an error */ 00767 SetLastError(ERROR_INVALID_HANDLE); 00768 return NULL; 00769 } 00770 00771 /* It's all good */ 00772 return hMem; 00773 } 00774 00775 /* Otherwise, lock the heap */ 00776 RtlLockHeap(BaseHeap); 00777 _SEH2_TRY 00778 { 00779 /* Get the handle entry */ 00780 HandleEntry = BaseHeapGetEntry(hMem); 00781 BASE_TRACE_HANDLE(HandleEntry, hMem); 00782 00783 /* Make sure it's valid */ 00784 if (!BaseHeapValidateEntry(HandleEntry)) 00785 { 00786 /* It's not, fail */ 00787 BASE_TRACE_FAILURE(); 00788 SetLastError(ERROR_INVALID_HANDLE); 00789 Ptr = NULL; 00790 } 00791 else 00792 { 00793 /* Otherwise, get the pointer */ 00794 Ptr = HandleEntry->Object; 00795 if (Ptr) 00796 { 00797 /* Increase the lock count, unless we've went too far */ 00798 if (HandleEntry->LockCount++ == GMEM_LOCKCOUNT) 00799 { 00800 /* In which case we simply unlock once */ 00801 HandleEntry->LockCount--; 00802 } 00803 } 00804 else 00805 { 00806 /* The handle is still there but the memory was already freed */ 00807 SetLastError(ERROR_DISCARDED); 00808 } 00809 } 00810 } 00811 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00812 { 00813 SetLastError(ERROR_INVALID_HANDLE); 00814 Ptr = NULL; 00815 } 00816 _SEH2_END; 00817 00818 /* All done. Unlock the heap and return the pointer */ 00819 RtlUnlockHeap(BaseHeap); 00820 return Ptr; 00821 } 00822 00823 HGLOBAL 00824 NTAPI 00825 GlobalReAlloc(HGLOBAL hMem, 00826 SIZE_T dwBytes, 00827 UINT uFlags) 00828 { 00829 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 00830 HANDLE Handle; 00831 LPVOID Ptr; 00832 ULONG Flags = 0; 00833 00834 /* Throw out invalid flags */ 00835 if (uFlags & ~(GMEM_VALID_FLAGS | GMEM_MODIFY)) 00836 { 00837 SetLastError(ERROR_INVALID_PARAMETER); 00838 return NULL; 00839 } 00840 00841 /* Throw out invalid combo */ 00842 if ((uFlags & GMEM_DISCARDABLE) && !(uFlags & GMEM_MODIFY)) 00843 { 00844 SetLastError(ERROR_INVALID_PARAMETER); 00845 return NULL; 00846 } 00847 00848 /* Convert ZEROINIT */ 00849 if (uFlags & GMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; 00850 00851 /* If this wasn't a movable heap, then we MUST re-alloc in place */ 00852 if (!(uFlags & GMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY; 00853 00854 /* Lock the heap and disable built-in locking in the RTL Heap funcitons */ 00855 RtlLockHeap(BaseHeap); 00856 Flags |= HEAP_NO_SERIALIZE; 00857 00858 /* Check if this is a simple handle-based block */ 00859 if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 00860 { 00861 /* Get the entry */ 00862 HandleEntry = BaseHeapGetEntry(hMem); 00863 BASE_TRACE_HANDLE(HandleEntry, hMem); 00864 00865 /* Make sure the handle is valid */ 00866 if (!BaseHeapValidateEntry(HandleEntry)) 00867 { 00868 /* Fail */ 00869 BASE_TRACE_FAILURE(); 00870 SetLastError(ERROR_INVALID_HANDLE); 00871 hMem = NULL; 00872 } 00873 else if (uFlags & GMEM_MODIFY) 00874 { 00875 /* User is changing flags... check if the memory was discardable */ 00876 if (uFlags & GMEM_DISCARDABLE) 00877 { 00878 /* Then set the flag */ 00879 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; 00880 } 00881 else 00882 { 00883 /* Otherwise, remove the flag */ 00884 HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSABLE; 00885 } 00886 } 00887 else 00888 { 00889 /* Otherwise, get the object and check if we have no size */ 00890 Ptr = HandleEntry->Object; 00891 if (!dwBytes) 00892 { 00893 /* Clear the handle and check for a pointer */ 00894 hMem = NULL; 00895 if (Ptr) 00896 { 00897 /* Make sure the handle isn't locked */ 00898 if ((uFlags & GMEM_MOVEABLE) && !(HandleEntry->LockCount)) 00899 { 00900 /* Free the current heap */ 00901 if (RtlFreeHeap(BaseHeap, Flags, Ptr)) 00902 { 00903 /* Free the handle */ 00904 HandleEntry->Object = NULL; 00905 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; 00906 00907 /* Get the object pointer */ 00908 hMem = &HandleEntry->Object; 00909 } 00910 } 00911 } 00912 else 00913 { 00914 /* Otherwise just return the object pointer */ 00915 hMem = &HandleEntry->Object; 00916 } 00917 } 00918 else 00919 { 00920 /* Otherwise, we're allocating, so set the new flags needed */ 00921 Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE; 00922 if (!Ptr) 00923 { 00924 /* We don't have a base, so allocate one */ 00925 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes); 00926 BASE_TRACE_ALLOC2(Ptr); 00927 if (Ptr) 00928 { 00929 /* Allocation succeeded, so save our entry */ 00930 RtlSetUserValueHeap(BaseHeap, 00931 HEAP_NO_SERIALIZE, 00932 Ptr, 00933 hMem); 00934 } 00935 } 00936 else 00937 { 00938 /* 00939 * If it's not movable or currently locked, we MUST allocate 00940 * in-place! 00941 */ 00942 if (!(uFlags & GMEM_MOVEABLE) && (HandleEntry->LockCount)) 00943 { 00944 /* Set the flag */ 00945 Flags |= HEAP_REALLOC_IN_PLACE_ONLY; 00946 } 00947 else 00948 { 00949 /* Otherwise clear the flag if we set it previously */ 00950 Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY; 00951 } 00952 00953 /* Do the re-allocation. No need to save the entry again */ 00954 Ptr = RtlReAllocateHeap(BaseHeap, Flags, Ptr, dwBytes); 00955 } 00956 00957 /* Make sure we have a pointer by now */ 00958 if (Ptr) 00959 { 00960 /* Write it in the handle entry and mark it in use */ 00961 HandleEntry->Object = Ptr; 00962 HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE; 00963 } 00964 else 00965 { 00966 /* Otherwise we failed */ 00967 hMem = NULL; 00968 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00969 } 00970 } 00971 } 00972 } 00973 else if (uFlags & GMEM_MODIFY) 00974 { 00975 /* This is not a handle-based heap and the caller wants it to be one */ 00976 if (uFlags & GMEM_MOVEABLE) 00977 { 00978 /* Get information on its current state */ 00979 Handle = hMem; 00980 if (RtlGetUserInfoHeap(BaseHeap, 00981 HEAP_NO_SERIALIZE, 00982 hMem, 00983 &Handle, 00984 NULL)) 00985 { 00986 /* 00987 * Check if the handle matches the pointer or the moveable flag 00988 * isn't there, which is what we expect since it currenly isn't. 00989 */ 00990 if ((Handle == hMem) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) 00991 { 00992 /* Allocate a handle for it */ 00993 HandleEntry = BaseHeapAllocEntry(); 00994 if (!HandleEntry) 00995 { 00996 /* No entry could be allocated */ 00997 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00998 RtlUnlockHeap(BaseHeap); 00999 return NULL; 01000 } 01001 01002 /* Calculate the size of the current heap */ 01003 dwBytes = RtlSizeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem); 01004 01005 /* Set the movable flag */ 01006 Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE; 01007 01008 /* Now allocate the actual heap for it */ 01009 HandleEntry->Object = RtlAllocateHeap(BaseHeap, 01010 Flags, 01011 dwBytes); 01012 BASE_TRACE_PTR(HandleEntry->Object, HandleEntry); 01013 if (!HandleEntry->Object) 01014 { 01015 /* 01016 * We failed, manually set the allocate flag and 01017 * free the handle 01018 */ 01019 HandleEntry->Flags = RTL_HANDLE_VALID; 01020 BaseHeapFreeEntry(HandleEntry); 01021 01022 /* For the cleanup case */ 01023 BASE_TRACE_FAILURE(); 01024 HandleEntry = NULL; 01025 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01026 } 01027 else 01028 { 01029 /* Otherwise, copy the new heap and free the old one */ 01030 RtlMoveMemory(HandleEntry->Object, hMem, dwBytes); 01031 RtlFreeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem); 01032 01033 /* Select the heap pointer */ 01034 hMem = (HANDLE)&HandleEntry->Object; 01035 01036 /* Initialize the count and default flags */ 01037 HandleEntry->LockCount = 0; 01038 HandleEntry->Flags = RTL_HANDLE_VALID | 01039 BASE_HEAP_ENTRY_FLAG_MOVABLE; 01040 01041 /* Check if it's also discardable */ 01042 if (uFlags & GMEM_DISCARDABLE) 01043 { 01044 /* Set the internal flag */ 01045 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; 01046 } 01047 01048 /* Check if it's also DDE Shared */ 01049 if (uFlags & GMEM_DDESHARE) 01050 { 01051 /* Set the internal flag */ 01052 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE; 01053 } 01054 01055 /* Allocation succeeded, so save our entry */ 01056 RtlSetUserValueHeap(BaseHeap, 01057 HEAP_NO_SERIALIZE, 01058 HandleEntry->Object, 01059 hMem); 01060 } 01061 } 01062 } 01063 } 01064 } 01065 else 01066 { 01067 /* Otherwise, this is a simple RTL Managed Heap, so just call it */ 01068 hMem = RtlReAllocateHeap(BaseHeap, 01069 Flags | HEAP_NO_SERIALIZE, 01070 hMem, 01071 dwBytes); 01072 if (!hMem) 01073 { 01074 /* Fail */ 01075 BASE_TRACE_FAILURE(); 01076 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01077 } 01078 } 01079 01080 /* All done, unlock the heap and return the pointer */ 01081 RtlUnlockHeap(BaseHeap); 01082 return hMem; 01083 } 01084 01085 /* 01086 * @implemented 01087 */ 01088 SIZE_T 01089 NTAPI 01090 GlobalSize(HGLOBAL hMem) 01091 { 01092 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01093 PVOID Handle = NULL; 01094 ULONG Flags = 0; 01095 SIZE_T dwSize = MAXULONG_PTR; 01096 01097 /* Lock the heap */ 01098 RtlLockHeap(BaseHeap); 01099 _SEH2_TRY 01100 { 01101 /* Check if this is a simple RTL Heap Managed block */ 01102 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 01103 { 01104 /* Then we'll query RTL Heap */ 01105 if (RtlGetUserInfoHeap(BaseHeap, Flags, hMem, &Handle, &Flags)) 01106 { 01107 BASE_TRACE_PTR(Handle, hMem); 01108 /* 01109 * Check if RTL Heap didn't give us a handle or said that this 01110 * heap isn't movable. 01111 */ 01112 if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) 01113 { 01114 /* We're not a handle heap, so use the generic call */ 01115 dwSize = RtlSizeHeap(BaseHeap, HEAP_NO_SERIALIZE, hMem); 01116 } 01117 else 01118 { 01119 /* We're a handle heap so get the internal handle */ 01120 hMem = Handle; 01121 } 01122 } 01123 } 01124 01125 /* Make sure that this is an entry in our handle database */ 01126 if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) 01127 { 01128 /* Get the entry */ 01129 HandleEntry = BaseHeapGetEntry(hMem); 01130 BASE_TRACE_HANDLE(HandleEntry, hMem); 01131 01132 /* Make sure the handle is valid */ 01133 if (!BaseHeapValidateEntry(HandleEntry)) 01134 { 01135 /* Fail */ 01136 BASE_TRACE_FAILURE(); 01137 SetLastError(ERROR_INVALID_HANDLE); 01138 } 01139 else if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE) 01140 { 01141 /* We've reused this block, but we've saved the size for you */ 01142 dwSize = HandleEntry->OldSize; 01143 } 01144 else 01145 { 01146 /* Otherwise, query RTL about it */ 01147 dwSize = RtlSizeHeap(BaseHeap, 01148 HEAP_NO_SERIALIZE, 01149 HandleEntry->Object); 01150 } 01151 } 01152 } 01153 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01154 { 01155 /* Set failure for later */ 01156 dwSize = MAXULONG_PTR; 01157 } 01158 _SEH2_END; 01159 01160 /* Check if by now, we still haven't gotten any useful size */ 01161 if (dwSize == MAXULONG_PTR) 01162 { 01163 /* Fail */ 01164 BASE_TRACE_FAILURE(); 01165 SetLastError(ERROR_INVALID_HANDLE); 01166 dwSize = 0; 01167 } 01168 01169 /* All done! Unlock heap and return the size */ 01170 RtlUnlockHeap(BaseHeap); 01171 return dwSize; 01172 } 01173 01174 /* 01175 * @implemented 01176 */ 01177 VOID 01178 NTAPI 01179 GlobalUnfix(HGLOBAL hMem) 01180 { 01181 /* If the handle is valid, unlock it */ 01182 if (hMem != INVALID_HANDLE_VALUE) GlobalUnlock(hMem); 01183 } 01184 01185 /* 01186 * @implemented 01187 */ 01188 BOOL 01189 NTAPI 01190 GlobalUnlock(HGLOBAL hMem) 01191 { 01192 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01193 BOOL RetVal = TRUE; 01194 01195 /* Check if this was a simple allocated heap entry */ 01196 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) return RetVal; 01197 01198 /* Otherwise, lock the heap */ 01199 RtlLockHeap(BaseHeap); 01200 01201 /* Get the handle entry */ 01202 HandleEntry = BaseHeapGetEntry(hMem); 01203 BASE_TRACE_HANDLE(HandleEntry, hMem); 01204 01205 _SEH2_TRY 01206 { 01207 /* Make sure it's valid */ 01208 if (!BaseHeapValidateEntry(HandleEntry)) 01209 { 01210 /* It's not, fail */ 01211 BASE_TRACE_FAILURE(); 01212 SetLastError(ERROR_INVALID_HANDLE); 01213 RetVal = FALSE; 01214 } 01215 else 01216 { 01217 /* Otherwise, decrement lock count, unless we're already at 0*/ 01218 if (!HandleEntry->LockCount--) 01219 { 01220 /* In which case we simply lock it back and fail */ 01221 HandleEntry->LockCount++; 01222 SetLastError(ERROR_NOT_LOCKED); 01223 RetVal = FALSE; 01224 } 01225 else if (!HandleEntry->LockCount) 01226 { 01227 /* Nothing to unlock */ 01228 SetLastError(NO_ERROR); 01229 RetVal = FALSE; 01230 } 01231 } 01232 } 01233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01234 { 01235 SetLastError(ERROR_INVALID_PARAMETER); 01236 RetVal = FALSE; 01237 } 01238 _SEH2_END; 01239 01240 /* All done. Unlock the heap and return the pointer */ 01241 RtlUnlockHeap(BaseHeap); 01242 return RetVal; 01243 } 01244 01245 /* 01246 * @implemented 01247 */ 01248 BOOL 01249 NTAPI 01250 GlobalUnWire(HGLOBAL hMem) 01251 { 01252 /* This is simply an unlock */ 01253 return GlobalUnlock(hMem); 01254 } 01255 01256 /* 01257 * @implemented 01258 */ 01259 LPVOID 01260 NTAPI 01261 GlobalWire(HGLOBAL hMem) 01262 { 01263 /* This is just a lock */ 01264 return GlobalLock(hMem); 01265 } 01266 01267 /* 01268 * @implemented 01269 */ 01270 BOOL 01271 NTAPI 01272 GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer) 01273 { 01274 SYSTEM_PERFORMANCE_INFORMATION PerformanceInfo; 01275 VM_COUNTERS VmCounters; 01276 QUOTA_LIMITS QuotaLimits; 01277 ULONGLONG PageFile, PhysicalMemory; 01278 01279 /* Query performance information */ 01280 NtQuerySystemInformation(SystemPerformanceInformation, 01281 &PerformanceInfo, 01282 sizeof(PerformanceInfo), 01283 NULL); 01284 01285 /* Calculate memory load */ 01286 lpBuffer->dwMemoryLoad = ((DWORD)(BaseStaticServerData->SysInfo.NumberOfPhysicalPages - 01287 PerformanceInfo.AvailablePages) * 100) / 01288 BaseStaticServerData->SysInfo.NumberOfPhysicalPages; 01289 01290 /* Save physical memory */ 01291 PhysicalMemory = BaseStaticServerData->SysInfo.NumberOfPhysicalPages * 01292 BaseStaticServerData->SysInfo.PageSize; 01293 lpBuffer->ullTotalPhys = PhysicalMemory; 01294 01295 /* Now save available physical memory */ 01296 PhysicalMemory = PerformanceInfo.AvailablePages * 01297 BaseStaticServerData->SysInfo.PageSize; 01298 lpBuffer->ullAvailPhys = PhysicalMemory; 01299 01300 /* Query VM and Quota Limits */ 01301 NtQueryInformationProcess(NtCurrentProcess(), 01302 ProcessQuotaLimits, 01303 &QuotaLimits, 01304 sizeof(QUOTA_LIMITS), 01305 NULL); 01306 NtQueryInformationProcess(NtCurrentProcess(), 01307 ProcessVmCounters, 01308 &VmCounters, 01309 sizeof(VM_COUNTERS), 01310 NULL); 01311 01312 /* Save the commit limit */ 01313 lpBuffer->ullTotalPageFile = min(QuotaLimits.PagefileLimit, 01314 PerformanceInfo.CommitLimit); 01315 01316 /* Calculate how many pages are left */ 01317 PageFile = PerformanceInfo.CommitLimit - PerformanceInfo.CommittedPages; 01318 01319 /* Save the total */ 01320 lpBuffer->ullAvailPageFile = min(PageFile, 01321 QuotaLimits.PagefileLimit - 01322 VmCounters.PagefileUsage); 01323 lpBuffer->ullAvailPageFile *= BaseStaticServerData->SysInfo.PageSize; 01324 01325 /* Now calculate the total virtual space */ 01326 lpBuffer->ullTotalVirtual = (BaseStaticServerData->SysInfo.MaximumUserModeAddress - 01327 BaseStaticServerData->SysInfo.MinimumUserModeAddress) + 1; 01328 01329 /* And finally the avilable virtual space */ 01330 lpBuffer->ullAvailVirtual = lpBuffer->ullTotalVirtual - 01331 VmCounters.VirtualSize; 01332 lpBuffer->ullAvailExtendedVirtual = 0; 01333 return TRUE; 01334 } 01335 01336 /* 01337 * @implemented 01338 */ 01339 VOID 01340 NTAPI 01341 GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) 01342 { 01343 MEMORYSTATUSEX lpBufferEx; 01344 01345 /* Call the extended function */ 01346 lpBufferEx.dwLength = sizeof(MEMORYSTATUSEX); 01347 if (GlobalMemoryStatusEx(&lpBufferEx)) 01348 { 01349 /* Reset the right size and fill out the information */ 01350 lpBuffer->dwLength = sizeof(MEMORYSTATUS); 01351 lpBuffer->dwMemoryLoad = lpBufferEx.dwMemoryLoad; 01352 lpBuffer->dwTotalPhys = (SIZE_T)lpBufferEx.ullTotalPhys; 01353 lpBuffer->dwAvailPhys = (SIZE_T)lpBufferEx.ullAvailPhys; 01354 lpBuffer->dwTotalPageFile = (SIZE_T)lpBufferEx.ullTotalPageFile; 01355 lpBuffer->dwAvailPageFile = (SIZE_T)lpBufferEx.ullAvailPageFile; 01356 lpBuffer->dwTotalVirtual = (SIZE_T)lpBufferEx.ullTotalVirtual; 01357 lpBuffer->dwAvailVirtual = (SIZE_T)lpBufferEx.ullAvailVirtual; 01358 } 01359 } 01360 01361 /* 01362 * @implemented 01363 */ 01364 HLOCAL 01365 NTAPI 01366 LocalAlloc(UINT uFlags, 01367 SIZE_T dwBytes) 01368 { 01369 ULONG Flags = 0; 01370 PVOID Ptr = NULL; 01371 HANDLE hMemory; 01372 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01373 BASE_TRACE_ALLOC(dwBytes, uFlags); 01374 ASSERT(BaseHeap); 01375 01376 /* Make sure the flags are valid */ 01377 if (uFlags & ~LMEM_VALID_FLAGS) 01378 { 01379 /* They aren't, fail */ 01380 BASE_TRACE_FAILURE(); 01381 SetLastError(ERROR_INVALID_PARAMETER); 01382 return NULL; 01383 } 01384 01385 /* Convert ZEROINIT */ 01386 if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; 01387 01388 /* Check if we're not movable, which means pointer-based heap */ 01389 if (!(uFlags & LMEM_MOVEABLE)) 01390 { 01391 /* Allocate heap for it */ 01392 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes); 01393 BASE_TRACE_ALLOC2(Ptr); 01394 return Ptr; 01395 } 01396 01397 /* This is heap based, so lock it in first */ 01398 RtlLockHeap(BaseHeap); 01399 01400 /* 01401 * Disable locking, enable custom flags, and write the 01402 * movable flag (deprecated) 01403 */ 01404 Flags |= HEAP_NO_SERIALIZE | 01405 HEAP_SETTABLE_USER_VALUE | 01406 BASE_HEAP_FLAG_MOVABLE; 01407 01408 /* Allocate the handle */ 01409 HandleEntry = BaseHeapAllocEntry(); 01410 if (!HandleEntry) 01411 { 01412 /* Fail */ 01413 hMemory = NULL; 01414 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01415 BASE_TRACE_FAILURE(); 01416 goto Quickie; 01417 } 01418 01419 /* Get the object and make sure we have size */ 01420 hMemory = &HandleEntry->Object; 01421 if (dwBytes) 01422 { 01423 /* Allocate the actual memory for it */ 01424 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes); 01425 BASE_TRACE_PTR(HandleEntry, Ptr); 01426 if (!Ptr) 01427 { 01428 /* We failed, manually set the allocate flag and free the handle */ 01429 HandleEntry->Flags = RTL_HANDLE_VALID; 01430 BaseHeapFreeEntry(HandleEntry); 01431 01432 /* For the cleanup case */ 01433 HandleEntry = NULL; 01434 } 01435 else 01436 { 01437 /* All worked well, save our heap entry */ 01438 RtlSetUserValueHeap(BaseHeap, HEAP_NO_SERIALIZE, Ptr, hMemory); 01439 } 01440 } 01441 01442 Quickie: 01443 /* Cleanup! First unlock the heap */ 01444 RtlUnlockHeap(BaseHeap); 01445 01446 /* Check if a handle was allocated */ 01447 if (HandleEntry) 01448 { 01449 /* Set the pointer and allocated flag */ 01450 HandleEntry->Object = Ptr; 01451 HandleEntry->Flags = RTL_HANDLE_VALID; 01452 if (!Ptr) 01453 { 01454 /* We don't have a valid pointer, but so reuse this handle */ 01455 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; 01456 } 01457 01458 /* Check if the handle is discardable */ 01459 if (uFlags & GMEM_DISCARDABLE) 01460 { 01461 /* Save it in the handle entry */ 01462 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; 01463 } 01464 01465 /* Check if the handle is moveable */ 01466 if (uFlags & GMEM_MOVEABLE) 01467 { 01468 /* Save it in the handle entry */ 01469 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE; 01470 } 01471 01472 /* Set the pointer */ 01473 Ptr = hMemory; 01474 } 01475 01476 /* Return the pointer */ 01477 return Ptr; 01478 } 01479 01480 /* 01481 * @implemented 01482 */ 01483 SIZE_T 01484 NTAPI 01485 LocalCompact(UINT dwMinFree) 01486 { 01487 /* Call the RTL Heap Manager */ 01488 return RtlCompactHeap(BaseHeap, 0); 01489 } 01490 01491 /* 01492 * @implemented 01493 */ 01494 UINT 01495 NTAPI 01496 LocalFlags(HLOCAL hMem) 01497 { 01498 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01499 HANDLE Handle = NULL; 01500 ULONG Flags = 0; 01501 UINT uFlags = LMEM_INVALID_HANDLE; 01502 01503 /* Start by locking the heap */ 01504 RtlLockHeap(BaseHeap); 01505 01506 /* Check if this is a simple RTL Heap Managed block */ 01507 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 01508 { 01509 /* Then we'll query RTL Heap */ 01510 RtlGetUserInfoHeap(BaseHeap, Flags, hMem, &Handle, &Flags); 01511 BASE_TRACE_PTR(Handle, hMem); 01512 01513 /* 01514 * Check if RTL Heap didn't find a handle associated with us or 01515 * said that this heap isn't movable, which means something we're 01516 * really not a handle-based heap. 01517 */ 01518 if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) 01519 { 01520 /* Then set the flags to 0 */ 01521 uFlags = 0; 01522 } 01523 else 01524 { 01525 /* Otherwise we're handle-based, so get the internal handle */ 01526 hMem = Handle; 01527 } 01528 } 01529 01530 /* Check if the handle is actually an entry in our table */ 01531 if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) 01532 { 01533 /* Then get the entry */ 01534 HandleEntry = BaseHeapGetEntry(hMem); 01535 BASE_TRACE_HANDLE(HandleEntry, hMem); 01536 01537 /* Make sure it's a valid handle */ 01538 if (BaseHeapValidateEntry(HandleEntry)) 01539 { 01540 /* Get the lock count first */ 01541 uFlags = HandleEntry->LockCount & LMEM_LOCKCOUNT; 01542 01543 /* Now check if it's discardable */ 01544 if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE) 01545 { 01546 /* Set the Win32 Flag */ 01547 uFlags |= LMEM_DISCARDABLE; 01548 } 01549 01550 /* Now check if it's discarded */ 01551 if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE) 01552 /* Set the Win32 Flag */ 01553 uFlags |= LMEM_DISCARDED; 01554 } 01555 } 01556 01557 /* Check if by now, we still haven't gotten any useful flags */ 01558 if (uFlags == LMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE); 01559 01560 /* All done! Unlock heap and return Win32 Flags */ 01561 RtlUnlockHeap(BaseHeap); 01562 return uFlags; 01563 } 01564 01565 /* 01566 * @implemented 01567 */ 01568 HLOCAL 01569 NTAPI 01570 LocalFree(HLOCAL hMem) 01571 { 01572 /* This is identical to a Global Free */ 01573 return GlobalFree(hMem); 01574 } 01575 01576 /* 01577 * @implemented 01578 */ 01579 HLOCAL 01580 NTAPI 01581 LocalHandle(LPCVOID pMem) 01582 { 01583 /* This is identical to a Global Handle */ 01584 return GlobalHandle(pMem); 01585 } 01586 01587 /* 01588 * @implemented 01589 */ 01590 LPVOID 01591 NTAPI 01592 LocalLock(HLOCAL hMem) 01593 { 01594 /* This is the same as a GlobalLock, assuming these never change */ 01595 C_ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT); 01596 return GlobalLock(hMem); 01597 } 01598 01599 HLOCAL 01600 NTAPI 01601 LocalReAlloc(HLOCAL hMem, 01602 SIZE_T dwBytes, 01603 UINT uFlags) 01604 { 01605 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01606 LPVOID Ptr; 01607 ULONG Flags = 0; 01608 01609 /* Convert ZEROINIT */ 01610 if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; 01611 01612 /* If this wasn't a movable heap, then we MUST re-alloc in place */ 01613 if (!(uFlags & LMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY; 01614 01615 /* Lock the heap and disable built-in locking in the RTL Heap funcitons */ 01616 RtlLockHeap(BaseHeap); 01617 Flags |= HEAP_NO_SERIALIZE; 01618 01619 /* Check if this is a simple handle-based block */ 01620 if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 01621 { 01622 /* Get the entry */ 01623 HandleEntry = BaseHeapGetEntry(hMem); 01624 BASE_TRACE_HANDLE(HandleEntry, hMem); 01625 01626 /* Make sure the handle is valid */ 01627 if (!BaseHeapValidateEntry(HandleEntry)) 01628 { 01629 /* Fail */ 01630 BASE_TRACE_FAILURE(); 01631 SetLastError(ERROR_INVALID_HANDLE); 01632 hMem = NULL; 01633 } 01634 else if (uFlags & LMEM_MODIFY) 01635 { 01636 /* User is changing flags... check if the memory was discardable */ 01637 if (uFlags & LMEM_DISCARDABLE) 01638 { 01639 /* Then set the flag */ 01640 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; 01641 } 01642 else 01643 { 01644 /* Otherwise, remove the flag */ 01645 HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSABLE; 01646 } 01647 } 01648 else 01649 { 01650 /* Otherwise, get the object and check if we have no size */ 01651 Ptr = HandleEntry->Object; 01652 if (!dwBytes) 01653 { 01654 /* Clear the handle and check for a pointer */ 01655 hMem = NULL; 01656 if (Ptr) 01657 { 01658 /* Make sure the handle isn't locked */ 01659 if ((uFlags & LMEM_MOVEABLE) && !(HandleEntry->LockCount)) 01660 { 01661 /* Free the current heap */ 01662 RtlFreeHeap(BaseHeap, Flags, Ptr); 01663 01664 /* Free the handle */ 01665 HandleEntry->Object = NULL; 01666 HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; 01667 01668 /* Get the object pointer */ 01669 hMem = &HandleEntry->Object; 01670 } 01671 } 01672 else 01673 { 01674 /* Otherwise just return the object pointer */ 01675 hMem = &HandleEntry->Object; 01676 } 01677 } 01678 else 01679 { 01680 /* Otherwise, we're allocating, so set the new flags needed */ 01681 Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE; 01682 if (!Ptr) 01683 { 01684 /* We don't have a base, so allocate one */ 01685 Ptr = RtlAllocateHeap(BaseHeap, Flags, dwBytes); 01686 BASE_TRACE_ALLOC2(Ptr); 01687 if (Ptr) 01688 { 01689 /* Allocation succeeded, so save our entry */ 01690 RtlSetUserValueHeap(BaseHeap, 01691 HEAP_NO_SERIALIZE, 01692 Ptr, 01693 hMem); 01694 } 01695 } 01696 else 01697 { 01698 /* 01699 * If it's not movable or currently locked, we MUST allocate 01700 * in-place! 01701 */ 01702 if (!(uFlags & LMEM_MOVEABLE) && (HandleEntry->LockCount)) 01703 { 01704 /* Set the flag */ 01705 Flags |= HEAP_REALLOC_IN_PLACE_ONLY; 01706 } 01707 else 01708 { 01709 /* Otherwise clear the flag if we set it previously */ 01710 Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY; 01711 } 01712 01713 /* And do the re-allocation */ 01714 Ptr = RtlReAllocateHeap(BaseHeap, Flags, Ptr, dwBytes); 01715 } 01716 01717 /* Make sure we have a pointer by now */ 01718 if (Ptr) 01719 { 01720 /* Write it in the handle entry and mark it in use */ 01721 HandleEntry->Object = Ptr; 01722 HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE; 01723 } 01724 else 01725 { 01726 /* Otherwise we failed */ 01727 hMem = NULL; 01728 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01729 } 01730 } 01731 } 01732 } 01733 else if (!(uFlags & LMEM_MODIFY)) 01734 { 01735 /* Otherwise, this is a simple RTL Managed Heap, so just call it */ 01736 hMem = RtlReAllocateHeap(BaseHeap, 01737 Flags | HEAP_NO_SERIALIZE, 01738 hMem, 01739 dwBytes); 01740 if (!hMem) 01741 { 01742 /* Fail */ 01743 BASE_TRACE_FAILURE(); 01744 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01745 } 01746 } 01747 01748 /* All done, unlock the heap and return the pointer */ 01749 RtlUnlockHeap(BaseHeap); 01750 return hMem; 01751 } 01752 01753 /* 01754 * @implemented 01755 */ 01756 SIZE_T 01757 WINAPI 01758 LocalShrink(HLOCAL hMem, 01759 UINT cbNewSize) 01760 { 01761 /* Call RTL */ 01762 return RtlCompactHeap(BaseHeap, 0); 01763 } 01764 01765 /* 01766 * @implemented 01767 */ 01768 SIZE_T 01769 NTAPI 01770 LocalSize(HLOCAL hMem) 01771 { 01772 /* This is the same as a Global Size */ 01773 return GlobalSize(hMem); 01774 } 01775 01776 /* 01777 * @implemented 01778 */ 01779 BOOL 01780 NTAPI 01781 LocalUnlock(HLOCAL hMem) 01782 { 01783 PBASE_HEAP_HANDLE_ENTRY HandleEntry; 01784 BOOL RetVal = TRUE; 01785 01786 /* Check if this was a simple allocated heap entry */ 01787 if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) 01788 { 01789 /* Fail, because LocalUnlock is not supported on LMEM_FIXED allocations */ 01790 SetLastError(ERROR_NOT_LOCKED); 01791 return FALSE; 01792 } 01793 01794 /* Otherwise, lock the heap */ 01795 RtlLockHeap(BaseHeap); 01796 01797 /* Get the handle entry */ 01798 HandleEntry = BaseHeapGetEntry(hMem); 01799 BASE_TRACE_HANDLE(HandleEntry, hMem); 01800 _SEH2_TRY 01801 { 01802 /* Make sure it's valid */ 01803 if (!BaseHeapValidateEntry(HandleEntry)) 01804 { 01805 /* It's not, fail */ 01806 BASE_TRACE_FAILURE(); 01807 SetLastError(ERROR_INVALID_HANDLE); 01808 RetVal = FALSE; 01809 } 01810 else 01811 { 01812 /* Otherwise, decrement lock count, unless we're already at 0*/ 01813 if (!HandleEntry->LockCount--) 01814 { 01815 /* In which case we simply lock it back and fail */ 01816 HandleEntry->LockCount++; 01817 SetLastError(ERROR_NOT_LOCKED); 01818 RetVal = FALSE; 01819 } 01820 else if (!HandleEntry->LockCount) 01821 { 01822 /* Nothing to unlock */ 01823 SetLastError(NO_ERROR); 01824 RetVal = FALSE; 01825 } 01826 } 01827 } 01828 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01829 { 01830 SetLastError(ERROR_INVALID_PARAMETER); 01831 RetVal = FALSE; 01832 } 01833 _SEH2_END; 01834 01835 /* All done. Unlock the heap and return the pointer */ 01836 RtlUnlockHeap(BaseHeap); 01837 return RetVal; 01838 } 01839 01840 /* EOF */ Generated on Sat May 26 2012 04:23:00 for ReactOS by
1.7.6.1
|