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.

625 lines
14 KiB

  1. #pragma warning(disable:4135)
  2. #include <afxwin.h>
  3. #include <afxdlgs.h>
  4. #pragma warning(default:4135)
  5. #include <process.h>
  6. #include "resource.h"
  7. #define _DBWIN32_
  8. #include "dbwin32.h"
  9. char szCompany[] = "Microsoft";
  10. char szApplication[] = "DbWin32";
  11. char szIniSection1[] = "Window";
  12. char szIniSection2[] = "Options";
  13. char szKey1[] = "X";
  14. char szKey2[] = "Y";
  15. char szKey3[] = "Width";
  16. char szKey4[] = "Height";
  17. char szKey5[] = "State";
  18. char szKey6[] = "OnTop";
  19. char szKey7[] = "ChildMaximized";
  20. char szKey8[] = "InactiveWindows";
  21. char szKey9[] = "NewWindowOnProcess";
  22. char szKey10[] = "NewWindowOnThread";
  23. char szKey11[] = "EventFilter";
  24. char *rgpszHistoryKeys[MAX_HISTORY] = {"LastCommandLine1", "LastCommandLine2",
  25. "LastCommandLine3", "LastCommandLine4", "LastCommandLine5"};
  26. GrowableList::GrowableList(int cbSizeIn)
  27. {
  28. cbSize = cbSizeIn;
  29. cItemsCur = 0;
  30. cItemsMax = INITIAL_LIST_SIZE;
  31. pvData = malloc(cbSize * INITIAL_LIST_SIZE);
  32. }
  33. GrowableList::~GrowableList()
  34. {
  35. free(pvData);
  36. }
  37. int GrowableList::Count()
  38. {
  39. return(cItemsCur);
  40. }
  41. BOOL GrowableList::FindItem(void *pvItem, int *piFound)
  42. {
  43. int iItem;
  44. BYTE *pbItem;
  45. for (iItem = 0, pbItem = (BYTE *)pvData; ((iItem < cItemsCur) &&
  46. !IsEqual(pvItem, pbItem)); iItem++, pbItem += cbSize);
  47. if (iItem == cItemsCur)
  48. return(FALSE);
  49. memcpy(pvItem, pbItem, cbSize);
  50. if (piFound)
  51. *piFound = iItem;
  52. return(TRUE);
  53. }
  54. void GrowableList::GetItem(int iItem, void *pvItem)
  55. {
  56. BYTE *pbItem = (BYTE *)pvData;
  57. pbItem += (cbSize * iItem);
  58. memcpy(pvItem, pbItem, cbSize);
  59. }
  60. void GrowableList::InsertItem(void *pvItem)
  61. {
  62. void *pvNew;
  63. BYTE *pbNew;
  64. if (!FindItem(pvItem))
  65. {
  66. if (cItemsCur == cItemsMax)
  67. {
  68. cItemsMax += LIST_CHUNK_SIZE;
  69. pvNew = malloc(cbSize * cItemsMax);
  70. if (!pvNew)
  71. {
  72. return;
  73. }
  74. memcpy(pvNew, pvData, (cbSize * (cItemsMax - LIST_CHUNK_SIZE)));
  75. free(pvData);
  76. pvData = pvNew;
  77. }
  78. pbNew = (BYTE *)pvData;
  79. pbNew += (cbSize * cItemsCur);
  80. cItemsCur++;
  81. memcpy(pbNew, pvItem, cbSize);
  82. }
  83. }
  84. void GrowableList::RemoveItem(void *pvItem)
  85. {
  86. int iItem;
  87. if (FindItem(pvItem, &iItem))
  88. RemoveItem(iItem);
  89. }
  90. void GrowableList::RemoveItem(int iItem)
  91. {
  92. BYTE *pbSrc, *pbDest;
  93. if (iItem != (cItemsCur - 1))
  94. {
  95. pbDest = (BYTE *)pvData;
  96. pbDest += (cbSize * iItem);
  97. pbSrc = pbDest + cbSize;
  98. memmove(pbDest, pbSrc, (cbSize * (cItemsCur - iItem - 1)));
  99. }
  100. cItemsCur--;
  101. }
  102. WindowList::WindowList() : GrowableList(sizeof(WindowInfo))
  103. {
  104. }
  105. WindowList::~WindowList()
  106. {
  107. }
  108. BOOL WindowList::IsEqual(void *pv1, void *pv2)
  109. {
  110. return(!memcmp(pv1, pv2, (2 * sizeof(DWORD))));
  111. }
  112. DbWin32App::DbWin32App()
  113. {
  114. }
  115. DbWin32App::~DbWin32App()
  116. {
  117. }
  118. BOOL DbWin32App::InitInstance()
  119. {
  120. if (!CWinApp::InitInstance())
  121. return(FALSE);
  122. SetRegistryKey(szCompany);
  123. m_pszProfileName = szApplication;
  124. Enable3dControls();
  125. m_pMainWnd = new DbWin32Frame(&dbo);
  126. ((DbWin32Frame *)m_pMainWnd)->LoadFrame(IDR_MAIN, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
  127. if (m_lpCmdLine && *m_lpCmdLine)
  128. ((DbWin32Frame *)m_pMainWnd)->ExecProcess(m_lpCmdLine);
  129. else
  130. ((DbWin32Frame *)m_pMainWnd)->FileSystem();
  131. return(TRUE);
  132. }
  133. void DbWin32App::ReadOptions()
  134. {
  135. int wMaxWidth, wMaxHeight, iKey;
  136. wMaxWidth = GetSystemMetrics(SM_CXSCREEN);
  137. wMaxHeight = GetSystemMetrics(SM_CYSCREEN);
  138. dbo.rcWindow.left = GetProfileInt(szIniSection1, szKey1, wMaxWidth/5);
  139. dbo.rcWindow.top = GetProfileInt(szIniSection1, szKey2, wMaxHeight/5);
  140. dbo.rcWindow.right = GetProfileInt(szIniSection1, szKey3, wMaxWidth/2)-1;
  141. dbo.rcWindow.bottom = GetProfileInt(szIniSection1, szKey4, wMaxHeight/2)-1;
  142. if (dbo.rcWindow.right < 0)
  143. dbo.rcWindow.right = wMaxWidth/2;
  144. if (dbo.rcWindow.bottom < 0)
  145. dbo.rcWindow.bottom = wMaxHeight/2;
  146. if (dbo.rcWindow.left < 0 || dbo.rcWindow.left > wMaxWidth)
  147. dbo.rcWindow.left = wMaxWidth/5;
  148. dbo.rcWindow.right += dbo.rcWindow.left;
  149. if (dbo.rcWindow.right > wMaxWidth)
  150. dbo.rcWindow.right = wMaxWidth;
  151. if (dbo.rcWindow.top < 0 || dbo.rcWindow.top > wMaxHeight)
  152. dbo.rcWindow.top = wMaxHeight /5;
  153. dbo.rcWindow.bottom += dbo.rcWindow.top;
  154. if (dbo.rcWindow.bottom > wMaxHeight)
  155. dbo.rcWindow.bottom = wMaxHeight;
  156. dbo.nShowCmd = GetProfileInt(szIniSection1, szKey5, 0);
  157. if (dbo.nShowCmd < 0)
  158. dbo.nShowCmd = WS_MINIMIZE;
  159. else if (dbo.nShowCmd > 0)
  160. dbo.nShowCmd = WS_MAXIMIZE;
  161. dbo.fOnTop = GetProfileInt(szIniSection1, szKey6, FALSE);
  162. dbo.fChildMax = GetProfileInt(szIniSection1, szKey7, FALSE);
  163. dbo.nInactive = GetProfileInt(szIniSection2, szKey8, INACTIVE_MINIMIZE);
  164. dbo.fNewOnProcess = GetProfileInt(szIniSection2, szKey9, TRUE);
  165. dbo.fNewOnThread = GetProfileInt(szIniSection2, szKey10, FALSE);
  166. dbo.wFilter = (WORD)GetProfileInt(szIniSection2, szKey11, DBO_ALL);
  167. for (iKey = 0; iKey < MAX_HISTORY; iKey++)
  168. dbo.rgstCommandLine[iKey] = GetProfileString(szIniSection2,
  169. rgpszHistoryKeys[iKey]);
  170. }
  171. void DbWin32App::WriteOptions(WINDOWPLACEMENT *pwpl)
  172. {
  173. int wState, iKey;
  174. if (pwpl)
  175. {
  176. if (pwpl->showCmd == SW_SHOWMAXIMIZED)
  177. wState = 1;
  178. else if (pwpl->showCmd == SW_SHOWMINIMIZED)
  179. wState = -1;
  180. else
  181. wState = 0;
  182. WriteProfileInt(szIniSection1, szKey1, (int) pwpl->rcNormalPosition.left);
  183. WriteProfileInt(szIniSection1, szKey2, (int) pwpl->rcNormalPosition.top);
  184. WriteProfileInt(szIniSection1, szKey3,
  185. pwpl->rcNormalPosition.right-pwpl->rcNormalPosition.left+1);
  186. WriteProfileInt(szIniSection1, szKey4,
  187. pwpl->rcNormalPosition.bottom-pwpl->rcNormalPosition.top+1);
  188. WriteProfileInt(szIniSection1, szKey5, wState);
  189. }
  190. WriteProfileInt(szIniSection1, szKey6, dbo.fOnTop);
  191. WriteProfileInt(szIniSection1, szKey7, dbo.fChildMax);
  192. WriteProfileInt(szIniSection2, szKey8, dbo.nInactive);
  193. WriteProfileInt(szIniSection2, szKey9, dbo.fNewOnProcess);
  194. WriteProfileInt(szIniSection2, szKey10, dbo.fNewOnThread);
  195. WriteProfileInt(szIniSection2, szKey11, dbo.wFilter);
  196. for (iKey = 0; iKey < MAX_HISTORY; iKey++)
  197. WriteProfileString(szIniSection2, rgpszHistoryKeys[iKey],
  198. dbo.rgstCommandLine[iKey]);
  199. }
  200. static NEAR DbWin32App theApp;
  201. DbWin32Edit::DbWin32Edit()
  202. {
  203. }
  204. DbWin32Edit::~DbWin32Edit()
  205. {
  206. }
  207. BOOL DbWin32Edit::Create(CWnd *pwndParent)
  208. {
  209. CRect rc;
  210. return(CEdit::Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL |
  211. WS_HSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE,
  212. rc, pwndParent, 100));
  213. }
  214. BEGIN_MESSAGE_MAP(DbWin32Child, CMDIChildWnd)
  215. // Windows messages
  216. ON_WM_CREATE()
  217. ON_WM_SIZE()
  218. ON_WM_MDIACTIVATE()
  219. ON_WM_NCACTIVATE()
  220. // Command handlers
  221. ON_COMMAND(CMD_FILESAVEBUFFER, OnFileSaveBuffer)
  222. ON_COMMAND(CMD_EDITCOPY, OnEditCopy)
  223. ON_COMMAND(CMD_EDITCLEARBUFFER, OnEditClearBuffer)
  224. ON_COMMAND(CMD_EDITSELECTALL, OnEditSelectAll)
  225. // Idle update handlers
  226. // Notification messages
  227. ON_EN_MAXTEXT(100, OnMaxText)
  228. END_MESSAGE_MAP()
  229. DbWin32Child::DbWin32Child(WORD wFilterIn)
  230. {
  231. wFilter = wFilterIn;
  232. }
  233. DbWin32Child::~DbWin32Child()
  234. {
  235. }
  236. void DbWin32Child::AddText(WORD wEvent, LPCSTR lpszText, int cLines, BOOL fSetTitle)
  237. {
  238. int cLinesNew;
  239. CString st;
  240. if (!m_hWnd)
  241. return;
  242. if (fSetTitle && !strncmp(lpszText, "Create Process", 14))
  243. {
  244. st = lpszText;
  245. SetWindowText(st.Mid(16, st.GetLength() - 18));
  246. }
  247. if (fSetTitle && !strncmp(lpszText, "Create Thread", 13))
  248. {
  249. st = lpszText;
  250. SetWindowText(st.Mid(15, st.GetLength() - 17));
  251. }
  252. if (wEvent & wFilter)
  253. {
  254. cLinesNew = wndEdit.GetLineCount() + cLines;
  255. if (cLinesNew > MAX_LINES)
  256. {
  257. wndEdit.SetSel(0, wndEdit.LineIndex(cLinesNew + 50 - MAX_LINES), TRUE);
  258. wndEdit.ReplaceSel("");
  259. }
  260. wndEdit.SetSel(0x7FFF7FFF);
  261. wndEdit.ReplaceSel(lpszText);
  262. wndEdit.SetSel(0x7FFF7FFF);
  263. }
  264. }
  265. int DbWin32Child::OnCreate(LPCREATESTRUCT lpcs)
  266. {
  267. LOGFONT lf;
  268. if (CMDIChildWnd::OnCreate(lpcs) == -1)
  269. return(-1);
  270. m_hMenuShared = ::LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_CHILD));
  271. wndEdit.Create(this);
  272. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  273. fontCur.CreateFontIndirect(&lf);
  274. wndEdit.SetFont(&fontCur);
  275. wndEdit.ShowWindow(SW_SHOWNORMAL);
  276. return(0);
  277. }
  278. void DbWin32Child::OnSize(UINT nType, int cx, int cy)
  279. {
  280. CRect rc;
  281. ((DbWin32Frame *)GetMDIFrame())->ChildMaximized(nType == SIZE_MAXIMIZED);
  282. GetClientRect(rc);
  283. rc.InflateRect(1, 1);
  284. wndEdit.MoveWindow(rc, TRUE);
  285. CMDIChildWnd::OnSize(nType, cx, cy);
  286. }
  287. void DbWin32Child::OnMDIActivate(BOOL fActivate, CWnd *pwndActivate, CWnd *pwndDeactivate)
  288. {
  289. if (fActivate)
  290. wndEdit.SetFocus();
  291. CMDIChildWnd::OnMDIActivate(fActivate, pwndActivate, pwndDeactivate);
  292. }
  293. BOOL DbWin32Child::OnNcActivate(BOOL fActivate)
  294. {
  295. if (fActivate)
  296. wndEdit.SetFocus();
  297. return(CMDIChildWnd::OnNcActivate(fActivate));
  298. }
  299. void DbWin32Child::OnFileSaveBuffer()
  300. {
  301. CFile file;
  302. int cch;
  303. void *pv;
  304. CFileDialog dlgFile(FALSE, NULL, NULL, OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
  305. OFN_PATHMUSTEXIST, "All|*.*||", GetMDIFrame());
  306. if (dlgFile.DoModal() == IDOK)
  307. if (file.Open(dlgFile.GetPathName(), CFile::modeCreate | CFile::modeWrite))
  308. {
  309. cch = wndEdit.GetWindowTextLength();
  310. if (cch)
  311. {
  312. pv = GlobalAlloc(GMEM_FIXED, cch + 1);
  313. if (pv)
  314. {
  315. cch = wndEdit.GetWindowText((LPTSTR)pv, cch + 1);
  316. file.Write(pv, cch);
  317. file.Close();
  318. GlobalFree(pv);
  319. }
  320. }
  321. }
  322. }
  323. void DbWin32Child::OnEditCopy()
  324. {
  325. wndEdit.Copy();
  326. }
  327. void DbWin32Child::OnEditClearBuffer()
  328. {
  329. OnEditSelectAll();
  330. wndEdit.ReplaceSel("");
  331. }
  332. void DbWin32Child::OnEditSelectAll()
  333. {
  334. wndEdit.SetSel(0, -1, FALSE);
  335. }
  336. void DbWin32Child::OnMaxText()
  337. {
  338. MessageBox("Help! I'm out of space!", "DbWin32", MB_ICONEXCLAMATION | MB_OK);
  339. }
  340. BEGIN_MESSAGE_MAP(DbWin32Frame, CMDIFrameWnd)
  341. // Windows messages
  342. ON_WM_DESTROY()
  343. ON_MESSAGE(WM_SENDTEXT, OnSendText)
  344. ON_MESSAGE(WM_ENDTHREAD, OnEndThread)
  345. // Command handlers
  346. ON_COMMAND(CMD_FILERUN, OnFileRun)
  347. ON_COMMAND(CMD_FILEATTACH, OnFileAttach)
  348. ON_COMMAND(CMD_FILESYSTEM, OnFileSystem)
  349. ON_COMMAND(CMD_FILEEXIT, OnFileExit)
  350. ON_COMMAND(CMD_OPTIONS, OnOptions)
  351. ON_COMMAND(CMD_ABOUT, OnAbout)
  352. // Idle update handlers
  353. ON_UPDATE_COMMAND_UI(CMD_FILESYSTEM, OnUpdateFileSystem)
  354. END_MESSAGE_MAP()
  355. DbWin32Frame::DbWin32Frame(DbWin32Options *pdboIn)
  356. {
  357. OSVERSIONINFO osvi;
  358. pwndSystem = NULL;
  359. pdbo = pdboIn;
  360. fInCreate = FALSE;
  361. fNT351 = FALSE;
  362. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  363. if (GetVersionEx(&osvi))
  364. {
  365. if ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && ((osvi.dwMajorVersion > 3) || (osvi.dwMinorVersion > 5)))
  366. fNT351 = TRUE;
  367. }
  368. }
  369. DbWin32Frame::~DbWin32Frame()
  370. {
  371. }
  372. void DbWin32Frame::ExecProcess(LPCSTR lpszCommandLine)
  373. {
  374. int iKey;
  375. ExecInfo *pei;
  376. for (iKey = 0; iKey < MAX_HISTORY; iKey++)
  377. if (pdbo->rgstCommandLine[iKey] == lpszCommandLine)
  378. break;
  379. if (iKey == MAX_HISTORY)
  380. {
  381. for (iKey = MAX_HISTORY - 1; iKey > 0; iKey--)
  382. pdbo->rgstCommandLine[iKey] = pdbo->rgstCommandLine[iKey-1];
  383. pdbo->rgstCommandLine[0] = lpszCommandLine;
  384. }
  385. pei = new ExecInfo;
  386. pei->lpszCommandLine = _strdup(lpszCommandLine);
  387. pei->hwndFrame = GetSafeHwnd();
  388. _beginthread(ExecThread, 0, pei);
  389. }
  390. void DbWin32Frame::ChildMaximized(BOOL fMax)
  391. {
  392. if (!fInCreate)
  393. pdbo->fChildMax = fMax;
  394. }
  395. void DbWin32Frame::FileSystem()
  396. {
  397. if (fNT351)
  398. OnFileSystem();
  399. }
  400. BOOL DbWin32Frame::PreCreateWindow(CREATESTRUCT &cs)
  401. {
  402. ((DbWin32App *)AfxGetApp())->ReadOptions();
  403. cs.cy = (int)(pdbo->rcWindow.bottom - pdbo->rcWindow.top);
  404. cs.cx = (int)(pdbo->rcWindow.right - pdbo->rcWindow.left);
  405. cs.y = (int)pdbo->rcWindow.top;
  406. cs.x = (int)pdbo->rcWindow.left;
  407. cs.style |= pdbo->nShowCmd;
  408. if (pdbo->fOnTop)
  409. cs.dwExStyle |= WS_EX_TOPMOST;
  410. return(CMDIFrameWnd::PreCreateWindow(cs));
  411. }
  412. void DbWin32Frame::OnDestroy()
  413. {
  414. WINDOWPLACEMENT wpl;
  415. wpl.length = sizeof(WINDOWPLACEMENT);
  416. wpl.rcNormalPosition.top = wpl.rcNormalPosition.left = 0;
  417. if (GetWindowPlacement(&wpl))
  418. ((DbWin32App *)AfxGetApp())->WriteOptions(&wpl);
  419. else
  420. ((DbWin32App *)AfxGetApp())->WriteOptions(NULL);
  421. }
  422. LRESULT DbWin32Frame::OnSendText(WPARAM wParam, LPARAM lParam)
  423. {
  424. StringInfo *psi = (StringInfo *)lParam;
  425. WindowInfo wi;
  426. BOOL fCreated = FALSE;
  427. wi.dwProcess = psi->dwProcess;
  428. wi.dwThread = psi->dwThread;
  429. if (!wi.dwProcess && !wi.dwThread)
  430. wi.pwndChild = pwndSystem;
  431. else
  432. {
  433. wi.pwndChild = NULL;
  434. if (!wl.FindItem(&wi))
  435. if (pdbo->fNewOnThread)
  436. fCreated = TRUE;
  437. else
  438. {
  439. wi.dwThread = 0;
  440. if (!wl.FindItem(&wi))
  441. if (pdbo->fNewOnProcess)
  442. fCreated = TRUE;
  443. else
  444. {
  445. wi.dwProcess = psi->dwParentProcess;
  446. if (!wl.FindItem(&wi))
  447. fCreated = TRUE;
  448. }
  449. }
  450. if (fCreated)
  451. {
  452. wi.pwndChild = new DbWin32Child(pdbo->wFilter);
  453. fInCreate = TRUE;
  454. wi.pwndChild->LoadFrame(IDR_CHILD,
  455. WS_OVERLAPPEDWINDOW | WS_VISIBLE, this);
  456. fInCreate = FALSE;
  457. if (pdbo->fChildMax)
  458. MDIMaximize(wi.pwndChild);
  459. wl.InsertItem(&wi);
  460. }
  461. }
  462. ASSERT(wi.pwndChild);
  463. wi.pwndChild->AddText((WORD)wParam, psi->lpszText, psi->cLines, fCreated);
  464. free((void *)(psi->lpszText));
  465. delete psi;
  466. return(0);
  467. }
  468. LRESULT DbWin32Frame::OnEndThread(WPARAM wParam, LPARAM lParam)
  469. {
  470. CString st;
  471. WindowInfo wi;
  472. int iItem;
  473. wi.dwProcess = (DWORD)lParam;
  474. wi.dwThread = (DWORD)wParam;
  475. if (wl.FindItem(&wi, &iItem))
  476. {
  477. wi.pwndChild->GetWindowText(st);
  478. st += " [Inactive]";
  479. wi.pwndChild->SetWindowText(st);
  480. switch (pdbo->nInactive)
  481. {
  482. case INACTIVE_CLOSE:
  483. wi.pwndChild->MDIDestroy();
  484. break;
  485. case INACTIVE_NONE:
  486. break;
  487. default:
  488. wi.pwndChild->ShowWindow(SW_MINIMIZE);
  489. break;
  490. }
  491. wl.RemoveItem(iItem);
  492. }
  493. return(0L);
  494. }
  495. void DbWin32Frame::OnFileRun()
  496. {
  497. DbWin32RunDlg dlgRun(pdbo->rgstCommandLine);
  498. if (dlgRun.DoModal() == IDOK)
  499. ExecProcess(dlgRun.GetCommandLine());
  500. }
  501. void DbWin32Frame::OnFileAttach()
  502. {
  503. AttachInfo *pai;
  504. DbWin32AttachDlg dlgAttach(&wl);
  505. if (dlgAttach.DoModal() == IDOK)
  506. {
  507. pai = new AttachInfo;
  508. pai->dwProcess = dlgAttach.GetSelectedProcess();
  509. pai->hwndFrame = GetSafeHwnd();
  510. _beginthread(AttachThread, 0, pai);
  511. }
  512. }
  513. void DbWin32Frame::OnFileSystem()
  514. {
  515. if (!fNT351)
  516. {
  517. MessageBeep(MB_ICONEXCLAMATION);
  518. MessageBox("Not available on this platform.", "DbWin32",
  519. MB_ICONEXCLAMATION | MB_OK);
  520. return;
  521. }
  522. if (pwndSystem)
  523. {
  524. MDIActivate(pwndSystem);
  525. return;
  526. }
  527. pwndSystem = new DbWin32Child(DBO_OUTPUTDEBUGSTRING);
  528. fInCreate = TRUE;
  529. pwndSystem->LoadFrame(IDR_CHILD, WS_OVERLAPPEDWINDOW | WS_VISIBLE, this);
  530. fInCreate = FALSE;
  531. pwndSystem->SetWindowText("System Window");
  532. if (pdbo->fChildMax)
  533. MDIMaximize(pwndSystem);
  534. _beginthread(SystemThread, 0, GetSafeHwnd());
  535. }
  536. void DbWin32Frame::OnFileExit()
  537. {
  538. OnClose();
  539. }
  540. void DbWin32Frame::OnOptions()
  541. {
  542. DbWin32OptionsDlg dlgOptions(pdbo);
  543. dlgOptions.DoModal();
  544. }
  545. void DbWin32Frame::OnAbout()
  546. {
  547. CDialog dlgAbout(IDR_ABOUTDLG);
  548. dlgAbout.DoModal();
  549. }
  550. void DbWin32Frame::OnUpdateFileSystem(CCmdUI *pCmdUI)
  551. {
  552. pCmdUI->Enable(!pwndSystem && fNT351);
  553. }