/***************************************************************************** * portclsd.cpp - Portcls WinDbg/KD Debugger Extensions ***************************************************************************** * Copyright (c) 1998 Microsoft Corporation */ #include "precomp.h" #define PC_KDEXT typedef enum _PCKD_PORTTYPE { Topology = 0, WaveCyclic, WavePci, Midi, UnknownPort } PCKD_PORTTYPE; #define MAPPED_QUEUE 0 #define LOCKED_QUEUE 1 #define PRELOCK_QUEUE 2 #define MAX_QUEUES 3 typedef union _PORTCLS_FLAGS { struct { ULONG PortDump : 1; ULONG FilterDump : 1; ULONG PinDump : 1; ULONG DeviceContext : 1; ULONG PowerInfo : 1; ULONG Reserved1 : 3; ULONG Verbose : 1; ULONG ReallyVerbose : 1; ULONG Reserved : 22; }; ULONG Flags; } PORTCLS_FLAGS; typedef struct _PCKD_IRPSTREAM_ENTRY { LIST_ENTRY ListEntry; PVOID Irp; ULONG QueueType; } PCKD_IRP_ENTRY; typedef struct _PCKD_PIN_ENTRY { LIST_ENTRY ListEntry; LIST_ENTRY IrpList; PVOID PinData; PVOID IrpStreamData; ULONG PinInstanceId; } PCKD_PIN_ENTRY; typedef struct _PCKD_FILTER_ENTRY { LIST_ENTRY ListEntry; LIST_ENTRY PinList; PVOID FilterData; ULONG FilterInstanceId; } PCKD_FILTER_ENTRY; typedef struct _PCKD_PORT { LIST_ENTRY FilterList; PCKD_PORTTYPE PortType; PVOID PortData; } PCKD_PORT; typedef struct { ULONG64 Create; ULONG64 Context; UNICODE_STRING ObjectClass; ULONG64 ObjectClassBuffer; ULONG64 SecurityDescriptor; ULONG Flags; } KSOBJECT_CREATE_ITEM_READ, *PKSOBJECT_CREATE_ITEM_READ; typedef struct _PCKD_SUBDEVICE_ENTRY { LIST_ENTRY ListEntry; PCKD_PORT Port; ULONG64 CreateItemAddr; KSOBJECT_CREATE_ITEM_READ CreateItem; } PCKD_SUBDEVICE_ENTRY; #define TranslateDevicePower( x ) \ ( x == PowerDeviceD0 ? "PowerDeviceD0" : \ x == PowerDeviceD1 ? "PowerDeviceD1" : \ x == PowerDeviceD2 ? "PowerDeviceD2" : \ x == PowerDeviceD3 ? "PowerDeviceD3" : "Unknown" ) #define TranslateSystemPower( x ) \ ( x == PowerSystemWorking ? "PowerSystemWorking" : \ x == PowerSystemSleeping1 ? "PowerSystemSleeping1" : \ x == PowerSystemSleeping2 ? "PowerSystemSleeping2" : \ x == PowerSystemSleeping3 ? "PowerSystemSleeping3" : \ x == PowerSystemHibernate ? "PowerSystemHibernate" : \ x == PowerSystemShutdown ? "PowerSystemShutdown" : "Unknown" ) #define TranslateKsState( x ) \ ( x == KSSTATE_STOP ? "KSSTATE_STOP" : \ x == KSSTATE_ACQUIRE ? "KSSTATE_ACQUIRE" : \ x == KSSTATE_PAUSE ? "KSSTATE_PAUSE" : \ x == KSSTATE_RUN ? "KSSTATE_RUN" : "Unknown" ) #define TranslateKsDataFlow( x ) \ ( x == KSPIN_DATAFLOW_IN ? "KSPIN_DATAFLOW_IN" : \ x == KSPIN_DATAFLOW_OUT ? "KSPIN_DATAFLOW_OUT" : "Unknown" ) #define TranslateQueueType( x ) \ ( x == PRELOCK_QUEUE ? "P" : \ x == LOCKED_QUEUE ? "L" : \ x == MAPPED_QUEUE ? "M" : "U" ) /********************************************************************** * Forward References ********************************************************************** */ BOOL PCKD_ValidateDevObj ( PDEVICE_CONTEXT DeviceContext ); VOID PCKD_AcquireDeviceData ( PDEVICE_CONTEXT DeviceContext, PLIST_ENTRY SubdeviceList, ULONG Flags ); VOID PCKD_DisplayDeviceData ( PDEVICE_CONTEXT DeviceContext, PLIST_ENTRY SubdeviceList, ULONG Flags ); VOID PCKD_FreeDeviceData ( PLIST_ENTRY SubdeviceList ); VOID PCKD_AcquireIrpStreamData ( PVOID PinEntry, CIrpStream *RemoteIrpStream, CIrpStream *LocalIrpStream ); /********************************************************************** * DECLARE_API( portcls ) ********************************************************************** * Description: * Dumps PortCls data given the device object (FDO) of a PortCls * bound DevObj. * * Arguments: * args - address flags * * Return Value: * None */ extern "C" DECLARE_API( portcls ) { ULONG64 memLoc; ULONG result; CHAR buffer[256]; PORTCLS_FLAGS flags; LIST_ENTRY SubdeviceList; ULONG64 DeviceExtension; buffer[0] = '\0'; flags.Flags = 0; // // get the arguments // if( !*args ) { memLoc = EXPRLastDump; } else { if (GetExpressionEx(args, &memLoc, &args)) { StringCchCopy(buffer, sizeof(buffer), args); } } flags.Flags = 0; if ('\0' != buffer[0]) { flags.Flags = GetExpression(buffer); } // // print out info // dprintf("Dump Portcls DevObj Info %p %x \n", memLoc, flags.Flags ); // // get the DevObj data // if( memLoc ) { if( GetFieldValue( memLoc, "DEVICE_OBJECT", "DeviceExtension", DeviceExtension ) ) { dprintf("Could not read DevObj data\n"); return E_INVALIDARG; } } else { dprintf("\nSYNTAX: !portcls [flags]\n"); } // // check for device extension // if( !DeviceExtension ) { dprintf("DevObj has no device extension\n"); return E_INVALIDARG; } // // get the device context // if( InitTypeRead( DeviceExtension, "DEVICE_CONTEXT" ) ) { dprintf("Could not read DevObj device extension\n"); return E_INVALIDARG; } // // validate the DevObj // if( !PCKD_ValidateDevObj( DeviceExtension ) ) { dprintf("DevObj not valid or not bound to PortCls\n"); return E_INVALIDARG; } // // initialize the subdevice list // InitializeListHead( &SubdeviceList ); // // acquire the device data // PCKD_AcquireDeviceData( DeviceExtension, &SubdeviceList, flags.Flags ); // // display the requested info // PCKD_DisplayDeviceData( DeviceExtension, &SubdeviceList, flags.Flags ); // // release the device data // PCKD_FreeDeviceData( &SubdeviceList ); return S_OK; } /********************************************************************** * PCKD_ValidateDevObj ********************************************************************** * Description: * This routine attempts to validate whether or not a given device * extension is from a PortCls bound DevObj. * * Arguments: * PDEVICE_CONTEXT DeviceContext * PORTCLS_FLAGS Flags * * Return Value: * BOOL TRUE = Valid, FALSE = Invalid */ BOOL PCKD_ValidateDevObj ( ULONG64 DeviceContext ) { UNREFERENCED_PARAMETER( DeviceContext ); // TODO - Validate device extension return TRUE; } /********************************************************************** * PCKD_AcquireDeviceData ********************************************************************** * Description: * This routine acquires device data given a validated device * context and builds a subdevice list contain all of the data. * * Arguments: * PDEVICE_CONTEXT DeviceContext * PLIST_ENTRY SubdeviceList * PORTCLS_FLAGS Flags * * Return Value: * None */ VOID PCKD_AcquireDeviceData ( ULONG64 DeviceContext, PLIST_ENTRY SubdeviceList, ULONG flags ) { ULONG SubdeviceIndex; PCKD_SUBDEVICE_ENTRY *SubdeviceEntry; ULONG64 CreateItems; ULONG64 CurrentCreateItemAddr; PKSOBJECT_CREATE_ITEM_READ ReadCreateItems; PKSOBJECT_CREATE_ITEM_READ CurrentCreateItem; PWSTR Buffer; ULONG Size; ULONG Result; ANSI_STRING AnsiString; PLIST_ENTRY ListEntry; PORTCLS_FLAGS Flags; ULONG ItemSz, MaxObjects; ULONG i; Flags.Flags = flags; ItemSz = GetTypeSize("KSOBJECT_CREATE_ITEM"); InitTypeRead(DeviceContext, DEVICE_CONTEXT); // allocate local memory for the create items table Size = (MaxObjects = (ULONG) ReadField(MaxObjects)) * sizeof(KSOBJECT_CREATE_ITEM_READ); ReadCreateItems = (PKSOBJECT_CREATE_ITEM_READ)LocalAlloc( LPTR, Size ); if( !ReadCreateItems ) { dprintf("** Unable to allocate create item table memory\n"); return; } CreateItems = ReadField(CreateItems); // copy the create items table to local memory for (i=0, CurrentCreateItemAddr=CreateItems; iCreate) ) { // allocate a subdevice list entry SubdeviceEntry = (PCKD_SUBDEVICE_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_SUBDEVICE_ENTRY) ); if( SubdeviceEntry ) { // initialize the port filter list InitializeListHead( &(SubdeviceEntry->Port.FilterList) ); // copy the create item data memcpy( &(SubdeviceEntry->CreateItem), CurrentCreateItem, sizeof(KSOBJECT_CREATE_ITEM_READ) ); // allocate memory for the unicode string buffer Buffer = (PWSTR)LocalAlloc( LPTR, CurrentCreateItem->ObjectClass.MaximumLength ); if( !Buffer ) { dprintf("** Unable to allocate unicode string buffer\n"); LocalFree( SubdeviceEntry ); break; } // read unicode string data if( !ReadMemory( CurrentCreateItem->ObjectClassBuffer, Buffer, CurrentCreateItem->ObjectClass.MaximumLength, &Result ) ) { dprintf("** Unable to read unicode string buffer (0x%p)\n",CurrentCreateItem->ObjectClassBuffer); LocalFree( Buffer ); LocalFree( SubdeviceEntry ); break; } // point the create item string to the local buffer // ????? SubdeviceEntry->CreateItem.ObjectClass.Buffer = Buffer; // determine port type by checking string // TODO: this should be done by the GUID // // convert to ansi RtlUnicodeStringToAnsiString( &AnsiString, &(SubdeviceEntry->CreateItem.ObjectClass), TRUE ); if( 0 == _stricmp( AnsiString.Buffer, "topology" ) ) { SubdeviceEntry->Port.PortType = Topology; SubdeviceEntry->Port.PortData = NULL; } else if( 0 == _stricmp( AnsiString.Buffer, "wave" ) ) { SubdeviceEntry->Port.PortType = WaveCyclic; SubdeviceEntry->Port.PortData = NULL; } else if( (0 == _stricmp( AnsiString.Buffer, "uart") ) || (0 == _stricmp( AnsiString.Buffer, "fmsynth") ) ) { SubdeviceEntry->Port.PortType = Midi; SubdeviceEntry->Port.PortData = NULL; } else { SubdeviceEntry->Port.PortType = UnknownPort; SubdeviceEntry->Port.PortData = NULL; } // free the ansi string RtlFreeAnsiString( &AnsiString ); // add the subdevice entry to the subdevice list InsertTailList( SubdeviceList, &(SubdeviceEntry->ListEntry) ); } else { dprintf("** Unable to allocate subdevice memory\n"); } } } // free the create item table local storage LocalFree( ReadCreateItems ); // acquire the port, filter, and pin data if( (!IsListEmpty(SubdeviceList)) && (Flags.PortDump || Flags.FilterDump || Flags.PinDump) ) { for( ListEntry = SubdeviceList->Flink; ListEntry != SubdeviceList; ListEntry = ListEntry->Flink ) { SubdeviceEntry = (PCKD_SUBDEVICE_ENTRY *) ListEntry; // read basic port data PVOID Port; ULONG PortSize; switch( SubdeviceEntry->Port.PortType) { case Topology: Port = LocalAlloc( LPTR, sizeof(CPortTopology) ); if( !Port ) { dprintf("** Unable to allocate port memory\n"); break; } if( !ReadMemory( (ULONG)((CPortTopology *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))), Port, sizeof(CPortTopology), &Result ) ) { dprintf("** Unable to read port data\n"); LocalFree( Port ); Port = NULL; break; } break; case WaveCyclic: Port = LocalAlloc( LPTR, sizeof(CPortWaveCyclic) ); if( !Port ) { dprintf("** Unable to allocate port memory\n"); break; } if( !ReadMemory( (ULONG)((CPortWaveCyclic *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))), Port, sizeof(CPortWaveCyclic), &Result ) ) { dprintf("** Unable to read port data\n"); LocalFree( Port ); Port = NULL; break; } break; case WavePci: Port = LocalAlloc( LPTR, sizeof(CPortWavePci) ); if( !Port ) { dprintf("** Unable to allocate port memory\n"); break; } if( !ReadMemory( (ULONG)((CPortWavePci *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))), Port, sizeof(CPortWavePci), &Result ) ) { dprintf("** Unable to read port data\n"); LocalFree( Port ); Port = NULL; break; } break; case Midi: Port = LocalAlloc( LPTR, sizeof(CPortMidi) ); if( !Port ) { dprintf("** Unable to allocate port memory\n"); break; } if( !ReadMemory( (ULONG)((CPortMidi *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))), Port, sizeof(CPortMidi), &Result ) ) { dprintf("** Unable to read port data\n"); LocalFree( Port ); Port = NULL; break; } break; default: break; } // attach the port data to the subdevice entry SubdeviceEntry->Port.PortData = Port; switch( SubdeviceEntry->Port.PortType ) { case Topology: break; case WaveCyclic: { CPortWaveCyclic *PortWaveCyclic = (CPortWaveCyclic *)Port; // get the filter and pin data if( Flags.FilterDump || Flags.PinDump ) { ULONG Offset; ULONG PortBase; PLIST_ENTRY Flink; PLIST_ENTRY TempListEntry; ULONG PinNumber = 0; CPortPinWaveCyclic *PortPinWaveCyclic; CIrpStream *IrpStream; PCKD_PIN_ENTRY *CurrentPinEntry; BOOL NeedNewFilter; // get the offsets needed to walk the list Offset = FIELD_OFFSET(CPortWaveCyclic,m_PinList); PortBase = (ULONG)((CPortWaveCyclic *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))); // get the first pin pointer Flink = PortWaveCyclic->m_PinList.Flink; while (Flink != PLIST_ENTRY(PortBase + Offset)) { // allocate a pin list entry CurrentPinEntry = (PCKD_PIN_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_PIN_ENTRY) ); if( !CurrentPinEntry ) { dprintf("** Unable to allocate pin list entry\n"); break; } // initialize the pin entry InitializeListHead( &(CurrentPinEntry->IrpList) ); CurrentPinEntry->PinData = NULL; CurrentPinEntry->IrpStreamData = NULL; CurrentPinEntry->PinInstanceId = PinNumber++; // allocate local storage for the pin data PortPinWaveCyclic = (CPortPinWaveCyclic *)LocalAlloc( LPTR, sizeof(CPortPinWaveCyclic) ); if( !PortPinWaveCyclic ) { dprintf("** Unable to allocate pin data storage\n"); LocalFree( CurrentPinEntry ); break; } // read the pin data if( !ReadMemory( (ULONG)CONTAINING_RECORD(Flink, CPortPinWaveCyclic, m_PinListEntry), PortPinWaveCyclic, sizeof(CPortPinWaveCyclic), &Result ) ) { dprintf("** Unable to read pin data\n"); LocalFree( PortPinWaveCyclic ); LocalFree( CurrentPinEntry ); break; } // is there an irp stream if( PortPinWaveCyclic->m_IrpStream ) { // allocate local storage for the irp stream data IrpStream = (CIrpStream *)LocalAlloc( LPTR, sizeof(CIrpStream) ); if( IrpStream ) { // read the irp stream data if( !ReadMemory( (ULONG)((CIrpStream *)(PortPinWaveCyclic->m_IrpStream)), IrpStream, sizeof(CIrpStream), &Result ) ) { dprintf("** Unable to read irp stream data\n"); LocalFree( IrpStream ); } else { PCKD_AcquireIrpStreamData( CurrentPinEntry, (CIrpStream *)(PortPinWaveCyclic->m_IrpStream), IrpStream ); } } else { dprintf("** Unable to allocate irp stream storage\n"); } } // we need a new filter unless we find it in the filter list NeedNewFilter = TRUE; // is the filter list empty? if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { PLIST_ENTRY FilterListEntry; for( FilterListEntry = SubdeviceEntry->Port.FilterList.Flink; FilterListEntry != &(SubdeviceEntry->Port.FilterList); FilterListEntry = FilterListEntry->Flink ) { PCKD_FILTER_ENTRY *CurrentFilterEntry = (PCKD_FILTER_ENTRY *) FilterListEntry; if( CurrentFilterEntry->FilterInstanceId == (ULONG)(PortPinWaveCyclic->m_Filter) ) { // found our filter NeedNewFilter = FALSE; // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinWaveCyclic; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); } } } // do we need a new filter entry? if( NeedNewFilter ) { PCKD_FILTER_ENTRY *CurrentFilterEntry; // allocate a new filter entry CurrentFilterEntry = (PCKD_FILTER_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_FILTER_ENTRY) ); if(!CurrentFilterEntry) { dprintf("** Unable to allocate filter entry\n"); LocalFree( PortPinWaveCyclic ); if( CurrentPinEntry->IrpStreamData ) { LocalFree( CurrentPinEntry->IrpStreamData ); } // free up any irps in the irp list while(!IsListEmpty( &(CurrentPinEntry->IrpList))) { PCKD_IRP_ENTRY *IrpEntry = (PCKD_IRP_ENTRY *)RemoveTailList(&(CurrentPinEntry->IrpList)); LocalFree( IrpEntry ); } LocalFree( CurrentPinEntry ); break; } //initialize the new filter entry InitializeListHead( &(CurrentFilterEntry->PinList) ); CurrentFilterEntry->FilterData = NULL; CurrentFilterEntry->FilterInstanceId = (ULONG)(PortPinWaveCyclic->m_Filter); // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinWaveCyclic; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); /// add the filter entry to the port's filter list InsertTailList( &(SubdeviceEntry->Port.FilterList), &(CurrentFilterEntry->ListEntry) ); } // allocate list entry storage TempListEntry = (PLIST_ENTRY)LocalAlloc( LPTR, sizeof(LIST_ENTRY) ); if( TempListEntry ) { // read in the next list entry if( !ReadMemory( (ULONG)Flink, TempListEntry, sizeof(LIST_ENTRY), &Result ) ) { dprintf("** Unable to read temp list entry\n"); LocalFree(TempListEntry); break; } // update FLINK Flink = TempListEntry->Flink; // free the temp list entry LocalFree( TempListEntry ); } else { dprintf("** Unable to allocate temp list entry\n"); break; } } } } break; case WavePci: { CPortWavePci *PortWavePci = (CPortWavePci *)Port; // get the filter and pin data if( Flags.FilterDump || Flags.PinDump ) { ULONG Offset; ULONG PortBase; PLIST_ENTRY Flink; PLIST_ENTRY TempListEntry; ULONG PinNumber = 0; CPortPinWavePci *PortPinWavePci; CIrpStream *IrpStream; PCKD_PIN_ENTRY *CurrentPinEntry; BOOL NeedNewFilter; // get the offsets needed to walk the list Offset = FIELD_OFFSET(CPortWavePci,m_PinList); PortBase = (ULONG)((CPortWavePci *)((ISubdevice *)(SubdeviceEntry->CreateItem.Context))); // get the first pin pointer Flink = PortWavePci->m_PinList.Flink; while (Flink != PLIST_ENTRY(PortBase + Offset)) { // allocate a pin list entry CurrentPinEntry = (PCKD_PIN_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_PIN_ENTRY) ); if( !CurrentPinEntry ) { dprintf("** Unable to allocate pin list entry\n"); break; } // initialize the pin entry InitializeListHead( &(CurrentPinEntry->IrpList) ); CurrentPinEntry->PinData = NULL; CurrentPinEntry->IrpStreamData = NULL; CurrentPinEntry->PinInstanceId = PinNumber++; // allocate local storage for the pin data PortPinWavePci = (CPortPinWavePci *)LocalAlloc( LPTR, sizeof(CPortPinWavePci) ); if( !PortPinWavePci ) { dprintf("** Unable to allocate pin data storage\n"); LocalFree( CurrentPinEntry ); break; } // read the pin data if( !ReadMemory( (ULONG)CONTAINING_RECORD(Flink, CPortPinWavePci, m_PinListEntry), PortPinWavePci, sizeof(CPortPinWavePci), &Result ) ) { dprintf("** Unable to read pin data\n"); LocalFree( PortPinWavePci ); LocalFree( CurrentPinEntry ); break; } // is there an irp stream if( PortPinWavePci->m_IrpStream ) { // allocate local storage for the irp stream data IrpStream = (CIrpStream *)LocalAlloc( LPTR, sizeof(CIrpStream) ); if( IrpStream ) { // read the irp stream data if( !ReadMemory( (ULONG)((CIrpStream *)(PortPinWavePci->m_IrpStream)), IrpStream, sizeof(CIrpStream), &Result ) ) { dprintf("** Unable to read irp stream data\n"); LocalFree( IrpStream ); } else { PCKD_AcquireIrpStreamData( CurrentPinEntry, (CIrpStream *)(PortPinWavePci->m_IrpStream), IrpStream ); } } else { dprintf("** Unable to allocate irp stream storage\n"); } } // we need a new filter unless we find it in the filter list NeedNewFilter = TRUE; // is the filter list empty? if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { PLIST_ENTRY FilterListEntry; for( FilterListEntry = SubdeviceEntry->Port.FilterList.Flink; FilterListEntry != &(SubdeviceEntry->Port.FilterList); FilterListEntry = FilterListEntry->Flink ) { PCKD_FILTER_ENTRY *CurrentFilterEntry = (PCKD_FILTER_ENTRY *) FilterListEntry; if( CurrentFilterEntry->FilterInstanceId == (ULONG)(PortPinWavePci->Filter) ) { // found our filter NeedNewFilter = FALSE; // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinWavePci; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); } } } // do we need a new filter entry? if( NeedNewFilter ) { PCKD_FILTER_ENTRY *CurrentFilterEntry; // allocate a new filter entry CurrentFilterEntry = (PCKD_FILTER_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_FILTER_ENTRY) ); if(!CurrentFilterEntry) { dprintf("** Unable to allocate filter entry\n"); LocalFree( PortPinWavePci ); if( CurrentPinEntry->IrpStreamData ) { LocalFree( CurrentPinEntry->IrpStreamData ); } // free up any irps in the irp list while(!IsListEmpty( &(CurrentPinEntry->IrpList))) { PCKD_IRP_ENTRY *IrpEntry = (PCKD_IRP_ENTRY *)RemoveTailList(&(CurrentPinEntry->IrpList)); LocalFree( IrpEntry ); } LocalFree( CurrentPinEntry ); break; } //initialize the new filter entry InitializeListHead( &(CurrentFilterEntry->PinList) ); CurrentFilterEntry->FilterData = NULL; CurrentFilterEntry->FilterInstanceId = (ULONG)(PortPinWavePci->Filter); // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinWavePci; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); /// add the filter entry to the port's filter list InsertTailList( &(SubdeviceEntry->Port.FilterList), &(CurrentFilterEntry->ListEntry) ); } // allocate list entry storage TempListEntry = (PLIST_ENTRY)LocalAlloc( LPTR, sizeof(LIST_ENTRY) ); if( TempListEntry ) { // read in the next list entry if( !ReadMemory( (ULONG)Flink, TempListEntry, sizeof(LIST_ENTRY), &Result ) ) { dprintf("** Unable to read temp list entry\n"); LocalFree(TempListEntry); break; } // update FLINK Flink = TempListEntry->Flink; // free the temp list entry LocalFree( TempListEntry ); } else { dprintf("** Unable to allocate temp list entry\n"); break; } } } } break; case Midi: { CPortMidi *PortMidi = (CPortMidi *)Port; // get the filter and pin data if( Flags.FilterDump || Flags.PinDump ) { ULONG PinIndex; CPortPinMidi *PortPinMidi; CIrpStream *IrpStream; PCKD_PIN_ENTRY *CurrentPinEntry; BOOL NeedNewFilter; for( PinIndex = 0; PinIndex < PortMidi->m_PinEntriesUsed; PinIndex++ ) { if( PortMidi->m_Pins[ PinIndex] ) { // allocate a pin list entry CurrentPinEntry = (PCKD_PIN_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_PIN_ENTRY) ); if( !CurrentPinEntry ) { dprintf("** Unable to allocate pin list entry\n"); break; } // initialize the pin entry InitializeListHead( &(CurrentPinEntry->IrpList) ); CurrentPinEntry->PinData = NULL; CurrentPinEntry->PinInstanceId = (ULONG)(PortMidi->m_Pins[ PinIndex ]); // allocate local storage for the pin data PortPinMidi = (CPortPinMidi *)LocalAlloc( LPTR, sizeof(CPortPinMidi) ); if( !PortPinMidi ) { dprintf("** Unable to allocate pin data storage\n"); LocalFree( CurrentPinEntry ); break; } // read the pin data if( !ReadMemory( (ULONG)(PortMidi->m_Pins[ PinIndex ]), PortPinMidi, sizeof(CPortPinMidi), &Result ) ) { dprintf("** Unable to read pin data\n"); LocalFree( PortPinMidi ); LocalFree( CurrentPinEntry ); break; } // is there an irp stream if( PortPinMidi->m_IrpStream ) { // allocate local storage for the irp stream data IrpStream = (CIrpStream *)LocalAlloc( LPTR, sizeof(CIrpStream) ); if( IrpStream ) { // read the irp stream data if( !ReadMemory( (ULONG)(PortPinMidi->m_IrpStream), IrpStream, sizeof(CIrpStream), &Result ) ) { dprintf("** Unable to read irp stream data\n"); LocalFree( IrpStream ); } else { PCKD_AcquireIrpStreamData( CurrentPinEntry, (CIrpStream *)(PortPinMidi->m_IrpStream), IrpStream ); } } else { dprintf("** Unable to allocate irp stream storage\n"); } } // we need a new filter unless we find it in the filter list NeedNewFilter = TRUE; // is the filter list empty? if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { PLIST_ENTRY FilterListEntry; for( FilterListEntry = SubdeviceEntry->Port.FilterList.Flink; FilterListEntry != &(SubdeviceEntry->Port.FilterList); FilterListEntry = FilterListEntry->Flink ) { PCKD_FILTER_ENTRY *CurrentFilterEntry = (PCKD_FILTER_ENTRY *) FilterListEntry; if( CurrentFilterEntry->FilterInstanceId == (ULONG)(PortPinMidi->m_Filter) ) { // found our filter NeedNewFilter = FALSE; // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinMidi; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); } } } // do we need a new filter entry? if( NeedNewFilter ) { PCKD_FILTER_ENTRY *CurrentFilterEntry; // allocate a new filter entry CurrentFilterEntry = (PCKD_FILTER_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_FILTER_ENTRY) ); if(!CurrentFilterEntry) { dprintf("** Unable to allocate filter entry\n"); LocalFree( PortPinMidi ); if( CurrentPinEntry->IrpStreamData ) { LocalFree( CurrentPinEntry->IrpStreamData ); } // free up any irps in the irp list while(!IsListEmpty( &(CurrentPinEntry->IrpList))) { PCKD_IRP_ENTRY *IrpEntry = (PCKD_IRP_ENTRY *)RemoveTailList(&(CurrentPinEntry->IrpList)); LocalFree( IrpEntry ); } LocalFree( CurrentPinEntry ); break; } //initialize the new filter entry InitializeListHead( &(CurrentFilterEntry->PinList) ); CurrentFilterEntry->FilterData = NULL; CurrentFilterEntry->FilterInstanceId = (ULONG)(PortPinMidi->m_Filter); // add the pin data to the pin entry CurrentPinEntry->PinData = (PVOID)PortPinMidi; // add the pin entry to the filter's pin list InsertTailList( &(CurrentFilterEntry->PinList), &(CurrentPinEntry->ListEntry) ); /// add the filter entry to the port's filter list InsertTailList( &(SubdeviceEntry->Port.FilterList), &(CurrentFilterEntry->ListEntry) ); } } } } } break; default: break; } } } } /********************************************************************** * PCKD_DisplayDeviceData ********************************************************************** * Description: * This routine displays the requested device data on the debugger * given a valid device context and a subdevice list built with * PCKD_AcquireDeviceData. * Arguments: * PDEVICE_CONTEXT DeviceContext * PLIST_ENTRY SubdeviceList * PORTCLS_FLAGS Flags * * Return Value: * None */ VOID PCKD_DisplayDeviceData ( PDEVICE_CONTEXT DeviceContext, PLIST_ENTRY SubdeviceList, ULONG flags ) { PLIST_ENTRY SubdeviceListEntry; PCKD_SUBDEVICE_ENTRY *SubdeviceEntry; ANSI_STRING AnsiNameString; PORTCLS_FLAGS Flags; Flags.Flags = flags; dprintf("\n"); // dump misc device context information if( Flags.DeviceContext ) { dprintf("\n DEVICE INFO:\n"); dprintf(" PDO: 0x%x\n",DeviceContext->PhysicalDeviceObject); if( Flags.Verbose ) { if( Flags.ReallyVerbose ) { dprintf(" Max Objects: 0x%x\n",DeviceContext->MaxObjects); } dprintf(" Existing Objects: 0x%x\n",DeviceContext->ExistingObjectCount); dprintf(" Active Pin Count: 0x%x\n",DeviceContext->ActivePinCount); dprintf(" Pending IRP Count: 0x%x\n",DeviceContext->PendingIrpCount); } } // dump power management information if( Flags.PowerInfo ) { dprintf("\n POWER INFO:\n"); dprintf(" DeviceState: %s\n", TranslateDevicePower( DeviceContext->CurrentDeviceState ) ); dprintf(" SystemState: %s\n", TranslateSystemPower( DeviceContext->CurrentSystemState ) ); dprintf(" AdapterPower: 0x%x\n", DeviceContext->pAdapterPower ); if( Flags.Verbose && Flags.ReallyVerbose ) { ULONG index; dprintf(" Idle Timer: 0x%x\n", DeviceContext->IdleTimer ); dprintf(" Cons Idle Time: 0x%x\n", DeviceContext->ConservationIdleTime ); dprintf(" Perf Idle Time: 0x%x\n", DeviceContext->PerformanceIdleTime ); dprintf(" Idle Device State: %s\n", TranslateDevicePower( DeviceContext->IdleDeviceState ) ); dprintf(" State Mappings:\n"); for( index = 0; index < (ULONG)PowerSystemMaximum; index++ ) { dprintf(" %20s ==> %14s\n", TranslateSystemPower( index ), TranslateDevicePower( DeviceContext->DeviceStateMap[ index ] ) ); } } } // dump port/filter/pin information if( Flags.PortDump || Flags.FilterDump || Flags.PinDump ) { if( !IsListEmpty( SubdeviceList ) ) { // go through the subdevice list for( SubdeviceListEntry = SubdeviceList->Flink; SubdeviceListEntry != SubdeviceList; SubdeviceListEntry = SubdeviceListEntry->Flink ) { SubdeviceEntry = (PCKD_SUBDEVICE_ENTRY *)SubdeviceListEntry; switch( SubdeviceEntry->Port.PortType ) { case Topology: // dump port name dprintf("\n TOPOLOGY PORT:\n"); break; case WaveCyclic: // dump port name dprintf("\n WAVECYCLIC PORT:\n"); break; case WavePci: // dump port name dprintf("\n WAVEPCI PORT:\n"); break; case Midi: // dump port name dprintf("\n MIDI PORT:\n"); break; default: // dump port name dprintf("\n UNKNOWN PORT:\n"); break; } // print out the real name RtlUnicodeStringToAnsiString( &AnsiNameString, &(SubdeviceEntry->CreateItem.ObjectClass), TRUE ); dprintf(" Name: %s\n",AnsiNameString.Buffer); RtlFreeAnsiString( &AnsiNameString ); // dump the port instance dprintf(" Port Instance: 0x%x\n",SubdeviceEntry->CreateItem.Context); if( Flags.Verbose && Flags.ReallyVerbose ) { // dump generic port data dprintf(" Create: 0x%x\n",SubdeviceEntry->CreateItem.Create); dprintf(" Security: 0x%x\n",SubdeviceEntry->CreateItem.SecurityDescriptor); dprintf(" Flags: 0x%x\n",SubdeviceEntry->CreateItem.Flags); } // dump port type specific port data switch( SubdeviceEntry->Port.PortType ) { case Topology: { CPortTopology *port = (CPortTopology *)(SubdeviceEntry->Port.PortData); dprintf(" Miniport: 0x%x\n",port->Miniport); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Subdevice Desc: 0x%x\n",port->m_pSubdeviceDescriptor); dprintf(" Filter Desc: 0x%x\n",port->m_pPcFilterDescriptor); } } break; case WaveCyclic: { CPortWaveCyclic *port = (CPortWaveCyclic *)(SubdeviceEntry->Port.PortData); dprintf(" Miniport: 0x%x\n",port->Miniport); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Subdevice Desc: 0x%x\n",port->m_pSubdeviceDescriptor); dprintf(" Filter Desc: 0x%x\n",port->m_pPcFilterDescriptor); } } break; case WavePci: { CPortWavePci *port = (CPortWavePci *)(SubdeviceEntry->Port.PortData); dprintf(" Miniport: 0x%x\n",port->Miniport); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Subdevice Desc: 0x%x\n",port->m_pSubdeviceDescriptor); dprintf(" Filter Desc: 0x%x\n",port->m_pPcFilterDescriptor); } } break; case Midi: { CPortMidi *port = (CPortMidi *)(SubdeviceEntry->Port.PortData); dprintf(" Miniport: 0x%x\n",port->m_Miniport); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Subdevice Desc: 0x%x\n",port->m_pSubdeviceDescriptor); dprintf(" Filter Desc: 0x%x\n",port->m_pPcFilterDescriptor); } dprintf(" Pin Count: 0x%x\n",port->m_PinEntriesUsed); } break; default: break; } if( Flags.FilterDump || Flags.PinDump ) { // dump the filters if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { PLIST_ENTRY FilterListEntry; PCKD_FILTER_ENTRY *FilterEntry; // run through the filter list for( FilterListEntry = SubdeviceEntry->Port.FilterList.Flink; FilterListEntry != &(SubdeviceEntry->Port.FilterList); FilterListEntry = FilterListEntry->Flink ) { FilterEntry = (PCKD_FILTER_ENTRY *)FilterListEntry; dprintf(" Filter Instance: 0x%x\n",FilterEntry->FilterInstanceId); if( Flags.PinDump ) { // dump the pins if( !IsListEmpty( &(FilterEntry->PinList) ) ) { PLIST_ENTRY PinListEntry; PCKD_PIN_ENTRY *PinEntry; // run through the pin list for( PinListEntry = FilterEntry->PinList.Flink; PinListEntry != &(FilterEntry->PinList); PinListEntry = PinListEntry->Flink ) { PinEntry = (PCKD_PIN_ENTRY *)PinListEntry; dprintf(" Pin Instance: 0x%x\n",PinEntry->PinInstanceId); // dump the pin data switch( SubdeviceEntry->Port.PortType ) { case WaveCyclic: { CPortPinWaveCyclic *pin = (CPortPinWaveCyclic *)(PinEntry->PinData); if( pin ) { dprintf(" Miniport Stream: 0x%x\n",pin->m_Stream); dprintf(" Stream State: %s\n", TranslateKsState(pin->m_DeviceState)); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin ID: 0x%x\n",pin->m_Id); dprintf(" Commanded State: %s\n", TranslateKsState(pin->m_CommandedState)); dprintf(" Suspended: %s\n", pin->m_Suspended ? "TRUE" : "FALSE"); } dprintf(" Dataflow: %s\n",TranslateKsDataFlow( pin->m_DataFlow ) ); dprintf(" Data Format: 0x%x\n",pin->m_DataFormat); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin Desc: 0x%x\n",pin->m_Descriptor); } if( Flags.Verbose ) { dprintf(" Service Group: 0x%x\n",pin->m_ServiceGroup); dprintf(" Dma Channel: 0x%x\n",pin->m_DmaChannel); dprintf(" Irp Stream: 0x%x\n",pin->m_IrpStream); if( !IsListEmpty( &(PinEntry->IrpList) ) ) { PLIST_ENTRY IrpListEntry; PCKD_IRP_ENTRY *IrpEntry; // run through the irp list for( IrpListEntry = PinEntry->IrpList.Flink; IrpListEntry != &(PinEntry->IrpList); IrpListEntry = IrpListEntry->Flink ) { IrpEntry = (PCKD_IRP_ENTRY *)IrpListEntry; dprintf(" Irp: 0x%x (%s)\n",IrpEntry->Irp, TranslateQueueType(IrpEntry->QueueType)); } } } } } break; case WavePci: { CPortPinWavePci *pin = (CPortPinWavePci *)(PinEntry->PinData); if( pin ) { dprintf(" Miniport Stream: 0x%x\n",pin->Stream); dprintf(" Stream State: %s\n", TranslateKsState(pin->m_DeviceState)); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin ID: 0x%x\n",pin->Id); dprintf(" Commanded State: %s\n", TranslateKsState(pin->CommandedState)); dprintf(" Suspended: %s\n", pin->m_Suspended ? "TRUE" : "FALSE"); } //dprintf(" Dataflow: %s\n",TranslateKsDataFlow( pin->DataFlow ) ); dprintf(" Data Format: 0x%x\n",pin->DataFormat); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin Desc: 0x%x\n",pin->Descriptor); } if( Flags.Verbose ) { dprintf(" Service Group: 0x%x\n",pin->ServiceGroup); dprintf(" Dma Channel: 0x%x\n",pin->DmaChannel); dprintf(" Irp Stream: 0x%x\n",pin->m_IrpStream); } } } break; case Midi: { CPortPinMidi *pin = (CPortPinMidi *)(PinEntry->PinData); if( pin ) { dprintf(" Miniport Stream: 0x%x\n",pin->m_Stream); dprintf(" Stream State: %s\n", TranslateKsState(pin->m_DeviceState)); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin ID: 0x%x\n",pin->m_Id); dprintf(" Commanded State: %s\n", TranslateKsState(pin->m_CommandedState)); dprintf(" Suspended: %s\n", pin->m_Suspended ? "TRUE" : "FALSE"); } dprintf(" Dataflow: %s\n",TranslateKsDataFlow( pin->m_DataFlow ) ); dprintf(" Data Format: 0x%x\n",pin->m_DataFormat); if( Flags.Verbose && Flags.ReallyVerbose ) { dprintf(" Pin Desc: 0x%x\n",pin->m_Descriptor); } if( Flags.Verbose ) { dprintf(" Service Group: 0x%x\n",pin->m_ServiceGroup); dprintf(" Irp Stream: 0x%x\n",pin->m_IrpStream); } } } break; default: break; } } } else { dprintf(" No Pin Instances:\n"); } } } } } } } } return; } /********************************************************************** * PCKD_FreeDeviceData ********************************************************************** * Description: * This routine cleans up and frees the subdevice list. * Arguments: * PLIST_ENTRY SubdeviceList * * Return Value: * None */ VOID PCKD_FreeDeviceData ( PLIST_ENTRY SubdeviceList ) { PLIST_ENTRY SubdeviceListEntry; PLIST_ENTRY FilterListEntry; PLIST_ENTRY PinListEntry; PCKD_SUBDEVICE_ENTRY *SubdeviceEntry; PCKD_FILTER_ENTRY *FilterEntry; PCKD_PIN_ENTRY *PinEntry; if( !IsListEmpty( SubdeviceList ) ) { SubdeviceListEntry = RemoveHeadList( SubdeviceList ); while( SubdeviceListEntry ) { SubdeviceEntry = (PCKD_SUBDEVICE_ENTRY *) SubdeviceListEntry; // see if we have filters in the filter list if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { FilterListEntry = RemoveHeadList( &(SubdeviceEntry->Port.FilterList) ); while( FilterListEntry ) { FilterEntry = (PCKD_FILTER_ENTRY *)FilterListEntry; // see if we have pins in the pin list if( !IsListEmpty( &(FilterEntry->PinList) ) ) { PinListEntry = RemoveHeadList( &(FilterEntry->PinList) ); while( PinListEntry ) { PinEntry = (PCKD_PIN_ENTRY *)PinListEntry; // free the pin data if( PinEntry->PinData ) { LocalFree( PinEntry->PinData ); } // free the irp stream data if( PinEntry->IrpStreamData ) { LocalFree( PinEntry->IrpStreamData ); } // free up any irps in the irp list while( !IsListEmpty( &(PinEntry->IrpList) ) ) { PCKD_IRP_ENTRY *IrpEntry = (PCKD_IRP_ENTRY *)RemoveTailList(&(PinEntry->IrpList)); LocalFree( IrpEntry ); } // free the pin entry LocalFree( PinEntry ); // get the next pin if( !IsListEmpty( &(FilterEntry->PinList) ) ) { PinListEntry = RemoveTailList( &(FilterEntry->PinList) ); } else { PinListEntry = NULL; } } } // free the filter data if( FilterEntry->FilterData ) { LocalFree( FilterEntry->FilterData ); } // free the filter entry LocalFree( FilterEntry ); // get the next filter if( !IsListEmpty( &(SubdeviceEntry->Port.FilterList) ) ) { FilterListEntry = RemoveTailList( &(SubdeviceEntry->Port.FilterList) ); } else { FilterListEntry = NULL; } } } // free the port data if( SubdeviceEntry->Port.PortData ) { LocalFree( SubdeviceEntry->Port.PortData ); } // free the unicode string buffer LocalFree( SubdeviceEntry->CreateItem.ObjectClass.Buffer ); // free the subdevice entry LocalFree( SubdeviceEntry ); // on to the next subdevice if( !IsListEmpty( SubdeviceList ) ) { SubdeviceListEntry = RemoveTailList( SubdeviceList ); } else { SubdeviceListEntry = NULL; } } } return; } /********************************************************************** * PCKD_AcquireIrpStreamData ********************************************************************** * Description: * This routine acquires irp stream irp queue data. * Arguments: * PCKD_PIN_ENTRY *CurrentPinEntry * CIrpStream *RemoteIrpStream, * CIrpStream *LocalIrpStream * * Return Value: * None */ VOID PCKD_AcquireIrpStreamData ( PVOID PinEntry, CIrpStream *RemoteIrpStream, CIrpStream *LocalIrpStream ) { ULONG QueueType; PLIST_ENTRY Flink; PLIST_ENTRY TempListEntry; PIRP pIrp; PCKD_IRP_ENTRY *IrpEntry; ULONG Offset; ULONG Result; PCKD_PIN_ENTRY *CurrentPinEntry; CurrentPinEntry = (PCKD_PIN_ENTRY *)PinEntry; // processs the queues for( QueueType = MAPPED_QUEUE; QueueType < MAX_QUEUES; QueueType++ ) { switch( QueueType ) { case PRELOCK_QUEUE: Offset = FIELD_OFFSET(CIrpStream,PreLockQueue); Flink = LocalIrpStream->PreLockQueue.Flink; break; case LOCKED_QUEUE: Offset = FIELD_OFFSET(CIrpStream,LockedQueue); Flink = LocalIrpStream->LockedQueue.Flink; break; case MAPPED_QUEUE: Offset = FIELD_OFFSET(CIrpStream,MappedQueue); Flink = LocalIrpStream->MappedQueue.Flink; break; default: Flink = 0; break; } // walk the list (note we can't use IsListEmpty) while( (Flink) && (Flink != (PLIST_ENTRY)((PBYTE)RemoteIrpStream + Offset))) { // get the irp pointer pIrp = CONTAINING_RECORD( Flink, IRP, Tail.Overlay.ListEntry ); // allocate an irp entry IrpEntry = (PCKD_IRP_ENTRY *)LocalAlloc( LPTR, sizeof(PCKD_IRP_ENTRY) ); if( IrpEntry ) { // initialize the irp entry IrpEntry->QueueType = QueueType; IrpEntry->Irp = pIrp; // add the irp entry to the pin entry InsertTailList( &(CurrentPinEntry->IrpList), &(IrpEntry->ListEntry) ); } else { dprintf("** Unable to allocate irp entry\n"); } // allocate list entry storage TempListEntry = (PLIST_ENTRY)LocalAlloc( LPTR, sizeof(LIST_ENTRY) ); if( TempListEntry ) { // read in the next list entry if( !ReadMemory( (ULONG)Flink, TempListEntry, sizeof(LIST_ENTRY), &Result ) ) { dprintf("** Unable to read temp list entry\n"); LocalFree(TempListEntry); break; } // update FLINK Flink = TempListEntry->Flink; // free the temp list entry LocalFree( TempListEntry ); } else { dprintf("** Unable to allocate temp list entry\n"); break; } } } }