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.

3373 lines
90 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. prcdlg.cpp
  5. Abstract:
  6. Contains dialog-related functions.
  7. --*/
  8. #include "precomp.hxx"
  9. #pragma hdrstop
  10. #include <time.h>
  11. // Remote client workspaces do not contain engine information
  12. // since a remote client attaches to many engines and it's
  13. // rare that you'd want the same piece of engine information
  14. // applied to every connect.
  15. #define SAVE_ENGINE_WORKSPACE() \
  16. (g_Workspace != NULL && !g_RemoteClient)
  17. #define DIRTY_ENGINE_WORKSPACE(Flags) FALSE
  18. // Find dialog, if open.
  19. HWND g_FindDialog;
  20. // Find text.
  21. char g_FindText[256];
  22. // Message code for FINDMSGSTRING.
  23. UINT g_FindMsgString;
  24. FINDREPLACE g_FindRep;
  25. PCOMMONWIN_DATA g_FindLast;
  26. char g_ComSettings[64];
  27. char g_1394Settings[64];
  28. TCHAR szOpenExeArgs[2 * _MAX_PATH];
  29. TCHAR g_DlgString[2 * _MAX_PATH];
  30. TCHAR g_DlgString2[2 * _MAX_PATH];
  31. PCSTR g_ExecutionNames[] =
  32. {
  33. "enabled", "disabled", "output", "ignore"
  34. };
  35. PCSTR g_ContinueNames[] =
  36. {
  37. "handled", "not handled"
  38. };
  39. PSTR g_SymbolTypeNames[] =
  40. {
  41. "None", "COFF", "CodeView", "PDB", "Export", "Deferred", "Sym",
  42. "DIA",
  43. };
  44. PTSTR __cdecl
  45. BufferString(PTSTR Buffer, ULONG Size, ULONG StrId, ...)
  46. {
  47. va_list Args;
  48. TCHAR FmtStr[SHORT_MSG];
  49. Buffer[0] = 0;
  50. Buffer[Size - 1] = 0;
  51. Dbg(LoadString(g_hInst, StrId, FmtStr, _tsizeof(FmtStr)));
  52. va_start(Args, StrId);
  53. _vsnprintf(Buffer, Size, FmtStr, Args);
  54. va_end(Args);
  55. return Buffer;
  56. }
  57. void
  58. SendLockStatusMessage(HWND Win, UINT Msg, HRESULT Status)
  59. {
  60. TCHAR Str[SHORT_MSG];
  61. if (FAILED(Status))
  62. {
  63. BufferString(Str, _tsizeof(Str), ERR_Unable_To_Retrieve_Info,
  64. FormatStatusCode(Status), FormatStatus(Status));
  65. }
  66. else
  67. {
  68. BufferString(Str, _tsizeof(Str),
  69. STR_Retrieving_Information);
  70. }
  71. SendMessage(Win, Msg, 0, (LPARAM)Str);
  72. }
  73. BpStateType
  74. IsBpAtOffset(BpBufferData* DataIn, ULONG64 Offset, PULONG Id)
  75. {
  76. BpBufferData* Data;
  77. if (DataIn == NULL)
  78. {
  79. if (g_BpBuffer->UiLockForRead() != S_OK)
  80. {
  81. return BP_NONE;
  82. }
  83. Data = (BpBufferData*)g_BpBuffer->GetDataBuffer();
  84. }
  85. else
  86. {
  87. Data = DataIn;
  88. }
  89. ULONG i;
  90. BpStateType BpState = BP_NONE;
  91. for (i = 0; i < g_BpCount; i++)
  92. {
  93. if (Data->Offset != DEBUG_INVALID_OFFSET &&
  94. Data->Offset == Offset)
  95. {
  96. if (Data->Flags & DEBUG_BREAKPOINT_ENABLED)
  97. {
  98. BpState = BP_ENABLED;
  99. }
  100. else
  101. {
  102. BpState = BP_DISABLED;
  103. }
  104. if (Id != NULL)
  105. {
  106. *Id = Data->Id;
  107. }
  108. break;
  109. }
  110. Data++;
  111. }
  112. if (DataIn == NULL)
  113. {
  114. UnlockStateBuffer(g_BpBuffer);
  115. }
  116. return BpState;
  117. }
  118. BOOL
  119. GetBpBufferData(ULONG Index, BpBufferData* RetData)
  120. {
  121. if (Index >= g_BpCount ||
  122. g_BpBuffer->UiLockForRead() != S_OK)
  123. {
  124. return FALSE;
  125. }
  126. BpBufferData* Data = (BpBufferData*)g_BpBuffer->GetDataBuffer();
  127. *RetData = Data[Index];
  128. UnlockStateBuffer(g_BpBuffer);
  129. return TRUE;
  130. }
  131. void
  132. EnableBpButtons(BOOL UpdateThread)
  133. {
  134. HWND Dlg = g_BpBuffer->m_Win;
  135. LRESULT Sel = SendDlgItemMessage(Dlg, ID_SETBREAK_BREAKPOINT,
  136. LB_GETCURSEL, 0, 0);
  137. BOOL Enable = Sel != LB_ERR;
  138. EnableWindow(GetDlgItem(Dlg, ID_SETBREAK_REMOVE), Enable);
  139. EnableWindow(GetDlgItem(Dlg, ID_SETBREAK_DISABLE), Enable);
  140. EnableWindow(GetDlgItem(Dlg, ID_SETBREAK_ENABLE), Enable);
  141. if (UpdateThread)
  142. {
  143. BpBufferData Data;
  144. char Text[16];
  145. Text[0] = 0;
  146. if (Sel >= 0 &&
  147. GetBpBufferData((ULONG)Sel, &Data) &&
  148. Data.Thread != DEBUG_ANY_ID)
  149. {
  150. _itoa(Data.Thread, Text, 10);
  151. }
  152. SetWindowText(GetDlgItem(Dlg, ID_SETBREAK_THREAD), Text);
  153. }
  154. EnableWindow(GetDlgItem(Dlg, ID_SETBREAK_THREAD),
  155. GetWindowTextLength(GetDlgItem(Dlg,
  156. ID_SETBREAK_COMMAND)) > 0);
  157. }
  158. void
  159. FillBpList(HWND List)
  160. {
  161. HRESULT Status;
  162. ULONG Width;
  163. RECT ListRect;
  164. LRESULT ListSel = SendMessage(List, LB_GETCURSEL, 0, 0);
  165. SendMessage(List, WM_SETREDRAW, FALSE, 0);
  166. SendMessage(List, LB_RESETCONTENT, 0, 0);
  167. GetClientRect(List, &ListRect);
  168. Width = ListRect.right - ListRect.left;
  169. Status = g_BpBuffer->UiLockForRead();
  170. if (Status == S_OK)
  171. {
  172. PSTR Buf = (PSTR)g_BpBuffer->GetDataBuffer() + g_BpTextOffset;
  173. // Ignore trailing terminator.
  174. PSTR End = (PSTR)g_BpBuffer->GetDataBuffer() +
  175. g_BpBuffer->GetDataLen() - 1;
  176. while (Buf < End)
  177. {
  178. ULONG Len, BufWidth;
  179. Len = strlen(Buf) + 1;
  180. if (Len == 1)
  181. {
  182. // Break out on empty lines to avoid displaying
  183. // kernel internal breakpoint information and blank
  184. // line separating it from the normal breakpoints.
  185. break;
  186. }
  187. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Buf);
  188. // Extra char in Len due to terminator ensures there's
  189. // a character of extra space to the right side.
  190. BufWidth = g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth * Len;
  191. if (BufWidth > Width)
  192. {
  193. Width = BufWidth;
  194. }
  195. Buf += Len;
  196. }
  197. UnlockStateBuffer(g_BpBuffer);
  198. }
  199. else
  200. {
  201. SendLockStatusMessage(List, LB_ADDSTRING, Status);
  202. }
  203. SendMessage(List, LB_SETHORIZONTALEXTENT, Width, 0);
  204. SendMessage(List, WM_SETREDRAW, TRUE, 0);
  205. if (ListSel != LB_ERR)
  206. {
  207. SendMessage(List, LB_SETCURSEL, ListSel, 0);
  208. }
  209. EnableBpButtons(TRUE);
  210. }
  211. ULONG
  212. GetBpListId(HWND List)
  213. {
  214. LRESULT ListSel = SendMessage(List, LB_GETCURSEL, 0, 0);
  215. if (ListSel == LB_ERR)
  216. {
  217. return DEBUG_ANY_ID;
  218. }
  219. LRESULT Len = SendMessage(List, LB_GETTEXTLEN, ListSel, 0);
  220. PSTR Buf = (PSTR)malloc(Len + 1);
  221. if (Buf == NULL)
  222. {
  223. return DEBUG_ANY_ID;
  224. }
  225. SendMessage(List, LB_GETTEXT, ListSel, (LPARAM)Buf);
  226. ULONG Id;
  227. if (sscanf(Buf, "%d", &Id) != 1)
  228. {
  229. return DEBUG_ANY_ID;
  230. }
  231. else
  232. {
  233. return Id;
  234. }
  235. }
  236. // Space for "Pending: ".
  237. #define BP_PENDING_CHARS 9
  238. void
  239. AddBpCommandString(HWND List, PSTR Buf, ULONG Thread)
  240. {
  241. BOOL HasThread = FALSE;
  242. BOOL IsBpCmd = FALSE;
  243. PCSTR Scan;
  244. //
  245. // If the string looks like a real command just pass
  246. // it on for execution. Otherwise, assume it's
  247. // a code breakpoint address expression.
  248. //
  249. Scan = Buf + BP_PENDING_CHARS;
  250. if (*Scan == '~')
  251. {
  252. Scan++;
  253. HasThread = TRUE;
  254. // Skip optional thread indicator.
  255. if (*Scan == '.' || *Scan == '#')
  256. {
  257. Scan++;
  258. }
  259. else
  260. {
  261. while (*Scan >= '0' && *Scan <= '9')
  262. {
  263. Scan++;
  264. }
  265. }
  266. }
  267. if (*Scan == 'b' || *Scan == 'B')
  268. {
  269. Scan++;
  270. if (*Scan == 'a' || *Scan == 'A' ||
  271. *Scan == 'i' || *Scan == 'I' ||
  272. *Scan == 'p' || *Scan == 'P' ||
  273. *Scan == 'u' || *Scan == 'U' ||
  274. *Scan == 'w' || *Scan == 'W')
  275. {
  276. Scan++;
  277. // Skip optional bp id.
  278. while (*Scan >= '0' && *Scan <= '9')
  279. {
  280. Scan++;
  281. }
  282. if (*Scan == ' ')
  283. {
  284. IsBpCmd = TRUE;
  285. }
  286. }
  287. else if (*Scan == 'c' || *Scan == 'C' ||
  288. *Scan == 'd' || *Scan == 'D' ||
  289. *Scan == 'e' || *Scan == 'E')
  290. {
  291. Scan++;
  292. if (*Scan == ' ')
  293. {
  294. IsBpCmd = TRUE;
  295. }
  296. }
  297. }
  298. // Immediately add the breakpoint string to the listbox
  299. // to indicate that it's pending.
  300. memcpy(Buf, "Pending: ", BP_PENDING_CHARS);
  301. LRESULT Sel = SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Buf);
  302. if (Sel != LB_ERR && Sel != LB_ERRSPACE)
  303. {
  304. SendMessage(List, LB_SETCURSEL, Sel, 0);
  305. }
  306. Buf += BP_PENDING_CHARS;
  307. if (IsBpCmd)
  308. {
  309. if (HasThread || Thread == DEBUG_ANY_ID)
  310. {
  311. AddStringCommand(UIC_SILENT_EXECUTE, Buf);
  312. }
  313. else
  314. {
  315. PrintStringCommand(UIC_SILENT_EXECUTE, "~%d%s",
  316. Thread, Buf);
  317. }
  318. }
  319. else if (Thread == DEBUG_ANY_ID)
  320. {
  321. PrintStringCommand(UIC_SILENT_EXECUTE, "bu %s", Buf);
  322. }
  323. else
  324. {
  325. PrintStringCommand(UIC_SILENT_EXECUTE, "~%dbu %s", Thread, Buf);
  326. }
  327. }
  328. INT_PTR CALLBACK
  329. DlgProc_SetBreak(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  330. {
  331. static UINT s_CmdLen;
  332. HWND List;
  333. HWND Ctrl;
  334. ULONG Id;
  335. List = GetDlgItem(Hwnd, ID_SETBREAK_BREAKPOINT);
  336. switch(Message)
  337. {
  338. case WM_INITDIALOG:
  339. s_CmdLen = 0;
  340. g_BpBuffer->m_Win = Hwnd;
  341. SendMessage(List, WM_SETFONT, (WPARAM)g_Fonts[FONT_FIXED].Font, FALSE);
  342. SendMessage(List, LB_SETCURSEL, -1, 0);
  343. FillBpList(List);
  344. break;
  345. case WM_COMMAND:
  346. switch(LOWORD(Wpm))
  347. {
  348. case ID_SETBREAK_COMMAND:
  349. if (HIWORD(Wpm) == EN_CHANGE)
  350. {
  351. EnableBpButtons(FALSE);
  352. UINT NewLen = GetWindowTextLength
  353. (GetDlgItem(Hwnd, ID_SETBREAK_COMMAND));
  354. if (NewLen == 1 && s_CmdLen == 0)
  355. {
  356. // If we're starting a new breakpoint command
  357. // default the thread to nothing.
  358. SetWindowText(GetDlgItem(Hwnd, ID_SETBREAK_THREAD), "");
  359. }
  360. s_CmdLen = NewLen;
  361. }
  362. break;
  363. case ID_SETBREAK_BREAKPOINT:
  364. SetWindowText(GetDlgItem(Hwnd, ID_SETBREAK_COMMAND), "");
  365. EnableBpButtons(TRUE);
  366. break;
  367. case ID_SETBREAK_REMOVE:
  368. Id = GetBpListId(List);
  369. if (Id != DEBUG_ANY_ID)
  370. {
  371. SetWindowText(GetDlgItem(Hwnd, ID_SETBREAK_COMMAND), "");
  372. PrintStringCommand(UIC_SILENT_EXECUTE, "bc %d", Id);
  373. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_BREAKPOINTS);
  374. }
  375. break;
  376. case ID_SETBREAK_REMOVEALL:
  377. SetWindowText(GetDlgItem(Hwnd, ID_SETBREAK_COMMAND), "");
  378. AddStringCommand(UIC_SILENT_EXECUTE, "bc *");
  379. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_BREAKPOINTS);
  380. break;
  381. case ID_SETBREAK_ENABLE:
  382. case ID_SETBREAK_DISABLE:
  383. Id = GetBpListId(List);
  384. if (Id != DEBUG_ANY_ID)
  385. {
  386. SetWindowText(GetDlgItem(Hwnd, ID_SETBREAK_COMMAND), "");
  387. PrintStringCommand(UIC_SILENT_EXECUTE, "b%c %d",
  388. LOWORD(Wpm) == ID_SETBREAK_ENABLE ?
  389. 'e' : 'd', Id);
  390. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_BREAKPOINTS);
  391. }
  392. break;
  393. case IDHELP:
  394. OpenHelpTopic(HELP_TOPIC_POPUP_BREAKPOINTS);
  395. break;
  396. case IDOK:
  397. char Buf[1024 + BP_PENDING_CHARS];
  398. UINT Thread;
  399. BOOL ThreadValid;
  400. Thread = GetDlgItemInt(Hwnd, ID_SETBREAK_THREAD,
  401. &ThreadValid, FALSE);
  402. if (!ThreadValid)
  403. {
  404. Thread = DEBUG_ANY_ID;
  405. }
  406. Ctrl = GetDlgItem(Hwnd, ID_SETBREAK_COMMAND);
  407. if (SendMessage(Ctrl, WM_GETTEXT, sizeof(Buf) - BP_PENDING_CHARS,
  408. (LPARAM)(Buf + BP_PENDING_CHARS)) > 0)
  409. {
  410. AddBpCommandString(List, Buf, Thread);
  411. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_BREAKPOINTS);
  412. SendMessage(Ctrl, WM_SETTEXT, 0, (LPARAM)"");
  413. // A command was executed so do not close the dialog.
  414. break;
  415. }
  416. // No command so fall through to close dialog.
  417. case IDCANCEL:
  418. g_BpBuffer->m_Win = NULL;
  419. EndDialog(Hwnd, LOWORD(Wpm));
  420. break;
  421. }
  422. break;
  423. case LB_RESETCONTENT:
  424. FillBpList(List);
  425. break;
  426. default:
  427. return FALSE;
  428. }
  429. return TRUE;
  430. }
  431. UINT_PTR
  432. OpenExeWithArgsHookProc(
  433. HWND hDlg,
  434. UINT msg,
  435. WPARAM wParam,
  436. LPARAM lParam
  437. )
  438. /*++
  439. Routine Description:
  440. Allows the user to specify command line arguments when opening an
  441. executable.
  442. Return Value:
  443. TRUE if we replaced default processing of the message, FALSE otherwise
  444. --*/
  445. {
  446. switch(msg)
  447. {
  448. case WM_INITDIALOG:
  449. CheckDlgButton(hDlg, IDC_EXEOPEN_CHILD_PROCESSES, FALSE);
  450. return TRUE;
  451. case WM_NOTIFY:
  452. if (((LPOFNOTIFY) lParam)->hdr.code == CDN_FILEOK)
  453. {
  454. *szOpenExeArgs = _T(' ');
  455. GetDlgItemText(hDlg,
  456. IDC_EDIT_ARGS,
  457. szOpenExeArgs + 1,
  458. sizeof(szOpenExeArgs) - 1);
  459. if (IsDlgButtonChecked(hDlg, IDC_EXEOPEN_CHILD_PROCESSES) ==
  460. BST_CHECKED)
  461. {
  462. g_DebugCreateFlags |= DEBUG_PROCESS;
  463. g_DebugCreateFlags &= ~DEBUG_ONLY_THIS_PROCESS;
  464. }
  465. else
  466. {
  467. g_DebugCreateFlags &= ~DEBUG_PROCESS;
  468. g_DebugCreateFlags |= DEBUG_ONLY_THIS_PROCESS;
  469. }
  470. return 0;
  471. }
  472. }
  473. return DlgFile(hDlg, msg, wParam, lParam);
  474. }
  475. #define NO_SERVERS "No servers registered"
  476. void
  477. FillServersList(HWND List, PCSTR Machine)
  478. {
  479. HRESULT Status;
  480. g_pUiClient->SetOutputCallbacks(&g_UiOutStateBuf);
  481. g_UiOutStateBuf.SetBuffer(&g_UiOutputCapture);
  482. g_UiOutStateBuf.Start(TRUE);
  483. Status = g_pUiClient->OutputServers(DEBUG_OUTCTL_THIS_CLIENT, Machine,
  484. DEBUG_SERVERS_DEBUGGER);
  485. g_pUiClient->SetOutputCallbacks(NULL);
  486. if (Status == S_OK)
  487. {
  488. Status = g_UiOutStateBuf.End(FALSE);
  489. }
  490. else
  491. {
  492. g_UiOutStateBuf.End(FALSE);
  493. }
  494. g_UiOutStateBuf.ReplaceChar('\n', 0);
  495. SendMessage(List, LB_RESETCONTENT, 0, 0);
  496. if (Status == S_OK)
  497. {
  498. PSTR Line, End;
  499. Line = (PSTR)g_UiOutputCapture.GetDataBuffer();
  500. End = Line + g_UiOutputCapture.GetDataLen() - 1;
  501. if (Line == NULL || Line >= End)
  502. {
  503. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)NO_SERVERS);
  504. }
  505. else
  506. {
  507. while (Line < End)
  508. {
  509. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Line);
  510. Line += strlen(Line) + 1;
  511. }
  512. }
  513. }
  514. else
  515. {
  516. SendLockStatusMessage(List, LB_ADDSTRING, Status);
  517. }
  518. SendMessage(List, LB_SETCURSEL, 0, 0);
  519. g_UiOutputCapture.Free();
  520. }
  521. INT_PTR CALLBACK
  522. DlgProc_BrowseServers(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  523. {
  524. char Machine[128];
  525. LRESULT Sel;
  526. switch(Message)
  527. {
  528. case WM_INITDIALOG:
  529. SendDlgItemMessage(Hwnd, IDC_BROWSE_MACHINE, EM_LIMITTEXT,
  530. sizeof(Machine) - 1, 0);
  531. SetWindowText(GetDlgItem(Hwnd, IDC_BROWSE_MACHINE), "");
  532. break;
  533. case WM_COMMAND:
  534. switch(LOWORD(Wpm))
  535. {
  536. case IDC_BROWSE_REFRESH:
  537. if (SendDlgItemMessage(Hwnd, IDC_BROWSE_MACHINE, WM_GETTEXT,
  538. sizeof(Machine), (LPARAM)Machine))
  539. {
  540. FillServersList(GetDlgItem(Hwnd, IDC_BROWSE_SERVERS_LIST),
  541. Machine);
  542. }
  543. break;
  544. case IDC_BROWSE_SERVERS_LIST:
  545. switch(HIWORD(Wpm))
  546. {
  547. case LBN_DBLCLK:
  548. Wpm = IDOK;
  549. goto SelectAndEnd;
  550. }
  551. break;
  552. case IDHELP:
  553. OpenHelpTopic(HELP_TOPIC_POPUP_CONNECT_TO_REMOTE_SESSION);
  554. break;
  555. case IDOK:
  556. SelectAndEnd:
  557. Sel = SendDlgItemMessage(Hwnd, IDC_BROWSE_SERVERS_LIST,
  558. LB_GETCURSEL, 0, 0);
  559. if (Sel >= 0 &&
  560. SendDlgItemMessage(Hwnd, IDC_BROWSE_SERVERS_LIST,
  561. LB_GETTEXT, Sel, (LPARAM)g_DlgString) > 0 &&
  562. strcmp(g_DlgString, NO_SERVERS) &&
  563. SendDlgItemMessage(Hwnd, IDC_BROWSE_MACHINE, WM_GETTEXT,
  564. sizeof(Machine), (LPARAM)Machine))
  565. {
  566. strcat(g_DlgString, ",Server=");
  567. strcat(g_DlgString, Machine);
  568. }
  569. else
  570. {
  571. g_DlgString[0] = 0;
  572. }
  573. // Fall through.
  574. case IDCANCEL:
  575. EndDialog(Hwnd, LOWORD(Wpm));
  576. break;
  577. }
  578. break;
  579. default:
  580. return FALSE;
  581. }
  582. return FALSE;
  583. }
  584. INT_PTR CALLBACK
  585. DlgProc_ConnectToRemote(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  586. {
  587. TCHAR ConnectString[1024];
  588. switch (Message)
  589. {
  590. case WM_INITDIALOG:
  591. //
  592. // Set up the controls to reflect current values
  593. //
  594. SendDlgItemMessage(Hwnd, IDC_REM_CONNECT, EM_LIMITTEXT,
  595. sizeof(ConnectString) - 1, 0);
  596. SetWindowText(GetDlgItem(Hwnd, IDC_REM_CONNECT), "");
  597. break;
  598. case WM_COMMAND:
  599. switch(LOWORD(Wpm))
  600. {
  601. case IDC_REM_BROWSE:
  602. if (StartDialog(IDD_DLG_BROWSE_SERVERS, DlgProc_BrowseServers,
  603. NULL) == IDOK && g_DlgString[0])
  604. {
  605. // Skip "<Server type> - " at the beginning.
  606. PSTR Start = strchr(g_DlgString, '-');
  607. if (Start != NULL)
  608. {
  609. SetWindowText(GetDlgItem(Hwnd, IDC_REM_CONNECT),
  610. Start + 2);
  611. }
  612. }
  613. break;
  614. case IDHELP:
  615. OpenHelpTopic(HELP_TOPIC_POPUP_CONNECT_TO_REMOTE_SESSION);
  616. break;
  617. case IDOK:
  618. if (SendDlgItemMessage(Hwnd, IDC_REM_CONNECT, WM_GETTEXT,
  619. sizeof(ConnectString),
  620. (LPARAM)ConnectString))
  621. {
  622. if (CreateUiInterfaces(TRUE, ConnectString))
  623. {
  624. StartDebugging();
  625. EndDialog(Hwnd, IDOK);
  626. }
  627. else if (!CreateUiInterfaces(FALSE, NULL))
  628. {
  629. // CreateUiInterfaces discards any previous
  630. // interfaces so we need to recreate something
  631. // so there are UI thread interfaces.
  632. InformationBox(ERR_Internal_Error, E_OUTOFMEMORY,
  633. "CreateUiInterfaces");
  634. ErrorExit(NULL, "Unable to recreate UI interfaces\n");
  635. }
  636. }
  637. return TRUE;
  638. case IDCANCEL:
  639. EndDialog(Hwnd, IDCANCEL);
  640. break;
  641. }
  642. break;
  643. default:
  644. return FALSE;
  645. }
  646. return FALSE;
  647. }
  648. INT_PTR
  649. CALLBACK
  650. DlgProc_SymbolPath(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  651. {
  652. TCHAR SymPath[MAX_ENGINE_PATH];
  653. ULONG PathSize;
  654. LRESULT Size;
  655. HRESULT Hr;
  656. switch (Message)
  657. {
  658. case WM_INITDIALOG:
  659. Hr = g_pUiSymbols->GetSymbolPath(SymPath, _tsizeof(SymPath),
  660. &PathSize);
  661. if (Hr != S_OK)
  662. {
  663. InformationBox(ERR_Internal_Error, Hr, "UI GetSymPath");
  664. }
  665. SendDlgItemMessage(Hwnd, IDC_SYMPATH, WM_SETTEXT, 0, (LPARAM)SymPath);
  666. //
  667. // Set up the controls to reflect current values
  668. //
  669. break;
  670. case WM_COMMAND:
  671. switch(LOWORD(Wpm))
  672. {
  673. case IDHELP:
  674. OpenHelpTopic(HELP_TOPIC_POPUP_SYMBOL_PATH);
  675. break;
  676. case IDOK:
  677. Size = SendDlgItemMessage(Hwnd, IDC_SYMPATH, WM_GETTEXT,
  678. sizeof(SymPath), (LPARAM)SymPath);
  679. if (Size == 0)
  680. {
  681. InformationBox(ERR_Path_Empty);
  682. SetFocus(Hwnd);
  683. return TRUE;
  684. }
  685. SymPath[Size] = 0;
  686. Hr = g_pUiSymbols->SetSymbolPath(SymPath);
  687. if (Hr != S_OK)
  688. {
  689. InformationBox(ERR_Internal_Error, Hr, "UI SetSymPath");
  690. }
  691. if (SAVE_ENGINE_WORKSPACE())
  692. {
  693. g_Workspace->SetString(WSP_GLOBAL_SYMBOL_PATH, SymPath);
  694. }
  695. EndDialog(Hwnd, IDOK);
  696. break;
  697. case IDCANCEL:
  698. EndDialog(Hwnd, IDCANCEL);
  699. break;
  700. }
  701. break;
  702. default:
  703. return FALSE;
  704. }
  705. return FALSE;
  706. }
  707. INT_PTR CALLBACK
  708. DlgProc_RegCustomize(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  709. {
  710. CPUWIN_DATA* CpuWin;
  711. switch(Message)
  712. {
  713. case WM_INITDIALOG:
  714. SetWindowLongPtr(Hwnd, DWLP_USER, Lpm);
  715. GetRegisterMapText(GetDlgItem(Hwnd, IDC_REGCUST_ENTRY));
  716. break;
  717. case WM_COMMAND:
  718. switch(LOWORD(Wpm))
  719. {
  720. case IDHELP:
  721. OpenHelpTopic(HELP_TOPIC_POPUP_REGISTERS);
  722. break;
  723. case IDOK:
  724. ScanRegisterMapText(GetDlgItem(Hwnd, IDC_REGCUST_ENTRY));
  725. if (g_RegisterMap != NULL && g_Workspace != NULL)
  726. {
  727. g_Workspace->SetBuffer(WSP_GLOBAL_REGISTER_MAP,
  728. g_RegisterMap, g_RegisterMapEntries *
  729. sizeof(*g_RegisterMap));
  730. }
  731. CpuWin = (CPUWIN_DATA*)GetWindowLongPtr(Hwnd, DWLP_USER);
  732. CpuWin->UpdateNames((PSTR)g_RegisterNamesBuffer->GetDataBuffer());
  733. CpuWin->OnUpdate(UPDATE_BUFFER);
  734. // Fall through.
  735. case IDCANCEL:
  736. EndDialog(Hwnd, LOWORD(Wpm));
  737. break;
  738. }
  739. break;
  740. default:
  741. return FALSE;
  742. }
  743. return TRUE;
  744. }
  745. INT_PTR CALLBACK
  746. DlgProc_GotoLine(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  747. {
  748. char Text[MAX_COMMAND_LEN];
  749. int Line;
  750. switch(Message)
  751. {
  752. case WM_INITDIALOG:
  753. SetWindowLongPtr(Hwnd, DWLP_USER, Lpm);
  754. SendDlgItemMessage(Hwnd, IDC_LINE_ENTRY, EM_LIMITTEXT,
  755. sizeof(Text) - 1, 0);
  756. SetWindowText(GetDlgItem(Hwnd, IDC_LINE_ENTRY), "");
  757. break;
  758. case WM_COMMAND:
  759. switch(LOWORD(Wpm))
  760. {
  761. case IDHELP:
  762. OpenHelpTopic(HELP_TOPIC_POPUP_GO_TO_LINE);
  763. break;
  764. case IDOK:
  765. COMMONWIN_DATA* CommonWinData;
  766. CommonWinData = (COMMONWIN_DATA*)GetWindowLongPtr(Hwnd, DWLP_USER);
  767. GetWindowText(GetDlgItem(Hwnd, IDC_LINE_ENTRY),
  768. Text, sizeof(Text));
  769. Line = atoi(Text);
  770. if (Line > 0)
  771. {
  772. CommonWinData->GotoLine(Line);
  773. }
  774. // Fall through.
  775. case IDCANCEL:
  776. EndDialog(Hwnd, LOWORD(Wpm));
  777. break;
  778. }
  779. break;
  780. default:
  781. return FALSE;
  782. }
  783. return TRUE;
  784. }
  785. INT_PTR CALLBACK
  786. DlgProc_GotoAddress(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  787. {
  788. char Text[MAX_COMMAND_LEN];
  789. switch(Message)
  790. {
  791. case WM_INITDIALOG:
  792. SendDlgItemMessage(Hwnd, IDC_ADDRESS_ENTRY, EM_LIMITTEXT,
  793. sizeof(Text) - 1, 0);
  794. SetWindowText(GetDlgItem(Hwnd, IDC_ADDRESS_ENTRY), "");
  795. break;
  796. case WM_COMMAND:
  797. switch(LOWORD(Wpm))
  798. {
  799. case IDHELP:
  800. OpenHelpTopic(HELP_TOPIC_POPUP_GO_TO_ADDRESS);
  801. break;
  802. case IDOK:
  803. GetWindowText(GetDlgItem(Hwnd, IDC_ADDRESS_ENTRY),
  804. Text, sizeof(Text));
  805. AddStringCommand(UIC_DISPLAY_CODE_EXPR, Text);
  806. // Fall through.
  807. case IDCANCEL:
  808. EndDialog(Hwnd, LOWORD(Wpm));
  809. break;
  810. }
  811. break;
  812. default:
  813. return FALSE;
  814. }
  815. return TRUE;
  816. }
  817. INT_PTR CALLBACK
  818. DlgProc_LogFile(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  819. {
  820. HRESULT Status;
  821. char LogFile[MAX_PATH];
  822. BOOL Append;
  823. HWND Ctrl;
  824. switch(Message)
  825. {
  826. case WM_INITDIALOG:
  827. Append = FALSE;
  828. Ctrl = GetDlgItem(Hwnd, IDC_LOG_FILE_NAME);
  829. SendMessage(Ctrl, EM_LIMITTEXT, sizeof(LogFile) - 1, 0);
  830. Status = g_pUiControl->GetLogFile(LogFile, sizeof(LogFile), NULL,
  831. &Append);
  832. if (Status == E_NOINTERFACE)
  833. {
  834. // No current log file.
  835. SetWindowText(Ctrl, "");
  836. }
  837. else if (Status != S_OK)
  838. {
  839. SetWindowText(Ctrl, "Unable to retrieve name");
  840. }
  841. else
  842. {
  843. SetWindowText(Ctrl, LogFile);
  844. }
  845. EnableWindow(GetDlgItem(Hwnd, IDC_LOG_CLOSE), Status == S_OK);
  846. CheckDlgButton(Hwnd, IDC_LOG_APPEND,
  847. Append ? BST_CHECKED : BST_UNCHECKED);
  848. break;
  849. case WM_COMMAND:
  850. switch(LOWORD(Wpm))
  851. {
  852. case IDC_LOG_CLOSE:
  853. g_pUiControl->CloseLogFile();
  854. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_LOG_FILE);
  855. SetWindowText(GetDlgItem(Hwnd, IDC_LOG_FILE_NAME), "");
  856. EnableWindow(GetDlgItem(Hwnd, IDC_LOG_CLOSE), FALSE);
  857. break;
  858. case IDHELP:
  859. OpenHelpTopic(HELP_TOPIC_POPUP_LOG_FILE);
  860. break;
  861. case IDOK:
  862. GetWindowText(GetDlgItem(Hwnd, IDC_LOG_FILE_NAME),
  863. LogFile, sizeof(LogFile));
  864. Append = IsDlgButtonChecked(Hwnd, IDC_LOG_APPEND) ==
  865. BST_CHECKED;
  866. if (LogFile[0] != 0)
  867. {
  868. g_pUiControl->OpenLogFile(LogFile, Append);
  869. DIRTY_ENGINE_WORKSPACE(WSPF_DIRTY_LOG_FILE);
  870. }
  871. // Fall through.
  872. case IDCANCEL:
  873. EndDialog(Hwnd, LOWORD(Wpm));
  874. break;
  875. }
  876. break;
  877. default:
  878. return FALSE;
  879. }
  880. return TRUE;
  881. }
  882. DLGPROC g_CurrentKd;
  883. INT_PTR
  884. CALLBACK
  885. DlgProc_KernelCom(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  886. {
  887. PSTR Sep;
  888. switch (Message)
  889. {
  890. case WM_INITDIALOG:
  891. //
  892. // Set up the controls to reflect current values
  893. //
  894. SetWindowText(GetDlgItem(Hwnd, IDC_KD_PORT), g_ComSettings);
  895. SetWindowText(GetDlgItem(Hwnd, IDC_KD_BAUDRATE),
  896. g_ComSettings + strlen(g_ComSettings) + 1);
  897. break;
  898. case WM_NOTIFY:
  899. switch(((LPNMHDR)Lpm)->code)
  900. {
  901. case PSN_HELP:
  902. OpenHelpTopic(HELP_TOPIC_POPUP_KERNEL_DEBUGGING);
  903. break;
  904. case PSN_SETACTIVE:
  905. g_CurrentKd = DlgProc_KernelCom;
  906. return 0;
  907. case PSN_KILLACTIVE:
  908. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, FALSE);
  909. return FALSE;
  910. case PSN_APPLY:
  911. if (g_CurrentKd != DlgProc_KernelCom)
  912. {
  913. // This isn't the current page so ignore.
  914. break;
  915. }
  916. TCHAR Com[256];
  917. TCHAR Baud[256];
  918. if (SendDlgItemMessage(Hwnd, IDC_KD_PORT, WM_GETTEXT,
  919. _tsizeof(Com), (LPARAM)Com) &&
  920. SendDlgItemMessage(Hwnd, IDC_KD_BAUDRATE, WM_GETTEXT,
  921. _tsizeof(Baud), (LPARAM)Baud))
  922. {
  923. if (PrintAllocString(&g_KernelConnectOptions, 256,
  924. "com:port=%s,baud=%s", Com, Baud))
  925. {
  926. strcpy(g_ComSettings, Com);
  927. strcpy(g_ComSettings + strlen(Com) + 1, Baud);
  928. if (SAVE_ENGINE_WORKSPACE())
  929. {
  930. PSTR Settings[2];
  931. Settings[0] = Com;
  932. Settings[1] = Baud;
  933. g_Workspace->SetStrings(WSP_GLOBAL_COM_SETTINGS, 2,
  934. Settings);
  935. }
  936. }
  937. }
  938. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  939. break;
  940. }
  941. break;
  942. default:
  943. return FALSE;
  944. }
  945. return TRUE;
  946. }
  947. INT_PTR
  948. CALLBACK
  949. DlgProc_Kernel1394(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  950. {
  951. switch (Message)
  952. {
  953. case WM_INITDIALOG:
  954. //
  955. // Set up the controls to reflect current values
  956. //
  957. SetWindowText(GetDlgItem(Hwnd, IDC_KD_1394_CHANNEL), g_1394Settings);
  958. break;
  959. case WM_NOTIFY:
  960. switch(((LPNMHDR)Lpm)->code)
  961. {
  962. case PSN_HELP:
  963. OpenHelpTopic(HELP_TOPIC_POPUP_KERNEL_DEBUGGING);
  964. break;
  965. case PSN_SETACTIVE:
  966. g_CurrentKd = DlgProc_Kernel1394;
  967. return 0;
  968. case PSN_KILLACTIVE:
  969. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, FALSE);
  970. return FALSE;
  971. case PSN_APPLY:
  972. if (g_CurrentKd != DlgProc_Kernel1394)
  973. {
  974. // This isn't the current page so ignore.
  975. break;
  976. }
  977. TCHAR Channel[256];
  978. PSTR Options;
  979. if (SendDlgItemMessage(Hwnd, IDC_KD_1394_CHANNEL, WM_GETTEXT,
  980. _tsizeof(Channel), (LPARAM)Channel))
  981. {
  982. if (PrintAllocString(&g_KernelConnectOptions, 256,
  983. "1394:channel=%s", Channel))
  984. {
  985. strcpy(g_1394Settings, Channel);
  986. if (SAVE_ENGINE_WORKSPACE())
  987. {
  988. g_Workspace->SetString(WSP_GLOBAL_1394_SETTINGS,
  989. g_1394Settings);
  990. }
  991. }
  992. }
  993. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  994. break;
  995. }
  996. break;
  997. default:
  998. return FALSE;
  999. }
  1000. return TRUE;
  1001. }
  1002. INT_PTR
  1003. CALLBACK
  1004. DlgProc_KernelLocal(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1005. {
  1006. switch (Message)
  1007. {
  1008. case WM_NOTIFY:
  1009. switch(((LPNMHDR)Lpm)->code)
  1010. {
  1011. case PSN_HELP:
  1012. OpenHelpTopic(HELP_TOPIC_POPUP_KERNEL_DEBUGGING);
  1013. break;
  1014. case PSN_SETACTIVE:
  1015. g_CurrentKd = DlgProc_KernelLocal;
  1016. return 0;
  1017. case PSN_KILLACTIVE:
  1018. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, FALSE);
  1019. return FALSE;
  1020. case PSN_APPLY:
  1021. if (g_CurrentKd != DlgProc_KernelLocal)
  1022. {
  1023. // This isn't the current page so ignore.
  1024. break;
  1025. }
  1026. g_AttachKernelFlags = DEBUG_ATTACH_LOCAL_KERNEL;
  1027. SetWindowLongPtr(Hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  1028. break;
  1029. }
  1030. break;
  1031. default:
  1032. return FALSE;
  1033. }
  1034. return FALSE;
  1035. }
  1036. void
  1037. StartKdPropSheet(void)
  1038. {
  1039. PROPSHEETHEADER Sheet;
  1040. PROPSHEETPAGE Pages[3];
  1041. ZeroMemory(&Sheet, sizeof(Sheet));
  1042. Sheet.dwSize = sizeof(PROPSHEETHEADER);
  1043. Sheet.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_HASHELP;
  1044. Sheet.hwndParent = g_hwndFrame;
  1045. Sheet.hInstance = g_hInst;
  1046. Sheet.pszCaption = "Kernel Debugging";
  1047. Sheet.nPages = 3;
  1048. Sheet.ppsp = Pages;
  1049. ZeroMemory(Pages, sizeof(Pages[0]));
  1050. Pages[0].dwSize = sizeof(Pages[0]);
  1051. Pages[0].dwFlags = PSP_HASHELP;
  1052. Pages[0].hInstance = g_hInst;
  1053. Pages[1] = Pages[0];
  1054. Pages[2] = Pages[0];
  1055. Pages[0].pszTemplate = MAKEINTRESOURCE(IDD_DLG_KERNEL_COM);
  1056. Pages[0].pfnDlgProc = DlgProc_KernelCom;
  1057. Pages[1].pszTemplate = MAKEINTRESOURCE(IDD_DLG_KERNEL_1394);
  1058. Pages[1].pfnDlgProc = DlgProc_Kernel1394;
  1059. Pages[2].pszTemplate = MAKEINTRESOURCE(IDD_DLG_KERNEL_LOCAL);
  1060. Pages[2].pfnDlgProc = DlgProc_KernelLocal;
  1061. g_CurrentKd = NULL;
  1062. INT_PTR Status = PropertySheet(&Sheet);
  1063. if (Status == IDOK)
  1064. {
  1065. if (g_ExplicitWorkspace && g_Workspace != NULL)
  1066. {
  1067. g_Workspace->SetUlong(WSP_GLOBAL_ATTACH_KERNEL_FLAGS,
  1068. g_AttachKernelFlags);
  1069. }
  1070. StartDebugging();
  1071. }
  1072. }
  1073. INT_PTR
  1074. CALLBACK
  1075. DlgProc_ImagePath(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1076. {
  1077. TCHAR Path[MAX_ENGINE_PATH];
  1078. LRESULT Size;
  1079. HRESULT Hr;
  1080. switch(Message)
  1081. {
  1082. case WM_INITDIALOG:
  1083. Hr = g_pUiSymbols->GetImagePath(Path, _tsizeof(Path), NULL);
  1084. if (Hr != S_OK)
  1085. {
  1086. InformationBox(ERR_Internal_Error, Hr, "UI GetImagePath");
  1087. }
  1088. SendDlgItemMessage(Hwnd, IDC_IMAGE_PATH, WM_SETTEXT, 0, (LPARAM)Path);
  1089. break;
  1090. case WM_COMMAND:
  1091. switch(LOWORD(Wpm))
  1092. {
  1093. case IDHELP:
  1094. OpenHelpTopic(HELP_TOPIC_POPUP_IMAGE_PATH);
  1095. break;
  1096. case IDOK:
  1097. Size = SendDlgItemMessage(Hwnd, IDC_IMAGE_PATH, WM_GETTEXT,
  1098. sizeof(Path), (LPARAM)Path);
  1099. if (Size == 0)
  1100. {
  1101. InformationBox(ERR_Path_Empty);
  1102. SetFocus(Hwnd);
  1103. return TRUE;
  1104. }
  1105. Path[Size] = 0;
  1106. Hr = g_pUiSymbols->SetImagePath(Path);
  1107. if (Hr != S_OK)
  1108. {
  1109. InformationBox(ERR_Internal_Error, Hr, "UI SetImagePath");
  1110. }
  1111. if (SAVE_ENGINE_WORKSPACE())
  1112. {
  1113. g_Workspace->SetString(WSP_GLOBAL_IMAGE_PATH, Path);
  1114. }
  1115. EndDialog(Hwnd, IDOK);
  1116. break;
  1117. case IDCANCEL:
  1118. EndDialog(Hwnd, IDCANCEL);
  1119. break;
  1120. }
  1121. break;
  1122. default:
  1123. return FALSE;
  1124. }
  1125. return TRUE;
  1126. }
  1127. INT_PTR
  1128. CALLBACK
  1129. DlgProc_SourcePath(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1130. {
  1131. TCHAR Path[MAX_ENGINE_PATH];
  1132. LRESULT Size;
  1133. HRESULT Hr;
  1134. HWND Ctrl;
  1135. ULONG Tag;
  1136. switch(Message)
  1137. {
  1138. case WM_INITDIALOG:
  1139. Ctrl = GetDlgItem(Hwnd, IDC_LOCAL_SOURCE);
  1140. SendMessage(Ctrl, BM_SETCHECK, TRUE, 0);
  1141. if (!g_RemoteClient)
  1142. {
  1143. EnableWindow(Ctrl, FALSE);
  1144. Hr = g_pUiSymbols->GetSourcePath(Path, _tsizeof(Path), NULL);
  1145. }
  1146. else
  1147. {
  1148. EnableWindow(Ctrl, TRUE);
  1149. Hr = g_pUiLocSymbols->GetSourcePath(Path, _tsizeof(Path), NULL);
  1150. }
  1151. if (Hr != S_OK)
  1152. {
  1153. InformationBox(ERR_Internal_Error, Hr, "UI GetSourcePath");
  1154. }
  1155. SendDlgItemMessage(Hwnd, IDC_SOURCE_PATH, WM_SETTEXT, 0, (LPARAM)Path);
  1156. break;
  1157. case WM_COMMAND:
  1158. switch(LOWORD(Wpm))
  1159. {
  1160. case IDC_LOCAL_SOURCE:
  1161. if (IsDlgButtonChecked(Hwnd, IDC_LOCAL_SOURCE) != BST_CHECKED)
  1162. {
  1163. Hr = g_pUiSymbols->GetSourcePath(Path, _tsizeof(Path), NULL);
  1164. }
  1165. else
  1166. {
  1167. Hr = g_pUiLocSymbols->GetSourcePath(Path, _tsizeof(Path),
  1168. NULL);
  1169. }
  1170. if (Hr != S_OK)
  1171. {
  1172. InformationBox(ERR_Internal_Error, Hr, "UI GetSourcePath");
  1173. }
  1174. SendDlgItemMessage(Hwnd, IDC_SOURCE_PATH, WM_SETTEXT, 0,
  1175. (LPARAM)Path);
  1176. break;
  1177. case IDHELP:
  1178. OpenHelpTopic(HELP_TOPIC_POPUP_SOURCE_PATH);
  1179. break;
  1180. case IDOK:
  1181. Size = SendDlgItemMessage(Hwnd, IDC_SOURCE_PATH, WM_GETTEXT,
  1182. sizeof(Path), (LPARAM)Path);
  1183. if (Size == 0)
  1184. {
  1185. InformationBox(ERR_Path_Empty);
  1186. SetFocus(Hwnd);
  1187. return TRUE;
  1188. }
  1189. Path[Size] = 0;
  1190. if (!g_RemoteClient ||
  1191. IsDlgButtonChecked(Hwnd, IDC_LOCAL_SOURCE) != BST_CHECKED)
  1192. {
  1193. Hr = g_pUiSymbols->SetSourcePath(Path);
  1194. Tag = WSP_GLOBAL_SOURCE_PATH;
  1195. }
  1196. else
  1197. {
  1198. Hr = g_pUiLocSymbols->SetSourcePath(Path);
  1199. Tag = WSP_GLOBAL_LOCAL_SOURCE_PATH;
  1200. }
  1201. if (Hr != S_OK)
  1202. {
  1203. InformationBox(ERR_Internal_Error, Hr, "UI SetSourcePath");
  1204. }
  1205. if (g_Workspace != NULL)
  1206. {
  1207. g_Workspace->SetString(Tag, Path);
  1208. }
  1209. EndDialog(Hwnd, IDOK);
  1210. break;
  1211. case IDCANCEL:
  1212. EndDialog(Hwnd, IDCANCEL);
  1213. break;
  1214. }
  1215. break;
  1216. default:
  1217. return FALSE;
  1218. }
  1219. return TRUE;
  1220. }
  1221. #define MAX_IDS 4096
  1222. void
  1223. FillProcessList(HWND List)
  1224. {
  1225. HRESULT Status;
  1226. ULONG Ids[MAX_IDS];
  1227. ULONG IdCount;
  1228. ULONG i;
  1229. ULONG64 Server = 0;
  1230. ULONG Extent = 0;
  1231. SendMessage(List, LB_RESETCONTENT, 0, 0);
  1232. if (g_ProcessServer != NULL)
  1233. {
  1234. if (g_pUiClient->
  1235. ConnectProcessServer(g_ProcessServer, &Server) != S_OK)
  1236. {
  1237. SendMessage(List, LB_ADDSTRING,
  1238. 0, (LPARAM)_T("Unable to connect to process server"));
  1239. return;
  1240. }
  1241. }
  1242. if ((Status = g_pUiClient->
  1243. GetRunningProcessSystemIds(Server, Ids, MAX_IDS,
  1244. &IdCount)) != S_OK)
  1245. {
  1246. SendMessage(List, LB_ADDSTRING,
  1247. 0, (LPARAM)_T("Unable to get process list"));
  1248. goto Disconnect;
  1249. }
  1250. if (IdCount > MAX_IDS)
  1251. {
  1252. SendMessage(List, LB_ADDSTRING,
  1253. 0, (LPARAM)_T("Incomplete process list"));
  1254. IdCount = MAX_IDS;
  1255. }
  1256. for (i = 0; i < IdCount; i++)
  1257. {
  1258. char IdAndExeName[MAX_PATH + 16];
  1259. char DescBuf[2 * MAX_PATH];
  1260. PSTR ExeName, Desc;
  1261. LRESULT Idx;
  1262. ULONG ItemEx;
  1263. if (Ids[i] >= 0x80000000)
  1264. {
  1265. sprintf(IdAndExeName, "0x%x", Ids[i]);
  1266. }
  1267. else
  1268. {
  1269. sprintf(IdAndExeName, "%4d", Ids[i]);
  1270. }
  1271. ExeName = IdAndExeName + strlen(IdAndExeName);
  1272. *ExeName++ = ' ';
  1273. Desc = DescBuf;
  1274. while ((Desc - DescBuf) < (ExeName - IdAndExeName))
  1275. {
  1276. *Desc++ = ' ';
  1277. }
  1278. Status = g_pUiClient->
  1279. GetRunningProcessDescription(Server, Ids[i],
  1280. DEBUG_PROC_DESC_NO_PATHS,
  1281. ExeName,
  1282. (ULONG)(sizeof(IdAndExeName) -
  1283. (ExeName - IdAndExeName)),
  1284. NULL,
  1285. Desc,
  1286. (ULONG)(sizeof(DescBuf) -
  1287. (Desc - DescBuf)),
  1288. NULL);
  1289. if (FAILED(Status))
  1290. {
  1291. sprintf(ExeName, "Error 0x%08X", Status);
  1292. }
  1293. Idx = SendMessage(List, LB_ADDSTRING, 0, (LPARAM)IdAndExeName);
  1294. SendMessage(List, LB_SETITEMDATA, Idx, TRUE);
  1295. ItemEx = (strlen(IdAndExeName) + 1) *
  1296. g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  1297. if (ItemEx > Extent)
  1298. {
  1299. Extent = ItemEx;
  1300. }
  1301. if (*Desc)
  1302. {
  1303. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)DescBuf);
  1304. ItemEx = (strlen(DescBuf) + 1) *
  1305. g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  1306. if (ItemEx > Extent)
  1307. {
  1308. Extent = ItemEx;
  1309. }
  1310. }
  1311. }
  1312. SendMessage(List, LB_SETHORIZONTALEXTENT, Extent, 0);
  1313. Disconnect:
  1314. if (Server != 0)
  1315. {
  1316. g_pUiClient->DisconnectProcessServer(Server);
  1317. }
  1318. }
  1319. INT_PTR CALLBACK
  1320. DlgProc_AttachProcess(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1321. {
  1322. char Text[MAX_PATH];
  1323. HWND List;
  1324. switch(Message)
  1325. {
  1326. case WM_INITDIALOG:
  1327. List = GetDlgItem(Hwnd, IDC_ATTACH_PROC_LIST);
  1328. SendMessage(List, WM_SETFONT, (WPARAM)g_Fonts[FONT_FIXED].Font, FALSE);
  1329. FillProcessList(List);
  1330. SendDlgItemMessage(Hwnd, IDC_ATTACH_PID, WM_SETFONT,
  1331. (WPARAM)g_Fonts[FONT_FIXED].Font, FALSE);
  1332. SendDlgItemMessage(Hwnd, IDC_ATTACH_PID, EM_LIMITTEXT,
  1333. sizeof(Text) - 1, 0);
  1334. SetWindowText(GetDlgItem(Hwnd, IDC_ATTACH_PID), "");
  1335. CheckDlgButton(Hwnd, IDC_ATTACH_NONINVASIVE, BST_UNCHECKED);
  1336. break;
  1337. case WM_COMMAND:
  1338. switch(LOWORD(Wpm))
  1339. {
  1340. case IDC_ATTACH_PROC_LIST:
  1341. LRESULT Sel;
  1342. List = GetDlgItem(Hwnd, IDC_ATTACH_PROC_LIST);
  1343. Sel = SendMessage(List, LB_GETCURSEL, 0, 0);
  1344. if (Sel >= 0)
  1345. {
  1346. if (!SendMessage(List, LB_GETITEMDATA, Sel, 0))
  1347. {
  1348. Sel = -1;
  1349. }
  1350. }
  1351. if (Sel < 0)
  1352. {
  1353. SetWindowText(GetDlgItem(Hwnd, IDC_ATTACH_PID), "");
  1354. }
  1355. else
  1356. {
  1357. SendMessage(List, LB_GETTEXT, Sel, (LPARAM)Text);
  1358. SetWindowText(GetDlgItem(Hwnd, IDC_ATTACH_PID), Text);
  1359. }
  1360. break;
  1361. case IDHELP:
  1362. OpenHelpTopic(HELP_TOPIC_POPUP_ATTACH_TO_PROCESS);
  1363. break;
  1364. case IDOK:
  1365. GetWindowText(GetDlgItem(Hwnd, IDC_ATTACH_PID),
  1366. Text, sizeof(Text));
  1367. g_PidToDebug = strtoul(Text, NULL, 0);
  1368. if (IsDlgButtonChecked(Hwnd, IDC_ATTACH_NONINVASIVE) ==
  1369. BST_CHECKED)
  1370. {
  1371. g_AttachProcessFlags |= DEBUG_ATTACH_NONINVASIVE;
  1372. }
  1373. StartDebugging();
  1374. // Fall through.
  1375. case IDCANCEL:
  1376. EndDialog(Hwnd, LOWORD(Wpm));
  1377. break;
  1378. }
  1379. break;
  1380. default:
  1381. return FALSE;
  1382. }
  1383. return TRUE;
  1384. }
  1385. void
  1386. FillEventFilters(HWND List)
  1387. {
  1388. HRESULT Status;
  1389. ULONG Width;
  1390. RECT ListRect;
  1391. LRESULT ListSel = SendMessage(List, LB_GETCURSEL, 0, 0);
  1392. SendMessage(List, WM_SETREDRAW, FALSE, 0);
  1393. SendMessage(List, LB_RESETCONTENT, 0, 0);
  1394. GetClientRect(List, &ListRect);
  1395. Width = ListRect.right - ListRect.left;
  1396. Status = g_FilterBuffer->UiLockForRead();
  1397. if (Status != S_OK)
  1398. {
  1399. SendLockStatusMessage(List, LB_ADDSTRING, Status);
  1400. goto Update;
  1401. }
  1402. Status = g_FilterTextBuffer->UiLockForRead();
  1403. if (Status != S_OK)
  1404. {
  1405. SendLockStatusMessage(List, LB_ADDSTRING, Status);
  1406. goto UnlockFilter;
  1407. }
  1408. ULONG i;
  1409. PSTR FilterArg, FilterText;
  1410. PDEBUG_SPECIFIC_FILTER_PARAMETERS SpecParams;
  1411. PDEBUG_EXCEPTION_FILTER_PARAMETERS ExParams;
  1412. char Str[256];
  1413. FilterText = (PSTR)g_FilterTextBuffer->GetDataBuffer();
  1414. SpecParams =
  1415. (PDEBUG_SPECIFIC_FILTER_PARAMETERS)g_FilterBuffer->GetDataBuffer();
  1416. ExParams =
  1417. (PDEBUG_EXCEPTION_FILTER_PARAMETERS)(SpecParams + g_NumSpecEvents);
  1418. FilterArg = (PSTR)g_FilterBuffer->GetDataBuffer() + g_FilterArgsOffset;
  1419. for (i = 0; i < g_NumSpecEvents; i++)
  1420. {
  1421. strcpy(Str, FilterText);
  1422. if (SpecParams->ArgumentSize > 1)
  1423. {
  1424. strcat(Str, " ");
  1425. strcat(Str, FilterArg);
  1426. FilterArg += strlen(FilterArg) + 1;
  1427. }
  1428. sprintf(Str + strlen(Str), " - %s - %s",
  1429. g_ExecutionNames[SpecParams->ExecutionOption],
  1430. g_ContinueNames[SpecParams->ContinueOption]);
  1431. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Str);
  1432. FilterText += strlen(FilterText) + 1;
  1433. SpecParams++;
  1434. }
  1435. for (i = 0; i < g_NumSpecEx; i++)
  1436. {
  1437. sprintf(Str, "%s - %s - %s",
  1438. FilterText,
  1439. g_ExecutionNames[ExParams->ExecutionOption],
  1440. g_ContinueNames[ExParams->ContinueOption]);
  1441. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Str);
  1442. FilterText += strlen(FilterText) + 1;
  1443. ExParams++;
  1444. }
  1445. for (i = 0; i < g_NumArbEx; i++)
  1446. {
  1447. sprintf(Str, "Exception %08X - %s - %s",
  1448. ExParams->ExceptionCode,
  1449. g_ExecutionNames[ExParams->ExecutionOption],
  1450. g_ContinueNames[ExParams->ContinueOption]);
  1451. SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Str);
  1452. ExParams++;
  1453. }
  1454. UnlockStateBuffer(g_FilterTextBuffer);
  1455. UnlockFilter:
  1456. UnlockStateBuffer(g_FilterBuffer);
  1457. Update:
  1458. SendMessage(List, LB_SETHORIZONTALEXTENT, Width, 0);
  1459. SendMessage(List, WM_SETREDRAW, TRUE, 0);
  1460. if (ListSel != LB_ERR)
  1461. {
  1462. SendMessage(List, LB_SETCURSEL, ListSel, 0);
  1463. }
  1464. }
  1465. void
  1466. GetFilterOptions(int Index, PULONG CodeArg, PULONG Exe, PULONG Cont)
  1467. {
  1468. *CodeArg = 0;
  1469. *Exe = 0;
  1470. *Cont = 0;
  1471. if (g_FilterBuffer->UiLockForRead() != S_OK)
  1472. {
  1473. return;
  1474. }
  1475. PDEBUG_SPECIFIC_FILTER_PARAMETERS SpecParams;
  1476. PDEBUG_EXCEPTION_FILTER_PARAMETERS ExParams;
  1477. SpecParams =
  1478. (PDEBUG_SPECIFIC_FILTER_PARAMETERS)g_FilterBuffer->GetDataBuffer();
  1479. ExParams =
  1480. (PDEBUG_EXCEPTION_FILTER_PARAMETERS)(SpecParams + g_NumSpecEvents);
  1481. if ((ULONG)Index < g_NumSpecEvents)
  1482. {
  1483. SpecParams += Index;
  1484. *CodeArg = SpecParams->ArgumentSize;
  1485. *Exe = SpecParams->ExecutionOption;
  1486. *Cont = SpecParams->ContinueOption;
  1487. }
  1488. else
  1489. {
  1490. ExParams += Index - g_NumSpecEvents;
  1491. *CodeArg = ExParams->ExceptionCode;
  1492. *Exe = ExParams->ExecutionOption;
  1493. *Cont = ExParams->ContinueOption;
  1494. }
  1495. UnlockStateBuffer(g_FilterBuffer);
  1496. }
  1497. void
  1498. GetFilterArgument(int Index, PTSTR Argument, ULONG Size)
  1499. {
  1500. *Argument = 0;
  1501. if (g_FilterBuffer->UiLockForRead() != S_OK)
  1502. {
  1503. return;
  1504. }
  1505. int i;
  1506. PDEBUG_SPECIFIC_FILTER_PARAMETERS SpecParams;
  1507. PSTR FilterArg;
  1508. SpecParams =
  1509. (PDEBUG_SPECIFIC_FILTER_PARAMETERS)g_FilterBuffer->GetDataBuffer();
  1510. FilterArg = (PSTR)g_FilterBuffer->GetDataBuffer() + g_FilterArgsOffset;
  1511. for (i = 0; i < Index; i++)
  1512. {
  1513. if (SpecParams->ArgumentSize > 1)
  1514. {
  1515. FilterArg += strlen(FilterArg) + 1;
  1516. }
  1517. SpecParams++;
  1518. }
  1519. if (SpecParams->ArgumentSize > 1)
  1520. {
  1521. strncat(Argument, FilterArg, Size);
  1522. }
  1523. UnlockStateBuffer(g_FilterBuffer);
  1524. }
  1525. void
  1526. GetFilterCommands(ULONG Index,
  1527. PTSTR Argument1, ULONG Size1,
  1528. PTSTR Argument2, ULONG Size2)
  1529. {
  1530. *Argument1 = 0;
  1531. *Argument2 = 0;
  1532. if (g_FilterBuffer->UiLockForRead() != S_OK)
  1533. {
  1534. return;
  1535. }
  1536. ULONG i, Limit;
  1537. PDEBUG_SPECIFIC_FILTER_PARAMETERS SpecParams;
  1538. PSTR FilterCmd;
  1539. ULONG CmdSize1, CmdSize2;
  1540. SpecParams =
  1541. (PDEBUG_SPECIFIC_FILTER_PARAMETERS)g_FilterBuffer->GetDataBuffer();
  1542. FilterCmd = (PSTR)g_FilterBuffer->GetDataBuffer() + g_FilterCmdsOffset;
  1543. if (Index < g_NumSpecEvents)
  1544. {
  1545. Limit = Index;
  1546. }
  1547. else
  1548. {
  1549. Limit = g_NumSpecEvents;
  1550. }
  1551. for (i = 0; i < Limit; i++)
  1552. {
  1553. if (SpecParams->CommandSize > 0)
  1554. {
  1555. FilterCmd += strlen(FilterCmd) + 1;
  1556. }
  1557. SpecParams++;
  1558. }
  1559. if (Index >= g_NumSpecEvents)
  1560. {
  1561. PDEBUG_EXCEPTION_FILTER_PARAMETERS ExParams =
  1562. (PDEBUG_EXCEPTION_FILTER_PARAMETERS)SpecParams;
  1563. while (i < Index)
  1564. {
  1565. if (ExParams->CommandSize > 0)
  1566. {
  1567. FilterCmd += strlen(FilterCmd) + 1;
  1568. }
  1569. if (ExParams->SecondCommandSize > 0)
  1570. {
  1571. FilterCmd += strlen(FilterCmd) + 1;
  1572. }
  1573. i++;
  1574. ExParams++;
  1575. }
  1576. CmdSize1 = ExParams->CommandSize;
  1577. CmdSize2 = ExParams->SecondCommandSize;
  1578. }
  1579. else
  1580. {
  1581. CmdSize1 = SpecParams->CommandSize;
  1582. CmdSize2 = 0;
  1583. }
  1584. if (CmdSize1 > 0)
  1585. {
  1586. strncat(Argument1, FilterCmd, Size1-1);
  1587. }
  1588. if (CmdSize2 > 0)
  1589. {
  1590. FilterCmd += strlen(FilterCmd) + 1;
  1591. strncat(Argument2, FilterCmd, Size2-1);
  1592. }
  1593. UnlockStateBuffer(g_FilterBuffer);
  1594. }
  1595. INT_PTR CALLBACK
  1596. DlgProc_EventFilters(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1597. {
  1598. UIC_SET_FILTER_DATA* SetFilter;
  1599. HWND List = GetDlgItem(Hwnd, IDC_FILTERS);
  1600. int Sel = (int)SendMessage(List, LB_GETCURSEL, 0, 0);
  1601. HWND Remove, Command, Arg;
  1602. ULONG CodeArg, Exe, Cont;
  1603. UINT Id;
  1604. switch(Message)
  1605. {
  1606. case WM_INITDIALOG:
  1607. g_FilterBuffer->m_Win = Hwnd;
  1608. SendMessage(List, WM_SETFONT, (WPARAM)g_Fonts[FONT_FIXED].Font, FALSE);
  1609. FillEventFilters(List);
  1610. break;
  1611. case WM_COMMAND:
  1612. Id = LOWORD(Wpm);
  1613. switch(Id)
  1614. {
  1615. case IDC_FILTERS:
  1616. Remove = GetDlgItem(Hwnd, IDC_FILTER_REMOVE);
  1617. Arg = GetDlgItem(Hwnd, IDC_FILTER_ARGUMENT);
  1618. Command = GetDlgItem(Hwnd, IDC_FILTER_COMMAND);
  1619. if (Sel >= 0)
  1620. {
  1621. EnableWindow(Remove,
  1622. (ULONG)Sel >= g_NumSpecEvents + g_NumSpecEx);
  1623. GetFilterOptions(Sel, &CodeArg, &Exe, &Cont);
  1624. CheckRadioButton(Hwnd, IDC_FILTER_ENABLED,
  1625. IDC_FILTER_IGNORE,
  1626. (Exe - DEBUG_FILTER_BREAK) +
  1627. IDC_FILTER_ENABLED);
  1628. CheckRadioButton(Hwnd, IDC_FILTER_HANDLED,
  1629. IDC_FILTER_NOT_HANDLED,
  1630. (Cont - DEBUG_FILTER_GO_HANDLED) +
  1631. IDC_FILTER_HANDLED);
  1632. if ((ULONG)Sel < g_NumSpecEvents)
  1633. {
  1634. GetFilterOptions(Sel, &CodeArg, &Exe, &Cont);
  1635. EnableWindow(Arg, CodeArg > 0);
  1636. }
  1637. EnableWindow(Command, TRUE);
  1638. }
  1639. else
  1640. {
  1641. EnableWindow(Remove, FALSE);
  1642. EnableWindow(Arg, FALSE);
  1643. EnableWindow(Command, FALSE);
  1644. }
  1645. break;
  1646. case IDC_FILTER_ADD:
  1647. StartDialog(IDD_DLG_EXCEPTION_FILTER, DlgProc_ExceptionFilter,
  1648. NULL);
  1649. break;
  1650. case IDC_FILTER_REMOVE:
  1651. if (Sel >= 0)
  1652. {
  1653. SetFilter = StartStructCommand(UIC_SET_FILTER);
  1654. if (SetFilter != NULL)
  1655. {
  1656. SetFilter->Index = 0xffffffff;
  1657. GetFilterOptions(Sel,
  1658. &SetFilter->Code,
  1659. &SetFilter->Execution,
  1660. &SetFilter->Continue);
  1661. SetFilter->Execution = DEBUG_FILTER_REMOVE;
  1662. FinishCommand();
  1663. }
  1664. }
  1665. break;
  1666. case IDC_FILTER_ARGUMENT:
  1667. if (Sel >= 0 && (ULONG)Sel < g_NumSpecEvents)
  1668. {
  1669. GetFilterArgument(Sel, g_DlgString,
  1670. sizeof(g_DlgString));
  1671. if (StartDialog(IDD_DLG_FILTER_ARGUMENT,
  1672. DlgProc_FilterArgument,
  1673. NULL) == IDOK)
  1674. {
  1675. UIC_SET_FILTER_ARGUMENT_DATA* SetFilterArg;
  1676. SetFilterArg = (UIC_SET_FILTER_ARGUMENT_DATA*)
  1677. StartCommand(UIC_SET_FILTER_ARGUMENT,
  1678. sizeof(*SetFilterArg) +
  1679. strlen(g_DlgString));
  1680. if (SetFilterArg != NULL)
  1681. {
  1682. SetFilterArg->Index = Sel;
  1683. strcpy(SetFilterArg->Argument, g_DlgString);
  1684. FinishCommand();
  1685. }
  1686. }
  1687. }
  1688. break;
  1689. case IDC_FILTER_COMMAND:
  1690. if (Sel >= 0)
  1691. {
  1692. GetFilterCommands(Sel,
  1693. g_DlgString, sizeof(g_DlgString),
  1694. g_DlgString2, sizeof(g_DlgString2));
  1695. if (StartDialog(IDD_DLG_FILTER_COMMAND,
  1696. DlgProc_FilterCommand,
  1697. (ULONG)Sel >= g_NumSpecEvents) == IDOK)
  1698. {
  1699. UIC_SET_FILTER_COMMAND_DATA* SetFilterCmd;
  1700. SetFilterCmd = (UIC_SET_FILTER_COMMAND_DATA*)
  1701. StartCommand(UIC_SET_FILTER_COMMAND,
  1702. sizeof(*SetFilterCmd) +
  1703. strlen(g_DlgString));
  1704. if (SetFilterCmd != NULL)
  1705. {
  1706. SetFilterCmd->Which = 0;
  1707. SetFilterCmd->Index = Sel;
  1708. strcpy(SetFilterCmd->Command, g_DlgString);
  1709. FinishCommand();
  1710. }
  1711. if ((ULONG)Sel <= g_NumSpecEvents)
  1712. {
  1713. break;
  1714. }
  1715. SetFilterCmd = (UIC_SET_FILTER_COMMAND_DATA*)
  1716. StartCommand(UIC_SET_FILTER_COMMAND,
  1717. sizeof(*SetFilterCmd) +
  1718. strlen(g_DlgString2));
  1719. if (SetFilterCmd != NULL)
  1720. {
  1721. SetFilterCmd->Which = 1;
  1722. SetFilterCmd->Index = Sel;
  1723. strcpy(SetFilterCmd->Command, g_DlgString2);
  1724. FinishCommand();
  1725. }
  1726. }
  1727. }
  1728. break;
  1729. case IDC_FILTER_ENABLED:
  1730. case IDC_FILTER_DISABLED:
  1731. case IDC_FILTER_OUTPUT:
  1732. case IDC_FILTER_IGNORE:
  1733. case IDC_FILTER_HANDLED:
  1734. case IDC_FILTER_NOT_HANDLED:
  1735. if (Sel >= 0)
  1736. {
  1737. SetFilter = StartStructCommand(UIC_SET_FILTER);
  1738. if (SetFilter != NULL)
  1739. {
  1740. SetFilter->Index = (ULONG)Sel < g_NumSpecEvents ?
  1741. Sel : 0xffffffff;
  1742. GetFilterOptions(Sel,
  1743. &SetFilter->Code,
  1744. &SetFilter->Execution,
  1745. &SetFilter->Continue);
  1746. if (Id >= IDC_FILTER_ENABLED && Id <= IDC_FILTER_IGNORE)
  1747. {
  1748. SetFilter->Execution = (Id - IDC_FILTER_ENABLED) +
  1749. DEBUG_FILTER_BREAK;
  1750. }
  1751. else
  1752. {
  1753. SetFilter->Continue = (Id - IDC_FILTER_HANDLED) +
  1754. DEBUG_FILTER_GO_HANDLED;
  1755. }
  1756. FinishCommand();
  1757. }
  1758. }
  1759. break;
  1760. case IDHELP:
  1761. OpenHelpTopic(HELP_TOPIC_POPUP_EVENT_FILTERS);
  1762. break;
  1763. case IDCANCEL:
  1764. g_FilterBuffer->m_Win = NULL;
  1765. EndDialog(Hwnd, Id);
  1766. break;
  1767. }
  1768. break;
  1769. case LB_RESETCONTENT:
  1770. FillEventFilters(List);
  1771. break;
  1772. default:
  1773. return FALSE;
  1774. }
  1775. return TRUE;
  1776. }
  1777. INT_PTR CALLBACK
  1778. DlgProc_ExceptionFilter(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1779. {
  1780. HWND Code = GetDlgItem(Hwnd, IDC_FILTER_CODE);
  1781. char CodeText[80];
  1782. UIC_SET_FILTER_DATA* SetFilter;
  1783. static UINT s_Execution;
  1784. static UINT s_Continue;
  1785. switch(Message)
  1786. {
  1787. case WM_INITDIALOG:
  1788. SendMessage(Code, EM_LIMITTEXT, sizeof(CodeText) - 1, 0);
  1789. SetWindowText(Code, "");
  1790. s_Execution = IDC_FILTER_ENABLED;
  1791. s_Continue = IDC_FILTER_NOT_HANDLED;
  1792. CheckRadioButton(Hwnd, IDC_FILTER_ENABLED,
  1793. IDC_FILTER_IGNORE, s_Execution);
  1794. CheckRadioButton(Hwnd, IDC_FILTER_HANDLED,
  1795. IDC_FILTER_NOT_HANDLED, s_Continue);
  1796. break;
  1797. case WM_COMMAND:
  1798. switch(LOWORD(Wpm))
  1799. {
  1800. case IDC_FILTER_ENABLED:
  1801. case IDC_FILTER_DISABLED:
  1802. case IDC_FILTER_OUTPUT:
  1803. case IDC_FILTER_IGNORE:
  1804. s_Execution = LOWORD(Wpm);
  1805. break;
  1806. case IDC_FILTER_HANDLED:
  1807. case IDC_FILTER_NOT_HANDLED:
  1808. s_Continue = LOWORD(Wpm);
  1809. break;
  1810. case IDHELP:
  1811. OpenHelpTopic(HELP_TOPIC_POPUP_EVENT_FILTERS);
  1812. break;
  1813. case IDOK:
  1814. int InputCode;
  1815. if (GetWindowText(Code, CodeText, sizeof(CodeText)) == 0)
  1816. {
  1817. MessageBeep(-1);
  1818. break;
  1819. }
  1820. if (sscanf(CodeText, "%x", &InputCode) != 1)
  1821. {
  1822. MessageBeep(-1);
  1823. break;
  1824. }
  1825. SetFilter = StartStructCommand(UIC_SET_FILTER);
  1826. if (SetFilter != NULL)
  1827. {
  1828. SetFilter->Index = 0xffffffff;
  1829. SetFilter->Code = InputCode;
  1830. SetFilter->Execution = (s_Execution - IDC_FILTER_ENABLED) +
  1831. DEBUG_FILTER_BREAK;
  1832. SetFilter->Continue = (s_Continue - IDC_FILTER_HANDLED) +
  1833. DEBUG_FILTER_GO_HANDLED;
  1834. FinishCommand();
  1835. }
  1836. // Fall through.
  1837. case IDCANCEL:
  1838. EndDialog(Hwnd, LOWORD(Wpm));
  1839. break;
  1840. }
  1841. break;
  1842. default:
  1843. return FALSE;
  1844. }
  1845. return TRUE;
  1846. }
  1847. INT_PTR CALLBACK
  1848. DlgProc_FilterArgument(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1849. {
  1850. HWND Arg = GetDlgItem(Hwnd, IDC_FILTER_ARGUMENT);
  1851. switch(Message)
  1852. {
  1853. case WM_INITDIALOG:
  1854. SendMessage(Arg, EM_LIMITTEXT, sizeof(g_DlgString) - 1, 0);
  1855. SetWindowText(Arg, g_DlgString);
  1856. break;
  1857. case WM_COMMAND:
  1858. switch(LOWORD(Wpm))
  1859. {
  1860. case IDHELP:
  1861. OpenHelpTopic(HELP_TOPIC_POPUP_EVENT_FILTERS);
  1862. break;
  1863. case IDOK:
  1864. if (GetWindowText(Arg, g_DlgString,
  1865. sizeof(g_DlgString)) == 0)
  1866. {
  1867. g_DlgString[0] = 0;
  1868. }
  1869. // Fall through.
  1870. case IDCANCEL:
  1871. EndDialog(Hwnd, LOWORD(Wpm));
  1872. break;
  1873. }
  1874. break;
  1875. default:
  1876. return FALSE;
  1877. }
  1878. return TRUE;
  1879. }
  1880. INT_PTR CALLBACK
  1881. DlgProc_FilterCommand(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1882. {
  1883. HWND Cmd1 = GetDlgItem(Hwnd, IDC_FILTER_COMMAND);
  1884. HWND Cmd2 = GetDlgItem(Hwnd, IDC_FILTER_COMMAND2);
  1885. switch(Message)
  1886. {
  1887. case WM_INITDIALOG:
  1888. SendMessage(Cmd1, EM_LIMITTEXT, sizeof(g_DlgString) - 1, 0);
  1889. SetWindowText(Cmd1, g_DlgString);
  1890. SendMessage(Cmd2, EM_LIMITTEXT, sizeof(g_DlgString2) - 1, 0);
  1891. SetWindowText(Cmd2, g_DlgString2);
  1892. EnableWindow(Cmd2, (BOOL)Lpm);
  1893. break;
  1894. case WM_COMMAND:
  1895. switch(LOWORD(Wpm))
  1896. {
  1897. case IDHELP:
  1898. OpenHelpTopic(HELP_TOPIC_POPUP_EVENT_FILTERS);
  1899. break;
  1900. case IDOK:
  1901. if (GetWindowText(Cmd1, g_DlgString, sizeof(g_DlgString)) == 0)
  1902. {
  1903. g_DlgString[0] = 0;
  1904. }
  1905. if (GetWindowText(Cmd2, g_DlgString2, sizeof(g_DlgString2)) == 0)
  1906. {
  1907. g_DlgString2[0] = 0;
  1908. }
  1909. // Fall through.
  1910. case IDCANCEL:
  1911. EndDialog(Hwnd, LOWORD(Wpm));
  1912. break;
  1913. }
  1914. break;
  1915. default:
  1916. return FALSE;
  1917. }
  1918. return TRUE;
  1919. }
  1920. ULONG
  1921. EditTabToUserTab(ULONG EditTab)
  1922. {
  1923. return EditTab / 4;
  1924. }
  1925. ULONG
  1926. UserTabToEditTab(ULONG UserTab)
  1927. {
  1928. return UserTab * 4;
  1929. }
  1930. INT_PTR CALLBACK
  1931. DlgProc_Options(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  1932. {
  1933. HWND Ctrl;
  1934. char Text[256];
  1935. LRESULT Sel, Idx;
  1936. switch(Message)
  1937. {
  1938. case WM_INITDIALOG:
  1939. ULONG EngOptions;
  1940. LONG Width;
  1941. HDC FontDc;
  1942. SendDlgItemMessage(Hwnd, IDC_OPTION_TAB_WIDTH, EM_LIMITTEXT,
  1943. sizeof(Text) - 1, 0);
  1944. _itoa(EditTabToUserTab(g_TabWidth), Text, 10);
  1945. SetWindowText(GetDlgItem(Hwnd, IDC_OPTION_TAB_WIDTH), Text);
  1946. g_pUiControl->GetEngineOptions(&EngOptions);
  1947. CheckDlgButton(Hwnd, IDC_OPTION_REPEAT_COMMANDS,
  1948. (EngOptions & DEBUG_ENGOPT_NO_EXECUTE_REPEAT) == 0 ?
  1949. BST_CHECKED : BST_UNCHECKED);
  1950. Ctrl = GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST);
  1951. SendMessage(Ctrl, WM_SETFONT, (WPARAM)g_Fonts[FONT_VARIABLE].Font, 0);
  1952. FontDc = GetDC(Ctrl);
  1953. SelectObject(FontDc, g_Fonts[FONT_VARIABLE].Font);
  1954. Width = 0;
  1955. SendMessage(Ctrl, LB_RESETCONTENT, 0, 0);
  1956. for (Sel = 0; Sel < COL_COUNT; Sel++)
  1957. {
  1958. Idx = SendMessage(Ctrl, LB_ADDSTRING,
  1959. 0, (LPARAM)g_Colors[Sel].Name);
  1960. SendMessage(Ctrl, LB_SETITEMDATA, Idx, Sel);
  1961. if (FontDc != NULL)
  1962. {
  1963. SIZE Extent;
  1964. if (GetTextExtentPoint32(FontDc, g_Colors[Sel].Name,
  1965. strlen(g_Colors[Sel].Name),
  1966. &Extent) &&
  1967. Extent.cx > Width)
  1968. {
  1969. Width = Extent.cx;
  1970. }
  1971. }
  1972. }
  1973. for (Sel = 0; Sel < OUT_MASK_COL_COUNT; Sel++)
  1974. {
  1975. if (g_OutMaskColors[Sel].Name != NULL)
  1976. {
  1977. Idx = SendMessage(Ctrl, LB_ADDSTRING,
  1978. 0, (LPARAM)g_OutMaskColors[Sel].Name);
  1979. SendMessage(Ctrl, LB_SETITEMDATA,
  1980. Idx, Sel + OUT_MASK_COL_BASE);
  1981. if (FontDc != NULL)
  1982. {
  1983. SIZE Extent;
  1984. if (GetTextExtentPoint32(FontDc, g_OutMaskColors[Sel].Name,
  1985. strlen(g_OutMaskColors[Sel].Name),
  1986. &Extent) &&
  1987. Extent.cx > Width)
  1988. {
  1989. Width = Extent.cx;
  1990. }
  1991. }
  1992. }
  1993. }
  1994. SendMessage(Ctrl, LB_SETCURSEL, 0, 0);
  1995. if (FontDc != NULL)
  1996. {
  1997. ReleaseDC(Ctrl, FontDc);
  1998. }
  1999. Width += g_Fonts[FONT_VARIABLE].Metrics.tmAveCharWidth;
  2000. SendMessage(Ctrl, LB_SETHORIZONTALEXTENT, Width, 0);
  2001. CheckDlgButton(Hwnd, IDC_OPTION_DISASM_ACTIVATE_SOURCE,
  2002. g_DisasmActivateSource ? BST_CHECKED : BST_UNCHECKED);
  2003. CheckDlgButton(Hwnd, IDC_OPTION_AUTO_CMD_SCROLL,
  2004. g_AutoCmdScroll ? BST_CHECKED : BST_UNCHECKED);
  2005. break;
  2006. case WM_CTLCOLORSTATIC:
  2007. if ((HWND)Lpm == GetDlgItem(Hwnd, IDC_OPTION_COLOR_DISPLAY))
  2008. {
  2009. Sel = SendMessage(GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST),
  2010. LB_GETCURSEL, 0, 0);
  2011. if (Sel >= 0)
  2012. {
  2013. Idx = SendMessage(GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST),
  2014. LB_GETITEMDATA, Sel, 0);
  2015. INDEXED_COLOR* IdxCol = GetIndexedColor((ULONG)Idx);
  2016. if (IdxCol != NULL)
  2017. {
  2018. return (INT_PTR)IdxCol->Brush;
  2019. }
  2020. }
  2021. }
  2022. break;
  2023. case WM_COMMAND:
  2024. switch(LOWORD(Wpm))
  2025. {
  2026. case IDC_OPTION_COLOR_LIST:
  2027. Sel = SendMessage(GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST),
  2028. LB_GETCURSEL, 0, 0);
  2029. if (Sel >= 0)
  2030. {
  2031. InvalidateRect(GetDlgItem(Hwnd, IDC_OPTION_COLOR_DISPLAY),
  2032. NULL, TRUE);
  2033. }
  2034. break;
  2035. case IDC_OPTION_COLOR_CHANGE:
  2036. Sel = SendMessage(GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST),
  2037. LB_GETCURSEL, 0, 0);
  2038. if (Sel >= 0)
  2039. {
  2040. Idx = SendMessage(GetDlgItem(Hwnd, IDC_OPTION_COLOR_LIST),
  2041. LB_GETITEMDATA, Sel, 0);
  2042. if (SelectColor(g_hwndFrame, (ULONG)Idx))
  2043. {
  2044. InvalidateRect(GetDlgItem(Hwnd, IDC_OPTION_COLOR_DISPLAY),
  2045. NULL, TRUE);
  2046. }
  2047. }
  2048. break;
  2049. case IDHELP:
  2050. OpenHelpTopic(HELP_TOPIC_POPUP_OPTIONS);
  2051. break;
  2052. case IDOK:
  2053. if (GetWindowText(GetDlgItem(Hwnd, IDC_OPTION_TAB_WIDTH),
  2054. Text, sizeof(Text)) == 0)
  2055. {
  2056. MessageBeep(-1);
  2057. break;
  2058. }
  2059. if (sscanf(Text, "%d", &g_TabWidth) != 1)
  2060. {
  2061. MessageBeep(-1);
  2062. }
  2063. g_TabWidth = UserTabToEditTab(g_TabWidth);
  2064. SetTabWidth(g_TabWidth);
  2065. ULONG RepeatState;
  2066. if (IsDlgButtonChecked(Hwnd, IDC_OPTION_REPEAT_COMMANDS) ==
  2067. BST_CHECKED)
  2068. {
  2069. g_pUiControl->
  2070. RemoveEngineOptions(DEBUG_ENGOPT_NO_EXECUTE_REPEAT);
  2071. RepeatState = TRUE;
  2072. }
  2073. else
  2074. {
  2075. g_pUiControl->
  2076. AddEngineOptions(DEBUG_ENGOPT_NO_EXECUTE_REPEAT);
  2077. RepeatState = FALSE;
  2078. }
  2079. if (g_Workspace != NULL)
  2080. {
  2081. g_Workspace->SetUlong(WSP_GLOBAL_REPEAT_COMMANDS, RepeatState);
  2082. }
  2083. UpdateAllColors();
  2084. g_DisasmActivateSource =
  2085. IsDlgButtonChecked(Hwnd, IDC_OPTION_DISASM_ACTIVATE_SOURCE) ==
  2086. BST_CHECKED;
  2087. if (g_Workspace != NULL)
  2088. {
  2089. g_Workspace->SetUlong(WSP_GLOBAL_DISASM_ACTIVATE_SOURCE,
  2090. g_DisasmActivateSource);
  2091. }
  2092. g_AutoCmdScroll =
  2093. IsDlgButtonChecked(Hwnd, IDC_OPTION_AUTO_CMD_SCROLL) ==
  2094. BST_CHECKED;
  2095. if (g_Workspace != NULL)
  2096. {
  2097. g_Workspace->SetUlong(WSP_GLOBAL_AUTO_CMD_SCROLL,
  2098. g_AutoCmdScroll);
  2099. }
  2100. // Fall through.
  2101. case IDCANCEL:
  2102. EndDialog(Hwnd, LOWORD(Wpm));
  2103. break;
  2104. }
  2105. break;
  2106. default:
  2107. return FALSE;
  2108. }
  2109. return TRUE;
  2110. }
  2111. void
  2112. ClwFillSaveList(HWND List)
  2113. {
  2114. SendMessage(List, LB_RESETCONTENT, 0, 0);
  2115. if (g_Workspace != NULL)
  2116. {
  2117. WSP_ENTRY* Entry = NULL;
  2118. LRESULT Idx;
  2119. BOOL CommonWinDone = FALSE;
  2120. while ((Entry = g_Workspace->NextEntry(Entry)) != NULL)
  2121. {
  2122. if (Entry->Tag == WSP_WINDOW_COMMONWIN_1)
  2123. {
  2124. if (CommonWinDone)
  2125. {
  2126. continue;
  2127. }
  2128. CommonWinDone = TRUE;
  2129. }
  2130. Idx = SendMessage(List, LB_ADDSTRING, 0, (LPARAM)
  2131. GetWspTagName(Entry->Tag));
  2132. SendMessage(List, LB_SETITEMDATA, Idx, (LPARAM)Entry->Tag);
  2133. }
  2134. }
  2135. SendMessage(List, LB_SETCURSEL, 0, 0);
  2136. }
  2137. void
  2138. ClwMoveBetweenLists(HWND From, HWND To, LRESULT Item)
  2139. {
  2140. LPARAM Data = SendMessage(From, LB_GETITEMDATA, Item, 0);
  2141. SendMessage(From, LB_DELETESTRING, Item, 0);
  2142. Item = SendMessage(To, LB_ADDSTRING, 0, (LPARAM)
  2143. GetWspTagName((WSP_TAG)Data));
  2144. SendMessage(To, LB_SETITEMDATA, Item, Data);
  2145. }
  2146. void
  2147. ClwMoveAllBetweenLists(HWND From, HWND To)
  2148. {
  2149. LRESULT Count = SendMessage(From, LB_GETCOUNT, 0, 0);
  2150. while (Count-- > 0)
  2151. {
  2152. ClwMoveBetweenLists(From, To, 0);
  2153. }
  2154. }
  2155. void
  2156. ClwMoveSelectedBetweenLists(HWND From, HWND To)
  2157. {
  2158. int Sel[1];
  2159. LRESULT Count;
  2160. // Move items one at a time as the indices change
  2161. // when items are moved.
  2162. for (;;)
  2163. {
  2164. Count = SendMessage(From, LB_GETSELITEMS,
  2165. sizeof(Sel) / sizeof(Sel[0]), (LPARAM)Sel);
  2166. if (Count <= 0)
  2167. {
  2168. break;
  2169. }
  2170. ClwMoveBetweenLists(From, To, Sel[0]);
  2171. }
  2172. }
  2173. void
  2174. ClwProcessClearList(HWND List)
  2175. {
  2176. LRESULT Count = SendMessage(List, LB_GETCOUNT, 0, 0);
  2177. LRESULT i;
  2178. WSP_TAG Tag;
  2179. for (i = 0; i < Count; i++)
  2180. {
  2181. Tag = (WSP_TAG)SendMessage(List, LB_GETITEMDATA, i, 0);
  2182. g_Workspace->Delete(Tag, WSP_GROUP_MASK | WSP_ITEM_MASK);
  2183. }
  2184. // If everything is deleted from an explicit workspace
  2185. // delete the workspace from the explicit registry area.
  2186. if (g_ExplicitWorkspace && g_Workspace->IsEmpty())
  2187. {
  2188. g_Workspace->DeleteReg(TRUE);
  2189. delete g_Workspace;
  2190. g_Workspace = NULL;
  2191. }
  2192. }
  2193. INT_PTR CALLBACK
  2194. DlgProc_ClearWorkspace(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2195. {
  2196. LRESULT Sel;
  2197. switch(Message)
  2198. {
  2199. case WM_INITDIALOG:
  2200. ClwFillSaveList(GetDlgItem(Hwnd, IDC_CLW_SAVE_LIST));
  2201. break;
  2202. case WM_COMMAND:
  2203. switch(LOWORD(Wpm))
  2204. {
  2205. case IDC_CLW_CLEAR:
  2206. ClwMoveSelectedBetweenLists(GetDlgItem(Hwnd, IDC_CLW_SAVE_LIST),
  2207. GetDlgItem(Hwnd, IDC_CLW_CLEAR_LIST));
  2208. break;
  2209. case IDC_CLW_CLEAR_ALL:
  2210. ClwMoveAllBetweenLists(GetDlgItem(Hwnd, IDC_CLW_SAVE_LIST),
  2211. GetDlgItem(Hwnd, IDC_CLW_CLEAR_LIST));
  2212. break;
  2213. case IDC_CLW_SAVE:
  2214. ClwMoveSelectedBetweenLists(GetDlgItem(Hwnd, IDC_CLW_CLEAR_LIST),
  2215. GetDlgItem(Hwnd, IDC_CLW_SAVE_LIST));
  2216. break;
  2217. case IDC_CLW_SAVE_ALL:
  2218. ClwMoveAllBetweenLists(GetDlgItem(Hwnd, IDC_CLW_CLEAR_LIST),
  2219. GetDlgItem(Hwnd, IDC_CLW_SAVE_LIST));
  2220. break;
  2221. case IDHELP:
  2222. OpenHelpTopic(HELP_TOPIC_POPUP_CLEAR_WORKSPACE);
  2223. break;
  2224. case IDOK:
  2225. ClwProcessClearList(GetDlgItem(Hwnd, IDC_CLW_CLEAR_LIST));
  2226. // Fall through.
  2227. case IDCANCEL:
  2228. EndDialog(Hwnd, LOWORD(Wpm));
  2229. break;
  2230. }
  2231. break;
  2232. default:
  2233. return FALSE;
  2234. }
  2235. return TRUE;
  2236. }
  2237. enum
  2238. {
  2239. MODCOL_NAME,
  2240. MODCOL_START,
  2241. MODCOL_END,
  2242. MODCOL_TIMESTAMP,
  2243. MODCOL_CHECKSUM,
  2244. MODCOL_SYMBOL_TYPE,
  2245. MODCOL_SYMBOL_FILE
  2246. };
  2247. void
  2248. InitializeModuleList(HWND List)
  2249. {
  2250. SendMessage(List, WM_SETFONT, (WPARAM)g_Fonts[FONT_FIXED].Font, FALSE);
  2251. LVCOLUMN Column;
  2252. // First column is for the module name.
  2253. Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  2254. Column.fmt = LVCFMT_LEFT;
  2255. Column.pszText = "Name";
  2256. Column.cx = 15 * g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2257. Column.iSubItem = MODCOL_NAME;
  2258. ListView_InsertColumn(List, 0, &Column);
  2259. // Second column is for start address.
  2260. Column.fmt = LVCFMT_CENTER;
  2261. Column.pszText = "Start";
  2262. Column.cx = (10 + (g_Ptr64 ? 9 : 0)) *
  2263. g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2264. Column.iSubItem = MODCOL_START;
  2265. ListView_InsertColumn(List, 1, &Column);
  2266. // Third column is for end address.
  2267. Column.fmt = LVCFMT_CENTER;
  2268. Column.pszText = "End";
  2269. Column.cx = (10 + (g_Ptr64 ? 9 : 0)) *
  2270. g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2271. Column.iSubItem = MODCOL_END;
  2272. ListView_InsertColumn(List, 2, &Column);
  2273. // Fourth column is for timestamp.
  2274. Column.fmt = LVCFMT_CENTER;
  2275. Column.pszText = "Timestamp";
  2276. Column.cx = 37 * g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2277. Column.iSubItem = MODCOL_TIMESTAMP;
  2278. ListView_InsertColumn(List, 3, &Column);
  2279. // Fifth column is for checksum.
  2280. Column.fmt = LVCFMT_CENTER;
  2281. Column.pszText = "Checksum";
  2282. Column.cx = 10 * g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2283. Column.iSubItem = MODCOL_CHECKSUM;
  2284. ListView_InsertColumn(List, 4, &Column);
  2285. // Sixth column is for symbol type.
  2286. Column.fmt = LVCFMT_CENTER;
  2287. Column.pszText = "Symbols";
  2288. Column.cx = 9 * g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2289. Column.iSubItem = MODCOL_SYMBOL_TYPE;
  2290. ListView_InsertColumn(List, 5, &Column);
  2291. // Seventh column is for symbol file.
  2292. Column.fmt = LVCFMT_LEFT;
  2293. Column.pszText = "Symbol file";
  2294. Column.cx = 80 * g_Fonts[FONT_FIXED].Metrics.tmAveCharWidth;
  2295. Column.iSubItem = MODCOL_SYMBOL_FILE;
  2296. ListView_InsertColumn(List, 6, &Column);
  2297. }
  2298. void
  2299. FillModuleList(HWND List)
  2300. {
  2301. LVCOLUMN Column;
  2302. Column.mask = LVCF_FMT;
  2303. if (!ListView_GetColumn(List, 0, &Column))
  2304. {
  2305. InitializeModuleList(List);
  2306. }
  2307. LVITEM Item;
  2308. ULONG i;
  2309. char Image[128];
  2310. char Text[128];
  2311. char Path[MAX_PATH];
  2312. ListView_DeleteAllItems(List);
  2313. if (g_ModuleBuffer->UiLockForRead() != S_OK)
  2314. {
  2315. Item.mask = LVIF_TEXT;
  2316. Item.iItem = 0;
  2317. Item.iSubItem = 0;
  2318. Item.pszText = "Unable to retrieve module list";
  2319. ListView_InsertItem(List, &Item);
  2320. return;
  2321. }
  2322. PDEBUG_MODULE_PARAMETERS Params = (PDEBUG_MODULE_PARAMETERS)
  2323. g_ModuleBuffer->GetDataBuffer();
  2324. for (i = 0; i < g_NumModules; i++)
  2325. {
  2326. PSTR LoadBuf;
  2327. ULONG LoadBufLen;
  2328. if ((Params->Flags & DEBUG_MODULE_UNLOADED) ||
  2329. g_pUiSymbols2 == NULL ||
  2330. g_pUiSymbols2->
  2331. GetModuleNameString(DEBUG_MODNAME_SYMBOL_FILE, DEBUG_ANY_ID,
  2332. Params->Base, Path, sizeof(Path),
  2333. NULL) != S_OK)
  2334. {
  2335. LoadBuf = Path;
  2336. LoadBufLen = sizeof(Path);
  2337. }
  2338. else
  2339. {
  2340. LoadBuf = NULL;
  2341. LoadBufLen = 0;
  2342. }
  2343. if (g_pUiSymbols->GetModuleNames(DEBUG_ANY_ID, Params->Base,
  2344. Image, sizeof(Image), NULL,
  2345. Text, sizeof(Text), NULL,
  2346. LoadBuf, LoadBufLen, NULL) != S_OK)
  2347. {
  2348. strcpy(Text, "<Unable to get name>");
  2349. if (LoadBuf != NULL)
  2350. {
  2351. strcpy(LoadBuf, "<Unable to get name>");
  2352. }
  2353. }
  2354. if (Params->Flags & DEBUG_MODULE_UNLOADED)
  2355. {
  2356. strcpy(Text, "<Unloaded>");
  2357. strcpy(Path, Image);
  2358. }
  2359. Item.mask = LVIF_TEXT | LVIF_PARAM;
  2360. Item.iItem = i;
  2361. Item.iSubItem = MODCOL_NAME;
  2362. Item.pszText = Text;
  2363. Item.lParam = i;
  2364. ListView_InsertItem(List, &Item);
  2365. ListView_SetItemText(List, i, MODCOL_START,
  2366. FormatAddr64(Params->Base));
  2367. ListView_SetItemText(List, i, MODCOL_END,
  2368. FormatAddr64(Params->Base + Params->Size));
  2369. if (Params->TimeDateStamp < 0xfffffffe)
  2370. {
  2371. time_t Time = (time_t)Params->TimeDateStamp;
  2372. strcpy(Text, ctime(&Time));
  2373. sprintf(Text + strlen(Text) - 1, " (%08x)", Params->TimeDateStamp);
  2374. }
  2375. else
  2376. {
  2377. sprintf(Text, "Unavailable");
  2378. }
  2379. ListView_SetItemText(List, i, MODCOL_TIMESTAMP, Text);
  2380. sprintf(Text, "%08x", Params->Checksum);
  2381. ListView_SetItemText(List, i, MODCOL_CHECKSUM, Text);
  2382. if (Params->SymbolType != DEBUG_SYMTYPE_DEFERRED &&
  2383. Params->SymbolType <
  2384. sizeof(g_SymbolTypeNames) / sizeof(g_SymbolTypeNames[0]))
  2385. {
  2386. ListView_SetItemText(List, i, MODCOL_SYMBOL_TYPE,
  2387. g_SymbolTypeNames[Params->SymbolType]);
  2388. }
  2389. else
  2390. {
  2391. ListView_SetItemText(List, i, MODCOL_SYMBOL_TYPE, "");
  2392. }
  2393. ListView_SetItemText(List, i, MODCOL_SYMBOL_FILE, Path);
  2394. Params++;
  2395. }
  2396. UnlockStateBuffer(g_ModuleBuffer);
  2397. }
  2398. struct SORT_MODULE
  2399. {
  2400. HWND List;
  2401. int Column;
  2402. };
  2403. int CALLBACK
  2404. SortModuleCompare(LPARAM Lpm1, LPARAM Lpm2, LPARAM LpmSort)
  2405. {
  2406. SORT_MODULE* Sort = (SORT_MODULE*)LpmSort;
  2407. LVITEM Item;
  2408. char Text1[MAX_PATH], Text2[MAX_PATH];
  2409. PDEBUG_MODULE_PARAMETERS Param1, Param2;
  2410. switch(Sort->Column)
  2411. {
  2412. case MODCOL_NAME:
  2413. case MODCOL_START:
  2414. case MODCOL_END:
  2415. case MODCOL_CHECKSUM:
  2416. case MODCOL_SYMBOL_TYPE:
  2417. case MODCOL_SYMBOL_FILE:
  2418. Item.mask = LVIF_TEXT;
  2419. Item.iItem = (int)Lpm1;
  2420. Item.iSubItem = Sort->Column;
  2421. Item.pszText = Text1;
  2422. Item.cchTextMax = sizeof(Text1);
  2423. ListView_GetItem(Sort->List, &Item);
  2424. Item.iItem = (int)Lpm2;
  2425. Item.pszText = Text2;
  2426. Item.cchTextMax = sizeof(Text2);
  2427. ListView_GetItem(Sort->List, &Item);
  2428. // Sort all empty text towards the bottom.
  2429. if (Text1[0] == 0 && Text2[0] != 0)
  2430. {
  2431. return 1;
  2432. }
  2433. else if (Text2[0] == 0 && Text1[0] != 0)
  2434. {
  2435. return -1;
  2436. }
  2437. return _strcmpi(Text1, Text2);
  2438. case MODCOL_TIMESTAMP:
  2439. Item.mask = LVIF_PARAM;
  2440. Item.iItem = (int)Lpm1;
  2441. Item.iSubItem = 0;
  2442. ListView_GetItem(Sort->List, &Item);
  2443. Param1 = (PDEBUG_MODULE_PARAMETERS)
  2444. g_ModuleBuffer->GetDataBuffer() + Item.lParam;
  2445. Item.iItem = (int)Lpm2;
  2446. ListView_GetItem(Sort->List, &Item);
  2447. Param2 = (PDEBUG_MODULE_PARAMETERS)
  2448. g_ModuleBuffer->GetDataBuffer() + Item.lParam;
  2449. switch(Sort->Column)
  2450. {
  2451. case MODCOL_TIMESTAMP:
  2452. return Param1->TimeDateStamp < Param2->TimeDateStamp ?
  2453. -1 : (Param1->TimeDateStamp > Param2->TimeDateStamp ?
  2454. 1 : 0);
  2455. }
  2456. }
  2457. return 0;
  2458. }
  2459. void
  2460. SortModuleColumns(HWND List, int Column)
  2461. {
  2462. if (g_ModuleBuffer->UiLockForRead() != S_OK)
  2463. {
  2464. return;
  2465. }
  2466. SORT_MODULE Sort = {List, Column};
  2467. ListView_SortItemsEx(List, SortModuleCompare, (LPARAM)&Sort);
  2468. UnlockStateBuffer(g_ModuleBuffer);
  2469. }
  2470. INT_PTR CALLBACK
  2471. DlgProc_Modules(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2472. {
  2473. LRESULT Sel;
  2474. switch(Message)
  2475. {
  2476. case WM_INITDIALOG:
  2477. g_ModuleBuffer->m_Win = Hwnd;
  2478. FillModuleList(GetDlgItem(Hwnd, IDC_MODULE_LIST));
  2479. break;
  2480. case WM_COMMAND:
  2481. switch(LOWORD(Wpm))
  2482. {
  2483. case IDHELP:
  2484. OpenHelpTopic(HELP_TOPIC_POPUP_MODULES);
  2485. break;
  2486. case IDCANCEL:
  2487. g_ModuleBuffer->m_Win = NULL;
  2488. EndDialog(Hwnd, LOWORD(Wpm));
  2489. break;
  2490. }
  2491. break;
  2492. case WM_NOTIFY:
  2493. if (Wpm == IDC_MODULE_LIST)
  2494. {
  2495. LPNMLISTVIEW Notify = (LPNMLISTVIEW)Lpm;
  2496. if (Notify->hdr.code == LVN_COLUMNCLICK)
  2497. {
  2498. SortModuleColumns(GetDlgItem(Hwnd, IDC_MODULE_LIST),
  2499. Notify->iSubItem);
  2500. }
  2501. }
  2502. break;
  2503. case LB_RESETCONTENT:
  2504. FillModuleList(GetDlgItem(Hwnd, IDC_MODULE_LIST));
  2505. break;
  2506. default:
  2507. return FALSE;
  2508. }
  2509. return TRUE;
  2510. }
  2511. void
  2512. EnumWorkspaceKey(HWND List, HKEY BaseKey, ULONG SubKey, BOOL ShowSubKey,
  2513. BOOL OmitCurrent)
  2514. {
  2515. LONG Status;
  2516. HKEY Key;
  2517. char Text[128];
  2518. sprintf(Text, WSP_REG_KEY "\\%s", g_WorkspaceKeyNames[SubKey]);
  2519. if ((Status = RegOpenKeyEx(BaseKey, Text,
  2520. 0, KEY_ALL_ACCESS, &Key)) != ERROR_SUCCESS)
  2521. {
  2522. return;
  2523. }
  2524. ULONG Index;
  2525. char Name[MAX_WSP_NAME];
  2526. ULONG NameLen;
  2527. ULONG Type;
  2528. ULONG Item;
  2529. Index = 0;
  2530. for (;;)
  2531. {
  2532. NameLen = sizeof(Name);
  2533. if ((Status = RegEnumValue(Key, Index, Name, &NameLen,
  2534. NULL, &Type, NULL, 0)) != ERROR_SUCCESS)
  2535. {
  2536. // Done with the enumeration.
  2537. break;
  2538. }
  2539. if (Type != REG_BINARY)
  2540. {
  2541. // Only binary values should be present.
  2542. break;
  2543. }
  2544. if (OmitCurrent && g_Workspace &&
  2545. SubKey == g_Workspace->GetKey() &&
  2546. !strcmp(g_Workspace->GetValue(), Name))
  2547. {
  2548. Index++;
  2549. continue;
  2550. }
  2551. if (ShowSubKey)
  2552. {
  2553. sprintf(Text, "%s - %s", g_WorkspaceKeyDescriptions[SubKey], Name);
  2554. Item = (ULONG)SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Text);
  2555. }
  2556. else
  2557. {
  2558. Item = (ULONG)SendMessage(List, LB_ADDSTRING, 0, (LPARAM)Name);
  2559. }
  2560. SendMessage(List, LB_SETITEMDATA, Item, SubKey);
  2561. Index++;
  2562. }
  2563. RegCloseKey(Key);
  2564. }
  2565. void
  2566. FillWorkspaceList(HWND List)
  2567. {
  2568. SendMessage(List, LB_RESETCONTENT, 0, 0);
  2569. EnumWorkspaceKey(List, HKEY_CURRENT_USER, WSP_NAME_EXPLICIT,
  2570. FALSE, FALSE);
  2571. EnumWorkspaceKey(List, HKEY_LOCAL_MACHINE, WSP_NAME_EXPLICIT,
  2572. FALSE, FALSE);
  2573. SendMessage(List, LB_SETCURSEL, 0, 0);
  2574. }
  2575. INT_PTR CALLBACK
  2576. DlgProc_OpenWorkspace(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2577. {
  2578. char Name[MAX_WSP_NAME];
  2579. LRESULT Sel;
  2580. HRESULT Status;
  2581. switch(Message)
  2582. {
  2583. case WM_INITDIALOG:
  2584. SetWindowText(Hwnd, "Open Workspace");
  2585. SendDlgItemMessage(Hwnd, IDC_WORKSPACE_NAME, EM_LIMITTEXT,
  2586. sizeof(Name) - 1, 0);
  2587. FillWorkspaceList(GetDlgItem(Hwnd, IDC_WORKSPACE_LIST));
  2588. SetWindowText(GetDlgItem(Hwnd, IDC_WORKSPACE_NAME), "");
  2589. break;
  2590. case WM_COMMAND:
  2591. switch(LOWORD(Wpm))
  2592. {
  2593. case IDC_WORKSPACE_LIST:
  2594. Sel = SendDlgItemMessage(Hwnd, IDC_WORKSPACE_LIST,
  2595. LB_GETCURSEL, 0, 0);
  2596. if (Sel >= 0 &&
  2597. SendDlgItemMessage(Hwnd, IDC_WORKSPACE_LIST, LB_GETTEXT,
  2598. Sel, (LPARAM)Name))
  2599. {
  2600. SetWindowText(GetDlgItem(Hwnd, IDC_WORKSPACE_NAME), Name);
  2601. }
  2602. break;
  2603. case IDHELP:
  2604. OpenHelpTopic(HELP_TOPIC_POPUP_OPEN_WORKSPACE);
  2605. break;
  2606. case IDOK:
  2607. if (SendDlgItemMessage(Hwnd, IDC_WORKSPACE_NAME, WM_GETTEXT,
  2608. sizeof(Name), (LPARAM)Name))
  2609. {
  2610. int Starts = 0;
  2611. if ((Status = UiSwitchWorkspace(WSP_NAME_EXPLICIT,
  2612. Name, FALSE,
  2613. WSP_APPLY_EXPLICIT,
  2614. &Starts)) != S_OK)
  2615. {
  2616. if (Starts < 0)
  2617. {
  2618. InformationBox(ERR_Workspace_Session_Conflict, Status);
  2619. }
  2620. else
  2621. {
  2622. InformationBox(ERR_Cant_Open_Workspace, Status);
  2623. }
  2624. break;
  2625. }
  2626. else
  2627. {
  2628. g_ExplicitWorkspace = TRUE;
  2629. if (Starts == 1)
  2630. {
  2631. StartDebugging();
  2632. }
  2633. }
  2634. }
  2635. // Fall through.
  2636. case IDCANCEL:
  2637. EndDialog(Hwnd, LOWORD(Wpm));
  2638. break;
  2639. }
  2640. break;
  2641. default:
  2642. return FALSE;
  2643. }
  2644. return FALSE;
  2645. }
  2646. INT_PTR CALLBACK
  2647. DlgProc_SaveWorkspaceAs(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2648. {
  2649. char Name[MAX_WSP_NAME];
  2650. LRESULT Sel;
  2651. HRESULT Status;
  2652. switch(Message)
  2653. {
  2654. case WM_INITDIALOG:
  2655. SetWindowText(Hwnd, "Save Workspace As");
  2656. SendDlgItemMessage(Hwnd, IDC_WORKSPACE_NAME, EM_LIMITTEXT,
  2657. sizeof(Name) - 1, 0);
  2658. FillWorkspaceList(GetDlgItem(Hwnd, IDC_WORKSPACE_LIST));
  2659. SetWindowText(GetDlgItem(Hwnd, IDC_WORKSPACE_NAME),
  2660. g_Workspace->GetValue());
  2661. break;
  2662. case WM_COMMAND:
  2663. switch(LOWORD(Wpm))
  2664. {
  2665. case IDC_WORKSPACE_LIST:
  2666. Sel = SendDlgItemMessage(Hwnd, IDC_WORKSPACE_LIST,
  2667. LB_GETCURSEL, 0, 0);
  2668. if (Sel >= 0 &&
  2669. SendDlgItemMessage(Hwnd, IDC_WORKSPACE_LIST, LB_GETTEXT,
  2670. Sel, (LPARAM)Name))
  2671. {
  2672. SetWindowText(GetDlgItem(Hwnd, IDC_WORKSPACE_NAME), Name);
  2673. }
  2674. break;
  2675. case IDHELP:
  2676. OpenHelpTopic(HELP_TOPIC_POPUP_SAVE_WORKSPACE_AS);
  2677. break;
  2678. case IDOK:
  2679. if (SendDlgItemMessage(Hwnd, IDC_WORKSPACE_NAME, WM_GETTEXT,
  2680. sizeof(Name), (LPARAM)Name) == 0)
  2681. {
  2682. MessageBeep(0);
  2683. break;
  2684. }
  2685. Status = g_Workspace->ChangeName(WSP_NAME_EXPLICIT, Name, FALSE);
  2686. if (Status == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
  2687. {
  2688. if (QuestionBox(ERR_Workspace_Already_Exists, MB_YESNO,
  2689. Name) == IDNO)
  2690. {
  2691. break;
  2692. }
  2693. Status = g_Workspace->ChangeName(WSP_NAME_EXPLICIT, Name,
  2694. TRUE);
  2695. }
  2696. if (Status != S_OK)
  2697. {
  2698. InformationBox(ERR_Cant_Save_Workspace, Status);
  2699. break;
  2700. }
  2701. g_Workspace->Flush(TRUE, FALSE);
  2702. // Fall through.
  2703. case IDCANCEL:
  2704. EndDialog(Hwnd, LOWORD(Wpm));
  2705. break;
  2706. }
  2707. break;
  2708. default:
  2709. return FALSE;
  2710. }
  2711. return FALSE;
  2712. }
  2713. INT_PTR CALLBACK
  2714. DlgProc_AddToCommandHistory(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2715. {
  2716. char Text[MAX_COMMAND_LEN];
  2717. PSTR TextEnd;
  2718. switch(Message)
  2719. {
  2720. case WM_INITDIALOG:
  2721. SendDlgItemMessage(Hwnd, IDC_ATCH_TEXT, EM_LIMITTEXT,
  2722. sizeof(Text) - 2, 0);
  2723. SetWindowText(GetDlgItem(Hwnd, IDC_ATCH_TEXT), "");
  2724. break;
  2725. case WM_COMMAND:
  2726. switch(LOWORD(Wpm))
  2727. {
  2728. case IDHELP:
  2729. OpenHelpTopic(HELP_TOPIC_POPUP_ADD_TO_COMMAND_OUTPUT);
  2730. break;
  2731. case IDOK:
  2732. GetWindowText(GetDlgItem(Hwnd, IDC_ATCH_TEXT),
  2733. Text, sizeof(Text) - 1);
  2734. TextEnd = Text + strlen(Text);
  2735. *TextEnd++ = '\n';
  2736. *TextEnd = 0;
  2737. CmdOutput(Text,
  2738. g_OutMaskColors[USER_OUT_MASK_COL].Color,
  2739. g_OutMaskColors[USER_OUT_MASK_COL + 1].Color);
  2740. // Send output for logging only.
  2741. g_pUiControl->ControlledOutput(DEBUG_OUTCTL_LOG_ONLY,
  2742. DEBUG_OUTPUT_NORMAL,
  2743. "%s", Text);
  2744. // Fall through.
  2745. case IDCANCEL:
  2746. EndDialog(Hwnd, LOWORD(Wpm));
  2747. break;
  2748. }
  2749. break;
  2750. default:
  2751. return FALSE;
  2752. }
  2753. return TRUE;
  2754. }
  2755. void
  2756. FillDeleteWorkspacesList(HWND List)
  2757. {
  2758. int i;
  2759. SendMessage(List, LB_RESETCONTENT, 0, 0);
  2760. for (i = 0; i < WSP_NAME_COUNT; i++)
  2761. {
  2762. EnumWorkspaceKey(List, HKEY_CURRENT_USER, i, TRUE, TRUE);
  2763. EnumWorkspaceKey(List, HKEY_LOCAL_MACHINE, i, TRUE, TRUE);
  2764. }
  2765. SendMessage(List, LB_SETCURSEL, 0, 0);
  2766. }
  2767. INT_PTR CALLBACK
  2768. DlgProc_DeleteWorkspaces(HWND Hwnd, UINT Message, WPARAM Wpm, LPARAM Lpm)
  2769. {
  2770. HWND List = GetDlgItem(Hwnd, IDC_WORKSPACE_LIST);
  2771. LRESULT Sel;
  2772. char NameBuf[MAX_WSP_NAME];
  2773. PSTR Name;
  2774. switch(Message)
  2775. {
  2776. case WM_INITDIALOG:
  2777. FillDeleteWorkspacesList(List);
  2778. break;
  2779. case WM_COMMAND:
  2780. switch(LOWORD(Wpm))
  2781. {
  2782. case IDC_WORKSPACE_LIST:
  2783. if (HIWORD(Wpm) == LBN_DBLCLK)
  2784. {
  2785. goto DelItem;
  2786. }
  2787. break;
  2788. case IDC_DELETE_WORKSPACE:
  2789. DelItem:
  2790. Sel = SendMessage(List, LB_GETCURSEL, 0, 0);
  2791. if (Sel >= 0)
  2792. {
  2793. ULONG Key;
  2794. Key = (ULONG)SendMessage(List, LB_GETITEMDATA, Sel, 0);
  2795. SendMessage(List, LB_GETTEXT, Sel, (LPARAM)NameBuf);
  2796. // Skip over introductory key description.
  2797. Name = NameBuf + strlen(g_WorkspaceKeyDescriptions[Key]) + 3;
  2798. Workspace::DeleteRegKey(TRUE, Key, Name);
  2799. Workspace::DeleteRegKey(FALSE, Key, Name);
  2800. FillDeleteWorkspacesList(List);
  2801. }
  2802. break;
  2803. case IDHELP:
  2804. // XXX drewb - Topic.
  2805. // OpenHelpTopic(HELP_TOPIC_POPUP_GO_TO_ADDRESS);
  2806. break;
  2807. case IDCANCEL:
  2808. EndDialog(Hwnd, LOWORD(Wpm));
  2809. break;
  2810. }
  2811. break;
  2812. default:
  2813. return FALSE;
  2814. }
  2815. return TRUE;
  2816. }
  2817. BOOL
  2818. CreateIndexedFont(ULONG FontIndex, BOOL SetAll)
  2819. {
  2820. HFONT Font;
  2821. Font = CreateFontIndirect(&g_Fonts[FontIndex].LogFont);
  2822. if (Font != NULL)
  2823. {
  2824. if (g_Fonts[FontIndex].Font)
  2825. {
  2826. DeleteObject(g_Fonts[FontIndex].Font);
  2827. }
  2828. g_Fonts[FontIndex].Font = Font;
  2829. g_Fonts[FontIndex].LogFontSet = TRUE;
  2830. HDC Dc = GetDC(NULL);
  2831. if (Dc != NULL)
  2832. {
  2833. SelectObject(Dc, Font);
  2834. GetTextMetrics(Dc, &g_Fonts[FontIndex].Metrics);
  2835. ReleaseDC(NULL, Dc);
  2836. }
  2837. if (SetAll)
  2838. {
  2839. SetAllFonts(FontIndex);
  2840. }
  2841. return TRUE;
  2842. }
  2843. else
  2844. {
  2845. return FALSE;
  2846. }
  2847. }
  2848. void
  2849. SelectFont(HWND Parent, ULONG FontIndex)
  2850. {
  2851. CHOOSEFONT Choose;
  2852. ZeroMemory(&Choose, sizeof(Choose));
  2853. Choose.lStructSize = sizeof(Choose);
  2854. Choose.hwndOwner = Parent;
  2855. Choose.lpLogFont = &g_Fonts[FontIndex].LogFont;
  2856. Choose.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
  2857. CF_SCREENFONTS | (g_Fonts[FontIndex].LogFontSet ?
  2858. CF_INITTOLOGFONTSTRUCT : 0);
  2859. if (ChooseFont(&Choose))
  2860. {
  2861. if (CreateIndexedFont(FontIndex, TRUE) && g_Workspace != NULL)
  2862. {
  2863. // If this function really is used to select different
  2864. // fonts the tag will have to be dynamically chosen.
  2865. g_Workspace->SetBuffer(WSP_GLOBAL_FIXED_LOGFONT,
  2866. &g_Fonts[FontIndex].LogFont,
  2867. sizeof(g_Fonts[FontIndex].LogFont));
  2868. }
  2869. }
  2870. }
  2871. BOOL
  2872. SelectColor(HWND Parent, ULONG Index)
  2873. {
  2874. CHOOSECOLOR Choose;
  2875. INDEXED_COLOR* IdxCol = GetIndexedColor(Index);
  2876. ZeroMemory(&Choose, sizeof(Choose));
  2877. Choose.lStructSize = sizeof(Choose);
  2878. Choose.hwndOwner = Parent;
  2879. Choose.rgbResult = IdxCol->Color;
  2880. Choose.lpCustColors = g_CustomColors;
  2881. Choose.Flags = CC_ANYCOLOR | CC_RGBINIT;
  2882. if (ChooseColor(&Choose))
  2883. {
  2884. if (g_Workspace != NULL)
  2885. {
  2886. g_Workspace->SetUlong(DEF_WSP_TAG(WSP_GROUP_COLORS, Index),
  2887. (ULONG)Choose.rgbResult);
  2888. }
  2889. SetColor(Index, Choose.rgbResult);
  2890. return TRUE;
  2891. }
  2892. else
  2893. {
  2894. return FALSE;
  2895. }
  2896. }