This example shows how to write a simple WinDbg extension DLL. The code is contained on the accompanying CD and on the book's web site: http://www.W2KDriverBook.com. The purpose of the extension is to provide one command: !devext that formats and displays the driver's Device Extension data structure. DBG.CAll the code for this extension resides in a single source file. Of course, the file #includes other files, but they are sourced from elsewhere, such as the driver. HEADERThis part of the code contains the definitions for the extension DLL. // The ordering of #include files is important #include <ntddk.h> #include <windef.h> // The following items are from WINBASE.H // in the Win32 SDK. (WINBASE.H itself can't // coexist with NTDDK.H, yet we need to be // able to get at DDK and driver-defined data // structures and types.) #define LMEM_FIXED 0x0000 #define LMEM_MOVEABLE 0x0002 #define LMEM_NOCOMPACT 0x0010 #define LMEM_NODISCARD 0x0020 #define LMEM_ZEROINIT 0x0040 #define LMEM_MODIFY 0x0080 #define LMEM_DISCARDABLE 0x0F00 #define LMEM_VALID_FLAGS 0x0F72 #define LMEM_INVALID_HANDLE 0x8000 #define LPTR (LMEM_FIXED | LMEM_ZEROINIT) #define WINBASEAPI WINBASEAPI HLOCAL WINAPI LocalAlloc( UINT uFlags, UINT uBytes ); WINBASEAPI HLOCAL WINAPI LocalFree( HLOCAL hMem ); #define CopyMemory RtlCopyMemory #define FillMemory RtlFillMemory #define ZeroMemory RtlZeroMemory // Now we can bring in the WINDBG extension // definitions... #include <wdbgexts.h> // Other header files... #include <stdlib.h> #include <string.h> // Driver-specific header file... #include ..\driver\xxdriver.h GLOBALSThese global variables are necessary for the proper operation of the extension library. // Structure passed back from ExtensionApiVersion static EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 }; // Holds callback function table from WinDbgExtensionDllInit static WINDBG_EXTENSION_APIS ExtensionApis; // Holds Windows 2000 build info - Major & Minor numbers static USHORT SavedMajorVersion; static USHORT SavedMinorVersion; REQUIRED FUNCTIONSThese functions perform the required initialization interaction with WinDbg. VOID WinDbgExtensionDllInit( PWINDBG_EXTENSION_APIS lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion ) { // Save pointer to the table of utility // functions provided by WinDbg ExtensionApis = *lpExtensionApis; // Save information about the version of // NT that's being debugged SavedMajorVersion = MajorVersion; SavedMinorVersion = MinorVersion; return; } VOID CheckVersion( VOID ) { // Your version-checking code goes here // dprintf( CheckVersion called... [%1x;%d]\n, SavedMajorVersion, SavedMinorVersion ); } LPEXT_API_VERSION ExtensionApiVersion( VOID ) { return &ApiVersion; } COMMAND ROUTINESThe one command supported by this sample DLL prints the contents of the Device Extension for an associated driver. It illustrates how to access memory on the system being debugged. DECLARE_API(devext) { DWORD dwBytesRead; DWORD dwAddress; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; // Get memory for Device object buffer if(( pDevObj = (PDEVICE_OBJECT) malloc ( sizeof( DEVICE_OBJECT ))) == NULL ) { dprintf( "Can't allocate buffer.\n" ); return; } // Get address of Device object from command line dwAddress = GetExpression( args ); if( !ReadMemory( dwAddress, pDevObj, sizeof( DEVICE_OBJECT ), &dwBytesRead )) { dprintf( "Can't get Device object.\n "); free( pDevObj ); return; } // Get memory for Device Extension buffer if( (pDevExt = (PDEVICE_OBJECT) malloc ( sizeof( DEVICE_EXTENSION ))) == NULL ) { dprintf( "Can't allocate buffer.\n" ); free( pDevObj ); return; } // Use Device object to get Device Extension if( !ReadMemory( (DWORD)pDevObj->DeviceExtension, pDevExt, sizeof( DEVICE_EXTENSION ), &dwBytesRead )) { dprintf( "Can't get Device Extension.\n "); free( pDevExt ); free( pDevObj ); return; } // Print out interesting values dprintf( "BytesRequested: %d\n" "BytesRemaining: %d\n" "TimeoutCounter: %d\n" "DeviceObject: %8x\n", pDevExt->BytesRequested, pDevExt->BytesRemaining, pDevExt->TimeoutCounter, pDevExt->DeviceObject ); // Clean up and go free( pDevExt ); free( pDevObj ); } SAMPLE OUTPUTHere is a sample of the output produced by the DBG extension DLL. > !load dbg ; dbg.DLL must be in the standard DLL ;path for Windows 2000 Debugger extension library [dbg] loaded > !devext ff58bc40 CheckVersion called... [f;2195] BytesRequested: 0 BytesRemaining: 0 TimeoutCounter: 0 DeviceObject: ff58bc40 > !unload dbg > Extension DLL dbg unloaded
|