Merge 25584, 25588.
authorAleksey Bragin <aleksey@reactos.org>
Mon, 5 Feb 2007 20:14:59 +0000 (20:14 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Mon, 5 Feb 2007 20:14:59 +0000 (20:14 +0000)
svn path=/branches/ros-branch-0_3_1/; revision=25730

1  2 
reactos/ntoskrnl/ex/init.c
reactos/ntoskrnl/include/internal/ex.h

@@@ -1,11 -1,11 +1,11 @@@
  /*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/ex/init.c
- * PURPOSE:         Executive Initialization Code
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- *                  Eric Kohl (ekohl@rz-online.de)
- */
 * PROJECT:         ReactOS Kernel
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            ntoskrnl/ex/init.c
 * PURPOSE:         Executive Initialization Code
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 *                  Eric Kohl (ekohl@rz-online.de)
 */
  
  /* INCLUDES ******************************************************************/
  
@@@ -39,6 -39,12 +39,6 @@@ BOOLEAN NoGuiBoot = FALSE
  /* NT Boot Path */
  UNICODE_STRING NtSystemRoot;
  
 -/* NT Initial User Application */
 -WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
 -ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
 -                                         sizeof(WCHAR);
 -ULONG NtInitialUserProcessBufferType = REG_SZ;
 -
  /* Boot NLS information */
  PVOID ExpNlsTableBase;
  ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
@@@ -68,7 -74,7 +68,7 @@@ ExpCreateSystemRootLink(IN PLOADER_PARA
                                 &LinkName,
                                 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                 NULL,
 -                               SePublicDefaultUnrestrictedSd);
 +                               SePublicDefaultSd);
  
      /* Create it */
      Status = NtCreateDirectoryObject(&LinkHandle,
@@@ -88,7 -94,7 +88,7 @@@
                                 &LinkName,
                                 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                 NULL,
 -                               SePublicDefaultUnrestrictedSd);
 +                               SePublicDefaultSd);
  
      /* Create it */
      Status = NtCreateDirectoryObject(&LinkHandle,
                                 &LinkName,
                                 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                 NULL,
 -                               SePublicDefaultUnrestrictedSd);
 +                               SePublicDefaultSd);
  
      /* Build the ARC name */
      sprintf(Buffer,
@@@ -353,10 -359,11 +353,10 @@@ ExpLoadInitialProcess(IN PHANDLE Proces
      PWSTR p;
      UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
      UNICODE_STRING SmssName, Environment, SystemDriveString;
 -    PVOID EnvironmentPtr = NULL;
  
      /* Allocate memory for the process parameters */
      Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
 -           ((MAX_PATH * 6) * sizeof(WCHAR));
 +           ((MAX_PATH * 4) * sizeof(WCHAR));
      Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
                                       (PVOID)&ProcessParameters,
                                       0,
      /* Allocate a page for the environment */
      Size = PAGE_SIZE;
      Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
 -                                     &EnvironmentPtr,
 +                                     (PVOID)&ProcessParameters->Environment,
                                       0,
                                       &Size,
                                       MEM_COMMIT,
          KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
      }
  
 -    /* Write the pointer */
 -    ProcessParameters->Environment = EnvironmentPtr;
 -
      /* Make a buffer for the DOS path */
      p = (PWSTR)(ProcessParameters + 1);
      ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
      ProcessParameters->ImagePathName.Buffer = p;
      ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
  
 -    /* Make sure the buffer is a valid string which within the given length */
 -    if ((NtInitialUserProcessBufferType != REG_SZ) ||
 -        ((NtInitialUserProcessBufferLength != -1) &&
 -         ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
 -          (NtInitialUserProcessBufferLength >
 -           sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
 -    {
 -        /* Invalid initial process string, bugcheck */
 -        KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
 -                     (ULONG_PTR)STATUS_INVALID_PARAMETER,
 -                     NtInitialUserProcessBufferType,
 -                     NtInitialUserProcessBufferLength,
 -                     sizeof(NtInitialUserProcessBuffer));
 -    }
 -
 -    /* Cut out anything after a space */
 -    p = NtInitialUserProcessBuffer;
 -    while (*p && *p != L' ') p++;
 -
 -    /* Set the image path length */
 -    ProcessParameters->ImagePathName.Length =
 -        (USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
 -
 -    /* Copy the actual buffer */
 -    RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
 -                  NtInitialUserProcessBuffer,
 -                  ProcessParameters->ImagePathName.Length);
 -
 -    /* Null-terminate it */
 -    ProcessParameters->
 -        ImagePathName.Buffer[ProcessParameters->ImagePathName.Length /
 -                             sizeof(WCHAR)] = UNICODE_NULL;
 -
 -    /* Make a buffer for the command line */
 -    p = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
 -                ProcessParameters->ImagePathName.MaximumLength);
 -    ProcessParameters->CommandLine.Buffer = p;
 -    ProcessParameters->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
 -
 -    /* Add the image name to the command line */
 -    RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
 -                             NtInitialUserProcessBuffer);
 +    /* Append the system path and session manager name */
 +    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
 +                             L"\\SystemRoot\\System32");
 +    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
 +                             L"\\smss.exe");
  
      /* Create the environment string */
      RtlInitEmptyUnicodeString(&Environment,
      RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
      RtlAppendUnicodeStringToString(&Environment, &NullString);
  
 -    /* Create SMSS process */
 +    /* Get and set the command line equal to the image path */
 +    ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
      SmssName = ProcessParameters->ImagePathName;
 +
 +    /* Create SMSS process */
      Status = RtlCreateUserProcess(&SmssName,
                                    OBJ_CASE_INSENSITIVE,
                                    RtlDeNormalizeProcessParams(
@@@ -731,9 -775,9 +731,9 @@@ ExpInitializeExecutive(IN ULONG Cpu
      Buffer[--AnsiPath.Length] = ANSI_NULL;
  
      /* Get the string from KUSER_SHARED_DATA's buffer */
 -    RtlInitEmptyUnicodeString(&NtSystemRoot,
 -                              SharedUserData->NtSystemRoot,
 -                              sizeof(SharedUserData->NtSystemRoot));
 +    NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
 +    NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR);
 +    NtSystemRoot.Length = 0;
  
      /* Now fill it in */
      Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
@@@ -960,19 -1004,17 +960,19 @@@ ExPhase2Init(PVOID Context
          /* Bugcheck the system if SMSS couldn't initialize */
          KeBugCheck(SESSION5_INITIALIZATION_FAILED);
      }
 +    else
 +    {
 +        /* Close process handles */
 +        ZwClose(ThreadHandle);
 +        ZwClose(ProcessHandle);
  
 -    /* Close process handles */
 -    ZwClose(ThreadHandle);
 -    ZwClose(ProcessHandle);
 -
 -    /* FIXME: We should free the initial process' memory!*/
 +        /* FIXME: We should free the initial process' memory!*/
  
 -    /* Increase init phase */
 -    ExpInitializationPhase += 1;
 +        /* Increase init phase */
 +        ExpInitializationPhase += 1;
  
 -    /* Jump into zero page thread */
 -    MmZeroPageThreadMain(NULL);
 +        /* Jump into zero page thread */
 +        MmZeroPageThreadMain(NULL);
 +    }
  }
  /* EOF */
@@@ -21,15 -21,41 +21,15 @@@ ULONG ExpAnsiCodePageDataOffset, ExpOem
  ULONG ExpUnicodeCaseTableDataOffset;
  PVOID ExpNlsSectionPointer;
  
 -typedef struct _EXHANDLE
 -{
 -    union
 -    {
 -        struct
 -        {
 -            ULONG TagBits:2;
 -            ULONG Index:30;
 -        };
 -        HANDLE GenericHandleOverlay;
 -        ULONG_PTR Value;
 -    };
 -} EXHANDLE, *PEXHANDLE;
 -
 -typedef struct _ETIMER
 -{
 -    KTIMER KeTimer;
 -    KAPC TimerApc;
 -    KDPC TimerDpc;
 -    LIST_ENTRY ActiveTimerListEntry;
 -    KSPIN_LOCK Lock;
 -    LONG Period;
 -    BOOLEAN ApcAssociated;
 -    BOOLEAN WakeTimer;
 -    LIST_ENTRY WakeTimerListEntry;
 -} ETIMER, *PETIMER;
 -
 -typedef struct
 -{
 -    PCALLBACK_OBJECT *CallbackObject;
 -    PWSTR Name;
 -} SYSTEM_CALLBACKS;
 -
  #define MAX_FAST_REFS           7
  
 +#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) &                \
 +  ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE |           \
 +  EX_HANDLE_ENTRY_AUDITONCLOSE)))
 +#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) &   \
 +  ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE |           \
 +  EX_HANDLE_ENTRY_AUDITONCLOSE)))
 +
  /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
  #ifndef CONFIG_SMP
  #define ExAcquireResourceLock(l, i) { \
  #define ExRundownCompleted                              _ExRundownCompleted
  #define ExGetPreviousMode                               KeGetPreviousMode
  
 -
 -//
 -// Various bits tagged on the handle or handle table
 -//
 -#define EXHANDLE_TABLE_ENTRY_LOCK_BIT    1
 -#define FREE_HANDLE_MASK                -1
 -
 -//
 -// Number of entries in each table level
 -//
 -#define LOW_LEVEL_ENTRIES   (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
 -#define MID_LEVEL_ENTRIES   (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
 -#define HIGH_LEVEL_ENTRIES  (65535 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
 -
 -//
 -// Maximum index in each table level before we need another table
 -//
 -#define MAX_LOW_INDEX       LOW_LEVEL_ENTRIES
 -#define MAX_MID_INDEX       (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
 -#define MAX_HIGH_INDEX      (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
 -
