コード例 #1
0
ファイル: workqueue.c プロジェクト: xqrzd/HazardShield
/**
 * Queues a work item to a work queue.
 *
 * \param WorkQueue A work queue object.
 * \param Function A function to execute.
 * \param Context A user-defined value to pass to the function.
 * \param DeleteFunction A callback function that is executed when the work queue item is about to be freed.
 */
VOID PhQueueItemWorkQueueEx(
    _Inout_ PPH_WORK_QUEUE WorkQueue,
    _In_ PUSER_THREAD_START_ROUTINE Function,
    _In_opt_ PVOID Context,
    _In_opt_ PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION DeleteFunction
    )
{
    PPH_WORK_QUEUE_ITEM workQueueItem;

    workQueueItem = PhpCreateWorkQueueItem(Function, Context, DeleteFunction);

    // Enqueue the work item.
    PhAcquireQueuedLockExclusive(&WorkQueue->QueueLock);
    InsertTailList(&WorkQueue->QueueListHead, &workQueueItem->ListEntry);
    _InterlockedIncrement(&WorkQueue->BusyCount);
    PhReleaseQueuedLockExclusive(&WorkQueue->QueueLock);
    // Signal the semaphore once to let a worker thread continue.
    NtReleaseSemaphore(PhpGetSemaphoreWorkQueue(WorkQueue), 1, NULL);

    PHLIB_INC_STATISTIC(WqWorkItemsQueued);

    // Check if all worker threads are currently busy, and if we can create more threads.
    if (WorkQueue->BusyCount >= WorkQueue->CurrentThreads &&
        WorkQueue->CurrentThreads < WorkQueue->MaximumThreads)
    {
        // Lock and re-check.
        PhAcquireQueuedLockExclusive(&WorkQueue->StateLock);

        if (WorkQueue->CurrentThreads < WorkQueue->MaximumThreads)
            PhpCreateWorkQueueThread(WorkQueue);

        PhReleaseQueuedLockExclusive(&WorkQueue->StateLock);
    }
}
コード例 #2
0
/**
 * Frees resources used by a work queue.
 *
 * \param WorkQueue A work queue object.
 */
VOID PhDeleteWorkQueue(
    __inout PPH_WORK_QUEUE WorkQueue
    )
{
    PLIST_ENTRY listEntry;
    PPH_WORK_QUEUE_ITEM workQueueItem;

#ifdef DEBUG
    PhAcquireQueuedLockExclusive(&PhDbgWorkQueueListLock);
    RemoveEntryList(&WorkQueue->DbgListEntry);
    PhReleaseQueuedLockExclusive(&PhDbgWorkQueueListLock);
#endif

    // Wait for all worker threads to exit.
    WorkQueue->Terminating = TRUE;
    NtReleaseSemaphore(WorkQueue->SemaphoreHandle, WorkQueue->CurrentThreads, NULL);
    PhWaitForRundownProtection(&WorkQueue->RundownProtect);

    // Free all un-executed work items.

    listEntry = WorkQueue->QueueListHead.Flink;

    while (listEntry != &WorkQueue->QueueListHead)
    {
        workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry);
        listEntry = listEntry->Flink;
        PhFreeToFreeList(&PhWorkQueueItemFreeList, workQueueItem);
    }

    NtClose(WorkQueue->SemaphoreHandle);
}
コード例 #3
0
ファイル: api32prf.c プロジェクト: mingpen/OpenNT
void FAR PASCAL ApfRecordInfo (WORD iApi, ULONG ulElapsedTime)
{
    NTSTATUS Status;


    // Get semaphore
    //
    Status = NtWaitForSingleObject(hDataSem,FALSE,NULL);

#ifdef ERRORDBG
    if (!NT_SUCCESS(Status)) {
	KdPrint (("WAP: Could not wait for Dsemaphore in RecordInfo, %lx\n",
	    Status));
    }
#endif	
		
    // kick bad times -- only should occur with timer wrap
    //
    if (ulElapsedTime > MAX_LONG) {
        ApfData[iApi].cTimingErrors++;
        return;
    }

    // subtract save/restore registers timer overhead and
    // zero out values that go negative
    //
    ulElapsedTime -= ApfData[I_CALIBRATE].ulMinTime;
    if (ulElapsedTime > MAX_LONG) {
	ulElapsedTime = 0;
    }

    // record valid info
    //
    ApfData[iApi].cCalls++;
    ApfData[iApi].ulTotalTime += ulElapsedTime;
    if (ApfData[iApi].cCalls == 1) {
	ApfData[iApi].ulFirstTime = ulElapsedTime;
    }
    else {
	if (ulElapsedTime > ApfData[iApi].ulMaxTime) {
	    ApfData[iApi].ulMaxTime = ulElapsedTime;
	}
	if (ulElapsedTime < ApfData[iApi].ulMinTime) {
	    ApfData[iApi].ulMinTime = ulElapsedTime;
	}
    }

    // Release semaphore
    //
    Status = NtReleaseSemaphore(hDataSem,1,NULL);
#ifdef ERRORDBG
    if (!NT_SUCCESS(Status)) {
	KdPrint (("WAP: DSemaphore Not Released in RecordInfo!! %lx\n",
	    Status));
    }
#endif

} /* ApfRecordInfo () */
コード例 #4
0
ファイル: synch.c プロジェクト: shuowen/OpenNT
BOOL
ReleaseSemaphore(
    HANDLE hSemaphore,
    LONG lReleaseCount,
    LPLONG lpPreviousCount
)

