Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. This is the initialization module for the pfmon program.
  7. Author:
  8. Mark Lucovsky (markl) 26-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "pfmonp.h"
  12. BOOL
  13. InitializePfmon( VOID )
  14. {
  15. LPTSTR CommandLine;
  16. BOOL fShowUsage;
  17. DWORD Pid = 0;
  18. fShowUsage = FALSE;
  19. CommandLine = GetCommandLine();
  20. while (*CommandLine > ' ') {
  21. CommandLine += 1;
  22. }
  23. while (TRUE) {
  24. while (*CommandLine <= ' ') {
  25. if (*CommandLine == '\0') {
  26. break;
  27. } else {
  28. CommandLine += 1;
  29. }
  30. }
  31. if (!_strnicmp( CommandLine, "/v", 2 ) || !_strnicmp( CommandLine, "-v", 2 )) {
  32. CommandLine += 2;
  33. fVerbose = TRUE;
  34. } else if (!_strnicmp( CommandLine, "/?", 2 ) || !_strnicmp( CommandLine, "-?", 2 )) {
  35. CommandLine += 2;
  36. fShowUsage = TRUE;
  37. goto showusage;
  38. } else if (!_strnicmp( CommandLine, "/c", 2 ) || !_strnicmp( CommandLine, "-c", 2 )) {
  39. CommandLine += 2;
  40. fCodeOnly = TRUE;
  41. } else if (!_strnicmp( CommandLine, "/h", 2 ) || !_strnicmp( CommandLine, "-h", 2 )) {
  42. CommandLine += 2;
  43. fHardOnly = TRUE;
  44. } else if (!_strnicmp( CommandLine, "/n", 2 ) || !_strnicmp( CommandLine, "-n", 2 )) {
  45. CommandLine += 2;
  46. LogFile = fopen("pfmon.log","wt");
  47. fLogOnly = TRUE;
  48. } else if (!_strnicmp( CommandLine, "/l", 2 ) || !_strnicmp( CommandLine, "-l", 2 )) {
  49. CommandLine += 2;
  50. LogFile = fopen("pfmon.log","wt");
  51. } else if (!_strnicmp( CommandLine, "/p", 2 ) || !_strnicmp( CommandLine, "-p", 2 )) {
  52. CommandLine += 2;
  53. while (*CommandLine <= ' ') {
  54. if (*CommandLine == '\0') {
  55. break;
  56. } else {
  57. ++CommandLine;
  58. }
  59. }
  60. Pid = atoi(CommandLine);
  61. CommandLine = strchr(CommandLine,' ');
  62. if (CommandLine==NULL) {
  63. break;
  64. }
  65. } else if (!strncmp( CommandLine, "/k", 2 ) || !strncmp( CommandLine, "-k", 2 )) {
  66. CommandLine += 2;
  67. fKernel = TRUE;
  68. fKernelOnly = FALSE;
  69. } else if (!strncmp( CommandLine, "/K", 2 ) || !strncmp( CommandLine, "-K", 2 )) {
  70. CommandLine += 2;
  71. fKernel = TRUE;
  72. fKernelOnly = TRUE;
  73. } else if (!_strnicmp( CommandLine, "/d", 2 ) || !_strnicmp( CommandLine, "-d", 2 )) {
  74. CommandLine += 2;
  75. fDatabase = TRUE;
  76. } else {
  77. break;
  78. }
  79. }
  80. showusage:
  81. if ( fShowUsage ) {
  82. fputs("Usage: PFMON [switches] application-command-line\n"
  83. " [-?] display this message\n"
  84. " [-n] don't display running faults, just log to pfmon.log\n"
  85. " [-l] log faults to pfmon.log\n"
  86. " [-c] only show code faults\n"
  87. " [-h] only show hard faults\n"
  88. " [-p pid] attach to existing process\n"
  89. " [-d] Database format (tab delimited)\n"
  90. " format: pagefault number, Page Fault type (Hard or Soft),\n"
  91. " Program Counter's Module, Symbol for PC, Decimal value of PC,\n"
  92. " Decimal value of PC, Module of the virtual address accessed,\n"
  93. " Symbol for VA, value of VA\n"
  94. " [-k] kernel mode page faults and user mode page faults\n"
  95. " [-K] kernel mode page faults instead of user mode\n",
  96. stdout);
  97. return FALSE;
  98. };
  99. InitializeListHead( &ProcessListHead );
  100. InitializeListHead( &ModuleListHead );
  101. SetSymbolSearchPath();
  102. if (!NT_SUCCESS(NtQuerySystemInformation(SystemRangeStartInformation,
  103. &SystemRangeStart,
  104. sizeof(SystemRangeStart),
  105. NULL))) {
  106. // Assume usermode is the low half of the address space
  107. SystemRangeStart = (ULONG_PTR)MAXLONG_PTR;
  108. }
  109. PfmonModuleHandle = GetModuleHandle( NULL );
  110. if (Pid != 0) {
  111. return(AttachApplicationForDebug(Pid));
  112. } else {
  113. return (LoadApplicationForDebug( CommandLine ));
  114. }
  115. return TRUE;
  116. }
  117. BOOL
  118. LoadApplicationForDebug(
  119. LPSTR CommandLine
  120. )
  121. {
  122. STARTUPINFO StartupInfo;
  123. PROCESS_INFORMATION ProcessInformation;
  124. ZeroMemory( &StartupInfo, sizeof( StartupInfo ) );
  125. StartupInfo.cb = sizeof(StartupInfo);
  126. if (!CreateProcess( NULL,
  127. CommandLine,
  128. NULL,
  129. NULL,
  130. FALSE, // No handles to inherit
  131. DEBUG_PROCESS,
  132. NULL,
  133. NULL,
  134. &StartupInfo,
  135. &ProcessInformation)) {
  136. DeclareError( PFMON_CANT_DEBUG_PROGRAM,
  137. GetLastError(),
  138. CommandLine
  139. );
  140. return FALSE;
  141. } else {
  142. hProcess = ProcessInformation.hProcess;
  143. SymInitialize(hProcess,NULL,FALSE);
  144. if (fKernel) {
  145. AddKernelDrivers();
  146. }
  147. return InitializeProcessForWsWatch(hProcess);
  148. }
  149. }
  150. BOOL
  151. NtsdDebugActiveProcess (
  152. DWORD dwPidToDebug
  153. )
  154. {
  155. #ifdef CHICAGO
  156. BOOL b;
  157. b = DebugActiveProcess(dwPidToDebug);
  158. return( b );
  159. #else
  160. HANDLE Token;
  161. PTOKEN_PRIVILEGES NewPrivileges;
  162. BYTE OldPriv[1024];
  163. PBYTE pbOldPriv;
  164. ULONG cbNeeded;
  165. BOOL b;
  166. BOOL fRc;
  167. LUID LuidPrivilege;
  168. //
  169. // Make sure we have access to adjust and to get the old token privileges
  170. //
  171. if (!OpenProcessToken( GetCurrentProcess(),
  172. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  173. &Token)) {
  174. return( FALSE );
  175. }
  176. cbNeeded = 0;
  177. //
  178. // Initialize the privilege adjustment structure
  179. //
  180. LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &LuidPrivilege );
  181. NewPrivileges = (PTOKEN_PRIVILEGES)calloc(1,sizeof(TOKEN_PRIVILEGES) +
  182. (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES));
  183. if (NewPrivileges == NULL) {
  184. CloseHandle(Token);
  185. return(FALSE);
  186. }
  187. NewPrivileges->PrivilegeCount = 1;
  188. NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  189. NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  190. //
  191. // Enable the privilege
  192. //
  193. pbOldPriv = OldPriv;
  194. fRc = AdjustTokenPrivileges( Token,
  195. FALSE,
  196. NewPrivileges,
  197. 1024,
  198. (PTOKEN_PRIVILEGES)pbOldPriv,
  199. &cbNeeded );
  200. if (!fRc) {
  201. //
  202. // If the stack was too small to hold the privileges
  203. // then allocate off the heap
  204. //
  205. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  206. pbOldPriv = calloc(1,cbNeeded);
  207. if (pbOldPriv == NULL) {
  208. CloseHandle(Token);
  209. return(FALSE);
  210. }
  211. fRc = AdjustTokenPrivileges( Token,
  212. FALSE,
  213. NewPrivileges,
  214. cbNeeded,
  215. (PTOKEN_PRIVILEGES)pbOldPriv,
  216. &cbNeeded );
  217. }
  218. }
  219. b = DebugActiveProcess(dwPidToDebug);
  220. CloseHandle( Token );
  221. return( b );
  222. #endif
  223. }
  224. BOOL
  225. AttachApplicationForDebug(
  226. DWORD Pid
  227. )
  228. {
  229. STARTUPINFO StartupInfo;
  230. PROCESS_INFORMATION ProcessInformation;
  231. if (!NtsdDebugActiveProcess(Pid)) {
  232. DeclareError( PFMON_CANT_DEBUG_ACTIVE_PROGRAM,
  233. GetLastError(),
  234. Pid );
  235. return FALSE;
  236. } else {
  237. hProcess = OpenProcess(PROCESS_VM_READ
  238. | PROCESS_QUERY_INFORMATION
  239. | PROCESS_SET_INFORMATION,
  240. FALSE,
  241. Pid);
  242. SymInitialize(hProcess,NULL,FALSE);
  243. if (fKernel) {
  244. AddKernelDrivers();
  245. }
  246. return InitializeProcessForWsWatch(hProcess);
  247. }
  248. }