kernelbase: Use the same HLOCAL flags / lock layout as native.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2022-04-04 10:02:02 +02:00 committed by Alexandre Julliard
parent 4f596c04be
commit dee510bd32
3 changed files with 53 additions and 50 deletions

View File

@ -147,14 +147,19 @@ BOOL WINAPI HeapDestroy( HANDLE heap /* [in] Handle of heap */ )
* Global/local heap functions, keep in sync with kernelbase/memory.c
***********************************************************************/
#define MEM_FLAG_USED 1
#define MEM_FLAG_MOVEABLE 2
#define MEM_FLAG_DISCARDABLE 4
#define MEM_FLAG_DISCARDED 8
#define MEM_FLAG_DDESHARE 0x8000
struct mem_entry
{
union
{
struct
{
WORD magic;
BYTE flags;
WORD flags;
BYTE lock;
};
void *next_free;
@ -166,7 +171,6 @@ C_ASSERT(sizeof(struct mem_entry) == 2 * sizeof(void *));
struct kernelbase_global_data *kernelbase_global_data;
#define MAGIC_LOCAL_USED 0x5342
#define POINTER_TO_HANDLE( p ) (*(((const HGLOBAL *)( p )) - 2))
/* align the storage needed for the HLOCAL on an 8-byte boundary thus
* LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
@ -181,7 +185,7 @@ static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle )
struct kernelbase_global_data *data = kernelbase_global_data;
if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL;
if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL;
if (mem->magic != MAGIC_LOCAL_USED) return NULL;
if (!(mem->flags & MEM_FLAG_USED)) return NULL;
return mem;
}
@ -431,32 +435,29 @@ VOID WINAPI GlobalUnfix( HGLOBAL handle )
*/
UINT WINAPI GlobalFlags( HGLOBAL handle )
{
HANDLE heap = GetProcessHeap();
struct mem_entry *mem;
DWORD retval;
UINT flags;
TRACE_(globalmem)( "handle %p\n", handle );
if (unsafe_ptr_from_HLOCAL( handle )) return 0;
if (unsafe_ptr_from_HLOCAL( handle ))
RtlLockHeap( heap );
if ((mem = unsafe_mem_from_HLOCAL( handle )))
{
retval = 0;
flags = mem->lock;
if (mem->flags & MEM_FLAG_DISCARDABLE) flags |= GMEM_DISCARDABLE;
if (mem->flags & MEM_FLAG_DISCARDED) flags |= GMEM_DISCARDED;
if (mem->flags & MEM_FLAG_DDESHARE) flags |= GMEM_DDESHARE;
}
else
{
RtlLockHeap( GetProcessHeap() );
if ((mem = unsafe_mem_from_HLOCAL( handle )))
{
retval = mem->lock + (mem->flags << 8);
if (mem->ptr == 0) retval |= GMEM_DISCARDED;
}
else
{
WARN_(globalmem)( "invalid handle %p\n", handle );
SetLastError( ERROR_INVALID_HANDLE );
retval = GMEM_INVALID_HANDLE;
}
RtlUnlockHeap( GetProcessHeap() );
WARN_(globalmem)( "invalid handle %p\n", handle );
SetLastError( ERROR_INVALID_HANDLE );
flags = GMEM_INVALID_HANDLE;
}
return retval;
RtlUnlockHeap( heap );
return flags;
}
@ -491,10 +492,11 @@ SIZE_T WINAPI LocalCompact( UINT minfree )
* Windows memory management does not provide a separate local heap
* and global heap.
*/
UINT WINAPI LocalFlags(
HLOCAL handle /* [in] Handle of memory object */
) {
return GlobalFlags( handle );
UINT WINAPI LocalFlags( HLOCAL handle )
{
UINT flags = GlobalFlags( handle );
if (flags & GMEM_DISCARDABLE) flags |= LMEM_DISCARDABLE;
return flags;
}

View File

@ -334,7 +334,6 @@ static void test_GlobalAlloc(void)
ok( size == 0, "GlobalSize returned %Iu\n", size );
ret = HeapValidate( GetProcessHeap(), 0, entry );
ok( !ret, "HeapValidate succeeded\n" );
todo_wine
ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags );
ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
mem = GlobalFree( mem );
@ -347,7 +346,6 @@ static void test_GlobalAlloc(void)
ok( size == 0, "GlobalSize returned %Iu\n", size );
ret = HeapValidate( GetProcessHeap(), 0, entry );
ok( !ret, "HeapValidate succeeded\n" );
todo_wine
ok( entry->flags == 0xb, "got unexpected flags %#Ix\n", entry->flags );
ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
mem = GlobalFree( mem );
@ -389,14 +387,12 @@ static void test_GlobalAlloc(void)
ok( !((UINT_PTR)ptr & (sizeof(void *) - 1)), "got unexpected ptr align\n" );
for (i = 1; i < 0xff; ++i)
{
todo_wine
ok( entry->flags == ((i<<16)|3), "got unexpected flags %#Ix\n", entry->flags );
ptr = GlobalLock( mem );
ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
}
ptr = GlobalLock( mem );
ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
todo_wine
ok( entry->flags == 0xff0003, "got unexpected flags %#Ix\n", entry->flags );
for (i = 1; i < 0xff; ++i)
{
@ -405,7 +401,6 @@ static void test_GlobalAlloc(void)
}
ret = GlobalUnlock( mem );
ok( !ret, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
todo_wine
ok( entry->flags == 0x3, "got unexpected flags %#Ix\n", entry->flags );
tmp_mem = GlobalFree( mem );
@ -418,7 +413,6 @@ static void test_GlobalAlloc(void)
mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 0 );
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
entry = mem_entry_from_HANDLE( mem );
todo_wine
ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags );
ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
flags = GlobalFlags( mem );
@ -429,7 +423,6 @@ static void test_GlobalAlloc(void)
mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 1 );
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
entry = mem_entry_from_HANDLE( mem );
todo_wine
ok( entry->flags == 0x7, "got unexpected flags %#Ix\n", entry->flags );
ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr );
flags = GlobalFlags( mem );
@ -440,7 +433,6 @@ static void test_GlobalAlloc(void)
mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE | GMEM_DDESHARE, 1 );
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
entry = mem_entry_from_HANDLE( mem );
todo_wine
ok( entry->flags == 0x8007, "got unexpected flags %#Ix\n", entry->flags );
ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr );
flags = GlobalFlags( mem );

