/*++ Copyright (c) 1995-1997 Microsoft Corporation Module Name : dbgthunk.cxx Abstract: This module defines all thunks for inlined functions, so that the debugger extension DLL can be peacefully linked. Author: Murali R. Krishnan ( MuraliK ) 24-Aug-1997 Environment: Debugging Mode - NTSD Debugger Extension DLL Project: IIS Debugger Extensions DLL Functions Exported: Revision History: --*/ /************************************************************ * Include Headers ************************************************************/ # include "inetdbgp.h" # undef DBG_ASSERT # define minSize(a, b) (((a) < (b)) ? (a) : (b)) #ifdef _NO_TRACING_ DECLARE_DEBUG_VARIABLE(); #endif DECLARE_DEBUG_PRINTS_OBJECT(); /************************************************************ * Utility Functions ************************************************************/ VOID dstring( CHAR * pszName, PVOID pvString, DWORD cbLen) /*++ Description: This function reads the data from the debuggee process at address [pvString] for specified length [cbLen] and echoes the string back on the debugger window. Arguments: pszName - pointer to string containing the name of the string read pvString - pointer to VOID specifying the location of the string in the debugee process cbLen - count of bytes to be read at [pvString] Returns: None --*/ { CHAR rgchString[10240]; DWORD cLength = minSize( cbLen, sizeof(rgchString) -1); // // Read the data block from the debuggee process into local buffer // moveBlock( rgchString, pvString, cLength); rgchString[cLength] = '\0'; // terminate the string buffer dprintf( "%s = %s\n", pszName, rgchString); return; } // dstring() VOID PrintLargeInteger( CHAR * pszName, LARGE_INTEGER * pli) { CHAR szLargeInt[100]; RtlLargeIntegerToChar( pli, // large integer location 10, // base for conversion sizeof(szLargeInt), szLargeInt ); dprintf( " %30s = %s\n", pszName, szLargeInt); return; } // PrintLargeInteger() VOID Print2Dwords( CHAR * pszN1, DWORD d1, CHAR * pszN2, DWORD d2 ) { dprintf(" %25s =%8d %25s =%8d\n", pszN1, d1, pszN2, d2 ); return; } // Print2Dwords() BOOL EnumLinkedList( IN LIST_ENTRY * pListHead, IN PFN_LIST_ENUMERATOR pfnListEnumerator, IN CHAR chVerbosity, IN DWORD cbSizeOfStructure, IN DWORD cbListEntryOffset ) /*++ Description: This function iterates over the NT's standard LIST_ENTRY structure (doubly linked circular list with header) and makes callbacks for objects found on the list. Arguments: pListHead - pointer to List head in the debugee process pfnListEnumerator - pointer to callback function for the object on the list chVerbosity - character indicating the verbosity level desired cbSizeOfStructure - count of bytes of object's size cbListEntryOffset - count of bytes of offset of the List entry structure inside the containing object Returns: TRUE on successful enumeration FALSE on failure --*/ { # define MAX_STRUCTURE_SIZE (10240) CHAR rgch[MAX_STRUCTURE_SIZE]; PVOID pvDebuggee = NULL; PVOID pvDebugger = (PVOID ) rgch; LIST_ENTRY leListHead; LIST_ENTRY * pListEntry; DWORD cItems = 0; if ( NULL == pListHead) { dprintf( "Invalid List given \n"); return (FALSE); } if ( MAX_STRUCTURE_SIZE < cbSizeOfStructure) { dprintf( "Given size for structure %d exceeds default max %d bytes\n", cbSizeOfStructure, MAX_STRUCTURE_SIZE); return (FALSE); } // make a local copy of the list head for navigation purposes MoveWithRet( leListHead, pListHead, FALSE); for ( pListEntry = leListHead.Flink; pListEntry != pListHead; ) { if ( CheckControlC() ) { return (FALSE); } pvDebuggee = (PVOID ) ((PCHAR ) pListEntry - cbListEntryOffset); // make a local copy of the debuggee structure MoveBlockWithRet( rgch, pvDebuggee, cbSizeOfStructure, FALSE); cItems++; if( pfnListEnumerator ) { (*pfnListEnumerator)( pvDebuggee, pvDebugger, chVerbosity, cItems); dprintf( "\n"); } MoveWithRet( pListEntry, &pListEntry->Flink, FALSE ); } // for all linked list entries dprintf( "%d entries traversed\n", cItems ); return (TRUE); } // EnumLinkedList() /*++ Description: COM objects registered as LocalServer result in running in a separate process. The base process communicates with these COM objects using RPC. It is often required to find the process id of destination process. The function cracks the process id of the target process given the first parameter to the function ole32!CRpcChannelBuffer__SendReceive() Argument: arg1 - pointer to string containing the parameter that is the hex-value of the RPC structure's location (which is the first param of function ole32!CRpcChannelBuffer__SendReceive()) Standard NTSD parameters: hCurrentProcess - Supplies a handle to the current process (at the time the extension was called). hCurrentThread - Supplies a handle to the current thread (at the time the extension was called). CurrentPc - Supplies the current pc at the time the extension is called. lpExtensionApis - Supplies the address of the functions callable by this extension. lpArgumentString - Supplies the asciiz string that describes the ansi string to be dumped. Returns: None --*/ DECLARE_API( rpcoop ) { DWORD * pRpcParam1; DWORD dwContent; INIT_API(); #if _WIN64 dprintf("inetdbg.rpcoop: Not functional for 64bit as of yet"); #else while (*lpArgumentString == ' ') lpArgumentString++; if ( !*lpArgumentString ) { PrintUsage( "rpcoop" ); return; } if ( *lpArgumentString == '-' ) { lpArgumentString++; if ( *lpArgumentString == 'h' ) { PrintUsage( "rpcoop" ); return; } } // while // // Treat the argument as the param1 of the RPC function // pRpcParam1 = (DWORD * ) GetExpression( lpArgumentString ); if ( !pRpcParam1 ) { dprintf( "inetdbg.rpcoop: Unable to evaluate \"%s\"\n", lpArgumentString ); return; } // // get the contents of the memory at seventh DWORD to pRpcParam1 // ie. get [pRpcParam1 + 0x6] // - this is valid based on NT 4.0 SP3 code base :( // move( dwContent, pRpcParam1 + 0x6 ); // // dwContent now contains the address of another structure // that carries the remote process Id // get the contents of the memory at seventh DWORD to dwContent // ie. get [dwContent + 9] // - this is valid based on NT 4.0 SP3 code base :( // DWORD dwProcessId; move( dwProcessId, ((LPDWORD ) dwContent) + 9); // // dump the process id to debugger screen // dprintf("\tRPC process ID = %d (0x%x)\n", dwProcessId, dwProcessId); #endif return; } // DECLARE_API( rpcoop ) DECLARE_API( llc ) /*++ Routine Description: This function is called as an NTSD extension to count the LIST_ENTRYs on a linked list. Arguments: hCurrentProcess - Supplies a handle to the current process (at the time the extension was called). hCurrentThread - Supplies a handle to the current thread (at the time the extension was called). CurrentPc - Supplies the current pc at the time the extension is called. lpExtensionApis - Supplies the address of the functions callable by this extension. lpArgumentString - Supplies the asciiz string that describes the ansi string to be dumped. Return Value: None. --*/ { PLIST_ENTRY remoteListHead; INIT_API(); // // Skip leading blanks. // while( *lpArgumentString == ' ' || *lpArgumentString == '\t' ) { lpArgumentString++; } if( *lpArgumentString == '\0' ) { PrintUsage( "llc" ); return; } // // Get the list head. // remoteListHead = (PLIST_ENTRY)GetExpression( lpArgumentString ); if( remoteListHead == NULL ) { dprintf( "!llc: cannot evaluate %s\n", lpArgumentString ); return; } // // Let the enumerator do the dirty work. // EnumLinkedList( remoteListHead, NULL, 0, sizeof(LIST_ENTRY), 0 ); } // DECLARE_API( llc ) /************************************************************ * FAKE Functions * * Fake the definitions of certain functions that belong only * in the local compilation of w3svc & infocomm dlls * ************************************************************/ extern "C" { // // NTSD Extensions & CRTDLL likes to have the main() function // Let us throw this in as well, while we are in the business // of faking several other functions :) // void _cdecl main( void ) { ; } } __int64 GetCurrentTimeInMilliseconds( VOID ) { return (0); } BOOL BUFFER::GetNewStorage( UINT cbRequested ) { return (TRUE);} BOOL BUFFER::ReallocStorage( UINT cbRequested ) { return (TRUE);} VOID STR::AuxInit( const BYTE * pInit ) {} BOOL STR::AuxAppend( const BYTE * pInit, UINT cbStr, BOOL fAddSlop ) { return (TRUE);} VOID MULTISZ::AuxInit( const BYTE * pInit ) {} BOOL MULTISZ::AuxAppend( const BYTE * pInit, UINT cbStr, BOOL fAddSlop ) { return (TRUE);} DWORD HASH_TABLE::CalculateHash( IN LPCSTR pszKey, IN DWORD cchKey) const { return ( 0); } VOID HASH_TABLE::Cleanup( VOID) {} HT_ELEMENT * HASH_TABLE::Lookup( IN LPCSTR pszKey, IN DWORD cchKey) { return ( NULL); } DWORD IIS_SERVER_INSTANCE::UpdateBindingsHelper( IN BOOL IsSecure ) { return (NO_ERROR); } DWORD IIS_SERVER_INSTANCE::UnbindHelper( IN PLIST_ENTRY BindingListHead ) { return ( NO_ERROR); } BOOL IIS_SERVICE::LoadStr( OUT STR & str, IN DWORD dwResId, IN BOOL fForceEnglish ) const { return ( TRUE); } DWORD IIS_SERVICE::UpdateServiceStatus(IN DWORD State, IN DWORD Win32ExitCode, IN DWORD CheckPoint, IN DWORD WaitHint ) { return ( NO_ERROR); } BOOL IIS_SERVICE::RemoveServerInstance( IN IIS_SERVER_INSTANCE * pInstance ) { return ( FALSE); } INET_PARSER::INET_PARSER( char * pszStart) {} INET_PARSER::~INET_PARSER(VOID) {} CHAR * INET_PARSER::AuxEatWhite(VOID) { return ( NULL); } CHAR * INET_PARSER::AuxEatNonWhite(CHAR ch) { return ( NULL); } CHAR * INET_PARSER::AuxSkipTo(CHAR ch) { return ( NULL); } VOID INET_PARSER::TerminateToken( CHAR ch) {} VOID INET_PARSER::RestoreToken( VOID ) {} VOID INET_PARSER::TerminateLine( VOID ) {} VOID INET_PARSER::RestoreLine( VOID ) {} CHAR * INET_PARSER::NextToken( CHAR ) { return (NULL); } AC_RESULT ADDRESS_CHECK::CheckName( LPSTR pName ) { return ( AC_NO_LIST); } VOID TS_DIRECTORY_INFO::CleanupThis(VOID) {}; VOID * TCP_AUTHENT::QueryPrimaryToken(VOID) { return (NULL); } /************************ End of File ***********************/