- Fixup Local* Heap implementation so that calls which have different semantics don't call the Global APIs (ie: LocalAlloc/LocalReAlloc and LocalFlags). The rest can be shared beteween them. Also fix some prototypes.

- Rename all the defintions to BASE_HEAP instead of GLOBAL_HEAP, since they apply just as well to the Local Heap.

svn path=/trunk/; revision=22582
This commit is contained in:
Alex Ionescu 2006-06-24 19:00:07 +00:00
parent aa75a24d24
commit 8ec0cfcce6
5 changed files with 459 additions and 145 deletions

View file

@ -36,7 +36,7 @@
// //
// The Handle Table // The Handle Table
// //
extern RTL_HANDLE_TABLE BaseGlobalHandleTable; extern RTL_HANDLE_TABLE BaseHeapHandleTable;
// //
// Tracing Support // Tracing Support
@ -62,13 +62,15 @@ extern RTL_HANDLE_TABLE BaseGlobalHandleTable;
#define BASE_TRACE_DEALLOC(x) \ #define BASE_TRACE_DEALLOC(x) \
BH_PRINT("[BASE_HEAP] %s : Freeing %p\n", \ BH_PRINT("[BASE_HEAP] %s : Freeing %p\n", \
__FUNCTION__, x) __FUNCTION__, x)
#define BASE_TRACE_FAILURE() \
BH_PRINT("[BASE_HEAP] %s : Failing %d\n", \
__FUNCTION__, __LINE__)
// //
// The handle structure for global heap handles. // The handle structure for global heap handles.
// Notice that it nicely overlays with RTL_HANDLE_ENTRY. // Notice that it nicely overlays with RTL_HANDLE_ENTRY.
// KEEP IT THAT WAY! ;-) // KEEP IT THAT WAY! ;-)
// //
typedef struct _GLOBAL_HEAP_HANDLE_ENTRY typedef struct _BASE_HEAP_HANDLE_ENTRY
{ {
USHORT Flags; USHORT Flags;
USHORT LockCount; USHORT LockCount;
@ -77,45 +79,45 @@ typedef struct _GLOBAL_HEAP_HANDLE_ENTRY
PVOID Object; PVOID Object;
ULONG OldSize; ULONG OldSize;
}; };
} GLOBAL_HEAP_HANDLE_ENTRY, *PGLOBAL_HEAP_HANDLE_ENTRY; } BASE_HEAP_HANDLE_ENTRY, *PBASE_HEAP_HANDLE_ENTRY;
// //
// Handle entry flags // Handle entry flags
// Note that 0x0001 is the shared/generic RTL_HANDLE_VALID // Note that 0x0001 is the shared/generic RTL_HANDLE_VALID
// //
#define GLOBAL_HEAP_ENTRY_FLAG_MOVABLE 0x0002 #define BASE_HEAP_ENTRY_FLAG_MOVABLE 0x0002
#define GLOBAL_HEAP_ENTRY_FLAG_REUSABLE 0x0004 #define BASE_HEAP_ENTRY_FLAG_REUSABLE 0x0004
#define GLOBAL_HEAP_ENTRY_FLAG_REUSE 0x0008 #define BASE_HEAP_ENTRY_FLAG_REUSE 0x0008
#define GLOBAL_HEAP_ENTRY_FLAG_DDESHARE 0x0010 #define BASE_HEAP_ENTRY_FLAG_DDESHARE 0x0010
// //
// Easy way to check if the global handle is actually an entry in our table // Easy way to check if the global handle is actually an entry in our table
// //
#define GLOBAL_HEAP_IS_HANDLE_ENTRY \ #define BASE_HEAP_IS_HANDLE_ENTRY \
(ULONG_PTR)FIELD_OFFSET(GLOBAL_HEAP_HANDLE_ENTRY, Object) (ULONG_PTR)FIELD_OFFSET(BASE_HEAP_HANDLE_ENTRY, Object)
// //
// Tags for the entire heap allocation for this global memory. // Tags for the entire heap allocation for this global memory.
// They are set part of the User Flags of the RTL Heap. // They are set part of the User Flags of the RTL Heap.
// //
#define GLOBAL_HEAP_FLAG_MOVABLE HEAP_SETTABLE_USER_FLAG1 #define BASE_HEAP_FLAG_MOVABLE HEAP_SETTABLE_USER_FLAG1
#define GLOBAL_HEAP_FLAG_DDESHARE HEAP_SETTABLE_USER_FLAG2 #define BASE_HEAP_FLAG_DDESHARE HEAP_SETTABLE_USER_FLAG2
// //
// Internal Handle Functions // Internal Handle Functions
// //
#define GlobalAllocEntry() \ #define BaseHeapAllocEntry() \
(PGLOBAL_HEAP_HANDLE_ENTRY)RtlAllocateHandle(&BaseGlobalHandleTable, NULL) (PBASE_HEAP_HANDLE_ENTRY)RtlAllocateHandle(&BaseHeapHandleTable, NULL)
#define GlobalGetEntry(h) \ #define BaseHeapGetEntry(h) \
(PGLOBAL_HEAP_HANDLE_ENTRY) \ (PBASE_HEAP_HANDLE_ENTRY) \
CONTAINING_RECORD(h, \ CONTAINING_RECORD(h, \
GLOBAL_HEAP_HANDLE_ENTRY, \ BASE_HEAP_HANDLE_ENTRY, \
Object); Object);
#define GlobalValidateEntry(he) \ #define BaseHeapValidateEntry(he) \
RtlIsValidHandle(&BaseGlobalHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he) RtlIsValidHandle(&BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he)
#define GlobalFreeEntry(he) \ #define BaseHeapFreeEntry(he) \
RtlFreeHandle(&BaseGlobalHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he); RtlFreeHandle(&BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)he);

