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.

711 lines
19 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: save.cpp
  4. // Created: March 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Save Support for REG.CPP
  7. // Modification History:
  8. // Copied from Copy.cpp and modificd - May 1997 (a-martih)
  9. // Aug 1997 - MartinHo
  10. // Fixed bug which didn't allow you to specify a ROOT key.
  11. // Example REG SAVE HKLM\Software didn't work - but should have
  12. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  13. //
  14. //------------------------------------------------------------------------//
  15. #include "stdafx.h"
  16. #include "reg.h"
  17. //
  18. // function prototypes
  19. //
  20. LONG RegAdjustTokenPrivileges( LPCWSTR pwszMachine,
  21. LPCWSTR pwszPrivilege, LONG lAttribute );
  22. BOOL ParseSaveCmdLine( DWORD argc, LPCWSTR argv[],
  23. LPCWSTR pwszOption, PTREG_PARAMS pParams, BOOL* pbUsage );
  24. BOOL ParseUnLoadCmdLine( DWORD argc, LPCWSTR argv[],
  25. PTREG_PARAMS pParams, BOOL* pbUsage );
  26. //
  27. // implementation
  28. //
  29. //-----------------------------------------------------------------------//
  30. //
  31. // SaveHive()
  32. //
  33. //-----------------------------------------------------------------------//
  34. LONG
  35. SaveHive( DWORD argc, LPCWSTR argv[] )
  36. {
  37. // local variables
  38. LONG lResult = 0;
  39. BOOL bResult = TRUE;
  40. HKEY hKey = NULL;
  41. BOOL bUsage = FALSE;
  42. TREG_PARAMS params;
  43. LPCWSTR pwszList = NULL;
  44. LPCWSTR pwszFormat = NULL;
  45. if ( argc == 0 || argv == NULL )
  46. {
  47. SetLastError( ERROR_INVALID_PARAMETER );
  48. ShowLastError( stderr );
  49. return 1;
  50. }
  51. // initialize the global data structure
  52. InitGlobalData( REG_SAVE, &params );
  53. //
  54. // Parse the cmd-line
  55. //
  56. bResult = ParseSaveCmdLine( argc, argv, L"SAVE", &params, &bUsage );
  57. if( bResult == FALSE )
  58. {
  59. ShowLastErrorEx( stderr, SLE_INTERNAL );
  60. FreeGlobalData( &params );
  61. return 1;
  62. }
  63. // check whether we need to display the usage
  64. if ( bUsage == TRUE )
  65. {
  66. Usage( REG_SAVE );
  67. FreeGlobalData( &params );
  68. return 0;
  69. }
  70. //
  71. // Connect to the Remote Machine - if applicable
  72. //
  73. bResult = RegConnectMachine( &params );
  74. if( bResult == FALSE )
  75. {
  76. SaveErrorMessage( -1 );
  77. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  78. FreeGlobalData( &params );
  79. return 1;
  80. }
  81. //
  82. // Open the key
  83. //
  84. lResult = RegOpenKeyEx( params.hRootKey, params.pwszSubKey, 0, KEY_READ, &hKey );
  85. if( lResult == ERROR_SUCCESS )
  86. {
  87. //
  88. // Acquire the necessary privilages and call the API
  89. //
  90. lResult = RegAdjustTokenPrivileges(
  91. params.pwszMachineName, SE_BACKUP_NAME, SE_PRIVILEGE_ENABLED);
  92. if( lResult == ERROR_SUCCESS )
  93. {
  94. lResult = RegSaveKeyEx( hKey, params.pwszValueName, NULL, REG_NO_COMPRESSION );
  95. if ( lResult == ERROR_ALREADY_EXISTS )
  96. {
  97. // load the format strings
  98. pwszFormat = GetResString2( IDS_SAVE_OVERWRITE_CONFIRM, 0 );
  99. pwszList = GetResString2( IDS_CONFIRM_CHOICE_LIST, 1 );
  100. // ...
  101. do
  102. {
  103. lResult = Prompt( pwszFormat,
  104. params.pwszValueName, pwszList, params.bForce );
  105. } while ( lResult > 2 );
  106. if( lResult != 1 )
  107. {
  108. lResult = ERROR_CANCELLED;
  109. }
  110. else
  111. {
  112. // since there are chances of getting access problems --
  113. // instead of deleting the existing file, we will try to
  114. // save the data using temporary file name and then transfer
  115. // the contents to the orignal filename
  116. params.pwszValue = params.pwszValueName;
  117. params.pwszValueName = GetTemporaryFileName( params.pwszValueName );
  118. if ( params.pwszValueName == NULL )
  119. {
  120. lResult = GetLastError();
  121. }
  122. else
  123. {
  124. // try to save
  125. lResult = RegSaveKey( hKey, params.pwszValueName, NULL );
  126. // check the result of the operation
  127. if ( lResult == ERROR_SUCCESS )
  128. {
  129. bResult = CopyFile(
  130. params.pwszValueName,
  131. params.pwszValue, FALSE );
  132. if ( bResult == FALSE )
  133. {
  134. lResult = GetLastError();
  135. }
  136. }
  137. // ...
  138. DeleteFile( params.pwszValueName );
  139. }
  140. }
  141. }
  142. else
  143. {
  144. switch( lResult )
  145. {
  146. case ERROR_INVALID_PARAMETER:
  147. {
  148. lResult = ERROR_FILENAME_EXCED_RANGE;
  149. break;
  150. }
  151. default:
  152. break;
  153. }
  154. }
  155. }
  156. SafeCloseKey( &hKey );
  157. }
  158. // display the result
  159. SaveErrorMessage( lResult );
  160. if ( lResult == ERROR_SUCCESS || lResult == ERROR_CANCELLED )
  161. {
  162. lResult = 0;
  163. ShowLastErrorEx( stdout, SLE_INTERNAL );
  164. }
  165. else
  166. {
  167. lResult = 1;
  168. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  169. }
  170. // return
  171. FreeGlobalData( &params );
  172. return lResult;
  173. }
  174. //-----------------------------------------------------------------------//
  175. //
  176. // RestoreHive()
  177. //
  178. //-----------------------------------------------------------------------//
  179. LONG
  180. RestoreHive( DWORD argc, LPCWSTR argv[] )
  181. {
  182. // local variables
  183. LONG lResult = 0;
  184. BOOL bResult = FALSE;
  185. HKEY hKey = NULL;
  186. BOOL bUsage = FALSE;
  187. TREG_PARAMS params;
  188. if ( argc == 0 || argv == NULL )
  189. {
  190. SetLastError( ERROR_INVALID_PARAMETER );
  191. ShowLastError( stderr );
  192. return 1;
  193. }
  194. // initialize the global data structure
  195. InitGlobalData( REG_RESTORE, &params );
  196. //
  197. // Parse the cmd-line
  198. //
  199. bResult = ParseSaveCmdLine( argc, argv, L"RESTORE", &params, &bUsage );
  200. if( bResult == FALSE )
  201. {
  202. ShowLastErrorEx( stderr, SLE_INTERNAL );
  203. FreeGlobalData( &params );
  204. return 1;
  205. }
  206. // check whether we need to display the usage
  207. if ( bUsage == TRUE )
  208. {
  209. Usage( REG_RESTORE );
  210. FreeGlobalData( &params );
  211. return 0;
  212. }
  213. //
  214. // Connect to the Remote Machine - if applicable
  215. //
  216. bResult = RegConnectMachine( &params );
  217. if( bResult == FALSE )
  218. {
  219. SaveErrorMessage( -1 );
  220. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  221. FreeGlobalData( &params );
  222. return 1;
  223. }
  224. //
  225. // Open the key
  226. //
  227. lResult = RegOpenKeyEx( params.hRootKey,
  228. params.pwszSubKey, 0, KEY_ALL_ACCESS, &hKey );
  229. if( lResult == ERROR_SUCCESS )
  230. {
  231. //
  232. // Acquire the necessary privilages and call the API
  233. //
  234. lResult = RegAdjustTokenPrivileges(
  235. params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  236. if( lResult == ERROR_SUCCESS )
  237. {
  238. lResult = RegRestoreKey( hKey, params.pwszValueName, REG_FORCE_RESTORE );
  239. // check the return error code
  240. switch( lResult )
  241. {
  242. case ERROR_INVALID_PARAMETER:
  243. {
  244. lResult = ERROR_FILENAME_EXCED_RANGE;
  245. break;
  246. }
  247. default:
  248. break;
  249. }
  250. }
  251. SafeCloseKey( &hKey );
  252. }
  253. // display the result
  254. SaveErrorMessage( lResult );
  255. if ( lResult == ERROR_SUCCESS )
  256. {
  257. ShowLastErrorEx( stdout, SLE_INTERNAL );
  258. }
  259. else
  260. {
  261. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  262. }
  263. // return
  264. FreeGlobalData( &params );
  265. return ((lResult == ERROR_SUCCESS) ? 0 : 1);
  266. }
  267. //-----------------------------------------------------------------------//
  268. //
  269. // LoadHive()
  270. //
  271. //-----------------------------------------------------------------------//
  272. LONG
  273. LoadHive( DWORD argc, LPCWSTR argv[] )
  274. {
  275. // local variables
  276. LONG lResult = 0;
  277. BOOL bResult = FALSE;
  278. BOOL bUsage = FALSE;
  279. TREG_PARAMS params;
  280. if ( argc == 0 || argv == NULL )
  281. {
  282. SetLastError( ERROR_INVALID_PARAMETER );
  283. ShowLastError( stderr );
  284. return 1;
  285. }
  286. // initialize the global data structure
  287. InitGlobalData( REG_LOAD, &params );
  288. //
  289. // Parse the cmd-line
  290. //
  291. bResult = ParseSaveCmdLine( argc, argv, L"LOAD", &params, &bUsage );
  292. if( bResult == FALSE )
  293. {
  294. ShowLastErrorEx( stderr, SLE_INTERNAL );
  295. FreeGlobalData( &params );
  296. return 1;
  297. }
  298. // check whether we need to display the usage
  299. if ( bUsage == TRUE )
  300. {
  301. Usage( REG_LOAD );
  302. FreeGlobalData( &params );
  303. return 0;
  304. }
  305. //
  306. // Connect to the Remote Machine - if applicable
  307. //
  308. bResult = RegConnectMachine( &params );
  309. if( bResult == FALSE )
  310. {
  311. SaveErrorMessage( -1 );
  312. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  313. FreeGlobalData( &params );
  314. return 1;
  315. }
  316. //
  317. // Acquire the necessary privilages and call the API
  318. //
  319. lResult = RegAdjustTokenPrivileges(
  320. params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  321. if( lResult == ERROR_SUCCESS )
  322. {
  323. lResult = RegLoadKey( params.hRootKey, params.pwszSubKey, params.pwszValueName );
  324. // check the return error code
  325. switch( lResult )
  326. {
  327. case ERROR_INVALID_PARAMETER:
  328. {
  329. lResult = ERROR_FILENAME_EXCED_RANGE;
  330. break;
  331. }
  332. default:
  333. break;
  334. }
  335. }
  336. // display the result
  337. SaveErrorMessage( lResult );
  338. if ( lResult == ERROR_SUCCESS )
  339. {
  340. ShowLastErrorEx( stdout, SLE_INTERNAL );
  341. }
  342. else
  343. {
  344. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  345. }
  346. // return
  347. FreeGlobalData( &params );
  348. return ((lResult == ERROR_SUCCESS) ? 0 : 1);
  349. }
  350. //-----------------------------------------------------------------------//
  351. //
  352. // UnLoadHive()
  353. //
  354. //-----------------------------------------------------------------------//
  355. LONG
  356. UnLoadHive( DWORD argc, LPCWSTR argv[] )
  357. {
  358. // local variables
  359. LONG lResult = 0;
  360. BOOL bResult = FALSE;
  361. BOOL bUsage = FALSE;
  362. TREG_PARAMS params;
  363. if ( argc == 0 || argv == NULL )
  364. {
  365. SetLastError( ERROR_INVALID_PARAMETER );
  366. ShowLastError( stderr );
  367. return 1;
  368. }
  369. // initialize the global data structure
  370. InitGlobalData( REG_UNLOAD, &params );
  371. //
  372. // Parse the cmd-line
  373. //
  374. bResult = ParseUnLoadCmdLine( argc, argv, &params, &bUsage );
  375. if( bResult == FALSE )
  376. {
  377. ShowLastErrorEx( stderr, SLE_INTERNAL );
  378. FreeGlobalData( &params );
  379. return 1;
  380. }
  381. // check whether we need to display the usage
  382. if ( bUsage == TRUE )
  383. {
  384. Usage( REG_UNLOAD );
  385. FreeGlobalData( &params );
  386. return 0;
  387. }
  388. //
  389. // Connect to the Remote Machine(s) - if applicable
  390. //
  391. bResult = RegConnectMachine( &params );
  392. if( bResult == FALSE )
  393. {
  394. SaveErrorMessage( -1 );
  395. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  396. FreeGlobalData( &params );
  397. return 1;
  398. }
  399. //
  400. // Acquire the necessary privilages and call the API
  401. //
  402. lResult = RegAdjustTokenPrivileges(
  403. params.pwszMachineName, SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  404. if( lResult == ERROR_SUCCESS )
  405. {
  406. lResult = RegUnLoadKey( params.hRootKey, params.pwszSubKey );
  407. }
  408. // display the result
  409. SaveErrorMessage( lResult );
  410. if ( lResult == ERROR_SUCCESS )
  411. {
  412. ShowLastErrorEx( stdout, SLE_INTERNAL );
  413. }
  414. else
  415. {
  416. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  417. }
  418. // return
  419. FreeGlobalData( &params );
  420. return ((lResult == ERROR_SUCCESS) ? 0 : 1);
  421. }
  422. //------------------------------------------------------------------------//
  423. //
  424. // ParseSaveCmdLine()
  425. //
  426. //------------------------------------------------------------------------//
  427. BOOL
  428. ParseSaveCmdLine( DWORD argc, LPCWSTR argv[],
  429. LPCWSTR pwszOption, PTREG_PARAMS pParams, BOOL* pbUsage )
  430. {
  431. // local variables
  432. DWORD dwLength = 0;
  433. BOOL bResult = FALSE;
  434. // check the input
  435. if ( argc == 0 || argv == NULL ||
  436. pwszOption == NULL || pParams == NULL || pbUsage == NULL )
  437. {
  438. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  439. return FALSE;
  440. }
  441. // check whether this function is being called for
  442. // valid operation or not
  443. if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT )
  444. {
  445. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  446. return FALSE;
  447. }
  448. //
  449. // Do we have a *valid* number of cmd-line params
  450. //
  451. if ( argc >= 3 && InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE )
  452. {
  453. if ( argc == 3 )
  454. {
  455. *pbUsage = TRUE;
  456. return TRUE;
  457. }
  458. else
  459. {
  460. SetLastError( (DWORD) MK_E_SYNTAX );
  461. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] );
  462. return FALSE;
  463. }
  464. }
  465. else if( (pParams->lOperation != REG_SAVE && argc != 4) ||
  466. (pParams->lOperation == REG_SAVE && (argc < 4 || argc > 5)) )
  467. {
  468. SetLastError( (DWORD) MK_E_SYNTAX );
  469. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] );
  470. return FALSE;
  471. }
  472. else if ( StringCompareEx( argv[ 1 ], pwszOption, TRUE, 0 ) != 0 )
  473. {
  474. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  475. return FALSE;
  476. }
  477. // Machine Name and Registry key
  478. //
  479. bResult = BreakDownKeyString( argv[ 2 ], pParams );
  480. if( bResult == FALSE )
  481. {
  482. return FALSE;
  483. }
  484. // for "LOAD" subkey should be present
  485. if ( pParams->lOperation == REG_LOAD )
  486. {
  487. if ( pParams->pwszSubKey == NULL ||
  488. StringLength( pParams->pwszSubKey, 0 ) == 0 )
  489. {
  490. SetLastError( (DWORD) MK_E_SYNTAX );
  491. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] );
  492. return FALSE;
  493. }
  494. }
  495. //
  496. // Get the FileName - using the szValueName string field to hold it
  497. //
  498. dwLength = StringLength( argv[ 3 ], 0 ) + 1;
  499. pParams->pwszValueName = (LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) );
  500. if( pParams->pwszValueName == NULL )
  501. {
  502. SaveErrorMessage( ERROR_OUTOFMEMORY );
  503. return FALSE;
  504. }
  505. // ...
  506. StringCopy( pParams->pwszValueName, argv[ 3 ], dwLength );
  507. // validate the file name -- it should not be empty
  508. TrimString( pParams->pwszValueName, TRIM_ALL );
  509. if ( StringLength( pParams->pwszValueName, 0 ) == 0 )
  510. {
  511. SetLastError( (DWORD) MK_E_SYNTAX );
  512. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] );
  513. return FALSE;
  514. }
  515. // check if user specified overwrite flag or not -- this is only for REG SAVE
  516. if ( argc == 5 && pParams->lOperation == REG_SAVE )
  517. {
  518. pParams->bForce = FALSE;
  519. if ( StringCompareEx( argv[ 4 ], L"/y", TRUE, 0 ) == 0 )
  520. {
  521. pParams->bForce = TRUE;
  522. }
  523. else
  524. {
  525. SetLastError( (DWORD) MK_E_SYNTAX );
  526. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ pParams->lOperation ] );
  527. return FALSE;
  528. }
  529. }
  530. // return
  531. return TRUE;
  532. }
  533. //------------------------------------------------------------------------//
  534. //
  535. // ParseUnLoadCmdLine()
  536. //
  537. //------------------------------------------------------------------------//
  538. BOOL
  539. ParseUnLoadCmdLine( DWORD argc, LPCWSTR argv[],
  540. PTREG_PARAMS pParams, BOOL* pbUsage )
  541. {
  542. // local variables
  543. BOOL bResult = FALSE;
  544. // check the input
  545. if ( argc == 0 || argv == NULL || pParams == NULL || pbUsage == NULL )
  546. {
  547. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  548. return FALSE;
  549. }
  550. // check whether this function is being called for
  551. // valid operation or not
  552. if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT )
  553. {
  554. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  555. return FALSE;
  556. }
  557. //
  558. // Do we have a *valid* number of cmd-line params
  559. //
  560. if( argc != 3 )
  561. {
  562. SetLastError( (DWORD) MK_E_SYNTAX );
  563. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_UNLOAD ] );
  564. return FALSE;
  565. }
  566. else if ( InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE )
  567. {
  568. *pbUsage = TRUE;
  569. return TRUE;
  570. }
  571. else if ( StringCompareEx( argv[ 1 ], L"UNLOAD", TRUE, 0 ) != 0 )
  572. {
  573. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  574. return FALSE;
  575. }
  576. // Machine Name and Registry key
  577. //
  578. bResult = BreakDownKeyString( argv[ 2 ], pParams );
  579. if( bResult == FALSE )
  580. {
  581. return FALSE;
  582. }
  583. if ( pParams->pwszSubKey == NULL ||
  584. StringLength( pParams->pwszSubKey, 0 ) == 0 )
  585. {
  586. SetLastError( (DWORD) MK_E_SYNTAX );
  587. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_UNLOAD ] );
  588. return FALSE;
  589. }
  590. // return
  591. return TRUE;
  592. }
  593. //------------------------------------------------------------------------//
  594. //
  595. // AdjustTokenPrivileges()
  596. //
  597. //------------------------------------------------------------------------//
  598. LONG
  599. RegAdjustTokenPrivileges( LPCWSTR pwszMachine,
  600. LPCWSTR pwszPrivilege, LONG lAttribute )
  601. {
  602. // local variables
  603. BOOL bResult = FALSE;
  604. HANDLE hToken = NULL;
  605. TOKEN_PRIVILEGES tkp;
  606. bResult = OpenProcessToken( GetCurrentProcess(),
  607. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
  608. if( bResult == FALSE )
  609. {
  610. return GetLastError();
  611. }
  612. bResult = LookupPrivilegeValue( pwszMachine, pwszPrivilege, &tkp.Privileges[0].Luid );
  613. if( bResult == FALSE )
  614. {
  615. return GetLastError();
  616. }
  617. tkp.PrivilegeCount = 1;
  618. tkp.Privileges[0].Attributes = lAttribute;
  619. bResult = AdjustTokenPrivileges( hToken,
  620. FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, NULL );
  621. if( bResult == FALSE )
  622. {
  623. return GetLastError();
  624. }
  625. return ERROR_SUCCESS;
  626. }