View File

@ -585,14 +585,19 @@ struct kernelbase_global_data
struct mem_entry *mem_entries_end;
};
#define MEM_FLAG_USED 1
#define MEM_FLAG_MOVEABLE 2
#define MEM_FLAG_DISCARDABLE 4
#define MEM_FLAG_DISCARDED 8
#define MEM_FLAG_DDESHARE 0x8000
struct mem_entry
{
union
{
struct
{
WORD magic;
BYTE flags;
WORD flags;
BYTE lock;
};
void *next_free;
@ -612,7 +617,6 @@ static struct kernelbase_global_data kernelbase_global_data =
.mem_entries_end = mem_entries + MAX_MEM_HANDLES,
};
#define MAGIC_LOCAL_USED 0x5342
/* align the storage needed for the HLOCAL on an 8-byte boundary thus
* LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with
* size = 8*k, where k=1,2,3,... allocs exactly the given size.
@ -626,12 +630,13 @@ static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle )
struct kernelbase_global_data *data = &kernelbase_global_data;
if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL;
if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL;
if (mem->magic != MAGIC_LOCAL_USED) return NULL;
if (!(mem->flags & MEM_FLAG_USED)) return NULL;
return mem;
}
static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem )
{
if (!mem) return 0;
return &mem->ptr;
}
@ -657,13 +662,18 @@ void *WINAPI KernelBaseGetGlobalData(void)
*/
HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size )
{
/* mask out obsolete flags */
flags &= ~(GMEM_NOCOMPACT | GMEM_NOT_BANKED | GMEM_NOTIFY);
struct mem_entry *mem;
HGLOBAL handle;
/* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */
if (!(flags & GMEM_MOVEABLE) && !size) size = 1;
return LocalAlloc( flags, size );
handle = LocalAlloc( flags, size );
if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & GMEM_DDESHARE))
mem->flags |= MEM_FLAG_DDESHARE;
return handle;
}
@ -712,12 +722,13 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
if (!mem) goto failed;
handle = HLOCAL_from_mem( mem );
mem->magic = MAGIC_LOCAL_USED;
mem->flags = flags >> 8;
mem->flags = MEM_FLAG_USED | MEM_FLAG_MOVEABLE;
if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE;
mem->lock = 0;
mem->ptr = NULL;
if (size)
if (!size) mem->flags |= MEM_FLAG_DISCARDED;
else
{
if (!(ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE ))) goto failed;
*(HLOCAL *)ptr = handle;
@ -798,9 +809,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
RtlLockHeap( heap );
if ((mem = unsafe_mem_from_HLOCAL( handle )))
{
ret = mem->ptr;
if (!mem->ptr) SetLastError( ERROR_DISCARDED );
else if (mem->lock < LMEM_LOCKCOUNT) mem->lock++;
if (!(ret = mem->ptr)) SetLastError( ERROR_DISCARDED );
else if (!++mem->lock) mem->lock--;
}
else
{
@ -935,13 +945,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle )
{
if (mem->lock)
{
mem->lock--;
ret = (mem->lock != 0);
ret = (--mem->lock != 0);
if (!ret) SetLastError( NO_ERROR );
}
else
{
WARN_(globalmem)( "%p not locked\n", handle );
WARN_(globalmem)( "handle %p not locked\n", handle );
SetLastError( ERROR_NOT_LOCKED );
}
}