Author: fireball Date: Wed Feb 9 20:42:44 2011 New Revision: 50637
URL: http://svn.reactos.org/svn/reactos?rev=50637&view=rev Log: - 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.
Modified: trunk/reactos/dll/win32/kernel32/mem/local.c
Modified: trunk/reactos/dll/win32/kernel32/mem/local.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/mem/loca... ============================================================================== --- trunk/reactos/dll/win32/kernel32/mem/local.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/mem/local.c [iso-8859-1] Wed Feb 9 20:42:44 2011 @@ -441,8 +441,62 @@ 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 */