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.

471 lines
14 KiB

  1. //
  2. // NicEnum.cpp
  3. //
  4. // NIC enumeration code, taken from JetNet (hardware group) and repurposed
  5. // for the Home Networking Wizard.
  6. //
  7. // History:
  8. //
  9. // 2/02/1999 KenSh Created for JetNet
  10. // 9/28/1999 KenSh Repurposed for Home Networking Wizard
  11. //
  12. #include "stdafx.h"
  13. #include "NetConn.h"
  14. #include "nconnwrap.h"
  15. #include "TheApp.h"
  16. // Local functions
  17. //
  18. HRESULT WINAPI DetectHardwareEx(const NETADAPTER* pAdapter);
  19. BOOL WINAPI IsNetAdapterEnabled(LPCSTR pszEnumKey);
  20. // EnumNetAdapters (public)
  21. //
  22. // Enumerates all network adapters installed on the system, allocates a structure
  23. // big enough to hold the information, and returns the number of adapters found.
  24. // Use NetConnFree() to free the allocated memory.
  25. //
  26. // History:
  27. //
  28. // 3/15/1999 KenSh Created
  29. // 3/25/1999 KenSh Added code to get Enum key for each adapter
  30. // 9/29/1999 KenSh Changed JetNetAlloc to NetConnAlloc
  31. //
  32. int WINAPI EnumNetAdapters(NETADAPTER** pprgNetAdapters)
  33. {
  34. CRegistry reg(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services\\Class\\Net"), KEY_READ, FALSE);
  35. DWORD cAdapters = 0;
  36. DWORD iKey;
  37. RegQueryInfoKey(reg.m_hKey, NULL, NULL, NULL, &cAdapters, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  38. NETADAPTER* prgNetAdapters = (NETADAPTER*)NetConnAlloc(sizeof(NETADAPTER) * cAdapters);
  39. if (prgNetAdapters == NULL)
  40. {
  41. cAdapters = 0;
  42. goto done;
  43. }
  44. ZeroMemory(prgNetAdapters, sizeof(NETADAPTER) * cAdapters);
  45. for (iKey = 0; iKey < cAdapters; iKey++)
  46. {
  47. NETADAPTER* pAdapter = &prgNetAdapters[iKey];
  48. pAdapter->bError = NICERR_NONE;
  49. pAdapter->bWarning = NICWARN_NONE;
  50. pAdapter->bNetSubType = SUBTYPE_NONE;
  51. lstrcpy(pAdapter->szClassKey, _T("Net\\"));
  52. static const int cchNet = _countof(_T("Net\\")) - 1;
  53. DWORD cbPnpID = _countof(pAdapter->szClassKey) - cchNet;
  54. if (ERROR_SUCCESS != RegEnumKeyEx(reg.m_hKey, iKey, pAdapter->szClassKey + cchNet, &cbPnpID, NULL, NULL, NULL, NULL))
  55. {
  56. pAdapter->bError = NICERR_BANGED;
  57. continue;
  58. }
  59. CRegistry reg2;
  60. if (!reg2.OpenKey(reg.m_hKey, pAdapter->szClassKey + cchNet, KEY_READ))
  61. {
  62. pAdapter->bError = NICERR_BANGED;
  63. continue;
  64. }
  65. // VERIFIED: Win95 gold, Win98 gold
  66. reg2.QueryStringValue(_T("DriverDesc"), pAdapter->szDisplayName, _countof(pAdapter->szDisplayName));
  67. CRegistry reg3;
  68. if (!reg3.OpenKey(reg2.m_hKey, _T("Ndi"), KEY_READ))
  69. {
  70. pAdapter->bError = NICERR_BANGED;
  71. continue;
  72. }
  73. if (reg2.QueryStringValue(_T("DisableWarning"), NULL, NULL))
  74. {
  75. pAdapter->bWarning = NICWARN_WARNING;
  76. }
  77. // VERIFIED: Win95 gold, Win98 gold
  78. reg2.QueryStringValue(_T("InfPath"), pAdapter->szInfFileName, _countof(pAdapter->szInfFileName));
  79. // VERIFIED: Win95 gold, Win98 gold
  80. reg3.QueryStringValue(_T("DeviceId"), pAdapter->szDeviceID, _countof(pAdapter->szDeviceID));
  81. // Get the name of the driver provider, not the manufacturer
  82. // We will replace with actual mfr name, if any, when we open the enum key
  83. reg2.QueryStringValue(_T("ProviderName"), pAdapter->szManufacturer, _countof(pAdapter->szManufacturer));
  84. // Check for supported interfaces to determine the network type
  85. CRegistry reg4;
  86. TCHAR szLower[60];
  87. szLower[0] = _T('\0');
  88. if (reg4.OpenKey(reg3.m_hKey, _T("Interfaces"), KEY_READ))
  89. {
  90. // REVIEW: should we check LowerRange instead?
  91. reg4.QueryStringValue(_T("Lower"), szLower, _countof(szLower));
  92. }
  93. // Figure out the network adapter type (NIC, Dial-Up, etc.)
  94. // Default is NETTYPE_LAN (which is automatically set since it's 0)
  95. if (strstr(szLower, _T("vcomm")))
  96. {
  97. pAdapter->bNetType = NETTYPE_DIALUP;
  98. }
  99. else if (strstr(szLower, _T("pptp")))
  100. {
  101. pAdapter->bNetType = NETTYPE_PPTP;
  102. }
  103. else if (strstr(szLower, _T("isdn")))
  104. {
  105. pAdapter->bNetType = NETTYPE_ISDN;
  106. }
  107. else if (strstr(szLower, _T("NabtsIp")) || strstr(szLower, _T("nabtsip")))
  108. {
  109. pAdapter->bNetType = NETTYPE_TV;
  110. pAdapter->bNicType = NIC_VIRTUAL;
  111. }
  112. else
  113. {
  114. TCHAR szBuf[80];
  115. // Check for IrDA adapter
  116. // VERIFIED: Win98 OSR1
  117. if (reg3.QueryStringValue(_T("NdiInstaller"), szBuf, _countof(szBuf)))
  118. {
  119. LPTSTR pchComma = strchr(szBuf, ',');
  120. if (pchComma != NULL)
  121. {
  122. *pchComma = _T('\0');
  123. if (!lstrcmpi(szBuf, _T("ir_ndi.dll")))
  124. {
  125. pAdapter->bNetType = NETTYPE_IRDA;
  126. }
  127. }
  128. }
  129. }
  130. // Determine if card is ISA, PCI, PCMCIA, etc.
  131. if (pAdapter->szDeviceID[0] == _T('*'))
  132. {
  133. if (strstr(szLower, _T("ethernet")))
  134. {
  135. if (0 == memcmp(pAdapter->szDeviceID, _T("*AOL"), 4))
  136. {
  137. pAdapter->bNicType = NIC_VIRTUAL;
  138. pAdapter->bNetSubType = SUBTYPE_AOL;
  139. }
  140. else
  141. {
  142. pAdapter->bNicType = NIC_UNKNOWN;
  143. }
  144. }
  145. else
  146. {
  147. pAdapter->bNicType = NIC_VIRTUAL;
  148. }
  149. }
  150. else if (0 == memcmp(pAdapter->szDeviceID, _T("PCMCIA\\"), _lengthof("PCMCIA\\")))
  151. {
  152. pAdapter->bNicType = NIC_PCMCIA;
  153. }
  154. else if (0 == memcmp(pAdapter->szDeviceID, _T("PCI\\"), _lengthof("PCI\\")))
  155. {
  156. pAdapter->bNicType = NIC_PCI;
  157. }
  158. else if (0 == memcmp(pAdapter->szDeviceID, _T("ISAPNP\\"), _lengthof("ISAPNP\\")))
  159. {
  160. pAdapter->bNicType = NIC_ISA;
  161. }
  162. else if (0 == memcmp(pAdapter->szDeviceID, _T("USB\\"), _lengthof("USB\\")))
  163. {
  164. pAdapter->bNicType = NIC_USB;
  165. }
  166. else if (0 == memcmp(pAdapter->szDeviceID, _T("LPTENUM\\"), _lengthof("LPTENUM\\")))
  167. {
  168. pAdapter->bNicType = NIC_PARALLEL;
  169. }
  170. else if (0 == memcmp(pAdapter->szDeviceID, _T("MF\\"), _lengthof("MF\\")))
  171. {
  172. pAdapter->bNicType = NIC_MF;
  173. }
  174. else if (0 == memcmp(pAdapter->szDeviceID, _T("V1394\\"), _lengthof("V1394\\")))
  175. {
  176. pAdapter->bNicType = NIC_1394;
  177. }
  178. else if (0 == lstrcmpi(pAdapter->szDeviceID, _T("ICSHARE")))
  179. {
  180. pAdapter->bNicType = NIC_VIRTUAL;
  181. pAdapter->bNetSubType = SUBTYPE_ICS;
  182. }
  183. // TODO: remove this code, replace with IcsIsExternalAdapter and IcsIsInternalAdapter
  184. // Check if this adapter is used by ICS
  185. {
  186. pAdapter->bIcsStatus = ICS_NONE;
  187. LPCSTR pszAdapterNumber = pAdapter->szClassKey + cchNet;
  188. TCHAR szBuf[10];
  189. CRegistry regIcs;
  190. if (regIcs.OpenKey(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services\\ICSharing\\Settings\\General"), KEY_QUERY_VALUE))
  191. {
  192. if (regIcs.QueryStringValue(_T("ExternalAdapterReg"), szBuf, _countof(szBuf)))
  193. {
  194. if (0 == lstrcmp(szBuf, pszAdapterNumber))
  195. {
  196. pAdapter->bIcsStatus = ICS_EXTERNAL;
  197. }
  198. }
  199. // TODO: allow > 1 internal adapter
  200. if (regIcs.QueryStringValue(_T("InternalAdapterReg"), szBuf, _countof(szBuf)))
  201. {
  202. if (0 == lstrcmp(szBuf, pszAdapterNumber))
  203. {
  204. pAdapter->bIcsStatus = ICS_INTERNAL;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. // Snip out any adapters that turned out to be invalid
  211. cAdapters = iKey;
  212. if (cAdapters == 0)
  213. {
  214. NetConnFree(prgNetAdapters);
  215. prgNetAdapters = NULL;
  216. goto done;
  217. }
  218. //
  219. // Walk the registry Enum key to find full enum key for each adapter
  220. //
  221. if (reg.OpenKey(HKEY_LOCAL_MACHINE, _T("Enum"), KEY_READ))
  222. {
  223. TCHAR szSubKey[MAX_PATH];
  224. DWORD cbSubKey;
  225. TCHAR szDevEnumKey[MAX_PATH];
  226. int cchDevEnumKey1; // length of "PCI\"
  227. int cchDevEnumKey2; // length of "PCI\VEN_10B7&DEV_9050&SUBSYS_00000000&REV_00\"
  228. for (DWORD iEnumKey = 0; ; iEnumKey++)
  229. {
  230. cbSubKey = _countof(szSubKey);
  231. if (ERROR_SUCCESS != RegEnumKeyEx(reg.m_hKey, iEnumKey, szSubKey, &cbSubKey, NULL, NULL, NULL, NULL))
  232. break;
  233. // Start building DevEnumKey e.g. "PCI\"
  234. lstrcpy(szDevEnumKey, szSubKey);
  235. cchDevEnumKey1 = (int)cbSubKey;
  236. szDevEnumKey[cchDevEnumKey1++] = _T('\\');
  237. CRegistry reg2;
  238. if (!reg2.OpenKey(reg.m_hKey, szSubKey, KEY_READ)) // e.g. "Enum\PCI"
  239. continue;
  240. for (DWORD iEnumKey2 = 0; ; iEnumKey2++)
  241. {
  242. cbSubKey = _countof(szSubKey);
  243. if (ERROR_SUCCESS != RegEnumKeyEx(reg2.m_hKey, iEnumKey2, szSubKey, &cbSubKey, NULL, NULL, NULL, NULL))
  244. break;
  245. // Continue building DevEnumKey e.g. "PCI\VEN_10B7&DEV_9050&SUBSYS_00000000&REV_00\"
  246. lstrcpy(szDevEnumKey + cchDevEnumKey1, szSubKey);
  247. cchDevEnumKey2 = cchDevEnumKey1 + (int)cbSubKey;
  248. szDevEnumKey[cchDevEnumKey2++] = _T('\\');
  249. CRegistry reg3;
  250. if (!reg3.OpenKey(reg2.m_hKey, szSubKey, KEY_READ)) // e.g. "Enum\PCI\VEN_10B7&DEV_9050&SUBSYS_00000000&REV_00"
  251. continue;
  252. for (DWORD iEnumKey3 = 0; ; iEnumKey3++)
  253. {
  254. cbSubKey = _countof(szSubKey);
  255. if (ERROR_SUCCESS != RegEnumKeyEx(reg3.m_hKey, iEnumKey3, szSubKey, &cbSubKey, NULL, NULL, NULL, NULL))
  256. break;
  257. // Finish building DevEnumKey e.g. "PCI\VEN_10B7&DEV_9050&SUBSYS_00000000&REV_00\407000"
  258. lstrcpy(szDevEnumKey + cchDevEnumKey2, szSubKey);
  259. CRegistry regLeaf;
  260. if (!regLeaf.OpenKey(reg3.m_hKey, szSubKey, KEY_READ)) // e.g. "Enum\PCI\VEN_10B7&DEV_9050&SUBSYS_00000000&REV_00\407000"
  261. continue;
  262. if (!regLeaf.QueryStringValue(_T("Driver"), szSubKey, _countof(szSubKey)))
  263. continue;
  264. //
  265. // See if the device matches one of our NICs
  266. //
  267. for (DWORD iAdapter = 0; iAdapter < cAdapters; iAdapter++)
  268. {
  269. NETADAPTER* pAdapter = &prgNetAdapters[iAdapter];
  270. if (0 != lstrcmpi(szSubKey, pAdapter->szClassKey))
  271. continue; // doesn't match
  272. lstrcpy(pAdapter->szEnumKey, _T("Enum\\"));
  273. lstrcpyn(pAdapter->szEnumKey + 5, szDevEnumKey, _countof(pAdapter->szEnumKey) - 5);
  274. if (regLeaf.QueryStringValue(_T("Mfg"), szSubKey, _countof(szSubKey)))
  275. lstrcpyn(pAdapter->szManufacturer, szSubKey, _countof(pAdapter->szManufacturer));
  276. if (regLeaf.QueryStringValue(_T("DeviceDesc"), szSubKey, _countof(szSubKey)))
  277. {
  278. lstrcpyn(pAdapter->szDisplayName, szSubKey, _countof(pAdapter->szDisplayName));
  279. // Detect more special types of adapters here
  280. if (pAdapter->bNetType == NETTYPE_DIALUP)
  281. {
  282. if (strstr(pAdapter->szDisplayName, _T("VPN")) ||
  283. strstr(pAdapter->szDisplayName, _T("#2")))
  284. {
  285. pAdapter->bNetSubType = SUBTYPE_VPN;
  286. }
  287. }
  288. }
  289. break; // found a match, so stop looking
  290. }
  291. }
  292. }
  293. }
  294. }
  295. // For all adapters that we think are present, check to see if they're
  296. // actually present
  297. DWORD iAdapter;
  298. for (iAdapter = 0; iAdapter < cAdapters; iAdapter++)
  299. {
  300. NETADAPTER* pAdapter = &prgNetAdapters[iAdapter];
  301. GetNetAdapterDevNode(pAdapter);
  302. // No enum key -> bad (JetNet bug 1234)
  303. if (pAdapter->szEnumKey[0] == _T('\0'))
  304. {
  305. pAdapter->bError = NICERR_CORRUPT;
  306. }
  307. // REVIEW: could still check if "broken" adapters are present
  308. if (pAdapter->bNicType != NIC_VIRTUAL && pAdapter->bError == NICERR_NONE)
  309. {
  310. HRESULT hrDetect = DetectHardwareEx(pAdapter);
  311. if (hrDetect == S_FALSE)
  312. {
  313. pAdapter->bError = NICERR_MISSING;
  314. }
  315. else if (hrDetect == S_OK)
  316. {
  317. // Is the adapter disabled?
  318. if (!IsNetAdapterEnabled(pAdapter->szEnumKey))
  319. {
  320. pAdapter->bError = NICERR_DISABLED;
  321. }
  322. else if (IsNetAdapterBroken(pAdapter))
  323. {
  324. pAdapter->bError = NICERR_BANGED;
  325. }
  326. }
  327. }
  328. }
  329. done:
  330. *pprgNetAdapters = prgNetAdapters;
  331. return (int)cAdapters;
  332. }
  333. // Gets the name of the VxD from the registry, e.g. "3c19250.sys".
  334. // Returns S_OK if the name was retrieved.
  335. // Returns E_FAIL if the name was not retrieved, and sets pszBuf to an empty string.
  336. HRESULT WINAPI GetNetAdapterDeviceVxDs(const NETADAPTER* pAdapter, LPSTR pszBuf, int cchBuf)
  337. {
  338. CRegistry reg(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services\\Class"), KEY_READ, FALSE);
  339. if (reg.OpenSubKey(pAdapter->szClassKey, KEY_READ))
  340. {
  341. if (reg.QueryStringValue(_T("DeviceVxDs"), pszBuf, cchBuf))
  342. {
  343. return S_OK;
  344. }
  345. }
  346. *pszBuf = '\0';
  347. return E_FAIL;
  348. }
  349. // Returns S_OK if the NIC is present, S_FALSE if not, or an error code if the test failed
  350. HRESULT WINAPI DetectHardware(LPCSTR pszDeviceID)
  351. {
  352. // Just thunk down to the 16-bit version which uses DiGetClassDevs
  353. HRESULT hr = FindClassDev16(NULL, _T("Net"), pszDeviceID);
  354. return hr;
  355. }
  356. HRESULT WINAPI DetectHardwareEx(const NETADAPTER* pAdapter)
  357. {
  358. // Hack: always assume IRDA adapters are present, since HW detection doesn't
  359. // work on them -ks 8/8/99
  360. // TODO: see if this is fixed in the updated DetectHardware() -ks 9/28/1999
  361. // if (pAdapter->bNetType == NETTYPE_IRDA)
  362. // return S_OK;
  363. // Hack: always assume unknown NIC types are present, since HW detection
  364. // doesn't work on them (JetNet bug 1264 - Intel AnyPoint Parallel Port Adapter)
  365. // TODO: see if this is fixed in the updated DetectHardware() -ks 9/28/1999
  366. // if (pAdapter->bNicType == NIC_UNKNOWN)
  367. // return S_OK;
  368. // Hack: work around Millennium bug 123237, which says that hardware detection
  369. // fails for NICs using the Dc21x4.sys driver. I never got a chance to track
  370. // down the cause of the failure, so I'm cheating instead. -ks 1/13/2000
  371. TCHAR szBuf[100];
  372. GetNetAdapterDeviceVxDs(pAdapter, szBuf, _countof(szBuf));
  373. if (0 == lstrcmpi(szBuf, _T("dc21x4.sys")))
  374. return S_OK;
  375. return DetectHardware(pAdapter->szDeviceID);
  376. }
  377. BOOL OpenConfigKey(CRegistry& reg, LPCSTR pszSubKey, REGSAM dwAccess)
  378. {
  379. if (reg.OpenKey(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\IDConfigDB", KEY_QUERY_VALUE))
  380. {
  381. TCHAR szConfigNumber[20];
  382. if (reg.QueryStringValue("CurrentConfig", szConfigNumber, _countof(szConfigNumber)))
  383. {
  384. TCHAR szRegKey[300];
  385. wsprintf(szRegKey, "Config\\%s\\%s", szConfigNumber, pszSubKey);
  386. if (reg.OpenKey(HKEY_LOCAL_MACHINE, szRegKey, dwAccess))
  387. {
  388. return TRUE;
  389. }
  390. }
  391. }
  392. return FALSE;
  393. }
  394. BOOL WINAPI IsNetAdapterEnabled(LPCSTR pszEnumKey)
  395. {
  396. BOOL bEnabled = TRUE; // assume enabled if reg keys are missing
  397. CRegistry reg;
  398. if (OpenConfigKey(reg, pszEnumKey, KEY_QUERY_VALUE))
  399. {
  400. DWORD dwDisabled;
  401. if (reg.QueryDwordValue("CSConfigFlags", &dwDisabled))
  402. {
  403. bEnabled = (dwDisabled == 0);
  404. }
  405. }
  406. return bEnabled;
  407. }