View file

@ -13,14 +13,10 @@
#define NDEBUG #define NDEBUG
#include "debug.h" #include "debug.h"
#define BASE_TRACE_FAILURE() \
DbgPrint("[BASE_HEAP] %s : Failing %d\n", \
__FUNCTION__, __LINE__)
/* TYPES *********************************************************************/ /* TYPES *********************************************************************/
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
RTL_HANDLE_TABLE BaseGlobalHandleTable; RTL_HANDLE_TABLE BaseHeapHandleTable;
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
@ -35,7 +31,7 @@ GlobalAlloc(UINT uFlags,
ULONG Flags = 0; ULONG Flags = 0;
PVOID Ptr = NULL; PVOID Ptr = NULL;
HANDLE hMemory; HANDLE hMemory;
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
BASE_TRACE_ALLOC(dwBytes, uFlags); BASE_TRACE_ALLOC(dwBytes, uFlags);
ASSERT(hProcessHeap); ASSERT(hProcessHeap);
@ -55,7 +51,7 @@ GlobalAlloc(UINT uFlags,
if (!(uFlags & GMEM_MOVEABLE)) if (!(uFlags & GMEM_MOVEABLE))
{ {
/* Check if this is DDESHARE (deprecated) */ /* Check if this is DDESHARE (deprecated) */
if (uFlags & GMEM_DDESHARE) Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE; if (uFlags & GMEM_DDESHARE) Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
/* Allocate heap for it */ /* Allocate heap for it */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
@ -72,10 +68,10 @@ GlobalAlloc(UINT uFlags,
*/ */
Flags |= HEAP_NO_SERIALIZE | Flags |= HEAP_NO_SERIALIZE |
HEAP_SETTABLE_USER_VALUE | HEAP_SETTABLE_USER_VALUE |
GLOBAL_HEAP_FLAG_MOVABLE; BASE_HEAP_FLAG_MOVABLE;
/* Allocate the handle */ /* Allocate the handle */
HandleEntry = GlobalAllocEntry(); HandleEntry = BaseHeapAllocEntry();
if (!HandleEntry) if (!HandleEntry)
{ {
/* Fail */ /* Fail */
@ -96,7 +92,7 @@ GlobalAlloc(UINT uFlags,
{ {
/* We failed, manually set the allocate flag and free the handle */ /* We failed, manually set the allocate flag and free the handle */
HandleEntry->Flags = RTL_HANDLE_VALID; HandleEntry->Flags = RTL_HANDLE_VALID;
GlobalFreeEntry(HandleEntry); BaseHeapFreeEntry(HandleEntry);
/* For the cleanup case */ /* For the cleanup case */
HandleEntry = NULL; HandleEntry = NULL;
@ -121,28 +117,28 @@ Quickie:
if (!Ptr) if (!Ptr)
{ {
/* We don't have a valid pointer, but so reuse this handle */ /* We don't have a valid pointer, but so reuse this handle */
HandleEntry->Flags = GLOBAL_HEAP_ENTRY_FLAG_REUSE; HandleEntry->Flags = BASE_HEAP_ENTRY_FLAG_REUSE;
} }
/* Check if the handle is discardable */ /* Check if the handle is discardable */
if (uFlags & GMEM_DISCARDABLE) if (uFlags & GMEM_DISCARDABLE)
{ {
/* Save it in the handle entry */ /* Save it in the handle entry */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
} }
/* Check if the handle is moveable */ /* Check if the handle is moveable */
if (uFlags & GMEM_MOVEABLE) if (uFlags & GMEM_MOVEABLE)
{ {
/* Save it in the handle entry */ /* Save it in the handle entry */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_MOVABLE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE;
} }
/* Check if the handle is DDE Shared */ /* Check if the handle is DDE Shared */
if (uFlags & GMEM_DDESHARE) if (uFlags & GMEM_DDESHARE)
{ {
/* Save it in the handle entry */ /* Save it in the handle entry */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
} }
/* Set the pointer */ /* Set the pointer */
@ -182,7 +178,7 @@ UINT
NTAPI NTAPI
GlobalFlags(HGLOBAL hMem) GlobalFlags(HGLOBAL hMem)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
HANDLE Handle = NULL; HANDLE Handle = NULL;
ULONG Flags = 0; ULONG Flags = 0;
UINT uFlags = GMEM_INVALID_HANDLE; UINT uFlags = GMEM_INVALID_HANDLE;
@ -191,7 +187,7 @@ GlobalFlags(HGLOBAL hMem)
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
/* Check if this is a simple RTL Heap Managed block */ /* Check if this is a simple RTL Heap Managed block */
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{ {
/* Then we'll query RTL Heap */ /* Then we'll query RTL Heap */
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags); RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
@ -202,7 +198,7 @@ GlobalFlags(HGLOBAL hMem)
* said that this heap isn't movable, which means something we're * said that this heap isn't movable, which means something we're
* really not a handle-based heap. * really not a handle-based heap.
*/ */
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE)) if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{ {
/* Then set the flags to 0 */ /* Then set the flags to 0 */
uFlags = 0; uFlags = 0;
@ -215,34 +211,34 @@ GlobalFlags(HGLOBAL hMem)
} }
/* Check if the handle is actually an entry in our table */ /* Check if the handle is actually an entry in our table */
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY) if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{ {
/* Then get the entry */ /* Then get the entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's a valid handle */ /* Make sure it's a valid handle */
if (GlobalValidateEntry(HandleEntry)) if (BaseHeapValidateEntry(HandleEntry))
{ {
/* Get the lock count first */ /* Get the lock count first */
uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT; uFlags = HandleEntry->LockCount & GMEM_LOCKCOUNT;
/* Now check if it's discarded */ /* Now check if it's discarded */
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_REUSABLE) if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
{ {
/* Set the Win32 Flag */ /* Set the Win32 Flag */
uFlags |= GMEM_DISCARDED; uFlags |= GMEM_DISCARDED;
} }
/* Check if it's movable */ /* Check if it's movable */
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_MOVABLE) if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
{ {
/* Set the Win32 Flag */ /* Set the Win32 Flag */
uFlags |= GMEM_MOVEABLE; uFlags |= GMEM_MOVEABLE;
} }
/* Check if it's DDE Shared */ /* Check if it's DDE Shared */
if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_DDESHARE) if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_DDESHARE)
{ {
/* Set the Win32 Flag */ /* Set the Win32 Flag */
uFlags |= GMEM_DDESHARE; uFlags |= GMEM_DDESHARE;
@ -265,12 +261,12 @@ HGLOBAL
NTAPI NTAPI
GlobalFree(HGLOBAL hMem) GlobalFree(HGLOBAL hMem)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
LPVOID Ptr; LPVOID Ptr;
BASE_TRACE_DEALLOC(hMem); BASE_TRACE_DEALLOC(hMem);
/* Check if this was a simple allocated heap entry */ /* Check if this was a simple allocated heap entry */
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{ {
/* Free it with the RTL Heap Manager */ /* Free it with the RTL Heap Manager */
if (RtlFreeHeap(hProcessHeap, 0, hMem)) if (RtlFreeHeap(hProcessHeap, 0, hMem))
@ -291,14 +287,14 @@ GlobalFree(HGLOBAL hMem)
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
/* Make sure that this is an entry in our handle database */ /* Make sure that this is an entry in our handle database */
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY) if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{ {
/* Get the entry */ /* Get the entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */ /* Make sure the handle is valid */
if (!GlobalValidateEntry(HandleEntry)) if (!BaseHeapValidateEntry(HandleEntry))
{ {
/* It's not, fail */ /* It's not, fail */
SetLastError(ERROR_INVALID_HANDLE); SetLastError(ERROR_INVALID_HANDLE);
@ -310,7 +306,7 @@ GlobalFree(HGLOBAL hMem)
Ptr = HandleEntry->Object; Ptr = HandleEntry->Object;
/* Free this handle */ /* Free this handle */
GlobalFreeEntry(HandleEntry); BaseHeapFreeEntry(HandleEntry);
/* If the pointer is 0, then we don't have a handle either */ /* If the pointer is 0, then we don't have a handle either */
if (!Ptr) hMem = NULL; if (!Ptr) hMem = NULL;
@ -361,7 +357,7 @@ GlobalHandle(LPCVOID pMem)
* Check if RTL Heap didn't find a handle for us or said that * Check if RTL Heap didn't find a handle for us or said that
* this heap isn't movable. * this heap isn't movable.
*/ */
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE)) if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{ {
/* We're actually handle-based, so the pointer is a handle */ /* We're actually handle-based, so the pointer is a handle */
Handle = (HANDLE)pMem; Handle = (HANDLE)pMem;
@ -379,11 +375,11 @@ LPVOID
NTAPI NTAPI
GlobalLock(HGLOBAL hMem) GlobalLock(HGLOBAL hMem)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
LPVOID Ptr; LPVOID Ptr;
/* Check if this was a simple allocated heap entry */ /* Check if this was a simple allocated heap entry */
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{ {
/* Then simply return the pointer */ /* Then simply return the pointer */
return hMem; return hMem;
@ -393,11 +389,11 @@ GlobalLock(HGLOBAL hMem)
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
/* Get the handle entry */ /* Get the handle entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's valid */ /* Make sure it's valid */
if (!GlobalValidateEntry(HandleEntry)) if (!BaseHeapValidateEntry(HandleEntry))
{ {
/* It's not, fail */ /* It's not, fail */
BASE_TRACE_FAILURE(); BASE_TRACE_FAILURE();
@ -435,7 +431,7 @@ GlobalReAlloc(HGLOBAL hMem,
DWORD dwBytes, DWORD dwBytes,
UINT uFlags) UINT uFlags)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
HANDLE Handle; HANDLE Handle;
LPVOID Ptr; LPVOID Ptr;
ULONG Flags = 0; ULONG Flags = 0;
@ -449,17 +445,16 @@ GlobalReAlloc(HGLOBAL hMem,
/* Lock the heap and disable built-in locking in the RTL Heap funcitons */ /* Lock the heap and disable built-in locking in the RTL Heap funcitons */
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
Flags |= HEAP_NO_SERIALIZE; Flags |= HEAP_NO_SERIALIZE;
DPRINT1("hmem: %p Flags: %lx\n", hMem, uFlags);
/* Check if this is a simple handle-based block */ /* Check if this is a simple handle-based block */
if (((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{ {
/* Get the entry */ /* Get the entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */ /* Make sure the handle is valid */
if (!GlobalValidateEntry(HandleEntry)) if (!BaseHeapValidateEntry(HandleEntry))
{ {
/* Fail */ /* Fail */
BASE_TRACE_FAILURE(); BASE_TRACE_FAILURE();
@ -472,12 +467,12 @@ GlobalReAlloc(HGLOBAL hMem,
if (uFlags & GMEM_DISCARDABLE) if (uFlags & GMEM_DISCARDABLE)
{ {
/* Then set the flag */ /* Then set the flag */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
} }
else else
{ {
/* Otherwise, remove the flag */ /* Otherwise, remove the flag */
HandleEntry->Flags &= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE; HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE;
} }
} }
else else
@ -498,7 +493,7 @@ GlobalReAlloc(HGLOBAL hMem,
/* Free the handle */ /* Free the handle */
HandleEntry->Object = NULL; HandleEntry->Object = NULL;
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
/* Get the object pointer */ /* Get the object pointer */
hMem = &HandleEntry->Object; hMem = &HandleEntry->Object;
@ -513,7 +508,7 @@ GlobalReAlloc(HGLOBAL hMem,
else else
{ {
/* Otherwise, we're allocating, so set the new flags needed */ /* Otherwise, we're allocating, so set the new flags needed */
Flags |= HEAP_SETTABLE_USER_VALUE | GLOBAL_HEAP_FLAG_MOVABLE; Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
if (!Ptr) if (!Ptr)
{ {
/* We don't have a base, so allocate one */ /* We don't have a base, so allocate one */
@ -554,7 +549,7 @@ GlobalReAlloc(HGLOBAL hMem,
{ {
/* Write it in the handle entry and mark it in use */ /* Write it in the handle entry and mark it in use */
HandleEntry->Object = Ptr; HandleEntry->Object = Ptr;
HandleEntry->Flags &= ~GLOBAL_HEAP_ENTRY_FLAG_REUSE; HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE;
} }
else else
{ {
@ -584,16 +579,16 @@ GlobalReAlloc(HGLOBAL hMem,
* Check if the handle matches the pointer or if the moveable flag * Check if the handle matches the pointer or if the moveable flag
* isn't there, which is what we expect since it currenly isn't. * isn't there, which is what we expect since it currenly isn't.
*/ */
if (Handle == hMem || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE)) if (Handle == hMem || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{ {
/* Allocate a handle for it */ /* Allocate a handle for it */
HandleEntry = GlobalAllocEntry(); HandleEntry = BaseHeapAllocEntry();
/* Calculate the size of the current heap */ /* Calculate the size of the current heap */
dwBytes = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem); dwBytes = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
/* Set the movable flag */ /* Set the movable flag */
Flags |= HEAP_SETTABLE_USER_VALUE | GLOBAL_HEAP_FLAG_MOVABLE; Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
/* Now allocate the actual heap for it */ /* Now allocate the actual heap for it */
HandleEntry->Object = RtlAllocateHeap(hProcessHeap, HandleEntry->Object = RtlAllocateHeap(hProcessHeap,
@ -607,7 +602,7 @@ GlobalReAlloc(HGLOBAL hMem,
* free the handle * free the handle
*/ */
HandleEntry->Flags = RTL_HANDLE_VALID; HandleEntry->Flags = RTL_HANDLE_VALID;
GlobalFreeEntry(HandleEntry); BaseHeapFreeEntry(HandleEntry);
/* For the cleanup case */ /* For the cleanup case */
BASE_TRACE_FAILURE(); BASE_TRACE_FAILURE();
@ -626,20 +621,20 @@ GlobalReAlloc(HGLOBAL hMem,
/* Initialize the count and default flags */ /* Initialize the count and default flags */
HandleEntry->LockCount = 0; HandleEntry->LockCount = 0;
HandleEntry->Flags = RTL_HANDLE_VALID | HandleEntry->Flags = RTL_HANDLE_VALID |
GLOBAL_HEAP_ENTRY_FLAG_MOVABLE; BASE_HEAP_ENTRY_FLAG_MOVABLE;
/* Check if it's also discardable */ /* Check if it's also discardable */
if (uFlags & GMEM_DISCARDABLE) if (uFlags & GMEM_DISCARDABLE)
{ {
/* Set the internal flag */ /* Set the internal flag */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_REUSABLE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
} }
/* Check if it's also DDE Shared */ /* Check if it's also DDE Shared */
if (uFlags & GMEM_DDESHARE) if (uFlags & GMEM_DDESHARE)
{ {
/* Set the internal flag */ /* Set the internal flag */
HandleEntry->Flags |= GLOBAL_HEAP_ENTRY_FLAG_DDESHARE; HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_DDESHARE;
} }
/* Allocation succeeded, so save our entry */ /* Allocation succeeded, so save our entry */
@ -678,7 +673,7 @@ DWORD
NTAPI NTAPI
GlobalSize(HGLOBAL hMem) GlobalSize(HGLOBAL hMem)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
PVOID Handle = NULL; PVOID Handle = NULL;
ULONG Flags = 0; ULONG Flags = 0;
SIZE_T dwSize = MAXULONG_PTR; SIZE_T dwSize = MAXULONG_PTR;
@ -687,7 +682,7 @@ GlobalSize(HGLOBAL hMem)
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
/* Check if this is a simple RTL Heap Managed block */ /* Check if this is a simple RTL Heap Managed block */
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{ {
/* Then we'll query RTL Heap */ /* Then we'll query RTL Heap */
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags); RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
@ -697,7 +692,7 @@ GlobalSize(HGLOBAL hMem)
* Check if RTL Heap didn't give us a handle or said that this heap * Check if RTL Heap didn't give us a handle or said that this heap
* isn't movable. * isn't movable.
*/ */
if (!(Handle) || !(Flags & GLOBAL_HEAP_FLAG_MOVABLE)) if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{ {
/* This implies we're not a handle heap, so use the generic call */ /* This implies we're not a handle heap, so use the generic call */
dwSize = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem); dwSize = RtlSizeHeap(hProcessHeap, HEAP_NO_SERIALIZE, hMem);
@ -710,20 +705,20 @@ GlobalSize(HGLOBAL hMem)
} }
/* Make sure that this is an entry in our handle database */ /* Make sure that this is an entry in our handle database */
if ((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY) if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{ {
/* Get the entry */ /* Get the entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */ /* Make sure the handle is valid */
if (!GlobalValidateEntry(HandleEntry)) if (!BaseHeapValidateEntry(HandleEntry))
{ {
/* Fail */ /* Fail */
BASE_TRACE_FAILURE(); BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_HANDLE); SetLastError(ERROR_INVALID_HANDLE);
} }
else if (HandleEntry->Flags & GLOBAL_HEAP_ENTRY_FLAG_REUSE) else if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE)
{ {
/* We've reused this block, but we've saved the size for you */ /* We've reused this block, but we've saved the size for you */
dwSize = HandleEntry->OldSize; dwSize = HandleEntry->OldSize;
@ -769,21 +764,21 @@ BOOL
NTAPI NTAPI
GlobalUnlock(HGLOBAL hMem) GlobalUnlock(HGLOBAL hMem)
{ {
PGLOBAL_HEAP_HANDLE_ENTRY HandleEntry; PBASE_HEAP_HANDLE_ENTRY HandleEntry;
BOOL RetVal = TRUE; BOOL RetVal = TRUE;
/* Check if this was a simple allocated heap entry */ /* Check if this was a simple allocated heap entry */
if (!((ULONG_PTR)hMem & GLOBAL_HEAP_IS_HANDLE_ENTRY)) return RetVal; if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) return RetVal;
/* Otherwise, lock the heap */ /* Otherwise, lock the heap */
RtlLockHeap(hProcessHeap); RtlLockHeap(hProcessHeap);
/* Get the handle entry */ /* Get the handle entry */
HandleEntry = GlobalGetEntry(hMem); HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem); BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's valid */ /* Make sure it's valid */
if (!GlobalValidateEntry(HandleEntry)) if (!BaseHeapValidateEntry(HandleEntry))
{ {
/* It's not, fail */ /* It's not, fail */
BASE_TRACE_FAILURE(); BASE_TRACE_FAILURE();

View file

@ -1,134 +1,450 @@
/* $Id$ /*
* * PROJECT: ReactOS Win32 Base API
* COPYRIGHT: See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* Copyright (C) 1996, Onno Hovers, All rights reserved * FILE: dll/win32/kernel32/mem/local.c
* PROJECT: ReactOS system libraries * PURPOSE: Local Memory APIs (sits on top of Heap*)
* FILE: lib/kernel32/mem/local.c * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PURPOSE: Manages the local heap
* PROGRAMER: Onno Hovers (original wfc version)
* David Welch (adapted for ReactOS)
* UPDATE HISTORY:
* 9/4/98: Adapted from the wfc project
*/ */
/* INCLUDES ******************************************************************/
/* NOTES
*
* The local heap is the same as the global heap for win32 and both are only
* required for legacy apps
*
*/
/* INCLUDES ****************************************************************/
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include "../include/debug.h" #include "debug.h"
/* TYPES *********************************************************************/
extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo;
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
/* /*
* @implemented * @implemented
*/ */
HLOCAL STDCALL HLOCAL
NTAPI
LocalAlloc(UINT uFlags, LocalAlloc(UINT uFlags,
SIZE_T uBytes) SIZE_T dwBytes)
{ {
return (HLOCAL)GlobalAlloc(uFlags, uBytes); ULONG Flags = 0;
PVOID Ptr = NULL;
HANDLE hMemory;
PBASE_HEAP_HANDLE_ENTRY HandleEntry;
BASE_TRACE_ALLOC(dwBytes, uFlags);
ASSERT(hProcessHeap);
/* Make sure the flags are valid */
if (uFlags & ~LMEM_VALID_FLAGS)
{
/* They aren't, fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
} }
/* Convert ZEROINIT */
if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
/* Check if we're not movable, which means pointer-based heap */
if (!(uFlags & LMEM_MOVEABLE))
{
/* Allocate heap for it */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
BASE_TRACE_ALLOC2(Ptr);
return Ptr;
}
/* This is heap based, so lock it in first */
RtlLockHeap(hProcessHeap);
/*
* Disable locking, enable custom flags, and write the
* movable flag (deprecated)
*/
Flags |= HEAP_NO_SERIALIZE |
HEAP_SETTABLE_USER_VALUE |
BASE_HEAP_FLAG_MOVABLE;
/* Allocate the handle */
HandleEntry = BaseHeapAllocEntry();
if (!HandleEntry)
{
/* Fail */
hMemory = NULL;
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
BASE_TRACE_FAILURE();
goto Quickie;
}
/* Get the object and make sure we have size */
hMemory = &HandleEntry->Object;
if (dwBytes)
{
/* Allocate the actual memory for it */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
BASE_TRACE_PTR(HandleEntry, Ptr);
if (!Ptr)
{
/* We failed, manually set the allocate flag and free the handle */
HandleEntry->Flags = RTL_HANDLE_VALID;
BaseHeapFreeEntry(HandleEntry);
/* For the cleanup case */
HandleEntry = NULL;
}
else
{
/* All worked well, save our heap entry */
RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory);
}
}
Quickie:
/* Cleanup! First unlock the heap */
RtlUnlockHeap(hProcessHeap);
/* Check if a handle was allocated */
if (HandleEntry)
{
/* Set the pointer and allocated flag */
HandleEntry->Object = Ptr;
HandleEntry->Flags = RTL_HANDLE_VALID;
if (!Ptr)
{
/* We don't have a valid pointer, but so reuse this handle */
HandleEntry->Flags = BASE_HEAP_ENTRY_FLAG_REUSE;
}
/* Check if the handle is discardable */
if (uFlags & GMEM_DISCARDABLE)
{
/* Save it in the handle entry */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
}
/* Check if the handle is moveable */
if (uFlags & GMEM_MOVEABLE)
{
/* Save it in the handle entry */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE;
}
/* Set the pointer */
Ptr = hMemory;
}
/* Return the pointer */
return Ptr;
}
/* /*
* @implemented * @implemented
*/ */
SIZE_T STDCALL SIZE_T
LocalCompact(UINT uMinFree) NTAPI
LocalCompact(UINT dwMinFree)
{ {
/* Call the RTL Heap Manager */
return RtlCompactHeap(hProcessHeap, 0); return RtlCompactHeap(hProcessHeap, 0);
} }
/* /*
* @implemented * @implemented
*/ */
UINT STDCALL UINT
NTAPI
LocalFlags(HLOCAL hMem) LocalFlags(HLOCAL hMem)
{ {
return GlobalFlags((HGLOBAL)hMem); PBASE_HEAP_HANDLE_ENTRY HandleEntry;
HANDLE Handle = NULL;
ULONG Flags = 0;
UINT uFlags = LMEM_INVALID_HANDLE;
/* Start by locking the heap */
RtlLockHeap(hProcessHeap);
/* Check if this is a simple RTL Heap Managed block */
if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Then we'll query RTL Heap */
RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags);
BASE_TRACE_PTR(Handle, hMem);
/*
* Check if RTL Heap didn't find a handle associated with us or
* said that this heap isn't movable, which means something we're
* really not a handle-based heap.
*/
if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE))
{
/* Then set the flags to 0 */
uFlags = 0;
}
else
{
/* Otherwise we're handle-based, so get the internal handle */
hMem = Handle;
}
} }
/* Check if the handle is actually an entry in our table */
if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)
{
/* Then get the entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure it's a valid handle */
if (BaseHeapValidateEntry(HandleEntry))
{
/* Get the lock count first */
uFlags = HandleEntry->LockCount & LMEM_LOCKCOUNT;
/* Now check if it's discarded */
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE)
{
/* Set the Win32 Flag */
uFlags |= LMEM_DISCARDED;
}
/* Check if it's movable */
if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_MOVABLE)
{
/* Set the Win32 Flag */
uFlags |= LMEM_DISCARDABLE;
}
}
}
/* Check if by now, we still haven't gotten any useful flags */
if (uFlags == LMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE);
/* All done! Unlock heap and return Win32 Flags */
RtlUnlockHeap(hProcessHeap);
return uFlags;
}
/* /*
* @implemented * @implemented
*/ */
HLOCAL STDCALL HLOCAL
NTAPI
LocalFree(HLOCAL hMem) LocalFree(HLOCAL hMem)
{ {
return (HLOCAL)GlobalFree((HGLOBAL)hMem); /* This is identical to a Global Free */
return GlobalFree(hMem);
} }
/* /*
* @implemented * @implemented
*/ */
HLOCAL STDCALL HLOCAL
NTAPI
LocalHandle(LPCVOID pMem) LocalHandle(LPCVOID pMem)
{ {
return (HLOCAL)GlobalHandle(pMem); /* This is identical to a Global Handle */
return GlobalHandle(pMem);
} }
/* /*
* @implemented * @implemented
*/ */
LPVOID STDCALL LPVOID
NTAPI
LocalLock(HLOCAL hMem) LocalLock(HLOCAL hMem)
{ {
return GlobalLock((HGLOBAL)hMem); /* This is the same as a GlobalLock, assuming these never change */
ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT);
return GlobalLock(hMem);
} }
HLOCAL
/* NTAPI
* @implemented
*/
HLOCAL STDCALL
LocalReAlloc(HLOCAL hMem, LocalReAlloc(HLOCAL hMem,
SIZE_T uBytes, SIZE_T dwBytes,
UINT uFlags) UINT uFlags)
{ {
return (HLOCAL)GlobalReAlloc((HGLOBAL)hMem, uBytes, uFlags); PBASE_HEAP_HANDLE_ENTRY HandleEntry;
LPVOID Ptr;
ULONG Flags = 0;
/* Convert ZEROINIT */
if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY;
/* If this wasn't a movable heap, then we MUST re-alloc in place */
if (!(uFlags & LMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
/* Lock the heap and disable built-in locking in the RTL Heap funcitons */
RtlLockHeap(hProcessHeap);
Flags |= HEAP_NO_SERIALIZE;
/* Check if this is a simple handle-based block */
if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY))
{
/* Get the entry */
HandleEntry = BaseHeapGetEntry(hMem);
BASE_TRACE_HANDLE(HandleEntry, hMem);
/* Make sure the handle is valid */
if (!BaseHeapValidateEntry(HandleEntry))
{
/* Fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_INVALID_HANDLE);
hMem = NULL;
}
else if (uFlags & LMEM_MODIFY)
{
/* User is changing flags... check if the memory was discardable */
if (uFlags & LMEM_DISCARDABLE)
{
/* Then set the flag */
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE;
}
else
{
/* Otherwise, remove the flag */
HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE;
}
}
else
{
/* Otherwise, get the object and check if we have no size */
Ptr = HandleEntry->Object;
if (!dwBytes)
{
/* Clear the handle and check for a pointer */
hMem = NULL;
if (Ptr)
{
/* Make sure the handle isn't locked */
if ((uFlags & LMEM_MOVEABLE) & !(HandleEntry->LockCount))
{
/* Free the current heap */
RtlFreeHeap(hProcessHeap, Flags, Ptr);
/* Free the handle */
HandleEntry->Object = NULL;
HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE;
/* Get the object pointer */
hMem = &HandleEntry->Object;
}
}
else
{
/* Otherwise just return the object pointer */
hMem = &HandleEntry->Object;
}
}
else
{
/* Otherwise, we're allocating, so set the new flags needed */
Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE;
if (!Ptr)
{
/* We don't have a base, so allocate one */
Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes);
BASE_TRACE_ALLOC2(Ptr);
if (Ptr)
{
/* Allocation succeeded, so save our entry */
RtlSetUserValueHeap(hProcessHeap,
HEAP_NO_SERIALIZE,
Ptr,
hMem);
}
}
else
{
/*
* If it's not movable or currently locked, we MUST allocate
* in-place!
*/
if (!(uFlags & LMEM_MOVEABLE) && (HandleEntry->LockCount))
{
/* Set the flag */
Flags |= HEAP_REALLOC_IN_PLACE_ONLY;
}
else
{
/* Otherwise clear the flag if we set it previously */
Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;
} }
/* And do the re-allocation */
Ptr = RtlReAllocateHeap(hProcessHeap, Flags, Ptr, dwBytes);
}
/* Make sure we have a pointer by now */
if (Ptr)
{
/* Write it in the handle entry and mark it in use */
HandleEntry->Object = Ptr;
HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE;
}
else
{
/* Otherwise we failed */
hMem = NULL;
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
}
}
}
else if (!(uFlags & LMEM_MODIFY))
{
/* Otherwise, this is a simple RTL Managed Heap, so just call it */
hMem = RtlReAllocateHeap(hProcessHeap,
Flags | HEAP_NO_SERIALIZE,
hMem,
dwBytes);
if (!hMem)
{
/* Fail */
BASE_TRACE_FAILURE();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
}
/* All done, unlock the heap and return the pointer */
RtlUnlockHeap(hProcessHeap);
return hMem;
}
/* /*
* @implemented * @implemented
*/ */
SIZE_T STDCALL SIZE_T
LocalShrink(HLOCAL hMem, UINT cbNewSize) STDCALL
LocalShrink(HLOCAL hMem,
UINT cbNewSize)
{ {
/* Call RTL */
return RtlCompactHeap(hProcessHeap, 0); return RtlCompactHeap(hProcessHeap, 0);
} }
/* /*
* @implemented * @implemented
*/ */
UINT STDCALL SIZE_T
NTAPI
LocalSize(HLOCAL hMem) LocalSize(HLOCAL hMem)
{ {
return GlobalSize((HGLOBAL)hMem); /* This is the same as a Global Size */
return GlobalSize(hMem);
} }
/* /*
* @implemented * @implemented
*/ */
BOOL STDCALL BOOL
NTAPI
LocalUnlock(HLOCAL hMem) LocalUnlock(HLOCAL hMem)
{ {
return GlobalUnlock((HGLOBAL)hMem); /* This is the same as a Global Unlock */
return GlobalUnlock(hMem);
} }
/* EOF */ /* EOF */

View file

@ -340,8 +340,8 @@ DllMain(HANDLE hDll,
hProcessHeap = RtlGetProcessHeap(); hProcessHeap = RtlGetProcessHeap();
RtlInitializeHandleTable(0xFFFF, RtlInitializeHandleTable(0xFFFF,
sizeof(GLOBAL_HEAP_HANDLE_ENTRY), sizeof(BASE_HEAP_HANDLE_ENTRY),
&BaseGlobalHandleTable); &BaseHeapHandleTable);
hCurrentModule = hDll; hCurrentModule = hDll;
DPRINT("Heap: %p\n", hProcessHeap); DPRINT("Heap: %p\n", hProcessHeap);

View file

@ -327,6 +327,7 @@ extern "C" {
#define LMEM_MODIFY 128 #define LMEM_MODIFY 128
#define LMEM_INVALID_HANDLE 32768 #define LMEM_INVALID_HANDLE 32768
#define LMEM_LOCKCOUNT 255 #define LMEM_LOCKCOUNT 255
#define LMEM_VALID_FLAGS 0x0F72
#define LPTR 64 #define LPTR 64
#define LHND 66 #define LHND 66
#define NONZEROLHND 2 #define NONZEROLHND 2
@ -1698,7 +1699,7 @@ HLOCAL WINAPI LocalHandle(LPCVOID);
PVOID WINAPI LocalLock(HLOCAL); PVOID WINAPI LocalLock(HLOCAL);
HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT); HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT);
SIZE_T WINAPI LocalShrink(HLOCAL,UINT); /* Obsolete: Has no effect. */ SIZE_T WINAPI LocalShrink(HLOCAL,UINT); /* Obsolete: Has no effect. */
UINT WINAPI LocalSize(HLOCAL); SIZE_T WINAPI LocalSize(HLOCAL);
BOOL WINAPI LocalUnlock(HLOCAL); BOOL WINAPI LocalUnlock(HLOCAL);
BOOL WINAPI LockFile(HANDLE,DWORD,DWORD,DWORD,DWORD); BOOL WINAPI LockFile(HANDLE,DWORD,DWORD,DWORD,DWORD);
BOOL WINAPI LockFileEx(HANDLE,DWORD,DWORD,DWORD,DWORD,LPOVERLAPPED); BOOL WINAPI LockFileEx(HANDLE,DWORD,DWORD,DWORD,DWORD,LPOVERLAPPED);