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.

1445 lines
40 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: Reg.cpp
  4. // Created: Jan 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Command-line registry manipulation (query, add, update, etc)
  7. // Modification History:
  8. // Created - Jan 1997 (a-martih)
  9. // Oct 1997 (martinho)
  10. // Fixed up help on Add and Update to display REG_MULTI_SZ examples.
  11. // Oct 1997 (martinho)
  12. // Changed /F to /FORCE under usage for delete
  13. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  14. //
  15. //-----------------------------------------------------------------------//
  16. #include "stdafx.h"
  17. #include "reg.h"
  18. #include <regstr.h>
  19. //
  20. // structures
  21. //
  22. typedef struct __tagRegDataTypes
  23. {
  24. DWORD dwType;
  25. LPCWSTR pwszType;
  26. } TREG_DATA_TYPE;
  27. //
  28. // defines / constants / enumerations
  29. //
  30. const WCHAR cwszRegSz[] = L"REG_SZ";
  31. const WCHAR cwszRegExpandSz[] = L"REG_EXPAND_SZ";
  32. const WCHAR cwszRegMultiSz[] = L"REG_MULTI_SZ";
  33. const WCHAR cwszRegBinary[] = L"REG_BINARY";
  34. const WCHAR cwszRegDWord[] = L"REG_DWORD";
  35. const WCHAR cwszRegDWordLittleEndian[] = L"REG_DWORD_LITTLE_ENDIAN";
  36. const WCHAR cwszRegDWordBigEndian[] = L"REG_DWORD_BIG_ENDIAN";
  37. const WCHAR cwszRegNone[] = L"REG_NONE";
  38. const WCHAR cwszRegLink[] = L"REG_LINK";
  39. const WCHAR cwszRegResourceList[] = L"REG_RESOURCE_LIST";
  40. const WCHAR cwszRegFullResourceDescriptor[] = L"REG_FULL_RESOURCE_DESCRIPTOR";
  41. const WCHAR g_wszOptions[ REG_OPTIONS_COUNT ][ 10 ] = {
  42. L"QUERY", L"ADD", L"DELETE",
  43. L"COPY", L"SAVE", L"RESTORE", L"LOAD",
  44. L"UNLOAD", L"COMPARE", L"EXPORT", L"IMPORT"
  45. };
  46. const TREG_DATA_TYPE g_regTypes[] = {
  47. { REG_SZ, cwszRegSz },
  48. { REG_EXPAND_SZ, cwszRegExpandSz },
  49. { REG_MULTI_SZ, cwszRegMultiSz },
  50. { REG_BINARY, cwszRegBinary },
  51. { REG_DWORD, cwszRegDWord },
  52. { REG_DWORD_LITTLE_ENDIAN, cwszRegDWordLittleEndian },
  53. { REG_DWORD_BIG_ENDIAN, cwszRegDWordBigEndian },
  54. { REG_NONE, cwszRegNone },
  55. { REG_LINK, cwszRegLink },
  56. { REG_RESOURCE_LIST, cwszRegResourceList },
  57. { REG_FULL_RESOURCE_DESCRIPTOR, cwszRegFullResourceDescriptor }
  58. };
  59. //
  60. // private functions
  61. //
  62. BOOL IsRegistryToolDisabled();
  63. BOOL ParseRegCmdLine( DWORD argc,
  64. LPCWSTR argv[],
  65. LONG* plOperation, BOOL* pbUsage );
  66. BOOL ParseMachineName( LPCWSTR pwszStr, PTREG_PARAMS pParams );
  67. LPWSTR AdjustKeyName( LPWSTR pwszStr );
  68. BOOL ParseKeyName( LPWSTR pwszStr, PTREG_PARAMS pParams );
  69. BOOL IsValidSubKey( LPCWSTR pwszSubKey );
  70. //------------------------------------------------------------------------//
  71. //
  72. // main()
  73. //
  74. //------------------------------------------------------------------------//
  75. DWORD __cdecl wmain( DWORD argc, LPCWSTR argv[] )
  76. {
  77. // local variables
  78. BOOL bUsage = FALSE;
  79. BOOL bResult = FALSE;
  80. DWORD dwExitCode = 0;
  81. LONG lOperation = 0;
  82. //
  83. // Determine the opertion - and pass control to the *deserving* function
  84. //
  85. bResult = ParseRegCmdLine( argc, argv, &lOperation, &bUsage );
  86. if ( bResult == FALSE )
  87. {
  88. dwExitCode = 1;
  89. ShowLastErrorEx( stderr, SLE_INTERNAL );
  90. }
  91. // check whether we need to display the usage
  92. else if ( bUsage == TRUE )
  93. {
  94. Usage( -1 );
  95. dwExitCode = 0;
  96. }
  97. // need to check the sub-option
  98. else
  99. {
  100. //
  101. // At this point we have a valid operation
  102. //
  103. switch( lOperation )
  104. {
  105. case REG_QUERY:
  106. dwExitCode = QueryRegistry( argc, argv );
  107. break;
  108. case REG_DELETE:
  109. dwExitCode = DeleteRegistry( argc, argv );
  110. break;
  111. case REG_ADD:
  112. dwExitCode = AddRegistry( argc, argv );
  113. break;
  114. case REG_COPY:
  115. dwExitCode = CopyRegistry( argc, argv );
  116. break;
  117. case REG_SAVE:
  118. dwExitCode = SaveHive( argc, argv );
  119. break;
  120. case REG_RESTORE:
  121. dwExitCode = RestoreHive( argc, argv );
  122. break;
  123. case REG_LOAD:
  124. dwExitCode = LoadHive( argc, argv );
  125. break;
  126. case REG_UNLOAD:
  127. dwExitCode = UnLoadHive( argc, argv );
  128. break;
  129. case REG_COMPARE:
  130. dwExitCode = CompareRegistry( argc, argv );
  131. break;
  132. case REG_EXPORT:
  133. dwExitCode = ExportRegistry( argc, argv );
  134. break;
  135. case REG_IMPORT:
  136. dwExitCode = ImportRegistry( argc, argv );
  137. break;
  138. default:
  139. break;
  140. }
  141. }
  142. ReleaseGlobals();
  143. return dwExitCode;
  144. }
  145. //------------------------------------------------------------------------//
  146. //
  147. // ParseRegCmdLine()
  148. // Find out the operation - each operation parses it's own cmd-line
  149. //
  150. //------------------------------------------------------------------------//
  151. BOOL ParseRegCmdLine( DWORD argc,
  152. LPCWSTR argv[],
  153. LONG* plOperation, BOOL* pbUsage )
  154. {
  155. // local variables
  156. LONG lIndex = 0;
  157. // check the input
  158. if ( argc == 0 || argv == NULL || plOperation == NULL || pbUsage == NULL )
  159. {
  160. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  161. return FALSE;
  162. }
  163. // just REG.EXE is error
  164. if ( argc == 1 )
  165. {
  166. SetReason( ERROR_INVALID_SYNTAX );
  167. return FALSE;
  168. }
  169. // prepare the parser data
  170. *pbUsage = FALSE;
  171. *plOperation = -1;
  172. for( lIndex = 0; lIndex < REG_OPTIONS_COUNT; lIndex++ )
  173. {
  174. if ( StringCompareEx( argv[ 1 ], g_wszOptions[ lIndex ], TRUE, 0 ) == 0 )
  175. {
  176. // ...
  177. *plOperation = lIndex;
  178. // check the GPO -- if GPO is enabled, we should block the
  179. // user from using the REGISTRY tool except to see the help
  180. if ( argc >= 3 &&
  181. IsRegistryToolDisabled() == TRUE &&
  182. InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == FALSE )
  183. {
  184. SetReason( GetResString2( IDS_REGDISABLED, 0 ) );
  185. return FALSE;
  186. }
  187. // ...
  188. return TRUE;
  189. }
  190. }
  191. // no option did match -- might be asking for help
  192. if ( InString( argv[ 1 ], L"-?|/?|-h|/h", TRUE ) == TRUE )
  193. {
  194. *pbUsage = TRUE;
  195. return TRUE;
  196. }
  197. // rest is invalid syntax
  198. SetReason2( 1, ERROR_INVALID_SYNTAX_EX, argv[ 1 ] );
  199. return FALSE;
  200. }
  201. BOOL
  202. InitGlobalData( LONG lOperation,
  203. PTREG_PARAMS pParams )
  204. {
  205. // check the input
  206. if ( pParams == NULL )
  207. {
  208. SetLastError( ERROR_INVALID_PARAMETER );
  209. return FALSE;
  210. }
  211. if ( lOperation < 0 || lOperation >= REG_OPTIONS_COUNT )
  212. {
  213. SetLastError( ERROR_INVALID_PARAMETER );
  214. return FALSE;
  215. }
  216. // init to zero's
  217. SecureZeroMemory( pParams, sizeof( TREG_PARAMS ) );
  218. pParams->lOperation = lOperation; // operation
  219. pParams->hRootKey = HKEY_LOCAL_MACHINE;
  220. pParams->lRegDataType = (lOperation == REG_QUERY) ? -1 : REG_SZ;
  221. pParams->bAllValues = FALSE;
  222. pParams->bUseRemoteMachine = FALSE;
  223. pParams->bCleanRemoteRootKey = FALSE;
  224. pParams->bForce = FALSE;
  225. pParams->bRecurseSubKeys = FALSE;
  226. pParams->pwszMachineName = NULL;
  227. pParams->pwszFullKey = NULL;
  228. pParams->pwszSubKey = NULL;
  229. pParams->pwszValueName = NULL;
  230. pParams->pwszValue = NULL;
  231. StringCopy( pParams->wszSeparator,
  232. L"\\0", SIZE_OF_ARRAY( pParams->wszSeparator ) );
  233. return TRUE;
  234. }
  235. //------------------------------------------------------------------------//
  236. //
  237. // FreeAppVars()
  238. //
  239. //------------------------------------------------------------------------//
  240. BOOL FreeGlobalData( PTREG_PARAMS pParams )
  241. {
  242. if ( pParams->bCleanRemoteRootKey == TRUE )
  243. {
  244. SafeCloseKey( &pParams->hRootKey );
  245. }
  246. FreeMemory( &pParams->pwszSubKey );
  247. FreeMemory( &pParams->pwszFullKey );
  248. FreeMemory( &pParams->pwszMachineName );
  249. FreeMemory( &pParams->pwszSearchData );
  250. FreeMemory( &pParams->pwszValueName );
  251. FreeMemory( &pParams->pwszValue );
  252. DestroyDynamicArray( &pParams->arrTypes );
  253. return TRUE;
  254. }
  255. //------------------------------------------------------------------------//
  256. //
  257. // Prompt() - Answer Y/N question if bForce == FALSE
  258. //
  259. //------------------------------------------------------------------------//
  260. LONG
  261. Prompt( LPCWSTR pwszFormat,
  262. LPCWSTR pwszValue,
  263. LPCWSTR pwszList, BOOL bForce )
  264. {
  265. // local variables
  266. WCHAR wch;
  267. LONG lIndex = 0;
  268. // check the input
  269. if ( pwszFormat == NULL || pwszList == NULL )
  270. {
  271. SetLastError( ERROR_INVALID_PARAMETER );
  272. return -1;
  273. }
  274. if ( bForce == TRUE )
  275. {
  276. return 1;
  277. }
  278. do
  279. {
  280. if ( pwszValue != NULL )
  281. {
  282. ShowMessageEx( stdout, 1, TRUE, pwszFormat, pwszValue );
  283. }
  284. else
  285. {
  286. ShowMessage( stdout, pwszFormat );
  287. }
  288. fflush( stdin );
  289. wch = (WCHAR) getwchar();
  290. } while ((lIndex = FindChar2( pwszList, wch, TRUE, 0 )) == -1);
  291. // check the character selected by the user
  292. // NOTE: we assume the resource string will have "Y" as the first character
  293. return (lIndex + 1);
  294. }
  295. // break down [\\MachineName\]keyName
  296. BOOL
  297. BreakDownKeyString( LPCWSTR pwszStr, PTREG_PARAMS pParams )
  298. {
  299. // local variables
  300. LONG lIndex = 0;
  301. DWORD dwLength = 0;
  302. LPWSTR pwszTemp = NULL;
  303. LPWSTR pwszTempStr = NULL;
  304. BOOL bResult = FALSE;
  305. // check the input
  306. if ( pwszStr == NULL || pParams == NULL )
  307. {
  308. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  309. return FALSE;
  310. }
  311. // check whether this function is being called for
  312. // valid operation or not
  313. if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT )
  314. {
  315. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  316. return FALSE;
  317. }
  318. dwLength = StringLength( pwszStr, 0 ) + 1;
  319. pwszTempStr = (LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) );
  320. if ( pwszTempStr == NULL )
  321. {
  322. SaveErrorMessage( -1 );
  323. return FALSE;
  324. }
  325. // copy the string name into temporary buffer
  326. StringCopy( pwszTempStr, pwszStr, dwLength );
  327. TrimString( pwszTempStr, TRIM_ALL );
  328. //
  329. // figure out machine name
  330. //
  331. bResult = TRUE;
  332. pwszTemp = pwszTempStr;
  333. // machine name
  334. if( StringLength( pwszTempStr, 0 ) > 2 &&
  335. StringCompareEx( pwszTempStr, L"\\\\", TRUE, 2 ) == 0 )
  336. {
  337. lIndex = FindChar2( pwszTempStr, L'\\', TRUE, 2 );
  338. if(lIndex != -1)
  339. {
  340. pwszTemp = pwszTempStr + lIndex + 1;
  341. *(pwszTempStr + lIndex) = cwchNullChar;
  342. }
  343. else
  344. {
  345. pwszTemp = NULL;
  346. }
  347. bResult = ParseMachineName( pwszTempStr, pParams );
  348. }
  349. // parse key name
  350. if( bResult == TRUE )
  351. {
  352. if( pwszTemp != NULL && StringLength( pwszTemp, 0 ) > 0)
  353. {
  354. bResult = ParseKeyName( pwszTemp, pParams );
  355. }
  356. else
  357. {
  358. SetLastError( (DWORD) REGDB_E_KEYMISSING );
  359. SetReason2( 1, ERROR_BADKEYNAME, g_wszOptions[ pParams->lOperation ] );
  360. bResult = FALSE;
  361. }
  362. }
  363. // release memory allocated
  364. FreeMemory( &pwszTempStr );
  365. // return
  366. return bResult;
  367. }
  368. //------------------------------------------------------------------------//
  369. //
  370. // FindAndAdjustKeyName()
  371. //
  372. // null out the cmdline based on what we think the end of the argument is
  373. //
  374. // we do this because users might not quote out the cmdline properly.
  375. //
  376. //------------------------------------------------------------------------//
  377. LPWSTR
  378. AdjustKeyName( LPWSTR pwszStr )
  379. {
  380. // local variables
  381. DWORD dwLength = 0;
  382. // check the input
  383. if ( pwszStr == NULL )
  384. {
  385. SetLastError( ERROR_INVALID_PARAMETER );
  386. return NULL;
  387. }
  388. // determine the length of the text passed
  389. dwLength = StringLength( pwszStr, 0 );
  390. if ( dwLength > 1 && pwszStr[ dwLength - 1 ] == L'\\' )
  391. {
  392. // nullify the last back slash
  393. pwszStr[ dwLength - 1 ] = cwchNullChar;
  394. }
  395. // return
  396. return pwszStr;
  397. }
  398. //------------------------------------------------------------------------//
  399. //
  400. // IsMachineName()
  401. //
  402. //------------------------------------------------------------------------//
  403. BOOL
  404. ParseMachineName( LPCWSTR pwszStr, PTREG_PARAMS pParams )
  405. {
  406. // local variables
  407. DWORD dwLength = 0;
  408. BOOL bUseRemoteMachine = FALSE;
  409. // check the input
  410. if ( pwszStr == NULL || pParams == NULL )
  411. {
  412. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  413. return FALSE;
  414. }
  415. //
  416. // copy string
  417. //
  418. bUseRemoteMachine = TRUE;
  419. if( StringCompareEx( pwszStr, L"\\\\", TRUE, 0 ) == 0 )
  420. {
  421. SetLastError( (DWORD) REGDB_E_KEYMISSING );
  422. SetReason2( 1, ERROR_BADKEYNAME, g_wszOptions[ pParams->lOperation ] );
  423. return FALSE;
  424. }
  425. else if(StringCompareEx( pwszStr, L"\\\\.", TRUE, 0) == 0)
  426. {
  427. // current machine -- local
  428. bUseRemoteMachine = FALSE;
  429. }
  430. dwLength = StringLength( pwszStr, 0 ) + 1;
  431. pParams->pwszMachineName = (LPWSTR) AllocateMemory( dwLength * sizeof(WCHAR) );
  432. if ( pParams->pwszMachineName == NULL )
  433. {
  434. SaveErrorMessage( -1 );
  435. return FALSE;
  436. }
  437. StringCopy( pParams->pwszMachineName, pwszStr, dwLength );
  438. pParams->bUseRemoteMachine = TRUE;
  439. SaveErrorMessage( ERROR_SUCCESS );
  440. return TRUE;
  441. }
  442. //------------------------------------------------------------------------//
  443. //
  444. // ParseKeyName()
  445. //
  446. // Pass the full registry path in szStr
  447. //
  448. // Based on input - Sets AppMember fields:
  449. //
  450. // hRootKey
  451. // szKey
  452. // szValueName
  453. // szValue
  454. //
  455. //------------------------------------------------------------------------//
  456. BOOL
  457. ParseKeyName( LPWSTR pwszStr,
  458. PTREG_PARAMS pParams )
  459. {
  460. // local variables
  461. LONG lIndex = 0;
  462. BOOL bResult = TRUE;
  463. DWORD dwSubKeySize = 0;
  464. DWORD dwRootKeySize = 0;
  465. DWORD dwFullKeySize = 0;
  466. LPWSTR pwszTemp = NULL;
  467. LPWSTR pwszRootKey = NULL;
  468. // check the input
  469. if ( pwszStr == NULL || pParams == NULL )
  470. {
  471. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  472. return FALSE;
  473. }
  474. // check whether this function is being called for
  475. // valid operation or not
  476. if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT )
  477. {
  478. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  479. return FALSE;
  480. }
  481. //
  482. // figure out what root key was specified
  483. //
  484. pwszTemp = NULL;
  485. lIndex = FindChar2( pwszStr, L'\\', TRUE, 0 );
  486. if (lIndex != -1)
  487. {
  488. pwszTemp = pwszStr + lIndex + 1;
  489. *(pwszStr + lIndex) = cwchNullChar;
  490. }
  491. if (*pwszStr == L'\"')
  492. {
  493. pwszStr += 1;
  494. }
  495. //
  496. // Check the ROOT has been entered
  497. //
  498. bResult = TRUE;
  499. dwRootKeySize = StringLength( STR_HKEY_CURRENT_CONFIG, 0 ) + 1;
  500. pwszRootKey = (LPWSTR) AllocateMemory( dwRootKeySize * sizeof(WCHAR) );
  501. if ( pwszRootKey == NULL)
  502. {
  503. SaveErrorMessage( -1 );
  504. return FALSE;
  505. }
  506. if (StringCompareEx( pwszStr, STR_HKCU, TRUE, 0) == 0 ||
  507. StringCompareEx( pwszStr, STR_HKEY_CURRENT_USER, TRUE, 0) == 0)
  508. {
  509. pParams->hRootKey = HKEY_CURRENT_USER;
  510. StringCopy( pwszRootKey, STR_HKEY_CURRENT_USER, dwRootKeySize );
  511. // check remotable and loadable
  512. if( pParams->bUseRemoteMachine == TRUE )
  513. {
  514. SetLastError( (DWORD) MK_E_SYNTAX );
  515. SetReason2( 1, ERROR_NONREMOTABLEROOT, g_wszOptions[ pParams->lOperation ] );
  516. bResult = FALSE;
  517. }
  518. else if( pParams->lOperation == REG_LOAD || pParams->lOperation == REG_UNLOAD )
  519. {
  520. SetLastError( (DWORD) MK_E_SYNTAX );
  521. SetReason2( 1, ERROR_NONLOADABLEROOT, g_wszOptions[ pParams->lOperation ] );
  522. bResult = FALSE;
  523. }
  524. }
  525. else if ( StringCompareEx( pwszStr, STR_HKCR, TRUE, 0 ) == 0 ||
  526. StringCompareEx( pwszStr, STR_HKEY_CLASSES_ROOT, TRUE, 0 ) == 0)
  527. {
  528. pParams->hRootKey = HKEY_CLASSES_ROOT;
  529. StringCopy( pwszRootKey, STR_HKEY_CLASSES_ROOT, dwRootKeySize );
  530. // check remotable and loadable
  531. if( pParams->bUseRemoteMachine == TRUE )
  532. {
  533. SetLastError( (DWORD) MK_E_SYNTAX );
  534. SetReason2( 1, ERROR_NONREMOTABLEROOT, g_wszOptions[ pParams->lOperation ] );
  535. bResult = FALSE;
  536. }
  537. else if( pParams->lOperation == REG_LOAD || pParams->lOperation == REG_UNLOAD )
  538. {
  539. SetLastError( (DWORD) MK_E_SYNTAX );
  540. SetReason2( 1, ERROR_NONLOADABLEROOT, g_wszOptions[ pParams->lOperation ] );
  541. bResult = FALSE;
  542. }
  543. }
  544. else if ( StringCompareEx( pwszStr, STR_HKCC, TRUE, 0 ) == 0 ||
  545. StringCompareEx( pwszStr, STR_HKEY_CURRENT_CONFIG, TRUE, 0 ) == 0)
  546. {
  547. pParams->hRootKey = HKEY_CURRENT_CONFIG;
  548. StringCopy( pwszRootKey, STR_HKEY_CURRENT_CONFIG, dwRootKeySize );
  549. // check remotable and loadable
  550. if( pParams->bUseRemoteMachine == TRUE )
  551. {
  552. SetLastError( (DWORD) MK_E_SYNTAX );
  553. SetReason2( 1, ERROR_NONREMOTABLEROOT, g_wszOptions[ pParams->lOperation ] );
  554. bResult = FALSE;
  555. }
  556. else if( pParams->lOperation == REG_LOAD ||
  557. pParams->lOperation == REG_UNLOAD )
  558. {
  559. SetLastError( (DWORD) MK_E_SYNTAX );
  560. SetReason2( 1, ERROR_NONLOADABLEROOT, g_wszOptions[ pParams->lOperation ] );
  561. bResult = FALSE;
  562. }
  563. }
  564. else if ( StringCompareEx( pwszStr, STR_HKLM, TRUE, 0 ) == 0 ||
  565. StringCompareEx( pwszStr, STR_HKEY_LOCAL_MACHINE, TRUE, 0 ) == 0)
  566. {
  567. pParams->hRootKey = HKEY_LOCAL_MACHINE;
  568. StringCopy( pwszRootKey, STR_HKEY_LOCAL_MACHINE, dwRootKeySize );
  569. }
  570. else if ( StringCompareEx( pwszStr, STR_HKU, TRUE, 0 ) == 0 ||
  571. StringCompareEx( pwszStr, STR_HKEY_USERS, TRUE, 0 ) == 0 )
  572. {
  573. pParams->hRootKey = HKEY_USERS;
  574. StringCopy( pwszRootKey, STR_HKEY_USERS, dwRootKeySize );
  575. }
  576. else
  577. {
  578. SetLastError( (DWORD) MK_E_SYNTAX );
  579. SetReason2( 1, ERROR_BADKEYNAME, g_wszOptions[ pParams->lOperation ] );
  580. bResult = FALSE;
  581. }
  582. if( bResult == TRUE )
  583. {
  584. //
  585. // parse the subkey
  586. //
  587. if ( pwszTemp == NULL )
  588. {
  589. // only root key, subkey is empty
  590. pParams->pwszSubKey = (LPWSTR) AllocateMemory( 1 * sizeof( WCHAR ) );
  591. if ( pParams->pwszSubKey == NULL)
  592. {
  593. SaveErrorMessage( -1 );
  594. bResult = FALSE;
  595. }
  596. else
  597. {
  598. pParams->pwszFullKey =
  599. (LPWSTR) AllocateMemory( dwRootKeySize * sizeof(WCHAR) );
  600. if ( pParams->pwszFullKey == NULL )
  601. {
  602. SaveErrorMessage( -1 );
  603. bResult = FALSE;
  604. }
  605. StringCopy( pParams->pwszFullKey, pwszRootKey, dwRootKeySize );
  606. }
  607. }
  608. else
  609. {
  610. //
  611. // figure out what root key was specified
  612. //
  613. pwszTemp = AdjustKeyName( pwszTemp );
  614. if ( IsValidSubKey( pwszTemp ) == FALSE )
  615. {
  616. bResult = FALSE;
  617. if ( GetLastError() == ERROR_INVALID_PARAMETER )
  618. {
  619. SaveErrorMessage( -1 );
  620. }
  621. else
  622. {
  623. SetLastError( (DWORD) MK_E_SYNTAX );
  624. SetReason2( 1, ERROR_BADKEYNAME, g_wszOptions[ pParams->lOperation ] );
  625. }
  626. }
  627. else
  628. {
  629. // get subkey
  630. dwSubKeySize = StringLength( pwszTemp, 0 ) + 1;
  631. pParams->pwszSubKey =
  632. (LPWSTR) AllocateMemory( dwSubKeySize * sizeof(WCHAR) );
  633. if( pParams->pwszSubKey == NULL )
  634. {
  635. SaveErrorMessage( -1 );
  636. bResult = FALSE;
  637. }
  638. else
  639. {
  640. StringCopy( pParams->pwszSubKey, pwszTemp, dwSubKeySize );
  641. // get fullkey ( +2 ==> "/" + buffer )
  642. dwFullKeySize = dwRootKeySize + dwSubKeySize + 2;
  643. pParams->pwszFullKey =
  644. (LPWSTR) AllocateMemory( dwFullKeySize * sizeof(WCHAR) );
  645. if ( pParams->pwszFullKey == NULL )
  646. {
  647. SaveErrorMessage( -1 );
  648. bResult = FALSE;
  649. }
  650. else
  651. {
  652. StringCopy( pParams->pwszFullKey, pwszRootKey, dwFullKeySize );
  653. StringConcat( pParams->pwszFullKey, L"\\", dwFullKeySize );
  654. StringConcat( pParams->pwszFullKey, pParams->pwszSubKey, dwFullKeySize );
  655. }
  656. }
  657. }
  658. }
  659. }
  660. FreeMemory( &pwszRootKey );
  661. return bResult;
  662. }
  663. BOOL
  664. IsValidSubKey( LPCWSTR pwszSubKey )
  665. {
  666. // local variables
  667. LONG lLength = 0;
  668. LONG lIndex = -1;
  669. LONG lPrevIndex = -1;
  670. if ( pwszSubKey == NULL )
  671. {
  672. SetLastError( ERROR_INVALID_PARAMETER );
  673. return FALSE;
  674. }
  675. else if ( StringLength( pwszSubKey, 0 ) == 0 )
  676. {
  677. SetLastError( (DWORD) NTE_BAD_KEY );
  678. return FALSE;
  679. }
  680. do
  681. {
  682. if ( lIndex != lPrevIndex )
  683. {
  684. if ( lIndex - lPrevIndex == 1 || lIndex - lPrevIndex > 255 )
  685. {
  686. SetLastError( (DWORD) NTE_BAD_KEY );
  687. return FALSE;
  688. }
  689. lPrevIndex = lIndex;
  690. }
  691. } while ((lIndex = FindChar2( pwszSubKey, L'\\', TRUE, lIndex + 1 )) != -1 );
  692. // get the length of the subkey
  693. lLength = StringLength( pwszSubKey, 0 );
  694. if ( lPrevIndex == lLength - 1 ||
  695. (lPrevIndex == -1 && lLength > 255) || (lLength - lPrevIndex > 255) )
  696. {
  697. SetLastError( (DWORD) NTE_BAD_KEY );
  698. return FALSE;
  699. }
  700. SetLastError( NO_ERROR );
  701. return TRUE;
  702. }
  703. //------------------------------------------------------------------------//
  704. //
  705. // IsRegDataType()
  706. //
  707. //------------------------------------------------------------------------//
  708. LONG
  709. IsRegDataType( LPCWSTR pwszStr )
  710. {
  711. // local variables
  712. LONG lResult = -1;
  713. LPWSTR pwszDup = NULL;
  714. if ( pwszStr == NULL )
  715. {
  716. SetLastError( ERROR_INVALID_PARAMETER );
  717. return -1;
  718. }
  719. // create a duplicate string of the input string
  720. pwszDup = StrDup( pwszStr );
  721. if ( pwszDup == NULL )
  722. {
  723. SetLastError( ERROR_OUTOFMEMORY );
  724. return -1;
  725. }
  726. // remove the unwanted spaces and tab characters
  727. TrimString2( pwszDup, NULL, TRIM_ALL );
  728. if( StringCompareEx( pwszDup, cwszRegSz, TRUE, 0 ) == 0)
  729. {
  730. lResult = REG_SZ;
  731. }
  732. else if( StringCompareEx( pwszDup, cwszRegExpandSz, TRUE, 0 ) == 0)
  733. {
  734. lResult = REG_EXPAND_SZ;
  735. }
  736. else if( StringCompareEx( pwszDup, cwszRegMultiSz, TRUE, 0 ) == 0)
  737. {
  738. lResult = REG_MULTI_SZ;
  739. }
  740. else if( StringCompareEx( pwszDup, cwszRegBinary, TRUE, 0 ) == 0)
  741. {
  742. lResult = REG_BINARY;
  743. }
  744. else if( StringCompareEx( pwszDup, cwszRegDWord, TRUE, 0 ) == 0)
  745. {
  746. lResult = REG_DWORD;
  747. }
  748. else if( StringCompareEx( pwszDup, cwszRegDWordLittleEndian, TRUE, 0 ) == 0)
  749. {
  750. lResult = REG_DWORD_LITTLE_ENDIAN;
  751. }
  752. else if( StringCompareEx( pwszDup, cwszRegDWordBigEndian, TRUE, 0 ) == 0)
  753. {
  754. lResult = REG_DWORD_BIG_ENDIAN;
  755. }
  756. else if( StringCompareEx( pwszDup, cwszRegNone, TRUE, 0) == 0 )
  757. {
  758. lResult = REG_NONE;
  759. }
  760. // free the memory
  761. LocalFree( pwszDup );
  762. pwszDup = NULL;
  763. // ...
  764. SetLastError( NO_ERROR );
  765. return lResult;
  766. }
  767. //------------------------------------------------------------------------//
  768. //
  769. // Usage() - Display Usage Information
  770. //
  771. //------------------------------------------------------------------------//
  772. BOOL
  773. Usage( LONG lOperation )
  774. {
  775. // display the banner
  776. ShowMessage( stdout, L"\n" );
  777. // display the help based on the operation
  778. switch( lOperation )
  779. {
  780. case REG_QUERY:
  781. ShowResMessage( stdout, IDS_USAGE_QUERY1 );
  782. ShowResMessage( stdout, IDS_USAGE_QUERY2 );
  783. ShowResMessage( stdout, IDS_USAGE_QUERY3 );
  784. break;
  785. case REG_ADD:
  786. ShowResMessage( stdout, IDS_USAGE_ADD1 );
  787. ShowResMessage( stdout, IDS_USAGE_ADD2 );
  788. break;
  789. case REG_DELETE:
  790. ShowResMessage( stdout, IDS_USAGE_DELETE );
  791. break;
  792. case REG_COPY:
  793. ShowResMessage( stdout, IDS_USAGE_COPY );
  794. break;
  795. case REG_SAVE:
  796. ShowResMessage( stdout, IDS_USAGE_SAVE );
  797. break;
  798. case REG_RESTORE:
  799. ShowResMessage( stdout, IDS_USAGE_RESTORE );
  800. break;
  801. case REG_LOAD:
  802. ShowResMessage( stdout, IDS_USAGE_LOAD );
  803. break;
  804. case REG_UNLOAD:
  805. ShowResMessage( stdout, IDS_USAGE_UNLOAD );
  806. break;
  807. case REG_COMPARE:
  808. ShowResMessage( stdout, IDS_USAGE_COMPARE1 );
  809. ShowResMessage( stdout, IDS_USAGE_COMPARE2 );
  810. break;
  811. case REG_EXPORT:
  812. ShowResMessage( stdout, IDS_USAGE_EXPORT );
  813. break;
  814. case REG_IMPORT:
  815. ShowResMessage( stdout, IDS_USAGE_IMPORT );
  816. break;
  817. case -1:
  818. default:
  819. ShowResMessage( stdout, IDS_USAGE_REG );
  820. break;
  821. }
  822. return TRUE;
  823. }
  824. BOOL
  825. RegConnectMachine( PTREG_PARAMS pParams )
  826. {
  827. // local variables
  828. LONG lResult = 0;
  829. HKEY hKeyConnect = NULL;
  830. // check the input
  831. if ( pParams == NULL )
  832. {
  833. SetLastError( ERROR_INVALID_PARAMETER );
  834. return FALSE;
  835. }
  836. lResult = ERROR_SUCCESS;
  837. if ( pParams->bUseRemoteMachine == TRUE )
  838. {
  839. // close the remote key
  840. if( pParams->hRootKey != NULL &&
  841. pParams->bCleanRemoteRootKey == TRUE )
  842. {
  843. SafeCloseKey( &pParams->hRootKey );
  844. }
  845. // connect to remote key
  846. lResult = RegConnectRegistry(
  847. pParams->pwszMachineName, pParams->hRootKey, &hKeyConnect);
  848. if( lResult == ERROR_SUCCESS )
  849. {
  850. // sanity check
  851. if ( hKeyConnect != NULL )
  852. {
  853. pParams->hRootKey = hKeyConnect;
  854. pParams->bCleanRemoteRootKey = TRUE;
  855. }
  856. else
  857. {
  858. lResult = ERROR_PROCESS_ABORTED;
  859. }
  860. }
  861. }
  862. SetLastError( lResult );
  863. return (lResult == ERROR_SUCCESS);
  864. }
  865. BOOL
  866. SaveErrorMessage( LONG lLastError )
  867. {
  868. // local variables
  869. DWORD dwLastError = 0;
  870. dwLastError = (lLastError < 0) ? GetLastError() : (DWORD) lLastError;
  871. switch( dwLastError )
  872. {
  873. case ERROR_FILE_NOT_FOUND:
  874. case ERROR_PATH_NOT_FOUND:
  875. {
  876. SetReason( ERROR_PATHNOTFOUND );
  877. break;
  878. }
  879. default:
  880. {
  881. SetLastError( dwLastError );
  882. SaveLastError();
  883. break;
  884. }
  885. }
  886. return TRUE;
  887. }
  888. LPCWSTR
  889. GetTypeStrFromType( LPWSTR pwszTypeStr,
  890. DWORD* pdwLength, DWORD dwType )
  891. {
  892. // local variables
  893. DWORD dw = 0;
  894. LPCWSTR pwsz = NULL;
  895. for( dw = 0; dw < SIZE_OF_ARRAY( g_regTypes ); dw++ )
  896. {
  897. if ( dwType == g_regTypes[ dw ].dwType )
  898. {
  899. pwsz = g_regTypes[ dw ].pwszType;
  900. break;
  901. }
  902. }
  903. if ( pwsz == NULL )
  904. {
  905. SetLastError( ERROR_NOT_FOUND );
  906. pwsz = cwszRegNone;
  907. }
  908. // check the input buffers passed by the caller
  909. if ( pwszTypeStr == NULL )
  910. {
  911. if ( pdwLength != NULL )
  912. {
  913. *pdwLength = StringLength( pwsz, 0 );
  914. }
  915. }
  916. else if ( pdwLength == NULL || *pdwLength == 0 )
  917. {
  918. SetLastError( ERROR_INVALID_PARAMETER );
  919. pwsz = cwszNullString;
  920. }
  921. else
  922. {
  923. StringCopy( pwszTypeStr, pwsz, *pdwLength );
  924. }
  925. // return
  926. return pwsz;
  927. }
  928. BOOL
  929. ShowRegistryValue( PTREG_SHOW_INFO pShowInfo )
  930. {
  931. // local variables
  932. DWORD dw = 0;
  933. DWORD dwSize = 0;
  934. LPCWSTR pwszEnd = NULL;
  935. LPBYTE pByteData = NULL;
  936. BOOL bShowSeparator = FALSE;
  937. LPCWSTR pwszSeparator = NULL;
  938. LPCWSTR pwszValueName = NULL;
  939. // check the input
  940. if ( pShowInfo == NULL )
  941. {
  942. SetLastError( ERROR_INVALID_PARAMETER );
  943. return FALSE;
  944. }
  945. // validate and the show the contents
  946. // ignore mask
  947. if ( (pShowInfo->dwFlags & RSI_IGNOREMASK) == RSI_IGNOREMASK )
  948. {
  949. return TRUE;
  950. }
  951. // check if the padding is required or not
  952. if ( pShowInfo->dwPadLength != 0 )
  953. {
  954. ShowMessageEx( stdout, 1, TRUE, L"%*s", pShowInfo->dwPadLength, L" " );
  955. }
  956. // value name
  957. if ( (pShowInfo->dwFlags & RSI_IGNOREVALUENAME) == 0 )
  958. {
  959. if ( pShowInfo->pwszValueName == NULL )
  960. {
  961. SetLastError( ERROR_INVALID_PARAMETER );
  962. return FALSE;
  963. }
  964. // alignment flag and separator cannot go along
  965. if ( pShowInfo->pwszSeparator != NULL &&
  966. (pShowInfo->dwFlags & RSI_ALIGNVALUENAME) )
  967. {
  968. SetLastError( ERROR_INVALID_PARAMETER );
  969. return FALSE;
  970. }
  971. // valuename = no name
  972. pwszValueName = pShowInfo->pwszValueName;
  973. if( StringLength( pwszValueName, 0 ) == 0 )
  974. {
  975. pwszValueName = GetResString2( IDS_NONAME, 0 );
  976. }
  977. // alignment
  978. if ( pShowInfo->dwFlags & RSI_ALIGNVALUENAME )
  979. {
  980. if ( pShowInfo->dwMaxValueNameLength == 0 )
  981. {
  982. SetLastError( ERROR_INVALID_PARAMETER );
  983. return FALSE;
  984. }
  985. // show the value name
  986. ShowMessageEx( stdout, 2, TRUE, L"%-*s",
  987. pShowInfo->dwMaxValueNameLength, pwszValueName );
  988. }
  989. else
  990. {
  991. ShowMessage( stdout, pwszValueName );
  992. }
  993. // display the separator
  994. if ( pShowInfo->pwszSeparator != NULL )
  995. {
  996. ShowMessage( stdout, pShowInfo->pwszSeparator );
  997. }
  998. else
  999. {
  1000. ShowMessage( stdout, L" " );
  1001. }
  1002. }
  1003. // type
  1004. if ( (pShowInfo->dwFlags & RSI_IGNORETYPE) == 0 )
  1005. {
  1006. if ( pShowInfo->dwFlags & RSI_SHOWTYPENUMBER )
  1007. {
  1008. ShowMessageEx( stdout, 2, TRUE, L"%s (%d)",
  1009. GetTypeStrFromType( NULL, NULL, pShowInfo->dwType ), pShowInfo->dwType );
  1010. }
  1011. else
  1012. {
  1013. ShowMessage( stdout,
  1014. GetTypeStrFromType( NULL, NULL, pShowInfo->dwType ) );
  1015. }
  1016. // display the separator
  1017. if ( pShowInfo->pwszSeparator != NULL )
  1018. {
  1019. ShowMessage( stdout, pShowInfo->pwszSeparator );
  1020. }
  1021. else
  1022. {
  1023. ShowMessage( stdout, L" " );
  1024. }
  1025. }
  1026. // value
  1027. if ( (pShowInfo->dwFlags & RSI_IGNOREVALUE) == 0 )
  1028. {
  1029. dwSize = pShowInfo->dwSize;
  1030. pByteData = pShowInfo->pByteData;
  1031. if ( pByteData == NULL )
  1032. {
  1033. SetLastError( ERROR_INVALID_PARAMETER );
  1034. return FALSE;
  1035. }
  1036. else if ( dwSize != 0 )
  1037. {
  1038. switch( pShowInfo->dwType )
  1039. {
  1040. default:
  1041. case REG_LINK:
  1042. case REG_BINARY:
  1043. case REG_RESOURCE_LIST:
  1044. case REG_FULL_RESOURCE_DESCRIPTOR:
  1045. {
  1046. for( dw = 0; dw < dwSize; dw++ )
  1047. {
  1048. ShowMessageEx( stdout, 1, TRUE, L"%02X", pByteData[ dw ] );
  1049. }
  1050. break;
  1051. }
  1052. case REG_SZ:
  1053. case REG_EXPAND_SZ:
  1054. {
  1055. ShowMessage( stdout, (LPCWSTR) pByteData );
  1056. break;
  1057. }
  1058. case REG_DWORD:
  1059. case REG_DWORD_BIG_ENDIAN:
  1060. {
  1061. ShowMessageEx( stdout, 1, TRUE, L"0x%x", *((DWORD*) pByteData) );
  1062. break;
  1063. }
  1064. case REG_MULTI_SZ:
  1065. {
  1066. //
  1067. // Replace '\0' with "\0" for MULTI_SZ
  1068. //
  1069. pwszSeparator = L"\\0";
  1070. if ( pShowInfo->pwszMultiSzSeparator != NULL )
  1071. {
  1072. pwszSeparator = pShowInfo->pwszMultiSzSeparator;
  1073. }
  1074. // ...
  1075. pwszEnd = (LPCWSTR) pByteData;
  1076. while( ((BYTE*) pwszEnd) < (pByteData + dwSize) )
  1077. {
  1078. if( *pwszEnd == 0 )
  1079. {
  1080. // enable the display of value separator and skip this
  1081. pwszEnd++;
  1082. bShowSeparator = TRUE;
  1083. }
  1084. else
  1085. {
  1086. // check whether we need to display the separator or not
  1087. if ( bShowSeparator == TRUE )
  1088. {
  1089. ShowMessage( stdout, pwszSeparator );
  1090. }
  1091. ShowMessage( stdout, pwszEnd );
  1092. pwszEnd += StringLength( pwszEnd, 0 );
  1093. }
  1094. }
  1095. break;
  1096. }
  1097. }
  1098. }
  1099. }
  1100. // ...
  1101. ShowMessage( stdout, L"\n" );
  1102. // return
  1103. return TRUE;
  1104. }
  1105. LPWSTR
  1106. GetTemporaryFileName( LPCWSTR pwszSavedFilePath )
  1107. {
  1108. // local variables
  1109. LONG lIndex = 0;
  1110. DWORD dwTemp = 0;
  1111. DWORD dwPathLength = 0;
  1112. DWORD dwFileNameLength = 0;
  1113. LPWSTR pwszPath = NULL;
  1114. LPWSTR pwszFileName = NULL;
  1115. // allocate memory for path info
  1116. dwPathLength = MAX_PATH;
  1117. pwszPath = (LPWSTR) AllocateMemory( (dwPathLength + 1) * sizeof( WCHAR ) );
  1118. if ( pwszPath == NULL )
  1119. {
  1120. SetLastError( ERROR_OUTOFMEMORY );
  1121. return NULL;
  1122. }
  1123. //
  1124. // get the temporary path location
  1125. dwTemp = GetTempPath( dwPathLength, pwszPath );
  1126. if ( dwTemp == 0 )
  1127. {
  1128. FreeMemory( &pwszPath );
  1129. return NULL;
  1130. }
  1131. else if ( dwTemp >= dwPathLength )
  1132. {
  1133. dwPathLength = dwTemp + 2;
  1134. if ( ReallocateMemory( &pwszPath, (dwPathLength + 1) * sizeof( WCHAR ) ) == FALSE )
  1135. {
  1136. FreeMemory( &pwszPath );
  1137. SetLastError( ERROR_OUTOFMEMORY );
  1138. return NULL;
  1139. }
  1140. // this is a simple and silly check being done just to overcome the
  1141. // PREfix error -- ReAllocateMemory function will not return TRUE
  1142. // when the memory is not successfully allocated
  1143. if ( pwszPath == NULL )
  1144. {
  1145. SetLastError( ERROR_OUTOFMEMORY );
  1146. return NULL;
  1147. }
  1148. // try to get temporary path again
  1149. dwTemp = GetTempPath( dwPathLength, pwszPath );
  1150. if ( dwTemp == 0 )
  1151. {
  1152. FreeMemory( &pwszPath );
  1153. return NULL;
  1154. }
  1155. else if ( dwTemp >= dwPathLength )
  1156. {
  1157. FreeMemory( &pwszPath );
  1158. SetLastError( (DWORD) STG_E_UNKNOWN );
  1159. return FALSE;
  1160. }
  1161. }
  1162. //
  1163. // get the temporary file name
  1164. dwFileNameLength = MAX_PATH;
  1165. pwszFileName = (LPWSTR) AllocateMemory( (dwFileNameLength + 1) * sizeof( WCHAR ) );
  1166. if ( pwszFileName == NULL )
  1167. {
  1168. FreeMemory( &pwszPath );
  1169. SetLastError( ERROR_OUTOFMEMORY );
  1170. return NULL;
  1171. }
  1172. // ...
  1173. dwTemp = GetTempFileName( pwszPath, L"REG", 0, pwszFileName );
  1174. if ( dwTemp == 0 )
  1175. {
  1176. if ( pwszSavedFilePath != NULL &&
  1177. GetLastError() == ERROR_ACCESS_DENIED )
  1178. {
  1179. SetLastError( ERROR_ACCESS_DENIED );
  1180. lIndex = StringLength( pwszSavedFilePath, 0 ) - 1;
  1181. for( ; lIndex >= 0; lIndex-- )
  1182. {
  1183. if ( pwszSavedFilePath[ lIndex ] == L'\\' )
  1184. {
  1185. if ( lIndex >= (LONG) dwPathLength )
  1186. {
  1187. dwPathLength = lIndex + 1;
  1188. if ( ReallocateMemory( &pwszPath, (dwPathLength + 5) ) == FALSE )
  1189. {
  1190. FreeMemory( &pwszPath );
  1191. FreeMemory( &pwszFileName );
  1192. return NULL;
  1193. }
  1194. }
  1195. // ...
  1196. StringCopy( pwszPath, pwszSavedFilePath, lIndex );
  1197. // break from the loop
  1198. break;
  1199. }
  1200. }
  1201. // check whether we got the path information or not
  1202. dwTemp = 0;
  1203. if ( lIndex == -1 )
  1204. {
  1205. StringCopy( pwszPath, L".", MAX_PATH );
  1206. }
  1207. // now again try to get the temporary file name
  1208. dwTemp = GetTempFileName( pwszPath, L"REG", 0, pwszFileName );
  1209. // ...
  1210. if ( dwTemp == 0 )
  1211. {
  1212. FreeMemory( &pwszPath );
  1213. FreeMemory( &pwszFileName );
  1214. return NULL;
  1215. }
  1216. }
  1217. else
  1218. {
  1219. FreeMemory( &pwszPath );
  1220. FreeMemory( &pwszFileName );
  1221. return NULL;
  1222. }
  1223. }
  1224. // release the memory allocated for path variable
  1225. FreeMemory( &pwszPath );
  1226. // since the API already created the file -- need to delete and pass just
  1227. // the file name to the caller
  1228. if ( DeleteFile( pwszFileName ) == FALSE )
  1229. {
  1230. FreeMemory( &pwszPath );
  1231. return FALSE;
  1232. }
  1233. // return temporary file name generated
  1234. return pwszFileName;
  1235. }
  1236. BOOL IsRegistryToolDisabled()
  1237. {
  1238. // local variables
  1239. HKEY hKey = NULL;
  1240. DWORD dwType = 0;
  1241. DWORD dwValue = 0;
  1242. DWORD dwLength = 0;
  1243. BOOL bRegistryToolDisabled = FALSE;
  1244. bRegistryToolDisabled = FALSE;
  1245. if ( RegOpenKey( HKEY_CURRENT_USER,
  1246. REGSTR_PATH_POLICIES TEXT("\\") REGSTR_KEY_SYSTEM,
  1247. &hKey ) == ERROR_SUCCESS )
  1248. {
  1249. dwLength = sizeof( DWORD );
  1250. if ( RegQueryValueEx( hKey,
  1251. REGSTR_VAL_DISABLEREGTOOLS,
  1252. NULL, &dwType, (LPBYTE) &dwValue, &dwLength ) == ERROR_SUCCESS )
  1253. {
  1254. if ( (dwType == REG_DWORD) && (dwLength == sizeof(DWORD)) && (dwValue != FALSE) )
  1255. {
  1256. bRegistryToolDisabled = TRUE;
  1257. }
  1258. }
  1259. SafeCloseKey( &hKey );
  1260. }
  1261. return bRegistryToolDisabled;
  1262. }