/*++

Routine Description:

    A semaphore object can be released with the ReleaseSemaphore
    function.

    When the semaphore is released, the current count of the semaphore
    is incremented by the ReleaseCount.  Any threads that are waiting
    for the semaphore are examined to see if the current semaphore value
    is sufficient to satisfy their wait.

    If the value specified by ReleaseCount would cause the maximum count
    for the semaphore to be exceeded, then the count for the semaphore
    is not affected and an error status is returned.


Arguments:

    hSemaphore - Supplies an open handle to a semaphore object.  The
        handle must have SEMAPHORE_MODIFY_STATE access to the semaphore.

    lReleaseCount - The release count for the semaphore.  The count
        must be greater than zero and less than the maximum value
        specified for the semaphore.

    lpPreviousCount - An optional pointer to a variable that receives
        the previous count for the semaphore.

Return Value:

    TRUE - The operation was successful

    FALSE/NULL - The operation failed. Extended error status is available
        using GetLastError.

--*/

{
    NTSTATUS Status;

    Status = NtReleaseSemaphore(hSemaphore,lReleaseCount,lpPreviousCount);
    if ( NT_SUCCESS(Status) ) {
        return TRUE;
    }
    else {
        BaseSetLastNTError(Status);
        return FALSE;
    }
}
コード例 #5
0
ファイル: synch.c プロジェクト: HBelusca/NasuTek-Odyssey
/*
 * @implemented
 */
