300 lines
8.6 KiB
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);
|
||
|
}
|
||
|
}
|