Windows-Server-2003/sdktools/pfmon/init.c

300 lines
8.6 KiB
C

/*++
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);
}
}