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.

1457 lines
44 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. tracer.c
  5. Abstract:
  6. This module contains the code for debug tracing of a windows app.
  7. Author:
  8. Michael Tsang (MikeTs) 02-May-2000
  9. Environment:
  10. User mode
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. //
  15. // Global Data
  16. //
  17. HANDLE ghServerThread = NULL;
  18. HINSTANCE ghInstance = 0;
  19. PSZ gpszWinTraceClass = "WinTrace_Class";
  20. HWND ghwndTracer = 0;
  21. HWND ghwndEdit = 0;
  22. HWND ghwndPropSheet = 0;
  23. HFONT ghFont = 0;
  24. HCURSOR ghStdCursor = 0;
  25. HCURSOR ghWaitCursor = 0;
  26. DWORD gdwfTracer = 0;
  27. LIST_ENTRY glistClients = {0};
  28. char gszApp[16] = {0};
  29. char gszSearchText[128] = {0}; //BUGBUG
  30. char gszFileName[MAX_PATH + 1] = {0};
  31. char gszSaveFilterSpec[80] = {0};
  32. int giPointSize = 120;
  33. LOGFONT gLogFont = {0};
  34. SETTINGS gDefGlobalSettings = {0, 0, 0};
  35. const int gTrigPtCtrlMap[NUM_TRIGPTS] =
  36. {
  37. IDC_TRIGPT1, IDC_TRIGPT2, IDC_TRIGPT3, IDC_TRIGPT4, IDC_TRIGPT5,
  38. IDC_TRIGPT6, IDC_TRIGPT7, IDC_TRIGPT8, IDC_TRIGPT9, IDC_TRIGPT10
  39. };
  40. const int gTrigPtTraceMap[NUM_TRIGPTS] =
  41. {
  42. IDC_TRIGPT1_TRACE, IDC_TRIGPT2_TRACE, IDC_TRIGPT3_TRACE,
  43. IDC_TRIGPT4_TRACE, IDC_TRIGPT5_TRACE, IDC_TRIGPT6_TRACE,
  44. IDC_TRIGPT7_TRACE, IDC_TRIGPT8_TRACE, IDC_TRIGPT9_TRACE,
  45. IDC_TRIGPT10_TRACE
  46. };
  47. const int gTrigPtBreakMap[NUM_TRIGPTS] =
  48. {
  49. IDC_TRIGPT1_BREAK, IDC_TRIGPT2_BREAK, IDC_TRIGPT3_BREAK,
  50. IDC_TRIGPT4_BREAK, IDC_TRIGPT5_BREAK, IDC_TRIGPT6_BREAK,
  51. IDC_TRIGPT7_BREAK, IDC_TRIGPT8_BREAK, IDC_TRIGPT9_BREAK,
  52. IDC_TRIGPT10_BREAK
  53. };
  54. const int gTrigPtTextMap[NUM_TRIGPTS] =
  55. {
  56. IDC_TRIGPT1_TEXT, IDC_TRIGPT2_TEXT, IDC_TRIGPT3_TEXT,
  57. IDC_TRIGPT4_TEXT, IDC_TRIGPT5_TEXT, IDC_TRIGPT6_TEXT,
  58. IDC_TRIGPT7_TEXT, IDC_TRIGPT8_TEXT, IDC_TRIGPT9_TEXT,
  59. IDC_TRIGPT10_TEXT
  60. };
  61. const int gTrigPtTraceTextMap[NUM_TRIGPTS] =
  62. {
  63. IDC_TRIGPT1_TRACE_TEXT, IDC_TRIGPT2_TRACE_TEXT,
  64. IDC_TRIGPT3_TRACE_TEXT, IDC_TRIGPT4_TRACE_TEXT,
  65. IDC_TRIGPT5_TRACE_TEXT, IDC_TRIGPT6_TRACE_TEXT,
  66. IDC_TRIGPT7_TRACE_TEXT, IDC_TRIGPT8_TRACE_TEXT,
  67. IDC_TRIGPT9_TRACE_TEXT, IDC_TRIGPT10_TRACE_TEXT
  68. };
  69. const int gTrigPtBreakTextMap[NUM_TRIGPTS] =
  70. {
  71. IDC_TRIGPT1_BREAK_TEXT, IDC_TRIGPT2_BREAK_TEXT,
  72. IDC_TRIGPT3_BREAK_TEXT, IDC_TRIGPT4_BREAK_TEXT,
  73. IDC_TRIGPT5_BREAK_TEXT, IDC_TRIGPT6_BREAK_TEXT,
  74. IDC_TRIGPT7_BREAK_TEXT, IDC_TRIGPT8_BREAK_TEXT,
  75. IDC_TRIGPT9_BREAK_TEXT, IDC_TRIGPT10_BREAK_TEXT
  76. };
  77. /*++
  78. @doc EXTERNAL
  79. @func int | WinMain | Program entry point.
  80. @parm IN HINSTANCE | hInstance | Instance handle.
  81. @parm IN HINSTANCE | hPrevInstance | Handle of previous instance.
  82. @parm IN LPSTR | pszCmdLine | Points to the command line string.
  83. @parm IN int | nCmdShow | Show state.
  84. @rvalue Always returns 0.
  85. --*/
  86. int WINAPI
  87. WinMain(
  88. IN HINSTANCE hInstance,
  89. IN HINSTANCE hPrevInstance,
  90. IN LPSTR pszCmdLine,
  91. IN int nCmdShow
  92. )
  93. {
  94. TRTRACEPROC("WinMain", 1)
  95. int rc = -1;
  96. TRENTER(("(hInstance=%x,hPrevInstance=%x,CmdLine=%s,CmdShow=%x)\n",
  97. hInstance, hPrevInstance, pszCmdLine, nCmdShow));
  98. if (TracerInit(hInstance, nCmdShow))
  99. {
  100. MSG msg;
  101. //
  102. // Message pump.
  103. //
  104. while (GetMessage(&msg, NULL, 0, 0))
  105. {
  106. // if ((ghDlgSettings == 0) || !IsDialogMessage(ghDlgSettings, &msg))
  107. {
  108. // if (TranslateAccelerator(ghwndTracer, )
  109. {
  110. TranslateMessage(&msg);
  111. DispatchMessage(&msg);
  112. }
  113. }
  114. }
  115. rc = (int)msg.wParam;
  116. }
  117. TREXIT(("=%x\n", rc));
  118. return rc;
  119. } //WinMain
  120. /*++
  121. @doc INTERNAL
  122. @func BOOL | TracerInit | Initialize tracer.
  123. @parm IN HINSTANCE | hInstance | Instance handle.
  124. @parm IN int | nCmdShow | Show state.
  125. @rvalue Always returns 0.
  126. --*/
  127. BOOL
  128. TracerInit(
  129. IN HINSTANCE hInstance,
  130. IN int nCmdShow
  131. )
  132. {
  133. TRTRACEPROC("TracerInit", 2)
  134. BOOL rc = FALSE;
  135. TRENTER(("(hInstance=%x,CmdShow=%x)\n", hInstance, nCmdShow));
  136. if ((rc = RegisterTracerClass(hInstance)) == FALSE)
  137. {
  138. TRERRPRINT(("Failed to register tracer class.\n"));
  139. }
  140. else
  141. {
  142. InitializeListHead(&glistClients);
  143. ghServerThread = (HANDLE)_beginthread(ServerThread,
  144. 0,
  145. 0);
  146. if (ghServerThread != (HANDLE)-1)
  147. {
  148. ghInstance = hInstance;
  149. LoadStringA(hInstance, IDS_APP, gszApp, sizeof(gszApp));
  150. ghStdCursor = LoadCursorA(NULL,
  151. (LPSTR)MAKEINTRESOURCE(IDC_IBEAM));
  152. ghWaitCursor = LoadCursorA(NULL,
  153. (LPSTR)MAKEINTRESOURCE(IDC_WAIT));
  154. ghwndTracer = CreateWindowA(gpszWinTraceClass,
  155. "",
  156. WS_OVERLAPPEDWINDOW,
  157. //BUGBUG: get/save location from reg.
  158. CW_USEDEFAULT,
  159. CW_USEDEFAULT,
  160. CW_USEDEFAULT,
  161. CW_USEDEFAULT,
  162. NULL,
  163. NULL,
  164. hInstance,
  165. NULL);
  166. if (ghwndTracer != 0)
  167. {
  168. int size, len;
  169. PSZ psz;
  170. psz = gszSaveFilterSpec;
  171. size = sizeof(gszSaveFilterSpec);
  172. len = LoadStringA(ghInstance, IDS_TEXTFILES, psz, size) + 1;
  173. psz += len;
  174. size -= len;
  175. lstrcpyA(psz, "*.txt");
  176. len = lstrlenA(psz) + 1;
  177. psz += len;
  178. size -= len;
  179. len = LoadStringA(ghInstance, IDS_ALLFILES, psz, size) + 1;
  180. psz += len;
  181. size -= len;
  182. lstrcpyA(psz, "*.*");
  183. len = lstrlenA(psz) + 1;
  184. psz += len;
  185. *psz = '\0';
  186. gdwfTracer = TF_UNTITLED;
  187. SetTitle(NULL);
  188. ShowWindow(ghwndTracer, nCmdShow);
  189. }
  190. else
  191. {
  192. rc = FALSE;
  193. TRERRPRINT(("Failed to create tracer window.\n"));
  194. }
  195. rc = TRUE;
  196. }
  197. else
  198. {
  199. ghServerThread = NULL;
  200. TRERRPRINT(("Failed to create server thread.\n"));
  201. }
  202. }
  203. TREXIT(("=%x\n", rc));
  204. return rc;
  205. } //TracerInit
  206. /*++
  207. @doc INTERNAL
  208. @func BOOL | RegisterTracerClass | Register tracer window class.
  209. @parm IN HINSTANCE | hInstance | Instance handle.
  210. @rvalue SUCCESS | Returns TRUE.
  211. @rvalue SUCCESS | Returns FALSE.
  212. --*/
  213. BOOL
  214. RegisterTracerClass(
  215. IN HINSTANCE hInstance
  216. )
  217. {
  218. TRTRACEPROC("RegisterTracerClass", 2)
  219. BOOL rc;
  220. WNDCLASSEXA wcex;
  221. TRENTER(("(hInstance=%x)\n", hInstance));
  222. wcex.cbSize = sizeof(wcex);
  223. wcex.style = 0;
  224. wcex.lpfnWndProc = TracerWndProc;
  225. wcex.cbClsExtra = 0;
  226. wcex.cbWndExtra = 0;
  227. wcex.hInstance = hInstance;
  228. wcex.hIcon = LoadIconA(hInstance, (LPSTR)MAKEINTRESOURCE(IDI_TRACER));
  229. wcex.hCursor = LoadCursorA(NULL, (LPSTR)MAKEINTRESOURCE(IDC_ARROW));
  230. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  231. wcex.lpszMenuName = (LPSTR)MAKEINTRESOURCE(IDD_MENU);
  232. wcex.lpszClassName = gpszWinTraceClass;
  233. wcex.hIconSm = NULL;
  234. rc = RegisterClassExA(&wcex) != 0;
  235. TREXIT(("=%x\n", rc));
  236. return rc;
  237. } //RegisterTracerClass
  238. /*++
  239. @doc EXTERNAL
  240. @func LRESULT | TracerWndProc | Window procedure for Tracer.
  241. @parm IN HWND | hwnd | Window handle.
  242. @parm IN UINT | uiMsg | Message ID.
  243. @parm IN WPARAM | wParam | First message parameter.
  244. @parm IN LPARAM | lParam | Second message parameter.
  245. @rvalue Return value is message specific.
  246. --*/
  247. LRESULT CALLBACK
  248. TracerWndProc(
  249. IN HWND hwnd,
  250. IN UINT uiMsg,
  251. IN WPARAM wParam,
  252. IN LPARAM lParam
  253. )
  254. {
  255. TRTRACEPROC("TracerWndProc", 3)
  256. LRESULT rc = 0;
  257. TRENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
  258. hwnd, LookupName(uiMsg, WMMsgNames), wParam, lParam));
  259. switch (uiMsg)
  260. {
  261. case WM_CREATE:
  262. {
  263. ghwndEdit = CreateWindowExA(WS_EX_CLIENTEDGE,
  264. "Edit",
  265. "",
  266. (gdwfTracer & TF_LINEWRAP)?
  267. ES_STD:
  268. (ES_STD | WS_HSCROLL),
  269. 0,
  270. 0,
  271. 0,
  272. 0,
  273. hwnd,
  274. NULL,
  275. ghInstance,
  276. NULL);
  277. if (ghwndEdit != NULL)
  278. {
  279. HDC hDC;
  280. hDC = GetDC(NULL);
  281. if (hDC != NULL)
  282. {
  283. INITCOMMONCONTROLSEX ComCtrl;
  284. SendMessage(ghwndEdit, EM_LIMITTEXT, 0, 0);
  285. ghFont = GetStockObject(SYSTEM_FIXED_FONT);
  286. GetObject(ghFont, sizeof(gLogFont), &gLogFont);
  287. gLogFont.lfHeight = -MulDiv(giPointSize,
  288. GetDeviceCaps(hDC,
  289. LOGPIXELSY),
  290. 720);
  291. ghFont = CreateFontIndirect(&gLogFont);
  292. TRASSERT(ghFont != 0);
  293. SendMessage(ghwndEdit,
  294. WM_SETFONT,
  295. (WPARAM)ghFont,
  296. MAKELONG(FALSE, 0));
  297. ReleaseDC(NULL, hDC);
  298. ComCtrl.dwSize = sizeof(ComCtrl);
  299. ComCtrl.dwICC = ICC_BAR_CLASSES | ICC_USEREX_CLASSES;
  300. if (!InitCommonControlsEx(&ComCtrl))
  301. {
  302. DestroyWindow(ghwndEdit);
  303. TRERRPRINT(("Failed to initialize Common Control\n"));
  304. rc = -1;
  305. }
  306. }
  307. else
  308. {
  309. DestroyWindow(ghwndEdit);
  310. TRERRPRINT(("Failed to get display DC\n"));
  311. rc = -1;
  312. }
  313. }
  314. else
  315. {
  316. TRERRPRINT(("Failed to create edit window.\n"));
  317. rc = -1;
  318. }
  319. break;
  320. }
  321. case WM_DESTROY:
  322. {
  323. PLIST_ENTRY plist;
  324. PCLIENT_ENTRY ClientEntry;
  325. while (!IsListEmpty(&glistClients))
  326. {
  327. plist = glistClients.Flink;
  328. ClientEntry = CONTAINING_RECORD(plist,
  329. CLIENT_ENTRY,
  330. list);
  331. WTDeregisterClient(NULL, (HCLIENT)ClientEntry);
  332. }
  333. DeleteObject(ghFont);
  334. DestroyWindow(ghwndEdit);
  335. PostQuitMessage(0);
  336. break;
  337. }
  338. case WM_COMMAND:
  339. if ((HWND)lParam == ghwndEdit)
  340. {
  341. switch (HIWORD(wParam))
  342. {
  343. case EN_ERRSPACE:
  344. case EN_MAXTEXT:
  345. ErrorMsg(IDS_ERRSPACE);
  346. break;
  347. }
  348. }
  349. else if (!TracerCmdProc(hwnd, wParam, lParam))
  350. {
  351. rc = DefWindowProc(hwnd, uiMsg, wParam, lParam);
  352. }
  353. break;
  354. case WM_SETFOCUS:
  355. SetFocus(ghwndEdit);
  356. break;
  357. case WM_SIZE:
  358. MoveWindow(ghwndEdit,
  359. 0,
  360. 0,
  361. LOWORD(lParam),
  362. HIWORD(lParam),
  363. TRUE);
  364. break;
  365. default:
  366. rc = DefWindowProc(hwnd, uiMsg, wParam, lParam);
  367. }
  368. TREXIT(("=%x\n", rc));
  369. return rc;
  370. } //TracerWndProc
  371. /*++
  372. @doc INTERNAL
  373. @func LRESULT | TracerCmdProc | Process the WM_COMMAND message.
  374. @parm IN HWND | hwnd | Window handle.
  375. @parm IN WPARAM | wParam | First message parameter.
  376. @parm IN LPARAM | lParam | Second message parameter.
  377. @rvalue Return value is message specific.
  378. --*/
  379. LRESULT
  380. TracerCmdProc(
  381. IN HWND hwnd,
  382. IN WPARAM wParam,
  383. IN LPARAM lParam
  384. )
  385. {
  386. TRTRACEPROC("TracerCmdProc", 3)
  387. LRESULT rc = 0;
  388. TRENTER(("(hwnd=%x,wParam=%x,lParam=%x)\n", hwnd, wParam, lParam));
  389. switch (LOWORD(wParam))
  390. {
  391. case M_SAVE:
  392. if (!(gdwfTracer & TF_UNTITLED) &&
  393. SaveFile(hwnd, gszFileName, FALSE))
  394. {
  395. break;
  396. }
  397. //
  398. // Otherwise, fall through.
  399. //
  400. case M_SAVEAS:
  401. {
  402. OPENFILENAMEA ofn;
  403. char szFileName[MAX_PATH + 1] = "";
  404. char szSaveAs[16];
  405. memset(&ofn, 0, sizeof(ofn));
  406. LoadStringA(ghInstance, IDS_SAVEAS, szSaveAs, sizeof(szSaveAs));
  407. ofn.lStructSize = sizeof(ofn);
  408. ofn.hwndOwner = ghwndTracer;
  409. ofn.hInstance = ghInstance;
  410. ofn.lpstrFilter = gszSaveFilterSpec;
  411. ofn.nFilterIndex = 1;
  412. ofn.lpstrFile = szFileName;
  413. ofn.nMaxFile = sizeof(szFileName);
  414. if (gdwfTracer & TF_UNTITLED)
  415. {
  416. lstrcpyA(szFileName, "*.txt");
  417. }
  418. else
  419. {
  420. lstrcpynA(szFileName, gszFileName, MAX_PATH);
  421. szFileName[MAX_PATH] = '\0';
  422. }
  423. ofn.lpstrTitle = szSaveAs;
  424. ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
  425. OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
  426. ofn.lpstrDefExt = "txt";
  427. if (GetSaveFileNameA(&ofn))
  428. {
  429. if (SaveFile(hwnd, szFileName, TRUE))
  430. {
  431. lstrcpynA(gszFileName, szFileName, MAX_PATH);
  432. gdwfTracer &= ~TF_UNTITLED;
  433. SetTitle(NULL);
  434. }
  435. }
  436. else
  437. {
  438. DWORD dwErr = CommDlgExtendedError();
  439. if (dwErr != 0)
  440. {
  441. ErrorMsg(IDS_GETSAVEFILENAME_FAILED, dwErr);
  442. }
  443. }
  444. break;
  445. }
  446. case M_PRINT:
  447. //
  448. // BUGBUG
  449. //
  450. break;
  451. case M_EXIT:
  452. PostMessage(hwnd, WM_CLOSE, 0, 0);
  453. break;
  454. case M_CLEAR:
  455. SendMessage(ghwndEdit, EM_SETSEL, 0, -1);
  456. SendMessage(ghwndEdit, EM_REPLACESEL, 0, (LPARAM)"");
  457. break;
  458. case M_FIND:
  459. if (gszSearchText[0])
  460. {
  461. //BUGBUG SearchText(gszSearchText);
  462. break;
  463. }
  464. //
  465. // Otherwise, fall through.
  466. //
  467. case M_FINDNEXT:
  468. //
  469. // BUGBUG
  470. //
  471. case M_GOTO:
  472. //BUGBUG
  473. break;
  474. case M_WORDWRAP:
  475. //BUGBUG
  476. break;
  477. case M_SETFONT:
  478. {
  479. HDC hDC;
  480. hDC = GetDC(NULL);
  481. if (hDC != NULL)
  482. {
  483. CHOOSEFONT cf;
  484. memset(&cf, 0, sizeof(cf));
  485. cf.lStructSize = sizeof(cf);
  486. cf.hwndOwner = hwnd;
  487. cf.lpLogFont = &gLogFont;
  488. gLogFont.lfHeight = -MulDiv(giPointSize,
  489. GetDeviceCaps(hDC, LOGPIXELSY),
  490. 720);
  491. cf.Flags = CF_SCREENFONTS | CF_NOVERTFONTS |
  492. CF_INITTOLOGFONTSTRUCT;
  493. cf.nFontType = SCREEN_FONTTYPE;
  494. ReleaseDC(NULL, hDC);
  495. if (ChooseFont(&cf))
  496. {
  497. HFONT hfontNew;
  498. SetCursor(ghWaitCursor);
  499. hfontNew = CreateFontIndirect(&gLogFont);
  500. if (hfontNew != NULL)
  501. {
  502. DeleteObject(ghFont);
  503. ghFont = hfontNew;
  504. SendMessage(ghwndEdit,
  505. WM_SETFONT,
  506. (WPARAM)ghFont,
  507. MAKELONG(TRUE, 0));
  508. giPointSize = cf.iPointSize;
  509. }
  510. SetCursor(ghStdCursor);
  511. }
  512. else
  513. {
  514. DWORD dwErr = CommDlgExtendedError();
  515. if (dwErr != 0)
  516. {
  517. ErrorMsg(IDS_CHOOSEFONT_FAILED, dwErr);
  518. }
  519. }
  520. }
  521. break;
  522. }
  523. case M_CLIENTS:
  524. {
  525. PROPSHEETHEADER psh;
  526. PLIST_ENTRY plist;
  527. psh.dwSize = sizeof(psh);
  528. psh.dwFlags = 0;
  529. psh.hwndParent = hwnd;
  530. psh.hInstance = ghInstance;
  531. psh.pszCaption = MAKEINTRESOURCE(IDS_CLIENT_SETTINGS);
  532. psh.nPages = 1;
  533. for (plist = glistClients.Flink;
  534. plist != &glistClients;
  535. plist = plist->Flink)
  536. {
  537. psh.nPages++;;
  538. }
  539. psh.phpage = LocalAlloc(LMEM_FIXED,
  540. sizeof(HPROPSHEETPAGE)*psh.nPages);
  541. psh.nStartPage = 0;
  542. CreatePropertyPages(psh.phpage);
  543. if (PropertySheet(&psh) < 0)
  544. {
  545. ErrorMsg(IDSERR_PROP_SHEET, GetLastError());
  546. }
  547. LocalFree(psh.phpage);
  548. break;
  549. }
  550. case M_HELP:
  551. //BUGBUG
  552. break;
  553. case M_ABOUT:
  554. ShellAboutA(hwnd,
  555. gszApp,
  556. "",
  557. LoadIconA(ghInstance,
  558. (LPCSTR)MAKEINTRESOURCE(IDI_TRACER)));
  559. break;
  560. }
  561. TREXIT(("=%x\n", rc));
  562. return rc;
  563. } //TracerCmdProc
  564. /*++
  565. @doc EXTERNAL
  566. @func INT_PTR | GlobalSettingsDlgProc | Global setting dialog procedure.
  567. @parm IN HWND | hwnd | Window handle.
  568. @parm IN UINT | uiMsg | Message ID.
  569. @parm IN WPARAM | wParam | First message parameter.
  570. @parm IN LPARAM | lParam | Second message parameter.
  571. @rvalue Return value is message specific.
  572. --*/
  573. INT_PTR APIENTRY
  574. GlobalSettingsDlgProc(
  575. IN HWND hwnd,
  576. IN UINT uiMsg,
  577. IN WPARAM wParam,
  578. IN LPARAM lParam
  579. )
  580. {
  581. TRTRACEPROC("GlobalSettingsDlgProc", 3)
  582. INT_PTR rc = 0;
  583. static SETTINGS GlobalSettings = {0};
  584. TRENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
  585. hwnd, LookupName(uiMsg, WMMsgNames), wParam, lParam));
  586. switch (uiMsg)
  587. {
  588. case WM_INITDIALOG:
  589. {
  590. ghwndPropSheet = GetParent(hwnd);
  591. GlobalSettings = gDefGlobalSettings;
  592. SendDlgItemMessage(hwnd,
  593. IDC_GLOBALVERBOSESPIN,
  594. UDM_SETRANGE,
  595. 0,
  596. MAKELONG(MAX_LEVELS, 0));
  597. SendDlgItemMessage(hwnd,
  598. IDC_GLOBALTRACESPIN,
  599. UDM_SETRANGE,
  600. 0,
  601. MAKELONG(MAX_LEVELS, 0));
  602. SendDlgItemMessage(hwnd,
  603. IDC_GLOBALVERBOSESPIN,
  604. UDM_SETPOS,
  605. 0,
  606. MAKELONG(GlobalSettings.iVerboseLevel, 0));
  607. SendDlgItemMessage(hwnd,
  608. IDC_GLOBALTRACESPIN,
  609. UDM_SETPOS,
  610. 0,
  611. MAKELONG(GlobalSettings.iTraceLevel, 0));
  612. CheckDlgButton(hwnd,
  613. IDC_GLOBALTRACEDEBUGGER,
  614. (GlobalSettings.dwfSettings &
  615. SETTINGS_TRACE_TO_DEBUGGER) != 0);
  616. rc = TRUE;
  617. break;
  618. }
  619. case WM_DESTROY:
  620. ghwndPropSheet = NULL;
  621. break;
  622. case WM_NOTIFY:
  623. {
  624. NMHDR *lpnm = (NMHDR *)lParam;
  625. switch (lpnm->code)
  626. {
  627. case PSN_APPLY:
  628. gDefGlobalSettings = GlobalSettings;
  629. break;
  630. }
  631. break;
  632. }
  633. case WM_COMMAND:
  634. {
  635. BOOL fChanged = FALSE;
  636. switch (LOWORD(wParam))
  637. {
  638. case IDC_GLOBALVERBOSE:
  639. case IDC_GLOBALTRACE:
  640. {
  641. switch (HIWORD(wParam))
  642. {
  643. BOOL fOK;
  644. int n;
  645. case EN_UPDATE:
  646. n = GetDlgItemInt(hwnd,
  647. LOWORD(wParam),
  648. &fOK,
  649. FALSE);
  650. if (fOK && (n <= MAX_LEVELS))
  651. {
  652. if (LOWORD(wParam) == IDC_GLOBALVERBOSE)
  653. {
  654. GlobalSettings.iVerboseLevel = n;
  655. }
  656. else
  657. {
  658. GlobalSettings.iTraceLevel = n;
  659. }
  660. fChanged = TRUE;
  661. }
  662. else
  663. {
  664. SetDlgItemInt(hwnd,
  665. LOWORD(wParam),
  666. (LOWORD(wParam) ==
  667. IDC_GLOBALVERBOSE)?
  668. GlobalSettings.iVerboseLevel:
  669. GlobalSettings.iTraceLevel,
  670. FALSE);
  671. SendMessage((HWND)lParam,
  672. EM_SETSEL,
  673. 0,
  674. -1);
  675. }
  676. break;
  677. }
  678. break;
  679. }
  680. case IDC_GLOBALTRACEDEBUGGER:
  681. if (IsDlgButtonChecked(hwnd, IDC_GLOBALTRACEDEBUGGER))
  682. {
  683. GlobalSettings.dwfSettings |=
  684. SETTINGS_TRACE_TO_DEBUGGER;
  685. }
  686. else
  687. {
  688. GlobalSettings.dwfSettings &=
  689. ~SETTINGS_TRACE_TO_DEBUGGER;
  690. }
  691. fChanged = TRUE;
  692. break;
  693. }
  694. if (fChanged)
  695. {
  696. SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0);
  697. }
  698. break;
  699. }
  700. }
  701. TREXIT(("=%x\n", rc));
  702. return rc;
  703. } //GlobalSettingsDlgProc
  704. /*++
  705. @doc EXTERNAL
  706. @func INT_PTR | ClientSettingsDlgProc | Client setting dialog procedure.
  707. @parm IN HWND | hwnd | Window handle.
  708. @parm IN UINT | uiMsg | Message ID.
  709. @parm IN WPARAM | wParam | First message parameter.
  710. @parm IN LPARAM | lParam | Second message parameter.
  711. @rvalue Return value is message specific.
  712. --*/
  713. INT_PTR APIENTRY
  714. ClientSettingsDlgProc(
  715. IN HWND hwnd,
  716. IN UINT uiMsg,
  717. IN WPARAM wParam,
  718. IN LPARAM lParam
  719. )
  720. {
  721. TRTRACEPROC("ClientSettingsDlgProc", 3)
  722. INT_PTR rc = 0;
  723. TRENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
  724. hwnd, LookupName(uiMsg, WMMsgNames), wParam, lParam));
  725. switch (uiMsg)
  726. {
  727. case WM_INITDIALOG:
  728. {
  729. PCLIENT_ENTRY ClientEntry =
  730. (PCLIENT_ENTRY)((LPPROPSHEETPAGE)lParam)->lParam;
  731. int i;
  732. ghwndPropSheet = GetParent(hwnd);
  733. SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)ClientEntry);
  734. SendServerRequest(ClientEntry,
  735. SRVREQ_GETCLIENTINFO,
  736. &ClientEntry->ClientInfo);
  737. SendDlgItemMessage(hwnd,
  738. IDC_CLIENTVERBOSESPIN,
  739. UDM_SETRANGE,
  740. 0,
  741. MAKELONG(MAX_LEVELS, 0));
  742. SendDlgItemMessage(hwnd,
  743. IDC_CLIENTTRACESPIN,
  744. UDM_SETRANGE,
  745. 0,
  746. MAKELONG(MAX_LEVELS, 0));
  747. SendDlgItemMessage(hwnd,
  748. IDC_CLIENTVERBOSESPIN,
  749. UDM_SETPOS,
  750. 0,
  751. MAKELONG(ClientEntry->ClientInfo.Settings.iVerboseLevel,
  752. 0));
  753. SendDlgItemMessage(hwnd,
  754. IDC_CLIENTTRACESPIN,
  755. UDM_SETPOS,
  756. 0,
  757. MAKELONG(ClientEntry->ClientInfo.Settings.iTraceLevel,
  758. 0));
  759. CheckDlgButton(hwnd,
  760. IDC_CLIENTTRACEDEBUGGER,
  761. (ClientEntry->ClientInfo.Settings.dwfSettings &
  762. SETTINGS_TRACE_TO_DEBUGGER) != 0);
  763. CheckDlgButton(hwnd,
  764. IDC_CLIENTTRIGGERTRACE,
  765. (ClientEntry->ClientInfo.Settings.dwfSettings &
  766. SETTINGS_TRIGMODE_ENABLED) != 0);
  767. for (i = 0; i < NUM_TRIGPTS; ++i)
  768. {
  769. SetDlgItemText(hwnd,
  770. gTrigPtCtrlMap[i],
  771. ClientEntry->ClientInfo.TrigPts[i].szProcName);
  772. CheckDlgButton(hwnd,
  773. gTrigPtTraceMap[i],
  774. (ClientEntry->ClientInfo.TrigPts[i].dwfTrigPt &
  775. TRIGPT_TRACE_ENABLED) != 0);
  776. CheckDlgButton(hwnd,
  777. gTrigPtBreakMap[i],
  778. (ClientEntry->ClientInfo.TrigPts[i].dwfTrigPt &
  779. TRIGPT_BREAK_ENABLED) != 0);
  780. }
  781. EnableTrigPts(hwnd,
  782. (ClientEntry->ClientInfo.Settings.dwfSettings &
  783. SETTINGS_TRIGMODE_ENABLED) != 0);
  784. rc = TRUE;
  785. break;
  786. }
  787. case WM_NOTIFY:
  788. {
  789. NMHDR *lpnm = (NMHDR *)lParam;
  790. switch (lpnm->code)
  791. {
  792. case PSN_APPLY:
  793. {
  794. PCLIENT_ENTRY ClientEntry;
  795. ClientEntry = (PCLIENT_ENTRY)GetWindowLongPtr(hwnd,
  796. DWLP_USER);
  797. if (ClientEntry != NULL)
  798. {
  799. ClientEntry->ClientInfo.Settings =
  800. ClientEntry->TempSettings;
  801. RtlCopyMemory(ClientEntry->ClientInfo.TrigPts,
  802. ClientEntry->TempTrigPts,
  803. sizeof(ClientEntry->ClientInfo.TrigPts));
  804. SendServerRequest(ClientEntry,
  805. SRVREQ_SETCLIENTINFO,
  806. &ClientEntry->ClientInfo);
  807. }
  808. else
  809. {
  810. TRWARNPRINT(("Notify: Failed to get Client Entry\n"));
  811. }
  812. break;
  813. }
  814. }
  815. break;
  816. }
  817. case WM_COMMAND:
  818. {
  819. BOOL fChanged = FALSE;
  820. PCLIENT_ENTRY ClientEntry;
  821. BOOL fTrace = FALSE;
  822. switch (LOWORD(wParam))
  823. {
  824. case IDC_CLIENTVERBOSE:
  825. case IDC_CLIENTTRACE:
  826. switch (HIWORD(wParam))
  827. {
  828. case EN_UPDATE:
  829. {
  830. BOOL fOK;
  831. int n;
  832. ClientEntry = (PCLIENT_ENTRY)GetWindowLongPtr(
  833. hwnd,
  834. DWLP_USER);
  835. if (ClientEntry != NULL)
  836. {
  837. n = GetDlgItemInt(hwnd,
  838. LOWORD(wParam),
  839. &fOK,
  840. FALSE);
  841. if (fOK && (n <= MAX_LEVELS))
  842. {
  843. if (LOWORD(wParam) == IDC_CLIENTVERBOSE)
  844. {
  845. ClientEntry->TempSettings.iVerboseLevel
  846. = n;
  847. }
  848. else
  849. {
  850. ClientEntry->TempSettings.iTraceLevel
  851. = n;
  852. }
  853. fChanged = TRUE;
  854. }
  855. else
  856. {
  857. SetDlgItemInt(
  858. hwnd,
  859. LOWORD(wParam),
  860. (LOWORD(wParam) == IDC_CLIENTVERBOSE)?
  861. ClientEntry->TempSettings.iVerboseLevel:
  862. ClientEntry->TempSettings.iTraceLevel,
  863. FALSE);
  864. SendMessage((HWND)lParam,
  865. EM_SETSEL,
  866. 0,
  867. -1);
  868. }
  869. }
  870. else
  871. {
  872. TRWARNPRINT(("Verbose/Trace: Failed to get Client Entry\n"));
  873. }
  874. break;
  875. }
  876. }
  877. break;
  878. case IDC_CLIENTTRACEDEBUGGER:
  879. case IDC_CLIENTTRIGGERTRACE:
  880. ClientEntry = (PCLIENT_ENTRY)GetWindowLongPtr(hwnd,
  881. DWLP_USER);
  882. if (ClientEntry != NULL)
  883. {
  884. DWORD dwf = (LOWORD(wParam) ==
  885. IDC_CLIENTTRACEDEBUGGER)?
  886. SETTINGS_TRACE_TO_DEBUGGER:
  887. SETTINGS_TRIGMODE_ENABLED;
  888. BOOL fChecked = IsDlgButtonChecked(hwnd,
  889. LOWORD(wParam));
  890. if (fChecked)
  891. {
  892. ClientEntry->TempSettings.dwfSettings |= dwf;
  893. }
  894. else
  895. {
  896. ClientEntry->TempSettings.dwfSettings &= ~dwf;
  897. }
  898. if (LOWORD(wParam) == IDC_CLIENTTRIGGERTRACE)
  899. {
  900. EnableTrigPts(hwnd, fChecked);
  901. }
  902. fChanged = TRUE;
  903. }
  904. else
  905. {
  906. TRWARNPRINT(("TraceToDebugger/TrigModeEnabled: Failed to get Client Entry\n"));
  907. }
  908. break;
  909. case IDC_TRIGPT1:
  910. case IDC_TRIGPT2:
  911. case IDC_TRIGPT3:
  912. case IDC_TRIGPT4:
  913. case IDC_TRIGPT5:
  914. case IDC_TRIGPT6:
  915. case IDC_TRIGPT7:
  916. case IDC_TRIGPT8:
  917. case IDC_TRIGPT9:
  918. case IDC_TRIGPT10:
  919. switch (HIWORD(wParam))
  920. {
  921. case EN_UPDATE:
  922. {
  923. int n;
  924. int iTrigPt;
  925. ClientEntry = (PCLIENT_ENTRY)GetWindowLongPtr(
  926. hwnd,
  927. DWLP_USER);
  928. if (ClientEntry != NULL)
  929. {
  930. iTrigPt = FindTrigPtIndex(LOWORD(wParam),
  931. gTrigPtCtrlMap);
  932. n = GetDlgItemTextA(
  933. hwnd,
  934. LOWORD(wParam),
  935. ClientEntry->TempTrigPts[iTrigPt].szProcName,
  936. MAX_PROCNAME_LEN - 1);
  937. if ((n > 0) ||
  938. (GetLastError() == ERROR_SUCCESS))
  939. {
  940. fChanged = TRUE;
  941. }
  942. else
  943. {
  944. TRWARNPRINT(("Failed to get trigger point text (err=%x)\n",
  945. GetLastError()));
  946. }
  947. }
  948. else
  949. {
  950. TRWARNPRINT(("TrigPt: Failed to get Client Entry\n"));
  951. }
  952. break;
  953. }
  954. }
  955. break;
  956. case IDC_TRIGPT1_TRACE:
  957. case IDC_TRIGPT2_TRACE:
  958. case IDC_TRIGPT3_TRACE:
  959. case IDC_TRIGPT4_TRACE:
  960. case IDC_TRIGPT5_TRACE:
  961. case IDC_TRIGPT6_TRACE:
  962. case IDC_TRIGPT7_TRACE:
  963. case IDC_TRIGPT8_TRACE:
  964. case IDC_TRIGPT9_TRACE:
  965. case IDC_TRIGPT10_TRACE:
  966. fTrace = TRUE;
  967. //
  968. // Fall through ...
  969. //
  970. case IDC_TRIGPT1_BREAK:
  971. case IDC_TRIGPT2_BREAK:
  972. case IDC_TRIGPT3_BREAK:
  973. case IDC_TRIGPT4_BREAK:
  974. case IDC_TRIGPT5_BREAK:
  975. case IDC_TRIGPT6_BREAK:
  976. case IDC_TRIGPT7_BREAK:
  977. case IDC_TRIGPT8_BREAK:
  978. case IDC_TRIGPT9_BREAK:
  979. case IDC_TRIGPT10_BREAK:
  980. {
  981. int iTrigPt;
  982. ClientEntry = (PCLIENT_ENTRY)GetWindowLongPtr(hwnd,
  983. DWLP_USER);
  984. if (ClientEntry != NULL)
  985. {
  986. DWORD dwf = fTrace? TRIGPT_TRACE_ENABLED:
  987. TRIGPT_BREAK_ENABLED;
  988. iTrigPt = FindTrigPtIndex(LOWORD(wParam),
  989. fTrace? gTrigPtTraceMap:
  990. gTrigPtBreakMap);
  991. if (IsDlgButtonChecked(hwnd, LOWORD(wParam)))
  992. {
  993. ClientEntry->TempTrigPts[iTrigPt].dwfTrigPt |= dwf;
  994. }
  995. else
  996. {
  997. ClientEntry->TempTrigPts[iTrigPt].dwfTrigPt &=
  998. ~dwf;
  999. }
  1000. fChanged = TRUE;
  1001. }
  1002. else
  1003. {
  1004. TRWARNPRINT(("TrigPtEnable: Failed to get Client Entry\n"));
  1005. }
  1006. break;
  1007. }
  1008. }
  1009. if (fChanged)
  1010. {
  1011. SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0);
  1012. }
  1013. break;
  1014. }
  1015. }
  1016. TREXIT(("=%x\n", rc));
  1017. return rc;
  1018. } //ClientSettingsDlgProc
  1019. /*++
  1020. @doc INTERNAL
  1021. @func VOID | EnableTrigPts | Enable trigger points controls.
  1022. @parm IN HWND | hDlg | Dialog box handle.
  1023. @parm IN BOOL | fEnable | TRUE if enable.
  1024. @rvalue None.
  1025. --*/
  1026. VOID
  1027. EnableTrigPts(
  1028. IN HWND hDlg,
  1029. IN BOOL fEnable
  1030. )
  1031. {
  1032. TRTRACEPROC("EnableTrigPts", 3)
  1033. int i;
  1034. TRENTER(("(hDlg=%x,fEnable=%x)\n", hDlg, fEnable));
  1035. EnableWindow(GetDlgItem(hDlg, IDC_CLIENTTRIGPTGROUPBOX), fEnable);
  1036. for (i = 0; i < NUM_TRIGPTS; ++i)
  1037. {
  1038. EnableWindow(GetDlgItem(hDlg, gTrigPtTextMap[i]), fEnable);
  1039. EnableWindow(GetDlgItem(hDlg, gTrigPtTraceTextMap[i]), fEnable);
  1040. EnableWindow(GetDlgItem(hDlg, gTrigPtBreakTextMap[i]), fEnable);
  1041. EnableWindow(GetDlgItem(hDlg, gTrigPtCtrlMap[i]), fEnable);
  1042. EnableWindow(GetDlgItem(hDlg, gTrigPtTraceMap[i]), fEnable);
  1043. EnableWindow(GetDlgItem(hDlg, gTrigPtBreakMap[i]), fEnable);
  1044. }
  1045. TREXIT(("!\n"));
  1046. return;
  1047. } //EnableTrigPts
  1048. /*++
  1049. @doc INTERNAL
  1050. @func BOOL | SaveFile | Save the text buffer to a file.
  1051. @parm IN HWND | hwndParent | Window handle parent.
  1052. @parm IN PSZ | pszFileName | Points to the file name string to save.
  1053. @parm IN BOOL | fSaveAs | TRUE if called from SaveAs.
  1054. @rvalue SUCCESS | Returns TRUE.
  1055. @rvalue FAILURE | Returns FALSE.
  1056. --*/
  1057. BOOL
  1058. SaveFile(
  1059. IN HWND hwndParent,
  1060. IN PSZ pszFileName,
  1061. IN BOOL fSaveAs
  1062. )
  1063. {
  1064. TRTRACEPROC("SaveFile", 3)
  1065. BOOL rc = FALSE;
  1066. HANDLE hFile;
  1067. TRENTER(("(hwnd=%x,File=%s,fSaveAs=%x)\n",
  1068. hwndParent, pszFileName, fSaveAs));
  1069. hFile = CreateFileA(pszFileName,
  1070. GENERIC_READ | GENERIC_WRITE,
  1071. FILE_SHARE_READ,
  1072. NULL,
  1073. fSaveAs? OPEN_ALWAYS: OPEN_EXISTING,
  1074. FILE_ATTRIBUTE_NORMAL,
  1075. NULL);
  1076. if (hFile != INVALID_HANDLE_VALUE)
  1077. {
  1078. BOOL fNew;
  1079. UINT uiTextSize;
  1080. HLOCAL hlText;
  1081. LPSTR lpch;
  1082. DWORD dwcbWritten;
  1083. fNew = (GetLastError() != ERROR_ALREADY_EXISTS);
  1084. uiTextSize = (UINT)SendMessage(ghwndEdit, WM_GETTEXTLENGTH, 0, 0);
  1085. hlText = (HLOCAL)SendMessage(ghwndEdit, EM_GETHANDLE, 0, 0);
  1086. if ((hlText != NULL) && ((lpch = (LPSTR)LocalLock(hlText)) != NULL))
  1087. {
  1088. rc = WriteFile(hFile,
  1089. lpch,
  1090. uiTextSize,
  1091. &dwcbWritten,
  1092. NULL);
  1093. if (rc == FALSE)
  1094. {
  1095. ErrorMsg(IDS_WRITEFILE_FAILED, pszFileName);
  1096. }
  1097. LocalUnlock(hlText);
  1098. }
  1099. else
  1100. {
  1101. TRERRPRINT(("Failed to get text length or get text handle\n"));
  1102. }
  1103. CloseHandle(hFile);
  1104. if ((rc == FALSE) && fNew)
  1105. {
  1106. DeleteFileA(pszFileName);
  1107. }
  1108. }
  1109. else
  1110. {
  1111. ErrorMsg(IDS_CREATEFILE_FAILED, pszFileName);
  1112. }
  1113. TREXIT(("=%x\n", rc));
  1114. return rc;
  1115. } //SaveFile
  1116. /*++
  1117. @doc INTERNAL
  1118. @func UINT | CreatePropertyPages | Create the global setting page as
  1119. well as a property page for each registered clients.
  1120. @parm OUT HPROPSHEETPAGE *| hPages | Points to the array to hold all
  1121. the created property sheet handles.
  1122. @rvalue SUCCESS | Returns number of pages created.
  1123. @rvalue FAILURE | Returns 0.
  1124. --*/
  1125. UINT
  1126. CreatePropertyPages(
  1127. OUT HPROPSHEETPAGE *hPages
  1128. )
  1129. {
  1130. TRTRACEPROC("CreatePropertyPages", 3)
  1131. UINT nPages = 0;
  1132. PROPSHEETPAGEA psp;
  1133. PLIST_ENTRY plist;
  1134. PCLIENT_ENTRY ClientEntry;
  1135. TRENTER(("(hPages=%p)\n", hPages));
  1136. psp.dwSize = sizeof(psp);
  1137. psp.dwFlags = 0;
  1138. psp.hInstance = ghInstance;
  1139. psp.pszTitle = NULL;
  1140. psp.lParam = 0;
  1141. psp.pszTemplate = (LPSTR)MAKEINTRESOURCE(IDD_GLOBALSETTINGS);
  1142. psp.pfnDlgProc = GlobalSettingsDlgProc;
  1143. hPages[nPages] = CreatePropertySheetPageA(&psp);
  1144. if (hPages[nPages] != NULL)
  1145. {
  1146. nPages++;
  1147. }
  1148. psp.dwFlags = PSP_USETITLE;
  1149. psp.pszTemplate = (LPSTR)MAKEINTRESOURCE(IDD_CLIENTSETTINGS);
  1150. psp.pfnDlgProc = ClientSettingsDlgProc;
  1151. for (plist = glistClients.Flink;
  1152. plist != &glistClients;
  1153. plist = plist->Flink)
  1154. {
  1155. ClientEntry = CONTAINING_RECORD(plist, CLIENT_ENTRY, list);
  1156. psp.pszTitle = ClientEntry->szClientName;
  1157. psp.lParam = (LPARAM)ClientEntry;
  1158. hPages[nPages] = CreatePropertySheetPageA(&psp);
  1159. if (hPages[nPages] != NULL)
  1160. {
  1161. ClientEntry->hPage = hPages[nPages];
  1162. nPages++;
  1163. }
  1164. }
  1165. TREXIT(("=%d\n", nPages));
  1166. return nPages;
  1167. } //CreatePropertyPages
  1168. /*++
  1169. @doc INTERNAL
  1170. @func VOID | SetTitle | Set the title bar text.
  1171. @parm IN PSZ | pszTitle | Points to title text string. If NULL, set
  1172. title to current file name.
  1173. @rvalue None.
  1174. --*/
  1175. VOID
  1176. SetTitle(
  1177. IN PSZ pszTitle OPTIONAL
  1178. )
  1179. {
  1180. TRTRACEPROC("SetTitle", 3)
  1181. char szWindowText[MAX_PATH + 16];
  1182. TRENTER(("(Title=%s)\n", pszTitle));
  1183. if (pszTitle != NULL)
  1184. {
  1185. lstrcpyA(szWindowText, pszTitle);
  1186. }
  1187. else
  1188. {
  1189. int len;
  1190. if (gdwfTracer & TF_UNTITLED)
  1191. {
  1192. LoadStringA(ghInstance,
  1193. IDS_UNTITLED,
  1194. szWindowText,
  1195. sizeof(szWindowText));
  1196. }
  1197. else
  1198. {
  1199. lstrcpynA(szWindowText, gszFileName, sizeof(szWindowText));
  1200. }
  1201. len = lstrlenA(szWindowText);
  1202. LoadStringA(ghInstance,
  1203. IDS_TITLE,
  1204. &szWindowText[len],
  1205. sizeof(szWindowText) - len);
  1206. }
  1207. SetWindowTextA(ghwndTracer, szWindowText);
  1208. TREXIT(("!\n"));
  1209. return;
  1210. } //SetTitle
  1211. /*++
  1212. @doc INTERNAL
  1213. @func int | FindTrigPtIndex | Find the trigger point index by its
  1214. control ID.
  1215. @parm IN int | iID | Dialog object control ID.
  1216. @parm IN const int * | IDTable | Points to the ID map.
  1217. @rvalue SUCCESS | Returns the trigger point index.
  1218. @rvalue FAILURE | Returns -1.
  1219. --*/
  1220. int
  1221. FindTrigPtIndex(
  1222. IN int iID,
  1223. IN const int *IDTable
  1224. )
  1225. {
  1226. TRTRACEPROC("FindTrigPtIndex", 3)
  1227. int i;
  1228. TRENTER(("(ID=%d,IDTable=%p)\n", iID, IDTable));
  1229. for (i = 0; i < NUM_TRIGPTS; ++i)
  1230. {
  1231. if (iID == IDTable[i])
  1232. {
  1233. break;
  1234. }
  1235. }
  1236. if (i == NUM_TRIGPTS)
  1237. {
  1238. i = -1;
  1239. }
  1240. TREXIT(("=%d\n", i));
  1241. return i;
  1242. } //FindTrigPtIndex
  1243. /*++
  1244. @doc INTERNAL
  1245. @func VOID | ErrorMsg | Put out an error message box.
  1246. @parm IN ULONG | ErrCode | The given error code.
  1247. @parm ... | Substituting arguments for the error message.
  1248. @rvalue Returns the number of chars in the message.
  1249. --*/
  1250. int
  1251. ErrorMsg(
  1252. IN ULONG ErrCode,
  1253. ...
  1254. )
  1255. {
  1256. static char szFormat[1024];
  1257. static char szErrMsg[1024];
  1258. int n;
  1259. va_list arglist;
  1260. LoadStringA(ghInstance, ErrCode, szFormat, sizeof(szFormat));
  1261. va_start(arglist, ErrCode);
  1262. n = wvsprintfA(szErrMsg, szFormat, arglist);
  1263. va_end(arglist);
  1264. MessageBoxA(NULL, szErrMsg, gszApp, MB_OK | MB_ICONERROR);
  1265. return n;
  1266. } //ErrorMsg