BOOL
WINAPI
ReleaseSemaphore(IN HANDLE hSemaphore,
                 IN LONG lReleaseCount,
                 IN LPLONG lpPreviousCount)
{
    NTSTATUS Status;

    /* Release the semaphore */
    Status = NtReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount);
    if (NT_SUCCESS(Status)) return TRUE;

    /* If we got here, then we failed */
    BaseSetLastNTError(Status);
    return FALSE;
}
コード例 #6
0
static int wine_pthread_cond_signal(pthread_cond_t *cond)
{
  int have_waiters;
  wine_cond_detail *detail;

  if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
  detail = ((wine_cond)cond)->cond;

  RtlEnterCriticalSection (&detail->waiters_count_lock);
  have_waiters = detail->waiters_count > 0;
  RtlLeaveCriticalSection (&detail->waiters_count_lock);

  /* If there aren't any waiters, then this is a no-op. */
  if (have_waiters)
    NtReleaseSemaphore(detail->sema, 1, NULL);

  return 0;
}
コード例 #7
0
static int wine_pthread_cond_broadcast(pthread_cond_t *cond)
{
  int have_waiters = 0;
  wine_cond_detail *detail;

  if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond);
  detail = ((wine_cond)cond)->cond;

  /*
   * This is needed to ensure that <waiters_count> and <was_broadcast> are
   * consistent relative to each other.
   */
  RtlEnterCriticalSection (&detail->waiters_count_lock);

  if (detail->waiters_count > 0) {
    /*
     * We are broadcasting, even if there is just one waiter...
     * Record that we are broadcasting, which helps optimize
     * <pthread_cond_wait> for the non-broadcast case.
     */
    detail->was_broadcast = 1;
    have_waiters = 1;
  }

  if (have_waiters) {
    /* Wake up all the waiters atomically. */
    NtReleaseSemaphore(detail->sema, detail->waiters_count, NULL);

    RtlLeaveCriticalSection (&detail->waiters_count_lock);

    /* Wait for all the awakened threads to acquire the counting semaphore. */
    NtWaitForMultipleObjects( 1, &detail->waiters_done, FALSE, FALSE, NULL );

    /*
     * This assignment is okay, even without the <waiters_count_lock> held
     * because no other waiter threads can wake up to access it.
     */
    detail->was_broadcast = 0;
  }
  else
    RtlLeaveCriticalSection (&detail->waiters_count_lock);
  return 0;
}
コード例 #8
0
ファイル: workqueue.c プロジェクト: xqrzd/HazardShield
/**
 * Frees resources used by a work queue.
 *
 * \param WorkQueue A work queue object.
 */
VOID PhDeleteWorkQueue(
    _Inout_ PPH_WORK_QUEUE WorkQueue
    )
{
    PLIST_ENTRY listEntry;
    PPH_WORK_QUEUE_ITEM workQueueItem;
#ifdef DEBUG
    ULONG index;
#endif

#ifdef DEBUG
    PhAcquireQueuedLockExclusive(&PhDbgWorkQueueListLock);
    if ((index = PhFindItemList(PhDbgWorkQueueList, WorkQueue)) != -1)
        PhRemoveItemList(PhDbgWorkQueueList, index);
    PhReleaseQueuedLockExclusive(&PhDbgWorkQueueListLock);
#endif

    // Wait for all worker threads to exit.

    WorkQueue->Terminating = TRUE;
    MemoryBarrier();

    if (WorkQueue->SemaphoreHandle)
        NtReleaseSemaphore(WorkQueue->SemaphoreHandle, WorkQueue->CurrentThreads, NULL);

    PhWaitForRundownProtection(&WorkQueue->RundownProtect);

    // Free all un-executed work items.

    listEntry = WorkQueue->QueueListHead.Flink;

    while (listEntry != &WorkQueue->QueueListHead)
    {
        workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry);
        listEntry = listEntry->Flink;
        PhpDestroyWorkQueueItem(workQueueItem);
    }

    if (WorkQueue->SemaphoreHandle)
        NtClose(WorkQueue->SemaphoreHandle);
}
コード例 #9
0
/**
 * Queues a work item to a work queue.
 *
 * \param WorkQueue A work queue object.
 * \param Function A function to execute.
 * \param Context A user-defined value to pass to the function.
 */
