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.

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