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.

668 lines
22 KiB

  1. //==========================================================================//
  2. // Includes //
  3. //==========================================================================//
  4. #include <string.h> // strupr
  5. #include <stdio.h> // for sprintf.
  6. #include "perfmon.h"
  7. #include "init.h" // external declarations for this file
  8. #include "alert.h" // for AlertIitializeApplication
  9. #include "command.h" // for ViewChart
  10. #include "grafdata.h" // for QuerySaveChart
  11. #include "graph.h" // for GraphInitializeApplication
  12. #include "legend.h" // for LegendInitializeApplication
  13. #include "log.h" // for LogInitializeApplication
  14. #include "intrline.h" // for ILineInitializeApplication
  15. #include "perfdata.h" // for PerfDataInitializeInstance
  16. #include "perfmops.h" // for OpenFileHandler, for now
  17. #include "status.h" // for StatusInitializeApplication
  18. #include "timeline.h" // for TLineInitializeApplication
  19. #include "playback.h" // for PlaybackInitializeInstance
  20. #include "registry.h" // for Load/SaveMainWindowPlacement
  21. #include "report.h" // for ReportInitializeApplication
  22. #include "toolbar.h" // for ToolbarInitializeApplication
  23. #include "utils.h"
  24. #include "fileopen.h" // for FileOpen
  25. #include "pmemory.h" // for MemoryFree
  26. extern TCHAR DefaultLangId[] ;
  27. extern TCHAR EnglishLangId[] ;
  28. static LPSTR lpszCommandLine ;
  29. //==========================================================================//
  30. // Constants //
  31. //==========================================================================//
  32. #define szPerfmonMainClass TEXT("PerfmonMainClass")
  33. HHOOK lpMsgFilterProc ;
  34. DWORD FAR PASCAL MessageFilterProc (int nCode, WPARAM wParam,
  35. LPARAM lParam) ;
  36. //==========================================================================//
  37. // Local Functions //
  38. //==========================================================================//
  39. static
  40. LONG
  41. EnablePrivilege (
  42. IN LPTSTR szPrivName
  43. )
  44. {
  45. LUID SePrivNameValue;
  46. TOKEN_PRIVILEGES tkp;
  47. HANDLE hToken = NULL;
  48. /* Retrieve a handle of the access token. */
  49. if (!OpenProcessToken(GetCurrentProcess(),
  50. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  51. &hToken)) {
  52. goto Exit_Point;
  53. }
  54. /*
  55. * Enable the privilege by name and get the ID
  56. */
  57. if (!LookupPrivilegeValue((LPTSTR) NULL,
  58. szPrivName,
  59. &SePrivNameValue)) {
  60. goto Exit_Point;
  61. }
  62. tkp.PrivilegeCount = 1;
  63. tkp.Privileges[0].Luid = SePrivNameValue;
  64. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  65. AdjustTokenPrivileges(hToken,
  66. FALSE,
  67. &tkp,
  68. sizeof(TOKEN_PRIVILEGES),
  69. (PTOKEN_PRIVILEGES) NULL,
  70. (PDWORD) NULL);
  71. /* The return value of AdjustTokenPrivileges be texted. */
  72. Exit_Point:
  73. if (hToken != NULL) CloseHandle (hToken);
  74. return GetLastError();
  75. }
  76. void
  77. GetScalesFonts (void)
  78. {
  79. LOGFONT lf ;
  80. CHARSETINFO csi;
  81. DWORD dw = GetACP();
  82. if (!TranslateCharsetInfo(UlongToPtr(dw), &csi, TCI_SRCCODEPAGE))
  83. csi.ciCharset = ANSI_CHARSET;
  84. memset (&lf, 0, sizeof (lf)) ;
  85. lstrcpy (lf.lfFaceName, szScalesFontFace) ;
  86. /*
  87. if (csi.ciCharset == ANSI_CHARSET)
  88. lf.lfHeight = iScalesFontHeightAnsi ;
  89. else
  90. lf.lfHeight = iScalesFontHeightNonAnsi ;
  91. */
  92. // make the text the same size as a menu text
  93. lf.lfHeight = GetSystemMetrics (SM_CYMENUCHECK);
  94. lf.lfWeight = FW_REGULAR ;
  95. lf.lfCharSet = (BYTE)csi.ciCharset;
  96. hFontScales = CreateFontIndirect (&lf) ;
  97. if (csi.ciCharset == ANSI_CHARSET)
  98. lf.lfWeight = FW_BOLD ;
  99. hFontScalesBold = CreateFontIndirect (&lf) ;
  100. }
  101. BOOL
  102. InitializeSystemValues (void)
  103. /*
  104. Effect: Read and store in variables the various system values,
  105. such as the width and height of the screen and icons,
  106. the width of scroll bars, etc.
  107. Called By: PerfmonInitialize only.
  108. Returns: Whether this function was successful in getting all
  109. needed system values.
  110. */
  111. {
  112. xScreenWidth = GetSystemMetrics (SM_CXSCREEN) ;
  113. yScreenHeight = GetSystemMetrics (SM_CYSCREEN) ;
  114. xBorderWidth = GetSystemMetrics (SM_CXBORDER) ;
  115. yBorderHeight = GetSystemMetrics (SM_CYBORDER) ;
  116. xScrollWidth = GetSystemMetrics (SM_CXVSCROLL) ;
  117. yScrollHeight = GetSystemMetrics (SM_CYHSCROLL) ;
  118. xScrollThumbWidth = GetSystemMetrics (SM_CXHTHUMB) ;
  119. yScrollThumbHeight = GetSystemMetrics (SM_CYVTHUMB) ;
  120. xDlgBorderWidth = GetSystemMetrics (SM_CXDLGFRAME) ;
  121. yDlgBorderHeight = GetSystemMetrics (SM_CYDLGFRAME) ;
  122. MinimumSize = yScrollHeight +
  123. GetSystemMetrics (SM_CYMENU) +
  124. GetSystemMetrics (SM_CYCAPTION) ;
  125. //================================================================//
  126. // create all the brushes and pens for performance improvement //
  127. //================================================================//
  128. CreatePerfmonSystemObjects () ;
  129. hWhitePen = CreatePen (PS_SOLID, 3, crWhite) ;
  130. return (TRUE) ;
  131. }
  132. BOOL
  133. InitializeApplication (void)
  134. /*
  135. Effect: Perform all initializations required for the FIRST
  136. instance of the Perfmon application. In particular,
  137. register all of Perfmon's window classes.
  138. Note: There is no background brush set for the MainWindow
  139. class so that the main window is never erased. The
  140. client area of MainWindow is always covered by one
  141. of the view windows. If we erase it, it would just
  142. flicker needlessly.
  143. Called By: PerfmonInitialize only.
  144. Returns: Whether this function was successful in initializing.
  145. */
  146. {
  147. BOOL bSuccess ;
  148. WNDCLASS wc ;
  149. TCHAR LocalHelpFileName [ShortTextLen] ;
  150. LPTSTR pFileName ;
  151. hIcon = LoadIcon (hInstance, idIcon) ;
  152. //=============================//
  153. // Register Main window class //
  154. //=============================//
  155. wc.style = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
  156. wc.lpfnWndProc = MainWndProc;
  157. wc.hInstance = hInstance;
  158. wc.cbClsExtra = 0 ;
  159. wc.cbWndExtra = 0;
  160. wc.hIcon = hIcon ;
  161. wc.hCursor = LoadCursor(NULL, IDI_APPLICATION);
  162. wc.hbrBackground = NULL ; // see note above
  163. wc.lpszMenuName = idMenuChart ;
  164. wc.lpszClassName = szPerfmonMainClass ;
  165. bSuccess = RegisterClass (&wc) ;
  166. //=============================//
  167. // Register Abstract "Systems" //
  168. //=============================//
  169. hbLightGray = GetStockObject (LTGRAY_BRUSH) ;
  170. if (bSuccess)
  171. bSuccess = StatusInitializeApplication () ;
  172. if (bSuccess)
  173. bSuccess = GraphInitializeApplication () ;
  174. #ifdef ADVANCED_PERFMON
  175. if (bSuccess)
  176. bSuccess = LogInitializeApplication () ;
  177. if (bSuccess)
  178. bSuccess = AlertInitializeApplication () ;
  179. if (bSuccess)
  180. bSuccess = ReportInitializeApplication () ;
  181. if (bSuccess)
  182. bSuccess = ILineInitializeApplication () ;
  183. if (bSuccess)
  184. bSuccess = TLineInitializeApplication () ;
  185. #endif
  186. // setup messagehook to handle F1 as help
  187. lpMsgFilterProc = SetWindowsHookEx (WH_MSGFILTER,
  188. (HOOKPROC) MessageFilterProc,
  189. hInstance,
  190. GetCurrentThreadId()) ;
  191. // get the help file full path name
  192. LoadString (hInstance, IDS_HELPFILE_NAME,
  193. (LPTSTR)LocalHelpFileName, ShortTextLen-1);
  194. if (LocalHelpFileName[0]) {
  195. DWORD dwLength;
  196. pszHelpFile = (LPTSTR) MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
  197. dwLength = SearchPath (NULL, LocalHelpFileName, NULL,
  198. FilePathLen - 1, pszHelpFile, &pFileName) ;
  199. if (dwLength == 0) {
  200. // not found in the path so check the help dir
  201. TCHAR szSearchPath[MAX_PATH];
  202. ExpandEnvironmentStrings (TEXT("%windir%\\help"),
  203. szSearchPath, ((sizeof (szSearchPath)/sizeof (TCHAR)) -1));
  204. SearchPath (szSearchPath, LocalHelpFileName, NULL,
  205. FilePathLen - 1, pszHelpFile, &pFileName) ;
  206. }
  207. } else {
  208. // no help file
  209. pszHelpFile = (LPTSTR) MemoryAllocate (sizeof (TCHAR)) ;
  210. if (pszHelpFile) {
  211. *pszHelpFile = TEXT('\0') ;
  212. }
  213. }
  214. return (bSuccess) ;
  215. }
  216. BOOL
  217. InitializeInstance (
  218. int nCmdShow,
  219. LPCSTR lpszCmdLine
  220. )
  221. /*
  222. Effect: Perform all initializations required for EACH instance
  223. of the Perfmon application. In particular, create all
  224. of Perfmon's initial windows, and perform any other
  225. initializations except registering classes (done in
  226. InitializeApplication).
  227. Called By: PerfmonInitialize only.
  228. Note: This function has multiple return points.
  229. Returns: Whether this function was successful in initalizing.
  230. */
  231. {
  232. DWORD ComputerNameLength;
  233. TCHAR szApplication [WindowCaptionLen] ;
  234. bCloseLocalMachine = FALSE;
  235. // enable privileges needed to profile system
  236. // if this fails, that's ok for now.
  237. EnablePrivilege (SE_SYSTEM_PROFILE_NAME); // to access perfdata
  238. EnablePrivilege (SE_INC_BASE_PRIORITY_NAME); // to raise priority
  239. //=============================//
  240. // Set Priority high //
  241. //=============================//
  242. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS) ;
  243. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ;
  244. //=============================//
  245. // Load Resources //
  246. //=============================//
  247. GetScalesFonts () ;
  248. hMenuChart = LoadMenu (hInstance, idMenuChart) ;
  249. #ifdef ADVANCED_PERFMON
  250. hMenuAlert = LoadMenu (hInstance, idMenuAlert) ;
  251. hMenuLog = LoadMenu (hInstance, idMenuLog) ;
  252. hMenuReport = LoadMenu (hInstance, idMenuReport) ;
  253. #endif
  254. hAccelerators = LoadAccelerators (hInstance, idAccelerators) ;
  255. //=============================//
  256. // Initialize Systems //
  257. //=============================//
  258. iLanguage = GetUserDefaultLangID() ;
  259. iEnglishLanguage = MAKELANGID (LANG_ENGLISH, LANG_NEUTRAL) ;
  260. // iEnglishLanguage = MAKELANGID (iLanguage & 0x0ff, LANG_NEUTRAL) ;
  261. TSPRINTF (DefaultLangId, TEXT("%03x"), iLanguage) ;
  262. TSPRINTF (EnglishLangId, TEXT("%03x"), iEnglishLanguage) ;
  263. // GetComputerName returns the name without the "\\" prefix. We add
  264. // the prefix before even calling the routine. This is so that all our
  265. // computer names have the prefix and are therefore compatible with
  266. // I_SetSystemFocus (see perfmops.c).
  267. ComputerNameLength = MAX_PATH + 1;
  268. lstrcpy (LocalComputerName, szComputerPrefix) ;
  269. GetComputerName (LocalComputerName + lstrlen (szComputerPrefix),
  270. &ComputerNameLength);
  271. PlaybackInitializeInstance () ;
  272. PerfDataInitializeInstance () ;
  273. //Copy command line into buffer for modification
  274. lpszCommandLine = (LPSTR)MemoryAllocate (strlen (lpszCmdLine) + sizeof(CHAR)) ;
  275. if (lpszCommandLine)
  276. strcpy(lpszCommandLine, lpszCmdLine) ;
  277. else
  278. return (FALSE) ;
  279. StringLoad (IDS_APPNAME, szApplication) ;
  280. //Insure CmdLineComputerName starts out NULL
  281. CmdLineComputerName[0] = TEXT('\0') ;
  282. //Check to see if there is a computer name specified on the command
  283. //line (indicated by /c, or /C). If there is, get it and
  284. //null out the command line string so that it is not mistaken for
  285. //startup file. This assumes that specifying a computer and a startup
  286. //file on the command line are mutually exclusive. If the /c option
  287. //is on the command line, anything else on the command line is discarded.
  288. if (!strempty (lpszCommandLine)) {
  289. LPSTR lpszNewCL ;
  290. //Preserve initial command line pointer position
  291. lpszNewCL = (LPSTR)lpszCommandLine ;
  292. while (*lpszNewCL != '\0' && *lpszCommandLine) {
  293. if (*lpszNewCL == '/' || *lpszNewCL == '-') {
  294. lpszNewCL++ ;
  295. if (*lpszNewCL == 'c' || *lpszNewCL == 'C') {
  296. int i = 0;
  297. lpszNewCL++ ;
  298. //ignore leading backslashes * spaces
  299. while (*lpszNewCL == '\\' || *lpszNewCL == ' ')
  300. lpszNewCL++ ;
  301. //Terminate at first blank space if there is one.
  302. //We don't allow anything else on the command line
  303. //if a computer name is specified.
  304. while (lpszNewCL[i] != ' ' && lpszNewCL[i] != '\0')
  305. i++ ;
  306. lpszNewCL[i] = '\0' ;
  307. if ((*lpszNewCL != '\0') && (strlen(lpszNewCL) <= MAX_PATH)) {
  308. int nSizePrefix ;
  309. nSizePrefix = lstrlen (szComputerPrefix) ;
  310. lstrcpy( CmdLineComputerName, szComputerPrefix ) ;
  311. MultiByteToWideChar (CP_ACP,
  312. MB_PRECOMPOSED,
  313. lpszNewCL,
  314. -1,
  315. CmdLineComputerName + nSizePrefix,
  316. sizeof(CmdLineComputerName) - nSizePrefix) ;
  317. //prevent lpszCommandLine from being used as input file & stop while loop
  318. *lpszCommandLine = '\0' ;
  319. } else {
  320. LPTSTR lpszErrMsg ;
  321. TCHAR lpszFormat[80] ;
  322. LoadString(hInstance, ERR_BADCOMPUTERNAME, lpszFormat, sizeof(lpszFormat)/sizeof(TCHAR)) ;
  323. lpszErrMsg = (LPTSTR)MemoryAllocate ((strlen (lpszNewCL) + 1)*sizeof(TCHAR) + sizeof(lpszFormat)) ;
  324. //If memory allocation failed, don't display error message
  325. if (lpszErrMsg) {
  326. //lpszFormat uses %S specifier so lpszNewCL can be ansi string
  327. wsprintf (lpszErrMsg, lpszFormat, lpszNewCL) ;
  328. MessageBox (NULL, lpszErrMsg, szApplication, MB_OK | MB_ICONSTOP | MB_TASKMODAL) ;
  329. }
  330. //prevent lpszCommandLine from being used as input file & stop while loop
  331. *lpszCommandLine = '\0' ;
  332. }
  333. }
  334. }
  335. lpszNewCL++ ;
  336. }
  337. }
  338. //=============================//
  339. // Create Window //
  340. //=============================//
  341. hWndMain = CreateWindow (szPerfmonMainClass,
  342. szApplication,
  343. WS_OVERLAPPEDWINDOW | WS_BORDER,
  344. CW_USEDEFAULT, CW_USEDEFAULT,
  345. CW_USEDEFAULT, CW_USEDEFAULT,
  346. NULL,
  347. NULL,
  348. NULL,
  349. NULL);
  350. if (!hWndMain)
  351. return (FALSE) ;
  352. ViewChart (hWndMain) ;
  353. LoadMainWindowPlacement (hWndMain) ;
  354. //=============================//
  355. // Setup for event logging //
  356. //=============================//
  357. hEventLog = RegisterEventSource (
  358. (LPTSTR)NULL, // Use Local Machine
  359. TEXT("PerfMon")); // event log app name to find in registry
  360. return (TRUE) ;
  361. }
  362. //==========================================================================//
  363. // Exported Functions //
  364. //==========================================================================//
  365. BOOL
  366. PerfmonInitialize (
  367. HINSTANCE hCurrentInstance,
  368. HINSTANCE hPrevInstance,
  369. LPCSTR lpszCmdLine,
  370. int nCmdShow
  371. )
  372. /*
  373. Effect: Performa all initializations required when Perfmon is
  374. started. In particular, initialize all "systems", register
  375. all window classes, create needed windows, read in and
  376. process font and Perfmon lists.
  377. Called By: WinMain only, at the start of the application.
  378. Assert: There are no other instances of Perfmon currently
  379. executing.
  380. Returns: Whether initialization was successful. If this function
  381. returns FALSE, Perfmon should exit immediately.
  382. Internals: The bSuccess variable is used to conditionalize each
  383. successive initialization step.
  384. */
  385. {
  386. BOOL bSuccess ;
  387. TCHAR szFilePath [FilePathLen + 1] ;
  388. LPTSTR pFileNameStart ;
  389. HANDLE hFindFile ;
  390. WIN32_FIND_DATA FindFileInfo ;
  391. CHAR QuoteChar ;
  392. LPSTR pCmdLine ;
  393. LPSTR lpszCmdLineStart = NULL ;
  394. SIZE_T NameOffset ;
  395. int StringLen ;
  396. hInstance = hCurrentInstance ;
  397. bSuccess = InitializeSystemValues () ;
  398. if (bSuccess && !hPrevInstance)
  399. bSuccess = InitializeApplication () ;
  400. if (bSuccess)
  401. bSuccess = InitializeInstance (nCmdShow, lpszCmdLine) ;
  402. GetDateTimeFormats() ;
  403. lpszCmdLineStart = lpszCommandLine ;
  404. if (bSuccess) {
  405. if (strempty (lpszCommandLine))
  406. StringLoad (IDS_DEFAULTPATH, szFilePath) ;
  407. else {
  408. // check for single or double quote
  409. QuoteChar = *lpszCommandLine ;
  410. if (QuoteChar == '\'' || QuoteChar == '\"') {
  411. lpszCommandLine++ ;
  412. // remove the matching QuoteChar if found
  413. pCmdLine = (LPSTR) lpszCommandLine ;
  414. while (*pCmdLine != '\0') {
  415. if (*pCmdLine == QuoteChar) {
  416. *pCmdLine = '\0' ;
  417. break ;
  418. } else {
  419. pCmdLine++ ;
  420. }
  421. }
  422. }
  423. // convert the LPSTR to LPTSTR
  424. StringLen = strlen(lpszCommandLine) + 1 ;
  425. if (StringLen > sizeof(szFilePath)) {
  426. StringLen = sizeof (szFilePath) - sizeof (TEXT('\0')) ;
  427. }
  428. szFilePath[FilePathLen] = TEXT('\0') ;
  429. mbstowcs (szFilePath, lpszCommandLine, StringLen) ;
  430. if (!(QuoteChar == '\'' || QuoteChar == '\"')) {
  431. // if there is no quote, then looking for trailing space
  432. LPTSTR pThisChar = szFilePath ;
  433. LPTSTR pLastChar = NULL;
  434. LPTSTR pSpaceChar = NULL;
  435. BOOL bWord = FALSE;
  436. while (*pThisChar != TEXT('\0')) {
  437. if (*pThisChar > TEXT(' ')) {
  438. // this is a printable char
  439. bWord = TRUE;
  440. pLastChar = pThisChar;
  441. } else if (bWord) {
  442. bWord = FALSE;
  443. pSpaceChar = pThisChar;
  444. }
  445. pThisChar++ ;
  446. }
  447. // terminate string after last printable character.
  448. if (pSpaceChar > pLastChar) *pSpaceChar = TEXT('\0');
  449. }
  450. pFileNameStart = ExtractFileName (szFilePath) ;
  451. NameOffset = pFileNameStart - szFilePath ;
  452. // convert short filename to long NTFS filename if necessary
  453. hFindFile = FindFirstFile (szFilePath, &FindFileInfo) ;
  454. if (hFindFile && hFindFile != INVALID_HANDLE_VALUE) {
  455. // append the file name back to the path name
  456. lstrcpy (&szFilePath[NameOffset], FindFileInfo.cFileName) ;
  457. FindClose (hFindFile) ;
  458. }
  459. }
  460. // OpenFileHandler (hWndMain, szFilePath) ;
  461. FileOpen (hWndMain, (int)0, (LPTSTR)szFilePath) ;
  462. PrepareMenu (GetMenu (hWndMain));
  463. }
  464. if (lpszCmdLineStart) {
  465. MemoryFree (lpszCmdLineStart) ;
  466. lpszCommandLine = NULL ;
  467. }
  468. return (bSuccess) ;
  469. }
  470. void
  471. PerfmonClose (
  472. HWND hWndMain
  473. )
  474. {
  475. DWORD dwException;
  476. // close the log file for now.
  477. // need to query the user later..!!
  478. #if 0
  479. if (LogCollecting (hWndLog)) {
  480. PLOG pLog = LogData (hWndLog) ;
  481. if (pLog) {
  482. CloseLog (hWndLog, pLog) ;
  483. }
  484. }
  485. #endif
  486. // reset all views - will free all systems as well
  487. ResetGraphView (hWndGraph) ;
  488. ResetAlertView (hWndAlert) ;
  489. ResetLogView (hWndLog) ;
  490. ResetReportView (hWndReport) ;
  491. try {
  492. // if the key has already been closed, this will
  493. // generate an exception so we'll catch that here
  494. // and continue...
  495. //
  496. // close the local machine
  497. if (bCloseLocalMachine) {
  498. RegCloseKey (HKEY_PERFORMANCE_DATA) ;
  499. }
  500. }except (EXCEPTION_EXECUTE_HANDLER) {
  501. // get the exception for the debugger user, that's all
  502. dwException = GetExceptionCode();
  503. }
  504. // free all the filenames
  505. if (pChartFullFileName) {
  506. MemoryFree (pChartFullFileName) ;
  507. pChartFullFileName = NULL ;
  508. }
  509. if (pAlertFullFileName) {
  510. MemoryFree (pAlertFullFileName) ;
  511. pAlertFullFileName = NULL ;
  512. }
  513. if (pLogFullFileName) {
  514. MemoryFree (pLogFullFileName) ;
  515. pLogFullFileName = NULL ;
  516. }
  517. if (pReportFullFileName) {
  518. MemoryFree (pReportFullFileName) ;
  519. pReportFullFileName = NULL ;
  520. }
  521. // free all the GDI resources
  522. DeletePen (hWhitePen) ;
  523. DeletePerfmonSystemObjects () ;
  524. // close event log
  525. DeregisterEventSource (hEventLog);
  526. SaveMainWindowPlacement (hWndMain) ;
  527. DestroyWindow (hWndMain) ;
  528. }