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/loc…
==============================================================================
--- 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 */