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.

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