Packet->FinalStatus = 0;

 Packet->SequenceNumber = 0;

 Packet->IoControlCode = 0;

 if (Irp!=NULL) {

  PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

  Packet->MajorFunctionCode = IrpStack->MajorFunction;

  Packet->FinalStatus = Irp->IoStatus.Status;

  if (IrpStack->MajorFunction==IRP_MJ_DEVICE_CONTROL || IrpStack->MajorFunction==IRP_MJ_INTERNAL_DEVICE_CONTROL)

   Packet->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;

 }

 // Fill in dump data

 if (DumpDataCount>0) {

  Packet->DumpDataSize = (USHORT)(sizeof(ULONG)*DumpDataCount); 

  for (int i=0; i<DumpDataCount; i++) Packet->DumpData[i] = DumpData[i];

 } else Packet->DumpDataSize = 0;

 // Fill in insertion strings after DumpData

 Packet->NumberOfStrings = (USHORT)StringCount;

 if (StringCount>0) {

  Packet->StringOffset = sizeof(IO_ERROR_L0G_PACKET) + (DumpDataCount-1) * sizeof(ULONG);

  PUCHAR pInsertionString = (PUCHAR)Packet + Packet->StringOffset;

  // Add each new string to the end

  for (int i=0; i<StringCount; i++) {

   RtlMoveMemory(pInsertionString, Strings[i], StringSizes[i]);

   pInsertionString += StringSizes[i];

  }

 }

 // Log the message

 IoWriteErrorLogEntry(Packet);

 if (StringSizes!=NULL) ExFreePool(StringSizes);

 return true;

}

To make LogEvent easier to use, Wdm3 provides a function called Wdm3EventMessage that simply takes an ANSI string as an argument. This is passed as a wide string to LogEvent to be inserted in the WDM3_MESSAGE message. Wdm3EventMessage is shown in Listing 13.6.

Listing 13.6 Wdm3EventMessage routines

void Wdm3EventMessage(const char* Msg) {

 int MsgLen = GetAnsiStringSize(Msg);

 int wMsgLen = MsgLen*2;

 PWSTR wMsg = (PWSTR)ExAllocatePool(NonPagedPool,wMsgLen);

 if (wMsg==NULL) return; 

 // Brutally make into a wide string

 for (int i=0; i<MsgLen; i++) wMsg[i] = (WCHAR)(unsigned char)Msg[i];

 PWSTR Strings[1] = { wMsg };

 LogEvent(WDM3_MESSAGE, NULL, // IRP

  NULL, 0, // dump data

  Strings, 1); // strings

 ExFreePool(wMsg);

}

Testing Wdm3 Events

The Wdm3EventMessage function is called in a few places in the Wdm3 driver as a test. Wdm3Unload sends a message 'Unload', Wdm3AddDevice sends 'AddDevice', and Wdm3Pnp sends 'PnP xx' where 'xx' represents the Plug and Play minor function code, in hex.

Installing and reinstalling a Wdm3 device should generate several events in the System event log. The events are generated in both the free and checked build versions. Remember to refresh the Event Viewer display to see any new events.

Conclusion

You should use NT events to report any problem events in NT 3.51, NT 4, and Windows 2000 drivers. The two relevant kernel function calls are just stubs in Windows 98, so you can safely generate events in WDM device drivers. 

Chapter 14

DebugPrint

This chapter looks at a fully-fledged driver, DebugPrint. The DebugPrint software lets you use formatted print trace statements in your code and view the output in the DebugPrint Monitor Win32 program.

Along the way, I cover the following important device driver topics.

• System threads

• Dispatcher objects: events, Mutexes, and semaphores

• Linked lists

• File I/O in drivers

• Queuing IRPs

• Basic cancel routines

• Win32 overlapped I/O requests

Design Specification

The main design requirement for the DebugPrint software is that test drivers can do formatted prints that appear in a user mode application running on the same PC as the driver. The software must work under Windows 98 and Windows 2000. It should be easy for developers to include trace statements in their code. They should be able to use trace statements in most types of driver code.

This specification does not include source level debugging or breakpoints.

Design Implementation

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×