Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1159 lines
29 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. TCHAR g_NoName[100];
  19. VOID
  20. InitGlobalStrings(
  21. VOID
  22. )
  23. {
  24. LoadString(
  25. NULL,
  26. IDS_NONAME,
  27. g_NoName,
  28. sizeof(g_NoName)/sizeof(TCHAR));
  29. }
  30. //------------------------------------------------------------------------//
  31. //
  32. // main()
  33. //
  34. //------------------------------------------------------------------------//
  35. int __cdecl wmain(int argc, TCHAR *argv[], TCHAR *envp[])
  36. {
  37. APPVARS AppVars; // Used for all operation
  38. APPVARS DstVars; // Used for COPY/COMPARE operation
  39. UINT nResult;
  40. // set the appropriate thread codepage
  41. SetThreadUILanguage0( 0);
  42. InitAppVars(&AppVars);
  43. InitAppVars(&DstVars);
  44. InitGlobalStrings();
  45. //
  46. // Determine the opertion - and pass control to the *deserving* function
  47. //
  48. nResult = ParseRegCmdLine(&AppVars, argc, argv);
  49. if(nResult == REG_STATUS_BADOPERATION)
  50. {
  51. TCHAR szString[LENGTH_MESSAGE] = {0};
  52. LoadString(NULL,
  53. IDS_ERROR_BADOPERATION,
  54. szString,
  55. LENGTH_MESSAGE);
  56. MyTPrintf(stderr,_T("%s"), szString);
  57. }
  58. else if(nResult == REG_STATUS_HELP)
  59. {
  60. Banner();
  61. Usage(AppVars);
  62. }
  63. else if(nResult == ERROR_SUCCESS)
  64. {
  65. //
  66. // At this point we have a valid operation
  67. //
  68. switch(AppVars.nOperation)
  69. {
  70. case REG_QUERY:
  71. nResult = QueryRegistry(&AppVars, argc, argv);
  72. break;
  73. case REG_DELETE:
  74. nResult = DeleteRegistry(&AppVars, argc, argv);
  75. break;
  76. case REG_ADD:
  77. nResult = AddRegistry(&AppVars, argc, argv);
  78. break;
  79. case REG_COPY:
  80. nResult = CopyRegistry(&AppVars, &DstVars, argc, argv);
  81. break;
  82. case REG_SAVE:
  83. nResult = SaveHive(&AppVars, argc, argv);
  84. break;
  85. case REG_RESTORE:
  86. nResult = RestoreHive(&AppVars, argc, argv);
  87. break;
  88. case REG_LOAD:
  89. nResult = LoadHive(&AppVars, argc, argv);
  90. break;
  91. case REG_UNLOAD:
  92. nResult = UnLoadHive(&AppVars, argc, argv);
  93. break;
  94. case REG_COMPARE:
  95. nResult = CompareRegistry(&AppVars, &DstVars, argc, argv);
  96. break;
  97. case REG_EXPORT:
  98. nResult = ExportRegFile(&AppVars, argc, argv);
  99. break;
  100. case REG_IMPORT:
  101. nResult = ImportRegFile(&AppVars, argc, argv);
  102. break;
  103. default:
  104. nResult = REG_STATUS_INVALIDPARAMS;
  105. break;
  106. }
  107. }
  108. if(nResult != ERROR_SUCCESS &&
  109. nResult != REG_STATUS_BADOPERATION &&
  110. nResult != REG_STATUS_HELP)
  111. {
  112. ErrorMessage(nResult);
  113. }
  114. else if(nResult == ERROR_SUCCESS &&
  115. AppVars.nOperation != REG_QUERY)
  116. {
  117. //
  118. // Print "The operation completed successfully" message
  119. //
  120. TCHAR szString[LENGTH_MESSAGE] = {0};
  121. LoadString(NULL,
  122. IDS_SUCCESS,
  123. szString,
  124. LENGTH_MESSAGE);
  125. MyTPrintf(stdout,_T("%s"), szString);
  126. }
  127. FreeAppVars(&AppVars);
  128. FreeAppVars(&DstVars);
  129. if(nResult == REG_STATUS_HELP)
  130. nResult = ERROR_SUCCESS;
  131. nResult = !(!nResult); // cast to 0 or 1
  132. if(AppVars.nOperation == REG_COMPARE)
  133. {
  134. if( nResult == 0 && // no error
  135. AppVars.bHasDifference)
  136. {
  137. nResult = 2; // has difference
  138. }
  139. }
  140. return nResult;
  141. }
  142. //------------------------------------------------------------------------//
  143. //
  144. // ParseRegCmdLine()
  145. // Find out the operation - each operation parses it's own cmd-line
  146. //
  147. //------------------------------------------------------------------------//
  148. REG_STATUS ParseRegCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  149. {
  150. REG_STATUS nResult = ERROR_SUCCESS;
  151. // Set default operation
  152. pAppVars->nOperation = REG_NOOPERATION;
  153. //
  154. // Do we have any cmd-line params
  155. //
  156. if(argc == 1)
  157. {
  158. return REG_STATUS_HELP;
  159. }
  160. //
  161. // If we fell through - we need to get the operation
  162. // MUST be the first parameter
  163. //
  164. if(_tcsicmp(argv[1], STR_QUERY) == 0)
  165. {
  166. pAppVars->nOperation = REG_QUERY;
  167. }
  168. else if(_tcsicmp(argv[1], STR_ADD) == 0)
  169. {
  170. pAppVars->nOperation = REG_ADD;
  171. }
  172. else if(_tcsicmp(argv[1], STR_DELETE) == 0)
  173. {
  174. pAppVars->nOperation = REG_DELETE;
  175. }
  176. else if(_tcsicmp(argv[1], STR_COPY) == 0)
  177. {
  178. pAppVars->nOperation = REG_COPY;
  179. }
  180. else if(_tcsicmp(argv[1], STR_SAVE) == 0)
  181. {
  182. pAppVars->nOperation = REG_SAVE;
  183. }
  184. else if(_tcsicmp(argv[1], STR_RESTORE) == 0)
  185. {
  186. pAppVars->nOperation = REG_RESTORE;
  187. }
  188. else if(_tcsicmp(argv[1], STR_LOAD) == 0)
  189. {
  190. pAppVars->nOperation = REG_LOAD;
  191. }
  192. else if(_tcsicmp(argv[1], STR_UNLOAD) == 0)
  193. {
  194. pAppVars->nOperation = REG_UNLOAD;
  195. }
  196. else if(_tcsicmp(argv[1], STR_COMPARE) == 0)
  197. {
  198. pAppVars->nOperation = REG_COMPARE;
  199. }
  200. else if(_tcsicmp(argv[1], STR_EXPORT) == 0)
  201. {
  202. pAppVars->nOperation = REG_EXPORT;
  203. }
  204. else if(_tcsicmp(argv[1], STR_IMPORT) == 0)
  205. {
  206. pAppVars->nOperation = REG_IMPORT;
  207. }
  208. else if((_tcsicmp(argv[1], _T("-?")) == 0) ||
  209. (_tcsicmp(argv[1], _T("/?")) == 0) ||
  210. (_tcsicmp(argv[1], _T("-h")) == 0) ||
  211. (_tcsicmp(argv[1], _T("/h")) == 0))
  212. {
  213. nResult = REG_STATUS_HELP;
  214. }
  215. else
  216. {
  217. nResult = REG_STATUS_BADOPERATION;
  218. }
  219. if(nResult == ERROR_SUCCESS && argc == 3)
  220. {
  221. if((_tcsicmp(argv[2], _T("-?")) == 0) ||
  222. (_tcsicmp(argv[2], _T("/?")) == 0) ||
  223. (_tcsicmp(argv[2], _T("-h")) == 0) ||
  224. (_tcsicmp(argv[2], _T("/h")) == 0))
  225. {
  226. nResult = REG_STATUS_HELP;
  227. }
  228. }
  229. return nResult;
  230. }
  231. //------------------------------------------------------------------------//
  232. //
  233. // AllocAppVars() - Allocate memory for the AppVars
  234. //
  235. //------------------------------------------------------------------------//
  236. void InitAppVars(PAPPVARS pAppVars)
  237. {
  238. // initialize
  239. pAppVars->nOperation = REG_NOOPERATION;
  240. pAppVars->hRootKey = HKEY_LOCAL_MACHINE;
  241. pAppVars->dwRegDataType = REG_SZ;
  242. pAppVars->bUseRemoteMachine = FALSE;
  243. pAppVars->bCleanRemoteRootKey = FALSE;
  244. pAppVars->bRecurseSubKeys = FALSE;
  245. pAppVars->bForce = FALSE;
  246. pAppVars->bAllValues = FALSE;
  247. pAppVars->bNT4RegFile = FALSE;
  248. pAppVars->bHasDifference = FALSE;
  249. pAppVars->nOutputType = OUTPUTTYPE_DIFF;
  250. pAppVars->szMachineName = NULL;
  251. pAppVars->szFullKey = NULL;
  252. pAppVars->szSubKey = NULL;
  253. pAppVars->szValueName = NULL;
  254. pAppVars->szValue = NULL;
  255. _tcscpy(pAppVars->szSeparator, _T("\\0"));
  256. }
  257. //------------------------------------------------------------------------//
  258. //
  259. // FreeAppVars()
  260. //
  261. //------------------------------------------------------------------------//
  262. void FreeAppVars(PAPPVARS pAppVars)
  263. {
  264. if(pAppVars->szMachineName)
  265. free(pAppVars->szMachineName);
  266. if(pAppVars->szFullKey)
  267. free(pAppVars->szFullKey);
  268. if(pAppVars->szSubKey)
  269. free(pAppVars->szSubKey);
  270. if(pAppVars->szValueName)
  271. free(pAppVars->szValueName);
  272. if(pAppVars->szValue)
  273. free(pAppVars->szValue);
  274. if(pAppVars->bCleanRemoteRootKey)
  275. {
  276. RegCloseKey(pAppVars->hRootKey);
  277. }
  278. }
  279. //------------------------------------------------------------------------//
  280. //
  281. // ErrorMessage() - Displays error string
  282. //
  283. //------------------------------------------------------------------------//
  284. void ErrorMessage(UINT nErr)
  285. {
  286. TCHAR szString[LENGTH_MESSAGE] = {0};
  287. // First check for OUR Errors
  288. switch(nErr)
  289. {
  290. case REG_STATUS_TOMANYPARAMS:
  291. LoadString(NULL,
  292. IDS_ERROR_TOMANYPARAMS,
  293. szString,
  294. LENGTH_MESSAGE);
  295. break;
  296. case REG_STATUS_TOFEWPARAMS:
  297. LoadString(NULL,
  298. IDS_ERROR_TOFEWPARAMS,
  299. szString,
  300. LENGTH_MESSAGE);
  301. break;
  302. case REG_STATUS_INVALIDPARAMS:
  303. LoadString(NULL,
  304. IDS_ERROR_INVALIDPARAMS,
  305. szString,
  306. LENGTH_MESSAGE);
  307. break;
  308. case REG_STATUS_NONREMOTABLEROOT:
  309. LoadString(NULL,
  310. IDS_ERROR_NONREMOTABLEROOT,
  311. szString,
  312. LENGTH_MESSAGE);
  313. break;
  314. case REG_STATUS_NONLOADABLEROOT:
  315. LoadString(NULL,
  316. IDS_ERROR_NONLOADABLEROOT,
  317. szString,
  318. LENGTH_MESSAGE);
  319. break;
  320. case REG_STATUS_COPYTOSELF:
  321. LoadString(NULL,
  322. IDS_ERROR_COPYTOSELF,
  323. szString,
  324. LENGTH_MESSAGE);
  325. break;
  326. case REG_STATUS_COMPARESELF:
  327. LoadString(NULL,
  328. IDS_ERROR_COMPARESELF,
  329. szString,
  330. LENGTH_MESSAGE);
  331. break;
  332. case REG_STATUS_BADKEYNAME:
  333. case REG_STATUS_NOKEYNAME:
  334. LoadString(NULL,
  335. IDS_ERROR_BADKEYNAME,
  336. szString,
  337. LENGTH_MESSAGE);
  338. break;
  339. case REG_STATUS_BADFILEFORMAT:
  340. LoadString(NULL,
  341. IDS_ERROR_BADFILEFORMAT,
  342. szString,
  343. LENGTH_MESSAGE);
  344. break;
  345. case REG_STATUS_NONREMOTABLE:
  346. LoadString(NULL,
  347. IDS_ERROR_NONREMOTABLE,
  348. szString,
  349. LENGTH_MESSAGE);
  350. break;
  351. //
  352. // Deal with these two Win32 Error Values - I don't like the
  353. // text strings displayed
  354. //
  355. case ERROR_FILE_NOT_FOUND:
  356. case ERROR_PATH_NOT_FOUND:
  357. LoadString(NULL,
  358. IDS_ERROR_PATHNOTFOUND,
  359. szString,
  360. LENGTH_MESSAGE);
  361. break;
  362. //
  363. // Must be a Win32 Error number
  364. //
  365. default:
  366. {
  367. TCHAR* szMessage;
  368. if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  369. FORMAT_MESSAGE_FROM_SYSTEM,
  370. NULL,
  371. nErr,
  372. 0,
  373. (LPTSTR) &szMessage,
  374. 0,
  375. NULL))
  376. {
  377. wsprintf(szString, _T("\r\nError: %s"), szMessage);
  378. LocalFree(szMessage);
  379. }
  380. else
  381. {
  382. wsprintf(szString,
  383. _T("\r\nError: Unknown Return Code %d\r\n"),
  384. nErr);
  385. }
  386. break;
  387. }
  388. }
  389. // print the error message
  390. MyTPrintf(stderr, _T("%s"), szString);
  391. }
  392. //------------------------------------------------------------------------//
  393. //
  394. // Prompt() - Answer Y/N question if bForce == FALSE
  395. //
  396. //------------------------------------------------------------------------//
  397. BOOL Prompt(LPCTSTR szFormat, LPCTSTR szStr, BOOL bForce)
  398. {
  399. TCHAR ch;
  400. if(bForce == TRUE)
  401. {
  402. return TRUE;
  403. }
  404. MyTPrintf(stdout,szFormat, szStr);
  405. ch = (TCHAR)_gettchar();
  406. if(ch == _T( 'y' ) || ch == _T( 'Y' ) )
  407. {
  408. return TRUE;
  409. }
  410. return FALSE;
  411. }
  412. // break down [\\MachineName\]keyName
  413. REG_STATUS BreakDownKeyString(TCHAR *szStr, PAPPVARS pAppVars)
  414. {
  415. REG_STATUS nResult = ERROR_SUCCESS;
  416. TCHAR* pTemp;
  417. TCHAR* szTempStr;
  418. szTempStr = (TCHAR*) calloc(_tcslen(szStr) + 1, sizeof(TCHAR));
  419. if (!szTempStr) {
  420. return ERROR_NOT_ENOUGH_MEMORY;
  421. }
  422. _tcscpy(szTempStr, szStr);
  423. //
  424. // figure out machine name
  425. //
  426. pTemp = szTempStr;
  427. // machine name
  428. if( szTempStr[0] == _T('\\') &&
  429. szTempStr[1] == _T('\\') )
  430. {
  431. pTemp = _tcschr(szTempStr + 2, _T('\\'));
  432. if(pTemp)
  433. {
  434. *pTemp = 0;
  435. pTemp += 1;
  436. }
  437. nResult = ParseMachineName(szTempStr, pAppVars);
  438. }
  439. // parse key name
  440. if( nResult == ERROR_SUCCESS)
  441. {
  442. if(pTemp && _tcslen(pTemp) > 0)
  443. {
  444. nResult = ParseKeyName(pTemp, pAppVars);
  445. }
  446. else
  447. {
  448. nResult = REG_STATUS_NOKEYNAME;
  449. }
  450. }
  451. if(szTempStr)
  452. free(szTempStr);
  453. return nResult;
  454. }
  455. //------------------------------------------------------------------------//
  456. //
  457. // FindAndAdjustKeyName()
  458. //
  459. // null out the cmdline based on what we think the end of the argument is
  460. //
  461. // we do this because users might not quote out the cmdline properly.
  462. //
  463. //------------------------------------------------------------------------//
  464. PTCHAR
  465. AdjustKeyName(
  466. PTCHAR szStr
  467. )
  468. {
  469. PTCHAR p;
  470. p = _tcschr(szStr, _T('\"'));
  471. if (p != NULL) {
  472. *p = 0;
  473. }
  474. p = _tcschr(szStr, _T('/'));
  475. if (p != NULL) {
  476. *p = 0;
  477. }
  478. return szStr;
  479. }
  480. //------------------------------------------------------------------------//
  481. //
  482. // ParseKeyName()
  483. //
  484. // Pass the full registry path in szStr
  485. //
  486. // Based on input - Sets AppMember fields:
  487. //
  488. // hRootKey
  489. // szKey
  490. // szValueName
  491. // szValue
  492. //
  493. //------------------------------------------------------------------------//
  494. REG_STATUS ParseKeyName(TCHAR *szStr, PAPPVARS pAppVars)
  495. {
  496. REG_STATUS nResult = ERROR_SUCCESS;
  497. TCHAR* pTemp;
  498. TCHAR* szRootKey;
  499. //
  500. // figure out what root key was specified
  501. //
  502. pTemp = _tcschr(szStr, _T('\\'));
  503. if (pTemp != NULL)
  504. {
  505. *pTemp = 0;
  506. pTemp += 1;
  507. }
  508. if (*szStr == '\"') {
  509. szStr += 1;
  510. }
  511. //
  512. // Check the ROOT has been entered
  513. //
  514. szRootKey = (TCHAR*) calloc(_tcslen(STR_HKEY_CURRENT_CONFIG) + 1,
  515. sizeof(TCHAR));
  516. if (!szRootKey) {
  517. return ERROR_NOT_ENOUGH_MEMORY;
  518. }
  519. if (_tcsicmp(szStr, STR_HKEY_CURRENT_USER) == 0 ||
  520. _tcsicmp(szStr, STR_HKCU) == 0)
  521. {
  522. pAppVars->hRootKey = HKEY_CURRENT_USER;
  523. _tcscpy(szRootKey, STR_HKEY_CURRENT_USER);
  524. // check remotable and loadable
  525. if(pAppVars->bUseRemoteMachine)
  526. nResult = REG_STATUS_NONREMOTABLEROOT;
  527. else if( pAppVars->nOperation == REG_LOAD ||
  528. pAppVars->nOperation == REG_UNLOAD )
  529. nResult = REG_STATUS_NONLOADABLEROOT;
  530. }
  531. else if (_tcsicmp(szStr, STR_HKEY_CLASSES_ROOT) == 0 ||
  532. _tcsicmp(szStr, STR_HKCR) == 0)
  533. {
  534. pAppVars->hRootKey = HKEY_CLASSES_ROOT;
  535. _tcscpy(szRootKey, STR_HKEY_CLASSES_ROOT);
  536. // check remotable and loadable
  537. if(pAppVars->bUseRemoteMachine)
  538. nResult = REG_STATUS_NONREMOTABLEROOT;
  539. else if( pAppVars->nOperation == REG_LOAD ||
  540. pAppVars->nOperation == REG_UNLOAD )
  541. nResult = REG_STATUS_NONLOADABLEROOT;
  542. }
  543. else if (_tcsicmp(szStr, STR_HKEY_CURRENT_CONFIG) == 0 ||
  544. _tcsicmp(szStr, STR_HKCC) == 0)
  545. {
  546. pAppVars->hRootKey = HKEY_CURRENT_CONFIG;
  547. _tcscpy(szRootKey, STR_HKEY_CURRENT_CONFIG);
  548. // check remotable and loadable
  549. if(pAppVars->bUseRemoteMachine)
  550. nResult = REG_STATUS_NONREMOTABLEROOT;
  551. else if( pAppVars->nOperation == REG_LOAD ||
  552. pAppVars->nOperation == REG_UNLOAD )
  553. nResult = REG_STATUS_NONLOADABLEROOT;
  554. }
  555. else if (_tcsicmp(szStr, STR_HKEY_LOCAL_MACHINE) == 0 ||
  556. _tcsicmp(szStr, STR_HKLM) == 0)
  557. {
  558. pAppVars->hRootKey = HKEY_LOCAL_MACHINE;
  559. _tcscpy(szRootKey, STR_HKEY_LOCAL_MACHINE);
  560. }
  561. else if (_tcsicmp(szStr, STR_HKEY_USERS) == 0 ||
  562. _tcsicmp(szStr, STR_HKU) == 0)
  563. {
  564. pAppVars->hRootKey = HKEY_USERS;
  565. _tcscpy(szRootKey, STR_HKEY_USERS);
  566. }
  567. else
  568. {
  569. nResult = REG_STATUS_BADKEYNAME;
  570. }
  571. if(nResult == ERROR_SUCCESS)
  572. {
  573. //
  574. // parse the subkey
  575. //
  576. if (pTemp == NULL)
  577. {
  578. // only root key, subkey is empty
  579. pAppVars->szSubKey = (TCHAR*) calloc(1,
  580. sizeof(TCHAR));
  581. if (!pAppVars->szSubKey) {
  582. nResult = ERROR_NOT_ENOUGH_MEMORY;
  583. goto Cleanup;
  584. }
  585. pAppVars->szFullKey = (TCHAR*) calloc(_tcslen(szRootKey) + 1,
  586. sizeof(TCHAR));
  587. if (!pAppVars->szFullKey) {
  588. free (pAppVars->szSubKey);
  589. pAppVars->szSubKey = NULL;
  590. nResult = ERROR_NOT_ENOUGH_MEMORY;
  591. goto Cleanup;
  592. }
  593. _tcscpy(pAppVars->szFullKey, szRootKey);
  594. }
  595. else
  596. {
  597. //
  598. // figure out what root key was specified
  599. //
  600. pTemp = AdjustKeyName(pTemp);
  601. // get subkey
  602. pAppVars->szSubKey = (TCHAR*) calloc(_tcslen(pTemp) + 1,
  603. sizeof(TCHAR));
  604. if (!pAppVars->szSubKey) {
  605. nResult = ERROR_NOT_ENOUGH_MEMORY;
  606. goto Cleanup;
  607. }
  608. _tcscpy(pAppVars->szSubKey, pTemp);
  609. // get fullkey
  610. pAppVars->szFullKey = (TCHAR*) calloc(_tcslen(szRootKey) +
  611. _tcslen(pAppVars->szSubKey) +
  612. 2,
  613. sizeof(TCHAR));
  614. if (!pAppVars->szFullKey) {
  615. free (pAppVars->szSubKey);
  616. pAppVars->szSubKey = NULL;
  617. nResult = ERROR_NOT_ENOUGH_MEMORY;
  618. goto Cleanup;
  619. }
  620. _tcscpy(pAppVars->szFullKey, szRootKey);
  621. _tcscat(pAppVars->szFullKey, _T("\\"));
  622. _tcscat(pAppVars->szFullKey, pAppVars->szSubKey);
  623. }
  624. }
  625. Cleanup:
  626. if(szRootKey)
  627. free(szRootKey);
  628. return nResult;
  629. }
  630. //------------------------------------------------------------------------//
  631. //
  632. // IsRegDataType()
  633. //
  634. //------------------------------------------------------------------------//
  635. DWORD IsRegDataType(TCHAR *szStr)
  636. {
  637. DWORD nResult = (DWORD)-1;
  638. if(_tcsicmp(szStr, STR_REG_SZ) == 0)
  639. {
  640. nResult = REG_SZ;
  641. }
  642. else if(_tcsicmp(szStr, STR_REG_EXPAND_SZ) == 0)
  643. {
  644. nResult = REG_EXPAND_SZ;
  645. }
  646. else if(_tcsicmp(szStr, STR_REG_MULTI_SZ) == 0)
  647. {
  648. nResult = REG_MULTI_SZ;
  649. }
  650. else if(_tcsicmp(szStr, STR_REG_BINARY) == 0)
  651. {
  652. nResult = REG_BINARY;
  653. }
  654. else if(_tcsicmp(szStr, STR_REG_DWORD) == 0)
  655. {
  656. nResult = REG_DWORD;
  657. }
  658. else if(_tcsicmp(szStr, STR_REG_DWORD_LITTLE_ENDIAN) == 0)
  659. {
  660. nResult = REG_DWORD_LITTLE_ENDIAN;
  661. }
  662. else if(_tcsicmp(szStr, STR_REG_DWORD_BIG_ENDIAN) == 0)
  663. {
  664. nResult = REG_DWORD_BIG_ENDIAN;
  665. }
  666. else if(_tcsicmp(szStr, STR_REG_NONE) == 0)
  667. {
  668. nResult = REG_NONE;
  669. }
  670. return nResult;
  671. }
  672. //------------------------------------------------------------------------//
  673. //
  674. // Banner()
  675. //
  676. //------------------------------------------------------------------------//
  677. void Banner()
  678. {
  679. TCHAR szCopyRight[LENGTH_MESSAGE] = {0};
  680. LONG rc = 0;
  681. rc = LoadString( NULL,
  682. IDS_REG_BANNER,
  683. szCopyRight,
  684. LENGTH_MESSAGE);
  685. if( rc ) {
  686. MyTPrintf( stdout,_T("\r\n%s\r\n"), szCopyRight );
  687. }
  688. rc = LoadString( NULL,
  689. IDS_COPYRIGHT,
  690. szCopyRight,
  691. LENGTH_MESSAGE);
  692. if( rc ) {
  693. MyTPrintf( stdout,_T("%s\r\n"), szCopyRight );
  694. }
  695. }
  696. //------------------------------------------------------------------------//
  697. //
  698. // Usage() - Display Usage Information
  699. //
  700. //------------------------------------------------------------------------//
  701. void Usage(APPVARS AppVars)
  702. {
  703. TCHAR szUsage1[LENGTH_USAGE] = {0};
  704. TCHAR szUsage2[LENGTH_USAGE] = {0};
  705. switch(AppVars.nOperation)
  706. {
  707. case REG_QUERY:
  708. LoadString(NULL,
  709. IDS_USAGE_QUERY,
  710. szUsage1,
  711. LENGTH_USAGE);
  712. break;
  713. case REG_ADD:
  714. LoadString(NULL,
  715. IDS_USAGE_ADD1,
  716. szUsage1,
  717. LENGTH_USAGE);
  718. LoadString(NULL,
  719. IDS_USAGE_ADD2,
  720. szUsage2,
  721. LENGTH_USAGE);
  722. break;
  723. case REG_DELETE:
  724. LoadString(NULL,
  725. IDS_USAGE_DELETE,
  726. szUsage1,
  727. LENGTH_USAGE);
  728. break;
  729. case REG_COPY:
  730. LoadString(NULL,
  731. IDS_USAGE_COPY,
  732. szUsage1,
  733. LENGTH_USAGE);
  734. break;
  735. case REG_SAVE:
  736. LoadString(NULL,
  737. IDS_USAGE_SAVE,
  738. szUsage1,
  739. LENGTH_USAGE);
  740. break;
  741. case REG_RESTORE:
  742. LoadString(NULL,
  743. IDS_USAGE_RESTORE,
  744. szUsage1,
  745. LENGTH_USAGE);
  746. break;
  747. case REG_LOAD:
  748. LoadString(NULL,
  749. IDS_USAGE_LOAD,
  750. szUsage1,
  751. LENGTH_USAGE);
  752. break;
  753. case REG_UNLOAD:
  754. LoadString(NULL,
  755. IDS_USAGE_UNLOAD,
  756. szUsage1,
  757. LENGTH_USAGE);
  758. break;
  759. case REG_COMPARE:
  760. LoadString(NULL,
  761. IDS_USAGE_COMPARE1,
  762. szUsage1,
  763. LENGTH_USAGE);
  764. LoadString(NULL,
  765. IDS_USAGE_COMPARE2,
  766. szUsage2,
  767. LENGTH_USAGE);
  768. break;
  769. case REG_EXPORT:
  770. LoadString(NULL,
  771. IDS_USAGE_EXPORT,
  772. szUsage1,
  773. LENGTH_USAGE);
  774. break;
  775. case REG_IMPORT:
  776. LoadString(NULL,
  777. IDS_USAGE_IMPORT,
  778. szUsage1,
  779. LENGTH_USAGE);
  780. break;
  781. default:
  782. LoadString(NULL,
  783. IDS_USAGE_REG,
  784. szUsage1,
  785. LENGTH_USAGE);
  786. break;
  787. }
  788. MyTPrintf(stdout,_T("%s%s"), szUsage1, szUsage2);
  789. }
  790. //------------------------------------------------------------------------//
  791. //
  792. // IsMachineName()
  793. //
  794. //------------------------------------------------------------------------//
  795. REG_STATUS ParseMachineName(TCHAR* szStr, PAPPVARS pAppVars)
  796. {
  797. //
  798. // copy string
  799. //
  800. if(!_tcsicmp(szStr, _T("\\\\"))) // need a machine name
  801. return REG_STATUS_BADKEYNAME;
  802. else if(!_tcsicmp(szStr, _T("\\\\."))) // current machine
  803. return ERROR_SUCCESS;
  804. pAppVars->szMachineName = (TCHAR*) calloc(_tcslen(szStr) + 1,
  805. sizeof(TCHAR));
  806. if (!pAppVars->szMachineName) {
  807. return ERROR_NOT_ENOUGH_MEMORY;
  808. }
  809. _tcscpy(pAppVars->szMachineName, szStr);
  810. pAppVars->bUseRemoteMachine = TRUE;
  811. return ERROR_SUCCESS;
  812. }
  813. LONG RegConnectMachine(PAPPVARS pAppVars)
  814. {
  815. HKEY hKeyConnect;
  816. LONG nResult = ERROR_SUCCESS;
  817. if (pAppVars->bUseRemoteMachine)
  818. {
  819. // close the remote key
  820. if(pAppVars->bCleanRemoteRootKey)
  821. RegCloseKey(pAppVars->hRootKey);
  822. // connect to remote key
  823. nResult = RegConnectRegistry(pAppVars->szMachineName,
  824. pAppVars->hRootKey,
  825. &hKeyConnect);
  826. if (nResult == ERROR_SUCCESS)
  827. {
  828. pAppVars->hRootKey = hKeyConnect;
  829. pAppVars->bCleanRemoteRootKey = TRUE;
  830. }
  831. }
  832. return nResult;
  833. }
  834. //
  835. // BOOL
  836. // IsConsoleHandle(
  837. // IN HANDLE ConsoleHandle
  838. // );
  839. //
  840. #define IsConsoleHandle( h ) \
  841. ((( DWORD_PTR )( h )) & 1 )
  842. TCHAR ReallyBigBuffer[4096];
  843. CHAR ReallyBigBufferAnsi[4096];
  844. int __cdecl
  845. MyTPrintf(
  846. FILE* fp,
  847. LPCTSTR FormatString,
  848. ...
  849. )
  850. /*++
  851. Routine Description:
  852. This is a function that does what tprintf should really do for console
  853. applications.
  854. tprintf converts strings for the terminal to ansi codepage instead of
  855. oem codepage. This doesn't work for localized apps where the ansi codepage
  856. conversions do not match the oem codepage conversions.
  857. This routine uses WriteConsole() api instead, which does the correct
  858. thing for console apps, but only if the app is writing to the console. if
  859. it's not writing to the console, WriteConsole will fail, so we have to do
  860. something different. So the output unicode text is converted to and saved
  861. in ansi codepage format. This means you can look at the output text with
  862. "notepad.exe" but not with the "type" command for instance.
  863. Arguments:
  864. FormatString - format string
  865. Return Value:
  866. Number of characters written to stdout.
  867. --*/
  868. {
  869. va_list arglist;
  870. HANDLE Handle;
  871. DWORD CharsIn, CharsOut;
  872. PSTR pBuffer;
  873. BOOL Success;
  874. va_start(arglist,FormatString);
  875. CharsIn = _vsntprintf( ReallyBigBuffer, sizeof(ReallyBigBuffer)/sizeof(TCHAR), FormatString, arglist );
  876. //
  877. // If the standard output handle is a console handle, write the string
  878. // via console api
  879. //
  880. Handle = GetStdHandle( fp == stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE );
  881. if ( IsConsoleHandle( Handle )) {
  882. Success = WriteConsole(
  883. Handle,
  884. ReallyBigBuffer,
  885. CharsIn,
  886. &CharsOut,
  887. NULL
  888. );
  889. } else {
  890. #ifdef UNICODE
  891. //
  892. // convert to ansi codepage and write to stdout
  893. //
  894. int rc;
  895. rc = WideCharToMultiByte(
  896. CP_ACP,
  897. 0,
  898. ReallyBigBuffer,
  899. CharsIn,
  900. ReallyBigBufferAnsi,
  901. sizeof( ReallyBigBufferAnsi ),
  902. NULL,
  903. NULL
  904. );
  905. if ( rc == 0 ) {
  906. Success = FALSE;
  907. goto exit;
  908. }
  909. pBuffer = ReallyBigBufferAnsi;
  910. #else
  911. pBuffer = ReallyBigBuffer;
  912. #endif
  913. Success = WriteFile(
  914. Handle,
  915. pBuffer,
  916. CharsIn,
  917. &CharsOut,
  918. NULL
  919. );
  920. }
  921. exit:
  922. va_end(arglist);
  923. //
  924. // Return the number of characters written.
  925. //
  926. if ( Success ) {
  927. return CharsOut;
  928. } else {
  929. return 0;
  930. }
  931. }
  932. // ***************************************************************************
  933. // Routine Description:
  934. //
  935. // Complex scripts cannot be rendered in the console, so we
  936. // force the English (US) resource.
  937. //
  938. // Arguments:
  939. // [ in ] dwReserved => must be zero
  940. //
  941. // Return Value:
  942. // TRUE / FALSE
  943. //
  944. // ***************************************************************************
  945. BOOL SetThreadUILanguage0( DWORD dwReserved )
  946. {
  947. // local variables
  948. HMODULE hKernel32Lib = NULL;
  949. const CHAR cstrFunctionName[] = "SetThreadUILanguage";
  950. typedef BOOLEAN (WINAPI * FUNC_SetThreadUILanguage)( DWORD dwReserved );
  951. FUNC_SetThreadUILanguage pfnSetThreadUILanguage = NULL;
  952. // try loading the kernel32 dynamic link library
  953. hKernel32Lib = LoadLibrary( _T( "kernel32.dll" ) );
  954. if ( hKernel32Lib != NULL )
  955. {
  956. // library loaded successfully ... now load the addresses of functions
  957. pfnSetThreadUILanguage = (FUNC_SetThreadUILanguage) GetProcAddress( hKernel32Lib, cstrFunctionName );
  958. // we will keep the library loaded in memory only if all the functions were loaded successfully
  959. if ( pfnSetThreadUILanguage == NULL )
  960. {
  961. // some (or) all of the functions were not loaded ... unload the library
  962. FreeLibrary( hKernel32Lib );
  963. hKernel32Lib = NULL;
  964. pfnSetThreadUILanguage = NULL;
  965. return FALSE;
  966. }
  967. else
  968. {
  969. // call the function
  970. ((FUNC_SetThreadUILanguage) pfnSetThreadUILanguage)( dwReserved );
  971. }
  972. }
  973. // unload the library and return success
  974. FreeLibrary( hKernel32Lib );
  975. hKernel32Lib = NULL;
  976. pfnSetThreadUILanguage = NULL;
  977. return TRUE;
  978. }