VOID PhQueueItemWorkQueue(
    __inout PPH_WORK_QUEUE WorkQueue,
    __in PTHREAD_START_ROUTINE Function,
    __in_opt PVOID Context
    )
{
    PPH_WORK_QUEUE_ITEM workQueueItem;

    workQueueItem = PhAllocateFromFreeList(&PhWorkQueueItemFreeList);
    PhpInitializeWorkQueueItem(workQueueItem, Function, Context);

    // Enqueue the work item.
    PhAcquireQueuedLockExclusive(&WorkQueue->QueueLock);
    InsertTailList(&WorkQueue->QueueListHead, &workQueueItem->ListEntry);
    PhReleaseQueuedLockExclusive(&WorkQueue->QueueLock);
    // Signal the semaphore once to let a worker thread continue.
    NtReleaseSemaphore(WorkQueue->SemaphoreHandle, 1, NULL);

    PHLIB_INC_STATISTIC(WqWorkItemsQueued);

    // Check if all worker threads are currently busy,
    // and if we can create more threads.
    if (
        WorkQueue->BusyThreads == WorkQueue->CurrentThreads &&
        WorkQueue->CurrentThreads < WorkQueue->MaximumThreads
        )
    {
        // Lock and re-check.
        PhAcquireQueuedLockExclusive(&WorkQueue->StateLock);

        if (WorkQueue->CurrentThreads < WorkQueue->MaximumThreads)
        {
            PhpCreateWorkQueueThread(WorkQueue);
        }

        PhReleaseQueuedLockExclusive(&WorkQueue->StateLock);
    }
}
コード例 #10
0
ファイル: api32prf.c プロジェクト: mingpen/OpenNT
BOOLEAN ZMain(
    IN PVOID DllHandle,
    ULONG Reason,
    IN PCONTEXT Context OPTIONAL)
					
{
    static char szDumpFile[13];
    NTSTATUS Status;
    DllHandle, Context;	// avoid compiler warnings


    // if process is attaching, initialize the dll
    //
    if (Reason == DLL_PROCESS_ATTACH) {
		GdiSetBatchLimit (1);
    	ApfInitDll();
    }
    else if (Reason == DLL_THREAD_ATTACH) {
		GdiSetBatchLimit (1);
    }
    else if (Reason == DLL_PROCESS_DETACH) {
	//
	// Get semaphore
	//
	Status = NtWaitForSingleObject(hDataSem,FALSE,NULL);

#ifdef ERRORDBG
	if (!NT_SUCCESS(Status)) {
	    KdPrint (("WAP: Could not wait for Dsemaphore in ZMain, %lx\n",
		Status));
    }
#endif	

	// Number of processes accessing this dll is contained in
	// ApfData[I_CALIBRATE].cCalls.	Decrement this number, and
	// if this number is then zero, dump the data.
			
	ApfData[I_CALIBRATE].cCalls--;
	if (ApfData[I_CALIBRATE].cCalls == 0) {
	    strcpy (szDumpFile, MODULE_NAME);
	    strcat (szDumpFile, ".end");
	    ApfDumpData ((LPSTR)szDumpFile);
	    //
	    // Unmap and close sections, and close semaphores
	    //
	    Status = NtUnmapViewOfSection(MyProcess,(PVOID)ApfControl);
	    Status = NtClose(ApfDataSectionHandle);

	    // This instance is now "uninitialized"
	    //
	    fInitDone = FALSE;
	}
	//
	// Release semaphore
	//
	Status = NtReleaseSemaphore(hDataSem,1,NULL);
#ifdef ERRORDBG
	if (!NT_SUCCESS(Status)) {
	    KdPrint (("WAP: DSemaphore Not Released in ZMain!! %lx\n",
		Status));
	}
#endif		
    }
    return(TRUE);

} /* ZMain () */
コード例 #11
0
ファイル: api32prf.c プロジェクト: mingpen/OpenNT
void  ApfInitDll ()
{
    NTSTATUS Status;		
    DWORD ulInitElapsedTime;
    SHORT sInitTimerHandle;
	DWORD ARGS64;

#ifdef CALIBDBG
    SHORT sTimerHandle;
    ULONG ulElapsedTime;
#endif

#ifdef ERRORDBG
    DWORD Error;
#endif


    int   i;
    STRING DataSemName;
    UNICODE_STRING DataSemUnicodeName;
    OBJECT_ATTRIBUTES DataSemAttributes;


    // Create public share security descriptor for all the named objects
    //
    Status = RtlCreateSecurityDescriptor (
		&SecDescriptor,
		SECURITY_DESCRIPTOR_REVISION1
		);
#ifdef ERRORDBG
    if (!NT_SUCCESS(Status)) {
	KdPrint (("WAP: RtlCreateSecurityDescriptor falied - 0x%lx\n", Status));
    }
#endif

    Status = RtlSetDaclSecurityDescriptor (
		&SecDescriptor,	   // SecurityDescriptor
		TRUE,		   // DaclPresent
		NULL,		   // Dacl
		FALSE		   // DaclDefaulted
                );
#ifdef ERRORDBG
    if (!NT_SUCCESS(Status)) {
	KdPrint (("WAP: RtlSetDaclSecurityDescriptor falied - 0x%lx\n", Status));
    }
#endif

    // Create sections for data and api arrays
    //
    if ( NT_SUCCESS(ApfCreateDataSection(&ApfControl)) ) {

	// Leave room for control flag
	//
	ApfData = (PAPFDATA)(ApfControl+1);
		
	// Initialization for semaphore creation
	//
	RtlInitString(&DataSemName, DATA_SEM_NAME);
			
	Status = RtlAnsiStringToUnicodeString(
		     &DataSemUnicodeName,
		     &DataSemName,
		     TRUE);
			
	if (NT_SUCCESS(Status)) {
		InitializeObjectAttributes(
			&DataSemAttributes,
			&DataSemUnicodeName,
			OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
			NULL,
			&SecDescriptor);
	}

	// Create semaphores
	//
	Status = NtCreateSemaphore(
			&hDataSem,
			SEMAPHORE_QUERY_STATE |
			SEMAPHORE_MODIFY_STATE |
			SYNCHRONIZE,
			&DataSemAttributes,
			1L,
			1L);

#ifdef ERRORDBG
	if (!NT_SUCCESS(Status)) {
	    KdPrint (("WAP: Data semaphore creation falied %lx\n",
		Status));
	}
#endif

	// Get semaphores
	//
	Status = NtWaitForSingleObject(hDataSem,FALSE,NULL);
#ifdef ERRORDBG
	if (!NT_SUCCESS(Status)) {
	    KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n",
		Status));
	}
