/*++ Copyright (C) Microsoft Corporation, 1999 - 1999 Module Name: debug.c Abstract: Common code for debugging. Author: Keisuke Tsuchida (KeisukeT) Environment: kernel mode only Notes: Revision History: --*/ // // Includes // #include "stddef.h" #include "wdm.h" #include "debug.h" // // Globals // ULONG DebugTraceLevel = MIN_TRACE | DEBUG_FLAG_DISABLE; // ULONG DebugTraceLevel = MAX_TRACE | DEBUG_FLAG_DISABLE | TRACE_PROC_ENTER | TRACE_PROC_LEAVE; LONG AllocateCount = 0; ULONG DebugDumpMax = MAX_DUMPSIZE; PVOID MyAllocatePool( IN POOL_TYPE PoolType, IN ULONG ulNumberOfBytes ) /*++ Routine Description: Wrapper for pool allocation. Use tag to avoid heap corruption. Arguments: PoolType - type of pool memory to allocate ulNumberOfBytes - number of bytes to allocate Return Value: Pointer to the allocated memory --*/ { PVOID pvRet; DebugTrace(TRACE_PROC_ENTER,("MyAllocatePool: Enter.. Size = %d\n", ulNumberOfBytes)); pvRet = ExAllocatePoolWithTag(PoolType, ulNumberOfBytes, NAME_POOLTAG); #if DBG if(NULL == pvRet){ DebugTrace(TRACE_ERROR,("MyAllocatePool: ERROR!! Cannot allocate pool.\n")); } else { if(++AllocateCount > MAXNUM_POOL){ DebugTrace(TRACE_WARNING,("MyAllocatePool: WARNING!! Allocate called %dtimes more than Free\n", MAXNUM_POOL)); } DebugTrace(TRACE_STATUS,("MyAllocatePool: Count = %d\n", AllocateCount)); } #endif // DBG DebugTrace(TRACE_PROC_LEAVE,("MyAllocatePool: Leaving.. pvRet = %x\n", pvRet)); return pvRet; } VOID MyFreePool( IN PVOID pvAddress ) /*++ Routine Description: Wrapper for pool free. Check tag to avoid heap corruption Arguments: pvAddress - Pointer to the allocated memory Return Value: none. --*/ { DebugTrace(TRACE_PROC_ENTER,("USFreePool: Enter..\n")); #if DBG { ULONG ulTag; ulTag = *((PULONG)pvAddress-1); // if( (NAME_POOLTAG == ulTag) || (DebugTraceLevel & TRACE_IGNORE_TAG) ){ if(NAME_POOLTAG == ulTag){ if(--AllocateCount < 0){ DebugTrace(TRACE_WARNING,("MyFreePool: Warning!! Free called more than Allocate.\n")); } } else { DebugTrace(TRACE_WARNING,("MyFreePool: WARNING!! tag = %c%c%c%c\n", ((PUCHAR)&ulTag)[0], ((PUCHAR)&ulTag)[1], ((PUCHAR)&ulTag)[2], ((PUCHAR)&ulTag)[3] )); } } #endif ExFreePool(pvAddress); DebugTrace(TRACE_PROC_LEAVE,("MyFreePool: Leaving.. Return = NONE\n")); } #if DBG VOID MyDebugInit( IN PUNICODE_STRING pRegistryPath ) /*++ Routine Description: Read DebugTraceLevel key from driver's registry if exists. Arguments: pRegistryPath - pointer to a unicode string representing the path to driver-specific key in the registry Return Value: none. --*/ { HANDLE hDriverRegistry; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING unicodeKeyName; ULONG DataSize; PKEY_VALUE_PARTIAL_INFORMATION pValueInfo; NTSTATUS Status; DebugTrace(TRACE_PROC_ENTER,("MyDebugInit: Enter... \n")); // // Initialize local variables. // Status = STATUS_SUCCESS; hDriverRegistry = NULL; pValueInfo = NULL; DataSize = 0; // // Initialize object attribute and open registry key. // RtlZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); InitializeObjectAttributes(&ObjectAttributes, pRegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&hDriverRegistry, KEY_READ, &ObjectAttributes); if(!NT_SUCCESS(Status)){ DebugTrace(TRACE_ERROR,("MyDebugInit: ERROR!! Can't open driver registry key.\n")); goto MyDebugInit_return; } // // Read "DebugTraceLevel" key. // DebugTrace(TRACE_CRITICAL,("MyDebugInit: Query %wZ\\%ws.\n", pRegistryPath, REG_DEBUGLEVEL)); // // Query required size. // RtlInitUnicodeString(&unicodeKeyName, REG_DEBUGLEVEL); Status = ZwQueryValueKey(hDriverRegistry, &unicodeKeyName, KeyValuePartialInformation, NULL, 0, &DataSize); if( (Status != STATUS_BUFFER_OVERFLOW) && (Status != STATUS_BUFFER_TOO_SMALL) && (Status != STATUS_SUCCESS) ) { if(Status == STATUS_OBJECT_NAME_NOT_FOUND){ DebugTrace(TRACE_STATUS,("MyDebugInit: DebugTraceLevel doesn't exist. Use default(0x%x).\n", DebugTraceLevel)); } else { DebugTrace(TRACE_ERROR,("MyDebugInit: ERROR!! ZwQueryValueKey failed. Status=0x%x\n", Status)); } goto MyDebugInit_return; } // // Check size of data. // if (MAX_TEMPBUF < DataSize) { DebugTrace(TRACE_ERROR, ("MyDebugInit: ERROR!! DataSize (0x%x) is too big.\n", DataSize)); goto MyDebugInit_return; } if (0 == DataSize) { DebugTrace(TRACE_ERROR, ("MyDebugInit: ERROR!! Cannot retrieve required data size.\n")); goto MyDebugInit_return; } // // Allocate memory for temp buffer. size +2 for NULL. // pValueInfo = MyAllocatePool(NonPagedPool, DataSize+2); if(NULL == pValueInfo){ DebugTrace(TRACE_CRITICAL, ("MyDebugInit: ERROR!! Buffer allocate failed.\n")); Status = STATUS_INSUFFICIENT_RESOURCES; goto MyDebugInit_return; } RtlZeroMemory(pValueInfo, DataSize+2); // // Query specified value. // Status = ZwQueryValueKey(hDriverRegistry, &unicodeKeyName, KeyValuePartialInformation, pValueInfo, DataSize, &DataSize); if(!NT_SUCCESS(Status)){ DebugTrace(TRACE_ERROR, ("MyDebugInit: ERROR!! ZwQueryValueKey failed.\n")); goto MyDebugInit_return; } // // Set DebugTraceLevel. // DebugTraceLevel = *((PULONG)pValueInfo->Data); DebugTrace(TRACE_CRITICAL, ("MyDebugInit: Reg-key found. DebugTraceLevel=0x%x.\n", *((PULONG)pValueInfo->Data))); MyDebugInit_return: // // Clean up. // if(pValueInfo){ MyFreePool(pValueInfo); } if(NULL != hDriverRegistry){ ZwClose(hDriverRegistry); } DebugTrace(TRACE_PROC_LEAVE,("MyDebugInit: Leaving... Status=0x%x, Ret=VOID.\n", Status)); return; } VOID MyDumpMemory( PUCHAR pDumpBuffer, ULONG dwSize, BOOLEAN bRead ) { NTSTATUS Status; ULONG ulCounter; ULONG ulMaxSize; // // Check the flag first. // if(bRead){ if(!(DebugTraceLevel & TRACE_FLAG_DUMP_READ)){ return; } } else { // if(bRead) if(!(DebugTraceLevel & TRACE_FLAG_DUMP_WRITE)){ return; } } // if(bRead) DebugTrace(TRACE_PROC_ENTER,("MyDebugDump: Enter... \n")); // // Initialize local. // Status = STATUS_SUCCESS; ulCounter = 0; ulMaxSize = DebugDumpMax; // // Check the arguments. // if(NULL == pDumpBuffer){ DebugTrace(TRACE_WARNING,("MyDebugDump: WARNING!! pDumpBuffer = NULL \n")); Status = STATUS_INVALID_PARAMETER_1; goto MyDumpMemory_return; } if(0 == dwSize){ DebugTrace(TRACE_STATUS,("MyDebugDump: WARNING!! dwSize = 0 \n")); Status = STATUS_INVALID_PARAMETER_2; goto MyDumpMemory_return; } if(bRead){ DebugTrace(TRACE_ERROR,("MyDebugDump: Received buffer. Size=0x%x.\n", dwSize)); } else { DebugTrace(TRACE_ERROR,("MyDebugDump: Passing buffer. Size=0x%x.\n", dwSize)); } /* // // Probe the buffer. // try { ProbeForRead(pDumpBuffer, dwSize, sizeof(UCHAR)); } except(EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DebugTrace(TRACE_ERROR,("MyDebugDump: Buffer pointer (0x%x) is invalid. Status=0x%x\n", pDumpBuffer, Status)); goto MyDumpMemory_return; } // except */ // // Max dump size = 1k; // ulMaxSize = min(ulMaxSize , dwSize); // // Dump the buffer. // for(ulCounter = 0; ulCounter < ulMaxSize; ulCounter++){ if(0 == (ulCounter & 0xfF)){ DbgPrint("\n"); DbgPrint(NAME_DRIVER); DbgPrint(" +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f\n"); DbgPrint(NAME_DRIVER); DbgPrint("------------------------------------------------------------\n"); } if(0 == (ulCounter & 0xf)){ DbgPrint(NAME_DRIVER); DbgPrint("%p :", pDumpBuffer+ulCounter); } DbgPrint(" %02x", *(pDumpBuffer+ulCounter)); if(0x7 == (ulCounter & 0xf)){ DbgPrint(" -"); } if(0xf == (ulCounter & 0xf)){ DbgPrint("\n"); } } DbgPrint("\n"); DbgPrint(NAME_DRIVER); DbgPrint("------------------------------------------------------------\n\n"); MyDumpMemory_return: DebugTrace(TRACE_PROC_LEAVE,("MyDebugDump: Leaving... Status=0x%x, Ret=VOID.\n", Status)); return; } // MyDumpMemory( #endif // DBG