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.

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