#endif

	//
	// Do timer calibration if not already done.
	//
	if (!ApfControl->fCalibrate) {

	    ApfControl->fCalibrate = TRUE;

	    //
	    //	 Calibrate time overheads:
        //   we get the minimum time here, to avoid extra time from
        //   interrupts etc.
        //   the tedious approach has two benefits
        //   - duplicate generated code as accurately as possible
        //   - pick up timer overhead, that isn't handled correctly
	    //	 in timer
        //   NOTE: ApfData[I_CALIBRATE].ulMinTime contains the
	    //	       timer overhead, while ApfData[I_CALIBRATE].cCalls
	    //	       contains the number of processess accessing this
	    //	       DLL.
		//
	    ApfData[I_CALIBRATE].cCalls = 0L;
        ApfData[I_CALIBRATE].cTimingErrors = 0L;
	    ApfData[I_CALIBRATE].ulTotalTime = 0L;
	    ApfData[I_CALIBRATE].ulFirstTime = MAX_LONG;
	    ApfData[I_CALIBRATE].ulMaxTime = MAX_LONG;
        ApfData[I_CALIBRATE].ulMinTime = MAX_LONG;

	    ApfClearData();

		TimerOpen(&sInitTimerHandle, MICROSECONDS);
#ifdef CALIBDBG
		// Release semaphore
		//
		Status = NtReleaseSemaphore(hDataSem,1,NULL);
#ifdef ERRORDBG
		if (!NT_SUCCESS(Status)) {
			KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n",
				Status));
		}
#endif
		//
		// Overhead for all the API wrapper code
		// Stored in ApfData[I_CALIBRATE].ulMaxTime
		// Used for debugging - for WOW profiling overhead.
		//
		for (i=0; i<NUM_ITRATIONS; i++) {
			TimerInit(sInitTimerHandle);
			if (fInitDone == FALSE) {
			}
			TimerOpen(&sTimerHandle, MICROSECONDS);
			TimerInit(sTimerHandle);
			//
			// Get the elapsed time
			//
			ulElapsedTime = TimerRead(sTimerHandle);
			ApfRecordInfo(1, ulElapsedTime);
			TimerClose(sTimerHandle);
			ulInitElapsedTime = TimerRead(sInitTimerHandle);
			if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMaxTime) &&
				(ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) {
				ApfData[I_CALIBRATE].ulMaxTime = ulInitElapsedTime;
			}
		}

		// Get semaphores
		//
		Status = NtWaitForSingleObject(hDataSem,FALSE,NULL);
