/*++ Copyright (c) 1992 Microsoft Corporation Module Name: init.c Abstract: This is the initialization module for the pfmon program. Author: Mark Lucovsky (markl) 26-Jan-1995 Revision History: --*/ #include "pfmonp.h" BOOL InitializePfmon( VOID ) { LPTSTR CommandLine; BOOL fShowUsage; DWORD Pid = 0; fShowUsage = FALSE; CommandLine = GetCommandLine(); while (*CommandLine > ' ') { CommandLine += 1; } while (TRUE) { while (*CommandLine <= ' ') { if (*CommandLine == '\0') { break; } else { CommandLine += 1; } } if (!_strnicmp( CommandLine, "/v", 2 ) || !_strnicmp( CommandLine, "-v", 2 )) { CommandLine += 2; fVerbose = TRUE; } else if (!_strnicmp( CommandLine, "/?", 2 ) || !_strnicmp( CommandLine, "-?", 2 )) { CommandLine += 2; fShowUsage = TRUE; goto showusage; } else if (!_strnicmp( CommandLine, "/c", 2 ) || !_strnicmp( CommandLine, "-c", 2 )) { CommandLine += 2; fCodeOnly = TRUE; } else if (!_strnicmp( CommandLine, "/h", 2 ) || !_strnicmp( CommandLine, "-h", 2 )) { CommandLine += 2; fHardOnly = TRUE; } else if (!_strnicmp( CommandLine, "/n", 2 ) || !_strnicmp( CommandLine, "-n", 2 )) { CommandLine += 2; LogFile = fopen("pfmon.log","wt"); fLogOnly = TRUE; } else if (!_strnicmp( CommandLine, "/l", 2 ) || !_strnicmp( CommandLine, "-l", 2 )) { CommandLine += 2; LogFile = fopen("pfmon.log","wt"); } else if (!_strnicmp( CommandLine, "/p", 2 ) || !_strnicmp( CommandLine, "-p", 2 )) { CommandLine += 2; while (*CommandLine <= ' ') { if (*CommandLine == '\0') { break; } else { ++CommandLine; } } Pid = atoi(CommandLine); CommandLine = strchr(CommandLine,' '); if (CommandLine==NULL) { break; } } else if (!strncmp( CommandLine, "/k", 2 ) || !strncmp( CommandLine, "-k", 2 )) { CommandLine += 2; fKernel = TRUE; fKernelOnly = FALSE; } else if (!strncmp( CommandLine, "/K", 2 ) || !strncmp( CommandLine, "-K", 2 )) { CommandLine += 2; fKernel = TRUE; fKernelOnly = TRUE; } else if (!_strnicmp( CommandLine, "/d", 2 ) || !_strnicmp( CommandLine, "-d", 2 )) { CommandLine += 2; fDatabase = TRUE; } else { break; } } showusage: if ( fShowUsage ) { fputs("Usage: PFMON [switches] application-command-line\n" " [-?] display this message\n" " [-n] don't display running faults, just log to pfmon.log\n" " [-l] log faults to pfmon.log\n" " [-c] only show code faults\n" " [-h] only show hard faults\n" " [-p pid] attach to existing process\n" " [-d] Database format (tab delimited)\n" " format: pagefault number, Page Fault type (Hard or Soft),\n" " Program Counter's Module, Symbol for PC, Decimal value of PC,\n" " Decimal value of PC, Module of the virtual address accessed,\n" " Symbol for VA, value of VA\n" " [-k] kernel mode page faults and user mode page faults\n" " [-K] kernel mode page faults instead of user mode\n", stdout); return FALSE; }; InitializeListHead( &ProcessListHead ); InitializeListHead( &ModuleListHead ); SetSymbolSearchPath(); if (!NT_SUCCESS(NtQuerySystemInformation(SystemRangeStartInformation, &SystemRangeStart, sizeof(SystemRangeStart), NULL))) { // Assume usermode is the low half of the address space SystemRangeStart = (ULONG_PTR)MAXLONG_PTR; } PfmonModuleHandle = GetModuleHandle( NULL ); if (Pid != 0) { return(AttachApplicationForDebug(Pid)); } else { return (LoadApplicationForDebug( CommandLine )); } return TRUE; } BOOL LoadApplicationForDebug( LPSTR CommandLine ) { STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInformation; ZeroMemory( &StartupInfo, sizeof( StartupInfo ) ); StartupInfo.cb = sizeof(StartupInfo); if (!CreateProcess( NULL, CommandLine, NULL, NULL, FALSE, // No handles to inherit DEBUG_PROCESS, NULL, NULL, &StartupInfo, &ProcessInformation)) { DeclareError( PFMON_CANT_DEBUG_PROGRAM, GetLastError(), CommandLine ); return FALSE; } else { hProcess = ProcessInformation.hProcess; SymInitialize(hProcess,NULL,FALSE); if (fKernel) { AddKernelDrivers(); } return InitializeProcessForWsWatch(hProcess); } } BOOL NtsdDebugActiveProcess ( DWORD dwPidToDebug ) { #ifdef CHICAGO BOOL b; b = DebugActiveProcess(dwPidToDebug); return( b ); #else HANDLE Token; PTOKEN_PRIVILEGES NewPrivileges; BYTE OldPriv[1024]; PBYTE pbOldPriv; ULONG cbNeeded; BOOL b; BOOL fRc; LUID LuidPrivilege; // // Make sure we have access to adjust and to get the old token privileges // if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token)) { return( FALSE ); } cbNeeded = 0; // // Initialize the privilege adjustment structure // LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &LuidPrivilege ); NewPrivileges = (PTOKEN_PRIVILEGES)calloc(1,sizeof(TOKEN_PRIVILEGES) + (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)); if (NewPrivileges == NULL) { CloseHandle(Token); return(FALSE); } NewPrivileges->PrivilegeCount = 1; NewPrivileges->Privileges[0].Luid = LuidPrivilege; NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // // Enable the privilege // pbOldPriv = OldPriv; fRc = AdjustTokenPrivileges( Token, FALSE, NewPrivileges, 1024, (PTOKEN_PRIVILEGES)pbOldPriv, &cbNeeded ); if (!fRc) { // // If the stack was too small to hold the privileges // then allocate off the heap // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pbOldPriv = calloc(1,cbNeeded); if (pbOldPriv == NULL) { CloseHandle(Token); return(FALSE); } fRc = AdjustTokenPrivileges( Token, FALSE, NewPrivileges, cbNeeded, (PTOKEN_PRIVILEGES)pbOldPriv, &cbNeeded ); } } b = DebugActiveProcess(dwPidToDebug); CloseHandle( Token ); return( b ); #endif } BOOL AttachApplicationForDebug( DWORD Pid ) { STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInformation; if (!NtsdDebugActiveProcess(Pid)) { DeclareError( PFMON_CANT_DEBUG_ACTIVE_PROGRAM, GetLastError(), Pid ); return FALSE; } else { hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, FALSE, Pid); SymInitialize(hProcess,NULL,FALSE); if (fKernel) { AddKernelDrivers(); } return InitializeProcessForWsWatch(hProcess); } }