Leaked source code of windows server 2003
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.

3627 lines
102 KiB

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