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.

990 lines
22 KiB

  1. //============================================================================
  2. // Copyright (c) 1996, Microsoft Corporation
  3. //
  4. // File: setup.c
  5. //
  6. // History:
  7. // 06/24/96 Abolade Gbadegesin Created.
  8. //
  9. // Implements API functions used by IP and IPX to read installation information
  10. // stored under HKLM\Software\Microsoft\Router.
  11. //
  12. // The API functions are presented first, followed by private functions
  13. // in alphabetical order.
  14. //============================================================================
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <rtutils.h>
  20. #include <mprapi.h>
  21. //
  22. // Constant strings used to access the registry:
  23. //
  24. extern const WCHAR c_szProtocolId[];
  25. extern const WCHAR c_szRouter[];
  26. extern const WCHAR c_szRouterManagers[];
  27. const WCHAR c_szDLLName[] = L"DLLName";
  28. const TCHAR c_szCurrentVersion[] = L"CurrentVersion";
  29. const WCHAR c_szMicrosoft[] = L"Microsoft";
  30. const WCHAR c_szSoftware[] = L"Software";
  31. #ifdef KSL_IPINIP
  32. const WCHAR c_szIpInIp[] = L"IpInIp";
  33. #endif
  34. //
  35. // Memory management macros:
  36. //
  37. #define Malloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
  38. #define ReAlloc(p,s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
  39. #define Free(p) HeapFree(GetProcessHeap(), 0, (p))
  40. #define Free0(p) ((p) ? Free(p) : TRUE)
  41. DWORD
  42. QueryRmSoftwareKey(
  43. IN HKEY hkeyMachine,
  44. IN DWORD dwTransportId,
  45. OUT HKEY* phkrm,
  46. OUT LPWSTR* lplpwsRm
  47. );
  48. #ifdef KSL_IPINIP
  49. DWORD
  50. QueryIpInIpSoftwareKey(
  51. IN HKEY hkeyMachine,
  52. OUT HKEY* phkIpIpRead,
  53. OUT HKEY* phkIpIpWrite,
  54. OUT PDWORD pdwNumValues,
  55. OUT PDWORD pdwMaxValueNameLen,
  56. OUT PDWORD pdwMaxValueLen
  57. );
  58. #endif
  59. //----------------------------------------------------------------------------
  60. // Function: MprSetupProtocolEnum
  61. //
  62. // Enumerates the protocols installed for transport 'dwTransportId'.
  63. //
  64. // The information is loaded from HKLM\Software\Microsoft\Router,
  65. // where subkeys exist for each router-manager under the 'RouterManagers' key.
  66. // Each router-manager subkey has subkeys containing information
  67. // about that router-manager's routing-protocols.
  68. //
  69. // This API reads a subset of that information, so that router-managers
  70. // can map protocol-IDs to DLL names when loading routing-protocols.
  71. //----------------------------------------------------------------------------
  72. DWORD APIENTRY
  73. MprSetupProtocolEnum(
  74. IN DWORD dwTransportId,
  75. OUT LPBYTE* lplpBuffer, // MPR_PROTOCOL_0
  76. OUT LPDWORD lpdwEntriesRead
  77. ) {
  78. HKEY hkrm;
  79. WCHAR* lpwsRm = NULL;
  80. DWORD dwErr, dwItemCount;
  81. MPR_PROTOCOL_0* pItem, *pItemTable = NULL;
  82. //
  83. // Validate the caller's parameters
  84. //
  85. if (!lplpBuffer ||
  86. !lpdwEntriesRead) { return ERROR_INVALID_PARAMETER; }
  87. *lplpBuffer = NULL;
  88. *lpdwEntriesRead = 0;
  89. //
  90. // Open the key for the specified router-manager
  91. // under HKLM\Software\Microsoft\Router\CurrentVersion\RouterManagers
  92. //
  93. dwErr = QueryRmSoftwareKey(
  94. HKEY_LOCAL_MACHINE, dwTransportId, &hkrm, &lpwsRm
  95. );
  96. if (dwErr != NO_ERROR) { return dwErr; }
  97. //
  98. // The transport was found, so its registry key is in 'hkrm'
  99. //
  100. do {
  101. //
  102. // Retrieve information about the subkeys of the router-manager,
  103. // since these should all contain data for routing-protocols.
  104. //
  105. WCHAR* pwsKey;
  106. DWORD i, dwSize, dwType;
  107. DWORD dwKeyCount, dwMaxKeyLength;
  108. dwErr = RegQueryInfoKey(
  109. hkrm, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLength,
  110. NULL, NULL, NULL, NULL, NULL, NULL
  111. );
  112. if (dwErr != ERROR_SUCCESS) { break; }
  113. //
  114. // Allocate enough space for the longest of the subkeys
  115. //
  116. pwsKey = Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  117. if (!pwsKey) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  118. //
  119. // Allocate an array to hold the keys' contents
  120. //
  121. pItemTable = (MPR_PROTOCOL_0*)Malloc(dwKeyCount * sizeof(*pItem));
  122. if (!pItemTable) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  123. ZeroMemory(pItemTable, dwKeyCount * sizeof(*pItem));
  124. //
  125. // Enumerate the keys
  126. //
  127. dwItemCount = 0;
  128. for (i = 0; i < dwKeyCount; i++) {
  129. HKEY hkprot;
  130. PBYTE pValue = NULL;
  131. //
  132. // Get the name of the current key
  133. //
  134. dwSize = dwMaxKeyLength + 1;
  135. dwErr = RegEnumKeyEx(
  136. hkrm, i, pwsKey, &dwSize, NULL, NULL, NULL, NULL
  137. );
  138. if (dwErr != ERROR_SUCCESS) { continue; }
  139. //
  140. // Open the key
  141. //
  142. dwErr = RegOpenKeyEx(hkrm, pwsKey, 0, KEY_READ, &hkprot);
  143. if (dwErr != ERROR_SUCCESS) { continue; }
  144. pItem = pItemTable + dwItemCount;
  145. do {
  146. DWORD dwMaxValLength;
  147. //
  148. // Copy the string for the protocol
  149. //
  150. lstrcpyn(pItem->wszProtocol, pwsKey, MAX_PROTOCOL_NAME_LEN+1);
  151. //
  152. // Get information about the key's values
  153. //
  154. dwErr = RegQueryInfoKey(
  155. hkprot, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  156. NULL, &dwMaxValLength, NULL, NULL
  157. );
  158. if (dwErr != ERROR_SUCCESS) { break; }
  159. //
  160. // Allocate space to hold the longest of the values
  161. //
  162. pValue = Malloc(dwMaxValLength + 1);
  163. if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  164. //
  165. // Read the ProtocolId value
  166. //
  167. dwSize = dwMaxValLength + 1;
  168. dwErr = RegQueryValueEx(
  169. hkprot, c_szProtocolId, 0, &dwType, pValue, &dwSize
  170. );
  171. if (dwErr != ERROR_SUCCESS) { break; }
  172. pItem->dwProtocolId = *(PDWORD)pValue;
  173. //
  174. // Read the DLLName value
  175. //
  176. dwSize = dwMaxValLength + 1;
  177. dwErr = RegQueryValueEx(
  178. hkprot, c_szDLLName, 0, &dwType, pValue, &dwSize
  179. );
  180. if (dwErr != ERROR_SUCCESS) { break; }
  181. lstrcpyn(
  182. pItem->wszDLLName, (WCHAR*)pValue, MAX_PROTOCOL_DLL_LEN+1);
  183. //
  184. // Increment the count of loaded protocols
  185. //
  186. ++dwItemCount;
  187. dwErr = ERROR_SUCCESS;
  188. } while(FALSE);
  189. Free0(pValue);
  190. RegCloseKey(hkprot);
  191. }
  192. Free0(pwsKey);
  193. } while(FALSE);
  194. Free0(lpwsRm);
  195. if (dwErr != NO_ERROR) {
  196. Free0(pItemTable);
  197. }
  198. else {
  199. //
  200. // Adjust the size of the buffer to be returned,
  201. // in case not all the keys contained routing-protocols,
  202. // and save the number of protocols loaded.
  203. //
  204. *lplpBuffer = ReAlloc(pItemTable, dwItemCount * sizeof(*pItem));
  205. *lpdwEntriesRead = dwItemCount;
  206. }
  207. RegCloseKey(hkrm);
  208. return dwErr;
  209. }
  210. //----------------------------------------------------------------------------
  211. // Function: MprSetupProtocolFree
  212. //
  213. // Called to free a buffer allocated by 'MprSetupProtocolEnum'.
  214. //----------------------------------------------------------------------------
  215. DWORD APIENTRY
  216. MprSetupProtocolFree(
  217. IN LPVOID lpBuffer
  218. ) {
  219. if (!lpBuffer) { return ERROR_INVALID_PARAMETER; }
  220. Free(lpBuffer);
  221. return NO_ERROR;
  222. }
  223. #ifdef KSL_IPINIP
  224. DWORD
  225. APIENTRY
  226. MprSetupIpInIpInterfaceFriendlyNameEnum(
  227. IN PWCHAR pwszMachineName,
  228. OUT LPBYTE* lplpBuffer, // MPR_IPINIP_INTERFACE_0
  229. OUT LPDWORD lpdwEntriesRead
  230. )
  231. {
  232. HKEY hkRead=NULL, hkWrite=NULL, hkMachine=NULL;
  233. DWORD dwErr, dwIndex, i;
  234. DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueLen;
  235. PMPR_IPINIP_INTERFACE_0 pItem, pTable = NULL;
  236. //
  237. // Validate the caller's parameters
  238. //
  239. if (!lplpBuffer ||
  240. !lpdwEntriesRead) {
  241. return ERROR_INVALID_PARAMETER;
  242. }
  243. *lplpBuffer = NULL;
  244. *lpdwEntriesRead = 0;
  245. //
  246. // Connect to the registry
  247. //
  248. dwErr = RegConnectRegistry(
  249. pwszMachineName,
  250. HKEY_LOCAL_MACHINE,
  251. &hkMachine
  252. );
  253. if(dwErr != NO_ERROR) {
  254. return dwErr;
  255. }
  256. //
  257. // Open the HKLM\Software\Microsoft\IpInIp key
  258. //
  259. dwErr = QueryIpInIpSoftwareKey(
  260. hkMachine,
  261. &hkRead,
  262. &hkWrite,
  263. &dwNumValues,
  264. &dwMaxValueNameLen,
  265. &dwMaxValueLen
  266. );
  267. if (dwErr != NO_ERROR)
  268. {
  269. //We need to close hkMachine here
  270. RegCloseKey(hkMachine);
  271. return dwErr;
  272. }
  273. if(dwNumValues == 0) {
  274. if(hkWrite != NULL) {
  275. RegCloseKey(hkWrite);
  276. }
  277. RegCloseKey(hkRead);
  278. RegCloseKey(hkMachine);
  279. return NO_ERROR;
  280. }
  281. //
  282. // So the Value Name shouldnt be longer than a GUID length and
  283. // the value itself should be less that MAX_INTERFACE_NAME_LEN
  284. //
  285. if((dwMaxValueNameLen > 38) ||
  286. (dwMaxValueLen > MAX_INTERFACE_NAME_LEN)) {
  287. RegCloseKey(hkMachine);
  288. return ERROR_REGISTRY_CORRUPT;
  289. }
  290. dwErr = NO_ERROR;
  291. do {
  292. UNICODE_STRING usTempString;
  293. WCHAR rgwcGuid[40];
  294. DWORD dwType;
  295. //
  296. // Allocate an array to hold the ipinip info
  297. //
  298. pTable = Malloc(dwNumValues * sizeof(*pItem));
  299. if (!pTable) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  300. ZeroMemory(pTable, dwNumValues * sizeof(*pItem));
  301. //
  302. // Enumerate the keys
  303. //
  304. usTempString.MaximumLength = sizeof(rgwcGuid);
  305. usTempString.Buffer = rgwcGuid;
  306. for (i = 0, dwIndex = 0; i < dwNumValues; i++) {
  307. DWORD dwValueNameLen = 39;
  308. DWORD dwValueLen = (MAX_INTERFACE_NAME_LEN + 1) * sizeof(WCHAR);
  309. dwErr = RegEnumValue(
  310. hkRead,
  311. i,
  312. rgwcGuid,
  313. &dwValueNameLen,
  314. NULL,
  315. &dwType,
  316. (PBYTE)(pTable[dwIndex].wszFriendlyName),
  317. &dwValueLen
  318. );
  319. if((dwErr == NO_ERROR) &&
  320. (dwType == REG_SZ)) {
  321. //
  322. // Convert the string to a guid
  323. //
  324. ASSERT(dwValueNameLen <= 38);
  325. usTempString.Length = (USHORT)(dwValueNameLen * sizeof(WCHAR));
  326. dwErr = RtlGUIDFromString(
  327. &usTempString,
  328. &(pTable[dwIndex].Guid)
  329. );
  330. if(dwErr == STATUS_SUCCESS) {
  331. dwIndex++;
  332. }
  333. }
  334. }
  335. } while(FALSE);
  336. if (dwIndex == 0) {
  337. Free0(pTable);
  338. } else {
  339. *lplpBuffer = (PBYTE)pTable;
  340. *lpdwEntriesRead = dwIndex;
  341. }
  342. if(hkWrite != NULL) {
  343. RegCloseKey(hkWrite);
  344. }
  345. RegCloseKey(hkRead);
  346. RegCloseKey(hkMachine);
  347. if(dwIndex == 0) {
  348. return dwErr ? dwErr : ERROR_CAN_NOT_COMPLETE;
  349. }
  350. return NO_ERROR;
  351. }
  352. DWORD
  353. APIENTRY
  354. MprSetupIpInIpInterfaceFriendlyNameFree(
  355. IN LPVOID lpBuffer
  356. )
  357. {
  358. if (!lpBuffer) { return ERROR_INVALID_PARAMETER; }
  359. Free(lpBuffer);
  360. return NO_ERROR;
  361. }
  362. DWORD
  363. APIENTRY
  364. MprSetupIpInIpInterfaceFriendlyNameCreate(
  365. PWCHAR pwszMachineName,
  366. PMPR_IPINIP_INTERFACE_0 pNameInformation
  367. )
  368. {
  369. DWORD dwErr, dwNumValues, dwMaxValueNameLen, dwMaxValueLen;
  370. DWORD dwType, dwValueLen;
  371. HKEY hkMachine=NULL, hkRead=NULL, hkWrite=NULL;
  372. WCHAR rgwcName[MAX_INTERFACE_NAME_LEN + 2];
  373. UNICODE_STRING usTempString;
  374. //
  375. // Connect to the registry
  376. //
  377. dwErr = RegConnectRegistry(
  378. pwszMachineName,
  379. HKEY_LOCAL_MACHINE,
  380. &hkMachine);
  381. if(dwErr != NO_ERROR) {
  382. return dwErr;
  383. }
  384. //
  385. // Just call the query function to open the key
  386. //
  387. dwErr = QueryIpInIpSoftwareKey(
  388. hkMachine,
  389. &hkRead,
  390. &hkWrite,
  391. &dwNumValues,
  392. &dwMaxValueNameLen,
  393. &dwMaxValueLen
  394. );
  395. RegCloseKey(hkMachine);
  396. if (dwErr != NO_ERROR) {
  397. return dwErr;
  398. }
  399. //
  400. // Dont need this
  401. //
  402. RegCloseKey(hkRead);
  403. if(hkWrite == NULL) {
  404. return ERROR_ACCESS_DENIED;
  405. }
  406. //
  407. // Convert guid to string
  408. //
  409. dwErr = RtlStringFromGUID(
  410. &(pNameInformation->Guid),
  411. &usTempString);
  412. if(dwErr != STATUS_SUCCESS) {
  413. RegCloseKey(hkWrite);
  414. return ERROR_INVALID_PARAMETER;
  415. }
  416. //
  417. // See if it exists
  418. //
  419. dwValueLen = sizeof(rgwcName);
  420. dwErr = RegQueryValueEx(
  421. hkWrite,
  422. usTempString.Buffer,
  423. NULL,
  424. &dwType,
  425. (PBYTE)rgwcName,
  426. &dwValueLen);
  427. if(dwErr == NO_ERROR) {
  428. //
  429. // hmm already exists
  430. //
  431. RegCloseKey(hkWrite);
  432. RtlFreeUnicodeString(&usTempString);
  433. return ERROR_OBJECT_ALREADY_EXISTS;
  434. }
  435. //
  436. // Set the value
  437. //
  438. dwErr = RegSetValueEx(
  439. hkWrite,
  440. usTempString.Buffer,
  441. 0,
  442. REG_SZ,
  443. (PBYTE)pNameInformation->wszFriendlyName,
  444. (wcslen(pNameInformation->wszFriendlyName) + 1) * sizeof(WCHAR));
  445. RegCloseKey(hkWrite);
  446. RtlFreeUnicodeString(&usTempString);
  447. return dwErr;
  448. }
  449. DWORD
  450. APIENTRY
  451. MprSetupIpInIpInterfaceFriendlyNameDelete(
  452. IN PWCHAR pwszMachineName,
  453. IN GUID *pGuid
  454. )
  455. {
  456. DWORD dwErr, dwNumValues, dwMaxValueNameLen, dwMaxValueLen;
  457. HKEY hkMachine=NULL, hkRead=NULL, hkWrite=NULL;
  458. UNICODE_STRING usTempString;
  459. //
  460. // Connect to the registry
  461. //
  462. dwErr = RegConnectRegistry(
  463. pwszMachineName,
  464. HKEY_LOCAL_MACHINE,
  465. &hkMachine);
  466. if(dwErr != NO_ERROR) {
  467. return dwErr;
  468. }
  469. //
  470. // Just call the query function to open the key
  471. //
  472. dwErr = QueryIpInIpSoftwareKey(
  473. hkMachine,
  474. &hkRead,
  475. &hkWrite,
  476. &dwNumValues,
  477. &dwMaxValueNameLen,
  478. &dwMaxValueLen
  479. );
  480. RegCloseKey(hkMachine);
  481. if (dwErr != NO_ERROR) {
  482. return dwErr;
  483. }
  484. //
  485. // Dont need this
  486. //
  487. RegCloseKey(hkRead);
  488. if(hkWrite == NULL) {
  489. return ERROR_ACCESS_DENIED;
  490. }
  491. //
  492. // Convert guid to string
  493. //
  494. dwErr = RtlStringFromGUID(
  495. pGuid,
  496. &usTempString);
  497. if(dwErr != STATUS_SUCCESS) {
  498. RegCloseKey(hkWrite);
  499. return ERROR_INVALID_PARAMETER;
  500. }
  501. //
  502. // See if it exists
  503. //
  504. dwErr = RegDeleteValue(
  505. hkWrite,
  506. usTempString.Buffer);
  507. RegCloseKey(hkWrite);
  508. RtlFreeUnicodeString(&usTempString);
  509. return dwErr;
  510. }
  511. #endif //KSL_IPINIP
  512. //----------------------------------------------------------------------------
  513. // Function: QueryRmSoftwareKey
  514. //
  515. // Called to open the key for a router-manager given its transport ID.
  516. //----------------------------------------------------------------------------
  517. DWORD
  518. QueryRmSoftwareKey(
  519. IN HKEY hkeyMachine,
  520. IN DWORD dwTransportId,
  521. OUT HKEY* phkrm,
  522. OUT LPWSTR* lplpwsRm
  523. ) {
  524. HKEY hkey;
  525. DWORD dwErr;
  526. WCHAR wszKey[256], *pwsKey;
  527. //
  528. // Open the key HKLM\Software\Microsoft\Router\RouterManagers
  529. //
  530. wsprintf(
  531. wszKey, L"%s\\%s\\%s\\%s\\%s", c_szSoftware, c_szMicrosoft, c_szRouter,
  532. c_szCurrentVersion, c_szRouterManagers
  533. );
  534. dwErr = RegOpenKeyEx(hkeyMachine, wszKey, 0, KEY_READ, &hkey);
  535. if (dwErr != ERROR_SUCCESS) { return dwErr; }
  536. //
  537. // Enumerate the subkeys of the 'RouterManagers' key,
  538. // in search of one which as a 'ProtocolId' value equal to 'dwTransportId'.
  539. //
  540. do {
  541. //
  542. // Retrieve information about the subkeys of the key
  543. //
  544. DWORD dwKeyCount, dwMaxKeyLength;
  545. DWORD i, dwSize, dwType, dwProtocolId = ~dwTransportId;
  546. dwErr = RegQueryInfoKey(
  547. hkey, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLength,
  548. NULL, NULL, NULL, NULL, NULL, NULL
  549. );
  550. if (dwErr != ERROR_SUCCESS) { break; }
  551. //
  552. // Allocate enough space for the longest of the subkeys
  553. //
  554. pwsKey = Malloc((dwMaxKeyLength + 1) * sizeof(WCHAR));
  555. if (!pwsKey) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  556. //
  557. // Enumerate the keys
  558. //
  559. for (i = 0; i < dwKeyCount; i++) {
  560. //
  561. // Get the name of the current key
  562. //
  563. dwSize = dwMaxKeyLength + 1;
  564. dwErr = RegEnumKeyEx(
  565. hkey, i, pwsKey, &dwSize, NULL, NULL, NULL, NULL
  566. );
  567. if (dwErr != ERROR_SUCCESS) { continue; }
  568. //
  569. // Open the key
  570. //
  571. dwErr = RegOpenKeyEx(hkey, pwsKey, 0, KEY_READ, phkrm);
  572. if (dwErr != ERROR_SUCCESS) { continue; }
  573. //
  574. // Try to read the ProtocolId value
  575. //
  576. dwSize = sizeof(dwProtocolId);
  577. dwErr = RegQueryValueEx(
  578. *phkrm, c_szProtocolId, 0, &dwType,
  579. (BYTE*)&dwProtocolId, &dwSize
  580. );
  581. //
  582. // Break if this is the transport we're looking for,
  583. // otherwise close the key and continue
  584. //
  585. if (dwErr == ERROR_SUCCESS &&
  586. dwProtocolId == dwTransportId) { break; }
  587. RegCloseKey(*phkrm);
  588. }
  589. if (i >= dwKeyCount) { Free(pwsKey); break; }
  590. //
  591. // The transport was found, so save its key-name
  592. //
  593. *lplpwsRm = pwsKey;
  594. } while(FALSE);
  595. RegCloseKey(hkey);
  596. return (*lplpwsRm ? NO_ERROR : ERROR_NO_MORE_ITEMS);
  597. }
  598. #ifdef KSL_IPINIP
  599. DWORD
  600. QueryIpInIpSoftwareKey(
  601. IN HKEY hkeyMachine,
  602. OUT HKEY* phkIpIpRead,
  603. OUT HKEY* phkIpIpWrite,
  604. OUT PDWORD pdwNumValues,
  605. OUT PDWORD pdwMaxValueNameLen,
  606. OUT PDWORD pdwMaxValueLen
  607. )
  608. {
  609. HKEY hkReg;
  610. DWORD dwErr, dwDisp;
  611. WCHAR wszKey[256], *pwsKey;
  612. DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueLen;
  613. *phkIpIpWrite = NULL;
  614. *phkIpIpRead = NULL;
  615. *pdwNumValues = 0;
  616. *pdwMaxValueLen = 0;
  617. *pdwMaxValueNameLen = 0;
  618. //
  619. // Open the key HKLM\Software\Microsoft\IpInIp
  620. //
  621. wsprintf(
  622. wszKey, L"%s\\%s\\%s", c_szSoftware, c_szMicrosoft, c_szIpInIp
  623. );
  624. //
  625. // First open/create a key for all access
  626. //
  627. dwErr = RegCreateKeyEx(
  628. hkeyMachine,
  629. wszKey,
  630. 0,
  631. NULL,
  632. 0,
  633. KEY_ALL_ACCESS,
  634. NULL,
  635. &hkReg,
  636. &dwDisp);
  637. if (dwErr == NO_ERROR) {
  638. *phkIpIpWrite = hkReg;
  639. } else {
  640. *phkIpIpWrite = NULL;
  641. }
  642. dwErr = RegOpenKeyEx(
  643. hkeyMachine,
  644. wszKey,
  645. 0,
  646. KEY_READ,
  647. &hkReg);
  648. if (dwErr != NO_ERROR) {
  649. ASSERT(*phkIpIpWrite == NULL);
  650. *phkIpIpRead = NULL;
  651. return dwErr;
  652. } else {
  653. *phkIpIpRead = hkReg;
  654. }
  655. //
  656. // Atleast the read key is opened, query the number of interfaces
  657. //
  658. dwErr = RegQueryInfoKey(
  659. *phkIpIpRead,
  660. NULL,
  661. NULL,
  662. NULL,
  663. NULL,
  664. NULL,
  665. NULL,
  666. &dwNumValues,
  667. &dwMaxValueNameLen,
  668. &dwMaxValueLen,
  669. NULL,
  670. NULL);
  671. if (dwErr != NO_ERROR) {
  672. if(*phkIpIpWrite != NULL) {
  673. RegCloseKey(*phkIpIpWrite);
  674. }
  675. RegCloseKey(*phkIpIpRead);
  676. return dwErr;
  677. }
  678. *pdwNumValues = dwNumValues;
  679. *pdwMaxValueLen = dwMaxValueLen;
  680. *pdwMaxValueNameLen = dwMaxValueNameLen;
  681. return NO_ERROR;
  682. }
  683. #endif //KSL_IPINIP