bool ReadEvent(PDEBUGPRINT_DEVICE_EXTENSION dx, PIRP Irp) {
// Try to remove Event from EventList
PLIST_ENTRY pListEntry = ExInterlockedRemoveHeadList(&dx->EventList, &dx->EventListLock);
if (pListEntry==NULL) return false;
// Get event as DEBUGPRINT_EVENT
PDEBUGPRINT_EVENT pEvent = CONTAINING_RECORD(pListEntry, DEBUGPRINT_EVENT, ListEntry);
// Get length of event data
ULONG EventDataLen = pEvent->Len;
// Get max read length acceptible
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG ReadLen = IrpStack->Parameters.Read.Length;
// Shorten event length if necessary
if(EventDataLen>ReadLen) EventDataLen = ReadLen;
// Copy data to Irp and complete it
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, pEvent->EventData, EventDataLen);
IoSetCancelRoutine(Irp, NULL);
CompleteIrp(Irp, STATUS_SUCCESS, EventDataLen);
// Free event memory
ExFreePool(pEvent);
return true;
}
The
The Monitor program saves its current screen position and column widths in the registry. Consult the code to find out how this is done.
The Monitor uses a single document interface. The view class CDebugPrintMonitorView is derived from CListView, which encapsulates a list view control. It is this list view control that stores the event information once it has been received by the Monitor. The corresponding document class CDebugPrintMonitorDoc does not store the event information. It simply implements the
The main work is carried out in a worker thread, which runs
The
The code uses a LISTENER_INFO structure to pass information to the worker thread. There is only one instance of this object called ListenerInfo.
typedef struct _LISTENER_INFO {
HANDLE DebugPrintDriver;
bool KeepGoing;
} LISTENER_INFO, *PLISTENER_INFO;
LISTENER_INFO ListenerInfo;
It then finds the first DebugPrint driver device and opens a handle to it using
The code uses the
The DebugPrint_Event class shown in Listing 14.11 is used to communicate events to the view class. Each class instance has
DebugPrint_Event::SendEvent( 'Monitor', 'Starting to listen', CTime::GetCurrentTime(), false);
Listing 14.11 DebugPrint driver DebugPrint_Event class
const UINT WM_DEBUGPRINTEVENT = (WM_USER+1);
class DebugPrint_Event {
public:
CString Driver;
CTime Timestamp;
CString Message;
bool SetModified; // false to reset document SetModifiedFlag.
static HWND ViewHwnd; // View Hwnd
// Generate and send an event
static void SendEvent(CString d, CString m, CTime t = 0, bool sm=true) {
if (ViewHwnd==NULL) return;
DebugPrint_Event* pEvent = new DebugPrint_Event;
pEvent->Driver = d;
if (t==0) t = CTime::GetCurrentTime();
pEvent->Timestamp = t;
pEvent->Message = m;
pEvent->SetModified = sm;
::PostMessage(ViewHwnd, WM_DEBUGPRINTEVENT, 0, (LPARAM)pEvent);
}
};
The code in
To do overlapped I/O, a Win32 event and an OVERLAPPED structure are needed.
A standard