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.

1048 lines
28 KiB

  1. //============================================================================
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: util.cpp
  5. //
  6. // History:
  7. // 03/10/97 Kenn M. Takara Created
  8. //
  9. // Source code for some of the utility functions in util.h
  10. //============================================================================
  11. #include "stdafx.h"
  12. #include "mprsnap.h"
  13. #include "rtrutilp.h"
  14. #include "rtrstr.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. static const GUID GUID_DevClass_Net = {0x4D36E972,0xE325,0x11CE,{0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18}};
  21. //----------------------------------------------------------------------------
  22. // Function: ConnectRegistry
  23. //
  24. // Connects to the registry on the specified machine
  25. //----------------------------------------------------------------------------
  26. TFSCORE_API(DWORD)
  27. ConnectRegistry(
  28. IN LPCTSTR pszMachine,
  29. OUT HKEY* phkeyMachine
  30. ) {
  31. //
  32. // if no machine name was specified, connect to the local machine.
  33. // otherwise, connect to the specified machine
  34. //
  35. DWORD dwErr = NO_ERROR;
  36. if (IsLocalMachine(pszMachine))
  37. {
  38. *phkeyMachine = HKEY_LOCAL_MACHINE;
  39. }
  40. else
  41. {
  42. //
  43. // Make the connection
  44. //
  45. dwErr = ::RegConnectRegistry(
  46. (LPTSTR)pszMachine, HKEY_LOCAL_MACHINE, phkeyMachine
  47. );
  48. }
  49. HrReportExit(HRESULT_FROM_WIN32(dwErr), TEXT("ConnectRegistry"));
  50. return dwErr;
  51. }
  52. //----------------------------------------------------------------------------
  53. // Function: DisconnectRegistry
  54. //
  55. // Disconnects the specified config-handle. The handle is assumed to have been
  56. // acquired by calling 'ConnectRegistry'.
  57. //----------------------------------------------------------------------------
  58. TFSCORE_API(VOID)
  59. DisconnectRegistry(
  60. IN HKEY hkeyMachine
  61. ) {
  62. if (hkeyMachine != HKEY_LOCAL_MACHINE)
  63. {
  64. ::RegCloseKey(hkeyMachine);
  65. }
  66. }
  67. /*!--------------------------------------------------------------------------
  68. QueryRouterType
  69. -
  70. Author: KennT
  71. ---------------------------------------------------------------------------*/
  72. TFSCORE_API(HRESULT) QueryRouterType(HKEY hkeyMachine, DWORD *pdwRouterType,
  73. RouterVersionInfo *pVersion)
  74. {
  75. Assert(pdwRouterType);
  76. Assert(hkeyMachine);
  77. DWORD dwErr = ERROR_SUCCESS;
  78. HKEY hkey = 0;
  79. DWORD dwType;
  80. DWORD dwRouterType;
  81. DWORD dwSize;
  82. RouterVersionInfo versionTemp;
  83. LPCTSTR pszRouterTypeKey = NULL;
  84. BOOL fFirstTry = TRUE;
  85. // If the version structure is not passed in, we have to do it
  86. // ourselves
  87. // ----------------------------------------------------------------
  88. if (pVersion == NULL)
  89. {
  90. dwErr = QueryRouterVersionInfo(hkeyMachine, &versionTemp);
  91. if ( dwErr != ERROR_SUCCESS )
  92. {
  93. goto Error;
  94. }
  95. pVersion = &versionTemp;
  96. }
  97. // Windows NT Bug : 137200
  98. // Need to get the router type from a different place depending
  99. // on the version.
  100. // ----------------------------------------------------------------
  101. // if (pVersion->dwRouterVersion <= 4)
  102. if (pVersion->dwOsBuildNo < RASMAN_PPP_KEY_LAST_VERSION)
  103. pszRouterTypeKey = c_szRegKeyRasProtocols;
  104. else
  105. pszRouterTypeKey = c_szRegKeyRemoteAccessParameters;
  106. // This is where we perform a retry
  107. // ----------------------------------------------------------------
  108. Retry:
  109. // Cool, we have a machine registry entry, now get the
  110. // path down to the routertype key
  111. dwErr = RegOpenKeyEx(hkeyMachine, pszRouterTypeKey, 0, KEY_READ, &hkey);
  112. if (dwErr)
  113. goto Error;
  114. // Ok, at this point we just need to get the RouterType value from
  115. // the key
  116. dwType = REG_DWORD;
  117. dwSize = sizeof(dwRouterType);
  118. dwErr = RegQueryValueEx(hkey, c_szRouterType, NULL,
  119. &dwType,
  120. (LPBYTE) &dwRouterType,
  121. &dwSize);
  122. if (dwErr)
  123. {
  124. // Need to retry (look at the RAS/protocols key), for NT5
  125. if ((pVersion->dwRouterVersion >= 5) && fFirstTry)
  126. {
  127. dwErr = ERROR_SUCCESS;
  128. fFirstTry = FALSE;
  129. if (hkey)
  130. RegCloseKey(hkey);
  131. hkey = 0;
  132. pszRouterTypeKey = c_szRegKeyRasProtocols;
  133. goto Retry;
  134. }
  135. goto Error;
  136. }
  137. // Is this the right type?
  138. if (dwType != REG_DWORD)
  139. {
  140. dwErr = ERROR_BADKEY;
  141. goto Error;
  142. }
  143. // We have the right type, now return that value
  144. *pdwRouterType = dwRouterType;
  145. Error:
  146. if (hkey)
  147. RegCloseKey(hkey);
  148. return HrReportExit(HRESULT_FROM_WIN32(dwErr), TEXT("QueryRouterType"));
  149. }
  150. //----------------------------------------------------------------------------
  151. // Function: LoadLinkageList
  152. //
  153. // Loads a list of strings with the adapters to which 'pszService' is bound;
  154. // the list is built by examining the 'Linkage' and 'Disabled' subkeys
  155. // of the service under HKLM\System\CurrentControlSet\Services.
  156. //----------------------------------------------------------------------------
  157. HRESULT LoadLinkageList(
  158. LPCTSTR pszMachine,
  159. HKEY hkeyMachine,
  160. LPCTSTR pszService,
  161. CStringList* pLinkageList)
  162. {
  163. Assert(hkeyMachine);
  164. DWORD dwErr;
  165. BYTE* pValue = NULL;
  166. HKEY hkeyLinkage = NULL, hkeyDisabled = NULL;
  167. if (!pszService || !lstrlen(pszService) || !pLinkageList) {
  168. return ERROR_INVALID_PARAMETER;
  169. }
  170. do {
  171. TCHAR* psz;
  172. CString skey;
  173. DWORD dwType, dwSize;
  174. BOOL fNt4;
  175. dwErr = IsNT4Machine(hkeyMachine, &fNt4);
  176. if (dwErr != NO_ERROR)
  177. break;
  178. //$NT5 : where is the registry key? same as NT4
  179. skey = c_szSystemCCSServices;
  180. skey += TEXT('\\');
  181. skey += pszService;
  182. skey += TEXT('\\');
  183. skey += c_szLinkage;
  184. //
  185. // Open the service's 'Linkage' key
  186. //
  187. dwErr = RegOpenKeyEx(
  188. hkeyMachine, skey, 0, KEY_READ, &hkeyLinkage
  189. );
  190. if (dwErr != NO_ERROR) {
  191. if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
  192. CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("QueryLinkageList"));
  193. break;
  194. }
  195. //
  196. // Retrieve the size of the 'Bind' value
  197. //
  198. dwErr = RegQueryValueEx(
  199. hkeyLinkage, c_szBind, NULL, &dwType, NULL, &dwSize
  200. );
  201. if (dwErr != NO_ERROR) {
  202. if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
  203. CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szBind, _T("QueryLinkageList"));
  204. break;
  205. }
  206. //
  207. // Allocate space for the 'Bind' value
  208. //
  209. pValue = new BYTE[dwSize + sizeof(TCHAR)];
  210. if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  211. ::ZeroMemory(pValue, dwSize + sizeof(TCHAR));
  212. //
  213. // Read the 'Bind' value
  214. //
  215. dwErr = RegQueryValueEx(
  216. hkeyLinkage, c_szBind, NULL, &dwType, pValue, &dwSize
  217. );
  218. CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szBind, _T("QueryLinkageList"));
  219. if (dwErr != NO_ERROR) { break; }
  220. //
  221. // Convert the 'Bind' multi-string to a list of strings,
  222. // leaving out the string "\Device\" which is the prefix
  223. // for all the bindings.
  224. //
  225. for (psz = (TCHAR*)pValue; *psz; psz += lstrlen(psz) + 1) {
  226. pLinkageList->AddTail(psz + 8);
  227. }
  228. delete [] pValue; pValue = NULL;
  229. //
  230. // Now open the service's 'Disabled' key.
  231. //
  232. dwErr = RegOpenKeyEx(
  233. hkeyLinkage, c_szDisabled, 0, KEY_READ, &hkeyDisabled
  234. );
  235. if (dwErr != NO_ERROR) {
  236. if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
  237. CheckRegOpenError(dwErr, c_szDisabled, _T("QueryLinkageList"));
  238. break;
  239. }
  240. //
  241. // Retrieve the size of the 'Bind' value
  242. //
  243. dwErr = RegQueryValueEx(
  244. hkeyDisabled, c_szBind, NULL, &dwType, NULL, &dwSize
  245. );
  246. if (dwErr != NO_ERROR) {
  247. if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
  248. CheckRegQueryValueError(dwErr, c_szDisabled, c_szBind, _T("QueryLinkageList"));
  249. break;
  250. }
  251. //
  252. // Allocate space for the 'Bind' value
  253. //
  254. pValue = new BYTE[dwSize + sizeof(TCHAR)];
  255. if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
  256. ::ZeroMemory(pValue, dwSize + sizeof(TCHAR));
  257. //
  258. // Read the 'Bind' value
  259. //
  260. dwErr = RegQueryValueEx(
  261. hkeyDisabled, c_szBind, NULL, &dwType, pValue, &dwSize
  262. );
  263. CheckRegQueryValueError(dwErr, c_szDisabled, c_szBind, _T("QueryLinkageList"));
  264. if (dwErr != NO_ERROR) { break; }
  265. //
  266. // Each device in the 'Bind' mulit-string is disabled for the service,
  267. // so we will now remove such devices from the string-list built
  268. // from the 'Linkage' key.
  269. //
  270. for (psz = (TCHAR*)pValue; *psz; psz += lstrlen(psz) + 1) {
  271. POSITION pos = pLinkageList->Find(psz);
  272. if (pos) { pLinkageList->RemoveAt(pos); }
  273. }
  274. } while(FALSE);
  275. if (pValue) { delete [] pValue; }
  276. if (hkeyDisabled) { ::RegCloseKey(hkeyDisabled); }
  277. if (hkeyLinkage) { ::RegCloseKey(hkeyLinkage); }
  278. return dwErr;
  279. }
  280. /*!--------------------------------------------------------------------------
  281. IsNT4Machine
  282. -
  283. Author: KennT, WeiJiang
  284. ---------------------------------------------------------------------------*/
  285. TFSCORE_API(DWORD) GetNTVersion(HKEY hkeyMachine, DWORD *pdwMajor, DWORD *pdwMinor, DWORD* pdwCurrentBuildNumber)
  286. {
  287. // Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
  288. // CurrentVersion = REG_SZ "4.0"
  289. CString skey;
  290. DWORD dwErr;
  291. TCHAR szVersion[64];
  292. TCHAR szCurrentBuildNumber[64];
  293. RegKey regkey;
  294. CString strVersion;
  295. CString strMajor;
  296. CString strMinor;
  297. ASSERT(pdwMajor);
  298. ASSERT(pdwMinor);
  299. ASSERT(pdwCurrentBuildNumber);
  300. skey = c_szSoftware;
  301. skey += TEXT('\\');
  302. skey += c_szMicrosoft;
  303. skey += TEXT('\\');
  304. skey += c_szWindowsNT;
  305. skey += TEXT('\\');
  306. skey += c_szCurrentVersion;
  307. dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
  308. CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("GetNTVersion"));
  309. if (dwErr != ERROR_SUCCESS)
  310. return dwErr;
  311. // Ok, now try to get the current version value
  312. dwErr = regkey.QueryValue( c_szCurrentVersion, szVersion,
  313. sizeof(szVersion),
  314. FALSE);
  315. CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentVersion,
  316. _T("GetNTVersion"));
  317. if (dwErr != ERROR_SUCCESS)
  318. goto Err;
  319. // Ok, now try to get the current build number value
  320. dwErr = regkey.QueryValue( c_szCurrentBuildNumber, szCurrentBuildNumber,
  321. sizeof(szCurrentBuildNumber),
  322. FALSE);
  323. CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentBuildNumber,
  324. _T("GetNTVersion"));
  325. if (dwErr != ERROR_SUCCESS)
  326. goto Err;
  327. strVersion = szVersion;
  328. strMajor = strVersion.Left(strVersion.Find(_T('.')));
  329. strMinor = strVersion.Mid(strVersion.Find(_T('.')) + 1);
  330. if(pdwMajor)
  331. *pdwMajor = _ttol(strMajor);
  332. if(pdwMinor)
  333. *pdwMinor = _ttol(strMinor);
  334. if(pdwCurrentBuildNumber)
  335. *pdwCurrentBuildNumber = _ttol(szCurrentBuildNumber);
  336. Err:
  337. return dwErr;
  338. }
  339. /*!--------------------------------------------------------------------------
  340. IsNT4Machine
  341. -
  342. Author: KennT
  343. ---------------------------------------------------------------------------*/
  344. TFSCORE_API(DWORD) IsNT4Machine(HKEY hkeyMachine, BOOL *pfNt4)
  345. {
  346. // Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
  347. // CurrentVersion = REG_SZ "4.0"
  348. DWORD dwMajor = 0;
  349. DWORD dwErr = 0;
  350. dwErr = GetNTVersion(hkeyMachine, &dwMajor, NULL, NULL);
  351. if (dwErr == ERROR_SUCCESS)
  352. {
  353. *pfNt4 = (dwMajor == 4);
  354. }
  355. return dwErr;
  356. }
  357. //----------------------------------------------------------------------------
  358. // Function: FindRmSoftwareKey
  359. //
  360. // Finds the key for a router-manager in the Software section of the registry.
  361. //----------------------------------------------------------------------------
  362. HRESULT FindRmSoftwareKey(
  363. HKEY hkeyMachine,
  364. DWORD dwTransportId,
  365. HKEY* phkrm,
  366. LPTSTR* lplpszRm
  367. )
  368. {
  369. Assert(phkrm);
  370. DWORD dwErr;
  371. RegKey regkey;
  372. HRESULT hr = hrOK;
  373. CString stKey;
  374. RegKeyIterator regkeyIter;
  375. HRESULT hrIter;
  376. RegKey regkeyRM;
  377. DWORD dwProtocolId;
  378. BOOL bFound = FALSE;
  379. //
  380. // open the key HKLM\Software\Microsoft\Router\RouterManagers
  381. //
  382. CString skey(c_szSoftware);
  383. skey += TEXT('\\');
  384. skey += c_szMicrosoft;
  385. skey += TEXT('\\');
  386. skey += c_szRouter;
  387. skey += TEXT('\\');
  388. skey += c_szCurrentVersion;
  389. skey += TEXT('\\');
  390. skey += c_szRouterManagers;
  391. dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
  392. CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("QueryRmSoftwareKey"));
  393. CWRg(dwErr);
  394. if (lplpszRm)
  395. *lplpszRm = NULL;
  396. *phkrm = 0;
  397. //
  398. // Enumerate its subkeys looking for one which has a ProtocolId value
  399. // equal to 'dwTransportId';
  400. //
  401. CWRg( regkeyIter.Init(&regkey) );
  402. hrIter = regkeyIter.Next(&stKey);
  403. for (; hrIter == hrOK; hrIter = regkeyIter.Next(&stKey))
  404. {
  405. //
  406. // open the key
  407. //
  408. dwErr = regkeyRM.Open(regkey, stKey, KEY_READ);
  409. CheckRegOpenError(dwErr, stKey, _T("QueryRmSoftwareKey"));
  410. if (dwErr != ERROR_SUCCESS) { continue; }
  411. //
  412. // try to read the ProtocolId value
  413. //
  414. dwErr = regkeyRM.QueryValue(c_szProtocolId, dwProtocolId);
  415. CheckRegQueryValueError(dwErr, stKey, c_szProtocolId, _T("QueryRmSoftwareKey"));
  416. //
  417. // Break if this is the transport we're looking for,
  418. // otherwise close the key and continue
  419. //
  420. if ((dwErr == ERROR_SUCCESS) && (dwProtocolId == dwTransportId))
  421. break;
  422. regkeyRM.Close();
  423. }
  424. if (hrIter == hrOK)
  425. {
  426. //
  427. // The transport was found, so save its key-name and key
  428. //
  429. Assert(((HKEY)regkeyRM) != 0);
  430. if (lplpszRm)
  431. *lplpszRm = StrDup((LPCTSTR) stKey);
  432. bFound = TRUE;
  433. *phkrm = regkeyRM.Detach();
  434. }
  435. Error:
  436. if (FHrSucceeded(hr) && !bFound)
  437. {
  438. hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  439. }
  440. return hr;
  441. }
  442. #ifdef _DEBUG
  443. void CheckRegOpenErrorEx(DWORD dwError, LPCTSTR pszSubKey,
  444. LPCTSTR pszDesc, LPCTSTR pszFile, int iLineNo)
  445. {
  446. if (dwError)
  447. {
  448. CString st;
  449. st.Format(_T("RegOpenEx failed(%08lx)\nfile: %s\nline: %d\nDesc: %s\nkey: %s"),
  450. dwError, pszFile, iLineNo,
  451. pszDesc, pszSubKey);
  452. if (AfxMessageBox(st, MB_OKCANCEL) == IDCANCEL)
  453. {
  454. DebugBreak();
  455. }
  456. }
  457. }
  458. void CheckRegQueryValueErrorEx(DWORD dwError, LPCTSTR pszSubKey,
  459. LPCTSTR pszValue, LPCTSTR pszDesc,
  460. LPCTSTR pszFile, int iLineNo)
  461. {
  462. if (dwError)
  463. {
  464. CString st;
  465. st.Format(_T("RegQueryValue failed(%08lx)\nfile: %s\nline: %d\ndesc: %s\nkey: %s\nvalue: %s"),
  466. dwError, pszFile, iLineNo, pszDesc, pszSubKey, pszValue);
  467. if (AfxMessageBox(st, MB_OKCANCEL) == IDCANCEL)
  468. {
  469. DebugBreak();
  470. }
  471. }
  472. }
  473. #endif
  474. /*!--------------------------------------------------------------------------
  475. SetupFindInterfaceTitle
  476. -
  477. This function retrieves the title of the given interface.
  478. The argument 'LpszIf' should contain the ID of the interface,
  479. for instance "EPRO1".
  480. Author: KennT
  481. ---------------------------------------------------------------------------*/
  482. STDMETHODIMP SetupFindInterfaceTitle(LPCTSTR pszMachine,
  483. LPCTSTR pszInterface,
  484. LPTSTR *ppszTitle)
  485. {
  486. HRESULT hr = hrOK;
  487. CString stMachine;
  488. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  489. HKEY hkMachine = NULL;
  490. HKEY hkDevice= NULL;
  491. CString stPnpInstanceId;
  492. RegKey rkNet;
  493. RegKey rkNetcard;
  494. RegKey rkDevice;
  495. RegKey rkConnection;
  496. CString stBuffer, stPath;
  497. CString stConnection;
  498. TCHAR szClassGuid[128];
  499. DWORD dwAction;
  500. DWORD dwErr;
  501. SP_DEVINFO_DATA DevInfo;
  502. stMachine = pszMachine;
  503. if (IsLocalMachine(stMachine))
  504. {
  505. hDevInfo = SetupDiCreateDeviceInfoList(
  506. (LPGUID) &GUID_DevClass_Net,
  507. NULL);
  508. }
  509. else
  510. {
  511. // Append on the "\\\\" if needed
  512. if (StrniCmp((LPCTSTR) stMachine, _T("\\\\"), 2) != 0)
  513. {
  514. stMachine = _T("\\\\");
  515. stMachine += pszMachine;
  516. }
  517. hDevInfo = SetupDiCreateDeviceInfoListEx(
  518. (LPGUID) &GUID_DevClass_Net,
  519. NULL,
  520. (LPCTSTR) stMachine,
  521. 0);
  522. }
  523. // Get hkMachine from system
  524. // ----------------------------------------------------------------
  525. CWRg( ConnectRegistry( (LPCTSTR) stMachine, &hkMachine) );
  526. // Get the PnpInstanceID
  527. // ----------------------------------------------------------------
  528. CWRg( rkNet.Open(hkMachine, c_szNetworkCardsNT5Key, KEY_READ) );
  529. CWRg( rkNetcard.Open(rkNet, pszInterface, KEY_READ) );
  530. dwErr = rkNetcard.QueryValue(c_szPnpInstanceID, stPnpInstanceId);
  531. if (dwErr != ERROR_SUCCESS)
  532. {
  533. RegKey rkConnection;
  534. // Need to open another key to get this info.
  535. CWRg( rkConnection.Open(rkNetcard, c_szRegKeyConnection, KEY_READ) );
  536. CWRg( rkConnection.QueryValue(c_szPnpInstanceID, stPnpInstanceId) );
  537. }
  538. // Get hkDevice from SetupDiOpenDevRegKey
  539. // Now get the info for this device
  540. // ----------------------------------------------------------------
  541. ::ZeroMemory(&DevInfo, sizeof(DevInfo));
  542. DevInfo.cbSize = sizeof(DevInfo);
  543. if (!SetupDiOpenDeviceInfo(hDevInfo,
  544. (LPCTSTR) stPnpInstanceId,
  545. NULL,
  546. 0,
  547. &DevInfo))
  548. {
  549. CWRg( GetLastError() );
  550. }
  551. // Now that we have the info, get the reg key
  552. // ----------------------------------------------------------------
  553. hkDevice = SetupDiOpenDevRegKey(hDevInfo,
  554. &DevInfo,
  555. DICS_FLAG_GLOBAL,
  556. 0,
  557. DIREG_DRV,
  558. KEY_READ);
  559. if ((hkDevice == NULL) || (hkDevice == INVALID_HANDLE_VALUE))
  560. {
  561. CWRg( GetLastError() );
  562. }
  563. // Attach so that it will get freed up
  564. // ----------------------------------------------------------------
  565. rkDevice.Attach( hkDevice );
  566. // Read in the netcfg instance
  567. // ----------------------------------------------------------------
  568. CWRg( rkDevice.QueryValue(c_szRegValNetCfgInstanceId, stBuffer) );
  569. // Generate path in registry for lookup
  570. StringFromGUID2(GUID_DevClass_Net,
  571. szClassGuid,
  572. DimensionOf(szClassGuid));
  573. stPath.Format(_T("%s\\%s\\%s\\Connection"),
  574. c_szRegKeyComponentClasses,
  575. szClassGuid,
  576. stBuffer);
  577. // Open the key
  578. CWRg( rkConnection.Open(hkMachine, stPath, KEY_READ) );
  579. // Read in and store the connections name
  580. CWRg( rkConnection.QueryValue(c_szRegValName, stConnection) );
  581. *ppszTitle = StrDup((LPCTSTR) stConnection);
  582. Error:
  583. if (hDevInfo != INVALID_HANDLE_VALUE)
  584. SetupDiDestroyDeviceInfoList(hDevInfo);
  585. if (hkMachine)
  586. DisconnectRegistry( hkMachine );
  587. return hr;
  588. }
  589. /*!--------------------------------------------------------------------------
  590. RegFindInterfaceTitle
  591. -
  592. This function retrieves the title of the given interface.
  593. The argument 'LpszIf' should contain the ID of the interface,
  594. for instance "EPRO1".
  595. Author: KennT
  596. ---------------------------------------------------------------------------*/
  597. STDMETHODIMP RegFindInterfaceTitle(LPCTSTR pszMachine,
  598. LPCTSTR pszInterface,
  599. LPTSTR *ppszTitle)
  600. {
  601. HRESULT hr = hrOK;
  602. DWORD dwErr;
  603. HKEY hkeyMachine = NULL;
  604. RegKey regkey;
  605. RegKeyIterator regkeyIter;
  606. HRESULT hrIter;
  607. CString stKey;
  608. RegKey regkeyCard;
  609. CString stServiceName;
  610. CString stTitle;
  611. BOOL fNT4;
  612. LPCTSTR pszKey;
  613. CNetcardRegistryHelper ncreghelp;
  614. COM_PROTECT_TRY
  615. {
  616. //
  617. // connect to the registry
  618. //
  619. CWRg( ConnectRegistry(pszMachine, &hkeyMachine) );
  620. CWRg( IsNT4Machine(hkeyMachine, &fNT4) );
  621. //
  622. // open HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards
  623. //
  624. pszKey = fNT4 ? c_szNetworkCardsKey : c_szNetworkCardsNT5Key;
  625. CWRg( regkey.Open(hkeyMachine, pszKey, KEY_READ) );
  626. //
  627. // enumerate the subkeys, and for each key,
  628. // see if it's the one we want
  629. //
  630. CWRg( regkeyIter.Init(&regkey) );
  631. hrIter = regkeyIter.Next(&stKey);
  632. for (; hrIter == hrOK; hrIter = regkeyIter.Next(&stKey))
  633. {
  634. hr = hrOK;
  635. //
  636. // now open the key
  637. //
  638. regkeyCard.Close();
  639. dwErr = regkeyCard.Open(regkey, stKey, KEY_READ);
  640. if (dwErr != ERROR_SUCCESS)
  641. continue;
  642. ncreghelp.Initialize(fNT4, regkeyCard, stKey,
  643. pszMachine);
  644. //
  645. // read the ServiceName
  646. //
  647. //$NT5: the service name is not in the same format as NT4
  648. // this will need to be done differently.
  649. if (fNT4)
  650. {
  651. ncreghelp.ReadServiceName();
  652. if (dwErr != ERROR_SUCCESS)
  653. continue;
  654. stServiceName = ncreghelp.GetServiceName();
  655. }
  656. else
  657. stServiceName = pszKey;
  658. //
  659. // see if it's the one we're looking for
  660. //
  661. if (StriCmp(pszInterface, (LPCTSTR) stServiceName))
  662. {
  663. dwErr = ERROR_INVALID_HANDLE;
  664. continue;
  665. }
  666. //
  667. // this is the one; read the title
  668. //
  669. dwErr = ncreghelp.ReadTitle();
  670. if (dwErr != NO_ERROR)
  671. break;
  672. stTitle = (LPCTSTR) ncreghelp.GetTitle();
  673. *ppszTitle = StrDup((LPCTSTR) stTitle);
  674. }
  675. if (dwErr)
  676. hr = HRESULT_FROM_WIN32(dwErr);
  677. COM_PROTECT_ERROR_LABEL;
  678. }
  679. COM_PROTECT_CATCH;
  680. if (hkeyMachine)
  681. DisconnectRegistry(hkeyMachine);
  682. return hr;
  683. }
  684. /*!--------------------------------------------------------------------------
  685. RegFindRtrMgrTitle
  686. -
  687. This function retrieves the title of the given router-manager.
  688. The argument 'dwTransportId' should contain the ID of the router-manager,
  689. for instance PID_IP.
  690. Author: KennT
  691. ---------------------------------------------------------------------------*/
  692. STDMETHODIMP RegFindRtrMgrTitle(LPCTSTR pszMachine,
  693. DWORD dwTransportId,
  694. LPTSTR *ppszTitle)
  695. {
  696. HRESULT hr = hrOK;
  697. HKEY hkey, hkeyMachine = 0;
  698. RegKey regkey;
  699. CString stValue;
  700. COM_PROTECT_TRY
  701. {
  702. //
  703. // connect to the registry
  704. //
  705. CWRg( ConnectRegistry(pszMachine, &hkeyMachine) );
  706. //
  707. // open the key for the router-manager
  708. // under HKLM\Software\Microsoft\Router\RouterManagers
  709. //
  710. CORg( FindRmSoftwareKey(hkeyMachine, dwTransportId, &hkey, NULL) );
  711. regkey.Attach(hkey);
  712. //
  713. // Now find the "Title" value
  714. //
  715. CWRg( regkey.QueryValue( c_szTitle, stValue ) );
  716. // Copy the output data
  717. *ppszTitle = StrDup((LPCTSTR) stValue);
  718. COM_PROTECT_ERROR_LABEL;
  719. }
  720. COM_PROTECT_CATCH;
  721. if (hkeyMachine)
  722. DisconnectRegistry(hkeyMachine);
  723. return hr;
  724. }
  725. /*!--------------------------------------------------------------------------
  726. QueryRouterVersionInfo
  727. -
  728. Author: KennT
  729. ---------------------------------------------------------------------------*/
  730. TFSCORE_API(HRESULT) QueryRouterVersionInfo(HKEY hkeyMachine,
  731. RouterVersionInfo *pVerInfo)
  732. {
  733. // Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
  734. // CurrentVersion = REG_SZ "4.0"
  735. CString skey;
  736. DWORD dwErr;
  737. TCHAR szData[64];
  738. RegKey regkey;
  739. BOOL fNt4;
  740. DWORD dwMajorVer, dwMinorVer, dwBuildNumber;
  741. DWORD dwConfigured;
  742. DWORD dwSPVer = 0;
  743. DWORD dwOsFlags = 0;
  744. skey = c_szSoftware;
  745. skey += TEXT('\\');
  746. skey += c_szMicrosoft;
  747. skey += TEXT('\\');
  748. skey += c_szWindowsNT;
  749. skey += TEXT('\\');
  750. skey += c_szCurrentVersion;
  751. Assert(hkeyMachine != NULL);
  752. Assert(hkeyMachine != INVALID_HANDLE_VALUE);
  753. dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
  754. CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("IsNT4Machine"));
  755. if (dwErr != ERROR_SUCCESS)
  756. return HRESULT_FROM_WIN32(dwErr);
  757. // Ok, now try to get the current version value
  758. dwErr = regkey.QueryValue( c_szCurrentVersion, szData,
  759. sizeof(szData),
  760. FALSE);
  761. CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentVersion,
  762. _T("QueryRouterVersionInfo"));
  763. if (dwErr == ERROR_SUCCESS)
  764. {
  765. int nPos;
  766. int nLength;
  767. CString stData;
  768. stData = szData;
  769. nPos = stData.Find(_T('.'));
  770. nLength = stData.GetLength();
  771. // This assumes that
  772. // CurrentVersion : REG_SZ : Major.Minor.XX.XX
  773. // ------------------------------------------------------------
  774. // Pick out the major version from the string
  775. // ------------------------------------------------------------
  776. dwMajorVer = _ttoi(stData.Left(nPos));
  777. // Pick out the minor version
  778. // ------------------------------------------------------------
  779. dwMinorVer = _ttoi(stData.Right(nLength - nPos - 1));
  780. }
  781. // Get the build number
  782. // ----------------------------------------------------------------
  783. dwErr = regkey.QueryValue( c_szCurrentBuildNumber, szData,
  784. sizeof(szData),
  785. FALSE);
  786. if (dwErr == ERROR_SUCCESS)
  787. dwBuildNumber = _ttoi(szData);
  788. // If this is an NT4 machine, look for the Software\Microsoft\Router
  789. // registry key. If that doesn't exist, then this is a
  790. // non-Steelhead router.
  791. // ----------------------------------------------------------------
  792. if ((dwErr == ERROR_SUCCESS) && (dwMajorVer < 5))
  793. {
  794. RegKey regkeyRouter;
  795. dwErr = regkeyRouter.Open(hkeyMachine, c_szRegKeyRouter, KEY_READ);
  796. if (dwErr != ERROR_SUCCESS)
  797. dwOsFlags |= RouterSnapin_RASOnly;
  798. // Ignore the return code
  799. dwErr = ERROR_SUCCESS;
  800. }
  801. // Now get the SP version
  802. // ----------------------------------------------------------------
  803. dwErr = regkey.QueryValue( c_szCSDVersion, szData,
  804. sizeof(szData),
  805. FALSE);
  806. if (dwErr == ERROR_SUCCESS)
  807. dwSPVer = _ttoi(szData);
  808. dwErr = ERROR_SUCCESS; // this could fail, so ignore return code
  809. // Look at the router is configured flag
  810. // ----------------------------------------------------------------
  811. regkey.Close();
  812. if (ERROR_SUCCESS == regkey.Open(hkeyMachine,c_szRemoteAccessKey) )
  813. {
  814. dwErr = regkey.QueryValue( c_szRtrConfigured, dwConfigured);
  815. if (dwErr != ERROR_SUCCESS)
  816. dwConfigured = FALSE;
  817. // Ignore the return code
  818. dwErr = ERROR_SUCCESS;
  819. }
  820. if (dwErr == ERROR_SUCCESS)
  821. {
  822. pVerInfo->dwRouterVersion = dwMajorVer;
  823. pVerInfo->dwOsMajorVersion = dwMajorVer;
  824. pVerInfo->dwOsMinorVersion = dwMinorVer;
  825. pVerInfo->dwOsServicePack = dwSPVer;
  826. pVerInfo->dwOsFlags |= (1 | dwOsFlags);
  827. pVerInfo->dwRouterFlags = dwConfigured ? RouterSnapin_IsConfigured : 0;
  828. // If this is NT4, then the default is the router is configured
  829. if (dwMajorVer <= 4)
  830. pVerInfo->dwRouterFlags |= RouterSnapin_IsConfigured;
  831. pVerInfo->dwOsBuildNo = dwBuildNumber;
  832. }
  833. return HRESULT_FROM_WIN32(dwErr);
  834. }