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.

1443 lines
39 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. services.c
  5. Abstract:
  6. This module implements all access to the services db.
  7. Author:
  8. Wesley Witt (wesw) 21-Oct-1998
  9. Revision History:
  10. --*/
  11. #include "cmdcons.h"
  12. #pragma hdrstop
  13. #include "ntregapi.h"
  14. // forward-decl
  15. BOOLEAN RcFindService(
  16. IN LPCWSTR ServiceName,
  17. OUT HANDLE* KeyHandle
  18. );
  19. BOOLEAN RcFindServiceByDisplayName(
  20. IN HANDLE ServicesKey,
  21. IN LPCWSTR ServiceName,
  22. OUT HANDLE* KeyHandle
  23. );
  24. BOOLEAN RcGetStartType(
  25. IN HANDLE hKey,
  26. OUT DWORD *start_type
  27. );
  28. BOOLEAN RcSetStartType(
  29. IN HANDLE hKey,
  30. OUT DWORD start_type
  31. );
  32. BOOLEAN RcPrintStartType(
  33. IN ULONG msg_id,
  34. IN DWORD start_type
  35. );
  36. RcOpenHive(
  37. PWSTR szHiveName,
  38. PWSTR szHiveKey
  39. );
  40. BOOLEAN
  41. RcCloseHive(
  42. PWSTR szHiveKey
  43. );
  44. BOOLEAN RcOpenSystemHive();
  45. BOOLEAN RcCloseSystemHive();
  46. BOOLEAN RcDetermineCorrectControlKey(
  47. OUT DWORD * pCorrectKey
  48. );
  49. ULONG
  50. RcCmdEnableService(
  51. IN PTOKENIZED_LINE TokenizedLine
  52. )
  53. /*++
  54. Routine Description:
  55. Top-level routine supporting the enable command in the setup diagnostic
  56. command interpreter.
  57. Arguments:
  58. TokenizedLine - supplies structure built by the line parser describing
  59. each string on the line as typed by the user.
  60. Return Value:
  61. None.
  62. --*/
  63. {
  64. DWORD correctKey = 0;
  65. DWORD new_start_type = 4;
  66. DWORD start_type = 0;
  67. HANDLE hkey = 0;
  68. ASSERT(TokenizedLine->TokenCount >= 1);
  69. // there should be three tokens,
  70. // enable_service
  71. // the name of the service/driver to be enabled
  72. // the start_type of the service
  73. if (RcCmdParseHelp( TokenizedLine, MSG_SERVICE_ENABLE_HELP )) {
  74. return 1;
  75. }
  76. if(TokenizedLine->TokenCount == 2) {
  77. // just display the current setting
  78. RcOpenSystemHive();
  79. if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) {
  80. RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String );
  81. if( RcGetStartType(hkey, &start_type ) ) {
  82. RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type );
  83. RcMessageOut( MSG_START_TYPE_NOT_SPECIFIED );
  84. }
  85. } else {
  86. RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String );
  87. }
  88. NtClose( hkey );
  89. RcCloseSystemHive();
  90. } else if(TokenizedLine->TokenCount == 3) {
  91. // change the setting
  92. RcOpenSystemHive();
  93. if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) {
  94. RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String );
  95. // we found it - open and retrieve the start type
  96. if( RcGetStartType(hkey, &start_type ) ) {
  97. if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_BOOT_START" ) ) {
  98. new_start_type = 0;
  99. } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_SYSTEM_START" ) ) {
  100. new_start_type = 1;
  101. } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_AUTO_START" ) ) {
  102. new_start_type = 2;
  103. } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_DEMAND_START" ) ) {
  104. new_start_type = 3;
  105. } else {
  106. new_start_type = -1;
  107. }
  108. if( new_start_type == start_type ) {
  109. // the service is already in the state
  110. RcPrintStartType( MSG_SERVICE_SAME_STATE, start_type );
  111. } else if( new_start_type != -1 ) {
  112. // print the old start type
  113. RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type );
  114. // setup the service
  115. if( RcSetStartType( hkey, new_start_type ) ) {
  116. RcPrintStartType( MSG_SERVICE_CHANGE_STATE, new_start_type );
  117. }
  118. } else {
  119. RcMessageOut( MSG_SERVICE_ENABLE_SYNTAX_ERROR );
  120. }
  121. }
  122. // close the key
  123. NtClose( hkey );
  124. } else {
  125. // we couldn't find the service - report an error
  126. RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String );
  127. }
  128. RcCloseSystemHive();
  129. } else {
  130. // oops, we didn't get two or three parameters, print a help string.
  131. RcMessageOut( MSG_SERVICE_ENABLE_HELP );
  132. }
  133. return 1;
  134. }
  135. ULONG
  136. RcCmdDisableService(
  137. IN PTOKENIZED_LINE TokenizedLine
  138. )
  139. /*++
  140. Routine Description:
  141. Top-level routine supporting the disable command in the setup diagnostic
  142. command interpreter.
  143. Arguments:
  144. TokenizedLine - supplies structure built by the line parser describing
  145. each string on the line as typed by the user.
  146. Return Value:
  147. None.
  148. --*/
  149. {
  150. HANDLE hkey;
  151. DWORD start_type;
  152. WCHAR start_type_string[10];
  153. PLINE_TOKEN Token;
  154. BOOL syntaxError = FALSE;
  155. BOOL doHelp = FALSE;
  156. LPCWSTR Arg;
  157. if (RcCmdParseHelp( TokenizedLine, MSG_SERVICE_DISABLE_HELP )) {
  158. return 1;
  159. }
  160. RtlZeroMemory( (VOID *)&start_type_string, sizeof( WCHAR ) * 10 );
  161. // the command will print the old start_type of the
  162. // service before it asks for verification to disable it.
  163. if(TokenizedLine->TokenCount == 2) {
  164. // find the service key
  165. RcOpenSystemHive();
  166. if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) {
  167. RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String );
  168. // we found it - open and retrieve the start type
  169. if( RcGetStartType(hkey, &start_type ) ) {
  170. if( start_type != SERVICE_DISABLED ) {
  171. // print the old start type
  172. RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type );
  173. // disable the service
  174. if( RcSetStartType( hkey, SERVICE_DISABLED ) ) {
  175. RcPrintStartType( MSG_SERVICE_CHANGE_STATE, SERVICE_DISABLED );
  176. }
  177. } else {
  178. RcMessageOut( MSG_SERVICE_ALREADY_DISABLED, TokenizedLine->Tokens->Next->String );
  179. }
  180. }
  181. // close the key
  182. NtClose( hkey );
  183. } else {
  184. // we couldn't find the service - report an error
  185. RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String );
  186. }
  187. RcCloseSystemHive();
  188. } else {
  189. // oops, we didn't get two parameters, print a help string.
  190. RcMessageOut( MSG_SERVICE_DISABLE_HELP );
  191. }
  192. return 1;
  193. }
  194. BOOLEAN
  195. RcFindService(
  196. IN LPCWSTR ServiceName,
  197. OUT PHANDLE KeyHandle
  198. )
  199. /*++
  200. Routine Description:
  201. Attempts to find and open the registry key for a particular
  202. service by its key name in
  203. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
  204. If it fails, it will call RcFindServiceByDisplayName() to
  205. locate the service by the DisplayName string value.
  206. Arguments:
  207. ServiceName - the name of the service as a wstring.
  208. KeyHandle - pointer to a HANDLE where the function should
  209. return the open registry handle.
  210. this handle needs to be closed when the key is no
  211. longer needed.
  212. Return Value:
  213. TRUE indicates sucess.
  214. FALSE indicates that it couldn't find the service or failure.
  215. --*/
  216. {
  217. NTSTATUS Status;
  218. WCHAR RegPath[ MAX_PATH ];
  219. OBJECT_ATTRIBUTES Obja;
  220. DWORD correctKey;
  221. UNICODE_STRING ServiceString;
  222. HANDLE ServiceKeyHandle;
  223. // zero out the buffer
  224. RtlZeroMemory( (VOID * )&RegPath,
  225. sizeof( WCHAR ) * MAX_PATH );
  226. // find the correct controlset key
  227. if( !RcDetermineCorrectControlKey( &correctKey ) ) {
  228. return FALSE;
  229. }
  230. // prepend HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services to
  231. // the supplied parameter
  232. swprintf( RegPath, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services\\", correctKey );
  233. wcscat( RegPath, ServiceName );
  234. // build the unicode string
  235. RtlInitUnicodeString( &ServiceString, RegPath );
  236. InitializeObjectAttributes( &Obja,&ServiceString,
  237. OBJ_CASE_INSENSITIVE, NULL, NULL);
  238. // attempt to open the key.
  239. Status = ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja );
  240. if( NT_SUCCESS( Status) ) {
  241. // if we suceeded, set and return
  242. // the handle.
  243. *KeyHandle = ServiceKeyHandle;
  244. } else {
  245. // build the unicode string
  246. swprintf( RegPath, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services", correctKey );
  247. RtlInitUnicodeString( &ServiceString, RegPath );
  248. InitializeObjectAttributes( &Obja,&ServiceString,
  249. OBJ_CASE_INSENSITIVE, NULL, NULL);
  250. // open a handle to \\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services
  251. if( NT_SUCCESS( ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja ) ) ) {
  252. if( !RcFindServiceByDisplayName( ServiceKeyHandle, ServiceName, KeyHandle ) ) {
  253. // if we failed, NULL out KeyHandle, and return FALSE.
  254. DEBUG_PRINTF(( "CMDCONS: failed to find key!\n" ));
  255. *KeyHandle = INVALID_HANDLE_VALUE;
  256. if( !NT_SUCCESS( NtClose( ServiceKeyHandle ) ) ) {
  257. DEBUG_PRINTF(( "CMDCONS: failed to close service key handle\n" ));
  258. }
  259. return FALSE;
  260. }
  261. // we found the key!
  262. // close the service key handle
  263. if( !NT_SUCCESS( NtClose( ServiceKeyHandle ) ) ) {
  264. DEBUG_PRINTF(( "CMDCONS: failed to close service key handle\n" ));
  265. }
  266. } else {
  267. DEBUG_PRINTF(( "CMDCONS: failed to open service key handle\n" ));
  268. RcMessageOut( MSG_SYSTEM_MISSING_CURRENT_CONTROLS );
  269. }
  270. }
  271. // return true
  272. return TRUE;
  273. }
  274. // buffersizes
  275. #define sizeof_buffer1 sizeof( KEY_FULL_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
  276. #define sizeof_buffer2 sizeof( KEY_BASIC_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
  277. #define sizeof_buffer3 sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
  278. BOOLEAN
  279. RcFindServiceByDisplayName(
  280. IN HANDLE ServicesKey,
  281. IN LPCWSTR ServiceName,
  282. OUT PHANDLE KeyHandle
  283. )
  284. /*++
  285. Routine Description:
  286. Attempts to find and open the registry key for a particular
  287. service by the DisplayName string value.
  288. Arguments:
  289. SevicesKey - an open handle to the correct Services Key to search under
  290. ServiceName - the name of the service as a wstring.
  291. KeyHandle - pointer to a HANDLE where the function should
  292. return the open registry handle.
  293. this handle needs to be closed when the key is no
  294. longer needed.
  295. Return Value:
  296. TRUE indicates sucess.
  297. FALSE indicates that it couldn't find the service or failure.
  298. --*/
  299. {
  300. WCHAR ValueName[] = L"DisplayName";
  301. BYTE buffer1[ sizeof_buffer1 ];
  302. BYTE buffer2[ sizeof_buffer2 ];
  303. BYTE buffer3[ sizeof_buffer3 ];
  304. KEY_FULL_INFORMATION * pKeyFullInfo;
  305. KEY_BASIC_INFORMATION * pKeyBasicInfo;
  306. KEY_VALUE_PARTIAL_INFORMATION * pKeyValuePartialInfo;
  307. ULONG actualBytes;
  308. ULONG loopCount;
  309. ULONG keyCount;
  310. OBJECT_ATTRIBUTES Obja;
  311. HANDLE newHandle;
  312. UNICODE_STRING unicodeString;
  313. BOOL keyFound = FALSE;
  314. // zero out the buffer
  315. RtlZeroMemory( (VOID * ) &(buffer1[0]), sizeof_buffer1 );
  316. pKeyFullInfo= (KEY_FULL_INFORMATION*) &( buffer1[0] );
  317. pKeyBasicInfo = (KEY_BASIC_INFORMATION* ) &( buffer2[0] );
  318. pKeyValuePartialInfo = (KEY_VALUE_PARTIAL_INFORMATION* ) &(buffer3[0]);
  319. // do a ZwQueryKey() to find out the number of subkeys.
  320. if( !NT_SUCCESS( ZwQueryKey( ServicesKey,
  321. KeyFullInformation,
  322. pKeyFullInfo,
  323. sizeof_buffer1,
  324. &actualBytes ) ) ) {
  325. *KeyHandle = INVALID_HANDLE_VALUE;
  326. DEBUG_PRINTF(( "FindServiceByDisplayName: failed to get number of keys!\n" ));
  327. return FALSE;
  328. }
  329. keyCount = pKeyFullInfo->SubKeys;
  330. // loop
  331. for( loopCount = 0; loopCount < keyCount; loopCount++ ) {
  332. // zero out the buffer
  333. RtlZeroMemory( (VOID * ) &(buffer2[0]), sizeof_buffer2 );
  334. // zero out the buffer
  335. RtlZeroMemory( (VOID * ) &(buffer3[0]), sizeof_buffer3 );
  336. // do an ZwEnumerateKey() to find the name of the subkey
  337. ZwEnumerateKey( ServicesKey,
  338. loopCount,
  339. KeyBasicInformation,
  340. pKeyBasicInfo,
  341. sizeof_buffer2,
  342. &actualBytes );
  343. // setup the ZwOpenKey() with the name we just got back
  344. RtlInitUnicodeString( &unicodeString, pKeyBasicInfo->Name );
  345. InitializeObjectAttributes( &Obja, &unicodeString,
  346. OBJ_CASE_INSENSITIVE, ServicesKey, NULL);
  347. // do a ZwOpenKey() to open the key
  348. if( !NT_SUCCESS( ZwOpenKey( &newHandle, KEY_ALL_ACCESS, &Obja ) ) ) {
  349. DEBUG_PRINTF(( "FindServiceByDisplayName: failed to open the subkey?!\n" ));
  350. }
  351. // do a ZwQueryKeyValue() to find the key value DisplayName if it exists
  352. RtlInitUnicodeString( &unicodeString, ValueName );
  353. if( !NT_SUCCESS( ZwQueryValueKey( newHandle,
  354. &unicodeString,
  355. KeyValuePartialInformation,
  356. pKeyValuePartialInfo,
  357. sizeof_buffer3,
  358. &actualBytes
  359. )
  360. )
  361. ) {
  362. DEBUG_PRINTF(( "FindServiceByDisplayName: display name get failed\n" ));
  363. } else {
  364. // if the ZwQueryKeyValue() succeeded
  365. if( pKeyValuePartialInfo->Type != REG_SZ ) {
  366. DEBUG_PRINTF(( "FindServiceByDisplayName: paranoia!! mismatched key type?!\n" ));
  367. } else {
  368. // paranoia check SUCCEEDED
  369. // if the value matches, break out of the loop
  370. if( _wcsicmp( (WCHAR*)&(pKeyValuePartialInfo->Data[0]), ServiceName ) == 0 ) {
  371. keyFound = TRUE;
  372. break;
  373. }
  374. }
  375. }
  376. // close the key
  377. if( !NT_SUCCESS( ZwClose( newHandle ) ) ) {
  378. DEBUG_PRINTF(( "FindServiceByDisplayName: Failure closing the handle!!" ));
  379. }
  380. }
  381. // return the handle to the opened key.
  382. if( keyFound == TRUE ) {
  383. *KeyHandle = newHandle;
  384. return TRUE;
  385. }
  386. *KeyHandle = INVALID_HANDLE_VALUE;
  387. return FALSE;
  388. }
  389. BOOLEAN
  390. RcGetStartType(
  391. IN HANDLE hKey,
  392. OUT PULONG start_type
  393. )
  394. /*++
  395. Routine Description:
  396. Given an open service key, gets the start_type of the service.
  397. Arguments:
  398. hKey - a handle to the open service key
  399. start_type - integer indicating the start type of the service
  400. SERVICE_BOOT_START - 0x0
  401. SERVICE_SYSTEM_START - 0x1
  402. SERVICE_AUTO_START - 0x2
  403. SERVUCE_DEMAMD_START - 0x3
  404. SERVICE_DISABLED - 0x4
  405. Return Value:
  406. TRUE indicates sucess.
  407. FALSE indicates failure.
  408. --*/
  409. {
  410. BYTE buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 ]; // just grab a bunch of bytes
  411. ULONG resultSize;
  412. KEY_VALUE_PARTIAL_INFORMATION * keyPartialInfo;
  413. UNICODE_STRING StartKey;
  414. WCHAR KEY_NAME[] = L"Start";
  415. RtlZeroMemory( (VOID * )&(buffer[0]),
  416. sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 );
  417. keyPartialInfo = (KEY_VALUE_PARTIAL_INFORMATION*)&(buffer[0]);
  418. ASSERT( keyPartialInfo );
  419. RtlInitUnicodeString( &StartKey, KEY_NAME );
  420. if( !NT_SUCCESS( ZwQueryValueKey( hKey,
  421. &StartKey,
  422. KeyValuePartialInformation,
  423. keyPartialInfo,
  424. sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100,
  425. &resultSize
  426. )
  427. )
  428. ) {
  429. DEBUG_PRINTF(( "CMDCONS: start type get failed\n" ));
  430. RcMessageOut( MSG_SERVICE_MISSING_START_KEY );
  431. *start_type = -1;
  432. return FALSE;
  433. }
  434. // paranoia check
  435. if( keyPartialInfo->Type != REG_DWORD ) {
  436. RcMessageOut( MSG_SERVICE_MISSING_START_KEY );
  437. DEBUG_PRINTF(( "CMDCONS: mismatched key type?!\n" ));
  438. *start_type = -1;
  439. return FALSE;
  440. }
  441. *start_type = *( (DWORD*) &(keyPartialInfo->Data[0]) );
  442. return TRUE;
  443. }
  444. BOOLEAN
  445. RcSetStartType(
  446. IN HANDLE hKey,
  447. IN DWORD start_type
  448. )
  449. /*++
  450. Routine Description:
  451. Given an open service key, sets the start_type of the service.
  452. Arguments:
  453. hKey - a handle to the open service key
  454. start_type - integer indicating the start type of the service
  455. SERVICE_BOOT_START - 0x0
  456. SERVICE_SYSTEM_START - 0x1
  457. SERVICE_AUTO_START - 0x2
  458. SERVUCE_DEMAMD_START - 0x3
  459. SERVICE_DISABLED - 0x4
  460. Return Value:
  461. TRUE indicates sucess.
  462. FALSE indicates failure.
  463. --*/
  464. {
  465. UNICODE_STRING StartKey;
  466. RtlInitUnicodeString( &StartKey, L"Start" );
  467. if( NT_SUCCESS( ZwSetValueKey( hKey,
  468. &StartKey,
  469. 0,
  470. REG_DWORD,
  471. &start_type,
  472. sizeof( DWORD )
  473. )
  474. )
  475. ) {
  476. return TRUE;
  477. }
  478. RcMessageOut( MSG_SERVICE_MISSING_START_KEY );
  479. DEBUG_PRINTF(( "CMDCONS: start type get failed\n" ));
  480. return FALSE;
  481. }
  482. BOOLEAN
  483. RcPrintStartType(
  484. ULONG msg_id,
  485. DWORD start_type
  486. )
  487. /*++
  488. Routine Description:
  489. Prints the start_type.
  490. Arguments:
  491. start_type - integer indicating the start type of the service
  492. SERVICE_BOOT_START - 0x0
  493. SERVICE_SYSTEM_START - 0x1
  494. SERVICE_AUTO_START - 0x2
  495. SERVUCE_DEMAMD_START - 0x3
  496. SERVICE_DISABLED - 0x4
  497. Return Value:
  498. TRUE - indicates sucess
  499. FALSE - indicates failure
  500. --*/
  501. {
  502. switch( start_type ) {
  503. case 0:
  504. RcMessageOut( msg_id, L"SERVICE_BOOT_START" );
  505. break;
  506. case 1:
  507. RcMessageOut( msg_id, L"SERVICE_SYSTEM_START" );
  508. break;
  509. case 2:
  510. RcMessageOut( msg_id, L"SERVICE_AUTO_START" );
  511. break;
  512. case 3:
  513. RcMessageOut( msg_id, L"SERVICE_DEMAND_START" );
  514. break;
  515. case 4:
  516. RcMessageOut( msg_id, L"SERVICE_DISABLED" );
  517. break;
  518. default:
  519. break;
  520. }
  521. return TRUE;
  522. }
  523. BOOLEAN
  524. RcOpenSystemHive(
  525. VOID
  526. )
  527. /*++
  528. Routine Description:
  529. Opens the SYSTEM hive of the selected NT install.
  530. Arguments:
  531. None.
  532. Return Value:
  533. TRUE - indicates sucess
  534. FALSE - indicates failure
  535. --*/
  536. {
  537. PWSTR Hive = NULL;
  538. PWSTR HiveKey = NULL;
  539. PUCHAR buffer = NULL;
  540. PWSTR PartitionPath = NULL;
  541. NTSTATUS Status;
  542. if (SelectedInstall == NULL) {
  543. return FALSE;
  544. }
  545. //
  546. // Allocate buffers.
  547. //
  548. Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  549. HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  550. buffer = SpMemAlloc(BUFFERSIZE);
  551. //
  552. // Get the name of the target patition.
  553. //
  554. SpNtNameFromRegion(
  555. SelectedInstall->Region, // SelectedInstall is a global defined in cmdcons.h
  556. _CmdConsBlock->TemporaryBuffer,
  557. _CmdConsBlock->TemporaryBufferSize,
  558. PartitionOrdinalCurrent
  559. );
  560. PartitionPath = SpDupStringW(_CmdConsBlock->TemporaryBuffer);
  561. //
  562. // Load the SYSTEM hive
  563. //
  564. wcscpy(Hive,PartitionPath);
  565. SpConcatenatePaths(Hive,SelectedInstall->Path);
  566. SpConcatenatePaths(Hive,L"system32\\config");
  567. SpConcatenatePaths(Hive,L"system");
  568. //
  569. // Form the path of the key into which we will
  570. // load the hive. We'll use the convention that
  571. // a hive will be loaded into \registry\machine\x<hivename>.
  572. //
  573. wcscpy(HiveKey,L"\\registry\\machine\\xSYSTEM");
  574. //
  575. // Attempt to load the key.
  576. //
  577. Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
  578. if(!NT_SUCCESS(Status)) {
  579. DEBUG_PRINTF(("CMDCONS: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
  580. SpMemFree( Hive );
  581. SpMemFree( HiveKey );
  582. SpMemFree( buffer );
  583. return FALSE;
  584. }
  585. SpMemFree( Hive );
  586. SpMemFree( HiveKey );
  587. SpMemFree( buffer );
  588. return TRUE;
  589. }
  590. BOOLEAN
  591. RcCloseSystemHive(
  592. VOID
  593. )
  594. /*++
  595. Routine Description:
  596. Closes the SYSTEM hive of the selected NT install.
  597. Arguments:
  598. none.
  599. Return Value:
  600. TRUE - indicates sucess
  601. FALSE - indicates failure
  602. --*/
  603. {
  604. PWSTR HiveKey = NULL;
  605. NTSTATUS TmpStatus;
  606. //
  607. // Allocate buffers.
  608. //
  609. HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
  610. wcscpy(HiveKey,L"\\registry\\machine\\xSYSTEM");
  611. //
  612. // Unload the SYSTEM hive
  613. //
  614. TmpStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
  615. if(!NT_SUCCESS(TmpStatus)) {
  616. KdPrint(("CMDCONS: warning: unable to unload key %ws (%lx)\n",HiveKey,TmpStatus));
  617. SpMemFree( HiveKey );
  618. return FALSE;
  619. }
  620. SpMemFree( HiveKey );
  621. return TRUE;
  622. }
  623. BOOLEAN
  624. RcDetermineCorrectControlKey(
  625. OUT PULONG pCorrectKey
  626. )
  627. /*++
  628. Routine Description:
  629. Parses the select node and finds the correct ControlSetXXX to use.
  630. Arguments:
  631. pCorrectKey - pointer to a DWORD which will contain the number.
  632. Return Value:
  633. TRUE - indicates sucess
  634. FALSE - indicates failure
  635. --*/
  636. {
  637. NTSTATUS Status;
  638. WCHAR RegPath[ MAX_PATH ];
  639. OBJECT_ATTRIBUTES Obja;
  640. UNICODE_STRING SelectString;
  641. HANDLE SelectKeyHandle;
  642. BYTE buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 ]; // just grab a bunch of bytes
  643. ULONG resultSize = 0;
  644. KEY_VALUE_PARTIAL_INFORMATION * keyPartialInfo;
  645. UNICODE_STRING SelectValue;
  646. WCHAR VALUE_NAME[] = L"Current";
  647. RtlZeroMemory( (VOID * )&(buffer[0]),
  648. sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 );
  649. keyPartialInfo = (KEY_VALUE_PARTIAL_INFORMATION*)&(buffer[0]);
  650. ASSERT( keyPartialInfo );
  651. *pCorrectKey = -1;
  652. // prepend HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services to
  653. // the supplied parameter
  654. wcscpy( RegPath, L"\\registry\\machine\\xSYSTEM\\Select" );
  655. // build the unicode string
  656. RtlInitUnicodeString( &SelectString, RegPath );
  657. InitializeObjectAttributes( &Obja,&SelectString,
  658. OBJ_CASE_INSENSITIVE, NULL, NULL);
  659. // we need to determine the correct ControlSet to open
  660. Status = ZwOpenKey( &SelectKeyHandle, KEY_ALL_ACCESS, &Obja );
  661. if( NT_SUCCESS( Status ) ) {
  662. RtlInitUnicodeString( &SelectValue, VALUE_NAME );
  663. Status = ZwQueryValueKey( SelectKeyHandle,
  664. &SelectValue,
  665. KeyValuePartialInformation,
  666. keyPartialInfo,
  667. sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100,
  668. &resultSize
  669. );
  670. if( !NT_SUCCESS(Status) || Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  671. // couldn't find correct control value!
  672. DEBUG_PRINTF(( "CMDCONS: failed to find correct control value!\n" ));
  673. } else {
  674. // we found a control value
  675. // check if it's ok
  676. if( keyPartialInfo->Type != REG_DWORD ) {
  677. // paranoia check failed
  678. DEBUG_PRINTF(( "CMDCONS: paranoia check failed?!\n" ));
  679. DEBUG_PRINTF(( "CMDCONS: mismatched key type?!\n" ));
  680. DEBUG_PRINTF(( "CMDCONS: key type of %d?!\n", keyPartialInfo->Type ));
  681. DEBUG_PRINTF(( "CMDCONS: resultsize of %d?!\n", resultSize ));
  682. } else {
  683. // parnoia check sucess
  684. *pCorrectKey = *( (DWORD*) &(keyPartialInfo->Data[0]) );
  685. Status = NtClose( SelectKeyHandle );
  686. if( !NT_SUCCESS ( Status ) ) {
  687. DEBUG_PRINTF(( "CMDCONS: failure closing handle?!\n" ));
  688. }
  689. return TRUE;
  690. }
  691. }
  692. }
  693. // failed to find the Select node.
  694. RcMessageOut( MSG_SYSTEM_MISSING_CURRENT_CONTROLS );
  695. DEBUG_PRINTF(( "CMDCONS: failed to find select node!\n", *pCorrectKey ));
  696. Status = NtClose( SelectKeyHandle );
  697. if( !NT_SUCCESS ( Status ) ) {
  698. DEBUG_PRINTF(( "CMDCONS: failure closing handle?!\n" ));
  699. }
  700. return FALSE;
  701. }
  702. ULONG
  703. RcCmdListSvc(
  704. IN PTOKENIZED_LINE TokenizedLine
  705. )
  706. {
  707. #define DISPLAY_BUFFER_SIZE 512
  708. NTSTATUS Status;
  709. UNICODE_STRING UnicodeString;
  710. OBJECT_ATTRIBUTES Obja;
  711. HANDLE ServiceKeyHandle = NULL;
  712. ULONG ControlSetNumber;
  713. ULONG cb;
  714. ULONG KeyCount;
  715. ULONG i;
  716. HANDLE ValueHandle;
  717. ULONG StartType;
  718. PWSTR DisplayBuffer = NULL;
  719. PKEY_BASIC_INFORMATION bi;
  720. PKEY_VALUE_PARTIAL_INFORMATION pi;
  721. WCHAR ServiceName[64];
  722. PWSTR DisplayName;
  723. static ULONG StartTypeIds[] = {
  724. MSG_SVCTYPE_BOOT,
  725. MSG_SVCTYPE_SYSTEM,
  726. MSG_SVCTYPE_AUTO,
  727. MSG_SVCTYPE_MANUAL,
  728. MSG_SVCTYPE_DISABLED
  729. };
  730. static WCHAR *StartTypeStr[sizeof(StartTypeIds)/sizeof(ULONG)] = { 0 };
  731. static WCHAR *DefaultSvcTypes[sizeof(StartTypeIds)/sizeof(ULONG)] =
  732. { L"Boot", L"System", L"Auto", L"Manual", L"Disabled" };
  733. if (!StartTypeStr[0]) {
  734. //
  735. // load all the service type strings
  736. //
  737. ULONG Index;
  738. for (Index = 0; Index < sizeof(StartTypeIds)/sizeof(ULONG); Index++) {
  739. StartTypeStr[Index] = SpRetreiveMessageText(ImageBase, StartTypeIds[Index],
  740. NULL, 0);
  741. if (!StartTypeStr[Index])
  742. StartTypeStr[Index] = DefaultSvcTypes[Index];
  743. }
  744. }
  745. if (RcCmdParseHelp( TokenizedLine, MSG_LISTSVC_HELP )) {
  746. return 1;
  747. }
  748. if (!RcOpenSystemHive()) {
  749. return 1;
  750. }
  751. pRcEnableMoreMode();
  752. if (!RcDetermineCorrectControlKey( &ControlSetNumber ) ) {
  753. goto exit;
  754. }
  755. DisplayBuffer = (PWSTR) SpMemAlloc( DISPLAY_BUFFER_SIZE );
  756. if (DisplayBuffer == NULL) {
  757. goto exit;
  758. }
  759. swprintf( _CmdConsBlock->TemporaryBuffer, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services\\", ControlSetNumber );
  760. RtlInitUnicodeString( &UnicodeString, _CmdConsBlock->TemporaryBuffer );
  761. InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
  762. Status = ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja );
  763. if (!NT_SUCCESS(Status)) {
  764. goto exit;
  765. }
  766. Status = ZwQueryKey(
  767. ServiceKeyHandle,
  768. KeyFullInformation,
  769. _CmdConsBlock->TemporaryBuffer,
  770. _CmdConsBlock->TemporaryBufferSize,
  771. &cb
  772. );
  773. if (!NT_SUCCESS(Status)) {
  774. goto exit;
  775. }
  776. KeyCount = ((KEY_FULL_INFORMATION*)_CmdConsBlock->TemporaryBuffer)->SubKeys;
  777. bi = (PKEY_BASIC_INFORMATION)_CmdConsBlock->TemporaryBuffer;
  778. pi = (PKEY_VALUE_PARTIAL_INFORMATION)_CmdConsBlock->TemporaryBuffer;
  779. for (i=0; i<KeyCount; i++) {
  780. RtlZeroMemory( DisplayBuffer, DISPLAY_BUFFER_SIZE );
  781. RtlZeroMemory( _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize );
  782. Status = ZwEnumerateKey(
  783. ServiceKeyHandle,
  784. i,
  785. KeyBasicInformation,
  786. _CmdConsBlock->TemporaryBuffer,
  787. _CmdConsBlock->TemporaryBufferSize,
  788. &cb
  789. );
  790. if (!NT_SUCCESS(Status)) {
  791. goto exit;
  792. }
  793. wcsncpy( ServiceName, bi->Name, (sizeof(ServiceName)/sizeof(WCHAR))-1 );
  794. RtlInitUnicodeString( &UnicodeString, bi->Name );
  795. InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, ServiceKeyHandle, NULL );
  796. Status = ZwOpenKey( &ValueHandle, KEY_ALL_ACCESS, &Obja );
  797. if (!NT_SUCCESS(Status)) {
  798. goto exit;
  799. }
  800. RtlInitUnicodeString( &UnicodeString, L"Start" );
  801. Status = ZwQueryValueKey(
  802. ValueHandle,
  803. &UnicodeString,
  804. KeyValuePartialInformation,
  805. _CmdConsBlock->TemporaryBuffer,
  806. _CmdConsBlock->TemporaryBufferSize,
  807. &cb
  808. );
  809. if (!NT_SUCCESS(Status)) {
  810. ZwClose( ValueHandle );
  811. continue;
  812. }
  813. if (pi->Type != REG_DWORD) {
  814. StartType = 5;
  815. } else {
  816. StartType = *(PULONG)&(pi->Data[0]);
  817. }
  818. RtlInitUnicodeString( &UnicodeString, L"DisplayName" );
  819. Status = ZwQueryValueKey(
  820. ValueHandle,
  821. &UnicodeString,
  822. KeyValuePartialInformation,
  823. _CmdConsBlock->TemporaryBuffer,
  824. _CmdConsBlock->TemporaryBufferSize,
  825. &cb
  826. );
  827. if (NT_SUCCESS(Status)) {
  828. DisplayName = (PWSTR)&(pi->Data[0]);
  829. } else {
  830. DisplayName = NULL;
  831. }
  832. ZwClose( ValueHandle );
  833. if (StartType != 5) {
  834. swprintf( DisplayBuffer, L"%-15s %-8s %s\r\n",
  835. ServiceName,
  836. StartTypeStr[StartType],
  837. DisplayName == NULL ? L"" : DisplayName
  838. );
  839. if (!RcTextOut( DisplayBuffer )){
  840. goto exit;
  841. }
  842. }
  843. }
  844. exit:
  845. if (ServiceKeyHandle) {
  846. ZwClose( ServiceKeyHandle );
  847. }
  848. RcCloseSystemHive();
  849. if (DisplayBuffer) {
  850. SpMemFree(DisplayBuffer);
  851. }
  852. pRcDisableMoreMode();
  853. return 1;
  854. }
  855. #define VERIFIER_DRV_LEVEL L"VerifyDriverLevel"
  856. #define VERIFIER_DRIVERS L"VerifyDrivers"
  857. #define VERIFIER_IO_LEVEL L"IoVerifierLevel"
  858. #define VERIFIER_QUERY_INFO L"Flags = %ld; IO Level = %ld\r\nDrivers = %ws\r\n"
  859. #define MEMMGR_PATH L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Session Manager\\Memory Management"
  860. #define IOSYS_PATH L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Session Manager\\I/O System"
  861. #define SYS_HIVE_NAME L"system"
  862. #define SYS_HIVE_KEY L"\\registry\\machine\\xSYSTEM"
  863. ULONG
  864. RcCmdVerifier(
  865. IN PTOKENIZED_LINE TokenizedLine
  866. )
  867. {
  868. BOOLEAN ShowHelp = FALSE;
  869. WCHAR *Args[128] = {0};
  870. ULONG Index;
  871. PLINE_TOKEN CurrToken = 0;
  872. WCHAR Drivers[256] = {0};
  873. DWORD Flags = -1;
  874. DWORD IoLevel = -1;
  875. BOOLEAN DisplaySettings = FALSE;
  876. UNICODE_STRING UnicodeString;
  877. ULONG NumArgs = 0;
  878. BOOLEAN UseDefFlags = TRUE;
  879. BOOLEAN UseDefIoLevel = TRUE;
  880. BOOLEAN ResetSettings = FALSE;
  881. if (RcCmdParseHelp(TokenizedLine, MSG_VERIFIER_HELP)) {
  882. return 1;
  883. }
  884. //
  885. // parse the arguments
  886. //
  887. Index = 0;
  888. CurrToken = TokenizedLine->Tokens;
  889. do {
  890. Args[Index] = CurrToken->String;
  891. CurrToken = CurrToken->Next;
  892. Index++;
  893. }
  894. while ((Index < TokenizedLine->TokenCount) &&
  895. (Index < sizeof(Args)/sizeof(PWCHAR)) && CurrToken);
  896. NumArgs = min(TokenizedLine->TokenCount, Index);
  897. if (TokenizedLine->TokenCount == 2) {
  898. //
  899. // should be one of /all, /reset, /query
  900. //
  901. if (!_wcsicmp(Args[1], L"/all")) {
  902. wcscpy(Drivers, L"*");
  903. Flags = 0;
  904. IoLevel = 1;
  905. } else if (!_wcsicmp(Args[1], L"/reset")) {
  906. Drivers[0] = 0;
  907. Flags = 0;
  908. IoLevel = 1;
  909. ResetSettings = TRUE;
  910. } else if (!_wcsicmp(Args[1], L"/query")) {
  911. DisplaySettings = TRUE;
  912. } else {
  913. ShowHelp = TRUE;
  914. }
  915. } else {
  916. ULONG NextArg = 1;
  917. if (!_wcsicmp(Args[NextArg], L"/flags")) {
  918. RtlInitUnicodeString(&UnicodeString, Args[NextArg + 1]);
  919. RtlUnicodeStringToInteger(&UnicodeString, 10, &Flags);
  920. NextArg += 2;
  921. UseDefFlags = FALSE;
  922. }
  923. if (!_wcsicmp(Args[NextArg], L"/iolevel")) {
  924. RtlInitUnicodeString(&UnicodeString, Args[NextArg + 1]);
  925. RtlUnicodeStringToInteger(&UnicodeString, 10, &IoLevel);
  926. NextArg += 2;
  927. UseDefIoLevel = FALSE;
  928. }
  929. if (!_wcsicmp(Args[NextArg], L"/driver")) {
  930. ULONG Len = 0;
  931. Drivers[0] = 0;
  932. for (Index = NextArg + 1; Index < NumArgs; Index++) {
  933. wcscat(Drivers, Args[Index]);
  934. wcscat(Drivers, L" ");
  935. }
  936. if (!Drivers[0])
  937. ShowHelp = TRUE; // need a driver name
  938. } else if (!_wcsicmp(Args[NextArg], L"/all")) {
  939. wcscpy(Drivers, L"*");
  940. } else {
  941. ShowHelp = TRUE;
  942. }
  943. }
  944. //
  945. // Verify the arguments
  946. //
  947. if (!ShowHelp) {
  948. ShowHelp = !DisplaySettings && !ResetSettings &&
  949. (Flags == -1) && (IoLevel == -1) && (!Drivers[0]);
  950. }
  951. if (ShowHelp) {
  952. RcMessageOut(MSG_VERIFIER_HELP);
  953. } else {
  954. ULONG ControlSetNumber = 0;
  955. HANDLE MemMgrKeyHandle = NULL;
  956. HANDLE IOMgrKeyHandle = NULL;
  957. OBJECT_ATTRIBUTES ObjAttrs;
  958. BOOLEAN KeysOpened = FALSE;
  959. PVOID TemporaryBuffer = _CmdConsBlock->TemporaryBuffer;
  960. ULONG TemporaryBufferSize = _CmdConsBlock->TemporaryBufferSize;
  961. NTSTATUS Status;
  962. BOOLEAN SysHiveOpened;
  963. //
  964. // open the system hive & determine correct control set to use
  965. //
  966. SysHiveOpened = (BOOLEAN)RcOpenHive(SYS_HIVE_NAME, SYS_HIVE_KEY);
  967. //
  968. // get the control set which we are going to manipulate
  969. //
  970. if (SysHiveOpened && RcDetermineCorrectControlKey(&ControlSetNumber)) {
  971. //
  972. // open "Memory Management" subkey under "SM"
  973. //
  974. swprintf((PWSTR)TemporaryBuffer, MEMMGR_PATH, ControlSetNumber);
  975. RtlInitUnicodeString(&UnicodeString, (PWSTR)TemporaryBuffer);
  976. InitializeObjectAttributes(&ObjAttrs, &UnicodeString,
  977. OBJ_CASE_INSENSITIVE, NULL, NULL);
  978. Status = ZwOpenKey(&MemMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs);
  979. if (NT_SUCCESS(Status)) {
  980. //
  981. // open "I/O System" subkey under "SM"
  982. //
  983. swprintf((PWSTR)TemporaryBuffer, IOSYS_PATH, ControlSetNumber);
  984. RtlInitUnicodeString(&UnicodeString, (PWSTR)TemporaryBuffer);
  985. InitializeObjectAttributes(&ObjAttrs, &UnicodeString,
  986. OBJ_CASE_INSENSITIVE, NULL, NULL);
  987. Status = ZwOpenKey(&IOMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs);
  988. if (!NT_SUCCESS(Status)) {
  989. ULONG Disposition = 0;
  990. //
  991. // Create "I/O System" subkey under "SM", if it does not exist
  992. //
  993. Status = ZwCreateKey(&IOMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs,
  994. 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
  995. }
  996. if (NT_SUCCESS(Status))
  997. KeysOpened = TRUE;
  998. }
  999. }
  1000. if (KeysOpened) {
  1001. ULONG ByteCount = 0;
  1002. ULONG KeyCount = 0;
  1003. PKEY_VALUE_FULL_INFORMATION ValueFullInfo;
  1004. WCHAR ValueName[256];
  1005. ULONG Len;
  1006. if (DisplaySettings) {
  1007. //
  1008. // Query the Flags and Drivers
  1009. //
  1010. Flags = 0;
  1011. Drivers[0] = 0;
  1012. for(Index=0; ;Index++){
  1013. Status = ZwEnumerateValueKey(
  1014. MemMgrKeyHandle,
  1015. Index,
  1016. KeyValueFullInformation,
  1017. TemporaryBuffer,
  1018. TemporaryBufferSize,
  1019. &ByteCount
  1020. );
  1021. if (!NT_SUCCESS(Status)) {
  1022. if (Status == STATUS_NO_MORE_ENTRIES)
  1023. Status = STATUS_SUCCESS;
  1024. break;
  1025. }
  1026. ValueFullInfo = (PKEY_VALUE_FULL_INFORMATION)TemporaryBuffer;
  1027. Len = ValueFullInfo->NameLength / sizeof(WCHAR);
  1028. wcsncpy(ValueName, ValueFullInfo->Name, Len);
  1029. ValueName[Len] = 0;
  1030. if ((!_wcsicmp(ValueName, VERIFIER_DRV_LEVEL)) &&
  1031. (ValueFullInfo->Type == REG_DWORD)) {
  1032. Flags = *(PDWORD)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset);
  1033. } else if ((!_wcsicmp(ValueName, VERIFIER_DRIVERS)) &&
  1034. (ValueFullInfo->Type == REG_SZ)) {
  1035. Len = ValueFullInfo->DataLength / sizeof(WCHAR);
  1036. wcsncpy(Drivers, (PWSTR)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset),
  1037. Len);
  1038. Drivers[Len] = 0;
  1039. }
  1040. }
  1041. //
  1042. // Query the IO level
  1043. //
  1044. for(Index=0; ;Index++){
  1045. Status = ZwEnumerateValueKey(
  1046. IOMgrKeyHandle,
  1047. Index,
  1048. KeyValueFullInformation,
  1049. TemporaryBuffer,
  1050. TemporaryBufferSize,
  1051. &ByteCount
  1052. );
  1053. if (!NT_SUCCESS(Status)) {
  1054. if (Status == STATUS_NO_MORE_ENTRIES)
  1055. Status = STATUS_SUCCESS;
  1056. break;
  1057. }
  1058. ValueFullInfo = (PKEY_VALUE_FULL_INFORMATION)TemporaryBuffer;
  1059. Len = ValueFullInfo->NameLength / sizeof(WCHAR);
  1060. wcsncpy(ValueName, ValueFullInfo->Name, Len);
  1061. ValueName[Len] = 0;
  1062. if ((!_wcsicmp(ValueName, VERIFIER_IO_LEVEL)) &&
  1063. (ValueFullInfo->Type == REG_DWORD)) {
  1064. IoLevel = *(PDWORD)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset);
  1065. }
  1066. }
  1067. if (IoLevel == 3)
  1068. IoLevel = 2;
  1069. else
  1070. IoLevel = 1;
  1071. //
  1072. // format the output and display it
  1073. //
  1074. swprintf((PWSTR)TemporaryBuffer, VERIFIER_QUERY_INFO,
  1075. Flags, IoLevel, Drivers);
  1076. RcTextOut((PWSTR)TemporaryBuffer);
  1077. } else {
  1078. //
  1079. // If IO verify bit is not set, then clear IoLevel
  1080. //
  1081. if (!(Flags & 0x10))
  1082. IoLevel = 0;
  1083. if (IoLevel == 2)
  1084. IoLevel = 3; // actual value stored in the registry
  1085. if (IoLevel != 3)
  1086. UseDefIoLevel = TRUE;
  1087. //
  1088. // set IO level
  1089. //
  1090. RtlInitUnicodeString(&UnicodeString, VERIFIER_IO_LEVEL);
  1091. if (UseDefIoLevel) {
  1092. Status = ZwDeleteValueKey(IOMgrKeyHandle, &UnicodeString);
  1093. } else {
  1094. Status = ZwSetValueKey(IOMgrKeyHandle, &UnicodeString, 0, REG_DWORD,
  1095. &IoLevel, sizeof(DWORD));
  1096. }
  1097. //
  1098. // set the DRV verification level
  1099. //
  1100. RtlInitUnicodeString(&UnicodeString, VERIFIER_DRV_LEVEL);
  1101. if (UseDefFlags) {
  1102. Status = ZwDeleteValueKey(MemMgrKeyHandle, &UnicodeString);
  1103. } else {
  1104. Status = ZwSetValueKey(MemMgrKeyHandle, &UnicodeString, 0, REG_DWORD,
  1105. &Flags, sizeof(DWORD));
  1106. }
  1107. //
  1108. // set the drivers to be verified
  1109. //
  1110. RtlInitUnicodeString(&UnicodeString, VERIFIER_DRIVERS);
  1111. if (Drivers[0]) {
  1112. Status = ZwSetValueKey(MemMgrKeyHandle, &UnicodeString, 0, REG_SZ,
  1113. Drivers, (wcslen(Drivers) + 1) * sizeof(WCHAR));
  1114. } else {
  1115. Status = ZwDeleteValueKey(MemMgrKeyHandle, &UnicodeString);
  1116. }
  1117. }
  1118. }
  1119. if (MemMgrKeyHandle)
  1120. ZwClose(MemMgrKeyHandle);
  1121. if (IOMgrKeyHandle)
  1122. ZwClose(IOMgrKeyHandle);
  1123. if (SysHiveOpened)
  1124. RcCloseHive(SYS_HIVE_KEY);
  1125. }
  1126. return 1;
  1127. }