+ //
+ // Detect GCC 4.1.2+
+ //
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40102
+ //
+ // Broken GCC with Alignment Bug. We'll do alignment ourselves at higher cost.
+ //
+ #define DEFINE_WAIT_BLOCK(x)                                \
+     struct _AlignHack                                       \
+     {                                                       \
+         UCHAR Hack[15];                                     \
+         EX_PUSH_LOCK_WAIT_BLOCK UnalignedBlock;             \
+     } WaitBlockBuffer;                                      \
+     PEX_PUSH_LOCK_WAIT_BLOCK x = (PEX_PUSH_LOCK_WAIT_BLOCK) \
+         ((ULONG_PTR)&WaitBlockBuffer.UnalignedBlock &~ 0xF);
+         
+ #else
+ //
+ // This is only for compatibility; the compiler will optimize the extra
+ // local variable (the actual pointer) away, so we don't take any perf hit
+ // by doing this.
+ //
+ #define DEFINE_WAIT_BLOCK(x)                                \
+     EX_PUSH_LOCK_WAIT_BLOCK WaitBlockBuffer;                \
+     PEX_PUSH_LOCK_WAIT_BLOCK x = &WaitBlockBuffer;
+     
+ #endif
  /* INITIALIZATION FUNCTIONS *************************************************/
  
  VOID