#ifdef ERRORDBG
		if (!NT_SUCCESS(Status)) {
			KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n",
			Status));
		}
#endif
#endif
		//
		// Excess overhead for TimerInit() followed by TimerREad() calls
		// Stored in ApfData[I_CALIBRATE].ulMinTime
		// Used by all APIs
		//
	    for (i=0; i<NUM_ITRATIONS; i++) {
			TimerInit(sInitTimerHandle);
			ulInitElapsedTime = TimerRead(sInitTimerHandle);
			if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMinTime) &&
				(ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) {
				ApfData[I_CALIBRATE].ulMinTime = ulInitElapsedTime;
			}
	    }
		//
		// Oerhead for calling cdecl APIs with 64 DWORD arguments
		// Stored in ApfData[I_CALIBRATE].ulFirstTime
		// Used by all variable argument cdecl APIs such as wsprintf()
		//
	    for (i=0; i<NUM_ITRATIONS; i++) {
			TimerInit(sInitTimerHandle);
			CalibCdeclApi (ARGS64);
			ulInitElapsedTime = TimerRead(sInitTimerHandle);
			if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulFirstTime) &&
				(ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) {
				ApfData[I_CALIBRATE].ulFirstTime = ulInitElapsedTime;
			}
	    }
		ApfData[I_CALIBRATE].ulFirstTime -= ApfData[I_CALIBRATE].ulMinTime;
		TimerClose(sInitTimerHandle);	
	}

	// Increment the number of active processes on this DLL
	//
	ApfData[I_CALIBRATE].cCalls++;
	
	// Load the module being profiled
    //
	hModule=GetModuleHandle(MODULE_NAME);
#ifdef ERRORDBG
	if (hModule==NULL) {
	    Error=GetLastError();
	    KdPrint (("WAP: Module Handle is null - %lx\n",Error));
	}
#endif
	// Release semaphore
	//
	Status = NtReleaseSemaphore(hDataSem,1,NULL);
#ifdef ERRORDBG
	if (!NT_SUCCESS(Status)) {
	    KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n",
		    Status));
	}
#endif
        fInitDone = TRUE;
    }
#ifdef ERRORDBG
    else {
	KdPrint (("WAP: Couldn't create DATA section in ApfInitDll\n"));
    }
#endif


} /* ApfInitDll () */
コード例 #12
0
INT_PTR CALLBACK PhpSemaphorePageProc(
    _In_ HWND hwndDlg,
    _In_ UINT uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    PCOMMON_PAGE_CONTEXT pageContext;

    pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);

    if (!pageContext)
        return FALSE;

    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        PhpRefreshSemaphorePageInfo(hwndDlg, pageContext);
    }
    break;
    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case IDC_ACQUIRE:
        case IDC_RELEASE:
        {
            NTSTATUS status;
            HANDLE semaphoreHandle;

            if (NT_SUCCESS(status = pageContext->OpenObject(
                                        &semaphoreHandle,
                                        LOWORD(wParam) == IDC_ACQUIRE ? SYNCHRONIZE : SEMAPHORE_MODIFY_STATE,
                                        pageContext->Context
                                    )))
            {
                switch (LOWORD(wParam))
                {
                case IDC_ACQUIRE:
                {
                    LARGE_INTEGER timeout;

                    timeout.QuadPart = 0;
                    NtWaitForSingleObject(semaphoreHandle, FALSE, &timeout);
                }
                break;
                case IDC_RELEASE:
                    NtReleaseSemaphore(semaphoreHandle, 1, NULL);
                    break;
                }

                NtClose(semaphoreHandle);
            }

            PhpRefreshSemaphorePageInfo(hwndDlg, pageContext);

            if (!NT_SUCCESS(status))
                PhShowStatus(hwndDlg, L"Unable to open the semaphore", status, 0);
        }
        break;
        }
    }
    break;
    }

    return FALSE;
}