mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
7.8 KiB
369 lines
7.8 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: monitor.c
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* Implements functions that handle waiting for an object to be signalled
|
|
* asynchronously.
|
|
*
|
|
* History:
|
|
* 01-11-93 Davidc Created.
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Define this to enable verbose output for this module
|
|
//
|
|
|
|
// #define DEBUG_MONITOR
|
|
|
|
#ifdef DEBUG_MONITOR
|
|
#define VerbosePrint(s) WLPrint(s)
|
|
#else
|
|
#define VerbosePrint(s)
|
|
#endif
|
|
|
|
#define LockMonitor(Monitor) RtlEnterCriticalSection( &Monitor->CritSec )
|
|
#define UnlockMonitor(Monitor) RtlLeaveCriticalSection( &Monitor->CritSec )
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RefMonitor
|
|
//
|
|
// Synopsis: Safe Ref Count
|
|
//
|
|
// Arguments: [Monitor] --
|
|
//
|
|
// History: 7-12-96 RichardW Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
RefMonitor(
|
|
POBJECT_MONITOR Monitor)
|
|
{
|
|
LockMonitor( Monitor );
|
|
|
|
Monitor->RefCount ++ ;
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DerefMonitor
|
|
//
|
|
// Synopsis: Deref the monitor, cleaning up if refcount goes to zero
|
|
//
|
|
// Arguments: [Monitor] --
|
|
//
|
|
// History: 7-12-96 RichardW Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
DerefMonitor(
|
|
POBJECT_MONITOR Monitor )
|
|
{
|
|
LockMonitor( Monitor );
|
|
|
|
DebugLog(( DEB_TRACE, "Deref of Monitor at %x\n", Monitor));
|
|
|
|
Monitor->RefCount -- ;
|
|
|
|
if ( Monitor->RefCount == 0 )
|
|
{
|
|
//
|
|
// Clean up time:
|
|
//
|
|
|
|
DebugLog(( DEB_TRACE, "Cleaning up Monitor at %x\n", Monitor ));
|
|
|
|
if ( Monitor->Thread )
|
|
{
|
|
CloseHandle( Monitor->Thread );
|
|
}
|
|
|
|
if ( Monitor->Flags & MONITOR_CLOSEOBJ )
|
|
{
|
|
if ( Monitor->Object != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle( Monitor->Object );
|
|
}
|
|
}
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
RtlDeleteCriticalSection( &Monitor->CritSec );
|
|
|
|
Free( Monitor );
|
|
|
|
}
|
|
else
|
|
{
|
|
UnlockMonitor( Monitor );
|
|
}
|
|
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* FUNCTION: MonitorThread
|
|
*
|
|
* PURPOSE: Entry point for object monitor thread
|
|
*
|
|
* RETURNS: Windows error value
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 01-11-93 Davidc Created.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
DWORD MonitorThread(
|
|
LPVOID lpThreadParameter
|
|
)
|
|
{
|
|
POBJECT_MONITOR Monitor = (POBJECT_MONITOR)lpThreadParameter;
|
|
DWORD WaitResult;
|
|
NTSTATUS Status;
|
|
HANDLE Handle;
|
|
|
|
//
|
|
// Wait forever for object to be signalled
|
|
//
|
|
|
|
LockMonitor( Monitor );
|
|
|
|
Monitor->Flags |= MONITOR_ACTIVE ;
|
|
|
|
Handle = Monitor->Object ;
|
|
|
|
RefMonitor( Monitor );
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
if ( Handle != INVALID_HANDLE_VALUE )
|
|
{
|
|
|
|
Status = NtWaitForSingleObject( Handle, TRUE, NULL);
|
|
|
|
if (!NT_SUCCESS(Status) && (Status != STATUS_ALERTED))
|
|
{
|
|
DebugLog((DEB_ERROR, "MonitorThread: NtWaitForSingleObject returned %x\n", Status));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_SUCCESS ;
|
|
}
|
|
|
|
//
|
|
// Notify the appropriate window
|
|
//
|
|
if (Status != STATUS_ALERTED)
|
|
{
|
|
PostMessage( Monitor->hwndNotify,
|
|
WM_OBJECT_NOTIFY,
|
|
(WPARAM)Monitor,
|
|
(LPARAM)Monitor->CallerContext
|
|
);
|
|
}
|
|
|
|
LockMonitor( Monitor );
|
|
|
|
if ( Monitor->Flags & MONITOR_CLOSEOBJ )
|
|
{
|
|
CloseHandle( Handle );
|
|
}
|
|
|
|
Monitor->Object = INVALID_HANDLE_VALUE ;
|
|
|
|
Monitor->Flags = 0 ;
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
DerefMonitor( Monitor );
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* FUNCTION: CreateObjectMonitor
|
|
*
|
|
* PURPOSE: Creates a monitor object that will wait on the specified object
|
|
* and post a message to the specifed window when the object is
|
|
* signalled.
|
|
*
|
|
* NOTES: The object must have been opened for SYNCHRONIZE access.
|
|
* The caller is responsible for closing the object handle
|
|
* after the monitor object has been deleted.
|
|
*
|
|
* RETURNS: Handle to the monitor instance or NULL on failure.
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 01-11-93 Davidc Created.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
POBJECT_MONITOR
|
|
CreateObjectMonitor(
|
|
HANDLE Object,
|
|
HWND hwndNotify,
|
|
DWORD CallerContext
|
|
)
|
|
{
|
|
POBJECT_MONITOR Monitor;
|
|
DWORD ThreadId;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Create monitor object
|
|
//
|
|
|
|
Monitor = Alloc(sizeof(OBJECT_MONITOR));
|
|
if (Monitor == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Initialize monitor fields
|
|
//
|
|
|
|
Status = RtlInitializeCriticalSection( &Monitor->CritSec );
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
Free( Monitor );
|
|
return( NULL );
|
|
}
|
|
|
|
LockMonitor( Monitor );
|
|
|
|
Monitor->hwndNotify = hwndNotify;
|
|
Monitor->Object = Object;
|
|
Monitor->CallerContext = CallerContext;
|
|
Monitor->RefCount = 1;
|
|
Monitor->Flags = 0 ;
|
|
|
|
//
|
|
// Create the monitor thread
|
|
//
|
|
|
|
Monitor->Thread = CreateThread(
|
|
NULL, // Use default ACL
|
|
0, // Same stack size
|
|
MonitorThread, // Start address
|
|
(LPVOID)Monitor, // Parameter
|
|
0, // Creation flags
|
|
&ThreadId // Get the id back here
|
|
);
|
|
|
|
if (Monitor->Thread == NULL) {
|
|
|
|
DebugLog((DEB_ERROR, "Failed to create monitor thread, error = %d\n", GetLastError()));
|
|
|
|
DerefMonitor( Monitor );
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
return(Monitor);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* FUNCTION: DeleteObjectMonitor
|
|
*
|
|
* PURPOSE: Deletes an instance of a monitor object
|
|
*
|
|
* RETURNS: Nothing
|
|
*
|
|
* HISTORY:
|
|
*
|
|
* 01-11-93 Davidc Created.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
VOID
|
|
DeleteObjectMonitor(
|
|
POBJECT_MONITOR Monitor,
|
|
BOOLEAN fTerminate
|
|
)
|
|
{
|
|
BOOL Result;
|
|
|
|
if ( fTerminate )
|
|
{
|
|
CancelObjectMonitor( Monitor );
|
|
}
|
|
|
|
DerefMonitor( Monitor );
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CancelObjectMonitor
|
|
//
|
|
// Synopsis: Interrupts a monitor thread safely.
|
|
//
|
|
// Arguments: [Monitor] --
|
|
//
|
|
// History: 7-12-96 RichardW Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CancelObjectMonitor(
|
|
POBJECT_MONITOR Monitor )
|
|
{
|
|
LockMonitor( Monitor );
|
|
|
|
if ( Monitor->Flags & MONITOR_ACTIVE )
|
|
{
|
|
NtAlertThread( Monitor->Thread );
|
|
}
|
|
else
|
|
{
|
|
Monitor->Object = INVALID_HANDLE_VALUE ;
|
|
}
|
|
|
|
UnlockMonitor( Monitor );
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CloseObjectMonitorObject
|
|
//
|
|
// Synopsis: Tags the handle to be closed when the monitor goes away
|
|
//
|
|
// Arguments: [Monitor] --
|
|
//
|
|
// History: 7-19-96 RichardW Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CloseObjectMonitorObject(
|
|
POBJECT_MONITOR Monitor
|
|
)
|
|
{
|
|
LockMonitor( Monitor );
|
|
|
|
Monitor->Flags |= MONITOR_CLOSEOBJ ;
|
|
|
|
UnlockMonitor( Monitor );
|
|
}
|