@@@ -94,7 -171,7 +124,7 @@@ ExInitializeSystemLookasideList
      IN PLIST_ENTRY ListHead
  );
  
 -BOOLEAN
 +VOID
  NTAPI
  ExpInitializeCallbacks(VOID);
  
@@@ -150,7 -227,59 +180,7 @@@ ExInitPoolLookasidePointers(VOID)
  VOID
  NTAPI
  ExInitializeCallBack(
 -    IN OUT PEX_CALLBACK Callback
 -);
 -
 -PEX_CALLBACK_ROUTINE_BLOCK
 -NTAPI
 -ExAllocateCallBack(
 -    IN PEX_CALLBACK_FUNCTION Function,
 -    IN PVOID Context
 -);
 -
 -VOID
 -NTAPI
 -ExFreeCallBack(
 -    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
 -);
 -
 -BOOLEAN
 -NTAPI
 -ExCompareExchangeCallBack (
 -    IN OUT PEX_CALLBACK CallBack,
 -    IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
 -    IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
 -);
 -
 -PEX_CALLBACK_ROUTINE_BLOCK
 -NTAPI
 -ExReferenceCallBackBlock(
 -    IN OUT PEX_CALLBACK CallBack
 -);
 -
 -VOID
 -NTAPI
 -ExDereferenceCallBackBlock(
 -    IN OUT PEX_CALLBACK CallBack,
 -    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
 -);
 -
 -PEX_CALLBACK_FUNCTION
 -NTAPI
 -ExGetCallBackBlockRoutine(
 -    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
 -);
 -
 -PVOID
 -NTAPI
 -ExGetCallBackBlockContext(
 -    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
 -);
 -
 -VOID
 -NTAPI
 -ExWaitForCallBacks(
 -    IN PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock
 +    IN PEX_CALLBACK Callback
  );
  
  /* Rundown Functions ********************************************************/
