mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-03 01:33:42 +00:00
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:
parent
4f596c04be
commit
dee510bd32
|
@ -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 ))
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlLockHeap( GetProcessHeap() );
|
||||
RtlLockHeap( heap );
|
||||
if ((mem = unsafe_mem_from_HLOCAL( handle )))
|
||||
{
|
||||
retval = mem->lock + (mem->flags << 8);
|
||||
if (mem->ptr == 0) retval |= GMEM_DISCARDED;
|
||||
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
|
||||
{
|
||||
WARN_(globalmem)( "invalid handle %p\n", handle );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
retval = GMEM_INVALID_HANDLE;
|
||||
flags = GMEM_INVALID_HANDLE;
|
||||
}
|
||||
RtlUnlockHeap( GetProcessHeap() );
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue