[ros-diffs] [fireball] 50637: - 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 ERRO...

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Feb 9 20:42:45 UTC 2011


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/local.c?rev=50637&r1=50636&r2=50637&view=diff
==============================================================================
--- 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 */




More information about the Ros-diffs mailing list