#include "precomp.h" #pragma hdrstop MEMBER_VARIABLE_INFO _MemberInfo; #define STATE_FILENAME "tcpipext.state" STRUCTURE_TABLE StructureTable[] = { { NULL } }; BOOL NextListEntry( ULONG Current, PULONG Next ); BOOL PrevListEntry( ULONG Current, PULONG Prev ); VOID NextElement( PMEMBER_VARIABLE_INFO pMemberInfo ); VOID PrevElement( PMEMBER_VARIABLE_INFO pMemberInfo ); VOID DumpListItem( PMEMBER_VARIABLE_INFO pMemberInfo ); BOOL LocateMemberVariable ( PCHAR pchStructName, PCHAR pchMemberName, PVOID pvStructure, PMEMBER_VARIABLE_INFO pMemberInfo ) { BOOL bMatch; int index; PMEMBER_TABLE pMemberTable; CHAR pchCurrent[ MAX_LIST_VARIABLE_NAME_LENGTH + 1 ]; CHAR _pchStructName[ MAX_LIST_VARIABLE_NAME_LENGTH + 1 ]; CHAR _pchMemberName[ MAX_LIST_VARIABLE_NAME_LENGTH + 1 ]; dprintf( "LocateMemberVariable( \"%s\", \"%s\", 0x%08X )\n", pchStructName, pchMemberName, pMemberInfo ); strcpy( _pchStructName, pchStructName ); strcpy( _pchMemberName, pchMemberName ); _strupr( _pchStructName ); _strupr( _pchMemberName ); pMemberInfo->StructureIndex = 0; pMemberInfo->MemberIndex = 0; bMatch = FALSE; for ( index = 0; StructureTable[ index ].pchStructName != NULL; index ++ ) { strcpy( pchCurrent, StructureTable[ index ].pchStructName ); _strupr( pchCurrent ); if ( strstr( pchCurrent, _pchStructName )) { if ( bMatch ) { dprintf( "The specified structure name is ambiguous.\n" ); return( FALSE ); } pMemberInfo->StructureIndex = index; bMatch = TRUE; } } if ( !bMatch ) { dprintf( "No matching structure name was found.\n" ); return( FALSE ); } pMemberTable = StructureTable[ pMemberInfo->StructureIndex ].pMemberTable; bMatch = FALSE; for ( index = 0; pMemberTable[ index ].pchMemberName != NULL; index ++ ) { strcpy( pchCurrent, pMemberTable[ index ].pchMemberName ); _strupr( pchCurrent ); if ( strstr( pchCurrent, _pchMemberName )) { if ( bMatch ) { dprintf( "The variable specified is ambiguous.\n" ); return( FALSE ); } pMemberInfo->MemberIndex = index; bMatch = TRUE; } } if ( !bMatch ) { dprintf( "No matching member name was found in the %s structure.\n", pchStructName ); return( FALSE ); } pMemberInfo->prHeadContainingObject = ( ULONG )pvStructure; pMemberInfo->prHeadLinkage = (( ULONG )pvStructure ) + pMemberTable[ pMemberInfo->MemberIndex ].cbOffsetToHead; pMemberInfo->prCurrentLinkage = pMemberInfo->prHeadLinkage; pMemberInfo->cCurrentElement = 0; return( TRUE ); } BOOL WriteMemberInfo( PMEMBER_VARIABLE_INFO pMemberInfo ) { HANDLE hStateFile; DWORD dwWritten; hStateFile = CreateFile( STATE_FILENAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hStateFile == INVALID_HANDLE_VALUE ) { dprintf( "Can't create state file\n" ); return( FALSE ); } if ( !WriteFile( hStateFile, pMemberInfo, sizeof( MEMBER_VARIABLE_INFO ), &dwWritten, NULL ) || ( dwWritten != sizeof( MEMBER_VARIABLE_INFO ))) { dprintf( "Can't write to state file\n" ); CloseHandle( hStateFile ); return( FALSE ); } CloseHandle( hStateFile ); return( TRUE ); } BOOL ReadMemberInfo( PMEMBER_VARIABLE_INFO pMemberInfo ) { HANDLE hStateFile; DWORD dwRead; hStateFile = CreateFile( STATE_FILENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hStateFile == INVALID_HANDLE_VALUE ) { dprintf( "Can't open state file\n" ); return( FALSE ); } if ( !ReadFile( hStateFile, pMemberInfo, sizeof( MEMBER_VARIABLE_INFO ), &dwRead, NULL ) || ( dwRead != sizeof( MEMBER_VARIABLE_INFO ))) { dprintf( "Can't read from state file\n" ); CloseHandle( hStateFile ); return( FALSE ); } CloseHandle( hStateFile ); return( TRUE ); } DECLARE_API( next ) { MEMBER_VARIABLE_INFO MemberInfo; if ( !ReadMemberInfo( &MemberInfo ) ) { return; } NextElement( &MemberInfo ); DumpListItem( &MemberInfo ); WriteMemberInfo( &MemberInfo ); } DECLARE_API( prev ) { MEMBER_VARIABLE_INFO MemberInfo; if ( !ReadMemberInfo( &MemberInfo ) ) { return; } PrevElement( &MemberInfo ); DumpListItem( &MemberInfo ); WriteMemberInfo( &MemberInfo ); } VOID DumpListItem( PMEMBER_VARIABLE_INFO pMemberInfo ) { PBYTE pbObject; PMEMBER_TABLE pMemberTable; dprintf( "Focus is on: %s.%s, element # %d\n", StructureTable[ pMemberInfo->StructureIndex ].pchStructName, StructureTable[ pMemberInfo->StructureIndex ].pMemberTable[ pMemberInfo->MemberIndex ].pchMemberName, pMemberInfo->cCurrentElement ); pMemberTable = &StructureTable[ pMemberInfo->StructureIndex ].pMemberTable[ pMemberInfo->MemberIndex ]; if ( pMemberInfo->prCurrentLinkage == pMemberInfo->prHeadLinkage ) { // // Rather than dumping the head list item, dump all the items on the list, // in summary form. // do { NextElement( pMemberInfo ); if ( pMemberInfo->prCurrentLinkage != pMemberInfo->prHeadLinkage ) { pbObject = (( PBYTE )pMemberInfo->prCurrentLinkage ) - pMemberTable->cbOffsetToLink; pMemberTable->DumpStructure( ( ULONG )pbObject, VERBOSITY_ONE_LINER ); dprintf( "\n" ); } } while ( pMemberInfo->prCurrentLinkage != pMemberInfo->prHeadLinkage ); } else { pbObject = (( PBYTE )pMemberInfo->prCurrentLinkage ) - pMemberTable->cbOffsetToLink; pMemberTable->DumpStructure( ( ULONG )pbObject, VERBOSITY_NORMAL ); } } VOID NextElement( PMEMBER_VARIABLE_INFO pMemberInfo ) { ULONG NextLinkage; PMEMBER_TABLE pMember; pMember = &StructureTable[ pMemberInfo->StructureIndex ].pMemberTable[ pMemberInfo->MemberIndex ]; if ( !pMember->Next( pMemberInfo->prCurrentLinkage, &NextLinkage )) { dprintf( "Command failed.\n" ); return; } pMemberInfo->prCurrentLinkage = NextLinkage; pMemberInfo->cCurrentElement++; if ( pMemberInfo->prCurrentLinkage == pMemberInfo->prHeadLinkage ) { pMemberInfo->cCurrentElement = 0; } } BOOL NextListEntry( ULONG Current, PULONG Next ) { ULONG result; ULONG prNextEntry; LIST_ENTRY Entry; LIST_ENTRY NextEntry; if ( !ReadMemory( Current, &Entry, sizeof( Entry ), &result )) { dprintf( "Couldn't read current list entry at 0x%08X.\n", Current ); return( FALSE ); } prNextEntry = ( ULONG )Entry.Flink; if ( !ReadMemory( prNextEntry, &NextEntry, sizeof( NextEntry ), &result )) { dprintf( "Couldn't read next list entry at 0x%08X.\n", prNextEntry ); return( FALSE ); } if ( ( ULONG )NextEntry.Blink != Current ) { dprintf( "Next entry's Blink doesn't match current entry's address.\n" ); dprintf( "The list might be corrupt, or you may be using traversal state saved before the list changed.\n" ); return( FALSE ); } *Next = prNextEntry; return( TRUE ); } VOID PrevElement( PMEMBER_VARIABLE_INFO pMemberInfo ) { ULONG PrevLinkage; PMEMBER_TABLE pMember; pMember = &StructureTable[ pMemberInfo->StructureIndex ].pMemberTable[ pMemberInfo->MemberIndex ]; if ( !pMember->Prev( pMemberInfo->prCurrentLinkage, &PrevLinkage )) { dprintf( "Command failed.\n" ); return; } pMemberInfo->prCurrentLinkage = PrevLinkage; pMemberInfo->cCurrentElement++; if ( pMemberInfo->prCurrentLinkage == pMemberInfo->prHeadLinkage ) { pMemberInfo->cCurrentElement = 0; } } BOOL PrevListEntry( ULONG Current, PULONG Prev ) { ULONG result; ULONG prPrevEntry; LIST_ENTRY Entry; LIST_ENTRY PrevEntry; if ( !ReadMemory( Current, &Entry, sizeof( Entry ), &result )) { dprintf( "Couldn't read current list entry at 0x%08X.\n", Current ); return( FALSE ); } prPrevEntry = ( ULONG )Entry.Blink; if ( !ReadMemory( prPrevEntry, &PrevEntry, sizeof( PrevEntry ), &result )) { dprintf( "Couldn't read previous list entry at 0x%08X.\n", prPrevEntry ); return( FALSE ); } if ( ( ULONG )PrevEntry.Blink != Current ) { dprintf( "Previous entry's Blink doesn't match current entry's address.\n" ); dprintf( "The list might be corrupt, or you may be using traversal state saved before the list changed.\n" ); return( FALSE ); } *Prev = prPrevEntry; return( TRUE ); } BOOL ReadArgsForTraverse( const char *args, char *VarName ) { PCHAR pchListVar; int index; BOOL bRetval = FALSE; pchListVar = strstr( args, "-l" ); if ( pchListVar ) { pchListVar += 2; while ( *pchListVar == ' ' ) { pchListVar ++; } if ( *pchListVar == '\0' ) { dprintf( "NOT IMPLEMENTED: usage on -l\n" ); // ipxdev_usage(); return( bRetval ); } for ( index = 0; index < MAX_LIST_VARIABLE_NAME_LENGTH; index ++ ) { VarName[ index ] = *pchListVar; if ( *pchListVar == ' ' || *pchListVar == '\0' ) { VarName[ index ] = '\0'; break; } VarName[ index + 1 ] = '\0'; pchListVar ++; } bRetval = TRUE; } return( bRetval ); }