registry.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Westwood Library *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/registry.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 11/27/01 2:03p $*
  29. * *
  30. * $Revision:: 14 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  34. #include "registry.h"
  35. #include "rawfile.h"
  36. #include "ini.h"
  37. #include "inisup.h"
  38. #include <assert.h>
  39. #include <windows.h>
  40. //#include "wwdebug.h"
  41. bool RegistryClass::IsLocked = false;
  42. bool RegistryClass::Exists(const char* sub_key)
  43. {
  44. HKEY hKey;
  45. LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sub_key, 0, KEY_READ, &hKey);
  46. if (ERROR_SUCCESS == result) {
  47. RegCloseKey(hKey);
  48. return true;
  49. }
  50. return false;
  51. }
  52. /*
  53. **
  54. */
  55. RegistryClass::RegistryClass( const char * sub_key, bool create ) :
  56. IsValid( false )
  57. {
  58. HKEY key;
  59. assert( sizeof(HKEY) == sizeof(int) );
  60. LONG result = -1;
  61. if (create && !IsLocked) {
  62. DWORD disposition;
  63. result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sub_key, 0, NULL, 0,
  64. KEY_ALL_ACCESS, NULL, &key, &disposition);
  65. } else {
  66. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sub_key, 0, IsLocked ? KEY_READ : KEY_ALL_ACCESS, &key);
  67. }
  68. if (ERROR_SUCCESS == result) {
  69. IsValid = true;
  70. Key = (int)key;
  71. }
  72. }
  73. RegistryClass::~RegistryClass( void )
  74. {
  75. if ( IsValid ) {
  76. if (::RegCloseKey( (HKEY)Key ) != ERROR_SUCCESS) { // Close the reg key
  77. }
  78. IsValid = false;
  79. }
  80. }
  81. int RegistryClass::Get_Int( const char * name, int def_value )
  82. {
  83. assert( IsValid );
  84. DWORD type, data = 0, data_len = sizeof( data );
  85. if (( ::RegQueryValueEx( (HKEY)Key, name, NULL, &type, (LPBYTE)&data, &data_len ) ==
  86. ERROR_SUCCESS ) && ( type == REG_DWORD )) {
  87. } else {
  88. data = def_value;
  89. }
  90. return data;
  91. }
  92. void RegistryClass::Set_Int( const char * name, int value )
  93. {
  94. assert( IsValid );
  95. if (IsLocked) {
  96. return;
  97. }
  98. if (::RegSetValueEx( (HKEY)Key, name, 0, REG_DWORD, (LPBYTE)&value, sizeof( DWORD ) ) !=
  99. ERROR_SUCCESS) {
  100. }
  101. }
  102. bool RegistryClass::Get_Bool( const char * name, bool def_value )
  103. {
  104. return (Get_Int( name, def_value ) != 0);
  105. }
  106. void RegistryClass::Set_Bool( const char * name, bool value )
  107. {
  108. Set_Int( name, value ? 1 : 0 );
  109. }
  110. float RegistryClass::Get_Float( const char * name, float def_value )
  111. {
  112. assert( IsValid );
  113. float data = 0;
  114. DWORD type, data_len = sizeof( data );
  115. if (( ::RegQueryValueEx( (HKEY)Key, name, NULL, &type, (LPBYTE)&data, &data_len ) ==
  116. ERROR_SUCCESS ) && ( type == REG_DWORD )) {
  117. } else {
  118. data = def_value;
  119. }
  120. return data;
  121. }
  122. void RegistryClass::Set_Float( const char * name, float value )
  123. {
  124. assert( IsValid );
  125. if (IsLocked) {
  126. return;
  127. }
  128. if (::RegSetValueEx( (HKEY)Key, name, 0, REG_DWORD, (LPBYTE)&value, sizeof( DWORD ) ) !=
  129. ERROR_SUCCESS) {
  130. }
  131. }
  132. int RegistryClass::Get_Bin_Size( const char * name )
  133. {
  134. assert( IsValid );
  135. unsigned long size = 0;
  136. ::RegQueryValueEx( (HKEY)Key, name, NULL, NULL, NULL, &size );
  137. return size;
  138. }
  139. void RegistryClass::Get_Bin( const char * name, void *buffer, int buffer_size )
  140. {
  141. assert( IsValid );
  142. assert( buffer != NULL );
  143. assert( buffer_size > 0 );
  144. unsigned long size = buffer_size;
  145. ::RegQueryValueEx( (HKEY)Key, name, NULL, NULL, (LPBYTE)buffer, &size );
  146. return ;
  147. }
  148. void RegistryClass::Set_Bin( const char * name, const void *buffer, int buffer_size )
  149. {
  150. assert( IsValid );
  151. assert( buffer != NULL );
  152. assert( buffer_size > 0 );
  153. if (IsLocked) {
  154. return;
  155. }
  156. ::RegSetValueEx( (HKEY)Key, name, 0, REG_BINARY, (LPBYTE)buffer, buffer_size );
  157. return ;
  158. }
  159. void RegistryClass::Get_String( const char * name, StringClass &string, const char *default_string )
  160. {
  161. assert( IsValid );
  162. string = (default_string == NULL) ? "" : default_string;
  163. //
  164. // Get the size of the entry
  165. //
  166. DWORD data_size = 0;
  167. DWORD type = 0;
  168. LONG result = ::RegQueryValueEx ((HKEY)Key, name, NULL, &type, NULL, &data_size);
  169. if (result == ERROR_SUCCESS && type == REG_SZ) {
  170. //
  171. // Read the entry from the registry
  172. //
  173. ::RegQueryValueEx ((HKEY)Key, name, NULL, &type,
  174. (LPBYTE)string.Get_Buffer (data_size), &data_size);
  175. }
  176. return ;
  177. }
  178. char *RegistryClass::Get_String( const char * name, char *value, int value_size,
  179. const char * default_string )
  180. {
  181. assert( IsValid );
  182. DWORD type = 0;
  183. if (( ::RegQueryValueEx( (HKEY)Key, name, NULL, &type, (LPBYTE)value, (DWORD*)&value_size ) ==
  184. ERROR_SUCCESS ) && ( type == REG_SZ )) {
  185. } else {
  186. //*value = 0;
  187. //value = (char *) default_string;
  188. if (default_string == NULL) {
  189. *value = 0;
  190. } else {
  191. assert(strlen(default_string) < (unsigned int) value_size);
  192. strcpy(value, default_string);
  193. }
  194. }
  195. return value;
  196. }
  197. void RegistryClass::Set_String( const char * name, const char *value )
  198. {
  199. assert( IsValid );
  200. int size = strlen( value ) + 1; // must include NULL
  201. if (IsLocked) {
  202. return;
  203. }
  204. if (::RegSetValueEx( (HKEY)Key, name, 0, REG_SZ, (LPBYTE)value, size ) !=
  205. ERROR_SUCCESS ) {
  206. }
  207. }
  208. void RegistryClass::Get_Value_List( DynamicVectorClass<StringClass> &list )
  209. {
  210. char value_name[128];
  211. //
  212. // Simply enumerate all the values in this key
  213. //
  214. int index = 0;
  215. unsigned long sizeof_name = sizeof (value_name);
  216. while (::RegEnumValue ((HKEY)Key, index ++,
  217. value_name, &sizeof_name, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
  218. {
  219. sizeof_name = sizeof (value_name);
  220. //
  221. // Add this value name to the list
  222. //
  223. list.Add( value_name );
  224. }
  225. return ;
  226. }
  227. void RegistryClass::Delete_Value( const char * name)
  228. {
  229. if (IsLocked) {
  230. return;
  231. }
  232. ::RegDeleteValue( (HKEY)Key, name );
  233. return ;
  234. }
  235. void RegistryClass::Deleta_All_Values( void )
  236. {
  237. if (IsLocked) {
  238. return;
  239. }
  240. //
  241. // Build a list of the values in this key
  242. //
  243. DynamicVectorClass<StringClass> value_list;
  244. Get_Value_List (value_list);
  245. //
  246. // Loop over and delete each value
  247. //
  248. for (int index = 0; index < value_list.Count (); index ++) {
  249. Delete_Value( value_list[index] );
  250. }
  251. return ;
  252. }
  253. void RegistryClass::Get_String( const WCHAR * name, WideStringClass &string, const WCHAR *default_string )
  254. {
  255. assert( IsValid );
  256. string = (default_string == NULL) ? L"" : default_string;
  257. //
  258. // Get the size of the entry
  259. //
  260. DWORD data_size = 0;
  261. DWORD type = 0;
  262. LONG result = ::RegQueryValueExW ((HKEY)Key, name, NULL, &type, NULL, &data_size);
  263. if (result == ERROR_SUCCESS && type == REG_SZ) {
  264. //
  265. // Read the entry from the registry
  266. //
  267. ::RegQueryValueExW ((HKEY)Key, name, NULL, &type,
  268. (LPBYTE)string.Get_Buffer ((data_size / 2) + 1), &data_size);
  269. }
  270. return ;
  271. }
  272. void RegistryClass::Set_String( const WCHAR * name, const WCHAR *value )
  273. {
  274. assert( IsValid );
  275. //
  276. // Determine the size
  277. //
  278. int size = wcslen( value ) + 1;
  279. size = size * 2;
  280. //
  281. // Set the registry key
  282. //
  283. if (IsLocked) {
  284. return;
  285. }
  286. ::RegSetValueExW ( (HKEY)Key, name, 0, REG_SZ, (LPBYTE)value, size );
  287. return ;
  288. }
  289. /***********************************************************************************************
  290. * RegistryClass::Save_Registry_Values -- Save values in a key to an .ini file *
  291. * *
  292. * *
  293. * *
  294. * INPUT: Handle to key *
  295. * Path to key *
  296. * INI *
  297. * *
  298. * OUTPUT: Nothing *
  299. * *
  300. * WARNINGS: None *
  301. * *
  302. * HISTORY: *
  303. * 11/21/2001 3:32PM ST : Created *
  304. *=============================================================================================*/
  305. void RegistryClass::Save_Registry_Values(HKEY key, char *path, INIClass *ini)
  306. {
  307. int index = 0;
  308. long result = ERROR_SUCCESS;
  309. char save_name[512];
  310. while (result == ERROR_SUCCESS) {
  311. unsigned long type = 0;
  312. unsigned char data[8192];
  313. unsigned long data_size = sizeof(data);
  314. char value_name[256];
  315. unsigned long value_name_size = sizeof(value_name);
  316. result = RegEnumValue(key, index, value_name, &value_name_size, 0, &type, data, &data_size);
  317. if (result == ERROR_SUCCESS) {
  318. switch (type) {
  319. /*
  320. ** Handle dword values.
  321. */
  322. case REG_DWORD:
  323. strcpy(save_name, "DWORD_");
  324. strcat(save_name, value_name);
  325. ini->Put_Int(path, save_name, *((unsigned long*)data));
  326. break;
  327. /*
  328. ** Handle string values.
  329. */
  330. case REG_SZ:
  331. strcpy(save_name, "STRING_");
  332. strcat(save_name, value_name);
  333. ini->Put_String(path, save_name, (char*)data);
  334. break;
  335. /*
  336. ** Handle binary values.
  337. */
  338. case REG_BINARY:
  339. strcpy(save_name, "BIN_");
  340. strcat(save_name, value_name);
  341. ini->Put_UUBlock(path, save_name, (char*)data, data_size);
  342. break;
  343. /*
  344. ** Anything else isn't handled yet.
  345. */
  346. default:
  347. WWASSERT(type == REG_DWORD || type == REG_SZ || type == REG_BINARY);
  348. break;
  349. }
  350. }
  351. index++;
  352. }
  353. }
  354. /***********************************************************************************************
  355. * RegistryClass::Save_Registry_Tree -- Save out a whole chunk or registry as an .INI *
  356. * *
  357. * *
  358. * *
  359. * INPUT: Registry path *
  360. * INI to write to *
  361. * *
  362. * OUTPUT: Nothing *
  363. * *
  364. * WARNINGS: None *
  365. * *
  366. * HISTORY: *
  367. * 11/21/2001 3:33PM ST : Created *
  368. *=============================================================================================*/
  369. void RegistryClass::Save_Registry_Tree(char *path, INIClass *ini)
  370. {
  371. HKEY base_key;
  372. HKEY sub_key;
  373. int index = 0;
  374. char name[256];
  375. unsigned long name_size = sizeof(name);
  376. char class_name[256];
  377. unsigned long class_name_size = sizeof(class_name);
  378. FILETIME file_time;
  379. memset(&file_time, 0, sizeof(file_time));
  380. long result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_ALL_ACCESS, &base_key);
  381. WWASSERT(result == ERROR_SUCCESS);
  382. if (result == ERROR_SUCCESS) {
  383. Save_Registry_Values(base_key, path, ini);
  384. while (result == ERROR_SUCCESS) {
  385. class_name_size = sizeof(class_name);
  386. name_size = sizeof(name);
  387. result = RegEnumKeyEx(base_key, index, name, &name_size, 0, class_name, &class_name_size, &file_time);
  388. if (result == ERROR_SUCCESS) {
  389. /*
  390. ** See if there are sub keys.
  391. */
  392. char new_key_path[512];
  393. strcpy(new_key_path, path);
  394. strcat(new_key_path, "\\");
  395. strcat(new_key_path, name);
  396. unsigned long num_subs = 0;
  397. unsigned long num_values = 0;
  398. long new_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, new_key_path, 0, KEY_ALL_ACCESS, &sub_key);
  399. if (new_result == ERROR_SUCCESS) {
  400. new_result = RegQueryInfoKey(sub_key, NULL, NULL, 0, &num_subs, NULL, NULL, &num_values, NULL, NULL, NULL, NULL);
  401. /*
  402. ** If there are sun keys then enumerate those.
  403. */
  404. if (num_subs > 0) {
  405. Save_Registry_Tree(new_key_path, ini);
  406. }
  407. if (num_values > 0) {
  408. Save_Registry_Values(sub_key, new_key_path, ini);
  409. }
  410. RegCloseKey(sub_key);
  411. }
  412. }
  413. index++;
  414. }
  415. RegCloseKey(base_key);
  416. }
  417. }
  418. /***********************************************************************************************
  419. * RegistryClass::Save_Registry -- Save a chunk of registry to an .ini file. *
  420. * *
  421. * *
  422. * *
  423. * INPUT: File name *
  424. * Registry path *
  425. * *
  426. * OUTPUT: Nothing *
  427. * *
  428. * WARNINGS: None *
  429. * *
  430. * HISTORY: *
  431. * 11/21/2001 3:36PM ST : Created *
  432. *=============================================================================================*/
  433. void RegistryClass::Save_Registry(const char *filename, char *path)
  434. {
  435. RawFileClass file(filename);
  436. INIClass ini;
  437. Save_Registry_Tree(path, &ini);
  438. ini.Save(file);
  439. }
  440. /***********************************************************************************************
  441. * RegistryClass::Load_Registry -- Load a chunk of registry from an .INI file *
  442. * *
  443. * *
  444. * *
  445. * INPUT: Nothing *
  446. * *
  447. * OUTPUT: Nothing *
  448. * *
  449. * WARNINGS: None *
  450. * *
  451. * HISTORY: *
  452. * 11/21/2001 3:35PM ST : Created *
  453. *=============================================================================================*/
  454. void RegistryClass::Load_Registry(const char *filename, char *old_path, char *new_path)
  455. {
  456. if (!IsLocked) {
  457. RawFileClass file(filename);
  458. INIClass ini;
  459. ini.Load(file);
  460. int old_path_len = strlen(old_path);
  461. char path[1024];
  462. char string[1024];
  463. unsigned char buffer[8192];
  464. List<INISection *> &section_list = ini.Get_Section_List();
  465. for (INISection *section = section_list.First() ; section != NULL ; section = section->Next_Valid()) {
  466. /*
  467. ** Build the new path to use in the registry.
  468. */
  469. char *section_name = section->Section;
  470. strcpy(path, new_path);
  471. char *cut = strstr(section_name, old_path);
  472. if (cut) {
  473. strcat(path, cut + old_path_len);
  474. }
  475. /*
  476. ** Create the registry key.
  477. */
  478. RegistryClass reg(path);
  479. if (reg.Is_Valid()) {
  480. char *entry = (char*)1;
  481. int index = 0;
  482. while (entry) {
  483. entry = (char*)ini.Get_Entry(section_name, index++);
  484. if (entry) {
  485. if (strncmp(entry, "BIN_", 4) == 0) {
  486. int len = ini.Get_UUBlock(section_name, entry, buffer, sizeof(buffer));
  487. reg.Set_Bin(entry+4, buffer, len);
  488. } else {
  489. if (strncmp(entry, "DWORD_", 6) == 0) {
  490. int temp = ini.Get_Int(section_name, entry, 0);
  491. reg.Set_Int(entry+6, temp);
  492. } else {
  493. if (strncmp(entry, "STRING_", 7) == 0) {
  494. ini.Get_String(section_name, entry, "", string, sizeof(string));
  495. reg.Set_String(entry+7, string);
  496. } else {
  497. WWASSERT(false);
  498. }
  499. }
  500. }
  501. }
  502. }
  503. }
  504. }
  505. }
  506. }
  507. /***********************************************************************************************
  508. * RegistryClass::Delete_Registry_Values -- Delete all values under the given key *
  509. * *
  510. * *
  511. * *
  512. * INPUT: Key handle *
  513. * *
  514. * OUTPUT: Nothing *
  515. * *
  516. * WARNINGS: None *
  517. * *
  518. * HISTORY: *
  519. * 11/21/2001 3:37PM ST : Created *
  520. *=============================================================================================*/
  521. void RegistryClass::Delete_Registry_Values(HKEY key)
  522. {
  523. int index = 0;
  524. long result = ERROR_SUCCESS;
  525. while (result == ERROR_SUCCESS) {
  526. unsigned long type = 0;
  527. unsigned char data[8192];
  528. unsigned long data_size = sizeof(data);
  529. char value_name[256];
  530. unsigned long value_name_size = sizeof(value_name);
  531. result = RegEnumValue(key, index, value_name, &value_name_size, 0, &type, data, &data_size);
  532. if (result == ERROR_SUCCESS) {
  533. result = RegDeleteValue(key, value_name);
  534. }
  535. }
  536. }
  537. /***********************************************************************************************
  538. * RegistryClass::Delete_Registry_Tree -- Delete all values and sub keys of a registry key *
  539. * *
  540. * *
  541. * *
  542. * INPUT: Registry path to delete *
  543. * *
  544. * OUTPUT: Nothing *
  545. * *
  546. * WARNINGS: !!!!! DANGER DANGER !!!!! *
  547. * *
  548. * HISTORY: *
  549. * 11/21/2001 3:38PM ST : Created *
  550. *=============================================================================================*/
  551. void RegistryClass::Delete_Registry_Tree(char *path)
  552. {
  553. if (!IsLocked) {
  554. HKEY base_key;
  555. HKEY sub_key;
  556. int index = 0;
  557. char name[256];
  558. unsigned long name_size = sizeof(name);
  559. char class_name[256];
  560. unsigned long class_name_size = sizeof(class_name);
  561. FILETIME file_time;
  562. memset(&file_time, 0, sizeof(file_time));
  563. int max_times = 1000;
  564. long result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_ALL_ACCESS, &base_key);
  565. if (result == ERROR_SUCCESS) {
  566. Delete_Registry_Values(base_key);
  567. index = 0;
  568. while (result == ERROR_SUCCESS) {
  569. class_name_size = sizeof(class_name);
  570. name_size = sizeof(name);
  571. result = RegEnumKeyEx(base_key, index, name, &name_size, 0, class_name, &class_name_size, &file_time);
  572. if (result == ERROR_SUCCESS) {
  573. /*
  574. ** See if there are sub keys.
  575. */
  576. char new_key_path[512];
  577. strcpy(new_key_path, path);
  578. strcat(new_key_path, "\\");
  579. strcat(new_key_path, name);
  580. unsigned long num_subs = 0;
  581. unsigned long num_values = 0;
  582. long new_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, new_key_path, 0, KEY_ALL_ACCESS, &sub_key);
  583. if (new_result == ERROR_SUCCESS) {
  584. new_result = RegQueryInfoKey(sub_key, NULL, NULL, 0, &num_subs, NULL, NULL, &num_values, NULL, NULL, NULL, NULL);
  585. /*
  586. ** If there are sub keys then enumerate those.
  587. */
  588. if (num_subs > 0) {
  589. Delete_Registry_Tree(new_key_path);
  590. }
  591. if (num_values > 0) {
  592. Delete_Registry_Values(sub_key);
  593. }
  594. RegCloseKey(sub_key);
  595. RegDeleteKey(base_key, name);
  596. }
  597. }
  598. max_times--;
  599. if (max_times <= 0) {
  600. break;
  601. }
  602. }
  603. RegCloseKey(base_key);
  604. RegDeleteKey(HKEY_LOCAL_MACHINE, path);
  605. }
  606. }
  607. }