From 05de74702aa511e67c0a8066522f04b566ae4844 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Wed, 9 Feb 2011 20:42:44 +0000 Subject: [PATCH] - Robert Horvath: LocalUnlock has to be different from GlobalUnlock. The subtle difference between LocalUnlock and GlobalUnlock, is, that the former will return FALSE and set ERROR_NOT_LOCKED on LMEM_FIXED allocations. Fixes 1 kernel32:heap failure. See issue #5869 for more details. svn path=/trunk/; revision=50637 --- reactos/dll/win32/kernel32/mem/local.c | 58 +++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/reactos/dll/win32/kernel32/mem/local.c b/reactos/dll/win32/kernel32/mem/local.c index 68d9de20699..875ae4bce8a 100644 --- a/reactos/dll/win32/kernel32/mem/local.c +++ b/reactos/dll/win32/kernel32/mem/local.c @@ -441,8 +441,62 @@ BOOL NTAPI LocalUnlock(HLOCAL hMem) { - /* This is the same as a Global Unlock */ - return GlobalUnlock(hMem); + PBASE_HEAP_HANDLE_ENTRY HandleEntry; + BOOL RetVal = TRUE; + + /* Check if this was a simple allocated heap entry */ + if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) + { + /* Fail, because LocalUnlock is not supported on LMEM_FIXED allocations */ + SetLastError(ERROR_NOT_LOCKED); + return FALSE; + } + + /* Otherwise, lock the heap */ + RtlLockHeap(hProcessHeap); + + /* Get the handle entry */ + HandleEntry = BaseHeapGetEntry(hMem); + BASE_TRACE_HANDLE(HandleEntry, hMem); + + _SEH2_TRY + { + /* Make sure it's valid */ + if (!BaseHeapValidateEntry(HandleEntry)) + { + /* It's not, fail */ + BASE_TRACE_FAILURE(); + SetLastError(ERROR_INVALID_HANDLE); + RetVal = FALSE; + } + else + { + /* Otherwise, decrement lock count, unless we're already at 0*/ + if (!HandleEntry->LockCount--) + { + /* In which case we simply lock it back and fail */ + HandleEntry->LockCount++; + SetLastError(ERROR_NOT_LOCKED); + RetVal = FALSE; + } + else if (!HandleEntry->LockCount) + { + /* Nothing to unlock */ + SetLastError(NO_ERROR); + RetVal = FALSE; + } + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_PARAMETER); + RetVal = FALSE; + } + _SEH2_END + + /* All done. Unlock the heap and return the pointer */ + RtlUnlockHeap(hProcessHeap); + return RetVal; } /* EOF */