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.

1181 lines
26 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. Func.cpp
  5. Abstract:
  6. Misc. functions used throughout the application
  7. Notes:
  8. ANSI only - must run on Win9x.
  9. History:
  10. 01/30/01 rparsons Created
  11. 01/10/02 rparsons Revised
  12. --*/
  13. #include "demoapp.h"
  14. extern APPINFO g_ai;
  15. /*++
  16. Routine Description:
  17. Loads the contents of our 'readme' into the edit box.
  18. Arguments:
  19. None.
  20. Return Value:
  21. None.
  22. --*/
  23. void
  24. LoadFileIntoEditBox(
  25. void
  26. )
  27. {
  28. HRESULT hr;
  29. HANDLE hFile;
  30. DWORD dwFileSize;
  31. DWORD cbBytesRead;
  32. char szTextFile[MAX_PATH];
  33. char* pszBuffer = NULL;
  34. //
  35. // Set up a path to our file and load it.
  36. //
  37. hr = StringCchPrintf(szTextFile,
  38. sizeof(szTextFile),
  39. "%hs\\demoapp.txt",
  40. g_ai.szCurrentDir);
  41. if (FAILED(hr)) {
  42. return;
  43. }
  44. hFile = CreateFile(szTextFile,
  45. GENERIC_READ,
  46. FILE_SHARE_READ,
  47. NULL,
  48. OPEN_EXISTING,
  49. FILE_ATTRIBUTE_NORMAL,
  50. NULL);
  51. if (INVALID_HANDLE_VALUE == hFile) {
  52. return;
  53. }
  54. dwFileSize = GetFileSize(hFile, 0);
  55. if (0 == dwFileSize) {
  56. goto exit;
  57. }
  58. pszBuffer = (char*)HeapAlloc(GetProcessHeap(),
  59. HEAP_ZERO_MEMORY,
  60. ++dwFileSize);
  61. if (!pszBuffer) {
  62. goto exit;
  63. }
  64. if (!ReadFile(hFile, (LPVOID)pszBuffer, dwFileSize, &cbBytesRead, NULL)) {
  65. goto exit;
  66. }
  67. SetWindowText(g_ai.hWndEdit, pszBuffer);
  68. exit:
  69. CloseHandle(hFile);
  70. if (pszBuffer) {
  71. HeapFree(GetProcessHeap(), 0, pszBuffer);
  72. }
  73. }
  74. /*++
  75. Routine Description:
  76. Centers the specified window.
  77. Arguments:
  78. hWnd - Window to center.
  79. Return Value:
  80. TRUE on success, FALSE otherwise.
  81. --*/
  82. BOOL
  83. CenterWindow(
  84. IN HWND hWnd
  85. )
  86. {
  87. RECT rectWindow, rectParent, rectScreen;
  88. int nCX, nCY;
  89. HWND hParent;
  90. POINT ptPoint;
  91. hParent = GetParent(hWnd);
  92. if (hParent == NULL) {
  93. hParent = GetDesktopWindow();
  94. }
  95. GetWindowRect(hParent, &rectParent);
  96. GetWindowRect(hWnd, &rectWindow);
  97. GetWindowRect(GetDesktopWindow(), &rectScreen);
  98. nCX = rectWindow.right - rectWindow.left;
  99. nCY = rectWindow.bottom - rectWindow.top;
  100. ptPoint.x = ((rectParent.right + rectParent.left) / 2) - (nCX / 2);
  101. ptPoint.y = ((rectParent.bottom + rectParent.top ) / 2) - (nCY / 2);
  102. if (ptPoint.x < rectScreen.left) {
  103. ptPoint.x = rectScreen.left;
  104. }
  105. if (ptPoint.x > rectScreen.right - nCX) {
  106. ptPoint.x = rectScreen.right - nCX;
  107. }
  108. if (ptPoint.y < rectScreen.top) {
  109. ptPoint.y = rectScreen.top;
  110. }
  111. if (ptPoint.y > rectScreen.bottom - nCY) {
  112. ptPoint.y = rectScreen.bottom - nCY;
  113. }
  114. if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) {
  115. ScreenToClient(hParent, (LPPOINT)&ptPoint);
  116. }
  117. if (!MoveWindow(hWnd, ptPoint.x, ptPoint.y, nCX, nCY, TRUE)) {
  118. return FALSE;
  119. }
  120. return TRUE;
  121. }
  122. /*++
  123. Routine Description:
  124. Reboots the system properly.
  125. Arguments:
  126. fForceClose - A flag to indicate if apps should be forced
  127. to close.
  128. fReboot - A flag to indicate if we should reboot
  129. after shutdown.
  130. Return Value:
  131. TRUE on success, FALSE otherwise.
  132. --*/
  133. BOOL
  134. ShutdownSystem(
  135. IN BOOL fForceClose,
  136. IN BOOL fReboot
  137. )
  138. {
  139. BOOL bResult = FALSE;
  140. //
  141. // Attempt to give the user the required privilege.
  142. //
  143. if (!ModifyTokenPrivilege("SeShutdownPrivilege", FALSE)) {
  144. return FALSE;
  145. }
  146. bResult = InitiateSystemShutdown(NULL, // machinename
  147. NULL, // shutdown message
  148. 0, // delay
  149. fForceClose, // force apps close
  150. fReboot // reboot after shutdown
  151. );
  152. ModifyTokenPrivilege("SeShutdownPrivilege", TRUE);
  153. return bResult;
  154. }
  155. /*++
  156. Routine Description:
  157. Enables or disables a specified privilege.
  158. Arguments:
  159. pszPrivilege - The name of the privilege.
  160. fEnable - A flag to indicate if the
  161. privilege should be enabled.
  162. Return Value:
  163. TRUE on success, FALSE otherwise.
  164. --*/
  165. BOOL
  166. ModifyTokenPrivilege(
  167. IN LPCSTR pszPrivilege,
  168. IN BOOL fEnable
  169. )
  170. {
  171. HANDLE hToken = NULL;
  172. LUID luid;
  173. BOOL bResult = FALSE;
  174. BOOL bReturn;
  175. TOKEN_PRIVILEGES tp;
  176. if (!pszPrivilege) {
  177. return FALSE;
  178. }
  179. __try {
  180. //
  181. // Get a handle to the access token associated with the current process.
  182. //
  183. OpenProcessToken(GetCurrentProcess(),
  184. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  185. &hToken);
  186. if (!hToken) {
  187. __leave;
  188. }
  189. //
  190. // Obtain a LUID for the specified privilege.
  191. //
  192. if (!LookupPrivilegeValue(NULL, pszPrivilege, &luid)) {
  193. __leave;
  194. }
  195. tp.PrivilegeCount = 1;
  196. tp.Privileges[0].Luid = luid;
  197. tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
  198. //
  199. // Modify the access token.
  200. //
  201. bReturn = AdjustTokenPrivileges(hToken,
  202. FALSE,
  203. &tp,
  204. sizeof(TOKEN_PRIVILEGES),
  205. NULL,
  206. NULL);
  207. if (!bReturn || GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
  208. __leave;
  209. }
  210. bResult = TRUE;
  211. } // try
  212. __finally {
  213. if (hToken) {
  214. CloseHandle(hToken);
  215. }
  216. } // finally
  217. return bResult;
  218. }
  219. /*++
  220. Routine Description:
  221. Copies the necessary files to the destination.
  222. Arguments:
  223. hWnd - Parent window handle.
  224. Return Value:
  225. TRUE on success, FALSE otherwise.
  226. --*/
  227. BOOL
  228. CopyAppFiles(
  229. IN HWND hWnd
  230. )
  231. {
  232. char szSrcPath[MAX_PATH];
  233. char szDestPath[MAX_PATH];
  234. char szError[MAX_PATH];
  235. char szDestDir[MAX_PATH];
  236. UINT nCount;
  237. HRESULT hr;
  238. //
  239. // Obtain the location of \Program Files.
  240. //
  241. hr = SHGetFolderPath(hWnd, // HWND for message display
  242. CSIDL_PROGRAM_FILES, // need \Program Files folder
  243. NULL, // no token needed
  244. SHGFP_TYPE_CURRENT, // we want the current location of the folder
  245. szDestDir); // destination buffer
  246. if (FAILED(hr)) {
  247. LoadString(g_ai.hInstance, IDS_NO_PROG_FILES, szError, sizeof(szError));
  248. MessageBox(hWnd, szError, 0, MB_ICONERROR);
  249. return FALSE;
  250. }
  251. hr = StringCchCat(szDestDir, sizeof(szDestDir), "\\"COMPAT_DEMO_DIR);
  252. if (FAILED(hr)) {
  253. return FALSE;
  254. }
  255. if (GetFileAttributes(szDestDir) == -1) {
  256. if (!CreateDirectory(szDestDir, NULL)) {
  257. return FALSE;
  258. }
  259. }
  260. //
  261. // Preserve the path for later use.
  262. //
  263. StringCchCopy(g_ai.szDestDir, sizeof(g_ai.szDestDir), szDestDir);
  264. //
  265. // Now copy our files.
  266. //
  267. for (nCount = 0; nCount < g_ai.cFiles; ++nCount) {
  268. //
  269. // Build the source path.
  270. //
  271. hr = StringCchPrintf(szSrcPath,
  272. sizeof(szSrcPath),
  273. "%hs\\%hs",
  274. g_ai.szCurrentDir,
  275. g_ai.shortcut[nCount].szFileName);
  276. if (FAILED(hr)) {
  277. return FALSE;
  278. }
  279. //
  280. // Build the destination path.
  281. //
  282. hr = StringCchPrintf(szDestPath,
  283. sizeof(szDestPath),
  284. "%hs\\%hs",
  285. g_ai.szDestDir,
  286. g_ai.shortcut[nCount].szFileName);
  287. if (FAILED(hr)) {
  288. return FALSE;
  289. }
  290. CopyFile(szSrcPath, szDestPath, FALSE);
  291. }
  292. return TRUE;
  293. }
  294. /*++
  295. Routine Description:
  296. Create shortcuts for our three entries.
  297. Arguments:
  298. hWnd - Parent window handle.
  299. Return Value:
  300. TRUE on success, FALSE otherwise.
  301. --*/
  302. BOOL
  303. CreateShortcuts(
  304. IN HWND hWnd
  305. )
  306. {
  307. char szError[MAX_PATH];
  308. char szDestDir[MAX_PATH];
  309. char szLnkDirectory[MAX_PATH];
  310. char szFileNamePath[MAX_PATH];
  311. char szExplorer[MAX_PATH];
  312. const char szExplorerExe[] = "explorer.exe";
  313. UINT nCount;
  314. HRESULT hr;
  315. CShortcut cs;
  316. //
  317. // Obtain the location of the Start Menu folder for the
  318. // individual user.
  319. //
  320. hr = SHGetFolderPath(hWnd,
  321. CSIDL_PROGRAMS,
  322. NULL,
  323. SHGFP_TYPE_CURRENT,
  324. szDestDir);
  325. if (FAILED(hr)) {
  326. LoadString(g_ai.hInstance, IDS_NO_PROGRAMS, szError, sizeof(szError));
  327. MessageBox(hWnd, szError, 0, MB_ICONERROR);
  328. return FALSE;
  329. }
  330. //
  331. // Create our group - put it in the individual user folder
  332. // so we'll work with Win9x/ME.
  333. //
  334. cs.CreateGroup(COMPAT_DEMO_DIR, FALSE);
  335. //
  336. // Build the start menu directory -
  337. // C:\Documents and Settings\<username>\Start Menu\Programs\Compatibility Demo
  338. //
  339. hr = StringCchCat(szDestDir, sizeof(szDestDir), "\\"COMPAT_DEMO_DIR);
  340. if (FAILED(hr)) {
  341. return FALSE;
  342. }
  343. hr = StringCchCopy(szLnkDirectory, sizeof(szLnkDirectory), szDestDir);
  344. if (FAILED(hr)) {
  345. return FALSE;
  346. }
  347. //
  348. // Launch explorer.exe and display the window.
  349. //
  350. hr = StringCchPrintf(szExplorer,
  351. sizeof(szExplorer),
  352. "%hs %hs",
  353. szExplorerExe,
  354. szDestDir);
  355. if (FAILED(hr)) {
  356. return FALSE;
  357. }
  358. //
  359. // We use WinExec to emulate other apps -
  360. // CreateProcess is the proper way.
  361. //
  362. WinExec(szExplorer, SW_SHOWNORMAL);
  363. //
  364. // Give explorer a little time to come up.
  365. //
  366. Sleep(2000);
  367. //
  368. // Now create the shortcuts.
  369. //
  370. for (nCount = 0; nCount < g_ai.cFiles - 1; ++nCount) {
  371. //
  372. // Build the file system related path.
  373. //
  374. hr = StringCchPrintf(szFileNamePath,
  375. sizeof(szFileNamePath),
  376. "%hs\\%hs",
  377. g_ai.szDestDir,
  378. g_ai.shortcut[nCount].szFileName);
  379. if (FAILED(hr)) {
  380. return FALSE;
  381. }
  382. cs.CreateShortcut(szLnkDirectory,
  383. szFileNamePath,
  384. g_ai.shortcut[nCount].szDisplayName,
  385. nCount == 1 ? "-runapp" : NULL,
  386. g_ai.szDestDir,
  387. SW_SHOWNORMAL);
  388. //
  389. // Do it slowly like other apps do.
  390. //
  391. Sleep(3000);
  392. }
  393. //
  394. // Now try to create a shortcut to our EXE on the desktop,
  395. // but use a hard-coded path.
  396. //
  397. hr = StringCchPrintf(szFileNamePath,
  398. sizeof(szFileNamePath),
  399. "%hs\\%hs",
  400. g_ai.szDestDir,
  401. g_ai.shortcut[1].szFileName);
  402. if (FAILED(hr)) {
  403. return FALSE;
  404. }
  405. BadCreateShortcut(g_ai.fEnableBadFunc ? FALSE : TRUE,
  406. szFileNamePath,
  407. g_ai.szDestDir,
  408. g_ai.shortcut[1].szDisplayName);
  409. return TRUE;
  410. }
  411. /*++
  412. Routine Description:
  413. Performs some basic initialization.
  414. Arguments:
  415. lpCmdLine - Pointer to the command line provided.
  416. Return Value:
  417. None.
  418. --*/
  419. BOOL
  420. DemoAppInitialize(
  421. IN LPSTR lpCmdLine
  422. )
  423. {
  424. char szPath[MAX_PATH];
  425. char* pToken = NULL;
  426. char* pTemp = NULL;
  427. const char szSeps[] = " ";
  428. const char szDisable[] = "-disable";
  429. const char szRunApp[] = "-runapp";
  430. const char szExtended[] = "-ext";
  431. const char szInsecure[] = "-enableheap";
  432. const char szInternal[] = "-internal";
  433. DWORD cchReturned;
  434. HRESULT hr;
  435. UINT cchSize;
  436. g_ai.fEnableBadFunc = TRUE;
  437. g_ai.fInsecure = FALSE;
  438. //
  439. // Get paths to %windir% and %windir%\System(32)
  440. //
  441. cchSize = GetSystemWindowsDirectory(g_ai.szWinDir, sizeof(g_ai.szWinDir));
  442. if (cchSize > sizeof(g_ai.szWinDir) || cchSize == 0) {
  443. return FALSE;
  444. }
  445. cchSize = GetSystemDirectory(g_ai.szSysDir, sizeof(g_ai.szSysDir));
  446. if (cchSize > sizeof(g_ai.szSysDir) || cchSize == 0) {
  447. return FALSE;
  448. }
  449. //
  450. // Set up information for each of the shortcuts we'll be creating
  451. // and the files we're installing.
  452. //
  453. g_ai.cFiles = NUM_FILES;
  454. hr = StringCchCopy(g_ai.shortcut[0].szDisplayName,
  455. sizeof(g_ai.shortcut[0].szDisplayName),
  456. "Compatibility Demo Readme");
  457. if (FAILED(hr)) {
  458. return FALSE;
  459. }
  460. hr = StringCchCopy(g_ai.shortcut[0].szFileName,
  461. sizeof(g_ai.shortcut[0].szFileName),
  462. "demoapp.txt");
  463. if (FAILED(hr)) {
  464. return FALSE;
  465. }
  466. hr = StringCchCopy(g_ai.shortcut[1].szDisplayName,
  467. sizeof(g_ai.shortcut[1].szDisplayName),
  468. "Compatibility Demo");
  469. if (FAILED(hr)) {
  470. return FALSE;
  471. }
  472. hr = StringCchCopy(g_ai.shortcut[1].szFileName,
  473. sizeof(g_ai.shortcut[1].szFileName),
  474. "demoapp.exe");
  475. if (FAILED(hr)) {
  476. return FALSE;
  477. }
  478. hr = StringCchCopy(g_ai.shortcut[2].szDisplayName,
  479. sizeof(g_ai.shortcut[2].szDisplayName),
  480. "Compatibility Demo Help");
  481. if (FAILED(hr)) {
  482. return FALSE;
  483. }
  484. hr = StringCchCopy(g_ai.shortcut[2].szFileName,
  485. sizeof(g_ai.shortcut[2].szFileName),
  486. "demoapp.hlp");
  487. if (FAILED(hr)) {
  488. return FALSE;
  489. }
  490. hr = StringCchCopy(g_ai.shortcut[3].szFileName,
  491. sizeof(g_ai.shortcut[3].szFileName),
  492. "demodll.dll");
  493. if (FAILED(hr)) {
  494. return FALSE;
  495. }
  496. //
  497. // Save away the path that we're running from for later.
  498. //
  499. szPath[sizeof(szPath) - 1] = 0;
  500. cchReturned = GetModuleFileName(NULL, szPath, sizeof(szPath));
  501. if (szPath[sizeof(szPath) - 1] != 0 || cchReturned == 0) {
  502. return FALSE;
  503. }
  504. pTemp = strrchr(szPath, '\\');
  505. if (pTemp) {
  506. *pTemp = '\0';
  507. }
  508. StringCchCopy(g_ai.szCurrentDir, sizeof(g_ai.szCurrentDir), szPath);
  509. //
  510. // Check for Win9x - this won't get hooked by any VL.
  511. //
  512. IsWindows9x();
  513. //
  514. // Check for WinXP - this won't get hooked by any VL.
  515. //
  516. IsWindowsXP();
  517. //
  518. // Parse the command line, if one was provided.
  519. //
  520. if (lpCmdLine) {
  521. pToken = strtok(lpCmdLine, szSeps);
  522. while (pToken) {
  523. if (CompareString(LOCALE_USER_DEFAULT,
  524. NORM_IGNORECASE,
  525. pToken,
  526. -1,
  527. szDisable,
  528. -1) == CSTR_EQUAL) {
  529. g_ai.fEnableBadFunc = FALSE;
  530. }
  531. else if (CompareString(LOCALE_USER_DEFAULT,
  532. NORM_IGNORECASE,
  533. pToken,
  534. -1,
  535. szRunApp,
  536. -1) == CSTR_EQUAL) {
  537. g_ai.fRunApp = TRUE;
  538. }
  539. else if (CompareString(LOCALE_USER_DEFAULT,
  540. NORM_IGNORECASE,
  541. pToken,
  542. -1,
  543. szExtended,
  544. -1) == CSTR_EQUAL) {
  545. g_ai.fExtended = TRUE;
  546. }
  547. else if (CompareString(LOCALE_USER_DEFAULT,
  548. NORM_IGNORECASE,
  549. pToken,
  550. -1,
  551. szInsecure,
  552. -1) == CSTR_EQUAL) {
  553. g_ai.fInsecure = TRUE;
  554. }
  555. else if (CompareString(LOCALE_USER_DEFAULT,
  556. NORM_IGNORECASE,
  557. pToken,
  558. -1,
  559. szInternal,
  560. -1) == CSTR_EQUAL) {
  561. g_ai.fInternal = TRUE;
  562. }
  563. pToken = strtok(NULL, szSeps);
  564. }
  565. }
  566. return TRUE;
  567. }
  568. /*++
  569. Routine Description:
  570. Displays a common font dialog.
  571. Arguments:
  572. None.
  573. Return Value:
  574. None.
  575. --*/
  576. void
  577. DisplayFontDlg(
  578. IN HWND hWnd
  579. )
  580. {
  581. CHOOSEFONT cf;
  582. static LOGFONT lf;
  583. static DWORD rgbCurrent;
  584. ZeroMemory(&cf, sizeof(CHOOSEFONT));
  585. cf.lStructSize = sizeof(CHOOSEFONT);
  586. cf.hwndOwner = hWnd;
  587. cf.lpLogFont = &lf;
  588. cf.rgbColors = rgbCurrent;
  589. cf.Flags = CF_SCREENFONTS | CF_EFFECTS;
  590. //
  591. // Display the dialog - user input isn't processed.
  592. //
  593. ChooseFont(&cf);
  594. }
  595. /*++
  596. Routine Description:
  597. Determines if we're truly running on Windows 9x.
  598. A version lie will not correct this call.
  599. Arguments:
  600. None.
  601. Return Value:
  602. None - sets a global flag.
  603. --*/
  604. void
  605. IsWindows9x(
  606. void
  607. )
  608. {
  609. CRegistry creg;
  610. LPSTR lpRet = NULL;
  611. //
  612. // Query a part of the registry that's specific to NT/2000/XP.
  613. // We use the result when we're making calls for demo purposes
  614. // that work differently on Win9x/ME (example: creating shortcuts).
  615. //
  616. lpRet = creg.GetString(HKEY_LOCAL_MACHINE,
  617. PRODUCT_OPTIONS_KEY,
  618. "ProductType");
  619. if (!lpRet) {
  620. g_ai.fWin9x = TRUE;
  621. } else {
  622. g_ai.fWin9x = FALSE;
  623. creg.Free(lpRet);
  624. }
  625. }
  626. /*++
  627. Routine Description:
  628. Determines if we're running on Windows XP.
  629. A version lie will not correct this call.
  630. Arguments:
  631. None.
  632. Return Value:
  633. None - sets a global flag.
  634. --*/
  635. void
  636. IsWindowsXP(
  637. void
  638. )
  639. {
  640. CRegistry creg;
  641. LPSTR lpBuild = NULL;
  642. int nBuild = 0, nWin2K = 2195;
  643. //
  644. // This registry key should only exist for
  645. // Windows XP.
  646. //
  647. lpBuild = creg.GetString(HKEY_LOCAL_MACHINE,
  648. CURRENT_VERSION_KEY,
  649. "CurrentBuildNumber");
  650. //
  651. // Convert the string to an integer.
  652. //
  653. if (lpBuild) {
  654. nBuild = atoi(lpBuild);
  655. if (nWin2K < nBuild) {
  656. g_ai.fWinXP = TRUE;
  657. } else {
  658. g_ai.fWinXP = FALSE;
  659. }
  660. }
  661. if (lpBuild) {
  662. creg.Free(lpBuild);
  663. }
  664. }
  665. /*++
  666. Routine Description:
  667. Adds additional items to our menu.
  668. Arguments:
  669. hWnd - Handle to the parent window.
  670. Return Value:
  671. None.
  672. --*/
  673. void
  674. AddExtendedItems(
  675. IN HWND hWnd
  676. )
  677. {
  678. HMENU hMenu, hSubMenu;
  679. //
  680. // Get menu handles, then add additional items.
  681. //
  682. hMenu = GetMenu(hWnd);
  683. if (!hMenu) {
  684. return;
  685. }
  686. hSubMenu = GetSubMenu(hMenu, 2);
  687. if (!hSubMenu) {
  688. return;
  689. }
  690. AppendMenu(hSubMenu, MF_ENABLED | MF_SEPARATOR, 1, NULL);
  691. AppendMenu(hSubMenu,
  692. MF_ENABLED | MF_STRING,
  693. IDM_ACCESS_VIOLATION,
  694. "Access Violation");
  695. AppendMenu(hSubMenu,
  696. MF_ENABLED | MF_STRING,
  697. IDM_EXCEED_BOUNDS,
  698. "Exceed Array Bounds");
  699. AppendMenu(hSubMenu,
  700. MF_ENABLED | MF_STRING,
  701. IDM_FREE_INVALID_MEM,
  702. "Free Invalid Memory");
  703. AppendMenu(hSubMenu,
  704. MF_ENABLED | MF_STRING,
  705. IDM_FREE_MEM_TWICE,
  706. "Free Memory Twice");
  707. AppendMenu(hSubMenu,
  708. MF_ENABLED | MF_STRING,
  709. IDM_HEAP_CORRUPTION,
  710. "Heap Corruption");
  711. AppendMenu(hSubMenu,
  712. MF_ENABLED | MF_STRING,
  713. IDM_PRIV_INSTRUCTION,
  714. "Privileged Instruction");
  715. DrawMenuBar(hWnd);
  716. }
  717. /*++
  718. Routine Description:
  719. Adds internal items to the menu bar.
  720. Arguments:
  721. hWnd - Handle to the parent window.
  722. Return Value:
  723. None.
  724. --*/
  725. void
  726. AddInternalItems(
  727. IN HWND hWnd
  728. )
  729. {
  730. HMENU hMenu, hSubMenu;
  731. //
  732. // Get menu handles, then add additional items.
  733. //
  734. hMenu = GetMenu(hWnd);
  735. if (!hMenu) {
  736. return;
  737. }
  738. hSubMenu = GetSubMenu(hMenu, 2);
  739. if (!hSubMenu) {
  740. return;
  741. }
  742. AppendMenu(hSubMenu, MF_ENABLED | MF_SEPARATOR, 1, NULL);
  743. AppendMenu(hSubMenu,
  744. MF_ENABLED | MF_STRING,
  745. IDM_PROPAGATION_TEST,
  746. "Propagation Test");
  747. DrawMenuBar(hWnd);
  748. }
  749. /*++
  750. Routine Description:
  751. Obtains an address for an exported function,
  752. then calls it.
  753. Used to test the include/exclude functionality
  754. in QFixApp. Note that is not documented anywhere.
  755. Arguments:
  756. hWnd - Window handle to be passed to the function.
  757. Return Value:
  758. None.
  759. --*/
  760. void
  761. TestIncludeExclude(
  762. IN HWND hWnd
  763. )
  764. {
  765. HINSTANCE hInstance;
  766. HRESULT hr;
  767. char szDll[MAX_PATH];
  768. const char szDemoDll[] = "demodll.dll";
  769. LPFNDEMOAPPMESSAGEBOX DemoAppMessageBox;
  770. hr = StringCchPrintf(szDll,
  771. sizeof(szDll),
  772. "%hs\\%hs",
  773. g_ai.szCurrentDir,
  774. szDemoDll);
  775. if (FAILED(hr)) {
  776. return;
  777. }
  778. hInstance = LoadLibrary(szDll);
  779. if (hInstance) {
  780. //
  781. // Get the address of the function.
  782. //
  783. DemoAppMessageBox = (LPFNDEMOAPPMESSAGEBOX)GetProcAddress(hInstance,
  784. "DemoAppMessageBox");
  785. if (!DemoAppMessageBox) {
  786. FreeLibrary(hInstance);
  787. return;
  788. }
  789. DemoAppMessageBox(hWnd);
  790. FreeLibrary(hInstance);
  791. }
  792. }
  793. /*++
  794. Routine Description:
  795. Saves the contents of the edit window to a file
  796. specified by the user.
  797. Arguments:
  798. None.
  799. Return Value:
  800. None.
  801. --*/
  802. void
  803. SaveContentsToFile(
  804. IN LPCSTR pszFileName
  805. )
  806. {
  807. int nLen = 0;
  808. DWORD cbBytesWritten;
  809. HANDLE hFile;
  810. LPSTR pszData = NULL;
  811. char szError[MAX_PATH];
  812. //
  813. // Determine how much space we need for the buffer, then allocate it.
  814. //
  815. nLen = GetWindowTextLength(g_ai.hWndEdit);
  816. if (nLen) {
  817. pszData = (LPTSTR)HeapAlloc(GetProcessHeap(),
  818. HEAP_ZERO_MEMORY,
  819. nLen);
  820. if (!pszData) {
  821. LoadString(g_ai.hInstance, IDS_BUFFER_ALLOC_FAIL, szError, sizeof(szError));
  822. MessageBox(g_ai.hWndMain, szError, MAIN_APP_TITLE, MB_ICONERROR);
  823. return;
  824. }
  825. //
  826. // Get the text out of the text box and write it out to our file.
  827. //
  828. GetWindowText(g_ai.hWndEdit, pszData, nLen);
  829. hFile = CreateFile(pszFileName,
  830. GENERIC_WRITE,
  831. 0,
  832. NULL,
  833. CREATE_ALWAYS,
  834. FILE_ATTRIBUTE_NORMAL,
  835. NULL);
  836. if (hFile == INVALID_HANDLE_VALUE) {
  837. LoadString(g_ai.hInstance, IDS_FILE_CREATE_FAIL, szError, sizeof(szError));
  838. MessageBox(g_ai.hWndMain, szError, MAIN_APP_TITLE, MB_ICONERROR);
  839. goto cleanup;
  840. }
  841. WriteFile(hFile, pszData, nLen, &cbBytesWritten, NULL);
  842. CloseHandle(hFile);
  843. }
  844. cleanup:
  845. if (pszData) {
  846. HeapFree(GetProcessHeap(), 0, pszData);
  847. }
  848. }
  849. /*++
  850. Routine Description:
  851. Displays a common dialog to the user which allows
  852. them to save the contents of the edit box to a file.
  853. Arguments:
  854. None.
  855. Return Value:
  856. None.
  857. --*/
  858. void
  859. ShowSaveDialog(
  860. void
  861. )
  862. {
  863. char szFilter[MAX_PATH] = "";
  864. char szTemp[MAX_PATH];
  865. OPENFILENAME ofn = {0};
  866. *szTemp = 0;
  867. LoadString(g_ai.hInstance, IDS_SAVE_FILTER, szFilter, sizeof(szFilter));
  868. ofn.lStructSize = sizeof(OPENFILENAME);
  869. ofn.hwndOwner = g_ai.hWndMain;
  870. ofn.hInstance = g_ai.hInstance;
  871. ofn.lpstrFilter = szFilter;
  872. ofn.lpstrCustomFilter = NULL;
  873. ofn.nMaxCustFilter = 0;
  874. ofn.nFilterIndex = 1;
  875. ofn.lpstrFile = szTemp;
  876. ofn.nMaxFile = sizeof(szTemp);
  877. ofn.lpstrTitle = NULL;
  878. ofn.lpstrFileTitle = NULL;
  879. ofn.nMaxFileTitle = 0;
  880. ofn.lpstrInitialDir = NULL;
  881. ofn.nFileOffset = 0;
  882. ofn.nFileExtension = 0;
  883. ofn.lpstrDefExt = "txt";
  884. ofn.lCustData = 0;
  885. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST |
  886. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
  887. if (GetSaveFileName(&ofn)) {
  888. SaveContentsToFile(szTemp);
  889. }
  890. }