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.

889 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. reg.cxx
  5. Abstract:
  6. Contains code that implements REGISTRY_OBJ class defined in reg.hxx.
  7. Author:
  8. Madan Appiah (madana) 19-Dec-1994
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include <svcloc.hxx>
  14. MEMORY *CacheHeap = NULL;
  15. INLINE
  16. DWORD
  17. REGISTRY_OBJ::GetValueSizeAndType(
  18. LPWSTR ValueName,
  19. LPDWORD ValueSize,
  20. LPDWORD ValueType
  21. )
  22. /*++
  23. Routine Description:
  24. This function returns the size and type of a value of this key.
  25. Arguments:
  26. ValueName : name of the value whose size and type returned.
  27. ValueSize : pointer to a location where the value size is returned.
  28. ValueType : pointer to a location where the value type is returned.
  29. Return Value:
  30. Windows Error Code.
  31. --*/
  32. {
  33. DWORD Error;
  34. Error = RegQueryValueExW(
  35. _RegHandle,
  36. ValueName,
  37. 0,
  38. ValueType,
  39. NULL,
  40. ValueSize );
  41. return( Error );
  42. }
  43. REGISTRY_OBJ::REGISTRY_OBJ(
  44. HKEY Handle,
  45. DWORD Error
  46. )
  47. /*++
  48. Routine Description:
  49. This function is a inline function that initialize the registry
  50. object with given handle and status.
  51. Arguments:
  52. Handle : registry object handle value.
  53. Error : registry object status value.
  54. Return Value:
  55. None.
  56. --*/
  57. {
  58. _RegHandle = Handle;
  59. _Status = Error;
  60. _Index = 0;
  61. _ValIndex = 0;
  62. return;
  63. };
  64. REGISTRY_OBJ::REGISTRY_OBJ(
  65. HKEY ParentHandle,
  66. LPWSTR KeyName
  67. )
  68. /*++
  69. Routine Description:
  70. Initializes the registry object from its parent's registry key
  71. handle and this object's keyname.
  72. Arguments:
  73. ParentHandle : registry handle of the parent key.
  74. Keyname : key name of the new registry object being created.
  75. Return Value:
  76. None.
  77. --*/
  78. {
  79. _Index = 0;
  80. _ValIndex = 0;
  81. _Status = RegOpenKeyExW(
  82. ParentHandle,
  83. KeyName,
  84. 0,
  85. DEFAULT_KEY_ACCESS,
  86. &_RegHandle );
  87. if( _Status != ERROR_SUCCESS ) {
  88. _RegHandle = NULL;
  89. }
  90. return;
  91. }
  92. REGISTRY_OBJ::REGISTRY_OBJ(
  93. REGISTRY_OBJ *ParentObj,
  94. LPWSTR KeyName
  95. )
  96. /*++
  97. Routine Description:
  98. Initializes the registry object from its parent's registry object
  99. and this object's keyname.
  100. Arguments:
  101. ParentObj : registry object of the parent.
  102. Keyname : key name of the new registry object being created.
  103. Return Value:
  104. None.
  105. --*/
  106. {
  107. _Index = 0;
  108. _ValIndex = 0;
  109. _Status = RegOpenKeyExW(
  110. ParentObj->_RegHandle,
  111. KeyName,
  112. 0,
  113. DEFAULT_KEY_ACCESS,
  114. &_RegHandle );
  115. if( _Status != ERROR_SUCCESS ) {
  116. _RegHandle = NULL;
  117. }
  118. return;
  119. }
  120. DWORD
  121. REGISTRY_OBJ::Create(
  122. LPWSTR ChildName
  123. )
  124. /*++
  125. Routine Description:
  126. Creates a new subkey under this key.
  127. Arguments:
  128. ChildName : name of the subkey being created.
  129. Return Value:
  130. Windows Error Code.
  131. --*/
  132. {
  133. HKEY ChildHandle;
  134. DWORD KeyDisposition;
  135. _Status = RegCreateKeyExW(
  136. _RegHandle,
  137. ChildName,
  138. 0,
  139. DEFAULT_CLASS,
  140. REG_OPTION_NON_VOLATILE,
  141. DEFAULT_KEY_ACCESS,
  142. NULL,
  143. &ChildHandle,
  144. &KeyDisposition );
  145. if( _Status != ERROR_SUCCESS ) {
  146. return( _Status );
  147. }
  148. if( KeyDisposition == REG_CREATED_NEW_KEY ) {
  149. TcpsvcsDbgPrint(( DEBUG_REGISTRY,
  150. "Registry key (%ws) is created.\n", ChildName ));
  151. }
  152. //
  153. // close the child handle before return.
  154. //
  155. RegCloseKey( ChildHandle );
  156. return( ERROR_SUCCESS );
  157. }
  158. DWORD
  159. REGISTRY_OBJ::Create(
  160. LPWSTR ChildName,
  161. REGISTRY_OBJ **ChildObj
  162. )
  163. /*++
  164. Routine Description:
  165. Creates a new subney and a new subney registry object.
  166. Arguments:
  167. ChildName : name of the subkey being created.
  168. Return Value:
  169. Windows Error Code.
  170. --*/
  171. {
  172. DWORD Error;
  173. HKEY ChildHandle;
  174. DWORD KeyDisposition;
  175. Error = RegCreateKeyExW(
  176. _RegHandle,
  177. ChildName,
  178. 0,
  179. DEFAULT_CLASS,
  180. REG_OPTION_NON_VOLATILE,
  181. DEFAULT_KEY_ACCESS,
  182. NULL,
  183. &ChildHandle,
  184. &KeyDisposition );
  185. if( Error != ERROR_SUCCESS ) {
  186. *ChildObj = new REGISTRY_OBJ( NULL, Error );
  187. }
  188. else {
  189. if( KeyDisposition == REG_CREATED_NEW_KEY ) {
  190. TcpsvcsDbgPrint(( DEBUG_REGISTRY,
  191. "Registry key (%ws) is created.\n", ChildName ));
  192. }
  193. *ChildObj = new REGISTRY_OBJ( ChildHandle, (DWORD)ERROR_SUCCESS );
  194. }
  195. return( Error );
  196. }
  197. DWORD
  198. REGISTRY_OBJ::Create(
  199. LPWSTR ChildName,
  200. REGISTRY_OBJ **ChildObj,
  201. DWORD *KeyDisposition
  202. )
  203. /*++
  204. Routine Description:
  205. Creates a new subney and a new subney registry object.
  206. Arguments:
  207. ChildName : name of the subkey being created.
  208. ChildObj : pointer to a location where the child registry object
  209. pointer is returned.
  210. KeyDisposition : pointer to a location where the child KeyDisposition
  211. value is returned.
  212. Return Value:
  213. Windows Error Code.
  214. --*/
  215. {
  216. DWORD Error;
  217. HKEY ChildHandle;
  218. Error = RegCreateKeyExW(
  219. _RegHandle,
  220. ChildName,
  221. 0,
  222. DEFAULT_CLASS,
  223. REG_OPTION_NON_VOLATILE,
  224. DEFAULT_KEY_ACCESS,
  225. NULL,
  226. &ChildHandle,
  227. KeyDisposition );
  228. if( Error != ERROR_SUCCESS ) {
  229. *ChildObj = new REGISTRY_OBJ( NULL, Error );
  230. }
  231. else {
  232. if( *KeyDisposition == REG_CREATED_NEW_KEY ) {
  233. TcpsvcsDbgPrint(( DEBUG_REGISTRY,
  234. "Registry key (%ws) is created.\n", ChildName ));
  235. }
  236. *ChildObj = new REGISTRY_OBJ( ChildHandle, (DWORD)ERROR_SUCCESS );
  237. }
  238. return( Error );
  239. }
  240. DWORD
  241. REGISTRY_OBJ::GetValue(
  242. LPWSTR ValueName,
  243. DWORD *Data
  244. )
  245. /*++
  246. Routine Description:
  247. Gets a REG_DWORD value.
  248. Arguments:
  249. ValueName : name of the value being retrived.
  250. Return Value:
  251. Windows Error Code.
  252. --*/
  253. {
  254. DWORD Error;
  255. DWORD ValueType;
  256. DWORD ValueSize = sizeof(DWORD);
  257. Error = RegQueryValueExW(
  258. _RegHandle,
  259. ValueName,
  260. 0,
  261. &ValueType,
  262. (LPBYTE)Data,
  263. &ValueSize );
  264. TcpsvcsDbgAssert( ValueSize == sizeof( DWORD ) );
  265. TcpsvcsDbgAssert( ValueType == REG_DWORD );
  266. return( Error );
  267. }
  268. DWORD
  269. REGISTRY_OBJ::GetValue(
  270. LPWSTR ValueName,
  271. LPWSTR *Data,
  272. DWORD *NumStrings
  273. )
  274. /*++
  275. Routine Description:
  276. Gets a REG_SZ or REG_EXPAND_SZ or REG_MULTI_SZ value.
  277. Arguments:
  278. ValueName : name of the value being retrived.
  279. Return Value:
  280. Windows Error Code.
  281. --*/
  282. {
  283. DWORD Error;
  284. DWORD ValueType;
  285. DWORD ValueSize;
  286. LPBYTE StringData = NULL;
  287. Error = GetValueSizeAndType( ValueName, &ValueSize, &ValueType );
  288. if( Error != ERROR_SUCCESS ) {
  289. return( Error );
  290. }
  291. TcpsvcsDbgAssert(
  292. (ValueType == REG_SZ) ||
  293. (ValueType == REG_EXPAND_SZ) ||
  294. (ValueType == REG_MULTI_SZ) );
  295. StringData = (LPBYTE)CacheHeap->Alloc( ValueSize );
  296. if( StringData == NULL ) {
  297. return( ERROR_NOT_ENOUGH_MEMORY );
  298. }
  299. Error = RegQueryValueExW(
  300. _RegHandle,
  301. ValueName,
  302. 0,
  303. &ValueType,
  304. StringData,
  305. &ValueSize );
  306. if( Error != ERROR_SUCCESS ) {
  307. CacheHeap->Free( StringData );
  308. return( Error );
  309. }
  310. *Data = (LPWSTR)StringData;
  311. if( (ValueType == REG_SZ) || (ValueType == REG_EXPAND_SZ) ) {
  312. *NumStrings = 1;
  313. }
  314. else {
  315. DWORD Strings = 0;
  316. LPWSTR StrPtr = (LPWSTR)StringData;
  317. DWORD Len;
  318. while( (Len = wcslen(StrPtr)) != 0 ) {
  319. Strings++;
  320. StrPtr = StrPtr + Len + 1;
  321. }
  322. *NumStrings = Strings;
  323. }
  324. return( ERROR_SUCCESS );
  325. }
  326. DWORD
  327. REGISTRY_OBJ::GetValue(
  328. LPWSTR ValueName,
  329. LPBYTE *Data,
  330. DWORD *DataLen
  331. )
  332. /*++
  333. Routine Description:
  334. Gets a REG_BINARY value.
  335. Arguments:
  336. ValueName : name of the value being retrived.
  337. Return Value:
  338. Windows Error Code.
  339. --*/
  340. {
  341. DWORD Error;
  342. DWORD ValueType;
  343. DWORD ValueSize;
  344. LPBYTE BinaryData = NULL;
  345. Error = GetValueSizeAndType( ValueName, &ValueSize, &ValueType );
  346. if( Error != ERROR_SUCCESS ) {
  347. return( Error );
  348. }
  349. TcpsvcsDbgAssert( ValueType == REG_BINARY );
  350. BinaryData = (LPBYTE)CacheHeap->Alloc( ValueSize );
  351. if( BinaryData == NULL ) {
  352. return( ERROR_NOT_ENOUGH_MEMORY );
  353. }
  354. Error = RegQueryValueExW(
  355. _RegHandle,
  356. ValueName,
  357. 0,
  358. &ValueType,
  359. BinaryData,
  360. &ValueSize );
  361. if( Error != ERROR_SUCCESS ) {
  362. CacheHeap->Free( BinaryData );
  363. return( Error );
  364. }
  365. *Data = BinaryData;
  366. *DataLen = ValueSize;
  367. return( ERROR_SUCCESS );
  368. }
  369. DWORD
  370. REGISTRY_OBJ::GetValue(
  371. LPWSTR ValueName,
  372. LPBYTE Data,
  373. DWORD *DataLen
  374. )
  375. /*++
  376. Routine Description:
  377. Gets a REG_BINARY value.
  378. Arguments:
  379. ValueName : name of the value being retrived.
  380. Data : pointer to a buffer where the data will be read.
  381. Datalen : pointer to location where length of the above buffer is
  382. passed. On return this location will have the length of the
  383. data read.
  384. Return Value:
  385. Windows Error Code.
  386. --*/
  387. {
  388. DWORD Error;
  389. DWORD ValueType;
  390. Error = RegQueryValueExW(
  391. _RegHandle,
  392. ValueName,
  393. 0,
  394. &ValueType,
  395. Data,
  396. DataLen );
  397. return( Error );
  398. }
  399. DWORD
  400. REGISTRY_OBJ::SetValue(
  401. LPWSTR ValueName,
  402. LPDWORD Data
  403. )
  404. /*++
  405. Routine Description:
  406. Sets a REG_DWORD value.
  407. Arguments:
  408. ValueName : name of the value being set.
  409. Date : pointer to a DWORD data.
  410. Return Value:
  411. Windows Error Code.
  412. --*/
  413. {
  414. DWORD Error;
  415. Error = RegSetValueExW(
  416. _RegHandle,
  417. ValueName,
  418. 0,
  419. REG_DWORD,
  420. (LPBYTE)Data,
  421. sizeof(DWORD) );
  422. return( Error );
  423. }
  424. DWORD
  425. REGISTRY_OBJ::SetValue(
  426. LPWSTR ValueName,
  427. LPWSTR Data,
  428. DWORD StringType
  429. )
  430. /*++
  431. Routine Description:
  432. Sets a REG_SZ or REG_EXPAND_SZ or REG_MULTI_SZ value.
  433. Data : pointer to STRING(s) data.
  434. StringType : type of string data in the above buffer, it should be
  435. either of the following types :
  436. REG_SZ or REG_EXPAND_SZ or REG_MULTI_SZ
  437. Arguments:
  438. ValueName : name of the value being set.
  439. Return Value:
  440. Windows Error Code.
  441. --*/
  442. {
  443. DWORD Error;
  444. Error = RegSetValueExW(
  445. _RegHandle,
  446. ValueName,
  447. 0,
  448. StringType,
  449. (LPBYTE)Data,
  450. sizeof(WCHAR) * (wcslen(Data) + 1) );
  451. return( Error );
  452. }
  453. DWORD
  454. REGISTRY_OBJ::SetValue(
  455. LPSTR ValueName,
  456. LPSTR Data,
  457. DWORD DataLen,
  458. DWORD StringType
  459. )
  460. /*++
  461. Routine Description:
  462. Sets a REG_SZ or REG_EXPAND_SZ or REG_MULTI_SZ value.
  463. Data : pointer to STRING(s) data.
  464. DataLen : data length
  465. StringType : type of string data in the above buffer, it should be
  466. either of the following types :
  467. REG_SZ or REG_EXPAND_SZ or REG_MULTI_SZ
  468. Arguments:
  469. ValueName : name of the value being set.
  470. Return Value:
  471. Windows Error Code.
  472. --*/
  473. {
  474. DWORD Error;
  475. Error = RegSetValueEx(
  476. _RegHandle,
  477. ValueName,
  478. 0,
  479. StringType,
  480. (LPBYTE)Data,
  481. DataLen );
  482. return( Error );
  483. }
  484. DWORD
  485. REGISTRY_OBJ::SetValue(
  486. LPWSTR ValueName,
  487. LPBYTE Data,
  488. DWORD DataLen
  489. )
  490. /*++
  491. Routine Description:
  492. Sets a REG_BINARY value.
  493. Arguments:
  494. ValueName : name of the value being set.
  495. Return Value:
  496. Windows Error Code.
  497. --*/
  498. {
  499. DWORD Error;
  500. Error = RegSetValueExW(
  501. _RegHandle,
  502. ValueName,
  503. 0,
  504. REG_BINARY,
  505. Data,
  506. DataLen );
  507. return( Error );
  508. }
  509. DWORD
  510. REGISTRY_OBJ::FindNextKey(
  511. LPWSTR Key,
  512. DWORD KeySize
  513. )
  514. /*++
  515. Routine Description:
  516. Retrieves the Next subkey name of this key.
  517. Arguments:
  518. Key - pointer to a buffer that receives the subkey name.
  519. KeySize - size of the above buffer in CHARS.
  520. Return Value:
  521. Windows Error Code.
  522. --*/
  523. {
  524. DWORD Error;
  525. DWORD KeyLength;
  526. FILETIME KeyLastWrite;
  527. KeyLength = KeySize * sizeof(WCHAR);
  528. Error = RegEnumKeyExW(
  529. _RegHandle,
  530. _Index,
  531. Key,
  532. &KeyLength,
  533. 0, // reserved.
  534. NULL, // class string not required.
  535. 0, // class string buffer size.
  536. &KeyLastWrite );
  537. if( Error != ERROR_SUCCESS ) {
  538. return( Error );
  539. }
  540. TcpsvcsDbgAssert( KeyLength <= KeySize );
  541. //
  542. // increament the index to point to the next key.
  543. //
  544. _Index++;
  545. return( ERROR_SUCCESS );
  546. }
  547. DWORD
  548. REGISTRY_OBJ::DeleteKey(
  549. LPWSTR ChildKeyName
  550. )
  551. /*++
  552. Routine Description:
  553. Deletes a subkey node.
  554. Arguments:
  555. ChildKeyName : name of the subkey to be deleted.
  556. Return Value:
  557. Windows Error Code.
  558. --*/
  559. {
  560. DWORD Error;
  561. LPWSTR GChildKeyName[MAX_KEY_SIZE];
  562. REGISTRY_OBJ ChildObj( _RegHandle, ChildKeyName );
  563. Error = ChildObj.GetStatus();
  564. if( Error != ERROR_SUCCESS ) {
  565. return( Error );
  566. }
  567. //
  568. // delete all its subkeys.
  569. //
  570. Error = ChildObj.FindFirstKey(
  571. (LPWSTR)GChildKeyName,
  572. MAX_KEY_SIZE );
  573. while( Error == ERROR_SUCCESS ) {
  574. Error = ChildObj.DeleteKey( (LPWSTR)GChildKeyName );
  575. if( Error != ERROR_SUCCESS ) {
  576. return( Error );
  577. }
  578. Error = ChildObj.FindFirstKey(
  579. (LPWSTR)GChildKeyName,
  580. MAX_KEY_SIZE );
  581. }
  582. if( Error != ERROR_NO_MORE_ITEMS ) {
  583. return( Error );
  584. }
  585. //
  586. // delete this key.
  587. //
  588. Error = RegDeleteKeyW( _RegHandle, (LPWSTR)ChildKeyName );
  589. return( Error );
  590. }
  591. DWORD
  592. REGISTRY_OBJ::FindNextValue(
  593. LPSTR ValueName,
  594. DWORD ValueSize,
  595. LPBYTE Data,
  596. DWORD *DataLen
  597. )
  598. /*++
  599. Routine Description:
  600. Retrieves the Next value name of this key.
  601. Arguments:
  602. ValueName - pointer to a buffer that receives the Value name.
  603. ValueSize - size of the above buffer in CHARS.
  604. Data - pointer to a buffer that receives the Value data.
  605. DataLen - pointer to a buffer that receives data size.
  606. Return Value:
  607. Windows Error Code.
  608. --*/
  609. {
  610. DWORD Error;
  611. DWORD ValueLength;
  612. DWORD ValueType;
  613. ValueLength = ValueSize * sizeof(CHAR);
  614. Error = RegEnumValue(
  615. _RegHandle,
  616. _ValIndex,
  617. ValueName,
  618. &ValueLength,
  619. NULL, // reserved.
  620. &ValueType,
  621. Data,
  622. DataLen );
  623. if( Error != ERROR_SUCCESS ) {
  624. return( Error );
  625. }
  626. TcpsvcsDbgAssert( ValueLength <= ValueSize );
  627. //
  628. // increment the value index to point to the next value.
  629. //
  630. _ValIndex++;
  631. return( ERROR_SUCCESS );
  632. }
  633.