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.

2281 lines
66 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. --*/
  4. #include <nt.h>
  5. #include <ntrtl.h>
  6. #include <nturtl.h>
  7. #include <ntexapi.dbg>
  8. #include <windows.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "gflags.h"
  12. CHAR GflagsHelpText[] =
  13. " \n"
  14. "usage: GFLAGS [-r [<Flags>] | \n"
  15. " [-k [<Flags>]] | \n"
  16. " [-i <ImageFileName> [<Flags>]] | \n"
  17. " [-i <ImageFileName> -tracedb <SizeInMb>] | \n"
  18. " [-p <PageHeapOptions>] (use `-p ?' for help) \n"
  19. " \n"
  20. "where: <Flags> is a 32 bit hex number (0x12345678) that specifies \n"
  21. " one or more global flags to set. \n"
  22. " -r operates on system registry settings. \n"
  23. " -k operates on kernel settings of the running system. \n"
  24. " -i operates on settings for a specific image file. \n"
  25. " \n"
  26. " If only the switch is specified, then current settings \n"
  27. " are displayed, not modified. If flags specified for -i \n"
  28. " option are FFFFFFFF, then registry entry for that image \n"
  29. " is deleted \n"
  30. " \n"
  31. "The `-tracedb' option is used to set the size of the stack trace \n"
  32. "database used to store runtime stack traces. The actual database \n"
  33. "will be created if the `+ust' flag is set in a previous command. \n"
  34. "`-tracedb 0' will revert to the default size for the database. \n"
  35. " \n"
  36. "If no arguments are specified to GFLAGS then it displays \n"
  37. "a dialog box that allows the user to modify the global \n"
  38. "flag settings. \n"
  39. " \n"
  40. "Flags may either be a single hex number that specifies all \n"
  41. "32-bits of the GlobalFlags value, or it can be one or more \n"
  42. "arguments, each beginning with a + or -, where the + means \n"
  43. "to set the corresponding bit(s) in the GlobalFlags and a = \n"
  44. "means to clear the corresponding bit(s). After the + or = \n"
  45. "may be either a hex number or a three letter abbreviation \n"
  46. "for a GlobalFlag. Valid abbreviations are: \n"
  47. " \n";
  48. #define _PART_OF_GFLAGS_ 1
  49. #include "..\pageheap\pageheap.cxx"
  50. #if defined(_X86_)
  51. //
  52. // Use function pointers for ntdll import functions so gflags
  53. // can fail with a user friendly message on win9x.
  54. //
  55. #define RtlIntegerToChar pRtlIntegerToChar
  56. #define NtQueryInformationProcess pNtQueryInformationProcess
  57. #define RtlCharToInteger pRtlCharToInteger
  58. #define NtSetSystemInformation pNtSetSystemInformation
  59. #define NtQuerySystemInformation pNtQuerySystemInformation
  60. typedef NTSTATUS (NTAPI *PRTLINTEGERTOCHAR)(
  61. ULONG,
  62. ULONG,
  63. LONG,
  64. PSZ
  65. );
  66. typedef NTSTATUS (NTAPI *PNTQUERYINFORMATIONPROCESS) (
  67. IN HANDLE,
  68. IN PROCESSINFOCLASS,
  69. OUT PVOID,
  70. IN ULONG,
  71. OUT PULONG
  72. );
  73. typedef NTSTATUS (NTAPI * PRTLCHARTOINTEGER) (
  74. PCSZ,
  75. ULONG,
  76. PULONG
  77. );
  78. typedef NTSTATUS (NTAPI * PNTSETSYSTEMINFORMATION) (
  79. IN SYSTEM_INFORMATION_CLASS,
  80. IN PVOID,
  81. IN ULONG
  82. );
  83. typedef NTSTATUS (NTAPI * PNTQUERYSYSTEMINFORMATION) (
  84. IN SYSTEM_INFORMATION_CLASS,
  85. OUT PVOID,
  86. IN ULONG,
  87. OUT PULONG
  88. );
  89. PRTLINTEGERTOCHAR pRtlIntegerToChar;
  90. PNTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
  91. PRTLCHARTOINTEGER pRtlCharToInteger;
  92. PNTSETSYSTEMINFORMATION pNtSetSystemInformation;
  93. PNTQUERYSYSTEMINFORMATION pNtQuerySystemInformation;
  94. #endif
  95. BOOL
  96. GflagsSetTraceDatabaseSize (
  97. PCHAR ApplicationName,
  98. ULONG SizeInMb,
  99. PULONG RealSize
  100. );
  101. INT_PTR APIENTRY MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  102. BOOL
  103. EnableDebugPrivilege( VOID );
  104. BOOL
  105. OkToEnablePagedHeap( VOID );
  106. HWND hwndMain;
  107. HWND hwndPagedHeapDlg;
  108. HKEY hSmKey, hMmKey;
  109. DWORD InitialSetFlags;
  110. DWORD LastSetFlags;
  111. //
  112. // Special pool management
  113. //
  114. #define SPECIAL_POOL_OVERRUNS_CHECK_FORWARD 1
  115. #define SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD 0
  116. DWORD LastSetSpecialPoolTag;
  117. DWORD LastSetSpecialPoolOverruns = SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
  118. TCHAR SpecialPoolRenderBuffer[8 + 1];
  119. DWORD InitialMaxStackTraceDepth;
  120. CHAR LastDebuggerValue[ MAX_PATH ];
  121. UINT SpecialPool[] = {
  122. ID_SPECIAL_POOL_GROUP,
  123. ID_SPECIAL_POOL_IS_TEXT,
  124. ID_SPECIAL_POOL_IS_NUMBER,
  125. ID_SPECIAL_POOL_TAG,
  126. ID_SPECIAL_POOL_VERIFY_START,
  127. ID_SPECIAL_POOL_VERIFY_END,
  128. ID_MAX_STACK_DEPTH,
  129. 0
  130. };
  131. UINT Debugger[] = {
  132. ID_IMAGE_DEBUGGER_GROUP,
  133. ID_IMAGE_DEBUGGER_VALUE,
  134. ID_IMAGE_DEBUGGER_BUTTON,
  135. 0
  136. };
  137. PCHAR SystemProcesses[] = {
  138. "csrss.exe",
  139. "winlogon.exe",
  140. "services.exe",
  141. "lsass.exe",
  142. "svchost.exe",
  143. "ntmssvc.exe",
  144. "rpcss.exe",
  145. "spoolsv.exe"
  146. };
  147. EnableSetOfControls(
  148. HWND hDlg,
  149. UINT * Controls,
  150. BOOL Enable
  151. )
  152. {
  153. UINT Control ;
  154. HWND hWnd ;
  155. Control = *Controls++ ;
  156. while ( Control )
  157. {
  158. hWnd = GetDlgItem( hDlg, Control );
  159. EnableWindow( hWnd, Enable );
  160. ShowWindow( hWnd, Enable ? SW_NORMAL : SW_HIDE );
  161. Control = *Controls++ ;
  162. }
  163. return 0;
  164. }
  165. DWORD
  166. GetSystemRegistryFlags( VOID )
  167. {
  168. DWORD cbKey;
  169. DWORD GFlags;
  170. DWORD type;
  171. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  172. "SYSTEM\\CurrentControlSet\\Control\\Session Manager",
  173. 0,
  174. KEY_READ | KEY_WRITE,
  175. &hSmKey
  176. ) != ERROR_SUCCESS
  177. ) {
  178. MessageBox( hwndMain, "Open Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager", MB_OK );
  179. ExitProcess( 0 );
  180. }
  181. cbKey = sizeof( GFlags );
  182. if (RegQueryValueEx( hSmKey,
  183. "GlobalFlag",
  184. 0,
  185. &type,
  186. (LPBYTE)&GFlags,
  187. &cbKey
  188. ) != ERROR_SUCCESS ||
  189. type != REG_DWORD
  190. ) {
  191. MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
  192. RegCloseKey( hSmKey );
  193. ExitProcess( 0 );
  194. }
  195. cbKey = sizeof( InitialMaxStackTraceDepth );
  196. if (RegQueryValueEx( hSmKey,
  197. "MaxStackTraceDepth",
  198. 0,
  199. &type,
  200. (LPBYTE)&InitialMaxStackTraceDepth,
  201. &cbKey
  202. ) != ERROR_SUCCESS ||
  203. type != REG_DWORD
  204. ) {
  205. InitialMaxStackTraceDepth = 16;
  206. }
  207. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  208. "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
  209. 0,
  210. KEY_READ | KEY_WRITE,
  211. &hMmKey
  212. ) != ERROR_SUCCESS
  213. ) {
  214. MessageBox( hwndMain, "Open Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management", MB_OK );
  215. RegCloseKey( hSmKey );
  216. ExitProcess( 0 );
  217. }
  218. cbKey = sizeof( LastSetSpecialPoolTag );
  219. if (RegQueryValueEx( hMmKey,
  220. "PoolTag",
  221. 0,
  222. &type,
  223. (LPBYTE)&LastSetSpecialPoolTag,
  224. &cbKey
  225. ) == ERROR_SUCCESS
  226. ) {
  227. if (type != REG_DWORD) {
  228. MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PoolTag", MB_OK );
  229. RegCloseKey( hSmKey );
  230. RegCloseKey( hMmKey );
  231. ExitProcess( 0 );
  232. }
  233. } else {
  234. LastSetSpecialPoolTag = 0;
  235. }
  236. cbKey = sizeof( LastSetSpecialPoolOverruns );
  237. if (RegQueryValueEx( hMmKey,
  238. "PoolTagOverruns",
  239. 0,
  240. &type,
  241. (LPBYTE)&LastSetSpecialPoolOverruns,
  242. &cbKey
  243. ) == ERROR_SUCCESS
  244. ) {
  245. if (type != REG_DWORD) {
  246. MessageBox( hwndMain,
  247. "Value Type Error",
  248. "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
  249. "\\PoolTagOverruns",
  250. MB_OK );
  251. RegCloseKey( hSmKey );
  252. RegCloseKey( hMmKey );
  253. ExitProcess( 0 );
  254. }
  255. //
  256. // The only legal values are 0, 1.
  257. //
  258. if (LastSetSpecialPoolOverruns != SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD &&
  259. LastSetSpecialPoolOverruns != SPECIAL_POOL_OVERRUNS_CHECK_FORWARD) {
  260. MessageBox( hwndMain,
  261. "Value Data Error",
  262. "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
  263. "\\PoolTagOverruns",
  264. MB_OK );
  265. RegCloseKey( hSmKey );
  266. RegCloseKey( hMmKey );
  267. ExitProcess( 0 );
  268. }
  269. } else {
  270. LastSetSpecialPoolOverruns = SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
  271. }
  272. return GFlags;
  273. }
  274. BOOLEAN
  275. SetSystemRegistryFlags(
  276. DWORD GFlags,
  277. DWORD MaxStackTraceDepth,
  278. DWORD SpecialPoolTag,
  279. DWORD SpecialPoolOverruns
  280. )
  281. {
  282. if (RegSetValueEx( hSmKey,
  283. "GlobalFlag",
  284. 0,
  285. REG_DWORD,
  286. (LPBYTE)&GFlags,
  287. sizeof( GFlags )
  288. ) != ERROR_SUCCESS
  289. ) {
  290. MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
  291. RegCloseKey( hSmKey );
  292. RegCloseKey( hMmKey );
  293. ExitProcess( 0 );
  294. }
  295. if (RegSetValueEx( hSmKey,
  296. "MaxStackTraceDepth",
  297. 0,
  298. REG_DWORD,
  299. (LPBYTE)&MaxStackTraceDepth,
  300. sizeof( MaxStackTraceDepth )
  301. ) != ERROR_SUCCESS
  302. ) {
  303. MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\MaxStackTraceDepth", MB_OK );
  304. RegCloseKey( hSmKey );
  305. RegCloseKey( hMmKey );
  306. ExitProcess( 0 );
  307. }
  308. //
  309. // Only modify special pool if we went to GUI mode
  310. //
  311. if (hwndMain) {
  312. if (SpecialPoolTag) {
  313. if (RegSetValueEx( hMmKey,
  314. "PoolTag",
  315. 0,
  316. REG_DWORD,
  317. (LPBYTE)&SpecialPoolTag,
  318. sizeof( SpecialPoolTag )
  319. ) != ERROR_SUCCESS
  320. ) {
  321. MessageBox( hwndMain,
  322. "Value Error",
  323. "SYSTEM\\CurrentControlSet\\Control\\Session Manager"
  324. "\\Memory Management\\PoolTag",
  325. MB_OK );
  326. RegCloseKey( hSmKey );
  327. RegCloseKey( hMmKey );
  328. ExitProcess( 0 );
  329. }
  330. if (RegSetValueEx( hMmKey,
  331. "PoolTagOverruns",
  332. 0,
  333. REG_DWORD,
  334. (LPBYTE)&SpecialPoolOverruns,
  335. sizeof( SpecialPoolOverruns )
  336. ) != ERROR_SUCCESS
  337. ) {
  338. MessageBox( hwndMain,
  339. "Value Error",
  340. "SYSTEM\\CurrentControlSet\\Control\\Session Manager"
  341. "\\Memory Management\\PoolTag",
  342. MB_OK );
  343. RegCloseKey( hSmKey );
  344. RegCloseKey( hMmKey );
  345. ExitProcess( 0 );
  346. }
  347. } else {
  348. RegDeleteValue( hMmKey,
  349. "PoolTag"
  350. );
  351. RegDeleteValue( hMmKey,
  352. "PoolTagOverruns"
  353. );
  354. }
  355. }
  356. InitialMaxStackTraceDepth = MaxStackTraceDepth;
  357. LastSetFlags = GFlags;
  358. LastSetSpecialPoolTag = SpecialPoolTag;
  359. LastSetSpecialPoolOverruns = SpecialPoolOverruns;
  360. return TRUE;
  361. }
  362. DWORD
  363. GetKernelModeFlags( VOID )
  364. {
  365. NTSTATUS Status;
  366. SYSTEM_FLAGS_INFORMATION SystemInformation;
  367. Status = NtQuerySystemInformation( SystemFlagsInformation,
  368. &SystemInformation,
  369. sizeof( SystemInformation ),
  370. NULL
  371. );
  372. if (!NT_SUCCESS( Status )) {
  373. MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
  374. ExitProcess( 0 );
  375. }
  376. return SystemInformation.Flags;
  377. }
  378. BOOLEAN
  379. AddImageNameToUSTString(
  380. PCHAR ImageFileName
  381. )
  382. {
  383. CHAR RegKey[ MAX_PATH ];
  384. CHAR *Enabled = NULL;
  385. HKEY hKey;
  386. DWORD Result;
  387. DWORD Length;
  388. if (strlen( ImageFileName ) == 0)
  389. return FALSE;
  390. // Open the Key
  391. Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  392. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
  393. 0,
  394. NULL,
  395. REG_OPTION_NON_VOLATILE,
  396. KEY_ALL_ACCESS,
  397. NULL,
  398. &hKey,
  399. NULL
  400. );
  401. if (Result == ERROR_SUCCESS) {
  402. // Get the current length of the registry key
  403. Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, NULL, &Length );
  404. if (Result == ERROR_SUCCESS){
  405. // Get a buffer big enough for current key, a ';', and our new name.
  406. Enabled = (PCHAR)malloc(Length + strlen(ImageFileName)+ 1);
  407. if (Enabled) {
  408. // Get the current key value
  409. Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, (PBYTE)Enabled, &Length );
  410. if (Result == ERROR_SUCCESS) {
  411. // If we are not currently in there, let add ourselves
  412. if (!strstr(Enabled, ImageFileName)) {
  413. //Watch for a trailing ';'
  414. if (Enabled[strlen(Enabled) - 1] != ';')
  415. strcat(Enabled, ";");
  416. strcat(Enabled, ImageFileName);
  417. Result = RegSetValueEx( hKey,
  418. "USTEnabled",
  419. 0,
  420. REG_SZ,
  421. (PBYTE)Enabled,
  422. (strlen(Enabled) + 1));
  423. }
  424. }
  425. free(Enabled);
  426. } // if enabled
  427. } // Result == ERROR_SUCCESS on RegQueryValue
  428. else if (Result == ERROR_FILE_NOT_FOUND) {
  429. // Key doesnt currently exist so lets just set it.
  430. Result = RegSetValueEx( hKey,
  431. "USTEnabled",
  432. 0,
  433. REG_SZ,
  434. (PBYTE)ImageFileName,
  435. (strlen(ImageFileName) + 1));
  436. } // Result == ERROR_FILE_NOT_FOUND on RegQueryValue
  437. RegCloseKey( hKey );
  438. } // Result == ERROR_SUCCESS on RegCreateKeyEx
  439. // Did we succeed or not
  440. if (Result != ERROR_SUCCESS) {
  441. MessageBox( hwndMain,
  442. "Failure adding or accessing User Stack Trace Registry Key",
  443. ImageFileName,
  444. MB_OK
  445. );
  446. return FALSE;
  447. }
  448. return TRUE;
  449. }
  450. BOOLEAN
  451. DelImageNameFromUSTString(
  452. PCHAR ImageFileName
  453. )
  454. {
  455. CHAR RegKey[ MAX_PATH ];
  456. CHAR *Enabled = NULL;
  457. CHAR *NameStart = NULL, *NameEnd = NULL;
  458. HKEY hKey;
  459. DWORD Result;
  460. DWORD Length;
  461. if (strlen( ImageFileName ) == 0)
  462. return FALSE;
  463. // Open the Key
  464. Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  465. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
  466. 0,
  467. NULL,
  468. REG_OPTION_NON_VOLATILE,
  469. KEY_ALL_ACCESS,
  470. NULL,
  471. &hKey,
  472. NULL
  473. );
  474. if (Result == ERROR_SUCCESS) {
  475. // Get the current length of the registry key
  476. Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, NULL, &Length );
  477. if (Result == ERROR_SUCCESS) {
  478. if (Length != 0) {
  479. // Get a buffer big enough for current key
  480. Enabled = (PCHAR)malloc(Length);
  481. if (Enabled) {
  482. // Get the current key value
  483. Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, (PBYTE)Enabled, &Length );
  484. if (Result == ERROR_SUCCESS) {
  485. // If we are currently in there, delete ourselves
  486. if (NameStart = strstr(Enabled, ImageFileName)) {
  487. NameEnd = NameStart + strlen(ImageFileName);
  488. if (*NameEnd == ';'){
  489. NameEnd++;
  490. strcpy(NameStart, NameEnd);
  491. }
  492. else
  493. *NameStart = '\0';
  494. //Knock off any trailing ';'
  495. if (Enabled[strlen(Enabled) - 1] == ';')
  496. Enabled[strlen(Enabled) - 1] = '\0';
  497. if (strlen(Enabled)) {
  498. Result = RegSetValueEx( hKey,
  499. "USTEnabled",
  500. 0,
  501. REG_SZ,
  502. (PBYTE)Enabled,
  503. (strlen(Enabled) + 1));
  504. }
  505. else{
  506. Result = RegDeleteValue( hKey, "USTEnabled");
  507. }
  508. }
  509. }
  510. free(Enabled);
  511. }
  512. }
  513. }
  514. else if (Result == ERROR_FILE_NOT_FOUND) {
  515. // This is a case where the registry key does not already exist
  516. Result = ERROR_SUCCESS;
  517. }
  518. RegCloseKey( hKey );
  519. }
  520. // Did we succeed or not
  521. if (Result != ERROR_SUCCESS) {
  522. MessageBox( hwndMain,
  523. "Failure accessing or deleting User Stack Trace Registry Key",
  524. ImageFileName,
  525. MB_OK
  526. );
  527. return FALSE;
  528. }
  529. return TRUE;
  530. }
  531. BOOLEAN
  532. SetKernelModeFlags(
  533. DWORD GFlags
  534. )
  535. {
  536. NTSTATUS Status;
  537. SYSTEM_FLAGS_INFORMATION SystemInformation;
  538. if (!EnableDebugPrivilege()) {
  539. MessageBox( hwndMain, "Access Denied", "Unable to enable debug privilege", MB_OK );
  540. ExitProcess( 0 );
  541. }
  542. SystemInformation.Flags = GFlags;
  543. Status = NtSetSystemInformation( SystemFlagsInformation,
  544. &SystemInformation,
  545. sizeof( SystemInformation )
  546. );
  547. if (!NT_SUCCESS( Status )) {
  548. MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
  549. ExitProcess( 0 );
  550. }
  551. LastSetFlags = GFlags;
  552. return TRUE;
  553. }
  554. DWORD
  555. GetImageFileNameFlags(
  556. PCHAR ImageFileName
  557. )
  558. {
  559. CHAR Buffer[ MAX_PATH ];
  560. CHAR RegKey[ MAX_PATH ];
  561. DWORD Length = MAX_PATH;
  562. DWORD GFlags;
  563. HKEY hKey;
  564. GFlags = 0;
  565. if (strlen( ImageFileName ) != 0) {
  566. sprintf( RegKey,
  567. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
  568. ImageFileName
  569. );
  570. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS ) {
  571. if (RegQueryValueEx( hKey, "GlobalFlag", NULL, NULL, (PBYTE)Buffer, &Length ) == ERROR_SUCCESS ) {
  572. RtlCharToInteger( Buffer, 0, &GFlags );
  573. }
  574. RegCloseKey( hKey );
  575. }
  576. }
  577. return GFlags;
  578. }
  579. BOOL
  580. GetImageFileNameDebugger(
  581. PCHAR ImageFileName,
  582. PCHAR Debugger
  583. )
  584. {
  585. CHAR RegKey[ MAX_PATH ];
  586. DWORD Length = MAX_PATH;
  587. DWORD GFlags;
  588. HKEY hKey;
  589. BOOL Success = FALSE;
  590. GFlags = 0;
  591. if (strlen( ImageFileName ) != 0) {
  592. sprintf( RegKey,
  593. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
  594. ImageFileName
  595. );
  596. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS ) {
  597. if (RegQueryValueEx( hKey, "Debugger", NULL, NULL, (PBYTE)Debugger, &Length ) == ERROR_SUCCESS ) {
  598. Success = TRUE ;
  599. }
  600. RegCloseKey( hKey );
  601. }
  602. }
  603. return Success ;
  604. }
  605. BOOLEAN
  606. SetImageFileNameFlags(
  607. PCHAR ImageFileName,
  608. DWORD GFlags
  609. )
  610. {
  611. CHAR Buffer[ MAX_PATH ];
  612. CHAR RegKey[ MAX_PATH ];
  613. HKEY hKey;
  614. DWORD Result;
  615. DWORD Length;
  616. DWORD Disposition;
  617. if (strlen( ImageFileName ) != 0) {
  618. sprintf( RegKey,
  619. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
  620. ImageFileName
  621. );
  622. Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  623. RegKey,
  624. 0,
  625. NULL,
  626. REG_OPTION_NON_VOLATILE,
  627. KEY_ALL_ACCESS,
  628. NULL,
  629. &hKey,
  630. &Disposition
  631. );
  632. if (Result == ERROR_SUCCESS) {
  633. if (GFlags == (DWORD)-1) {
  634. Result = RegDeleteValue( hKey,
  635. "GlobalFlag"
  636. );
  637. DelImageNameFromUSTString(ImageFileName);
  638. }
  639. else {
  640. Length = sprintf( Buffer, "0x%08x", GFlags ) + 1;
  641. Result = RegSetValueEx( hKey,
  642. "GlobalFlag",
  643. 0,
  644. REG_SZ,
  645. (PBYTE)Buffer,
  646. Length
  647. );
  648. if (GFlags&FLG_USER_STACK_TRACE_DB)
  649. AddImageNameToUSTString(ImageFileName);
  650. else
  651. DelImageNameFromUSTString(ImageFileName);
  652. //
  653. // If we enable page heap for a single application
  654. // then we will avoid default behavior which is
  655. // page heap light (only normal allocations) and
  656. // we will enable the page heap full power.
  657. // Note that we do not do this for system wide
  658. // settings because this will make the machine
  659. // unbootable.
  660. //
  661. if ((GFlags & FLG_HEAP_PAGE_ALLOCS)) {
  662. Length = sprintf( Buffer, "0x%08x", 0x03 ) + 1;
  663. Result = RegSetValueEx(
  664. hKey,
  665. "PageHeapFlags",
  666. 0,
  667. REG_SZ,
  668. (PBYTE)Buffer,
  669. Length
  670. );
  671. }
  672. }
  673. RegCloseKey( hKey );
  674. }
  675. if (Result != ERROR_SUCCESS) {
  676. MessageBox( hwndMain,
  677. (GFlags == (DWORD)-1) ?
  678. "Failed to delete registry value" :
  679. "Failed to set registry value",
  680. ImageFileName,
  681. MB_OK
  682. );
  683. return FALSE;
  684. }
  685. LastSetFlags = GFlags;
  686. return TRUE;
  687. }
  688. return FALSE;
  689. }
  690. BOOLEAN
  691. SetImageFileNameDebugger(
  692. PCHAR ImageFileName,
  693. PCHAR Debugger
  694. )
  695. {
  696. CHAR RegKey[ MAX_PATH ];
  697. HKEY hKey;
  698. DWORD Result;
  699. DWORD Length;
  700. DWORD Disposition;
  701. if (strlen( ImageFileName ) != 0) {
  702. sprintf( RegKey,
  703. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
  704. ImageFileName
  705. );
  706. Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  707. RegKey,
  708. 0,
  709. NULL,
  710. REG_OPTION_NON_VOLATILE,
  711. KEY_ALL_ACCESS,
  712. NULL,
  713. &hKey,
  714. &Disposition
  715. );
  716. if (Result == ERROR_SUCCESS) {
  717. if ( *Debugger )
  718. {
  719. Result = RegSetValueEx( hKey,
  720. "Debugger",
  721. 0,
  722. REG_SZ,
  723. (PBYTE)Debugger,
  724. strlen( Debugger ) + 1 );
  725. }
  726. else
  727. {
  728. Result = RegDeleteValue( hKey, "Debugger" );
  729. }
  730. RegCloseKey( hKey );
  731. }
  732. if (Result != ERROR_SUCCESS) {
  733. MessageBox( hwndMain,
  734. ( *Debugger ) ?
  735. "Failed to delete registry value" :
  736. "Failed to set registry value",
  737. ImageFileName,
  738. MB_OK
  739. );
  740. return FALSE;
  741. }
  742. return TRUE;
  743. }
  744. return FALSE;
  745. }
  746. BOOLEAN fRegistrySettings;
  747. BOOLEAN fKernelSettings;
  748. BOOLEAN fImageFileSettings;
  749. BOOLEAN fDisplaySettings;
  750. BOOLEAN fLaunchCommand;
  751. BOOLEAN fFlushImageSettings;
  752. PUCHAR ImageFileName;
  753. DWORD GlobalFlagMask;
  754. DWORD GlobalFlagSetting;
  755. DWORD MaxDepthSetting;
  756. DWORD OldGlobalFlags;
  757. DWORD NewGlobalFlags;
  758. DWORD NewGlobalFlagsValidMask;
  759. DWORD NewGlobalFlagsIgnored;
  760. void
  761. DisplayFlags(
  762. PCHAR Msg,
  763. DWORD Flags,
  764. DWORD FlagsIgnored
  765. )
  766. {
  767. int i;
  768. if (Flags == 0xFFFFFFFF) {
  769. printf( "No %s\n", Msg );
  770. return;
  771. }
  772. printf( "Current %s are: %08x\n", Msg, Flags );
  773. for (i=0; i<32; i++) {
  774. if (GlobalFlagInfo[i].Abbreviation != NULL &&
  775. (Flags & GlobalFlagInfo[i].Flag)
  776. ) {
  777. if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
  778. printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, "Enable page heap");
  779. }
  780. else {
  781. printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, GlobalFlagInfo[i].Description );
  782. }
  783. }
  784. }
  785. if (FlagsIgnored) {
  786. printf( "Following settings were ignored: %08x\n", FlagsIgnored );
  787. for (i=0; i<32; i++) {
  788. if (GlobalFlagInfo[i].Abbreviation != NULL &&
  789. (FlagsIgnored & GlobalFlagInfo[i].Flag)
  790. ) {
  791. if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
  792. printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, "Enable page heap");
  793. }
  794. else {
  795. printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, GlobalFlagInfo[i].Description );
  796. }
  797. }
  798. }
  799. }
  800. }
  801. BOOL
  802. IsCmdlineOption (
  803. PCHAR Option,
  804. PCHAR Name,
  805. PCHAR NameEx
  806. )
  807. {
  808. if (_stricmp (Option, Name) == 0 || _stricmp (Option, NameEx) == 0) {
  809. return TRUE;
  810. }
  811. else {
  812. return FALSE;
  813. }
  814. }
  815. int
  816. __cdecl
  817. main(
  818. int argc,
  819. char **argv
  820. )
  821. {
  822. MSG msg;
  823. CHAR c;
  824. PCHAR s;
  825. BOOLEAN fUsage, fExpectingFlags, fExpectingDepth;
  826. ULONG i;
  827. CHAR Settings[ 2*MAX_PATH ];
  828. #if defined(_X86_)
  829. OSVERSIONINFO VersionInfo;
  830. VersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  831. GetVersionEx( &VersionInfo );
  832. if ( VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ) {
  833. MessageBox( NULL,
  834. "Global flags only runs on Windows NT and Windows 2000. The glfags command was ignored.",
  835. "Global Flags Error",
  836. 0 );
  837. exit(0);
  838. }
  839. else {
  840. HMODULE hDll;
  841. hDll = GetModuleHandle("ntdll");
  842. if (hDll != NULL) {
  843. pRtlIntegerToChar = ( PRTLINTEGERTOCHAR )
  844. GetProcAddress(
  845. hDll,
  846. "RtlIntegerToChar"
  847. );
  848. pNtQueryInformationProcess = ( PNTQUERYINFORMATIONPROCESS )
  849. GetProcAddress(
  850. hDll,
  851. "NtQueryInformationProcess"
  852. );
  853. pRtlCharToInteger = ( PRTLCHARTOINTEGER )
  854. GetProcAddress(
  855. hDll,
  856. "RtlCharToInteger"
  857. );
  858. pNtSetSystemInformation = ( PNTSETSYSTEMINFORMATION )
  859. GetProcAddress(
  860. hDll,
  861. "NtSetSystemInformation"
  862. );
  863. pNtQuerySystemInformation = ( PNTQUERYSYSTEMINFORMATION )
  864. GetProcAddress(
  865. hDll,
  866. "NtQuerySystemInformation"
  867. );
  868. }
  869. }
  870. #endif
  871. //
  872. // Check if we need to redirect the whole command line to the page heap
  873. // command line parser.
  874. //
  875. if (argc >= 2 && IsCmdlineOption (argv[1], "/p", "-p")) {
  876. PageHeapMain (argc - 1, argv + 1);
  877. exit(0);
  878. }
  879. //
  880. // Check forst for `-i APP -tracedb SIZE' option
  881. //
  882. if (argc == 5 &&
  883. IsCmdlineOption (argv[3], "/tracedb", "-tracedb") &&
  884. IsCmdlineOption (argv[1], "/i", "-i")) {
  885. ULONG RealSize;
  886. if (GflagsSetTraceDatabaseSize (argv[2], atoi (argv[4]), &RealSize) == FALSE) {
  887. printf("Failed to set the trace database size for `%s' \n", argv[2]);
  888. exit(5);
  889. }
  890. else {
  891. if (RealSize > 0) {
  892. printf("Trace database size for `%s' set to %u Mb.\n", argv[2], RealSize);
  893. }
  894. else {
  895. printf("Will use default size for the trace database. \n");
  896. }
  897. exit(0);
  898. }
  899. }
  900. //
  901. // Continue ...
  902. //
  903. hwndMain = NULL;
  904. fUsage = FALSE;
  905. fExpectingFlags = FALSE;
  906. fExpectingDepth = FALSE;
  907. GlobalFlagMask = 0xFFFFFFFF;
  908. GlobalFlagSetting = 0;
  909. while (--argc) {
  910. s = *++argv;
  911. if (!fExpectingFlags && (*s == '-' || *s == '/')) {
  912. while (*++s) {
  913. c = (char)tolower(*s);
  914. switch (c) {
  915. case 'r':
  916. case 'k':
  917. case 'i':
  918. if (fRegistrySettings || fKernelSettings || fImageFileSettings) {
  919. fprintf( stderr, "GFLAG: may only specify one of -r, -k or -i\n" );
  920. fUsage = TRUE;
  921. }
  922. else {
  923. fExpectingFlags = TRUE;
  924. fDisplaySettings = TRUE;
  925. if (c == 'r') {
  926. fRegistrySettings = TRUE;
  927. fExpectingDepth = TRUE;
  928. OldGlobalFlags = GetSystemRegistryFlags();
  929. NewGlobalFlagsValidMask = VALID_SYSTEM_REGISTRY_FLAGS;
  930. strcpy( Settings, "Boot Registry Settings" );
  931. }
  932. else
  933. if (c == 'k') {
  934. fKernelSettings = TRUE;
  935. NewGlobalFlagsValidMask = VALID_KERNEL_MODE_FLAGS;
  936. OldGlobalFlags = GetKernelModeFlags();
  937. strcpy( Settings, "Running Kernel Settings" );
  938. }
  939. else {
  940. fImageFileSettings = TRUE;
  941. NewGlobalFlagsValidMask = VALID_IMAGE_FILE_NAME_FLAGS;
  942. if (!--argc) {
  943. fprintf( stderr, "GFLAGS: ImageFileName missing after -i switch\n" );
  944. fUsage = TRUE;
  945. exit( 0 ); // 179741 - JHH
  946. }
  947. else {
  948. ImageFileName = (PUCHAR)(*++argv);
  949. OldGlobalFlags = GetImageFileNameFlags( (PCHAR)ImageFileName );
  950. sprintf( Settings, "Registry Settings for %s executable", ImageFileName );
  951. }
  952. }
  953. }
  954. break;
  955. case 'l':
  956. fLaunchCommand = TRUE;
  957. fExpectingFlags = TRUE;
  958. break;
  959. default:
  960. fUsage = TRUE;
  961. break;
  962. }
  963. }
  964. }
  965. else {
  966. if (fExpectingFlags) {
  967. fDisplaySettings = FALSE;
  968. if (*s == '+' || *s == '-') {
  969. if (strlen(s+1) == 3) {
  970. for (i = 0; i < 32; i += 1) {
  971. if ((NewGlobalFlagsValidMask & GlobalFlagInfo[i].Flag) &&
  972. (GlobalFlagInfo[i].Abbreviation != NULL) &&
  973. _stricmp( GlobalFlagInfo[i].Abbreviation, s+1 ) == NULL) {
  974. if (fKernelSettings) {
  975. if (_stricmp(GlobalFlagInfo[i].Abbreviation, "ptg") == NULL) {
  976. fprintf (stderr,
  977. "Ignoring `ptg' flag. It can be used only with registry "
  978. "settings (`-r') because it requires a reboot.\n");
  979. continue;
  980. }
  981. if (_stricmp(GlobalFlagInfo[i].Abbreviation, "kst") == NULL) {
  982. fprintf (stderr,
  983. "Ignoring `kst' flag. It can be used only with registry "
  984. "settings (`-r') because it requires a reboot.\n");
  985. continue;
  986. }
  987. }
  988. if (*s == '-') {
  989. GlobalFlagMask &= ~GlobalFlagInfo[i].Flag;
  990. }
  991. else {
  992. GlobalFlagSetting |= GlobalFlagInfo[i].Flag;
  993. }
  994. s += 4;
  995. break;
  996. }
  997. }
  998. }
  999. if (*s != '\0') {
  1000. if (*s++ == '-') {
  1001. GlobalFlagMask &= ~strtoul( s, &s, 16 );
  1002. }
  1003. else {
  1004. GlobalFlagSetting |= strtoul( s, &s, 16 );
  1005. }
  1006. }
  1007. }
  1008. else {
  1009. fExpectingFlags = FALSE;
  1010. GlobalFlagSetting = strtoul( s, &s, 16 );
  1011. }
  1012. if (fLaunchCommand) {
  1013. exit( 0 );
  1014. }
  1015. if (fImageFileSettings && OldGlobalFlags == 0xFFFFFFFF) {
  1016. OldGlobalFlags = 0;
  1017. }
  1018. }
  1019. else
  1020. if (fExpectingDepth) {
  1021. MaxDepthSetting = strtoul( s, &s, 10 );
  1022. fExpectingDepth = FALSE;
  1023. }
  1024. else {
  1025. fprintf( stderr, "GFLAGS: Unexpected argument - '%s'\n", s );
  1026. fUsage = TRUE;
  1027. }
  1028. }
  1029. }
  1030. if (fUsage) {
  1031. fputs(GflagsHelpText,
  1032. stderr);
  1033. for (i=0; i<32; i++) {
  1034. if (GlobalFlagInfo[i].Abbreviation != NULL) {
  1035. if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
  1036. fprintf( stderr, " %s - %s\n",
  1037. GlobalFlagInfo[i].Abbreviation,
  1038. "Enable page heap");
  1039. }
  1040. else {
  1041. fprintf( stderr, " %s - %s\n",
  1042. GlobalFlagInfo[i].Abbreviation,
  1043. GlobalFlagInfo[i].Description);
  1044. }
  1045. }
  1046. }
  1047. fprintf( stderr, "\nAll images with ust enabled can be accessed in the\n" );
  1048. fprintf( stderr, "USTEnabled key under 'Image File Options'.\n" );
  1049. exit( 1 );
  1050. }
  1051. NewGlobalFlags = (OldGlobalFlags & GlobalFlagMask) | GlobalFlagSetting;
  1052. if (!fImageFileSettings || NewGlobalFlags != 0xFFFFFFFF) {
  1053. NewGlobalFlagsIgnored = ~NewGlobalFlagsValidMask & NewGlobalFlags;
  1054. NewGlobalFlags &= NewGlobalFlagsValidMask;
  1055. }
  1056. if (fDisplaySettings) {
  1057. DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
  1058. exit( 0 );
  1059. }
  1060. if (fRegistrySettings) {
  1061. SetSystemRegistryFlags( NewGlobalFlags,
  1062. fExpectingDepth ? InitialMaxStackTraceDepth : MaxDepthSetting,
  1063. 0,
  1064. SPECIAL_POOL_OVERRUNS_CHECK_FORWARD
  1065. );
  1066. DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
  1067. exit( 0 );
  1068. }
  1069. else
  1070. if (fKernelSettings) {
  1071. SetKernelModeFlags( NewGlobalFlags );
  1072. DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
  1073. exit( 0 );
  1074. }
  1075. else
  1076. if (fImageFileSettings) {
  1077. SetImageFileNameFlags( (PCHAR)ImageFileName, NewGlobalFlags );
  1078. DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
  1079. exit( 0 );
  1080. }
  1081. CreateDialog( NULL,
  1082. (LPSTR)DID_GFLAGS,
  1083. NULL,
  1084. MainWndProc
  1085. );
  1086. if (!hwndMain) {
  1087. MessageBox( hwndMain, "Main Error", "Cant create dialog", MB_OK );
  1088. ExitProcess( 0 );
  1089. }
  1090. while (GetMessage( &msg, 0, 0, 0 )) {
  1091. if (!IsDialogMessage( hwndMain, &msg )) {
  1092. DispatchMessage( &msg );
  1093. }
  1094. }
  1095. exit( 0 );
  1096. return 0;
  1097. }
  1098. VOID
  1099. SetCheckBoxesFromFlags(
  1100. DWORD GFlags,
  1101. DWORD ValidFlags
  1102. )
  1103. {
  1104. int iBit;
  1105. GFlags &= ValidFlags;
  1106. LastSetFlags = GFlags;
  1107. for (iBit=0; iBit < 32; iBit++) {
  1108. CheckDlgButton( hwndMain,
  1109. ID_FLAG_1 + iBit,
  1110. (GFlags & (1 << iBit)) ? 1 : 0
  1111. );
  1112. ShowWindow( GetDlgItem( hwndMain, ID_FLAG_1 + iBit ),
  1113. (ValidFlags & (1 << iBit)) ? SW_SHOWNORMAL : SW_HIDE
  1114. );
  1115. }
  1116. }
  1117. DWORD
  1118. GetFlagsFromCheckBoxes( VOID )
  1119. {
  1120. DWORD GFlags;
  1121. int iBit;
  1122. GFlags = 0;
  1123. for (iBit=0; iBit < 32; iBit++) {
  1124. if (IsDlgButtonChecked( hwndMain, ID_FLAG_1 + iBit )) {
  1125. GFlags |= (1 << iBit);
  1126. }
  1127. }
  1128. return GFlags;
  1129. }
  1130. VOID
  1131. DoLaunch(
  1132. PCHAR CommandLine,
  1133. DWORD GFlags
  1134. )
  1135. {
  1136. STARTUPINFO StartupInfo;
  1137. PROCESS_INFORMATION ProcessInformation;
  1138. NTSTATUS Status;
  1139. PROCESS_BASIC_INFORMATION BasicInformation;
  1140. BOOLEAN ReadImageFileExecOptions;
  1141. memset( &StartupInfo, 0, sizeof( StartupInfo ) );
  1142. StartupInfo.cb = sizeof( StartupInfo );
  1143. if (CreateProcess( NULL,
  1144. CommandLine,
  1145. NULL,
  1146. NULL,
  1147. FALSE,
  1148. CREATE_SUSPENDED,
  1149. NULL,
  1150. NULL,
  1151. &StartupInfo,
  1152. &ProcessInformation
  1153. )
  1154. ) {
  1155. Status = NtQueryInformationProcess( ProcessInformation.hProcess,
  1156. ProcessBasicInformation,
  1157. &BasicInformation,
  1158. sizeof( BasicInformation ),
  1159. NULL
  1160. );
  1161. if (NT_SUCCESS( Status )) {
  1162. ReadImageFileExecOptions = TRUE;
  1163. if (!WriteProcessMemory( ProcessInformation.hProcess,
  1164. &BasicInformation.PebBaseAddress->ReadImageFileExecOptions,
  1165. &ReadImageFileExecOptions,
  1166. sizeof( ReadImageFileExecOptions ),
  1167. NULL
  1168. ) ||
  1169. !WriteProcessMemory( ProcessInformation.hProcess,
  1170. &BasicInformation.PebBaseAddress->NtGlobalFlag,
  1171. &GFlags,
  1172. sizeof( GFlags ),
  1173. NULL
  1174. )
  1175. ) {
  1176. Status = STATUS_UNSUCCESSFUL;
  1177. }
  1178. }
  1179. if (!NT_SUCCESS( Status )) {
  1180. MessageBox( hwndMain,
  1181. "Launch Command Line",
  1182. "Unable to pass flags to process - terminating",
  1183. MB_OK
  1184. );
  1185. TerminateProcess( ProcessInformation.hProcess, 1 );
  1186. }
  1187. ResumeThread( ProcessInformation.hThread );
  1188. CloseHandle( ProcessInformation.hThread );
  1189. MsgWaitForMultipleObjects( 1,
  1190. &ProcessInformation.hProcess,
  1191. FALSE,
  1192. NMPWAIT_WAIT_FOREVER,
  1193. QS_ALLINPUT
  1194. );
  1195. CloseHandle( ProcessInformation.hProcess );
  1196. }
  1197. else {
  1198. MessageBox( hwndMain, "Launch Command Line", "Unable to create process", MB_OK );
  1199. }
  1200. return;
  1201. }
  1202. DWORD LastRadioButtonId;
  1203. DWORD SpecialPoolModeId;
  1204. DWORD SpecialPoolOverrunsId;
  1205. BOOLEAN
  1206. CheckSpecialPoolTagItem(
  1207. HWND hwnd,
  1208. BOOLEAN ForApply
  1209. )
  1210. {
  1211. DWORD NumChars;
  1212. DWORD i;
  1213. BOOLEAN IsIllegal = FALSE;
  1214. BOOLEAN IsAmbiguous = FALSE;
  1215. NumChars = GetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer, sizeof( SpecialPoolRenderBuffer ));
  1216. if (NumChars != 0) {
  1217. if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
  1218. //
  1219. // Check for illegal characters.
  1220. //
  1221. if (NumChars > 8) {
  1222. IsIllegal = TRUE;
  1223. } else {
  1224. for (i = 0; i < NumChars; i++) {
  1225. if (!((SpecialPoolRenderBuffer[i] >= '0' &&
  1226. SpecialPoolRenderBuffer[i] <= '9') ||
  1227. (SpecialPoolRenderBuffer[i] >= 'a' &&
  1228. SpecialPoolRenderBuffer[i] <= 'f') ||
  1229. (SpecialPoolRenderBuffer[i] >= 'A' &&
  1230. SpecialPoolRenderBuffer[i] <= 'F'))) {
  1231. IsIllegal = TRUE;
  1232. break;
  1233. }
  1234. }
  1235. }
  1236. } else {
  1237. //
  1238. // Check for too many characters.
  1239. //
  1240. if (NumChars > sizeof(DWORD)) {
  1241. IsIllegal = TRUE;
  1242. }
  1243. //
  1244. // We check a few more things when the user is really writing back.
  1245. //
  1246. if (!IsIllegal && ForApply) {
  1247. //
  1248. // If this is not four characters and does not end in a '*',
  1249. // it is usually the case that the user really wanted a space
  1250. // at the end of the tag 'Gh1 ', not 'Gh1'. Make sure they
  1251. // get a little feedback.
  1252. //
  1253. if (NumChars != sizeof(DWORD) && SpecialPoolRenderBuffer[NumChars - 1] != '*') {
  1254. MessageBox( hwnd,
  1255. "The specified tag is less than 4 characters, but most\n"
  1256. "are really padded out with spaces. Please check and\n"
  1257. "add spaces if neccesary.",
  1258. "Possibly ambiguous special pool tag",
  1259. MB_OK );
  1260. }
  1261. }
  1262. }
  1263. }
  1264. if (IsIllegal) {
  1265. MessageBox( hwnd, (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER ? "Must be a hexadecimal DWORD" :
  1266. "Must be at most 4 characters"),
  1267. "Illegal characters in special pool tag",
  1268. MB_OK );
  1269. }
  1270. return !IsIllegal;
  1271. }
  1272. DWORD
  1273. GetSpecialPoolTagItem(
  1274. HWND hwnd
  1275. )
  1276. {
  1277. DWORD NumChars;
  1278. DWORD Tag = 0;
  1279. //
  1280. // We assume that the field is has been retrieved and checked.
  1281. //
  1282. NumChars = strlen( SpecialPoolRenderBuffer );
  1283. if (NumChars != 0) {
  1284. if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
  1285. RtlCharToInteger( SpecialPoolRenderBuffer, 16, &Tag );
  1286. } else {
  1287. //
  1288. // Just drop the bytes into the DWORD - endianess is correct as is.
  1289. //
  1290. RtlCopyMemory( &Tag,
  1291. SpecialPoolRenderBuffer,
  1292. NumChars );
  1293. }
  1294. }
  1295. return Tag;
  1296. }
  1297. DWORD
  1298. GetSpecialPoolOverrunsItem(
  1299. HWND hwnd
  1300. )
  1301. {
  1302. switch (SpecialPoolOverrunsId) {
  1303. case ID_SPECIAL_POOL_VERIFY_END: return SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
  1304. case ID_SPECIAL_POOL_VERIFY_START: return SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD;
  1305. default: return SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
  1306. }
  1307. }
  1308. VOID
  1309. ReRenderSpecialPoolTagItem(
  1310. HWND hwnd
  1311. )
  1312. {
  1313. DWORD NumChars;
  1314. DWORD Tag = 0;
  1315. //
  1316. // We assume that the field is has been retrieved and checked.
  1317. //
  1318. NumChars = strlen( SpecialPoolRenderBuffer );
  1319. //
  1320. // Assume that the dialog contents are of the previous mode. Switch it.
  1321. //
  1322. if (NumChars != 0) {
  1323. if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
  1324. RtlCopyMemory( &Tag,
  1325. SpecialPoolRenderBuffer,
  1326. NumChars );
  1327. RtlIntegerToChar( Tag, 16, sizeof( SpecialPoolRenderBuffer ), SpecialPoolRenderBuffer);
  1328. } else {
  1329. RtlCharToInteger( SpecialPoolRenderBuffer, 16, &Tag );
  1330. RtlCopyMemory( SpecialPoolRenderBuffer,
  1331. &Tag,
  1332. sizeof( Tag ));
  1333. SpecialPoolRenderBuffer[sizeof( Tag )] = '\0';
  1334. }
  1335. }
  1336. SetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer );
  1337. }
  1338. BOOLEAN
  1339. CheckForUnsaved(
  1340. HWND hwnd
  1341. )
  1342. {
  1343. BOOL b;
  1344. //
  1345. // Appropriate to the mode we are leaving, see if there were unsaved changes.
  1346. // Return TRUE if there are unsaved changes.
  1347. //
  1348. if (GetFlagsFromCheckBoxes() != LastSetFlags ||
  1349. (fFlushImageSettings && (LastRadioButtonId == ID_IMAGE_FILE_OPTIONS)) ||
  1350. (LastRadioButtonId == ID_SYSTEM_REGISTRY &&
  1351. (!CheckSpecialPoolTagItem( hwnd, FALSE ) ||
  1352. (GetSpecialPoolTagItem( hwnd ) != LastSetSpecialPoolTag) ||
  1353. (GetSpecialPoolOverrunsItem( hwnd ) != LastSetSpecialPoolOverruns)) ||
  1354. GetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, &b, FALSE ) != InitialMaxStackTraceDepth)) {
  1355. if (MessageBox( hwndMain,
  1356. "You didn't click 'apply' - did you want to discard current changes??",
  1357. "Warning",
  1358. MB_YESNO
  1359. ) == IDNO
  1360. ) {
  1361. return TRUE;
  1362. }
  1363. }
  1364. return FALSE;
  1365. }
  1366. INT_PTR
  1367. APIENTRY
  1368. MainWndProc(
  1369. HWND hwnd,
  1370. UINT message,
  1371. WPARAM wParam,
  1372. LPARAM lParam
  1373. )
  1374. {
  1375. DWORD NewFlags;
  1376. CHAR ImageFileName[ MAX_PATH ];
  1377. CHAR CommandLine[ MAX_PATH ];
  1378. BOOL b, bCancelDiscard;
  1379. int i;
  1380. bCancelDiscard = FALSE;
  1381. switch (message) {
  1382. case WM_INITDIALOG:
  1383. hwndMain = hwnd;
  1384. LastRadioButtonId = ID_SYSTEM_REGISTRY;
  1385. CheckRadioButton( hwnd,
  1386. ID_SYSTEM_REGISTRY,
  1387. ID_IMAGE_FILE_OPTIONS,
  1388. LastRadioButtonId
  1389. );
  1390. EnableSetOfControls( hwnd, SpecialPool, TRUE );
  1391. EnableSetOfControls( hwnd, Debugger, FALSE );
  1392. SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
  1393. SetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, InitialMaxStackTraceDepth, FALSE );
  1394. //
  1395. // Make a not so wild guess about what kind of tag it is.
  1396. //
  1397. if (LastSetSpecialPoolTag && LastSetSpecialPoolTag < 0x2000) {
  1398. SpecialPoolModeId = ID_SPECIAL_POOL_IS_NUMBER;
  1399. RtlIntegerToChar( LastSetSpecialPoolTag,
  1400. 16,
  1401. sizeof( SpecialPoolRenderBuffer ),
  1402. SpecialPoolRenderBuffer );
  1403. }
  1404. else {
  1405. SpecialPoolModeId = ID_SPECIAL_POOL_IS_TEXT;
  1406. RtlCopyMemory( SpecialPoolRenderBuffer,
  1407. &LastSetSpecialPoolTag,
  1408. sizeof( LastSetSpecialPoolTag ));
  1409. SpecialPoolRenderBuffer[sizeof(LastSetSpecialPoolTag)] = '\0';
  1410. }
  1411. CheckRadioButton( hwnd,
  1412. ID_SPECIAL_POOL_IS_TEXT,
  1413. ID_SPECIAL_POOL_IS_NUMBER,
  1414. SpecialPoolModeId
  1415. );
  1416. SetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer );
  1417. //
  1418. // Initial state for the special pool overrun radio buttons.
  1419. //
  1420. switch (LastSetSpecialPoolOverruns) {
  1421. case SPECIAL_POOL_OVERRUNS_CHECK_FORWARD:
  1422. SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_END;
  1423. break;
  1424. case SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD:
  1425. SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_START;
  1426. break;
  1427. default:
  1428. SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_END;
  1429. break;
  1430. }
  1431. CheckRadioButton( hwnd,
  1432. ID_SPECIAL_POOL_VERIFY_START,
  1433. ID_SPECIAL_POOL_VERIFY_END,
  1434. SpecialPoolOverrunsId
  1435. );
  1436. return(TRUE);
  1437. case WM_COMMAND:
  1438. switch ( LOWORD(wParam) ) {
  1439. case ID_LAUNCH:
  1440. GetDlgItemText( hwnd, ID_COMMAND_LINE, CommandLine, sizeof( CommandLine ) );
  1441. if (strlen( ImageFileName ) == 0) {
  1442. MessageBox( hwndMain, "Launch Command Line", "Must fill in command line first", MB_OK );
  1443. SetFocus( GetDlgItem( hwnd, ID_COMMAND_LINE ) );
  1444. break;
  1445. }
  1446. // fall through
  1447. case ID_APPLY:
  1448. if (IsDlgButtonChecked( hwnd, ID_SYSTEM_REGISTRY )) {
  1449. //
  1450. // System wide settings
  1451. //
  1452. if (CheckSpecialPoolTagItem( hwnd, TRUE )) {
  1453. NewFlags = GetFlagsFromCheckBoxes();
  1454. SetSystemRegistryFlags(
  1455. NewFlags,
  1456. GetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, &b, FALSE ),
  1457. GetSpecialPoolTagItem( hwnd ),
  1458. GetSpecialPoolOverrunsItem (hwnd));
  1459. }
  1460. }
  1461. else if (IsDlgButtonChecked( hwnd, ID_KERNEL_MODE )) {
  1462. //
  1463. // Kernel mode settings
  1464. //
  1465. // N.B. This will set flags on the fly. It does not touch
  1466. // the registry and does not require a reboot.
  1467. //
  1468. NewFlags = GetFlagsFromCheckBoxes();
  1469. SetKernelModeFlags( NewFlags );
  1470. }
  1471. else if (IsDlgButtonChecked( hwnd, ID_IMAGE_FILE_OPTIONS )) {
  1472. //
  1473. // Application specific settings
  1474. //
  1475. GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
  1476. if (strlen( ImageFileName ) == 0) {
  1477. MessageBox( hwnd, "Missing Image File Name", "Must set image file name", MB_OK );
  1478. SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
  1479. break;
  1480. }
  1481. SetImageFileNameFlags( ImageFileName, GetFlagsFromCheckBoxes() );
  1482. if ( fFlushImageSettings ) {
  1483. GetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, LastDebuggerValue, MAX_PATH );
  1484. SetImageFileNameDebugger( ImageFileName, LastDebuggerValue );
  1485. fFlushImageSettings = FALSE ;
  1486. }
  1487. }
  1488. if (LOWORD(wParam) == ID_LAUNCH) {
  1489. DoLaunch( CommandLine,
  1490. GetFlagsFromCheckBoxes()
  1491. );
  1492. }
  1493. break;
  1494. case IDOK:
  1495. if (CheckForUnsaved( hwnd )) {
  1496. break;
  1497. }
  1498. // fall through
  1499. case IDCANCEL:
  1500. PostQuitMessage(0);
  1501. DestroyWindow( hwnd );
  1502. break;
  1503. case ID_SPECIAL_POOL_IS_TEXT:
  1504. case ID_SPECIAL_POOL_IS_NUMBER:
  1505. if (CheckSpecialPoolTagItem( hwnd, FALSE )) {
  1506. if (LOWORD(wParam) != SpecialPoolModeId) {
  1507. SpecialPoolModeId = LOWORD(wParam);
  1508. CheckRadioButton( hwnd,
  1509. ID_SPECIAL_POOL_IS_TEXT,
  1510. ID_SPECIAL_POOL_IS_NUMBER,
  1511. SpecialPoolModeId
  1512. );
  1513. ReRenderSpecialPoolTagItem( hwnd );
  1514. }
  1515. }
  1516. else {
  1517. //
  1518. // Always treat this as a cancel.
  1519. //
  1520. bCancelDiscard = TRUE;
  1521. }
  1522. break;
  1523. case ID_SPECIAL_POOL_VERIFY_START:
  1524. case ID_SPECIAL_POOL_VERIFY_END:
  1525. if (LOWORD(wParam) != SpecialPoolOverrunsId) {
  1526. SpecialPoolOverrunsId = LOWORD(wParam);
  1527. CheckRadioButton( hwnd,
  1528. ID_SPECIAL_POOL_VERIFY_START,
  1529. ID_SPECIAL_POOL_VERIFY_END,
  1530. SpecialPoolOverrunsId
  1531. );
  1532. }
  1533. break;
  1534. case ID_IMAGE_DEBUGGER_BUTTON:
  1535. if (IsDlgButtonChecked( hwnd, ID_IMAGE_DEBUGGER_BUTTON ) == BST_CHECKED ) {
  1536. EnableWindow( GetDlgItem( hwnd, ID_IMAGE_DEBUGGER_VALUE ), TRUE );
  1537. GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, MAX_PATH );
  1538. for ( i = 0 ; i < sizeof( SystemProcesses ) / sizeof( PCHAR ) ; i++ ) {
  1539. if (_stricmp( ImageFileName, SystemProcesses[i] ) == 0 ) {
  1540. SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, "ntsd -d -g -G" );
  1541. break;
  1542. }
  1543. }
  1544. }
  1545. else {
  1546. SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, "" );
  1547. EnableWindow( GetDlgItem( hwnd, ID_IMAGE_DEBUGGER_VALUE ), FALSE );
  1548. }
  1549. fFlushImageSettings = TRUE ;
  1550. break;
  1551. case ID_SYSTEM_REGISTRY:
  1552. if (CheckForUnsaved( hwnd )) {
  1553. bCancelDiscard = TRUE;
  1554. break;
  1555. }
  1556. LastRadioButtonId = ID_SYSTEM_REGISTRY;
  1557. SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
  1558. EnableSetOfControls( hwnd, SpecialPool, TRUE );
  1559. EnableSetOfControls( hwnd, Debugger, FALSE );
  1560. break;
  1561. case ID_KERNEL_MODE:
  1562. if (CheckForUnsaved( hwnd )) {
  1563. bCancelDiscard = TRUE;
  1564. break;
  1565. }
  1566. LastRadioButtonId = ID_KERNEL_MODE;
  1567. SetCheckBoxesFromFlags( GetKernelModeFlags(), VALID_KERNEL_MODE_FLAGS );
  1568. EnableSetOfControls( hwnd, SpecialPool, FALSE );
  1569. EnableSetOfControls( hwnd, Debugger, FALSE );
  1570. break;
  1571. case ID_IMAGE_FILE_OPTIONS:
  1572. if (CheckForUnsaved( hwnd )) {
  1573. bCancelDiscard = TRUE;
  1574. break;
  1575. }
  1576. GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
  1577. if (strlen( ImageFileName ) == 0) {
  1578. MessageBox( hwndMain, "Image File Name Missing", "Must fill in image file name first", MB_OK );
  1579. CheckRadioButton( hwnd,
  1580. ID_SYSTEM_REGISTRY,
  1581. ID_IMAGE_FILE_OPTIONS,
  1582. LastRadioButtonId
  1583. );
  1584. SetCheckBoxesFromFlags( GetSystemRegistryFlags(), VALID_SYSTEM_REGISTRY_FLAGS );
  1585. SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
  1586. break;
  1587. }
  1588. else {
  1589. LastRadioButtonId = ID_IMAGE_FILE_OPTIONS;
  1590. SetCheckBoxesFromFlags( GetImageFileNameFlags( ImageFileName ),
  1591. VALID_IMAGE_FILE_NAME_FLAGS
  1592. );
  1593. if ( GetImageFileNameDebugger( ImageFileName, LastDebuggerValue ) ) {
  1594. SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, LastDebuggerValue );
  1595. CheckDlgButton( hwnd, ID_IMAGE_DEBUGGER_BUTTON, 1 );
  1596. }
  1597. EnableSetOfControls( hwnd, SpecialPool, FALSE );
  1598. EnableSetOfControls( hwnd, Debugger, TRUE );
  1599. }
  1600. break;
  1601. default:
  1602. break;
  1603. }
  1604. break;
  1605. case WM_CLOSE:
  1606. PostQuitMessage(0);
  1607. DestroyWindow( hwnd );
  1608. break;
  1609. }
  1610. if (bCancelDiscard) {
  1611. //
  1612. // Recheck the right radio buttons 'cause the user didn't
  1613. // *really* mean it.
  1614. //
  1615. CheckRadioButton( hwnd,
  1616. ID_SYSTEM_REGISTRY,
  1617. ID_IMAGE_FILE_OPTIONS,
  1618. LastRadioButtonId
  1619. );
  1620. CheckRadioButton( hwnd,
  1621. ID_SPECIAL_POOL_IS_TEXT,
  1622. ID_SPECIAL_POOL_IS_NUMBER,
  1623. SpecialPoolModeId
  1624. );
  1625. CheckRadioButton( hwnd,
  1626. ID_SPECIAL_POOL_VERIFY_START,
  1627. ID_SPECIAL_POOL_VERIFY_END,
  1628. SpecialPoolOverrunsId
  1629. );
  1630. }
  1631. return 0;
  1632. }
  1633. BOOL
  1634. EnableDebugPrivilege( VOID )
  1635. {
  1636. HANDLE Token;
  1637. PTOKEN_PRIVILEGES NewPrivileges;
  1638. BYTE OldPriv[ 1024 ];
  1639. PBYTE pbOldPriv;
  1640. ULONG cbNeeded;
  1641. BOOL fRc;
  1642. LUID LuidPrivilege;
  1643. //
  1644. // Make sure we have access to adjust and to get the old token privileges
  1645. //
  1646. if (!OpenProcessToken( GetCurrentProcess(),
  1647. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1648. &Token
  1649. )
  1650. ) {
  1651. return FALSE;
  1652. }
  1653. cbNeeded = 0;
  1654. //
  1655. // Initialize the privilege adjustment structure
  1656. //
  1657. LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege );
  1658. NewPrivileges = (PTOKEN_PRIVILEGES)HeapAlloc( GetProcessHeap(), 0,
  1659. sizeof(TOKEN_PRIVILEGES) +
  1660. (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)
  1661. );
  1662. if (NewPrivileges == NULL) {
  1663. CloseHandle( Token );
  1664. return FALSE;
  1665. }
  1666. NewPrivileges->PrivilegeCount = 1;
  1667. NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  1668. NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1669. //
  1670. // Enable the privilege
  1671. //
  1672. pbOldPriv = OldPriv;
  1673. fRc = AdjustTokenPrivileges( Token,
  1674. FALSE,
  1675. NewPrivileges,
  1676. sizeof( OldPriv ),
  1677. (PTOKEN_PRIVILEGES)pbOldPriv,
  1678. &cbNeeded
  1679. );
  1680. if (!fRc) {
  1681. //
  1682. // If the stack was too small to hold the privileges
  1683. // then allocate off the heap
  1684. //
  1685. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  1686. pbOldPriv = (PBYTE)HeapAlloc( GetProcessHeap(), 0, cbNeeded );
  1687. if (pbOldPriv == NULL) {
  1688. CloseHandle( Token );
  1689. return FALSE;
  1690. }
  1691. fRc = AdjustTokenPrivileges( Token,
  1692. FALSE,
  1693. NewPrivileges,
  1694. cbNeeded,
  1695. (PTOKEN_PRIVILEGES)pbOldPriv,
  1696. &cbNeeded
  1697. );
  1698. }
  1699. }
  1700. return fRc;
  1701. }
  1702. VOID
  1703. CenterDialog( HWND hWndDialog )
  1704. {
  1705. RECT rectWindow;
  1706. POINT pointCenter;
  1707. POINT pointNewCornerChild;
  1708. INT nChildWidth;
  1709. INT nChildHeight;
  1710. HWND hWndParent;
  1711. hWndParent = GetParent( hWndDialog );
  1712. //
  1713. // parent window's rectangle
  1714. //
  1715. GetWindowRect( hWndParent, &rectWindow );
  1716. //
  1717. // the center, in screen coordinates
  1718. //
  1719. pointCenter.x = rectWindow.left + ( rectWindow.right - rectWindow.left ) / 2;
  1720. pointCenter.y = rectWindow.top + ( rectWindow.bottom - rectWindow.top ) / 2;
  1721. //
  1722. // chils window's rectangle, in screen coordinates
  1723. //
  1724. GetWindowRect( hWndDialog, &rectWindow );
  1725. nChildWidth = rectWindow.right - rectWindow.left ;
  1726. nChildHeight = rectWindow.bottom - rectWindow.top;
  1727. //
  1728. // the new top-left corner of the child
  1729. //
  1730. pointNewCornerChild.x = pointCenter.x - nChildWidth / 2;
  1731. pointNewCornerChild.y = pointCenter.y - nChildHeight / 2;
  1732. //
  1733. // move the child window
  1734. //
  1735. MoveWindow(
  1736. hWndDialog,
  1737. pointNewCornerChild.x,
  1738. pointNewCornerChild.y,
  1739. nChildWidth,
  1740. nChildHeight,
  1741. TRUE );
  1742. }
  1743. INT_PTR
  1744. APIENTRY
  1745. PagedHeapDlgProc(
  1746. HWND hwnd,
  1747. UINT message,
  1748. WPARAM wParam,
  1749. LPARAM lParam
  1750. )
  1751. {
  1752. INT_PTR nResult;
  1753. nResult = FALSE;
  1754. switch ( message ) {
  1755. case WM_INITDIALOG:
  1756. hwndPagedHeapDlg = hwnd;
  1757. //
  1758. // center this dialog
  1759. //
  1760. CenterDialog( hwndPagedHeapDlg );
  1761. break;
  1762. case WM_COMMAND:
  1763. switch( LOWORD(wParam) ) {
  1764. case IDYES:
  1765. EndDialog( hwndPagedHeapDlg, IDYES );
  1766. break;
  1767. case IDNO:
  1768. EndDialog( hwndPagedHeapDlg, IDNO );
  1769. break;
  1770. }
  1771. break;
  1772. case WM_CLOSE:
  1773. case WM_DESTROY:
  1774. case WM_ENDSESSION:
  1775. case WM_QUIT:
  1776. EndDialog(hwndPagedHeapDlg,IDNO);
  1777. nResult = TRUE;
  1778. break;
  1779. default:
  1780. break;
  1781. }
  1782. return nResult;
  1783. }
  1784. BOOL
  1785. OkToEnablePagedHeap( VOID )
  1786. {
  1787. MEMORYSTATUS MemoryStatus;
  1788. GlobalMemoryStatus( &MemoryStatus );
  1789. if( MemoryStatus.dwTotalPhys < 512 * 1024 * 1024 ) {
  1790. //
  1791. // less than 512 Mb of RAM
  1792. //
  1793. return ( DialogBoxParam(
  1794. NULL,
  1795. (LPCTSTR)( MAKEINTRESOURCE(DID_PAGED_HEAP_WARNING) ),
  1796. hwndMain,
  1797. PagedHeapDlgProc,
  1798. 0 ) == IDYES );
  1799. }
  1800. return TRUE;
  1801. }
  1802. BOOL
  1803. GflagsSetTraceDatabaseSize (
  1804. PCHAR ApplicationName,
  1805. ULONG SizeInMb,
  1806. PULONG RealSize
  1807. )
  1808. {
  1809. HKEY ImageKey;
  1810. CHAR ImageKeyName[ MAX_PATH ];
  1811. LONG Result;
  1812. CHAR Buffer[ MAX_PATH ];
  1813. DWORD Length = MAX_PATH;
  1814. DWORD TraceDatabaseSize;
  1815. *RealSize = 0;
  1816. if (ApplicationName == NULL) {
  1817. return FALSE;
  1818. }
  1819. sprintf (ImageKeyName,
  1820. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
  1821. ApplicationName);
  1822. Result = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1823. ImageKeyName,
  1824. 0,
  1825. KEY_QUERY_VALUE | KEY_SET_VALUE,
  1826. &ImageKey);
  1827. if (Result != ERROR_SUCCESS) {
  1828. return FALSE;
  1829. }
  1830. if (SizeInMb == 0) {
  1831. Result = RegDeleteValue (ImageKey,
  1832. "StackTraceDatabaseSizeInMb");
  1833. if (Result != ERROR_SUCCESS) {
  1834. RegCloseKey (ImageKey);
  1835. return FALSE;
  1836. }
  1837. }
  1838. else {
  1839. if (SizeInMb < 8) {
  1840. TraceDatabaseSize = 8;
  1841. }
  1842. else {
  1843. TraceDatabaseSize = SizeInMb;
  1844. }
  1845. Result = RegSetValueEx (ImageKey,
  1846. "StackTraceDatabaseSizeInMb",
  1847. 0,
  1848. REG_DWORD,
  1849. (PBYTE)(&TraceDatabaseSize),
  1850. sizeof TraceDatabaseSize);
  1851. if (Result != ERROR_SUCCESS) {
  1852. RegCloseKey (ImageKey);
  1853. return FALSE;
  1854. }
  1855. *RealSize = TraceDatabaseSize;
  1856. }
  1857. RegCloseKey (ImageKey);
  1858. return TRUE;
  1859. }