/*++ Copyright (c) 1995 Microsoft Corporation Module Name: DBGSRVIC.C Abstract: Devug services exported by USBD Environment: kernel mode only Notes: Revision History: 09-29-95 : created --*/ #include "wdm.h" #include "stdarg.h" #include "stdio.h" #include "usbdi.h" //public data structures #include "hcdi.h" #include "usbd.h" //private data strutures #if DBG // default debug trace level is 0 #ifdef DEBUG1 ULONG USBD_Debug_Trace_Level = 1; #else #ifdef DEBUG2 ULONG USBD_Debug_Trace_Level = 2; #else #ifdef DEBUG3 ULONG USBD_Debug_Trace_Level = 3; #else ULONG USBD_Debug_Trace_Level = 0; #endif /* DEBUG3 */ #endif /* DEBUG2 */ #endif /* DEBUG1 */ LONG USBDTotalHeapAllocated = 0; #endif /* DBG */ #ifdef DEBUG_LOG struct USBD_LOG_ENTRY { CHAR le_name[4]; // Identifying string ULONG_PTR le_info1; // entry specific info ULONG_PTR le_info2; // entry specific info ULONG_PTR le_info3; // entry specific info }; /* USBD_LOG_ENTRY */ struct USBD_LOG_ENTRY *LStart = 0; // No log yet struct USBD_LOG_ENTRY *LPtr; struct USBD_LOG_ENTRY *LEnd; #endif /* DEBUG_LOG */ VOID USBD_Debug_LogEntry( IN CHAR *Name, IN ULONG_PTR Info1, IN ULONG_PTR Info2, IN ULONG_PTR Info3 ) /*++ Routine Description: Adds an Entry to USBD log. Arguments: Return Value: None. --*/ { #ifdef DEBUG_LOG if (LStart == 0) return; if (LPtr > LStart) LPtr -= 1; // Decrement to next entry else LPtr = LEnd; RtlCopyMemory(LPtr->le_name, Name, 4); // LPtr->le_ret = (stk[1] & 0x00ffffff) | (CurVMID()<<24); LPtr->le_info1 = Info1; LPtr->le_info2 = Info2; LPtr->le_info3 = Info3; #endif /* DEBUG_LOG */ return; } #ifdef DEBUG_LOG VOID USBD_LogInit( ) /*++ Routine Description: Init the debug log - remember interesting information in a circular buffer Arguments: LogSize - maximum size of log in pages Return Value: None. --*/ { ULONG LogSize = 4096; //1 page of log entries LStart = ExAllocatePool(NonPagedPool, LogSize); if (LStart) { LPtr = LStart; // Point the end (and first entry) 1 entry from the end of the segment LEnd = LStart + (LogSize / sizeof(struct USBD_LOG_ENTRY)) - 1; } return; } #endif /* DEBUG_LOG */ // // tag buffer we use to mark heap blocks we allocate // typedef struct _HEAP_TAG_BUFFER { ULONG Sig; ULONG Length; } HEAP_TAG_BUFFER, *PHEAP_TAG_BUFFER; PVOID USBD_Debug_GetHeap( IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Signature, IN PLONG TotalAllocatedHeapSpace ) /*++ Routine Description: Debug routine, used to debug heap problems. We are using this since most NT debug functions are not supported by NTKERN. Arguments: PoolType - pool type passed to ExAllocatePool NumberOfBytes - number of bytes for item Signature - four byte signature supplied by caller TotalAllocatedHeapSpace - pointer to variable where client stores the total accumulated heap space allocated. Return Value: pointer to allocated memory --*/ { PUCHAR p; #ifdef DEBUG_HEAP ULONG *stk = NULL; PHEAP_TAG_BUFFER tagBuffer; // we call ExAllocatePoolWithTag but no tag will be added // when running under NTKERN #ifdef _M_IX86 _asm mov stk, ebp #endif p = (PUCHAR) ExAllocatePoolWithTag(PoolType, NumberOfBytes + sizeof(HEAP_TAG_BUFFER), Signature); if (p) { tagBuffer = (PHEAP_TAG_BUFFER) p; tagBuffer->Sig = Signature; tagBuffer->Length = NumberOfBytes; p += sizeof(HEAP_TAG_BUFFER); *TotalAllocatedHeapSpace += NumberOfBytes; } LOGENTRY((PUCHAR) &Signature, 0, 0, 0); #ifdef _M_IX86 LOGENTRY("GetH", p, NumberOfBytes, stk[1] & 0x00FFFFFF); #else LOGENTRY("GetH", p, NumberOfBytes, 0); #endif #else p = (PUCHAR) ExAllocatePoolWithTag(PoolType, NumberOfBytes, Signature); #endif /* DEBUG_HEAP */ return p; } VOID USBD_Debug_RetHeap( IN PVOID P, IN ULONG Signature, IN PLONG TotalAllocatedHeapSpace ) /*++ Routine Description: Debug routine, used to debug heap problems. We are using this since most NT debug functions are not supported by NTKERN. Arguments: P - pointer to free Return Value: none. --*/ { #ifdef DEBUG_HEAP PHEAP_TAG_BUFFER tagBuffer; ULONG *stk = NULL ; USBD_ASSERT(P != 0); #ifdef _M_IX86 _asm mov stk, ebp #endif tagBuffer = (PHEAP_TAG_BUFFER) ((PUCHAR)P - sizeof(HEAP_TAG_BUFFER)); *TotalAllocatedHeapSpace -= tagBuffer->Length; LOGENTRY((PUCHAR) &Signature, 0, 0, 0); #ifdef _M_IX86 LOGENTRY("RetH", P, tagBuffer->Length, stk[1] & 0x00FFFFFF); #else LOGENTRY("RetH", P, tagBuffer->Length, 0); #endif USBD_ASSERT(*TotalAllocatedHeapSpace >= 0); USBD_ASSERT(tagBuffer->Sig == Signature); // fill the buffer with bad data RtlFillMemory(P, tagBuffer->Length, 0xff); tagBuffer->Sig = USBD_FREE_TAG; // free the original block ExFreePool(tagBuffer); #else ExFreePool(P); #endif /* DEBUG_HEAP */ } #if DBG ULONG _cdecl USBD_KdPrintX( PCH Format, ... ) { va_list list; int i; int arg[5]; va_start(list, Format); for (i=0; i<4; i++) arg[i] = va_arg(list, int); DbgPrint(Format, arg[0], arg[1], arg[2], arg[3]); return 0; } VOID USBD_Warning( PUSBD_DEVICE_DATA DeviceData, PUCHAR Message, BOOLEAN DebugBreak ) { DbgPrint("USBD: Warning ****************************************************************\n"); if (DeviceData) { DbgPrint("Device PID %04.4x, VID %04.4x\n", DeviceData->DeviceDescriptor.idProduct, DeviceData->DeviceDescriptor.idVendor); } DbgPrint("%s", Message); DbgPrint("******************************************************************************\n"); if (DebugBreak) { DBGBREAK(); } } VOID USBD_Assert( IN PVOID FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCHAR Message ) /*++ Routine Description: Debug Assert function. Arguments: DeviceObject - pointer to a device object Irp - pointer to an I/O Request Packet Return Value: --*/ { #ifdef NTKERN // this makes the compiler generate a ret ULONG stop = 1; assert_loop: #endif // just call the NT assert function and stop // in the debugger. RtlAssert( FailedAssertion, FileName, LineNumber, Message ); // loop here to prevent users from going past // are assert before we can look at it #ifdef NTKERN DBGBREAK(); if (stop) { goto assert_loop; } #endif return; } #endif /* DBG */