@@@ -207,104 -336,98 +237,104 @@@ ExfWaitForRundownProtectionRelease
  
  /* HANDLE TABLE FUNCTIONS ***************************************************/
  
 -typedef VOID
 -(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
 +#define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
 +#define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
 +#define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
 +#define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
 +
 +#define EX_HANDLE_TABLE_CLOSING 0x1
 +
 +#define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED |                    \
 +                                   EX_HANDLE_ENTRY_PROTECTFROMCLOSE |          \
 +                                   EX_HANDLE_ENTRY_INHERITABLE |               \
 +                                   EX_HANDLE_ENTRY_AUDITONCLOSE)
 +
 +typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK)(
      PHANDLE_TABLE_ENTRY HandleTableEntry,
 -    HANDLE Handle,
 +    HANDLE Handle,  
      PVOID Context
  );
  
 -typedef BOOLEAN
 -(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
 -    IN PEPROCESS Process,
 -    IN PHANDLE_TABLE HandleTable,
 -    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
 -    IN PHANDLE_TABLE_ENTRY NewEntry
 +typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK)(
 +    PHANDLE_TABLE HandleTable, 
 +    PHANDLE_TABLE_ENTRY HandleTableEntry, 
 +    PVOID Context
  );
  
 -typedef BOOLEAN
 -(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
 -    PHANDLE_TABLE_ENTRY HandleTableEntry,
 -    ULONG_PTR Context
 +typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK)(
 +    PHANDLE_TABLE HandleTable, 
 +    PHANDLE_TABLE_ENTRY HandleTableEntry, 
 +    PVOID Context
  );
  
  VOID
 -NTAPI
 -ExpInitializeHandleTables(
 -    VOID
 -);
 +ExpInitializeHandleTables(VOID);
  
  PHANDLE_TABLE
 -NTAPI
 -ExCreateHandleTable(
 -    IN PEPROCESS Process OPTIONAL
 +ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL);
 +
 +VOID
 +ExDestroyHandleTable(
 +    IN PHANDLE_TABLE HandleTable
  );
  
  VOID
 -NTAPI
 -ExUnlockHandleTableEntry(
 +ExSweepHandleTable(
      IN PHANDLE_TABLE HandleTable,
 -    IN PHANDLE_TABLE_ENTRY HandleTableEntry
 +    IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback  OPTIONAL,
 +    IN PVOID Context  OPTIONAL
  );
  
 -HANDLE
 -NTAPI
 -ExCreateHandle(
 +PHANDLE_TABLE
 +ExDupHandleTable(
 +    IN PEPROCESS QuotaProcess  OPTIONAL,
 +    IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback  OPTIONAL,
 +    IN PVOID Context  OPTIONAL,
 +    IN PHANDLE_TABLE SourceHandleTable
 +);
 +
 +BOOLEAN
 +ExLockHandleTableEntry(
      IN PHANDLE_TABLE HandleTable,
 -    IN PHANDLE_TABLE_ENTRY HandleTableEntry
 +    IN PHANDLE_TABLE_ENTRY Entry
  );
  
  VOID
 -NTAPI
 -ExDestroyHandleTable(
 +ExUnlockHandleTableEntry(
 +    IN PHANDLE_TABLE HandleTable,
 +    IN PHANDLE_TABLE_ENTRY Entry
 +);
 +
 +HANDLE
 +ExCreateHandle(
      IN PHANDLE_TABLE HandleTable,
 -    IN PVOID DestroyHandleProcedure OPTIONAL
 +    IN PHANDLE_TABLE_ENTRY Entry
  );
  
  BOOLEAN
 -NTAPI
  ExDestroyHandle(
      IN PHANDLE_TABLE HandleTable,
 -    IN HANDLE Handle,
 -    IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
 +    IN HANDLE Handle
  );
  
 -PHANDLE_TABLE_ENTRY
 -NTAPI
 -ExMapHandleToPointer(
 +VOID
 +ExDestroyHandleByEntry(
      IN PHANDLE_TABLE HandleTable,
 +    IN PHANDLE_TABLE_ENTRY Entry,
      IN HANDLE Handle
  );
  
 -PHANDLE_TABLE
 -NTAPI
 -ExDupHandleTable(
 -    IN PEPROCESS Process,
 +PHANDLE_TABLE_ENTRY
 +ExMapHandleToPointer(
      IN PHANDLE_TABLE HandleTable,
 -    IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
 -    IN ULONG_PTR Mask
 +    IN HANDLE Handle
  );
  
  BOOLEAN
 -NTAPI
  ExChangeHandle(
      IN PHANDLE_TABLE HandleTable,
      IN HANDLE Handle,
 -    IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
 -    IN ULONG_PTR Context
 -);
 -
 -VOID
 -NTAPI
 -ExSweepHandleTable(
 -    IN PHANDLE_TABLE HandleTable,
 -    IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
 +    IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
      IN PVOID Context
  );
  
@@@ -319,6 -442,33 +349,6 @@@ static __inline _SEH_FILTER(_SEH_ExSyst
      return ExSystemExceptionFilter();
  }
  
 -/* CALLBACKS *****************************************************************/
 -
 -VOID
 -FORCEINLINE
 -ExDoCallBack(IN OUT PEX_CALLBACK Callback,
 -             IN PVOID Context,
 -             IN PVOID Argument1,
 -             IN PVOID Argument2)
 -{
 -    PEX_CALLBACK_ROUTINE_BLOCK CallbackRoutineBlock;
 -    PEX_CALLBACK_FUNCTION Function;
 -
 -    /* Reference the block */
 -    CallbackRoutineBlock = ExReferenceCallBackBlock(Callback);
 -    if (CallbackRoutineBlock)
 -    {
 -        /* Get the function */
 -        Function = ExGetCallBackBlockRoutine(CallbackRoutineBlock);
 -
 -        /* Do the callback */
 -        Function(Context, Argument1, Argument2);
 -
 -        /* Now dereference it */
 -        ExDereferenceCallBackBlock(Callback, CallbackRoutineBlock);
 -    }
 -}
 -
  /* RUNDOWN *******************************************************************/
  
  #ifdef _WIN64
@@@ -498,6 -648,23 +528,23 @@@ _ExRundownCompleted(IN PEX_RUNDOWN_REF 
  
  /* PUSHLOCKS *****************************************************************/
  
+ /* FIXME: VERIFY THESE! */
+ VOID
+ FASTCALL
+ ExBlockPushLock(PEX_PUSH_LOCK PushLock,
+                 PVOID WaitBlock);
+ VOID
+ FASTCALL
+ ExfUnblockPushLock(PEX_PUSH_LOCK PushLock,
+                    PVOID CurrentWaitBlock);
+ VOID
+ FASTCALL
+ ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
+                          IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock);
  /*++
   * @name ExInitializePushLock
   * INTERNAL MACRO
@@@ -652,13 -819,17 +699,17 @@@ ExConvertPushLockSharedToExclusive(IN P
  VOID
  FORCEINLINE
  ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
 -{  
 +{
-     /* Acquire the lock */
-     ExfAcquirePushLockExclusive(PushLock);
-     ASSERT(PushLock->Locked);
+     /* Check if we're locked */
+     if (PushLock->Locked)
+     {
+         /* Acquire the lock */
+         ExfAcquirePushLockExclusive(PushLock);
+         ASSERT(PushLock->Locked);
  
-     /* Release it */
-     ExfReleasePushLockExclusive(PushLock);
+         /* Release it */
+         ExfReleasePushLockExclusive(PushLock);
+     }
  }
  
  /*++