ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

heapmem.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.