//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1998 // // File: debug.c // //-------------------------------------------------------------------------- #ifdef DBG #include "wdmsys.h" #pragma LOCKED_CODE #pragma LOCKED_DATA //----------------------------------------------------------------------------- // Globals that affect debug output: //----------------------------------------------------------------------------- // // NOTE: The documentation expects uiDebugBreakLevel to follow uiDebugLevel // in the data segment. Thus, do not put any variables between these two. // // Default to displaying all "Warning" messages UINT uiDebugLevel = DL_ERROR ; // This should be DL_WARNING // Default to breaking on all "Error" messages UINT uiDebugBreakLevel = DL_ERROR ; char szReturningErrorStr[]="Returning Status %X"; VOID GetuiDebugLevel() { // // This should read from the registry! // uiDebugLevel=DL_ERROR; //FA_NOTE|FA_HARDWAREEVENT|DL_TRACE; } VOID wdmaudDbgBreakPoint() { DbgBreakPoint(); } #define DEBUG_IT // // This routine will format the start of the string. But, before it does that // it will check to see if the user should even be seeing this message. // // uiMsgLevel is the flags in the code that classify the message. This value // is used if and only if the user is filtering on that class of messages. // UINT wdmaudDbgPreCheckLevel(UINT uiMsgLevel,char *pFunction, int iLine) { UINT uiRet=0; // // If path trap, tag it and move on. // if( (uiMsgLevel&DL_MASK) == DL_PATHTRAP ) { uiRet=1; } else { // // Read this like: if there is a bit set in the upper 3 bytes of the uiDebugLevel // variable, then the user is viewing messages of a specific type. We only // want to show those messages. // if( (uiDebugLevel&FA_MASK) ) { // // Yes, the user filtering on a particular class of messages. Did // we find one to display? We look at the message flags to determine this. // if( (uiMsgLevel&FA_MASK) & (uiDebugLevel&FA_MASK) ) { // // Yes, we found a message of the right class. Is it at the right // level for the user to see? // if( (uiMsgLevel&DL_MASK) <= (uiDebugLevel&DL_MASK) ) { // Yes. uiRet=1; } } // // But, we always want to break on DL_ERROR messages. So, if we get here // we want to break on particular output messages but we may not have found // one. Is this message a error message? // if( (uiMsgLevel&DL_MASK) == DL_ERROR ) uiRet=1; } else { // // Now check to see if the return bit is set // if(uiMsgLevel&RT_RETURN) { // we're dealing with return statement in the code. We need to // figure out what our debug level is to see if this code gets // viewed or not. // switch(uiMsgLevel&RT_MASK) { case RT_ERROR: if( (uiDebugLevel&DL_MASK) >= DL_WARNING ) { uiRet=1; } break; case RT_WARNING: if( (uiDebugLevel&DL_MASK) >= DL_TRACE ) { uiRet=1; #ifdef DEBUG_IT DbgPrint("Yes Return Warning %X %X\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK)); #endif } break; case RT_INFO: case 0: //SUCCESS if( (uiDebugLevel&DL_MASK) >= DL_MAX ) { uiRet=1; #ifdef DEBUG_IT DbgPrint("Yes Return Status %X %X\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK)); #endif } break; default: #ifdef DEBUG_IT DbgPrint("No Return %X&RT_MASK != %X&DL_MASK\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK)); #endif break; } } else { // The user is not viewing a specific type of message "class". Do we have // a message level worth displaying? if( (uiMsgLevel&DL_MASK) <= (uiDebugLevel&DL_MASK) ) { // Yes. uiRet=1; } } } } // Now just check to see if we need to display on this call. if( uiRet ) { // Yes. Every message needs to start where it's from! DbgPrint("WDMAUD.SYS %s(%d) ",pFunction, iLine); // Now lable it's type. switch(uiMsgLevel&DL_MASK) { case DL_ERROR: // for return status messages, the level is not set in the // uiMsgLevel in the normal way. Thus, we need to look for it. if( uiMsgLevel&RT_RETURN ) { // we have a return message. switch(uiMsgLevel&RT_MASK ) { case RT_ERROR: DbgPrint("Ret Error "); break; case RT_WARNING: DbgPrint("Ret Warning "); break; case RT_INFO: DbgPrint("Ret Info "); break; default: DbgPrint("Ret Suc "); break; } } else { DbgPrint("Error "); } break; case DL_WARNING: DbgPrint("Warning "); break; case DL_TRACE: DbgPrint("Trace "); break; case DL_MAX: DbgPrint("Max "); break; case DL_PATHTRAP: DbgPrint("Path Trap "); break; default: break; } // when uiRet is positive, we've displayed the header info. Tell the // macro that we're in display mode. } return uiRet; } UINT wdmaudDbgPostCheckLevel(UINT uiMsgLevel) { UINT uiRet=0; // Always finish the line. #ifdef HTTP DbgPrint(" &DL=%08X, see \\\\debugtips\\msgs\\wdmauds.htm\n",&uiDebugLevel); #else DbgPrint(" &DL=%08X\n",&uiDebugLevel); #endif // // uiDebugBreakLevel is set to DL_ERROR (0) by default. Any time we come // across an error message we will break in the debugger. If the user // wants to break on other messages, they can change uiDebugBreakLevel to // DL_WARNING, DL_TRACE or DL_MAX and break on any message of this level. // if( ( (uiMsgLevel&DL_MASK) <= uiDebugBreakLevel ) || ( (uiMsgLevel&DL_MASK) == DL_PATHTRAP ) ) { // The user wants to break on these messages. DbgBreakPoint(); uiRet = 1; } return uiRet; } typedef struct _MSGS { ULONG ulMsg; char *pString; } ERROR_MSGS, *PERROR_MSGS; #define MAPERR(_msg_) {_msg_,#_msg_}, ERROR_MSGS ReturnCodes[]={ MAPERR(STATUS_OBJECT_NAME_NOT_FOUND) MAPERR(STATUS_UNSUCCESSFUL) MAPERR(STATUS_INVALID_PARAMETER) MAPERR(STATUS_NOT_FOUND) MAPERR(STATUS_INVALID_DEVICE_REQUEST) MAPERR(STATUS_TOO_LATE) MAPERR(STATUS_NO_SUCH_DEVICE) MAPERR(STATUS_NOT_SUPPORTED) MAPERR(STATUS_DEVICE_OFF_LINE) MAPERR(STATUS_PROPSET_NOT_FOUND) MAPERR(STATUS_BUFFER_TOO_SMALL) MAPERR(STATUS_INVALID_BUFFER_SIZE) {0,NULL}, {0,"Not Mapped"} }; char * wdmaudReturnString(ULONG ulMsg) { PERROR_MSGS pTable=ReturnCodes; while(pTable->pString != NULL) { if(pTable->ulMsg==ulMsg) return pTable->pString; pTable++; } pTable++; return pTable->pString; } // // Sometimes there are return codes that are expected other then SUCCESS. We // need to be able to filter on them rather then displaying them. // #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) //#define va_start(ap,v) ap = (va_list)&v + _INTSIZEOF(v) #define va_start(ap,v) ap = (va_list)&v #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define va_end(ap) ap = (va_list)0 // // This routine simply walks the parameter list looking to see if status // matches any of the other parameters. Why? Well, sometimes error codes // are expected. Thus, you don't want to display an error if you are expecting // that error message. // // Do, to use this function, the first parameter represents how many unsigned long // parameters fallow. The first unsigned long "status" is that actual return // code. All the other unsigned longs are the exceptable error codes. // // wdmaudExclusionList(2, status, STATUS_INVALID_PARAMETER); // // wdmaudExlutionList(4, status, STATUS_INVALID_PARAMETER, // STATUS_NO_SUCH_DEVICE, // STATUS_INVALID_DEVICE_REQUEST); // // it returns 1 if status == any one of the supplied status codes. 0 otherwise. // int __cdecl wdmaudExclusionList(int lcount, unsigned long status,... ) { int count,i; int iFound=0; unsigned long value; unsigned long rstatus; va_list arglist; va_start(arglist, lcount); count = va_arg(arglist, int); rstatus = va_arg(arglist, unsigned long); for(i=1; idwSig != CONTEXT_SIGNATURE ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pWdmaContext->dwSig(%08X)",pWdmaContext->dwSig) ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { DPFBTRAP(); return FALSE; } } ///////////////////////////////////////////////////////////////////////////// // // IsValidDeviceInfo // // Validates that the pointer is a LPDEVICEINFO type. // BOOL IsValidDeviceInfo( IN LPDEVICEINFO pDeviceInfo ) { NTSTATUS Status=STATUS_SUCCESS; try { if( pDeviceInfo->DeviceNumber >= MAXNUMDEVS ) { DPF(DL_ERROR|FA_ASSERT,("DeviceNumber(%d) >= MAXNUMDEVS(%d)", pDeviceInfo->DeviceNumber,MAXNUMDEVS) ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { DPFBTRAP(); return FALSE; } } ///////////////////////////////////////////////////////////////////////////// // // ValidMixerObject // // Validates that the pointer is a MIXEROBJECT type. // BOOL IsValidMixerObject( IN PMIXEROBJECT pmxobj ) { NTSTATUS Status=STATUS_SUCCESS; try { if( pmxobj->dwSig != MIXEROBJECT_SIGNATURE ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->dwSig(%08X)",pmxobj->dwSig) ); Status=STATUS_UNSUCCESSFUL; } if( pmxobj->pfo == NULL ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->pfo(%08X)",pmxobj->pfo) ); Status=STATUS_UNSUCCESSFUL; } if( !IsValidMixerDevice(pmxobj->pMixerDevice) ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->pMixerDevice(%08X)",pmxobj->pMixerDevice) ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { DPFBTRAP(); Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { return FALSE; } } ///////////////////////////////////////////////////////////////////////////// // // ValidMixerDevice // // Validates that the pointer is a MIXERDEVICE type. // BOOL IsValidMixerDevice( IN PMIXERDEVICE pmxd ) { NTSTATUS Status=STATUS_SUCCESS; try { if( pmxd->dwSig != MIXERDEVICE_SIGNATURE ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pmxd->dwSig(%08X)",pmxd->dwSig) ); Status=STATUS_UNSUCCESSFUL; } if( !IsValidWdmaContext(pmxd->pWdmaContext) ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pmxd->pWdmaContext(%08X)",pmxd->pWdmaContext) ); Status=STATUS_UNSUCCESSFUL; } if( pmxd->pfo == NULL ) { DPF(DL_ERROR|FA_ASSERT,("fo NULL in MixerDevice") ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { return FALSE; } } ///////////////////////////////////////////////////////////////////////////// // // IsValidLine // // Validates that the pointer is a MXLLINE type. // BOOL IsValidLine( IN PMXLLINE pLine ) { NTSTATUS Status=STATUS_SUCCESS; try { if( ( pLine->SourceId == INVALID_ID ) || ( pLine->DestId == INVALID_ID ) ) { DPF(DL_ERROR|FA_ASSERT,("Bad SourceId(%08X) or DestId(%08X)", pLine->SourceId,pLine->DestId ) ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { DPFBTRAP(); return FALSE; } } ///////////////////////////////////////////////////////////////////////////// // // IsValidControl // // Validates that the pointer is a MXLCONTROL type. // BOOL IsValidControl( IN PMXLCONTROL pControl ) { NTSTATUS Status=STATUS_SUCCESS; // // Hack for contrls that fail to disable change notifications // if( pControl == LIVE_CONTROL ) { DPF(DL_WARNING|FA_NOTE,("Fake control in list!") ); return Status; } try { if( pControl->Tag != CONTROL_TAG ) { DPF(DL_ERROR|FA_ASSERT,("Invalid pControl(%08X)->Tag(%08X)",pControl,pControl->Tag) ); Status=STATUS_UNSUCCESSFUL; } } except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); } if( NT_SUCCESS(Status) ) { return TRUE; } else { return FALSE; } } #endif