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.

734 lines
23 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: add.cpp
  4. // Created: March 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Add (Write) Support for REG.CPP
  7. // Modification History:
  8. // March 1997 (a-martih):
  9. // Copied from Query.cpp and modificd.
  10. // October 1997 (martinho)
  11. // Added additional termination character for MULTI_SZ strings.
  12. // Added \0 delimiter between MULTI_SZ strings items
  13. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  14. //------------------------------------------------------------------------//
  15. #include "stdafx.h"
  16. #include "reg.h"
  17. //
  18. // function prototypes
  19. //
  20. BOOL ParseAddCmdLine( DWORD argc, LPCWSTR argv[],
  21. PTREG_PARAMS pParams, BOOL* pbUsage );
  22. //
  23. // implementation
  24. //
  25. //-----------------------------------------------------------------------//
  26. //
  27. // AddRegistry()
  28. //
  29. //-----------------------------------------------------------------------//
  30. LONG AddRegistry( DWORD argc, LPCWSTR argv[] )
  31. {
  32. // local variables
  33. DWORD dw = 0;
  34. DWORD dwBase = 0;
  35. DWORD dwCount = 0;
  36. HKEY hKey = NULL;
  37. LONG lEnd = 0;
  38. LONG lStart = 0;
  39. LONG lResult = 0;
  40. DWORD dwLength = 0;
  41. TREG_PARAMS params;
  42. BOOL bResult = FALSE;
  43. BYTE* pByteData = NULL;
  44. DWORD dwDisposition = 0;
  45. WCHAR wszTemp[ 3 ] = L"\0";
  46. LPWSTR pwszValue = NULL;
  47. BOOL bTrailing = FALSE;
  48. BOOL bErrorString = FALSE;
  49. DWORD dwLengthOfSeparator = 0;
  50. LPWSTR pwszData = NULL;
  51. LPWSTR pwszTemp = NULL;
  52. LPCWSTR pwszFormat = NULL;
  53. LPCWSTR pwszList = NULL;
  54. BOOL bUsage = FALSE;
  55. if ( argc == 0 || argv == NULL )
  56. {
  57. SetLastError( ERROR_INVALID_PARAMETER );
  58. ShowLastError( stderr );
  59. return 1;
  60. }
  61. // initialize the global data structure
  62. InitGlobalData( REG_ADD, &params );
  63. //
  64. // Parse the cmd-line
  65. //
  66. bResult = ParseAddCmdLine( argc, argv, &params, &bUsage );
  67. if( bResult == FALSE )
  68. {
  69. ShowLastErrorEx( stderr, SLE_INTERNAL );
  70. FreeGlobalData( &params );
  71. return 1;
  72. }
  73. // check whether we need to display the usage
  74. if ( bUsage == TRUE )
  75. {
  76. Usage( REG_ADD );
  77. FreeGlobalData( &params );
  78. return 0;
  79. }
  80. //
  81. // Connect to the Remote Machine - if applicable
  82. //
  83. bResult = RegConnectMachine( &params );
  84. if( bResult == FALSE )
  85. {
  86. SaveErrorMessage( -1 );
  87. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  88. FreeGlobalData( &params );
  89. return 1;
  90. }
  91. //
  92. // Create/Open the registry key
  93. //
  94. lResult = RegCreateKeyEx( params.hRootKey, params.pwszSubKey, 0, NULL,
  95. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisposition );
  96. if( lResult == ERROR_SUCCESS )
  97. {
  98. // safety check
  99. if ( hKey == NULL )
  100. {
  101. SaveErrorMessage( ERROR_PROCESS_ABORTED );
  102. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  103. FreeGlobalData( &params );
  104. return 1;
  105. }
  106. // value name should not be NULL
  107. if ( params.pwszValueName == NULL )
  108. {
  109. SafeCloseKey( &hKey );
  110. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  111. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  112. FreeGlobalData( &params );
  113. return 1;
  114. }
  115. // check value if existed
  116. lResult = RegQueryValueEx( hKey,
  117. params.pwszValueName, NULL, NULL, NULL, NULL );
  118. if( lResult == ERROR_SUCCESS )
  119. {
  120. pwszFormat = GetResString2( IDS_OVERWRITE_CONFIRM, 0 );
  121. pwszList = GetResString2( IDS_CONFIRM_CHOICE_LIST, 1 );
  122. do
  123. {
  124. lResult = Prompt( pwszFormat,
  125. params.pwszValueName, pwszList, params.bForce );
  126. } while ( lResult > 2 );
  127. if( lResult != 1 )
  128. {
  129. SafeCloseKey( &hKey );
  130. SaveErrorMessage( ERROR_CANCELLED );
  131. ShowLastErrorEx( stdout, SLE_INTERNAL );
  132. FreeGlobalData( &params );
  133. return 0;
  134. }
  135. }
  136. // check the error code
  137. else if ( lResult != ERROR_FILE_NOT_FOUND )
  138. {
  139. // some thing else happened -- need to quit
  140. SaveErrorMessage( lResult );
  141. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  142. SafeCloseKey( &hKey );
  143. FreeGlobalData( &params );
  144. return 1;
  145. }
  146. bResult = TRUE;
  147. lResult = ERROR_SUCCESS;
  148. switch( params.lRegDataType )
  149. {
  150. case REG_DWORD:
  151. case REG_DWORD_BIG_ENDIAN:
  152. //
  153. // auto convert szValue (hex, octal, decimal format) to dwData
  154. //
  155. {
  156. if( params.pwszValue == NULL )
  157. {
  158. lResult = ERROR_INVALID_PARAMETER;
  159. }
  160. else
  161. {
  162. // determine the base
  163. dwBase = 10;
  164. if ( StringCompare( params.pwszValue, L"0x", TRUE, 2 ) == 0 )
  165. {
  166. dwBase = 16;
  167. }
  168. if( IsNumeric( params.pwszValue, dwBase, FALSE ) == FALSE )
  169. {
  170. // invalid data format
  171. bResult = FALSE;
  172. lResult = IDS_ERROR_INVALID_NUMERIC_ADD;
  173. }
  174. else
  175. {
  176. // ...
  177. dw = (DWORD) AsLong( params.pwszValue, dwBase );
  178. lResult = RegSetValueEx( hKey, params.pwszValueName,
  179. 0, params.lRegDataType, (BYTE*) &dw, sizeof(DWORD) );
  180. }
  181. }
  182. break;
  183. }
  184. case REG_BINARY:
  185. {
  186. if ( params.pwszValue == NULL )
  187. {
  188. lResult = ERROR_INVALID_PARAMETER;
  189. }
  190. else
  191. {
  192. //
  193. // Convert szValue (hex data string) to binary
  194. //
  195. dwLength = StringLength( params.pwszValue, 0 );
  196. //
  197. // We're converting a string (representing
  198. // hex) into a binary stream. How much to
  199. // allocate? E.g. for "0xABCD", which has
  200. // a length of 4, we would need 2 bytes.
  201. //
  202. dwLength = (dwLength / 2) + (dwLength % 2) + 1;
  203. pByteData = (BYTE*) AllocateMemory( dwLength * sizeof( BYTE ) );
  204. if( pByteData == NULL )
  205. {
  206. lResult = ERROR_NOT_ENOUGH_MEMORY;
  207. }
  208. else
  209. {
  210. dwCount = 0;
  211. pwszValue = params.pwszValue;
  212. SecureZeroMemory( wszTemp,
  213. SIZE_OF_ARRAY( wszTemp ) * sizeof( WCHAR ) );
  214. while( (dw = StringLength( pwszValue, 0 )) > 1 )
  215. {
  216. if ( (dw % 2) == 0 )
  217. {
  218. wszTemp[ 0 ] = *pwszValue;
  219. pwszValue++;
  220. }
  221. else
  222. {
  223. wszTemp[ 0 ] = L'0';
  224. }
  225. wszTemp[ 1 ] = *pwszValue;
  226. pwszValue++;
  227. // hex format
  228. if( IsNumeric( wszTemp, 16, TRUE ) == FALSE )
  229. {
  230. bResult = FALSE;
  231. lResult = IDS_ERROR_INVALID_HEXVALUE_ADD;
  232. break;
  233. }
  234. else
  235. {
  236. pByteData[ dwCount] = (BYTE) AsLong( wszTemp, 16 );
  237. }
  238. dwCount++;
  239. //
  240. // make sure we aren't stepping off our buffer
  241. //
  242. if( dwCount >= dwLength )
  243. {
  244. ASSERT(0);
  245. lResult = ERROR_PROCESS_ABORTED;
  246. break;
  247. }
  248. }
  249. if( lResult == ERROR_SUCCESS )
  250. {
  251. lResult = RegSetValueEx(
  252. hKey, params.pwszValueName,
  253. 0, params.lRegDataType, pByteData, dwCount );
  254. }
  255. FreeMemory( &pByteData);
  256. }
  257. }
  258. break;
  259. }
  260. default:
  261. case REG_SZ:
  262. case REG_EXPAND_SZ:
  263. case REG_NONE:
  264. {
  265. if ( params.pwszValue == NULL )
  266. {
  267. lResult = ERROR_INVALID_PARAMETER;
  268. }
  269. else
  270. {
  271. dw = (StringLength(params.pwszValue, 0) + 1) * sizeof(WCHAR);
  272. lResult = RegSetValueEx( hKey,
  273. params.pwszValueName, 0,
  274. params.lRegDataType,
  275. (BYTE*) params.pwszValue, dw );
  276. }
  277. break;
  278. }
  279. case REG_MULTI_SZ:
  280. {
  281. //
  282. // Replace separator("\0") with '\0' for MULTI_SZ,
  283. // "\0" uses to separate string by default,
  284. // if two separators("\0\0"), error
  285. //
  286. dwLength = StringLength( params.pwszValue, 0 );
  287. dwLengthOfSeparator = StringLength( params.wszSeparator, 0 );
  288. // calloc() initializes all char to 0
  289. dwCount = dwLength + 2;
  290. pwszData = (LPWSTR) AllocateMemory( (dwCount + 1) * sizeof(WCHAR) );
  291. if ( pwszData == NULL)
  292. {
  293. lResult = ERROR_NOT_ENOUGH_MEMORY;
  294. }
  295. else
  296. {
  297. lEnd = -1;
  298. lStart = 0;
  299. pwszTemp = pwszData;
  300. while( lStart < (LONG) dwLength )
  301. {
  302. lEnd = FindString2( params.pwszValue,
  303. params.wszSeparator, TRUE, lStart );
  304. if( lEnd != -1 )
  305. {
  306. // specifying two separators in the data is error
  307. bTrailing = FALSE;
  308. if ( lEnd == lStart )
  309. {
  310. bErrorString = TRUE;
  311. break;
  312. }
  313. else if ( (dwLength - lEnd) == dwLengthOfSeparator )
  314. {
  315. // set the flag
  316. bTrailing = TRUE;
  317. }
  318. }
  319. else
  320. {
  321. lEnd = dwLength;
  322. }
  323. StringCopy( pwszTemp,
  324. (params.pwszValue + lStart), (lEnd - lStart) + 1 );
  325. pwszTemp += StringLength( pwszTemp, 0 ) + 1;
  326. //
  327. // make sure we aren't stepping off our buffer
  328. //
  329. if( pwszTemp >= (pwszData + dwCount) )
  330. {
  331. ASSERT(0);
  332. lResult = ERROR_PROCESS_ABORTED;
  333. break;
  334. }
  335. lStart = lEnd + dwLengthOfSeparator;
  336. }
  337. // empty
  338. if( StringCompare( params.pwszValue,
  339. params.wszSeparator, TRUE, 0 ) == 0 )
  340. {
  341. pwszTemp = pwszData + 2;
  342. bErrorString = FALSE;
  343. }
  344. else
  345. {
  346. pwszTemp += 1; // double null terminated string
  347. }
  348. if( bErrorString == TRUE )
  349. {
  350. bResult = FALSE;
  351. lResult = IDS_ERROR_INVALID_DATA_ADD;
  352. }
  353. else
  354. {
  355. dwCount = (DWORD)((pwszTemp - pwszData) * sizeof(WCHAR));
  356. lResult = RegSetValueEx( hKey, params.pwszValueName,
  357. 0, params.lRegDataType, (BYTE*) pwszData, dwCount );
  358. }
  359. FreeMemory( &pwszData );
  360. }
  361. break;
  362. }
  363. // default:
  364. // lResult = ERROR_PROCESS_ABORTED;
  365. // break;
  366. }
  367. }
  368. // close the registry key
  369. SafeCloseKey( &hKey );
  370. // release the memory allocated for global data
  371. FreeGlobalData( &params );
  372. // check the result of the operation performed
  373. if ( bResult == FALSE )
  374. {
  375. // custom error message
  376. ShowResMessage( stderr, lResult );
  377. lResult = 1;
  378. }
  379. else if ( lResult != ERROR_SUCCESS )
  380. {
  381. SaveErrorMessage( lResult );
  382. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  383. lResult = 1;
  384. }
  385. else
  386. {
  387. lResult = 0;
  388. SaveErrorMessage( ERROR_SUCCESS );
  389. ShowLastErrorEx( stdout, SLE_INTERNAL );
  390. }
  391. // return the exit code
  392. return lResult;
  393. }
  394. //------------------------------------------------------------------------//
  395. //
  396. // ParseAddCmdLine()
  397. //
  398. //------------------------------------------------------------------------//
  399. BOOL
  400. ParseAddCmdLine( DWORD argc,
  401. LPCWSTR argv[],
  402. PTREG_PARAMS pParams,
  403. BOOL* pbUsage )
  404. {
  405. // local variables
  406. DWORD dw = 0;
  407. LONG lResult = 0;
  408. DWORD dwLength = 0;
  409. BOOL bResult = FALSE;
  410. BOOL bHasType = FALSE;
  411. BOOL bHasSeparator = FALSE;
  412. // check the input
  413. if ( argc == 0 || argv == NULL || pParams == NULL || pbUsage == NULL )
  414. {
  415. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  416. return FALSE;
  417. }
  418. // check whether this function is being called for
  419. // valid operation or not
  420. if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT )
  421. {
  422. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  423. return FALSE;
  424. }
  425. if( argc < 3 )
  426. {
  427. SetLastError( (DWORD) MK_E_SYNTAX );
  428. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] );
  429. return FALSE;
  430. }
  431. else if ( StringCompareEx( argv[ 1 ], L"ADD", TRUE, 0 ) != 0 )
  432. {
  433. SaveErrorMessage( ERROR_INVALID_PARAMETER );
  434. return FALSE;
  435. }
  436. else if ( InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE )
  437. {
  438. if ( argc == 3 )
  439. {
  440. *pbUsage = TRUE;
  441. return TRUE;
  442. }
  443. else
  444. {
  445. SetLastError( (DWORD) MK_E_SYNTAX );
  446. SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] );
  447. return FALSE;
  448. }
  449. }
  450. // Machine Name and Registry key
  451. //
  452. bResult = BreakDownKeyString( argv[ 2 ], pParams );
  453. if( bResult == FALSE )
  454. {
  455. return FALSE;
  456. }
  457. // parsing
  458. bResult = TRUE;
  459. lResult = ERROR_SUCCESS;
  460. pParams->bForce = FALSE;
  461. for( dw = 3; dw < argc; dw++ )
  462. {
  463. if( StringCompareEx( argv[ dw ], L"/v", TRUE, 0 ) == 0 )
  464. {
  465. if( pParams->pwszValueName != NULL )
  466. {
  467. bResult = FALSE;
  468. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  469. break;
  470. }
  471. dw++;
  472. if( dw < argc )
  473. {
  474. dwLength = StringLength( argv[ dw ], 0 ) + 1;
  475. pParams->pwszValueName = (LPWSTR) AllocateMemory( dwLength * sizeof(WCHAR) );
  476. if ( pParams->pwszValueName == NULL )
  477. {
  478. lResult = ERROR_OUTOFMEMORY;
  479. break;
  480. }
  481. StringCopy( pParams->pwszValueName, argv[ dw ], dwLength );
  482. TrimString( pParams->pwszValueName, TRIM_ALL );
  483. }
  484. else
  485. {
  486. bResult = FALSE;
  487. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  488. break;
  489. }
  490. }
  491. else if( StringCompareEx( argv[ dw ], L"/ve", TRUE, 0 ) == 0 )
  492. {
  493. if( pParams->pwszValueName != NULL )
  494. {
  495. bResult = FALSE;
  496. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  497. break;
  498. }
  499. // allocate some memory so that "/v" will not allowed
  500. pParams->pwszValueName = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR) );
  501. if( pParams->pwszValueName == NULL )
  502. {
  503. lResult = ERROR_OUTOFMEMORY;
  504. break;
  505. }
  506. }
  507. else if( StringCompareEx( argv[ dw ], L"/t", TRUE, 0 ) == 0 )
  508. {
  509. if ( bHasType == TRUE )
  510. {
  511. bResult = FALSE;
  512. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  513. break;
  514. }
  515. dw++;
  516. if( dw < argc )
  517. {
  518. pParams->lRegDataType = IsRegDataType( argv[ dw ] );
  519. if( pParams->lRegDataType == -1 )
  520. {
  521. if ( IsNumeric( argv[ dw ], 10, TRUE ) == FALSE )
  522. {
  523. bResult = FALSE;
  524. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  525. break;
  526. }
  527. else
  528. {
  529. pParams->lRegDataType = AsLong( argv[ dw ], 10 );
  530. }
  531. }
  532. // ...
  533. if ( bHasSeparator == TRUE &&
  534. pParams->lRegDataType != REG_MULTI_SZ )
  535. {
  536. bResult = FALSE;
  537. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  538. break;
  539. }
  540. bHasType = TRUE;
  541. }
  542. else
  543. {
  544. bResult = FALSE;
  545. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  546. break;
  547. }
  548. }
  549. else if( StringCompareEx( argv[ dw ], L"/s", TRUE, 0 ) == 0 )
  550. {
  551. if( bHasSeparator == TRUE ||
  552. (bHasType == TRUE && pParams->lRegDataType != REG_MULTI_SZ) )
  553. {
  554. bResult = FALSE;
  555. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  556. break;
  557. }
  558. dw++;
  559. if( dw < argc )
  560. {
  561. if( StringLength( argv[ dw ], 0 ) == 1 )
  562. {
  563. bHasSeparator = TRUE;
  564. StringCopy( pParams->wszSeparator,
  565. argv[ dw ], SIZE_OF_ARRAY( pParams->wszSeparator ) );
  566. }
  567. else
  568. {
  569. bResult = FALSE;
  570. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  571. break;
  572. }
  573. }
  574. else
  575. {
  576. bResult = FALSE;
  577. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  578. break;
  579. }
  580. }
  581. else if( StringCompareEx( argv[ dw ], L"/d", TRUE, 0 ) == 0 )
  582. {
  583. if( pParams->pwszValue != NULL )
  584. {
  585. bResult = FALSE;
  586. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  587. break;
  588. }
  589. dw++;
  590. if( dw < argc )
  591. {
  592. dwLength = StringLength( argv[ dw ], 0 ) + 1;
  593. pParams->pwszValue = (LPWSTR) AllocateMemory( dwLength * sizeof(WCHAR) );
  594. if (pParams->pwszValue == NULL)
  595. {
  596. lResult = ERROR_OUTOFMEMORY;
  597. break;
  598. }
  599. StringCopy( pParams->pwszValue, argv[ dw ], dwLength );
  600. }
  601. else
  602. {
  603. bResult = FALSE;
  604. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  605. break;
  606. }
  607. }
  608. else if( StringCompareEx( argv[ dw ], L"/f", TRUE, 0 ) == 0 )
  609. {
  610. if ( pParams->bForce == TRUE )
  611. {
  612. bResult = FALSE;
  613. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  614. break;
  615. }
  616. pParams->bForce = TRUE;
  617. }
  618. else
  619. {
  620. bResult = FALSE;
  621. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  622. break;
  623. }
  624. }
  625. if ( lResult == ERROR_SUCCESS )
  626. {
  627. if( bHasSeparator == TRUE && bHasType == FALSE )
  628. {
  629. bResult = FALSE;
  630. lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
  631. }
  632. // if no value (or) value name, set to empty
  633. else
  634. {
  635. if ( pParams->pwszValueName == NULL )
  636. {
  637. pParams->pwszValueName = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR));
  638. if( pParams->pwszValueName == NULL )
  639. {
  640. lResult = ERROR_OUTOFMEMORY;
  641. }
  642. }
  643. if( lResult == ERROR_SUCCESS && pParams->pwszValue == NULL )
  644. {
  645. pParams->pwszValue = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR));
  646. if( pParams->pwszValue == NULL )
  647. {
  648. lResult = ERROR_OUTOFMEMORY;
  649. }
  650. }
  651. }
  652. }
  653. if( lResult != ERROR_SUCCESS )
  654. {
  655. if( bResult == FALSE )
  656. {
  657. SetLastError( (DWORD) MK_E_SYNTAX );
  658. SetReason2( 1,
  659. ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] );
  660. }
  661. else
  662. {
  663. SaveErrorMessage( lResult );
  664. }
  665. }
  666. return (lResult == ERROR_SUCCESS);
  667. }