Previous Topic Next Topic
 

While you are capturing I/O activity with busTRACE, you can also type in and insert your own message into the capture buffer. In addition, if you are a Windows software developer, you can also have your software communicate with busTRACE and have it insert any text into the capture buffer. This can help you document what is going on during the capture sequence.

For example, let's say you have written a file system driver for a removable media device. You start a busTRACE capture and insert the media. In your file system driver, you may want to inject messages into the capture buffer such as:

  • Initiating media mount process
  • New media detected
  • Media mount complete
  • etc.

By injecting these text messages, you can see the I/O activity that occurs before and after key events that you insert into the capture buffer.

There are two methods you can use to inject a text message into the busTRACE capture buffer. One is from a device driver; the other from a Windows application. Both methods are only valid if busTRACE is active capturing I/O activity.

Injecting Text Messages from a Device Driver

We provide a method for kernel drivers to inject a text message into the busTRACE capture buffer. When text messages are inserted into the buffer, they appear in the I/O Capture List window along with the time the message was sent.

Here is sample code:

typedef NTSTATUS (*PBT_ADD_STRING_DISPATCH) (IN LPCTSTR strMsg);

PBT_ADD_STRING_DISPATCH pMsgInjectFunc=NULL;

 

PFILE_OBJECT pFileObject = NULL;

PDEVICE_OBJECT pDeviceObject = NULL;

UNICODE_STRING NtDeviceName;

RtlInitUnicodeString ( &NtDeviceName, L"\\Device\\BUSTRC10" );

NTSTATUS nStatus = IoGetDeviceObjectPointer ( &NtDeviceName, FILE_ALL_ACCESS,

                                              &pFileObject, &pDeviceObject );

if ( NT_SUCCESS(nStatus) )

{

   PIRP Irp;

   KEVENT event;

   IO_STATUS_BLOCK ioStatus;

   NTSTATUS status;

 

   KeInitializeEvent(&event, NotificationEvent, FALSE);

   Irp = IoBuildDeviceIoControlRequest ( 0x80002034,

                                         pDeviceObject,

                                         NULL, 0 ,

                                         &pMsgInjectFunc, sizeof(pMsgInjectFunc),

                                         FALSE,

                                         &event,

                                         &ioStatus );

   if ( Irp )

   {

      status = IoCallDriver(pDeviceObject, Irp);

      if (status == STATUS_PENDING)

      {

         KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,NULL);

         status = ioStatus.Status;

      }

      if ( NT_SUCCESS(status) && pMsgInjectFunc)

      {

         // At this point, you have our message inject API that you can call directly.

         // You can call this function at IRQL <= DISPATCH_LEVEL. In this example,

         // we'll go ahead and insert a "test" message here.

 

         status = pMsgInjectFunc("This is a test");

 

         // If a value of 0xE0008007 is returned, then a busTRACE capture

         // is not active.

      }

   }

}

Injecting Text Messages from a Windows Application

If you have written a Windows application (i.e. ring 3 application), you can inject a text message into the busTRACE capture buffer by submitting an IOCTL to our driver. The best way to describe this is by way of sample source code.

HANDLE hBustrace = ::CreateFile ( "\\\\.\\bustrc10",

                                  GENERIC_WRITE|GENERIC_READ,

                                  FILE_SHARE_READ|FILE_SHARE_WRITE,

                                  NULL, OPEN_EXISTING, NULL, NULL );

if ( hBustrace != INVALID_HANDLE_VALUE )

{

   char* strMessage = "Submitting this text message to busTRACE!";

 

   // You *MUST* include the NULL terminator in the byte count as we do below

   DWORD nBytesReturned = 0;

   BOOL bStatus = ::DeviceIoControl ( hBustrace,

                                      0x80002024,

                                      strMessage,

                                      (ULONG)(strlen(strMessage)+1),

                                      NULL,

                                      NULL,

                                      &nBytesReturned,

                                      NULL );

   if ( bStatus )

   {

      // If here, messages was injected successfully

   }

   else

   {

      HRESULT hr = ::GetLastError();

      // If a value of 0xE0008007 is returned, then a busTRACE capture

      // is not active.

   }

 

   ::CloseHandle(hBustrace);

}

The sample code is relatively straight-forward. The sequence of events are as follows:

  1. We start by using CreateFile to get a handle to the busTRACE driver. If this call returns INVALID_HANDLE_VALUE, then the busTRACE driver is not resident on this system.
  2. We then use DeviceIoControl to submit the IOCTL request to the driver. You use an IOCTL value of 0x80002024 to submit the request. Notice how we also submit a pointer to the text message we want to inject as well as its buffer length.

The call to DeviceIoControl will fail with an error code of 0xE0008007 if the busTRACE capture is not active. If a successful status is returned, then the text message has been "injected" into the busTRACE capture buffer.

See Also: