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

903 lines
25 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. Memwin.cpp
  5. Abstract:
  6. This module contains the main line code for display of multiple memory
  7. windows and the subclassed win proc to handle editing, display, etc.
  8. --*/
  9. #include "precomp.hxx"
  10. #pragma hdrstop
  11. _INTERFACE_TYPE_NAMES rgInterfaceTypeNames[MaximumInterfaceType] =
  12. {
  13. { Internal, "Internal" },
  14. { Isa, "Isa" },
  15. { Eisa, "Eisa" },
  16. { MicroChannel, "MicroChannel" },
  17. { TurboChannel, "TurboChannel" },
  18. { PCIBus, "PCIBus" },
  19. { VMEBus, "VMEBus" },
  20. { NuBus, "NuBus" },
  21. { PCMCIABus, "PCMCIABus" },
  22. { CBus, "CBus" },
  23. { MPIBus, "MPIBus" },
  24. { MPSABus, "MPSABus" },
  25. { ProcessorInternal, "ProcessorInternal" },
  26. { InternalPowerBus, "InternalPowerBus" },
  27. { PNPISABus, "PNPISABus" },
  28. { PNPBus, "PNPBus" }
  29. };
  30. _BUS_TYPE_NAMES rgBusTypeNames[MaximumBusDataType] =
  31. {
  32. { Cmos, "Cmos" },
  33. { EisaConfiguration, "EisaConfiguration" },
  34. { Pos, "Pos" },
  35. { CbusConfiguration, "CbusConfiguration" },
  36. { PCIConfiguration, "PCIConfiguration" },
  37. { VMEConfiguration, "VMEConfiguration" },
  38. { NuBusConfiguration, "NuBusConfiguration" },
  39. { PCMCIAConfiguration, "PCMCIAConfiguration" },
  40. { MPIConfiguration, "MPIConfiguration" },
  41. { MPSAConfiguration, "MPSAConfiguration" },
  42. { PNPISAConfiguration, "PNPISAConfiguration" },
  43. { SgiInternalConfiguration, "SgiInternalConfiguration" }
  44. };
  45. PSTR g_MemTypeNames[] =
  46. {
  47. "Virtual:", "Physical:", "Control:", "I/O:", "MSR:", "Bus data:"
  48. };
  49. //
  50. //
  51. //
  52. MEMWIN_DATA::MEMWIN_DATA()
  53. : EDITWIN_DATA(512)
  54. {
  55. m_enumType = MEM_WINDOW;
  56. ZeroMemory(&m_GenMemData, sizeof(m_GenMemData));
  57. strcpy(m_OffsetExpr, FormatAddr64(g_EventIp));
  58. m_GenMemData.memtype = VIRTUAL_MEM_TYPE;
  59. m_GenMemData.nDisplayFormat = 2;
  60. m_Columns = 4;
  61. m_WindowDataSize = 0;
  62. }
  63. void
  64. MEMWIN_DATA::Validate()
  65. {
  66. EDITWIN_DATA::Validate();
  67. Assert(MEM_WINDOW == m_enumType);
  68. }
  69. HRESULT
  70. MEMWIN_DATA::ReadState(void)
  71. {
  72. HRESULT Status;
  73. ULONG DataSize;
  74. ULONG DataNeeded;
  75. PVOID Data;
  76. ULONG64 Offset;
  77. DEBUG_VALUE Value;
  78. ULONG i;
  79. // Evaluate offset expression.
  80. if ((Status = g_pDbgControl->Evaluate(m_OffsetExpr, DEBUG_VALUE_INT64,
  81. &Value, NULL)) != S_OK)
  82. {
  83. return Status;
  84. }
  85. Offset = Value.I64;
  86. // Compute how much data to retrieve. We don't want to
  87. // create a big matrix of memtype/display format so just
  88. // ask for a chunk of data big enough for any display format.
  89. DataNeeded = m_LineHeight * m_Columns * 2 * sizeof(ULONG64);
  90. Empty();
  91. Data = AddData(DataNeeded);
  92. if (Data == NULL)
  93. {
  94. return E_OUTOFMEMORY;
  95. }
  96. ULONG Read;
  97. switch(m_GenMemData.memtype)
  98. {
  99. default:
  100. Assert(!"Unhandled condition");
  101. Status = E_FAIL;
  102. break;
  103. case PHYSICAL_MEM_TYPE:
  104. Status = g_pDbgData->ReadPhysical(Offset,
  105. Data,
  106. DataNeeded,
  107. &Read
  108. );
  109. break;
  110. case VIRTUAL_MEM_TYPE:
  111. Status = g_pDbgData->ReadVirtual(Offset,
  112. Data,
  113. DataNeeded,
  114. &Read
  115. );
  116. break;
  117. case CONTROL_MEM_TYPE:
  118. Status = g_pDbgData->ReadControl(m_GenMemData.any.control.Processor,
  119. Offset,
  120. Data,
  121. DataNeeded,
  122. &Read
  123. );
  124. break;
  125. case IO_MEM_TYPE:
  126. Status = g_pDbgData->ReadIo(m_GenMemData.any.io.interface_type,
  127. m_GenMemData.any.io.BusNumber,
  128. m_GenMemData.any.io.AddressSpace,
  129. Offset,
  130. Data,
  131. DataNeeded,
  132. &Read
  133. );
  134. break;
  135. case MSR_MEM_TYPE:
  136. Read = 0;
  137. for (i = 0; i < DataNeeded / sizeof(ULONG64); i++)
  138. {
  139. if ((Status = g_pDbgData->ReadMsr((ULONG)Offset + i,
  140. (PULONG64)Data + i
  141. )) != S_OK)
  142. {
  143. // Assume an error means we've run out of MSRs to
  144. // read. If some were read, don't consider it an error.
  145. if (Read > 0)
  146. {
  147. Status = S_OK;
  148. }
  149. break;
  150. }
  151. Read += sizeof(ULONG64);
  152. }
  153. break;
  154. case BUS_MEM_TYPE:
  155. Status = g_pDbgData->ReadBusData(m_GenMemData.any.bus.bus_type,
  156. m_GenMemData.any.bus.BusNumber,
  157. m_GenMemData.any.bus.SlotNumber,
  158. (ULONG)Offset,
  159. Data,
  160. DataNeeded,
  161. &Read
  162. );
  163. break;
  164. }
  165. if (Status == S_OK)
  166. {
  167. // Trim data back if read didn't get everything.
  168. RemoveTail(DataNeeded - Read);
  169. m_OffsetRead = Offset;
  170. }
  171. return Status;
  172. }
  173. BOOL
  174. MEMWIN_DATA::HasEditableProperties()
  175. {
  176. return TRUE;
  177. }
  178. BOOL
  179. MEMWIN_DATA::EditProperties()
  180. /*++
  181. Returns
  182. TRUE - If properties were edited
  183. FALSE - If nothing was changed
  184. --*/
  185. {
  186. if (g_TargetClass != DEBUG_CLASS_UNINITIALIZED)
  187. {
  188. INT_PTR Res = DisplayOptionsPropSheet(GetParent(m_hwndChild),
  189. g_hInst,
  190. m_GenMemData.memtype
  191. );
  192. if (IDOK == Res)
  193. {
  194. UpdateOptions();
  195. return TRUE; // Properties have been changed
  196. }
  197. }
  198. MessageBeep(0);
  199. return FALSE; // No Debuggee or User Cancel out.
  200. }
  201. BOOL
  202. MEMWIN_DATA::OnCreate(void)
  203. {
  204. RECT Rect;
  205. int i;
  206. ULONG Height;
  207. Height = GetSystemMetrics(SM_CYVSCROLL) + 4 * GetSystemMetrics(SM_CYEDGE);
  208. m_Toolbar = CreateWindowEx(0, REBARCLASSNAME, NULL,
  209. WS_VISIBLE | WS_CHILD |
  210. WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  211. CCS_NODIVIDER | CCS_NOPARENTALIGN |
  212. RBS_VARHEIGHT | RBS_BANDBORDERS,
  213. 0, 0, m_Size.cx, Height, m_Win,
  214. (HMENU)ID_TOOLBAR,
  215. g_hInst, NULL);
  216. if (m_Toolbar == NULL)
  217. {
  218. return FALSE;
  219. }
  220. REBARINFO BarInfo;
  221. BarInfo.cbSize = sizeof(BarInfo);
  222. BarInfo.fMask = 0;
  223. BarInfo.himl = NULL;
  224. SendMessage(m_Toolbar, RB_SETBARINFO, 0, (LPARAM)&BarInfo);
  225. REBARBANDINFO BandInfo;
  226. BandInfo.cbSize = sizeof(BandInfo);
  227. BandInfo.fMask = RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE;
  228. m_ToolbarEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL,
  229. WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL,
  230. 0, 0, 18 *
  231. m_Font->Metrics.tmAveCharWidth,
  232. Height, m_Toolbar, (HMENU)IDC_EDIT_OFFSET,
  233. g_hInst, NULL);
  234. if (m_ToolbarEdit == NULL)
  235. {
  236. return FALSE;
  237. }
  238. SendMessage(m_ToolbarEdit, WM_SETFONT, (WPARAM)m_Font->Font, 0);
  239. SendMessage(m_ToolbarEdit, EM_LIMITTEXT, sizeof(m_OffsetExpr) - 1, 0);
  240. GetClientRect(m_ToolbarEdit, &Rect);
  241. BandInfo.lpText = "Offset:";
  242. BandInfo.hwndChild = m_ToolbarEdit;
  243. BandInfo.cxMinChild = Rect.right - Rect.left;
  244. BandInfo.cyMinChild = Rect.bottom - Rect.top;
  245. SendMessage(m_Toolbar, RB_INSERTBAND, -1, (LPARAM)&BandInfo);
  246. m_FormatCombo = CreateWindowEx(0, "COMBOBOX", NULL,
  247. WS_VISIBLE | WS_CHILD | WS_VSCROLL |
  248. CBS_SORT | CBS_DROPDOWNLIST, 0, 0,
  249. 15 * m_Font->Metrics.tmAveCharWidth,
  250. (g_nMaxNumFormatsMemWin *
  251. m_Font->Metrics.tmHeight / 2),
  252. m_Toolbar, (HMENU)IDC_COMBO_DISPLAY_FORMAT,
  253. g_hInst, NULL);
  254. if (m_FormatCombo == NULL)
  255. {
  256. return FALSE;
  257. }
  258. SendMessage(m_FormatCombo, WM_SETFONT, (WPARAM)m_Font->Font, 0);
  259. for (i = 0; i < g_nMaxNumFormatsMemWin; i++)
  260. {
  261. LRESULT Idx;
  262. // The format strings will be sorted so mark them with
  263. // their true index for retrieval when selected.
  264. Idx = SendMessage(m_FormatCombo, CB_ADDSTRING,
  265. 0, (LPARAM)g_FormatsMemWin[i].lpszDescription);
  266. SendMessage(m_FormatCombo, CB_SETITEMDATA, (WPARAM)Idx, i);
  267. }
  268. GetClientRect(m_FormatCombo, &Rect);
  269. BandInfo.lpText = "Display format:";
  270. BandInfo.hwndChild = m_FormatCombo;
  271. BandInfo.cxMinChild = Rect.right - Rect.left;
  272. BandInfo.cyMinChild = Rect.bottom - Rect.top;
  273. SendMessage(m_Toolbar, RB_INSERTBAND, -1, (LPARAM)&BandInfo);
  274. PSTR PrevText = "Previous";
  275. m_PreviousButton =
  276. AddButtonBand(m_Toolbar, PrevText, PrevText, IDC_MEM_PREVIOUS);
  277. m_NextButton =
  278. AddButtonBand(m_Toolbar, "Next", PrevText, IDC_MEM_NEXT);
  279. if (m_PreviousButton == NULL || m_NextButton == NULL)
  280. {
  281. return FALSE;
  282. }
  283. // Maximize the space for the offset expression.
  284. SendMessage(m_Toolbar, RB_MAXIMIZEBAND, 0, FALSE);
  285. GetClientRect(m_Toolbar, &Rect);
  286. m_ToolbarHeight = Rect.bottom - Rect.top + GetSystemMetrics(SM_CYEDGE);
  287. m_ShowToolbar = TRUE;
  288. if (!EDITWIN_DATA::OnCreate())
  289. {
  290. return FALSE;
  291. }
  292. // Switch background color back to window default as
  293. // this window does not use custom colors.
  294. SendMessage(m_hwndChild, EM_SETBKGNDCOLOR, FALSE,
  295. GetSysColor(COLOR_WINDOW));
  296. SendMessage(m_hwndChild, EM_SETEVENTMASK, 0, ENM_KEYEVENTS);
  297. UpdateOptions();
  298. return TRUE;
  299. }
  300. LRESULT
  301. MEMWIN_DATA::OnCommand(
  302. WPARAM wParam,
  303. LPARAM lParam
  304. )
  305. {
  306. switch(LOWORD(wParam))
  307. {
  308. case IDC_EDIT_OFFSET:
  309. if (HIWORD(wParam) == EN_CHANGE)
  310. {
  311. // This message is sent on every keystroke
  312. // which causes a bit too much updating.
  313. // Set up a timer to trigger the actual
  314. // update in half a second.
  315. SetTimer(m_Win, IDC_EDIT_OFFSET, EDIT_DELAY, NULL);
  316. m_UpdateExpr = TRUE;
  317. }
  318. break;
  319. case IDC_COMBO_DISPLAY_FORMAT:
  320. if (HIWORD(wParam) == CBN_SELCHANGE)
  321. {
  322. LRESULT Sel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
  323. if (Sel != CB_ERR)
  324. {
  325. m_GenMemData.nDisplayFormat = (int)
  326. SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)Sel, 0);
  327. UpdateOptions();
  328. UiRequestRead();
  329. }
  330. }
  331. break;
  332. case IDC_MEM_PREVIOUS:
  333. ScrollLower();
  334. break;
  335. case IDC_MEM_NEXT:
  336. ScrollHigher();
  337. break;
  338. }
  339. return 0;
  340. }
  341. void
  342. MEMWIN_DATA::OnSize(void)
  343. {
  344. EDITWIN_DATA::OnSize();
  345. // Force buffer to refill for new line count.
  346. UiRequestRead();
  347. }
  348. void
  349. MEMWIN_DATA::OnTimer(WPARAM TimerId)
  350. {
  351. char Buffer[MAX_OFFSET_EXPR];
  352. if (TimerId == IDC_EDIT_OFFSET && m_UpdateExpr)
  353. {
  354. m_UpdateExpr = FALSE;
  355. if (SendMessage(m_ToolbarEdit, EM_GETMODIFY, 0,0))
  356. {
  357. GetWindowText(m_ToolbarEdit, m_OffsetExpr, sizeof(m_OffsetExpr));
  358. SendMessage(m_ToolbarEdit, EM_SETMODIFY, 0,0);
  359. UiRequestRead();
  360. }
  361. // KillTimer(m_Win, IDC_EDIT_OFFSET);
  362. }
  363. }
  364. LRESULT
  365. MEMWIN_DATA::OnNotify(WPARAM Wpm, LPARAM Lpm)
  366. {
  367. LPNMHDR Hdr = (LPNMHDR)Lpm;
  368. switch(Hdr->code)
  369. {
  370. case RBN_HEIGHTCHANGE:
  371. PostMessage(m_Win, WU_RECONFIGURE, 0, 0);
  372. break;
  373. case EN_MSGFILTER:
  374. MSGFILTER* Filter = (MSGFILTER*)Lpm;
  375. if (Filter->msg == WM_KEYDOWN)
  376. {
  377. switch(Filter->wParam)
  378. {
  379. case VK_UP:
  380. {
  381. CHARRANGE range;
  382. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM) &range);
  383. if (!SendMessage(m_hwndChild, EM_LINEFROMCHAR,
  384. range.cpMin, 0))
  385. {
  386. // up arrow on top line, scroll
  387. ScrollLower();
  388. return TRUE;
  389. }
  390. break;
  391. }
  392. case VK_DOWN:
  393. {
  394. CHARRANGE range;
  395. int MaxLine;
  396. SendMessage(m_hwndChild, EM_EXGETSEL, 0, (LPARAM) &range);
  397. MaxLine = (int)SendMessage(m_hwndChild, EM_GETLINECOUNT, 0, 0);
  398. if (MaxLine == (1 + SendMessage(m_hwndChild, EM_LINEFROMCHAR,
  399. range.cpMin, 0)))
  400. {
  401. // down arrow on bottom line, scroll
  402. ScrollHigher();
  403. return TRUE;
  404. }
  405. break;
  406. }
  407. case VK_PRIOR:
  408. ScrollLower();
  409. return TRUE;
  410. case VK_NEXT:
  411. ScrollHigher();
  412. return TRUE;
  413. case VK_LEFT: case VK_RIGHT:
  414. break;
  415. case VK_DELETE:
  416. MessageBeep(0);
  417. return TRUE;
  418. default:
  419. // Allow default processing of everything else
  420. return TRUE;
  421. }
  422. }
  423. else if (Filter->msg == WM_KEYUP)
  424. {
  425. return TRUE;
  426. }
  427. if (ES_READONLY & GetWindowLongPtr(m_hwndChild, GWL_STYLE))
  428. {
  429. break;
  430. }
  431. if (Filter->msg == WM_CHAR)
  432. {
  433. switch(Filter->wParam)
  434. {
  435. case '0': case '1': case '2': case '3': case '4':
  436. case '5': case '6': case '7': case '8': case '9':
  437. case 'a': case 'A': case 'b': case 'B': case 'c':
  438. case 'C': case 'd': case 'D': case 'e': case 'E':
  439. case 'f': case 'F':
  440. {
  441. CHARRANGE value;
  442. ULONG charIndex;
  443. ULONG64 Address;
  444. CHAR writeval[2] = {0};
  445. writeval[0] = (CHAR) tolower((CHAR) Filter->wParam);
  446. Address = GetAddressOfCurValue(&charIndex, &value);
  447. if (Address)
  448. {
  449. TEXTRANGE textRange;
  450. SendMessage(m_hwndChild, EM_SETSEL,
  451. charIndex, charIndex+1);
  452. SendMessage(m_hwndChild, EM_REPLACESEL,
  453. FALSE, (LPARAM) &writeval);
  454. textRange.chrg = value;
  455. textRange.lpstrText = &m_ValueExpr[0];
  456. if (SendMessage(m_hwndChild, EM_GETTEXTRANGE,
  457. 0, (LPARAM) &textRange))
  458. {
  459. m_ValueExpr[charIndex - value.cpMin] = writeval[0];
  460. WriteValue(Address);
  461. SendMessage(m_hwndChild, EM_SETSEL,
  462. charIndex+1, charIndex+1);
  463. return TRUE;
  464. }
  465. }
  466. }
  467. default:
  468. MessageBeep(0);
  469. return TRUE;
  470. }
  471. }
  472. break;
  473. }
  474. return EDITWIN_DATA::OnNotify(Wpm, Lpm);
  475. }
  476. void
  477. MEMWIN_DATA::OnUpdate(
  478. UpdateType Type
  479. )
  480. {
  481. if (Type != UPDATE_BUFFER)
  482. {
  483. return;
  484. }
  485. HRESULT Status;
  486. Status = UiLockForRead();
  487. if (Status == S_OK)
  488. {
  489. ULONG charIndex;
  490. SendMessage(m_hwndChild, EM_GETSEL, (WPARAM) &charIndex, NULL);
  491. SendMessage(m_hwndChild, WM_SETREDRAW, FALSE, 0);
  492. CHARRANGE Sel;
  493. // Select everything so it's all replaced.
  494. Sel.cpMin = 0;
  495. Sel.cpMax = -1;
  496. SendMessage(m_hwndChild, EM_EXSETSEL, 0, (LPARAM)&Sel);
  497. TCHAR Buf[64];
  498. TCHAR CharBuf[64];
  499. TCHAR* ColChar;
  500. ULONG Row, Col;
  501. ULONG64 Offset;
  502. ULONG64 DataEnd;
  503. PUCHAR Data;
  504. ULONG Bytes;
  505. _FORMATS_MEM_WIN* Fmt = g_FormatsMemWin + m_GenMemData.nDisplayFormat;
  506. Offset = m_OffsetRead;
  507. Data = (PUCHAR)m_Data;
  508. DataEnd = Offset + m_DataUsed;
  509. Bytes = (Fmt->cBits + 7) / 8;
  510. for (Row = 0; Row < m_LineHeight; Row++)
  511. {
  512. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE,
  513. (LPARAM)FormatAddr64(Offset));
  514. ColChar = CharBuf;
  515. *ColChar++ = ' ';
  516. *ColChar++ = ' ';
  517. for (Col = 0; Col < m_Columns; Col++)
  518. {
  519. if (Offset < DataEnd)
  520. {
  521. _tcscpy(Buf, _T(" "));
  522. // If the formatting succeeds,
  523. // Buf contains the formatted data.
  524. if (!CPFormatMemory(Buf + 1,
  525. (DWORD)min(_tsizeof(Buf) - 1,
  526. Fmt->cchMax + 1),
  527. Data,
  528. Fmt->cBits,
  529. Fmt->fmtType,
  530. Fmt->radix))
  531. {
  532. // Else we don't know what to format
  533. for (UINT uTmp = 0; uTmp < Bytes; uTmp++)
  534. {
  535. m_AllowWrite = FALSE;
  536. _tcscat(Buf + 1, _T("??"));
  537. }
  538. }
  539. if (Fmt->fTwoFields)
  540. {
  541. if (!CPFormatMemory(ColChar, 1, Data, 8,
  542. fmtAscii, 0))
  543. {
  544. *ColChar = '?';
  545. }
  546. ColChar++;
  547. }
  548. }
  549. else
  550. {
  551. m_AllowWrite = FALSE;
  552. _tcscpy(Buf, _T(" ????????"));
  553. *ColChar++ = '?';
  554. }
  555. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)Buf);
  556. Data += Bytes;
  557. Offset += Bytes;
  558. }
  559. if (Fmt->fTwoFields)
  560. {
  561. *ColChar = 0;
  562. SendMessage(m_hwndChild, EM_REPLACESEL,
  563. FALSE, (LPARAM)CharBuf);
  564. }
  565. // Don't complete the last line to avoid leaving
  566. // a blank line at the bottom.
  567. if (Row < m_LineHeight - 1)
  568. {
  569. SendMessage(m_hwndChild, EM_REPLACESEL, FALSE, (LPARAM)"\n");
  570. }
  571. }
  572. m_WindowDataSize = (ULONG)(Offset - m_OffsetRead);
  573. UnlockStateBuffer(this);
  574. SendMessage(m_hwndChild, WM_SETREDRAW, TRUE, 0);
  575. InvalidateRect(m_hwndChild, NULL, TRUE);
  576. SendMessage(m_hwndChild, EM_SETSEL, charIndex, charIndex);
  577. }
  578. else
  579. {
  580. SendLockStatusMessage(m_hwndChild, WM_SETTEXT, Status);
  581. }
  582. }
  583. void
  584. MEMWIN_DATA::UpdateColors(void)
  585. {
  586. // Do not change colors.
  587. }
  588. void
  589. MEMWIN_DATA::ScrollLower(void)
  590. {
  591. ULONG64 Offs = m_OffsetRead;
  592. if (Offs >= m_WindowDataSize)
  593. {
  594. Offs -= m_WindowDataSize;
  595. }
  596. else
  597. {
  598. Offs = 0;
  599. }
  600. sprintf(m_OffsetExpr, "0x%I64x", Offs);
  601. UiRequestRead();
  602. }
  603. void
  604. MEMWIN_DATA::ScrollHigher(void)
  605. {
  606. ULONG64 Offs = m_OffsetRead;
  607. if (Offs + m_WindowDataSize > Offs)
  608. {
  609. Offs += m_WindowDataSize;
  610. }
  611. else
  612. {
  613. Offs = (ULONG64)-1 - m_WindowDataSize;
  614. }
  615. sprintf(m_OffsetExpr, "0x%I64x", Offs);
  616. UiRequestRead();
  617. }
  618. void
  619. MEMWIN_DATA::UpdateOptions(void)
  620. {
  621. REBARBANDINFO BandInfo;
  622. BandInfo.cbSize = sizeof(BandInfo);
  623. BandInfo.fMask = RBBIM_TEXT;
  624. BandInfo.lpText = g_MemTypeNames[m_GenMemData.memtype];
  625. SendMessage(m_Toolbar, RB_SETBANDINFO, 0, (LPARAM)&BandInfo);
  626. SetWindowText(m_ToolbarEdit, m_OffsetExpr);
  627. m_AllowWrite = (m_GenMemData.memtype == PHYSICAL_MEM_TYPE ||
  628. m_GenMemData.memtype == VIRTUAL_MEM_TYPE) &&
  629. ((g_FormatsMemWin[m_GenMemData.nDisplayFormat].fmtType & fmtBasis) == fmtUInt ||
  630. (g_FormatsMemWin[m_GenMemData.nDisplayFormat].fmtType & fmtBasis) == fmtInt ||
  631. (g_FormatsMemWin[m_GenMemData.nDisplayFormat].fmtType & fmtBasis) == fmtAddress
  632. ) &&
  633. g_FormatsMemWin[m_GenMemData.nDisplayFormat].radix == 16;
  634. SendMessage(m_hwndChild, EM_SETREADONLY, !m_AllowWrite, 0);
  635. for (LONG Idx = 0; Idx < g_nMaxNumFormatsMemWin; Idx++)
  636. {
  637. if ((LONG)SendMessage(m_FormatCombo, CB_GETITEMDATA, Idx, 0) ==
  638. m_GenMemData.nDisplayFormat)
  639. {
  640. SendMessage(m_FormatCombo, CB_SETCURSEL, Idx, 0);
  641. break;
  642. }
  643. }
  644. switch(m_GenMemData.memtype)
  645. {
  646. case MSR_MEM_TYPE:
  647. m_Columns = 1;
  648. break;
  649. default:
  650. if ((g_FormatsMemWin[m_GenMemData.nDisplayFormat].fmtType &
  651. fmtBasis) == fmtAscii ||
  652. (g_FormatsMemWin[m_GenMemData.nDisplayFormat].fmtType &
  653. fmtBasis) == fmtUnicode ||
  654. g_FormatsMemWin[m_GenMemData.nDisplayFormat].cBits == 8)
  655. {
  656. m_Columns = 16;
  657. }
  658. else if (g_FormatsMemWin[m_GenMemData.nDisplayFormat].cBits == 16)
  659. {
  660. m_Columns = 8;
  661. }
  662. else if (g_FormatsMemWin[m_GenMemData.nDisplayFormat].cBits > 64)
  663. {
  664. m_Columns = 2;
  665. }
  666. else
  667. {
  668. m_Columns = 4;
  669. }
  670. break;
  671. }
  672. }
  673. void
  674. MEMWIN_DATA::WriteValue(
  675. ULONG64 Offset
  676. )
  677. {
  678. if (!m_AllowWrite)
  679. {
  680. return;
  681. }
  682. ULONG64 Data;
  683. ULONG Size;
  684. DEBUG_VALUE Value;
  685. // Evaluate value expression.
  686. if (g_pDbgControl->Evaluate(m_ValueExpr, DEBUG_VALUE_INT64,
  687. &Value, NULL) != S_OK)
  688. {
  689. return;
  690. }
  691. Data = Value.I64;
  692. Size = g_FormatsMemWin[m_GenMemData.nDisplayFormat].cBits / 8;
  693. UIC_WRITE_DATA_DATA* WriteData;
  694. WriteData = StartStructCommand(UIC_WRITE_DATA);
  695. if (WriteData == NULL)
  696. {
  697. return;
  698. }
  699. // Fill in WriteData members.
  700. memcpy(WriteData->Data, &Data, Size);
  701. WriteData->Length = Size;
  702. WriteData->Offset = Offset;
  703. WriteData->Type = m_GenMemData.memtype;
  704. WriteData->Any = m_GenMemData.any;
  705. FinishCommand();
  706. }
  707. ULONG64
  708. MEMWIN_DATA::GetAddressOfCurValue(
  709. PULONG pCharIndex,
  710. CHARRANGE *pCRange
  711. )
  712. {
  713. CHARRANGE range;
  714. ULONG CurLine, FirstLineChar, CurCol;
  715. SendMessage(m_hwndChild, EM_EXGETSEL, NULL, (LPARAM) &range);
  716. CurLine = (ULONG)SendMessage(m_hwndChild, EM_LINEFROMCHAR, range.cpMin, 0);
  717. FirstLineChar = (ULONG)SendMessage(m_hwndChild, EM_LINEINDEX, CurLine, 0);
  718. CurCol = range.cpMin - FirstLineChar;
  719. ULONG Length;
  720. PCHAR pLineTxt = (PCHAR)
  721. malloc(Length = ((ULONG)SendMessage(m_hwndChild, EM_LINELENGTH,
  722. FirstLineChar, 0) + 2));
  723. if (!pLineTxt)
  724. {
  725. return 0;
  726. }
  727. Assert(Length >= CurCol);
  728. ZeroMemory(pLineTxt, Length);
  729. // Assert (Length = (ULONG) SendMessage(m_hwndChild, EM_GETLINE, (WPARAM) CurLine, (LPARAM) pLineTxt));
  730. TEXTRANGE textrange;
  731. textrange.chrg.cpMin = FirstLineChar;
  732. textrange.chrg.cpMax = FirstLineChar + Length-2;
  733. textrange.lpstrText = (LPSTR) pLineTxt;
  734. SendMessage(m_hwndChild, EM_GETTEXTRANGE, 0, (LPARAM) &textrange);
  735. ULONG ValueCol=0, Index=0, ValueIndex=0;
  736. while (pLineTxt[CurCol] == ' ')
  737. {
  738. CurCol++;
  739. }
  740. while (Index < CurCol)
  741. {
  742. if (pLineTxt[Index] == ' ')
  743. {
  744. if (ValueIndex != Index)
  745. {
  746. ValueCol++;
  747. }
  748. ValueIndex = Index+1;
  749. }
  750. ++Index;
  751. }
  752. if (!ValueIndex || !pLineTxt[CurCol]) // cursor on address column
  753. {
  754. free (pLineTxt);
  755. return 0;
  756. }
  757. ULONG Bytes;
  758. Bytes = (g_FormatsMemWin[m_GenMemData.nDisplayFormat].cBits + 7) / 8;
  759. ULONG64 Offset;
  760. Offset = m_OffsetRead + (CurLine * Bytes * m_Columns) + (ValueCol - 1)*Bytes;
  761. for (Index = ValueIndex; pLineTxt[Index] && pLineTxt[Index] != ' '; Index++) ;
  762. memcpy(m_ValueExpr, pLineTxt+ValueIndex, Index - ValueIndex);
  763. m_ValueExpr[Index-ValueIndex]=0;
  764. free (pLineTxt);
  765. if (pCharIndex)
  766. {
  767. *pCharIndex = FirstLineChar + CurCol;
  768. }
  769. if (pCRange)
  770. {
  771. pCRange->cpMin = FirstLineChar + CurCol - (CurCol - ValueIndex);
  772. pCRange->cpMax = pCRange->cpMin + Index - ValueIndex;
  773. }
  774. return Offset;
  775. }