|
|
/******************************Module*Header*******************************\
* Module Name: w32kevnt.c * * Event handling functions * * Copyright (c) 1996-1999 Microsoft Corporation * \**************************************************************************/
#include "engine.h"
#include "pw32kevt.h"
/*
* Object type exported from the kernel */ extern POBJECT_TYPE *ExEventObjectType;
BOOL EngCreateEvent( OUT PEVENT *ppEvent )
/*+++
Routine Description:
EngCreateEvent creates a synchronization type event object that can be used to synchronize hardware access between a display driver and video miniport.
---*/
{ PENG_EVENT *ppEngEvent = (PENG_EVENT *)ppEvent; PENG_EVENT pEngEvent; PUCHAR pAllocTmp; ULONG engevtsize = sizeof(ENG_EVENT);
//
// Align size to next higher multiple of 8.
//
engevtsize = (engevtsize + 7) & ~7;
//
// Allocate the whole amount and set pEngEvent to the top.
//
pAllocTmp = (PUCHAR)ENG_KEVENTALLOC(engevtsize + sizeof(KEVENT)); pEngEvent = (PENG_EVENT)pAllocTmp;
if (pEngEvent) {
RtlZeroMemory(pEngEvent, sizeof(ENG_EVENT));
//
// Skip past the ENG_EVENT and set pEngEvent->pKEvent to that.
//
pAllocTmp += engevtsize; pEngEvent->pKEvent = (PKEVENT)pAllocTmp;
//
// Initialize the KEVENT and then put the PENG_EVENT in the
// PPENG_EVENT.
//
KeInitializeEvent(pEngEvent->pKEvent, SynchronizationEvent, FALSE); *ppEngEvent = pEngEvent;
} else { return FALSE; }
return TRUE; }
BOOL EngDeleteEvent( IN PEVENT pEvent )
/*+++
Routine Description:
EngDeleteEvent deletes the specified event object.
---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent;
if ( !(pEngEvent->fFlags & ENG_EVENT_FLAG_IS_MAPPED_USER)) {
ENG_KEVENTFREE(pEngEvent); return TRUE;
} else {
ASSERTGDI(FALSE, "Don't delete MappedUserEvents"); return FALSE; } }
PEVENT EngMapEvent( IN HDEV hDev, IN HANDLE hUserObject, IN PVOID Reserved1, IN PVOID Reserved2, IN PVOID Reserved3 )
/*+++
Routine Description:
This routine allocates a ENG_EVENT and initialize its pKEvent pointer to the event object returned from Object manager. The reserved fields must be set to NULL
---*/
{ LONG status; PENG_EVENT pEngEvent;
//
// Allocate a pEngEvent, but don't allocate the PKEvent that
// resides within this is done by ObReferenceObjectByHandle().
//
pEngEvent = ENG_KEVENTALLOC(sizeof(ENG_EVENT));
if (!pEngEvent) { return NULL; }
RtlZeroMemory(pEngEvent, sizeof(ENG_EVENT));
//
// Create the reference to the HANDLE
// The ObRef call allocates and puts a PKEVENT object at
// the location pointed to by pEngEvent.
//
status = ObReferenceObjectByHandle( hUserObject, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, (PVOID)&(pEngEvent->pKEvent), NULL);
//
// If the reference was successful, then pulse the event object.
//
// KePulseEvent atomically sets the signal state of an event object
// to Signaled, attempts to satisfy as many Waits as possible, and
// then resets the signal state of the event object to Not-Signaled.
// The previous signalstate of the event object is returned as the
// function value.
//
if (NT_SUCCESS(status)) {
KePulseEvent(pEngEvent->pKEvent, EVENT_INCREMENT, FALSE); pEngEvent->fFlags |= ENG_EVENT_FLAG_IS_MAPPED_USER;
} else {
ENG_KEVENTFREE(pEngEvent); pEngEvent = NULL; }
//
// If the caller is using the old prototype of EngMapEvent, we should
// return the pointer of kernel event to the place pointed by the third
// argument.
//
if ( Reserved1 != NULL ) { *(PENG_EVENT *)Reserved1 = pEngEvent; }
return (PEVENT) pEngEvent; }
BOOL EngUnmapEvent( IN PEVENT pEvent )
/*+++
Routine Description:
EngUnmapEvent cleans up the kernel-mode resources allocated for a mapped user-mode event.
---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent;
if ( pEngEvent->fFlags & ENG_EVENT_FLAG_IS_MAPPED_USER ) {
//
// Decrements the object's reference count free the all the memory
//
ObDereferenceObject(pEngEvent->pKEvent); ENG_KEVENTFREE(pEngEvent); return TRUE;
} else {
return FALSE; } }
BOOL EngWaitForSingleObject( IN PEVENT pEvent, IN PLARGE_INTEGER pTimeOut )
/*+++
Routine Description:
Called by Display driver. Can only be called on events created by the Display or miniport driver, not on mapped events.
Return Value:
TRUE if successful, FALSE otherwise. A return value of FALSE indicates that either one of the parameters is invalid or a time-out occurred. ---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent; PKEVENT pKEvent; NTSTATUS Status;
pKEvent = pEngEvent->pKEvent;
//
// Don't even wait if it's mapped user. In fact, don't wait if it's
// invalid.
//
if (pKEvent && (!(pEngEvent->fFlags & ENG_EVENT_FLAG_IS_MAPPED_USER))) {
Status = KeWaitForSingleObject( pKEvent, Executive, KernelMode, FALSE, pTimeOut ); } else {
ASSERTGDI(FALSE, "No waiting on mapped user events."); return FALSE; }
if (NT_SUCCESS(Status)) return TRUE; else return FALSE;
}
LONG EngSetEvent( IN PEVENT pEvent )
/*+++
Routine Description:
EngSetEvent sets the state of the event object to signaled and returns the previous state of the event object
---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent;
return ( KeSetEvent(pEngEvent->pKEvent, 0, FALSE) );
}
VOID EngClearEvent ( IN PEVENT pEvent )
/*+++
Routine Description:
EngClearEvent sets the given event to a not signaled state.
---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent; KeClearEvent(pEngEvent->pKEvent); }
LONG EngReadStateEvent ( IN PEVENT pEvent )
/*+++
Routine Description:
EngReadStateEvent returns the current state, signaled or not signaled, of a given event object.
---*/
{ PENG_EVENT pEngEvent = (PENG_EVENT)pEvent; return ( KeReadStateEvent(pEngEvent->pKEvent) ); }
|