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.

956 lines
20 KiB

  1. //
  2. // Application verifier manager (command line version)
  3. // Copyright (c) Microsoft Corporation, 2001
  4. //
  5. //
  6. // module: avrf.cxx
  7. // author: silviuc
  8. // created: 02/14/2001
  9. //
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stdarg.h>
  13. #include <malloc.h>
  14. #include <tchar.h>
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <common.ver>
  20. LPTSTR HelpText =
  21. TEXT("avrf - Application verifier settings --") BUILD_MACHINE_TAG TEXT("\n")
  22. VER_LEGALCOPYRIGHT_STR TEXT("\n")
  23. TEXT(" \n")
  24. TEXT("avrf [OPTION ...] \n")
  25. TEXT(" \n")
  26. TEXT(" /enable PROGRAM Enable verifier with default settings. \n")
  27. TEXT(" /disable PROGRAM Disable verifier. \n")
  28. TEXT(" \n")
  29. TEXT(" /pageheap Enable full page heap (default). \n")
  30. TEXT(" /lightheap Enable light page heap. \n")
  31. TEXT(" /locks Enable critical section verifier (default). \n")
  32. TEXT(" /nolocks Disable critical section verifier. \n")
  33. TEXT(" /handles Enable handle checking and tracking (default). \n")
  34. TEXT(" /nohandles Disable handle checking. \n")
  35. TEXT(" /stacks Stack overflow in low memory conditions checks.\n")
  36. TEXT(" /nostacks Disable stack overflow checks (default). \n")
  37. TEXT(" \n")
  38. TEXT(" /debug Launch under debugger `ntsd -g -G -x'. \n")
  39. TEXT(" /kdebug Launch under debugger `ntsd -g -G -d -x'. \n")
  40. TEXT(" \n")
  41. TEXT(" /verifier DLL ... Specify additional verifier providers. \n")
  42. TEXT(" \n")
  43. TEXT("PROGRAM Name of the binary with extension (.exe or something else).\n")
  44. TEXT("DLL Name of the binary with extension (.dll or something else).\n")
  45. TEXT(" \n")
  46. TEXT("If no option specified the program will print all verifier enabled \n")
  47. TEXT("applications and their specific options. \n")
  48. TEXT(" \n")
  49. TEXT("The /verifier option is useful whenever additional verification layers \n")
  50. TEXT("must run on top of the core verification layer. The dlls specified \n")
  51. TEXT("must obey the format for a verifier provider dll. \n")
  52. TEXT(" \n")
  53. TEXT("Note. Enabling application verifier does not affect currently running \n")
  54. TEXT("processes. If you need to use verifier for processes that are \n")
  55. TEXT("already running and cannot be restarted (csrss.exe, winlogon.exe), \n")
  56. TEXT("a reboot is needed after the verifier has been enabled for \n")
  57. TEXT("that process. \n")
  58. TEXT(" \n");
  59. VOID
  60. Help (
  61. )
  62. {
  63. _tprintf (HelpText);
  64. exit(1);
  65. }
  66. VOID
  67. PrintFlags (
  68. DWORD Flags
  69. )
  70. {
  71. if ((Flags & RTL_VRF_FLG_FULL_PAGE_HEAP)) {
  72. printf("pageheap ");
  73. }
  74. else {
  75. printf("lightheap ");
  76. }
  77. if ((Flags & RTL_VRF_FLG_LOCK_CHECKS)) {
  78. printf("locks ");
  79. }
  80. if ((Flags & RTL_VRF_FLG_HANDLE_CHECKS)) {
  81. printf("handles ");
  82. }
  83. if ((Flags & RTL_VRF_FLG_STACK_CHECKS)) {
  84. printf("stacks ");
  85. }
  86. }
  87. BOOL
  88. EnableVerifier (
  89. LPCTSTR Name,
  90. LPTSTR DebugString,
  91. char * * Args);
  92. BOOL
  93. DisableVerifier (
  94. LPCTSTR Name);
  95. BOOL
  96. IsVerifierEnabled (
  97. LPCTSTR Name);
  98. BOOL
  99. IsVerifierFlagsValueDefined (
  100. LPCTSTR Name,
  101. PDWORD Value);
  102. BOOL
  103. ReadGlobalFlagValue (
  104. HKEY Key,
  105. LPTSTR Buffer,
  106. ULONG Length);
  107. BOOL
  108. WriteGlobalFlagValue (
  109. HKEY Key,
  110. LPTSTR Buffer,
  111. ULONG Length);
  112. BOOL
  113. ReadVerifierValue (
  114. HKEY Key,
  115. LPTSTR Name,
  116. PDWORD Value
  117. );
  118. BOOL
  119. WriteVerifierValue (
  120. HKEY Key,
  121. LPTSTR Name,
  122. DWORD Value
  123. );
  124. BOOL
  125. DeleteVerifierFlagValue (
  126. HKEY Key);
  127. BOOL
  128. WriteDebuggerValue (
  129. HKEY Key,
  130. LPTSTR Buffer,
  131. ULONG Length);
  132. BOOL
  133. DeleteDebuggerValue (
  134. HKEY Key);
  135. HKEY
  136. OpenImageKey (
  137. LPCTSTR Name,
  138. BOOL ShouldExist);
  139. VOID
  140. CloseImageKey (
  141. HKEY Key);
  142. VOID
  143. CreateImageName (
  144. LPCTSTR Source,
  145. LPTSTR Name,
  146. ULONG Length);
  147. VOID
  148. PrintVerifierEnabledApplications (
  149. );
  150. VOID
  151. Help (
  152. );
  153. VOID
  154. __cdecl
  155. Error (
  156. LPCTSTR Format,
  157. ...);
  158. BOOL
  159. IsWow64Active (
  160. );
  161. //////////////////////////////////////////////////////////////////////
  162. //////////////////////////////////////////////////////////////////////
  163. //////////////////////////////////////////////////////////////////////
  164. char * *
  165. SearchOption (
  166. char * Args[],
  167. char * Option
  168. )
  169. {
  170. while (*Args) {
  171. if (_stricmp(*Args, Option) == 0) {
  172. return Args;
  173. }
  174. Args++;
  175. }
  176. return NULL;
  177. }
  178. void _cdecl
  179. main (int argc, char *argv[])
  180. {
  181. TCHAR ImageName [MAX_PATH];
  182. char * * Option;
  183. if (IsWow64Active()) {
  184. _tprintf (TEXT ("Warning: avrf.exe is running inside WOW64. \n"
  185. "This scenario can be used to test x86 binaries (running inside WOW64) \n"
  186. "but not native (IA64) binaries. \n\n"));
  187. }
  188. if (argc == 2 && strstr (argv[1], TEXT("?")) != NULL) {
  189. Help ();
  190. }
  191. else if ((Option = SearchOption(argv + 1, "/enable"))) {
  192. PCHAR DebugString = NULL;
  193. if (SearchOption (argv + 1, "/debug") != NULL) {
  194. DebugString = "ntsd -g -G -x";
  195. }
  196. if (SearchOption (argv + 1, "/kdebug") != NULL) {
  197. DebugString = "ntsd -g -G -d -x";
  198. }
  199. if (Option[1] && Option[1][0] != '/') {
  200. CreateImageName (Option[1], ImageName, MAX_PATH);
  201. EnableVerifier (ImageName, DebugString, argv);
  202. }
  203. else {
  204. Help();
  205. }
  206. }
  207. else if ((Option = SearchOption(argv + 1, "/disable"))) {
  208. if (Option[1]) {
  209. CreateImageName (Option[1], ImageName, MAX_PATH);
  210. DisableVerifier (ImageName);
  211. }
  212. else {
  213. Help();
  214. }
  215. }
  216. else if (argc == 2) {
  217. CreateImageName (argv[1], ImageName, MAX_PATH);
  218. if (IsVerifierEnabled (ImageName) == FALSE) {
  219. _tprintf (TEXT("%s: verifier is not enabled for this application \n"), argv[1]);
  220. }
  221. else {
  222. DWORD Value;
  223. if (IsVerifierFlagsValueDefined (ImageName, &Value)) {
  224. _tprintf (TEXT("%s: verifier enabled with flags ("), argv[1]);
  225. PrintFlags (Value);
  226. _tprintf (TEXT(")\n"));
  227. }
  228. else {
  229. _tprintf (TEXT("%s: verifier enabled with default flags \n"), argv[1]);
  230. }
  231. }
  232. }
  233. else {
  234. PrintVerifierEnabledApplications ();
  235. }
  236. }
  237. VOID
  238. __cdecl
  239. Error (
  240. LPCTSTR Format,
  241. ...)
  242. {
  243. va_list Params;
  244. va_start (Params, Format);
  245. _tprintf (TEXT("Error: "));
  246. _vtprintf (Format, Params);
  247. _tprintf ( TEXT("\n "));
  248. exit (1);
  249. }
  250. //////////////////////////////////////////////////////////////////////
  251. //////////////////////////////////////////////////////////////////////
  252. //////////////////////////////////////////////////////////////////////
  253. BOOL
  254. IsVerifierEnabled (
  255. LPCTSTR Name)
  256. {
  257. HKEY Key;
  258. TCHAR Buffer [128];
  259. DWORD Flags;
  260. if ((Key = OpenImageKey (Name, TRUE)) == NULL) {
  261. return FALSE;
  262. }
  263. if (ReadGlobalFlagValue (Key, Buffer, sizeof Buffer) == FALSE) {
  264. return FALSE;
  265. }
  266. if (_stscanf (Buffer, TEXT("%x"), &Flags) == 0) {
  267. return FALSE;
  268. }
  269. CloseImageKey (Key);
  270. return (Flags & FLG_APPLICATION_VERIFIER) ? TRUE : FALSE;
  271. }
  272. BOOL
  273. IsVerifierFlagsValueDefined (
  274. LPCTSTR Name,
  275. PDWORD Value)
  276. {
  277. HKEY Key;
  278. DWORD VerifierFlags = 0;
  279. if ((Key = OpenImageKey (Name, TRUE)) == NULL) {
  280. return FALSE;
  281. }
  282. if (ReadVerifierValue (Key, TEXT("VerifierFlags"), &VerifierFlags) == FALSE) {
  283. return FALSE;
  284. }
  285. CloseImageKey (Key);
  286. *Value = VerifierFlags;
  287. return TRUE;
  288. }
  289. BOOL
  290. EnableVerifier (
  291. LPCTSTR Name,
  292. LPTSTR DebugString,
  293. char * * Args
  294. )
  295. {
  296. HKEY Key;
  297. TCHAR Buffer [128];
  298. DWORD Flags;
  299. DWORD VerifierFlags;
  300. char * * Option;
  301. LONG Result;
  302. if ((Key = OpenImageKey (Name, FALSE)) == NULL) {
  303. Error (TEXT("Cannot open image registry key for %s"), Name);
  304. }
  305. if (ReadGlobalFlagValue (Key, Buffer, sizeof Buffer) == FALSE) {
  306. Flags = 0;
  307. }
  308. else {
  309. _stscanf (Buffer, TEXT("%x"), &Flags);
  310. }
  311. Flags |= FLG_APPLICATION_VERIFIER;
  312. _stprintf (Buffer, TEXT("0x%08X"), Flags);
  313. if (WriteGlobalFlagValue (Key, Buffer, _tcslen(Buffer)) == FALSE) {
  314. return FALSE;
  315. }
  316. //
  317. // Write `Debugger' value if needed.
  318. //
  319. if (DebugString != NULL) {
  320. if (WriteDebuggerValue (Key, DebugString, _tcslen(DebugString)) == FALSE) {
  321. return FALSE;
  322. }
  323. }
  324. //
  325. // Fill out default verifier settings.
  326. //
  327. VerifierFlags = RTL_VRF_FLG_FULL_PAGE_HEAP
  328. | RTL_VRF_FLG_LOCK_CHECKS
  329. | RTL_VRF_FLG_HANDLE_CHECKS;
  330. //
  331. // Check for explicit feature requests.
  332. //
  333. if ((Option = SearchOption (Args, "/pageheap")) != NULL) {
  334. VerifierFlags |= RTL_VRF_FLG_FULL_PAGE_HEAP;
  335. }
  336. if ((Option = SearchOption (Args, "/lightheap")) != NULL) {
  337. VerifierFlags &= ~RTL_VRF_FLG_FULL_PAGE_HEAP;
  338. }
  339. if ((Option = SearchOption (Args, "/locks")) != NULL) {
  340. VerifierFlags |= RTL_VRF_FLG_LOCK_CHECKS;
  341. }
  342. if ((Option = SearchOption (Args, "/nolocks")) != NULL) {
  343. VerifierFlags &= ~RTL_VRF_FLG_LOCK_CHECKS;
  344. }
  345. if ((Option = SearchOption (Args, "/handles")) != NULL) {
  346. VerifierFlags |= RTL_VRF_FLG_HANDLE_CHECKS;
  347. }
  348. if ((Option = SearchOption (Args, "/nohandles")) != NULL) {
  349. VerifierFlags &= ~RTL_VRF_FLG_HANDLE_CHECKS;
  350. }
  351. if ((Option = SearchOption (Args, "/stacks")) != NULL) {
  352. VerifierFlags |= RTL_VRF_FLG_STACK_CHECKS;
  353. }
  354. if ((Option = SearchOption (Args, "/nostacks")) != NULL) {
  355. VerifierFlags &= ~RTL_VRF_FLG_STACK_CHECKS;
  356. }
  357. if ((Option = SearchOption (Args, "/_debug")) != NULL) {
  358. DWORD DebugFlags = 0;
  359. if (Option[1] && Option[1][0] != '/') {
  360. printf("Setting _debug to %s \n", Option[1]);
  361. if (_stscanf (Option[1], TEXT("%x"), &DebugFlags) == 0) {
  362. Error (TEXT("Failed to set internal debug flags."));
  363. }
  364. if (WriteVerifierValue (Key, TEXT("VerifierDebug"), DebugFlags) == FALSE) {
  365. Error (TEXT("Failed to write verifier internal debug registry value."));
  366. }
  367. }
  368. }
  369. //
  370. // Check /dlls option
  371. //
  372. Option = SearchOption (Args, "/verifier");
  373. if (Option != NULL) {
  374. TCHAR Dlls[512];
  375. ULONG Index;
  376. if (Option[1]) {
  377. for (Index = 1, Dlls[0] = '\0';
  378. Option[Index] && Option[Index][0] != '/';
  379. Index++) {
  380. _tcscat (Dlls, Option[Index]);
  381. _tcscat (Dlls, " ");
  382. //
  383. // We do not allow more than 200 characters because the verifier
  384. // support in loader (\nt\base\ntdll\verifier.c) does not handle
  385. // more characters anyway.
  386. //
  387. if (_tcslen (Dlls) > 200) {
  388. break;
  389. }
  390. }
  391. //
  392. // SilviuC: the call to _tcslen below is not correct if we
  393. // ever will want to make this program Unicode.
  394. //
  395. Result = RegSetValueEx (
  396. Key, TEXT ("VerifierDlls"), 0, REG_SZ,
  397. (LPBYTE)(Dlls), _tcslen(Dlls) + 1);
  398. if (Result) {
  399. Error (TEXT("Failed to write VerifierDlls value: error %u"), Result);
  400. }
  401. }
  402. }
  403. //
  404. // Finally write the verifier flags value.
  405. //
  406. if (WriteVerifierValue (Key, TEXT("VerifierFlags"), VerifierFlags) == FALSE) {
  407. Error (TEXT("Failed to write VerifierFlags value."));
  408. return FALSE;
  409. }
  410. CloseImageKey (Key);
  411. return TRUE;
  412. }
  413. BOOL
  414. DisableVerifier (
  415. LPCTSTR Name)
  416. {
  417. HKEY Key;
  418. TCHAR Buffer [128];
  419. DWORD Flags;
  420. if ((Key = OpenImageKey (Name, TRUE)) == NULL) {
  421. //
  422. // There is no key therefore nothing to disable.
  423. //
  424. return TRUE;
  425. }
  426. if (ReadGlobalFlagValue (Key, Buffer, sizeof Buffer) == FALSE) {
  427. Flags = 0;
  428. }
  429. else {
  430. if (_stscanf (Buffer, TEXT("%x"), &Flags) == 0) {
  431. Flags = 0;;
  432. }
  433. }
  434. Flags &= ~FLG_APPLICATION_VERIFIER;
  435. _stprintf (Buffer, TEXT("0x%08X"), Flags);
  436. //
  437. // If by wiping the verifier bit from `GlobalFlags' we get a zero
  438. // value we will wipe out the value altogether. This is important
  439. // when we run the app under debugger. In this case it makes a
  440. // difference if the value is not there or is all zeroes.
  441. //
  442. if (Flags != 0) {
  443. if (WriteGlobalFlagValue (Key, Buffer, _tcslen(Buffer)) == FALSE) {
  444. return FALSE;
  445. }
  446. }
  447. else {
  448. RegDeleteValue (Key, TEXT ("GlobalFlag"));
  449. }
  450. RegDeleteValue (Key, TEXT ("VerifierFlags"));
  451. RegDeleteValue (Key, TEXT ("VerifierDebug"));
  452. RegDeleteValue (Key, TEXT ("VerifierDlls"));
  453. RegDeleteValue (Key, TEXT ("Debugger"));
  454. CloseImageKey (Key);
  455. return TRUE;
  456. }
  457. BOOL
  458. ReadGlobalFlagValue (
  459. HKEY Key,
  460. LPTSTR Buffer,
  461. ULONG Length)
  462. {
  463. LONG Result;
  464. DWORD Type;
  465. DWORD ReadLength = Length;
  466. Result = RegQueryValueEx (
  467. Key,
  468. TEXT ("GlobalFlag"),
  469. 0,
  470. &Type,
  471. (LPBYTE)Buffer,
  472. &ReadLength);
  473. if (Result != ERROR_SUCCESS || Type != REG_SZ) {
  474. return FALSE;
  475. }
  476. else {
  477. return TRUE;
  478. }
  479. }
  480. BOOL
  481. WriteGlobalFlagValue (
  482. HKEY Key,
  483. LPTSTR Buffer,
  484. ULONG Length)
  485. {
  486. LONG Result;
  487. Result = RegSetValueEx (
  488. Key,
  489. TEXT ("GlobalFlag"),
  490. 0,
  491. REG_SZ,
  492. (LPBYTE)Buffer,
  493. Length);
  494. if (Result != ERROR_SUCCESS) {
  495. return FALSE;
  496. }
  497. else {
  498. return TRUE;
  499. }
  500. }
  501. BOOL
  502. ReadVerifierValue (
  503. HKEY Key,
  504. LPTSTR Name,
  505. PDWORD Value
  506. )
  507. {
  508. LONG Result;
  509. DWORD Type;
  510. DWORD ReadLength = sizeof *Value;
  511. Result = RegQueryValueEx (Key,
  512. Name,
  513. 0,
  514. &Type,
  515. (LPBYTE)Value,
  516. &ReadLength);
  517. if (Result != ERROR_SUCCESS || Type != REG_DWORD) {
  518. return FALSE;
  519. }
  520. else {
  521. return TRUE;
  522. }
  523. }
  524. BOOL
  525. WriteVerifierValue (
  526. HKEY Key,
  527. LPTSTR Name,
  528. DWORD Value
  529. )
  530. {
  531. LONG Result;
  532. Result = RegSetValueEx (Key,
  533. Name,
  534. 0,
  535. REG_DWORD,
  536. (LPBYTE)(&Value),
  537. sizeof Value);
  538. if (Result != ERROR_SUCCESS) {
  539. return FALSE;
  540. }
  541. else {
  542. return TRUE;
  543. }
  544. }
  545. BOOL
  546. WriteDebuggerValue (
  547. HKEY Key,
  548. LPTSTR Buffer,
  549. ULONG Length)
  550. {
  551. LONG Result;
  552. Result = RegSetValueEx (
  553. Key,
  554. TEXT ("Debugger"),
  555. 0,
  556. REG_SZ,
  557. (LPBYTE)Buffer,
  558. Length);
  559. if (Result != ERROR_SUCCESS) {
  560. return FALSE;
  561. }
  562. else {
  563. return TRUE;
  564. }
  565. }
  566. BOOL
  567. IsShutdownFlagsValueDefined (
  568. LPCTSTR KeyName
  569. )
  570. {
  571. HKEY Key;
  572. LONG Result;
  573. DWORD Value;
  574. DWORD Type;
  575. DWORD ReadLength = sizeof (DWORD);
  576. if ((Key = OpenImageKey (KeyName, TRUE)) == NULL) {
  577. return FALSE;
  578. }
  579. Result = RegQueryValueEx (
  580. Key,
  581. TEXT ("ShutdownFlags"),
  582. 0,
  583. &Type,
  584. (LPBYTE)(&Value),
  585. &ReadLength);
  586. CloseImageKey (Key);
  587. if (Result == ERROR_SUCCESS && (Value & 0x03) == 0x03) {
  588. return TRUE;
  589. }
  590. else {
  591. return FALSE;
  592. }
  593. }
  594. HKEY
  595. OpenImageKey (
  596. LPCTSTR Name,
  597. BOOL ShouldExist)
  598. {
  599. HKEY Key;
  600. LONG Result;
  601. TCHAR Buffer [MAX_PATH];
  602. _stprintf (
  603. Buffer,
  604. TEXT ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s"),
  605. Name);
  606. if (ShouldExist) {
  607. Result = RegOpenKeyEx (
  608. HKEY_LOCAL_MACHINE,
  609. Buffer,
  610. 0,
  611. KEY_ALL_ACCESS,
  612. &Key);
  613. }
  614. else {
  615. Result = RegCreateKeyEx (
  616. HKEY_LOCAL_MACHINE,
  617. Buffer,
  618. 0,
  619. 0,
  620. 0,
  621. KEY_ALL_ACCESS,
  622. NULL,
  623. &Key,
  624. NULL);
  625. }
  626. if (Result != ERROR_SUCCESS) {
  627. return NULL;
  628. }
  629. else {
  630. return Key;
  631. }
  632. }
  633. VOID
  634. CloseImageKey (
  635. HKEY Key)
  636. {
  637. RegCloseKey (Key);
  638. }
  639. VOID
  640. CreateImageName (
  641. LPCTSTR Source,
  642. LPTSTR Name,
  643. ULONG Length)
  644. {
  645. UNREFERENCED_PARAMETER (Length);
  646. _tcscpy (Name, Source);
  647. _tcslwr (Name);
  648. if (_tcsstr (Name, TEXT(".")) == 0) {
  649. _tcscat (Name, TEXT(".exe"));
  650. }
  651. }
  652. VOID
  653. PrintVerifierEnabledApplications (
  654. )
  655. {
  656. LPCTSTR ImageFileExecutionOptionsKeyName =
  657. TEXT ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
  658. HKEY OptionsKey;
  659. LONG Result;
  660. TCHAR KeyName [MAX_PATH];
  661. ULONG KeySize;
  662. BOOL FoundOne = FALSE;
  663. ULONG Index;
  664. FILETIME FileTime;
  665. Result = RegOpenKeyEx (
  666. HKEY_LOCAL_MACHINE,
  667. ImageFileExecutionOptionsKeyName,
  668. 0,
  669. KEY_ALL_ACCESS,
  670. &OptionsKey);
  671. if (Result != ERROR_SUCCESS) {
  672. Error (TEXT("Cannot open registry key %s: error %u"),
  673. ImageFileExecutionOptionsKeyName,
  674. Result);
  675. }
  676. for (Index = 0; TRUE; Index++) {
  677. KeySize = MAX_PATH;
  678. Result = RegEnumKeyEx (
  679. OptionsKey,
  680. Index,
  681. KeyName,
  682. &KeySize,
  683. NULL,
  684. NULL,
  685. NULL,
  686. &FileTime);
  687. if (Result == ERROR_NO_MORE_ITEMS) {
  688. break;
  689. }
  690. if (Result != ERROR_SUCCESS) {
  691. Error (TEXT("Cannot enumerate registry key %s: error %u"),
  692. ImageFileExecutionOptionsKeyName,
  693. Result);
  694. }
  695. if (IsVerifierEnabled (KeyName)) {
  696. DWORD Value;
  697. FoundOne = TRUE;
  698. if (IsVerifierFlagsValueDefined (KeyName, &Value)) {
  699. _tprintf (TEXT("%s: verifier enabled with flags ("), KeyName);
  700. PrintFlags (Value);
  701. _tprintf (TEXT(")\n"));
  702. }
  703. else {
  704. _tprintf (TEXT("%s: verifier enabled with default flags \n"), KeyName);
  705. }
  706. }
  707. }
  708. if (FoundOne == FALSE) {
  709. _tprintf (TEXT("No application has verifier enabled.\n"));
  710. }
  711. }
  712. BOOL
  713. IsWow64Active (
  714. )
  715. {
  716. ULONG_PTR ul;
  717. NTSTATUS st;
  718. //
  719. // If this call succeeds then we are on Windows 2000 or later.
  720. //
  721. st = NtQueryInformationProcess(NtCurrentProcess(),
  722. ProcessWow64Information,
  723. &ul,
  724. sizeof(ul),
  725. NULL);
  726. if (NT_SUCCESS(st) && (0 != ul)) {
  727. // 32-bit code running on Win64
  728. return TRUE;
  729. }
  730. else {
  731. return FALSE;
  732. }
  733. }