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.

2195 lines
51 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. registry.cxx
  5. Abstract:
  6. Functions to read/write registry parameters
  7. Contents:
  8. EnsureInternetSettingsKeyCached
  9. CloseInternetSettingsKey
  10. GetMyEmailName
  11. InternetGetComputerName
  12. InternetDeleteRegistryValue
  13. InternetReadRegistryDword
  14. InternetWriteRegistryDword
  15. InternetReadRegistryString
  16. InternetWriteRegistryString
  17. InternetReadRegistryBinary
  18. (InternetReadRegistryDwordKey)
  19. (InternetReadRegistryStringKey)
  20. (InternetReadRegistryBinaryKey)
  21. (InternetGetPrivateProfileString)
  22. (ReadRegistryOemString)
  23. (WriteRegistryDword)
  24. ReadRegistryDword
  25. GetFileExtensionFromMimeType
  26. CreateMimeExclusionTableForCache
  27. DestroyMimeExclusionTableForCache
  28. CreateHeaderExclusionTableForCache
  29. DestroyHeaderExclusionTableForCache
  30. (CreateTableFromRegistryList)
  31. (CreateStringArrayFromDelimitedList)
  32. Author:
  33. Richard L Firth (rfirth) 20-Mar-1995
  34. Environment:
  35. Win32(s) user-level DLL
  36. Revision History:
  37. 20-Mar-1995 rfirth
  38. Created
  39. --*/
  40. #include <wininetp.h>
  41. char vszDelimiters[] = ";, ";
  42. //
  43. // manifests
  44. //
  45. #define INTERNET_CLIENT_KEY "Internet Settings"
  46. #define SYSTEM_INI_FILE_NAME "SYSTEM.INI"
  47. #define NETWORK_SECTION_NAME "Network"
  48. #define COMPUTER_NAME_VALUE "ComputerName"
  49. #define PROFILE_INT_BUFFER_LENGTH 128
  50. #define MIME_TO_FILE_EXTENSION_KEY "MIME\\Database\\Content Type\\"
  51. #define EXTENSION_VALUE "Extension"
  52. //
  53. // private prototypes
  54. //
  55. PRIVATE
  56. DWORD
  57. InternetReadRegistryDwordKey(
  58. IN HKEY ParameterKey,
  59. IN LPCSTR ParameterName,
  60. OUT LPDWORD ParameterValue
  61. );
  62. PRIVATE
  63. DWORD
  64. InternetReadRegistryStringKey(
  65. IN HKEY ParameterKey,
  66. IN LPCSTR ParameterName,
  67. OUT LPSTR ParameterValue,
  68. IN OUT LPDWORD ParameterLength
  69. );
  70. //PRIVATE
  71. //DWORD
  72. //InternetReadRegistryBinaryKey(
  73. // IN HKEY ParameterKey,
  74. // IN LPCSTR ParameterName,
  75. // OUT LPBYTE ParameterValue,
  76. // IN OUT LPDWORD ParameterLength
  77. // );
  78. //
  79. //PRIVATE
  80. //DWORD
  81. //InternetGetPrivateProfileString(
  82. // IN LPSTR IniFileName,
  83. // IN LPSTR SectionName,
  84. // IN LPCSTR ParameterName,
  85. // OUT LPSTR ParameterValue,
  86. // IN OUT LPDWORD ParameterLength
  87. // );
  88. PRIVATE
  89. DWORD
  90. ReadRegistryOemString(
  91. IN HKEY Key,
  92. IN LPCSTR ParameterName,
  93. OUT LPSTR String,
  94. IN OUT LPDWORD Length
  95. );
  96. PRIVATE
  97. DWORD
  98. CreateTableFromRegistryList(
  99. IN LPSTR lpszParameter, // wininet registry parameter
  100. OUT LPSTR *lplpszList, // Delimited List
  101. OUT LPSTR **lplprgszTable, // Pointer table pointing into the list
  102. OUT DWORD **lplpdwTableSizes, // Pointer to table containing sizes of string elements
  103. OUT LPDWORD lpdwCount // count of elements in the table
  104. );
  105. PRIVATE
  106. DWORD
  107. CreateStringArrayFromDelimitedList(
  108. IN LPSTR lpszDelimitedList,
  109. IN LPSTR lpszDelimiters,
  110. IN LPSTR *lprgszStringArray,
  111. OUT LPDWORD lpdwCount
  112. );
  113. PRIVATE
  114. DWORD
  115. WriteRegistryDword(
  116. IN HKEY Key,
  117. IN LPCSTR ParameterName,
  118. IN DWORD ParameterValue
  119. );
  120. //
  121. // private data
  122. //
  123. PRIVATE CRefdKey* g_prkInternetSettings = NULL;
  124. //
  125. // functions
  126. //
  127. CRefdKey*
  128. OpenInternetSettingsKey(
  129. VOID
  130. )
  131. {
  132. CRefdKey* prk = NULL;
  133. HKEY hkInternetSettings = NULL;
  134. DWORD dwDisposition;
  135. REGCREATEKEYEX(HKEY_CURRENT_USER,
  136. INTERNET_SETTINGS_KEY,
  137. 0, // reserved
  138. NULL, // class
  139. 0, // options
  140. KEY_READ | KEY_WRITE,
  141. NULL, // security attributes
  142. &hkInternetSettings,
  143. &dwDisposition
  144. );
  145. if (hkInternetSettings)
  146. {
  147. prk = new CRefdKey(hkInternetSettings);
  148. if (!prk)
  149. {
  150. // we failed to create a ref'd key, so close the key we opened
  151. REGCLOSEKEY(hkInternetSettings);
  152. }
  153. }
  154. return prk;
  155. }
  156. CRefdKey*
  157. GetInternetSettingsKey(
  158. VOID
  159. )
  160. {
  161. CRefdKey* prk;
  162. EnterCriticalSection(&GeneralInitCritSec);
  163. prk = g_prkInternetSettings;
  164. if (prk)
  165. {
  166. prk->AddRef();
  167. }
  168. else
  169. {
  170. prk = OpenInternetSettingsKey();
  171. if (prk)
  172. {
  173. // addref once more for sticking in in the global
  174. prk->AddRef();
  175. // cache this value in the global
  176. g_prkInternetSettings = prk;
  177. }
  178. }
  179. LeaveCriticalSection(&GeneralInitCritSec);
  180. return prk;
  181. }
  182. VOID
  183. EnsureInternetSettingsKeyCached(
  184. VOID
  185. )
  186. /*++
  187. Routine Description:
  188. Ensures that the registry key for the Internet Settings branch is
  189. cached and ready to be used
  190. Arguments:
  191. None.
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. CRefdKey* prk;
  197. DEBUG_ENTER((DBG_REGISTRY,
  198. None,
  199. "EnsureInternetSettingsKeyCached",
  200. NULL
  201. ));
  202. // just get the key and release it to ensure that it has been cached in g_prkInternetSettings
  203. prk = GetInternetSettingsKey();
  204. if (prk)
  205. {
  206. prk->Release();
  207. }
  208. }
  209. DWORD
  210. CloseInternetSettingsKey(
  211. VOID
  212. )
  213. /*++
  214. Routine Description:
  215. Closes Internet Settings registry key
  216. Arguments:
  217. None.
  218. Return Value:
  219. DWORD
  220. Success - ERROR_SUCCESS
  221. Failure -
  222. --*/
  223. {
  224. DEBUG_ENTER((DBG_REGISTRY,
  225. Dword,
  226. "CloseInternetSettingsKey",
  227. NULL
  228. ));
  229. CRefdKey* prk;
  230. EnterCriticalSection (&GeneralInitCritSec);
  231. prk = g_prkInternetSettings;
  232. if (prk)
  233. {
  234. g_prkInternetSettings = NULL;
  235. prk->Release();
  236. }
  237. LeaveCriticalSection (&GeneralInitCritSec);
  238. DEBUG_LEAVE(ERROR_SUCCESS);
  239. return ERROR_SUCCESS;
  240. }
  241. DWORD
  242. GetMyEmailName(
  243. OUT LPSTR EmailName,
  244. IN OUT LPDWORD Length
  245. )
  246. /*++
  247. Routine Description:
  248. Retrieve the user's email name from the appropriate place in the registry
  249. Arguments:
  250. EmailName - place to store email name
  251. Length - IN: length of EmailName
  252. OUT: returned length of EmailName (in characters, minus
  253. trailing NUL)
  254. Return Value:
  255. DWORD
  256. Success - ERROR_SUCCESS
  257. Failure - ERROR_FILE_NOT_FOUND
  258. ERROR_PATH_NOT_FOUND
  259. --*/
  260. {
  261. DEBUG_ENTER((DBG_REGISTRY,
  262. Dword,
  263. "GetMyEmailName",
  264. "%#x, %#x [%d]",
  265. EmailName,
  266. Length,
  267. *Length
  268. ));
  269. DWORD error;
  270. //
  271. // for the EmailName, we first try HKEY_CURRENT_USER. If that fails then we
  272. // try the same branch of the HKEY_LOCAL_MACHINE tree. If that fails,
  273. // invent something
  274. //
  275. static HKEY KeysToTry[2] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
  276. int i;
  277. //
  278. // in the event we cannot find EmailName in both HKEY_CURRENT_USER and
  279. // HKEY_LOCAL_MACHINE trees, then we return this default
  280. //
  281. static char DefaultEmailName[] = DEFAULT_EMAIL_NAME;
  282. for (i = 0; i < ARRAY_ELEMENTS(KeysToTry); ++i) {
  283. error = InternetReadRegistryStringKey(KeysToTry[i],
  284. "EmailName",
  285. EmailName,
  286. Length
  287. );
  288. if (error == ERROR_SUCCESS) {
  289. break;
  290. }
  291. }
  292. if (error != ERROR_SUCCESS) {
  293. if (IsPlatformWinNT()) {
  294. //
  295. // only NT supports GetUserName()
  296. //
  297. if (GetUserName(EmailName, Length)) {
  298. //
  299. // we return the length as if the result from strlen/wcslen
  300. //
  301. *Length -= sizeof(char);
  302. DEBUG_PRINT(REGISTRY,
  303. INFO,
  304. ("GetUserName() returns %q\n",
  305. EmailName
  306. ));
  307. error = ERROR_SUCCESS;
  308. } else {
  309. //
  310. // BUGBUG - what's the required length?
  311. //
  312. error = GetLastError();
  313. }
  314. } else {
  315. //
  316. // Win95 & Win32s: have to do something different
  317. //
  318. }
  319. //
  320. // if we still don't have an email name, we use an internal default
  321. //
  322. if (error != ERROR_SUCCESS) {
  323. DEBUG_PRINT(REGISTRY,
  324. ERROR,
  325. ("Cannot find EmailName: using default (%s)\n",
  326. DefaultEmailName
  327. ));
  328. if (*Length >= sizeof(DEFAULT_EMAIL_NAME)) {
  329. memcpy(EmailName, DefaultEmailName, sizeof(DEFAULT_EMAIL_NAME));
  330. //
  331. // success - returned length as if from strlen()
  332. //
  333. *Length = sizeof(DEFAULT_EMAIL_NAME) - 1;
  334. error = ERROR_SUCCESS;
  335. } else {
  336. //
  337. // failure - returned length is the required buffer size
  338. //
  339. *Length = sizeof(DEFAULT_EMAIL_NAME);
  340. error = ERROR_INSUFFICIENT_BUFFER;
  341. }
  342. }
  343. }
  344. DEBUG_LEAVE(error);
  345. return error;
  346. }
  347. //
  348. //DWORD
  349. //InternetGetComputerName(
  350. // OUT LPSTR Buffer,
  351. // IN OUT LPDWORD Length
  352. // )
  353. //
  354. ///*++
  355. //
  356. //Routine Description:
  357. //
  358. // Platform-dependent function that returns this computer's name
  359. //
  360. //Arguments:
  361. //
  362. // Buffer - pointer to buffer where name is returned
  363. //
  364. // Length - IN: number of bytes in Buffer
  365. // OUT: number of characters in computer name, exluding terminating
  366. // NUL
  367. //
  368. //Return Value:
  369. //
  370. // DWORD
  371. // Success - ERROR_SUCCESS
  372. //
  373. // Failure - Win32 error
  374. //
  375. //--*/
  376. //
  377. //{
  378. // DWORD error;
  379. //
  380. // if (IsPlatformWin32s()) {
  381. // error = InternetGetPrivateProfileString(SYSTEM_INI_FILE_NAME,
  382. // NETWORK_SECTION_NAME,
  383. // COMPUTER_NAME_VALUE,
  384. // Buffer,
  385. // Length
  386. // );
  387. // } else {
  388. // if (GetComputerName(Buffer, Length)) {
  389. // error = ERROR_SUCCESS;
  390. // } else {
  391. // error = GetLastError();
  392. // }
  393. // }
  394. // return error;
  395. //}
  396. PUBLIC
  397. DWORD
  398. InternetDeleteRegistryValue(
  399. IN LPSTR ParameterName
  400. )
  401. /*++
  402. Routine Description:
  403. Delets an entry from a the Internet Client registry key if the platform
  404. is NT/Win95.
  405. Arguments:
  406. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  407. Return Value:
  408. DWORD
  409. Success - ERROR_SUCCESS
  410. Failure - ERROR_PATH_NOT_FOUND
  411. --*/
  412. {
  413. DWORD error;
  414. DEBUG_ENTER((DBG_REGISTRY,
  415. Dword,
  416. "InternetDeleteRegistryValue",
  417. "%q",
  418. ParameterName
  419. ));
  420. HKEY clientKey;
  421. //
  422. // open the registry key containing the Internet client values (this is
  423. // in the same place on NT and Win95)
  424. //
  425. error = REGOPENKEYEX(HKEY_CURRENT_USER,
  426. INTERNET_SETTINGS_KEY,
  427. 0, // reserved
  428. KEY_ALL_ACCESS,
  429. &clientKey
  430. );
  431. if (error == ERROR_SUCCESS) {
  432. error = RegDeleteValue(clientKey,
  433. ParameterName
  434. );
  435. REGCLOSEKEY(clientKey);
  436. }
  437. DEBUG_LEAVE(error);
  438. return error;
  439. }
  440. DWORD
  441. InternetReadRegistryDword(
  442. IN LPCSTR ParameterName,
  443. OUT LPDWORD ParameterValue
  444. )
  445. /*++
  446. Routine Description:
  447. Reads a single DWORD from a the Internet Client registry key if the platform
  448. is NT/Win95, else reads the value from SYSTEM.INI if we are running on Win32s
  449. Arguments:
  450. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  451. ParameterValue - pointer to place to store retrieved value
  452. Return Value:
  453. DWORD
  454. Success - ERROR_SUCCESS
  455. Failure - ERROR_PATH_NOT_FOUND
  456. --*/
  457. {
  458. DEBUG_ENTER((DBG_REGISTRY,
  459. Dword,
  460. "InternetReadRegistryDword",
  461. "%q, %x",
  462. ParameterName,
  463. ParameterValue
  464. ));
  465. DWORD error = InternetReadRegistryDwordKey(HKEY_CURRENT_USER,
  466. ParameterName,
  467. ParameterValue
  468. );
  469. DEBUG_LEAVE(error);
  470. return error;
  471. }
  472. #ifdef WININET6
  473. DWORD
  474. InternetIDEWriteRegistryDword(
  475. IN LPCSTR ParameterName,
  476. IN DWORD ParameterValue
  477. )
  478. /*++
  479. Routine Description:
  480. Writes a single DWORD from to the Internet Client registry key if the platform
  481. is NT/Win95, otherwise it fails.
  482. Arguments:
  483. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  484. ParameterValue - value to store in registry.
  485. Return Value:
  486. DWORD
  487. Success - ERROR_SUCCESS
  488. Failure - ERROR_PATH_NOT_FOUND
  489. --*/
  490. {
  491. DEBUG_ENTER((DBG_REGISTRY,
  492. Dword,
  493. "InternetIDEWriteRegistryDword",
  494. "%q, %x",
  495. ParameterName,
  496. ParameterValue
  497. ));
  498. DWORD error = GlobalIdentity
  499. ? WriteIDRegDword(ParameterName, ParameterValue)
  500. : InternetWriteRegistryDword(ParameterName, ParameterValue);
  501. DEBUG_LEAVE(error);
  502. return error;
  503. }
  504. DWORD
  505. InternetIDEReadRegistryDword(
  506. IN LPCSTR ParameterName,
  507. OUT LPDWORD ParameterValue
  508. )
  509. /*++
  510. Routine Description:
  511. If we're in an identity-mode, we'll read from the special location.
  512. Otherwise, read from the old location.
  513. Arguments:
  514. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  515. ParameterValue - pointer to place to store retrieved value
  516. Return Value:
  517. DWORD
  518. Success - ERROR_SUCCESS
  519. Failure - ERROR_PATH_NOT_FOUND
  520. --*/
  521. {
  522. DEBUG_ENTER((DBG_REGISTRY,
  523. Dword,
  524. "InternetIDEReadRegistryDword",
  525. "%q, %x",
  526. ParameterName,
  527. ParameterValue
  528. ));
  529. DWORD error = GlobalIdentity
  530. ? ReadIDRegDword(ParameterName, ParameterValue)
  531. : InternetReadRegistryDwordKey(HKEY_CURRENT_USER, ParameterName, ParameterValue);
  532. DEBUG_LEAVE(error);
  533. return error;
  534. }
  535. #endif
  536. DWORD
  537. InternetCacheReadRegistryDword(
  538. IN LPCSTR ParameterName,
  539. OUT LPDWORD ParameterValue
  540. )
  541. /*++
  542. Routine Description:
  543. Reads a single DWORD from a the Internet Client registry key if the platform
  544. is NT/Win95, else reads the value from SYSTEM.INI if we are running on Win32s
  545. Arguments:
  546. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  547. ParameterValue - pointer to place to store retrieved value
  548. Return Value:
  549. DWORD
  550. Success - ERROR_SUCCESS
  551. Failure - ERROR_PATH_NOT_FOUND
  552. --*/
  553. {
  554. DEBUG_ENTER((DBG_REGISTRY,
  555. Dword,
  556. "InternetCacheReadRegistryDword",
  557. "%q, %x",
  558. ParameterName,
  559. ParameterValue
  560. ));
  561. DWORD error = ERROR_SUCCESS;
  562. HKEY clientKey;
  563. error = REGOPENKEYEX(HKEY_CURRENT_USER,
  564. INTERNET_CACHE_SETTINGS_KEY,
  565. 0, // reserved
  566. KEY_QUERY_VALUE,
  567. &clientKey
  568. );
  569. if (error == ERROR_SUCCESS) {
  570. error = ReadRegistryDword(clientKey,
  571. ParameterName,
  572. ParameterValue
  573. );
  574. REGCLOSEKEY(clientKey);
  575. }
  576. DEBUG_LEAVE(error);
  577. return error;
  578. }
  579. DWORD
  580. InternetWriteRegistryDword(
  581. IN LPCSTR ParameterName,
  582. IN DWORD ParameterValue
  583. )
  584. /*++
  585. Routine Description:
  586. Writes a single DWORD from to the Internet Client registry key if the platform
  587. is NT/Win95, otherwise it fails.
  588. Arguments:
  589. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  590. ParameterValue - value to store in registry.
  591. Return Value:
  592. DWORD
  593. Success - ERROR_SUCCESS
  594. Failure - ERROR_PATH_NOT_FOUND
  595. --*/
  596. {
  597. DEBUG_ENTER((DBG_REGISTRY,
  598. Dword,
  599. "InternetWriteRegistryDword",
  600. "%q, %x",
  601. ParameterName,
  602. ParameterValue
  603. ));
  604. DWORD error;
  605. CRefdKey* prk = GetInternetSettingsKey();
  606. if (prk != NULL) {
  607. error = WriteRegistryDword(prk->GetKey(),
  608. ParameterName,
  609. ParameterValue
  610. );
  611. prk->Release();
  612. } else {
  613. error = ERROR_SUCCESS;
  614. }
  615. DEBUG_PRINT(REGISTRY,
  616. INFO,
  617. ("InternetWriteRegistryDword(%q): value = %d (%#x)\n",
  618. ParameterName,
  619. ParameterValue,
  620. ParameterValue
  621. ));
  622. DEBUG_LEAVE(error);
  623. return error;
  624. }
  625. DWORD
  626. InternetReadRegistryString(
  627. IN LPCSTR ParameterName,
  628. OUT LPSTR ParameterValue,
  629. IN OUT LPDWORD ParameterLength
  630. )
  631. /*++
  632. Routine Description:
  633. Reads a string from the Internet Client registry key on NT/Win95, or reads
  634. the corresponding value from SYSTEM.INI on a Win32s platform
  635. Arguments:
  636. ParameterName - name of value parameter within key (e.g. EmailName)
  637. ParameterValue - pointer to string buffer for returned string
  638. ParameterLength - IN: number of bytes in ParameterValue
  639. OUT: number of bytes in string (excluding trailing '\0')
  640. Return Value:
  641. DWORD
  642. Success - ERROR_SUCCESS
  643. Failure - ERROR_PATH_NOT_FOUND
  644. --*/
  645. {
  646. DEBUG_ENTER((DBG_REGISTRY,
  647. Dword,
  648. "InternetReadRegistryString",
  649. "%q, %x, %x [%d]",
  650. ParameterName,
  651. ParameterValue,
  652. ParameterLength,
  653. *ParameterLength
  654. ));
  655. DWORD error = InternetReadRegistryStringKey(HKEY_CURRENT_USER,
  656. ParameterName,
  657. ParameterValue,
  658. ParameterLength
  659. );
  660. DEBUG_LEAVE(error);
  661. return error;
  662. }
  663. //
  664. //DWORD
  665. //InternetWriteRegistryString(
  666. // IN LPCSTR ParameterName,
  667. // IN LPSTR ParameterValue
  668. // )
  669. //
  670. ///*++
  671. //
  672. //Routine Description:
  673. //
  674. // Writes a string to the Internet Client registry key on NT/Win95, or writes
  675. // the corresponding value to SYSTEM.INI on Win32s platform
  676. //
  677. //Arguments:
  678. //
  679. // ParameterName - name of value parameter within key (e.g. EmailName)
  680. //
  681. // ParameterValue - pointer to string to write
  682. //
  683. //Return Value:
  684. //
  685. // DWORD
  686. // Success - ERROR_SUCCESS
  687. //
  688. // Failure -
  689. //
  690. //--*/
  691. //
  692. //{
  693. // DEBUG_ENTER((DBG_REGISTRY,
  694. // Dword,
  695. // "InternetWriteRegistryString",
  696. // "%.40q, %.80q",
  697. // ParameterName,
  698. // ParameterValue
  699. // ));
  700. //
  701. // DWORD error;
  702. //
  703. // if (IsPlatformWin32s()) {
  704. //
  705. // BOOL ok;
  706. //
  707. // ok = WritePrivateProfileString(INTERNET_CLIENT_KEY,
  708. // ParameterName,
  709. // ParameterValue,
  710. // SYSTEM_INI_FILE_NAME
  711. // );
  712. // error = ok ? ERROR_SUCCESS : GetLastError();
  713. // } else {
  714. //
  715. // //
  716. // // BUGBUG - currently, nothing needs to write to registry if NT or Win95
  717. // //
  718. //
  719. // INET_ASSERT(FALSE);
  720. //
  721. // }
  722. //
  723. // DEBUG_LEAVE(error);
  724. //
  725. // return error;
  726. //}
  727. //
  728. //
  729. //DWORD
  730. //InternetReadRegistryBinary(
  731. // IN LPCSTR ParameterName,
  732. // OUT LPBYTE ParameterValue,
  733. // IN OUT LPDWORD ParameterLength
  734. // )
  735. //
  736. ///*++
  737. //
  738. //Routine Description:
  739. //
  740. // Reads a binary value from the Internet Client registry key on NT/Win95, or
  741. // reads the corresponding value from SYSTEM.INI on a Win32s platform
  742. //
  743. //Arguments:
  744. //
  745. // ParameterName - name of value parameter within key (e.g. EmailName)
  746. //
  747. // ParameterValue - pointer to buffer for returned data
  748. //
  749. // ParameterLength - IN: number of bytes in ParameterValue
  750. // OUT: number of bytes in buffer, or required size
  751. //
  752. //Return Value:
  753. //
  754. // DWORD
  755. // Success - ERROR_SUCCESS
  756. //
  757. // Failure - ERROR_PATH_NOT_FOUND
  758. // The parameter wasn't found
  759. //
  760. // ERROR_MORE_DATA
  761. // The buffer isn't large enough
  762. //
  763. //--*/
  764. //
  765. //{
  766. // DEBUG_ENTER((DBG_REGISTRY,
  767. // Dword,
  768. // "InternetReadRegistryBinary",
  769. // "%q, %#x, %#x [%d]",
  770. // ParameterName,
  771. // ParameterValue,
  772. // ParameterLength,
  773. // *ParameterLength
  774. // ));
  775. //
  776. // DWORD error;
  777. //
  778. // error = InternetReadRegistryBinaryKey(HKEY_CURRENT_USER,
  779. // ParameterName,
  780. // ParameterValue,
  781. // ParameterLength
  782. // );
  783. //
  784. // DEBUG_LEAVE(error);
  785. //
  786. // return error;
  787. //}
  788. //
  789. // private functions
  790. //
  791. PUBLIC
  792. DWORD
  793. InternetReadRegistryDwordKey(
  794. IN HKEY ParameterKey,
  795. IN LPCSTR ParameterName,
  796. OUT LPDWORD ParameterValue
  797. )
  798. /*++
  799. Routine Description:
  800. Reads a single DWORD from a the Internet Client registry key if the platform
  801. is NT/Win95, else reads the value from SYSTEM.INI if we are running on Win32s.
  802. Does not modify the *ParameterValue if the registry variable cannot be read
  803. Arguments:
  804. ParameterKey - root registry key (e.g. HKEY_CURRENT_USER)
  805. ParameterName - name of the parameter to retrieve (e.g. AccessType)
  806. ParameterValue - pointer to place to store retrieved value
  807. Return Value:
  808. DWORD
  809. Success - ERROR_SUCCESS
  810. Failure - ERROR_PATH_NOT_FOUND
  811. --*/
  812. {
  813. DEBUG_ENTER((DBG_REGISTRY,
  814. Dword,
  815. "InternetReadRegistryDwordKey",
  816. "%s, %q, %x",
  817. (ParameterKey == HKEY_LOCAL_MACHINE)
  818. ? "HKEY_LOCAL_MACHINE"
  819. : (ParameterKey == HKEY_CURRENT_USER)
  820. ? "HKEY_CURRENT_USER"
  821. : "???",
  822. ParameterName,
  823. ParameterValue
  824. ));
  825. DWORD error = ERROR_SUCCESS;
  826. CRefdKey* prk = GetInternetSettingsKey();
  827. BOOL bOpenedKey = FALSE;
  828. HKEY hkSettings = NULL;
  829. if (ParameterKey != HKEY_CURRENT_USER) {
  830. error = REGOPENKEYEX(ParameterKey,
  831. INTERNET_SETTINGS_KEY,
  832. 0, // reserved
  833. KEY_QUERY_VALUE,
  834. &hkSettings
  835. );
  836. if (error == ERROR_SUCCESS) {
  837. bOpenedKey = TRUE;
  838. }
  839. } else if (prk) {
  840. hkSettings = prk->GetKey();
  841. } else {
  842. error = ERROR_PATH_NOT_FOUND;
  843. }
  844. if (error == ERROR_SUCCESS) {
  845. error = ReadRegistryDword(hkSettings,
  846. ParameterName,
  847. ParameterValue
  848. );
  849. }
  850. if (bOpenedKey) {
  851. REGCLOSEKEY(hkSettings);
  852. }
  853. if (prk) {
  854. prk->Release();
  855. }
  856. DEBUG_PRINT(REGISTRY,
  857. INFO,
  858. ("InternetReadRegistryDwordKey(%q): value = %d (%#x)\n",
  859. ParameterName,
  860. *ParameterValue,
  861. *ParameterValue
  862. ));
  863. DEBUG_LEAVE(error);
  864. return error;
  865. }
  866. PRIVATE
  867. DWORD
  868. InternetReadRegistryStringKey(
  869. IN HKEY ParameterKey,
  870. IN LPCSTR ParameterName,
  871. OUT LPSTR ParameterValue,
  872. IN OUT LPDWORD ParameterLength
  873. )
  874. /*++
  875. Routine Description:
  876. Reads a string from the Internet Client registry key on NT/Win95, or reads
  877. the corresponding value from SYSTEM.INI on a Win32s platform
  878. Arguments:
  879. ParameterKey - root registry key (e.g. HKEY_LOCAL_MACHINE)
  880. ParameterName - name of value parameter within key (e.g. EmailName)
  881. ParameterValue - pointer to string buffer for returned string
  882. ParameterLength - IN: number of bytes in ParameterValue
  883. OUT: number of bytes in string (excluding trailing '\0')
  884. Return Value:
  885. DWORD
  886. Success - ERROR_SUCCESS
  887. Failure - ERROR_PATH_NOT_FOUND
  888. --*/
  889. {
  890. DEBUG_ENTER((DBG_REGISTRY,
  891. Dword,
  892. "InternetReadRegistryStringKey",
  893. "%s (%x), %q, %x, %x [%d]",
  894. (ParameterKey == HKEY_LOCAL_MACHINE)
  895. ? "HKEY_LOCAL_MACHINE"
  896. : (ParameterKey == HKEY_CURRENT_USER)
  897. ? "HKEY_CURRENT_USER"
  898. : "???",
  899. ParameterKey,
  900. ParameterName,
  901. ParameterValue,
  902. ParameterLength,
  903. *ParameterLength
  904. ));
  905. //
  906. // zero-terminate the string
  907. //
  908. if (*ParameterLength > 0) {
  909. *ParameterValue = '\0';
  910. }
  911. DWORD error = ERROR_SUCCESS;
  912. CRefdKey* prk = GetInternetSettingsKey();
  913. BOOL bOpenedKey = FALSE;
  914. HKEY hkSettings = NULL;
  915. if (ParameterKey != HKEY_CURRENT_USER) {
  916. error = REGOPENKEYEX(ParameterKey,
  917. INTERNET_SETTINGS_KEY,
  918. 0, // reserved
  919. KEY_QUERY_VALUE,
  920. &hkSettings
  921. );
  922. if (error == ERROR_SUCCESS) {
  923. bOpenedKey = TRUE;
  924. }
  925. } else if (prk) {
  926. hkSettings = prk->GetKey();
  927. } else {
  928. error = ERROR_PATH_NOT_FOUND;
  929. }
  930. if (error == ERROR_SUCCESS) {
  931. error = ReadRegistryOemString(hkSettings,
  932. ParameterName,
  933. ParameterValue,
  934. ParameterLength
  935. );
  936. }
  937. if (bOpenedKey) {
  938. REGCLOSEKEY(hkSettings);
  939. }
  940. if (prk) {
  941. prk->Release();
  942. }
  943. DEBUG_PRINT(REGISTRY,
  944. INFO,
  945. ("InternetReadRegistryStringKey(%q): value = %q\n",
  946. ParameterName,
  947. ParameterValue
  948. ));
  949. DEBUG_LEAVE(error);
  950. return error;
  951. }
  952. //
  953. //PRIVATE
  954. //DWORD
  955. //InternetReadRegistryBinaryKey(
  956. // IN HKEY ParameterKey,
  957. // IN LPCSTR ParameterName,
  958. // OUT LPBYTE ParameterValue,
  959. // IN OUT LPDWORD ParameterLength
  960. // )
  961. //
  962. ///*++
  963. //
  964. //Routine Description:
  965. //
  966. // Reads a binary value from the Internet Client registry key on NT/Win95, or
  967. // reads the corresponding value from SYSTEM.INI on a Win32s platform
  968. //
  969. //Arguments:
  970. //
  971. // ParameterKey - root registry key (e.g. HKEY_LOCAL_MACHINE)
  972. //
  973. // ParameterName - name of value parameter within key (e.g. EmailName)
  974. //
  975. // ParameterValue - pointer to buffer for returned data
  976. //
  977. // ParameterLength - IN: number of bytes in ParameterValue
  978. // OUT: number of bytes in buffer, or required size
  979. //
  980. //Return Value:
  981. //
  982. // DWORD
  983. // Success - ERROR_SUCCESS
  984. //
  985. // Failure - ERROR_PATH_NOT_FOUND
  986. // The parameter wasn't found
  987. //
  988. // ERROR_MORE_DATA
  989. // The buffer isn't large enough
  990. //
  991. //--*/
  992. //
  993. //{
  994. // DEBUG_ENTER((DBG_REGISTRY,
  995. // Dword,
  996. // "InternetReadRegistryBinaryKey",
  997. // "%s (%x), %q, %#x, %#x [%d]",
  998. // (ParameterKey == HKEY_LOCAL_MACHINE)
  999. // ? "HKEY_LOCAL_MACHINE"
  1000. // : (ParameterKey == HKEY_CURRENT_USER)
  1001. // ? "HKEY_CURRENT_USER"
  1002. // : "???",
  1003. // ParameterKey,
  1004. // ParameterName,
  1005. // ParameterValue,
  1006. // ParameterLength,
  1007. // *ParameterLength
  1008. // ));
  1009. //
  1010. // DWORD error;
  1011. // HKEY clientKey;
  1012. //
  1013. // //
  1014. // // open the registry key containing the Internet client values (this is
  1015. // // in the same place on NT and Win95)
  1016. // //
  1017. //
  1018. // error = REGOPENKEYEX(ParameterKey,
  1019. // INTERNET_SETTINGS_KEY,
  1020. // 0, // reserved
  1021. // KEY_QUERY_VALUE,
  1022. // &clientKey
  1023. // );
  1024. //
  1025. // if (error == ERROR_SUCCESS) {
  1026. //
  1027. // DWORD valueType;
  1028. //
  1029. // error = RegQueryValueEx(clientKey,
  1030. // ParameterName,
  1031. // NULL, // reserved
  1032. // &valueType,
  1033. // ParameterValue,
  1034. // ParameterLength
  1035. // );
  1036. // REGCLOSEKEY(clientKey);
  1037. // }
  1038. //
  1039. // DEBUG_PRINT(REGISTRY,
  1040. // INFO,
  1041. // ("InternetReadRegistryBinaryKey(%q): length = %d\n",
  1042. // ParameterName,
  1043. // *ParameterLength
  1044. // ));
  1045. //
  1046. // DEBUG_LEAVE(error);
  1047. //
  1048. // return error;
  1049. //}
  1050. //
  1051. //
  1052. //PRIVATE
  1053. //DWORD
  1054. //InternetGetPrivateProfileString(
  1055. // IN LPSTR IniFileName,
  1056. // IN LPSTR SectionName,
  1057. // IN LPCSTR ParameterName,
  1058. // OUT LPSTR ParameterValue,
  1059. // IN OUT LPDWORD ParameterLength
  1060. // )
  1061. //
  1062. ///*++
  1063. //
  1064. //Routine Description:
  1065. //
  1066. // Reads an string out of an INI file. Mainly just for Win32s
  1067. //
  1068. //Arguments:
  1069. //
  1070. // IniFileName - name of INI file to read
  1071. //
  1072. // SectionName - name of section in INI file to read
  1073. //
  1074. // ParameterName - name of entry in section to read
  1075. //
  1076. // ParameterValue - returned string
  1077. //
  1078. // ParameterLength - IN: Length of ParameterValue
  1079. // OUT: Number of characters in ParameterValue, excluding
  1080. // terminating NUL
  1081. //
  1082. //Return Value:
  1083. //
  1084. // DWORD
  1085. // Success - ERROR_SUCCESS
  1086. //
  1087. // Failure - ERROR_PATH_NOT_FOUND
  1088. // ERROR_FILE_NOT_FOUND
  1089. //
  1090. //--*/
  1091. //
  1092. //{
  1093. // DWORD error;
  1094. // DWORD nChars;
  1095. //
  1096. // nChars = GetPrivateProfileString(SectionName,
  1097. // ParameterName,
  1098. // "", // lpszDefault
  1099. // ParameterValue,
  1100. // *ParameterLength,
  1101. // IniFileName
  1102. // );
  1103. // if (nChars > 0) {
  1104. // *ParameterLength = nChars;
  1105. // error = ERROR_SUCCESS;
  1106. // } else {
  1107. // error = ERROR_PATH_NOT_FOUND;
  1108. // }
  1109. // return error;
  1110. //}
  1111. PRIVATE
  1112. DWORD
  1113. ReadRegistryOemString(
  1114. IN HKEY Key,
  1115. IN LPCSTR ParameterName,
  1116. OUT LPSTR String,
  1117. IN OUT LPDWORD Length
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. Reads a string out of the registry as an OEM string
  1122. Arguments:
  1123. Key - open registry key where to read value from
  1124. ParameterName - name of registry value to read
  1125. String - place to put it
  1126. Length - IN: length of String buffer in characters
  1127. OUT: length of String in characters, as if returned from
  1128. strlen()
  1129. Return Value:
  1130. DWORD
  1131. Success - ERROR_SUCCESS
  1132. Failure - ERROR_FILE_NOT_FOUND
  1133. Couldn't find the parameter
  1134. ERROR_PATH_NOT_FOUND
  1135. Couldn't find the parameter
  1136. ERROR_INTERNET_BAD_REGISTRY_PARAMETER
  1137. Inconsistent registry contents
  1138. --*/
  1139. {
  1140. DEBUG_ENTER((DBG_REGISTRY,
  1141. Dword,
  1142. "ReadRegistryOemString",
  1143. "%#x, %q, %#x, %#x [%d]",
  1144. Key,
  1145. ParameterName,
  1146. String,
  1147. Length,
  1148. *Length
  1149. ));
  1150. LONG error;
  1151. DWORD valueType;
  1152. LPSTR str;
  1153. DWORD valueLength;
  1154. //
  1155. // first, get the length of the string
  1156. //
  1157. valueLength = *Length;
  1158. error = RegQueryValueEx(Key,
  1159. ParameterName,
  1160. NULL, // reserved
  1161. &valueType,
  1162. (LPBYTE)String,
  1163. &valueLength
  1164. );
  1165. if (error != ERROR_SUCCESS) {
  1166. goto quit;
  1167. }
  1168. //
  1169. // we only support REG_SZ (single string) values in this function
  1170. //
  1171. if (valueType != REG_SZ) {
  1172. error = ERROR_INTERNET_BAD_REGISTRY_PARAMETER;
  1173. goto quit;
  1174. }
  1175. //
  1176. // if 1 or 0 chars returned then the string is empty
  1177. //
  1178. if (valueLength <= sizeof(char)) {
  1179. error = ERROR_PATH_NOT_FOUND;
  1180. goto quit;
  1181. }
  1182. //
  1183. // convert the ANSI string to OEM character set in place. According to Win
  1184. // help, this always succeeds
  1185. //
  1186. CharToOem(String, String);
  1187. //
  1188. // return the length as if returned from strlen() (i.e. drop the '\0')
  1189. //
  1190. *Length = valueLength - sizeof(char);
  1191. DEBUG_PRINT(REGISTRY,
  1192. INFO,
  1193. ("ReadRegistryOemString(%q) returning %q (%d chars)\n",
  1194. ParameterName,
  1195. String,
  1196. *Length
  1197. ));
  1198. quit:
  1199. DEBUG_LEAVE(error);
  1200. return error;
  1201. }
  1202. DWORD
  1203. ReadRegistryDword(
  1204. IN HKEY Key,
  1205. IN LPCSTR ParameterName,
  1206. OUT LPDWORD ParameterValue
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. Reads a DWORD parameter from the registry
  1211. Won't modify *ParameterValue unless a valid value is read from the registry
  1212. Arguments:
  1213. Key - handle of open registry key where parameter resides
  1214. ParameterName - name of DWORD parameter to read
  1215. ParameterValue - returned DWORD parameter read from registry
  1216. Return Value:
  1217. DWORD
  1218. Success - ERROR_SUCCESS
  1219. Failure - ERROR_PATH_NOT_FOUND
  1220. One of the following occurred:
  1221. - the parameter is not in the specified registry key
  1222. - the parameter is the wrong type
  1223. - the parameter is the wrong size
  1224. --*/
  1225. {
  1226. DEBUG_ENTER((DBG_REGISTRY,
  1227. Dword,
  1228. "ReadRegistryDword",
  1229. "%x, %q, %x",
  1230. Key,
  1231. ParameterName,
  1232. ParameterValue
  1233. ));
  1234. DWORD error;
  1235. DWORD valueLength;
  1236. DWORD valueType;
  1237. DWORD value;
  1238. valueLength = sizeof(*ParameterValue);
  1239. error = (DWORD)RegQueryValueEx(Key,
  1240. ParameterName,
  1241. NULL, // reserved
  1242. &valueType,
  1243. (LPBYTE)&value,
  1244. &valueLength
  1245. );
  1246. //
  1247. // if the size or type aren't correct then return an error, else only if
  1248. // success was returned do we modify *ParameterValue
  1249. //
  1250. if (error == ERROR_SUCCESS) {
  1251. if (((valueType != REG_DWORD)
  1252. && (valueType != REG_BINARY))
  1253. || (valueLength != sizeof(DWORD))) {
  1254. DEBUG_PRINT(REGISTRY,
  1255. ERROR,
  1256. ("valueType = %d, valueLength = %d\n",
  1257. valueType,
  1258. valueLength
  1259. ));
  1260. error = ERROR_PATH_NOT_FOUND;
  1261. } else {
  1262. *ParameterValue = value;
  1263. }
  1264. }
  1265. DEBUG_LEAVE(error);
  1266. return error;
  1267. }
  1268. PRIVATE
  1269. DWORD
  1270. WriteRegistryDword(
  1271. IN HKEY Key,
  1272. IN LPCSTR ParameterName,
  1273. IN DWORD ParameterValue
  1274. )
  1275. /*++
  1276. Routine Description:
  1277. Writes a DWORD parameter from the registry
  1278. Will write ParameterValue to the key.
  1279. Arguments:
  1280. Key - handle of open registry key where parameter resides
  1281. ParameterName - name of DWORD parameter to write
  1282. ParameterValue - DWORD parameter to write from registry
  1283. Return Value:
  1284. DWORD
  1285. Success - ERROR_SUCCESS
  1286. Failure - ERROR_PATH_NOT_FOUND
  1287. One of the following occurred:
  1288. - the parameter is not in the specified registry key
  1289. - the parameter is the wrong type
  1290. - the parameter is the wrong size
  1291. --*/
  1292. {
  1293. DEBUG_ENTER((DBG_REGISTRY,
  1294. Dword,
  1295. "WriteRegistryDword",
  1296. "%x, %q, %x",
  1297. Key,
  1298. ParameterName,
  1299. ParameterValue
  1300. ));
  1301. DWORD error;
  1302. DWORD valueLength;
  1303. DWORD valueType;
  1304. DWORD value;
  1305. valueLength = sizeof(ParameterValue);
  1306. valueType = REG_DWORD;
  1307. value = ParameterValue;
  1308. error = (DWORD)RegSetValueEx(Key,
  1309. ParameterName,
  1310. NULL, // reserved
  1311. valueType,
  1312. (LPBYTE)&value,
  1313. valueLength
  1314. );
  1315. DEBUG_PRINT(REGISTRY,
  1316. INFO,
  1317. ("added: valueType = %d, valueLength = %d\n",
  1318. valueType,
  1319. valueLength
  1320. ));
  1321. DEBUG_LEAVE(error);
  1322. return error;
  1323. }
  1324. BOOL
  1325. GetFileExtensionFromMimeType(
  1326. LPCSTR lpszMimeType,
  1327. DWORD dwMimeLen,
  1328. LPSTR lpszFileExtension,
  1329. LPDWORD lpdwExtLen
  1330. )
  1331. {
  1332. HKEY hKey = NULL;
  1333. LPSTR lpszMimeKey = (LPSTR)_alloca(sizeof(MIME_TO_FILE_EXTENSION_KEY)+dwMimeLen);
  1334. memcpy(lpszMimeKey, MIME_TO_FILE_EXTENSION_KEY,
  1335. sizeof(MIME_TO_FILE_EXTENSION_KEY)-1);
  1336. memcpy(lpszMimeKey + sizeof(MIME_TO_FILE_EXTENSION_KEY) - 1, lpszMimeType,
  1337. dwMimeLen);
  1338. lpszMimeKey[sizeof(MIME_TO_FILE_EXTENSION_KEY) + dwMimeLen - 1] = '\0';
  1339. if (REGOPENKEYEX(HKEY_CLASSES_ROOT,
  1340. lpszMimeKey,
  1341. 0,
  1342. KEY_QUERY_VALUE,
  1343. &hKey)==ERROR_SUCCESS)
  1344. {
  1345. DWORD dwType, dwError = RegQueryValueEx(hKey,
  1346. EXTENSION_VALUE,
  1347. NULL,
  1348. &dwType,
  1349. (LPBYTE)lpszFileExtension,
  1350. lpdwExtLen);
  1351. REGCLOSEKEY(hKey);
  1352. return (dwError==ERROR_SUCCESS);
  1353. }
  1354. return FALSE;
  1355. }
  1356. DWORD
  1357. CreateMimeExclusionTableForCache()
  1358. {
  1359. INET_ASSERT(lpvrgszMimeExclusionTable == NULL);
  1360. INET_ASSERT(vszMimeExclusionList == NULL);
  1361. return (CreateTableFromRegistryList("MimeExclusionListForCache",
  1362. &vszMimeExclusionList,
  1363. &lpvrgszMimeExclusionTable,
  1364. &lpvrgdwMimeExclusionTableOfSizes,
  1365. &vdwMimeExclusionTableCount));
  1366. }
  1367. VOID
  1368. DestroyMimeExclusionTableForCache()
  1369. {
  1370. if (lpvrgszMimeExclusionTable) {
  1371. INET_ASSERT(vszMimeExclusionList != NULL);
  1372. FREE_MEMORY(lpvrgszMimeExclusionTable);
  1373. FREE_MEMORY(lpvrgdwMimeExclusionTableOfSizes);
  1374. FREE_MEMORY(vszMimeExclusionList);
  1375. lpvrgszMimeExclusionTable = NULL;
  1376. vszMimeExclusionList = NULL;
  1377. vdwMimeExclusionTableCount = 0;
  1378. }
  1379. }
  1380. DWORD
  1381. CreateHeaderExclusionTableForCache()
  1382. {
  1383. INET_ASSERT(lpvrgszHeaderExclusionTable == NULL);
  1384. INET_ASSERT(vszHeaderExclusionList == NULL);
  1385. return (CreateTableFromRegistryList("HeaderExclusionListForCache",
  1386. &vszHeaderExclusionList,
  1387. &lpvrgszHeaderExclusionTable,
  1388. NULL,
  1389. &vdwHeaderExclusionTableCount));
  1390. }
  1391. VOID
  1392. DestroyHeaderExclusionTableForCache()
  1393. {
  1394. if (lpvrgszHeaderExclusionTable) {
  1395. INET_ASSERT(vszHeaderExclusionList != NULL);
  1396. FREE_MEMORY(lpvrgszHeaderExclusionTable);
  1397. FREE_MEMORY(vszHeaderExclusionList);
  1398. lpvrgszHeaderExclusionTable = NULL;
  1399. vszHeaderExclusionList = NULL;
  1400. vdwHeaderExclusionTableCount = 0;
  1401. }
  1402. }
  1403. PRIVATE
  1404. DWORD
  1405. CreateTableFromRegistryList(
  1406. IN LPSTR lpszParameter, // wininet registry parameter
  1407. OUT LPSTR *lplpszList, // Delimited List
  1408. OUT LPSTR **lplprgszTable, // Pointer table pointing into the list
  1409. OUT DWORD **lplpdwTableSizes, // Pointer to table containing sizes of string elements
  1410. OUT LPDWORD lpdwCount // count of elements in the table
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Creates argv array from registry string
  1415. Arguments:
  1416. lpszParameter - wininet registry parameter
  1417. lplpszList - delimited List
  1418. lplprgszTable - pointer table pointing into the list
  1419. lplpdwTableSizes - pointer to table containing sizes of string elements
  1420. lpdwCount - count of elements in the table
  1421. Return Value:
  1422. DWORD
  1423. Success - ERROR_SUCCESS
  1424. Failure - ERROR_NOT_ENOUGH_MEMORY
  1425. ERROR_INVALID_PARAMETER
  1426. --*/
  1427. {
  1428. INET_ASSERT(lplpszList != NULL);
  1429. INET_ASSERT(lplprgszTable != NULL);
  1430. DWORD dwLen = 0;
  1431. DWORD error;
  1432. //
  1433. // let us find out the length of this string
  1434. //
  1435. error = InternetReadRegistryString(lpszParameter, NULL, &dwLen);
  1436. if ((error != ERROR_SUCCESS) && (error != ERROR_MORE_DATA)) {
  1437. return error;
  1438. }
  1439. dwLen += 2; // for good measure
  1440. if (!(*lplpszList = (LPSTR)ALLOCATE_MEMORY(LPTR, dwLen))) {
  1441. return ERROR_NOT_ENOUGH_MEMORY;
  1442. }
  1443. error = InternetReadRegistryString(lpszParameter, *lplpszList, &dwLen);
  1444. //
  1445. // if it fails now, we need to bailout
  1446. //
  1447. if (error != ERROR_SUCCESS) {
  1448. goto bailout;
  1449. }
  1450. //
  1451. // now let us see how many elements are there in this list
  1452. //
  1453. error = CreateStringArrayFromDelimitedList(*lplpszList,
  1454. vszDelimiters,
  1455. NULL,
  1456. lpdwCount
  1457. );
  1458. if (!*lpdwCount) {
  1459. error = ERROR_INVALID_PARAMETER;
  1460. goto bailout;
  1461. }
  1462. //
  1463. // let us allocate an array of pointers
  1464. //
  1465. if (!(*lplprgszTable = (LPSTR *)ALLOCATE_MEMORY(LPTR, *lpdwCount * sizeof(LPSTR)))) {
  1466. error = ERROR_NOT_ENOUGH_MEMORY;
  1467. goto bailout;
  1468. }
  1469. error = CreateStringArrayFromDelimitedList(*lplpszList,
  1470. vszDelimiters,
  1471. *lplprgszTable,
  1472. lpdwCount
  1473. );
  1474. INET_ASSERT(*lpdwCount);
  1475. if ((lplpdwTableSizes == NULL) || (error != ERROR_SUCCESS)) {
  1476. goto bailout;
  1477. }
  1478. *lplpdwTableSizes = (LPDWORD)ALLOCATE_MEMORY(LPTR, (sizeof(DWORD)*(*lpdwCount)));
  1479. if (*lplpdwTableSizes == NULL) {
  1480. error = ERROR_NOT_ENOUGH_MEMORY;
  1481. goto bailout;
  1482. }
  1483. DWORD i;
  1484. for (i = 0; i < *lpdwCount; i++) {
  1485. INET_ASSERT((*lplprgszTable)[i]);
  1486. (*lplpdwTableSizes)[i] = lstrlen((*lplprgszTable)[i]);
  1487. }
  1488. bailout:
  1489. if (error != ERROR_SUCCESS) {
  1490. if (*lplpszList) {
  1491. FREE_MEMORY(*lplpszList);
  1492. *lplpszList = NULL;
  1493. }
  1494. if (*lplprgszTable) {
  1495. FREE_MEMORY(*lplprgszTable);
  1496. *lplprgszTable = NULL;
  1497. }
  1498. }
  1499. return error;
  1500. }
  1501. PRIVATE
  1502. DWORD
  1503. CreateStringArrayFromDelimitedList(
  1504. IN LPSTR lpszDelimitedList,
  1505. IN LPSTR lpszDelimiters,
  1506. IN LPSTR *lprgszStringArray,
  1507. OUT LPDWORD lpdwCount
  1508. )
  1509. {
  1510. LPSTR lpStart, lpEnd, lpTmp;
  1511. DWORD dwError = ERROR_INVALID_PARAMETER;
  1512. *lpdwCount = 0;
  1513. lpStart = lpszDelimitedList;
  1514. lpEnd = lpStart + strlen(lpszDelimitedList); // points to null
  1515. // strip out the trailing spaces
  1516. for(;(lpStart<lpEnd);--lpEnd) {
  1517. int c;
  1518. c = (int)*(lpEnd-1);
  1519. if (!isspace(c)) {
  1520. *lpEnd = '\0';
  1521. break;
  1522. }
  1523. }
  1524. // bailout if this is an empty string
  1525. if (lpStart == lpEnd) {
  1526. goto done;
  1527. }
  1528. dwError = ERROR_SUCCESS;
  1529. for (lpTmp = lpStart;(lpTmp && (lpEnd > lpStart)); lpStart = lpTmp+1) {
  1530. int c;
  1531. lpTmp = lpStart;
  1532. c = (int)*lpStart;
  1533. if (isspace(c)) {
  1534. continue;
  1535. }
  1536. // when we come here there is a non space character
  1537. INET_ASSERT(!isspace(*lpStart));
  1538. lpTmp = strpbrk(lpStart, lpszDelimiters);
  1539. if (lprgszStringArray) {
  1540. if (lpTmp) {
  1541. *lpTmp = 0; // create a string out of it
  1542. }
  1543. // plug the start pointer into the array
  1544. lprgszStringArray[*lpdwCount] = lpStart;
  1545. }
  1546. ++*lpdwCount;
  1547. }
  1548. done:
  1549. return (dwError);
  1550. }
  1551. #if INET_DEBUG
  1552. typedef struct {
  1553. LIST_ENTRY entry;
  1554. HKEY hkey;
  1555. char * file;
  1556. int line;
  1557. char name[1];
  1558. } DBGREGKEYINFO;
  1559. SERIALIZED_LIST DbgRegKeyList;
  1560. VOID DbgRegKey_Init(VOID) {
  1561. InitializeSerializedList(&DbgRegKeyList);
  1562. }
  1563. VOID DbgRegKey_Terminate(VOID) {
  1564. TerminateSerializedList(&DbgRegKeyList);
  1565. }
  1566. void regkey_add(const char * name, HKEY hkey, char * file, int line) {
  1567. if (!name) {
  1568. name = "";
  1569. }
  1570. int len = lstrlen(name);
  1571. DBGREGKEYINFO * p = (DBGREGKEYINFO *)ALLOCATE_FIXED_MEMORY(sizeof(DBGREGKEYINFO) + len);
  1572. if (p) {
  1573. //dprintf("Wininet.DbgRegKey: adding %q\n", name);
  1574. memcpy(p->name, name, len + 1);
  1575. p->line = line;
  1576. p->file = file;
  1577. p->hkey = hkey;
  1578. InsertAtHeadOfSerializedList(&DbgRegKeyList, &p->entry);
  1579. }
  1580. }
  1581. void regkey_remove(HKEY hkey) {
  1582. LockSerializedList(&DbgRegKeyList);
  1583. DBGREGKEYINFO * p = (DBGREGKEYINFO *)HeadOfSerializedList(&DbgRegKeyList);
  1584. while (p != (DBGREGKEYINFO *)SlSelf(&DbgRegKeyList)) {
  1585. if (p->hkey == hkey) {
  1586. RemoveFromSerializedList(&DbgRegKeyList, (PLIST_ENTRY)p);
  1587. //dprintf("Wininet.DbgRegKey: removing %q\n", p->name);
  1588. FREE_MEMORY(p);
  1589. break;
  1590. }
  1591. p = (DBGREGKEYINFO *)p->entry.Flink;
  1592. }
  1593. UnlockSerializedList(&DbgRegKeyList);
  1594. }
  1595. char * regkey_name(HKEY hkey, const char * subname) {
  1596. switch ((INT_PTR)hkey) {
  1597. case (INT_PTR)HKEY_CLASSES_ROOT:
  1598. return NEW_STRING("HKEY_CLASSES_ROOT");
  1599. case (INT_PTR)HKEY_CURRENT_USER:
  1600. return NEW_STRING("HKEY_CURRENT_USER");
  1601. case (INT_PTR)HKEY_LOCAL_MACHINE:
  1602. return NEW_STRING("HKEY_LOCAL_MACHINE");
  1603. case (INT_PTR)HKEY_USERS:
  1604. return NEW_STRING("HKEY_USERS");
  1605. case (INT_PTR)HKEY_PERFORMANCE_DATA:
  1606. return NEW_STRING("HKEY_PERFORMANCE_DATA");
  1607. case (INT_PTR)HKEY_CURRENT_CONFIG:
  1608. return NEW_STRING("HKEY_CURRENT_CONFIG");
  1609. case (INT_PTR)HKEY_DYN_DATA:
  1610. return NEW_STRING("HKEY_DYN_DATA");
  1611. }
  1612. char * name = NULL;
  1613. LockSerializedList(&DbgRegKeyList);
  1614. DBGREGKEYINFO * p = (DBGREGKEYINFO *)HeadOfSerializedList(&DbgRegKeyList);
  1615. while (p != (DBGREGKEYINFO *)SlSelf(&DbgRegKeyList)) {
  1616. if (p->hkey == hkey) {
  1617. int len = lstrlen(p->name);
  1618. int slen = lstrlen(subname);
  1619. name = (char *)ALLOCATE_FIXED_MEMORY(len + 1 + slen + 1);
  1620. if (name) {
  1621. memcpy(name, p->name, len);
  1622. name[len] = '\\';
  1623. memcpy(name + len + 1, subname, slen + 1);
  1624. }
  1625. break;
  1626. }
  1627. p = (DBGREGKEYINFO *)p->entry.Flink;
  1628. }
  1629. UnlockSerializedList(&DbgRegKeyList);
  1630. return name;
  1631. }
  1632. void regkey_freename(char * name) {
  1633. if (name) {
  1634. FREE_MEMORY(name);
  1635. }
  1636. }
  1637. LONG
  1638. DbgRegOpenKey(
  1639. IN HKEY hKey,
  1640. IN LPCTSTR lpszSubKey,
  1641. OUT PHKEY phkResult,
  1642. char * file,
  1643. int line
  1644. )
  1645. {
  1646. char * keyname = regkey_name(hKey, lpszSubKey);
  1647. LONG rc = RegOpenKey(hKey, lpszSubKey, phkResult);
  1648. if (rc == 0) {
  1649. regkey_add(keyname, *phkResult, file, line);
  1650. }
  1651. regkey_freename(keyname);
  1652. return rc;
  1653. }
  1654. LONG
  1655. DbgRegOpenKeyEx(
  1656. IN HKEY hKey,
  1657. IN LPCSTR lpSubKey,
  1658. IN DWORD ulOptions,
  1659. IN REGSAM samDesired,
  1660. OUT PHKEY phkResult,
  1661. char * file,
  1662. int line
  1663. )
  1664. {
  1665. char * keyname = regkey_name(hKey, lpSubKey);
  1666. LONG rc = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  1667. if (rc == 0) {
  1668. regkey_add(keyname, *phkResult, file, line);
  1669. }
  1670. regkey_freename(keyname);
  1671. return rc;
  1672. }
  1673. LONG
  1674. DbgRegCreateKeyEx(
  1675. IN HKEY hKey,
  1676. IN LPCSTR lpSubKey,
  1677. IN DWORD Reserved,
  1678. IN LPSTR lpClass,
  1679. IN DWORD dwOptions,
  1680. IN REGSAM samDesired,
  1681. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1682. OUT PHKEY phkResult,
  1683. OUT LPDWORD lpdwDisposition,
  1684. char * file,
  1685. int line
  1686. )
  1687. {
  1688. char * keyname = regkey_name(hKey, lpSubKey);
  1689. LONG rc = RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  1690. if (rc == 0) {
  1691. regkey_add(keyname, *phkResult, file, line);
  1692. }
  1693. regkey_freename(keyname);
  1694. return rc;
  1695. }
  1696. LONG
  1697. DbgRegCloseKey(
  1698. IN HKEY hKey
  1699. )
  1700. {
  1701. LONG rc = RegCloseKey(hKey);
  1702. if (rc == 0) {
  1703. regkey_remove(hKey);
  1704. }
  1705. return rc;
  1706. }
  1707. #endif // INET_DEBUG