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.

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