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.

2333 lines
69 KiB

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