2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/mem/local.c
5 * PURPOSE: Local Memory APIs (sits on top of Heap*)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
16 /* TYPES *********************************************************************/
18 extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo
;
20 /* FUNCTIONS ***************************************************************/
27 LocalAlloc(UINT uFlags
,
33 PBASE_HEAP_HANDLE_ENTRY HandleEntry
;
34 BASE_TRACE_ALLOC(dwBytes
, uFlags
);
37 /* Make sure the flags are valid */
38 if (uFlags
& ~LMEM_VALID_FLAGS
)
40 /* They aren't, fail */
42 SetLastError(ERROR_INVALID_PARAMETER
);
46 /* Convert ZEROINIT */
47 if (uFlags
& LMEM_ZEROINIT
) Flags
|= HEAP_ZERO_MEMORY
;
49 /* Check if we're not movable, which means pointer-based heap */
50 if (!(uFlags
& LMEM_MOVEABLE
))
52 /* Allocate heap for it */
53 Ptr
= RtlAllocateHeap(hProcessHeap
, Flags
, dwBytes
);
54 BASE_TRACE_ALLOC2(Ptr
);
58 /* This is heap based, so lock it in first */
59 RtlLockHeap(hProcessHeap
);
62 * Disable locking, enable custom flags, and write the
63 * movable flag (deprecated)
65 Flags
|= HEAP_NO_SERIALIZE
|
66 HEAP_SETTABLE_USER_VALUE
|
67 BASE_HEAP_FLAG_MOVABLE
;
69 /* Allocate the handle */
70 HandleEntry
= BaseHeapAllocEntry();
75 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
80 /* Get the object and make sure we have size */
81 hMemory
= &HandleEntry
->Object
;
84 /* Allocate the actual memory for it */
85 Ptr
= RtlAllocateHeap(hProcessHeap
, Flags
, dwBytes
);
86 BASE_TRACE_PTR(HandleEntry
, Ptr
);
89 /* We failed, manually set the allocate flag and free the handle */
90 HandleEntry
->Flags
= RTL_HANDLE_VALID
;
91 BaseHeapFreeEntry(HandleEntry
);
93 /* For the cleanup case */
98 /* All worked well, save our heap entry */
99 RtlSetUserValueHeap(hProcessHeap
, HEAP_NO_SERIALIZE
, Ptr
, hMemory
);
104 /* Cleanup! First unlock the heap */
105 RtlUnlockHeap(hProcessHeap
);
107 /* Check if a handle was allocated */
110 /* Set the pointer and allocated flag */
111 HandleEntry
->Object
= Ptr
;
112 HandleEntry
->Flags
= RTL_HANDLE_VALID
;
115 /* We don't have a valid pointer, but so reuse this handle */
116 HandleEntry
->Flags
|= BASE_HEAP_ENTRY_FLAG_REUSE
;
119 /* Check if the handle is discardable */
120 if (uFlags
& GMEM_DISCARDABLE
)
122 /* Save it in the handle entry */
123 HandleEntry
->Flags
|= BASE_HEAP_ENTRY_FLAG_REUSABLE
;
126 /* Check if the handle is moveable */
127 if (uFlags
& GMEM_MOVEABLE
)
129 /* Save it in the handle entry */
130 HandleEntry
->Flags
|= BASE_HEAP_ENTRY_FLAG_MOVABLE
;
133 /* Set the pointer */
137 /* Return the pointer */
146 LocalCompact(UINT dwMinFree
)
148 /* Call the RTL Heap Manager */
149 return RtlCompactHeap(hProcessHeap
, 0);
157 LocalFlags(HLOCAL hMem
)
159 PBASE_HEAP_HANDLE_ENTRY HandleEntry
;
160 HANDLE Handle
= NULL
;
162 UINT uFlags
= LMEM_INVALID_HANDLE
;
164 /* Start by locking the heap */
165 RtlLockHeap(hProcessHeap
);
167 /* Check if this is a simple RTL Heap Managed block */
168 if (!((ULONG_PTR
)hMem
& BASE_HEAP_IS_HANDLE_ENTRY
))
170 /* Then we'll query RTL Heap */
171 RtlGetUserInfoHeap(hProcessHeap
, Flags
, hMem
, &Handle
, &Flags
);
172 BASE_TRACE_PTR(Handle
, hMem
);
175 * Check if RTL Heap didn't find a handle associated with us or
176 * said that this heap isn't movable, which means something we're
177 * really not a handle-based heap.
179 if (!(Handle
) || !(Flags
& BASE_HEAP_FLAG_MOVABLE
))
181 /* Then set the flags to 0 */
186 /* Otherwise we're handle-based, so get the internal handle */
191 /* Check if the handle is actually an entry in our table */
192 if ((ULONG_PTR
)hMem
& BASE_HEAP_IS_HANDLE_ENTRY
)
194 /* Then get the entry */
195 HandleEntry
= BaseHeapGetEntry(hMem
);
196 BASE_TRACE_HANDLE(HandleEntry
, hMem
);
198 /* Make sure it's a valid handle */
199 if (BaseHeapValidateEntry(HandleEntry
))
201 /* Get the lock count first */
202 uFlags
= HandleEntry
->LockCount
& LMEM_LOCKCOUNT
;
204 /* Now check if it's discardable */
205 if (HandleEntry
->Flags
& BASE_HEAP_ENTRY_FLAG_REUSABLE
)
207 /* Set the Win32 Flag */
208 uFlags
|= LMEM_DISCARDABLE
;
211 /* Now check if it's discarded */
212 if (HandleEntry
->Flags
& BASE_HEAP_ENTRY_FLAG_REUSE
)
213 /* Set the Win32 Flag */
214 uFlags
|= LMEM_DISCARDED
;
218 /* Check if by now, we still haven't gotten any useful flags */
219 if (uFlags
== LMEM_INVALID_HANDLE
) SetLastError(ERROR_INVALID_HANDLE
);
221 /* All done! Unlock heap and return Win32 Flags */
222 RtlUnlockHeap(hProcessHeap
);
231 LocalFree(HLOCAL hMem
)
233 /* This is identical to a Global Free */
234 return GlobalFree(hMem
);
242 LocalHandle(LPCVOID pMem
)
244 /* This is identical to a Global Handle */
245 return GlobalHandle(pMem
);
253 LocalLock(HLOCAL hMem
)
255 /* This is the same as a GlobalLock, assuming these never change */
256 C_ASSERT(LMEM_LOCKCOUNT
== GMEM_LOCKCOUNT
);
257 return GlobalLock(hMem
);
262 LocalReAlloc(HLOCAL hMem
,
266 PBASE_HEAP_HANDLE_ENTRY HandleEntry
;
270 /* Convert ZEROINIT */
271 if (uFlags
& LMEM_ZEROINIT
) Flags
|= HEAP_ZERO_MEMORY
;
273 /* If this wasn't a movable heap, then we MUST re-alloc in place */
274 if (!(uFlags
& LMEM_MOVEABLE
)) Flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
276 /* Lock the heap and disable built-in locking in the RTL Heap funcitons */
277 RtlLockHeap(hProcessHeap
);
278 Flags
|= HEAP_NO_SERIALIZE
;
280 /* Check if this is a simple handle-based block */
281 if (((ULONG_PTR
)hMem
& BASE_HEAP_IS_HANDLE_ENTRY
))
284 HandleEntry
= BaseHeapGetEntry(hMem
);
285 BASE_TRACE_HANDLE(HandleEntry
, hMem
);
287 /* Make sure the handle is valid */
288 if (!BaseHeapValidateEntry(HandleEntry
))
291 BASE_TRACE_FAILURE();
292 SetLastError(ERROR_INVALID_HANDLE
);
295 else if (uFlags
& LMEM_MODIFY
)
297 /* User is changing flags... check if the memory was discardable */
298 if (uFlags
& LMEM_DISCARDABLE
)
300 /* Then set the flag */
301 HandleEntry
->Flags
|= BASE_HEAP_ENTRY_FLAG_REUSABLE
;
305 /* Otherwise, remove the flag */
306 HandleEntry
->Flags
&= BASE_HEAP_ENTRY_FLAG_REUSABLE
;
311 /* Otherwise, get the object and check if we have no size */
312 Ptr
= HandleEntry
->Object
;
315 /* Clear the handle and check for a pointer */
319 /* Make sure the handle isn't locked */
320 if ((uFlags
& LMEM_MOVEABLE
) && !(HandleEntry
->LockCount
))
322 /* Free the current heap */
323 RtlFreeHeap(hProcessHeap
, Flags
, Ptr
);
325 /* Free the handle */
326 HandleEntry
->Object
= NULL
;
327 HandleEntry
->Flags
|= BASE_HEAP_ENTRY_FLAG_REUSE
;
329 /* Get the object pointer */
330 hMem
= &HandleEntry
->Object
;
335 /* Otherwise just return the object pointer */
336 hMem
= &HandleEntry
->Object
;
341 /* Otherwise, we're allocating, so set the new flags needed */
342 Flags
|= HEAP_SETTABLE_USER_VALUE
| BASE_HEAP_FLAG_MOVABLE
;
345 /* We don't have a base, so allocate one */
346 Ptr
= RtlAllocateHeap(hProcessHeap
, Flags
, dwBytes
);
347 BASE_TRACE_ALLOC2(Ptr
);
350 /* Allocation succeeded, so save our entry */
351 RtlSetUserValueHeap(hProcessHeap
,
360 * If it's not movable or currently locked, we MUST allocate
363 if (!(uFlags
& LMEM_MOVEABLE
) && (HandleEntry
->LockCount
))
366 Flags
|= HEAP_REALLOC_IN_PLACE_ONLY
;
370 /* Otherwise clear the flag if we set it previously */
371 Flags
&= ~HEAP_REALLOC_IN_PLACE_ONLY
;
374 /* And do the re-allocation */
375 Ptr
= RtlReAllocateHeap(hProcessHeap
, Flags
, Ptr
, dwBytes
);
378 /* Make sure we have a pointer by now */
381 /* Write it in the handle entry and mark it in use */
382 HandleEntry
->Object
= Ptr
;
383 HandleEntry
->Flags
&= ~BASE_HEAP_ENTRY_FLAG_REUSE
;
387 /* Otherwise we failed */
389 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
394 else if (!(uFlags
& LMEM_MODIFY
))
396 /* Otherwise, this is a simple RTL Managed Heap, so just call it */
397 hMem
= RtlReAllocateHeap(hProcessHeap
,
398 Flags
| HEAP_NO_SERIALIZE
,
404 BASE_TRACE_FAILURE();
405 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
409 /* All done, unlock the heap and return the pointer */
410 RtlUnlockHeap(hProcessHeap
);
419 LocalShrink(HLOCAL hMem
,
423 return RtlCompactHeap(hProcessHeap
, 0);
431 LocalSize(HLOCAL hMem
)
433 /* This is the same as a Global Size */
434 return GlobalSize(hMem
);
442 LocalUnlock(HLOCAL hMem
)
444 /* This is the same as a Global Unlock */
445 return GlobalUnlock(hMem
);