Source code of Windows XP (NT5)
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.

400 lines
12 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: A D A P T E R. C P P
  7. //
  8. // Contents: Class installer functions for eumerated devices.
  9. //
  10. // Notes:
  11. //
  12. // Author: billbe 11 Nov 1996
  13. //
  14. //---------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "adapter.h"
  18. #include "benchmrk.h"
  19. #include "classinst.h"
  20. #include "ncreg.h"
  21. #include "ncsvc.h"
  22. #include "netcomm.h"
  23. VOID
  24. CiSetFriendlyNameIfNeeded(IN const COMPONENT_INSTALL_INFO &cii);
  25. //+--------------------------------------------------------------------------
  26. //
  27. // Function: HrCiGetBusInfoFromInf
  28. //
  29. // Purpose: Finds an adapter's bus information as listed in its inf
  30. // file.
  31. //
  32. // Arguments:
  33. // hinfFile [in] A handle to the component's inf file
  34. // szSectionName [in] The inf section to search in
  35. // peBusType [out] The bus type of the adapter
  36. // pulAdapterId [out] The AdapterId of the adapter (Eisa and Mca)
  37. // pulAdapterMask [out] The AdapterMask of the adapter (Eisa)
  38. //
  39. // Returns: HRESULT. S_OK if successful, error code otherwise
  40. //
  41. // Author: billbe 14 Jun 1997
  42. //
  43. // Notes:
  44. //
  45. HRESULT
  46. HrCiGetBusInfoFromInf (HINF hinfFile, COMPONENT_INSTALL_INFO* pcii)
  47. {
  48. HRESULT hr = S_OK;
  49. if (InterfaceTypeUndefined == pcii->BusType)
  50. {
  51. // Find the inf line that contains BusType and retrieve it
  52. DWORD dwBusType;
  53. hr = HrSetupGetFirstDword(hinfFile, pcii->pszSectionName,
  54. L"BusType", &dwBusType);
  55. if (S_OK == hr)
  56. {
  57. pcii->BusType = EInterfaceTypeFromDword(dwBusType);
  58. }
  59. else
  60. {
  61. TraceTag (ttidError, "Inf missing BusType field.");
  62. }
  63. }
  64. TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetBusInfoFromInf");
  65. return hr;
  66. }
  67. //+--------------------------------------------------------------------------
  68. //
  69. // Function: HrCiInstallEnumeratedComponent
  70. //
  71. // Purpose: This function completes the install of an enumerated
  72. // device.
  73. //
  74. // Arguments:
  75. // hinf [in] SetupApi handle to an inf file
  76. // hkeyInstance [in] The registry instance key of the adapter
  77. // during inf processing.
  78. // pcai [in] A structure containing the component information
  79. // See compinst.h for definition
  80. // hwndParent [in] The handle to the parent, for displaying UI
  81. // hdi [in] See Device Installer Api for more info
  82. // pdeid [in] See Device Installer Api for more info
  83. //
  84. // Returns: HRESULT. S_OK if successful and no restart required,
  85. // NETCFG_S_REBOOT if a reboot is required,
  86. // or error code otherwise
  87. //
  88. // Author: billbe 28 Apr 1997
  89. //
  90. // Notes:
  91. //
  92. HRESULT
  93. HrCiInstallEnumeratedComponent (
  94. IN HINF hinf,
  95. IN HKEY hkeyInstance,
  96. IN const COMPONENT_INSTALL_INFO& cii)
  97. {
  98. Assert (IsValidHandle (hinf));
  99. Assert (hkeyInstance);
  100. Assert (IsValidHandle (cii.hdi));
  101. Assert (cii.pdeid);
  102. HRESULT hr;
  103. // Because adapters can share descriptions, we may need to append
  104. // instance info so the user and other apps can differentiate.
  105. //
  106. // If the following fcn fails, we can still go on and
  107. // install the adapter.
  108. CiSetFriendlyNameIfNeeded (cii);
  109. // Is this a PCI multiport adapter where each port has the same
  110. // PnP Id? This is indicated by the inf value Port1DeviceNumber or
  111. // Port1FunctionNumber in the main section.
  112. //
  113. if (PCIBus == cii.BusType)
  114. {
  115. INFCONTEXT ctx;
  116. DWORD dwPortNumber;
  117. BOOL fUseDeviceNumber;
  118. DWORD dwFirstPort;
  119. hr = HrSetupGetFirstDword (hinf, cii.pszSectionName,
  120. L"Port1DeviceNumber", &dwFirstPort);
  121. if (S_OK == hr)
  122. {
  123. // The port number is based on the device number.
  124. fUseDeviceNumber = TRUE;
  125. }
  126. else
  127. {
  128. hr = HrSetupGetFirstDword (hinf, cii.pszSectionName,
  129. L"Port1FunctionNumber", &dwFirstPort);
  130. if (S_OK == hr)
  131. {
  132. // The port number is based on the function number.
  133. fUseDeviceNumber = FALSE;
  134. }
  135. }
  136. if (S_OK == hr)
  137. {
  138. // We have a mapping so now we need to get the address of the
  139. // device (device and function number).
  140. //
  141. DWORD dwAddress;
  142. hr = HrSetupDiGetDeviceRegistryProperty(cii.hdi, cii.pdeid,
  143. SPDRP_ADDRESS, NULL, (BYTE*)&dwAddress, sizeof(dwAddress),
  144. NULL);
  145. if (S_OK == hr)
  146. {
  147. // Use our mapping to get the correct port number.
  148. //
  149. DWORD dwPortLocation;
  150. dwPortLocation = fUseDeviceNumber ?
  151. HIWORD(dwAddress) : LOWORD(dwAddress);
  152. // Make sure the port location (either device or
  153. // function number) is greater than or equal to the first
  154. // port number, otherwise we will get a bogus port number.
  155. //
  156. if (dwPortLocation >= dwFirstPort)
  157. {
  158. dwPortNumber = dwPortLocation - dwFirstPort + 1;
  159. // Now store the port number in the device key for internal
  160. // consumption.
  161. HKEY hkeyDev;
  162. hr = HrSetupDiCreateDevRegKey (cii.hdi, cii.pdeid,
  163. DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL, &hkeyDev);
  164. if (S_OK == hr)
  165. {
  166. (VOID) HrRegSetDword (hkeyDev, L"Port", dwPortNumber);
  167. RegCloseKey (hkeyDev);
  168. }
  169. // Store the port in the driver key for public
  170. // consumption.
  171. //
  172. (VOID) HrRegSetDword (hkeyInstance, L"Port",
  173. dwPortNumber);
  174. }
  175. }
  176. }
  177. else
  178. {
  179. // No mapping available, so we won't display port number.
  180. hr = S_OK;
  181. }
  182. }
  183. // Update any advanced parameters that do not have a current value
  184. // with a default.
  185. UpdateAdvancedParametersIfNeeded (cii.hdi, cii.pdeid);
  186. // On fresh installs, INetCfg will be starting this adapter,
  187. // so we have to make sure we don't.
  188. //
  189. if (!cii.fPreviouslyInstalled)
  190. {
  191. (VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG,
  192. SDDFT_FLAGS, SDFBO_OR);
  193. }
  194. // Now finish the install of the adapter.
  195. //
  196. TraceTag(ttidClassInst, "Calling SetupDiInstallDevice");
  197. #ifdef ENABLETRACE
  198. CBenchmark bmrk;
  199. bmrk.Start("SetupDiInstallDevice");
  200. #endif //ENABLETRACE
  201. hr = HrSetupDiInstallDevice (cii.hdi, cii.pdeid);
  202. #ifdef ENABLETRACE
  203. bmrk.Stop();
  204. TraceTag(ttidBenchmark, "%s : %s seconds",
  205. bmrk.SznDescription(), bmrk.SznBenchmarkSeconds (2));
  206. #endif //ENABLETRACE
  207. if (!cii.fPreviouslyInstalled)
  208. {
  209. (VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG,
  210. SDDFT_FLAGS, SDFBO_XOR);
  211. }
  212. TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr,
  213. "HrCiInstallEnumeratedComponent");
  214. return hr;
  215. }
  216. //+--------------------------------------------------------------------------
  217. //
  218. // Function: HrCiRegOpenKeyFromEnumDevs
  219. //
  220. // Purpose: Enumerates through each device in an HDEVINFO and returns an
  221. // hkey to its driver key.
  222. //
  223. // Arguments:
  224. // hdi [in] See Device Installer Api
  225. // dwIndex [inout] The index of the device to retrieve
  226. // samDesired [in] The access level of the hkey
  227. // phkey [out] The device's driver key
  228. //
  229. // Returns: HRESULT. S_OK if successful, an error code otherwise
  230. //
  231. // Author: billbe 13 Jun 1997
  232. //
  233. // Notes:
  234. //
  235. HRESULT
  236. HrCiRegOpenKeyFromEnumDevs(HDEVINFO hdi, DWORD* pIndex, REGSAM samDesired,
  237. HKEY* phkey)
  238. {
  239. Assert(IsValidHandle(hdi));
  240. Assert (phkey);
  241. // Initialize output parameter.
  242. *phkey = NULL;
  243. SP_DEVINFO_DATA deid;
  244. HRESULT hr;
  245. // enumerate through the devices
  246. while ((S_OK == (hr = HrSetupDiEnumDeviceInfo(hdi, *pIndex, &deid))))
  247. {
  248. // open the adapter's instance key
  249. HRESULT hrT;
  250. hrT = HrSetupDiOpenDevRegKey(hdi, &deid, DICS_FLAG_GLOBAL,
  251. 0, DIREG_DRV, samDesired, phkey);
  252. if (S_OK == hrT)
  253. {
  254. break;
  255. }
  256. else
  257. {
  258. // If the key does not exists this is a phantom device,
  259. // (or if this device is hosed, we want to ignore it too)
  260. // move on to the next one and delete this one from
  261. // our list
  262. (*pIndex)++;
  263. (VOID)SetupDiDeleteDeviceInfo(hdi, &deid);
  264. }
  265. }
  266. TraceHr (ttidError, FAL, hr,
  267. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr,
  268. "HrCiRegOpenKeyFromEnumDevs");
  269. return hr;
  270. }
  271. ///////////////Legacy NT4 app support///////////////////////////////////
  272. VOID
  273. AddOrRemoveLegacyNt4AdapterKey (
  274. IN HDEVINFO hdi,
  275. IN PSP_DEVINFO_DATA pdeid,
  276. IN const GUID* pInstanceGuid,
  277. IN PCWSTR pszDescription,
  278. IN LEGACY_NT4_KEY_OP Op)
  279. {
  280. Assert (IsValidHandle (hdi));
  281. Assert (pdeid);
  282. Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pInstanceGuid));
  283. Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pszDescription));
  284. extern const WCHAR c_szRegKeyNt4Adapters[];
  285. const WCHAR c_szRegValDescription[] = L"Description";
  286. const WCHAR c_szRegValServiceName[] = L"ServiceName";
  287. PWSTR pszDriver;
  288. HRESULT hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc (
  289. hdi, pdeid, SPDRP_DRIVER, NULL, (BYTE**)&pszDriver);
  290. if (S_OK == hr)
  291. {
  292. PWSTR pszNumber = wcsrchr (pszDriver, L'\\');
  293. if (pszNumber && *(++pszNumber))
  294. {
  295. PWSTR pszStopString;
  296. ULONG Instance = 0;
  297. HKEY hkeyAdapters;
  298. Instance = wcstoul (pszNumber, &pszStopString, c_nBase10);
  299. // The NT4 key was one based so increment the instance number.
  300. Instance++;
  301. DWORD Disp;
  302. hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNt4Adapters,
  303. 0, KEY_WRITE, NULL, &hkeyAdapters, &Disp);
  304. if (S_OK == hr)
  305. {
  306. WCHAR szInstanceNumber [12];
  307. _snwprintf (szInstanceNumber, celems(szInstanceNumber) - 1,
  308. L"%d", Instance);
  309. HKEY hkeyInstance;
  310. if (LEGACY_NT4_KEY_ADD == Op)
  311. {
  312. hr = HrRegCreateKeyEx (hkeyAdapters, szInstanceNumber, 0,
  313. KEY_WRITE, NULL, &hkeyInstance, NULL);
  314. if (S_OK == hr)
  315. {
  316. WCHAR szGuid[c_cchGuidWithTerm];
  317. StringFromGUID2 (*pInstanceGuid, szGuid,
  318. c_cchGuidWithTerm);
  319. hr = HrRegSetValueEx (hkeyInstance,
  320. c_szRegValServiceName, REG_SZ,
  321. (const BYTE*)szGuid, sizeof (szGuid));
  322. TraceHr (ttidError, FAL, hr, FALSE,
  323. "AddAdapterToNt4Key: Setting Service Name "
  324. "in legacy registry");
  325. hr = HrRegSetValueEx (hkeyInstance,
  326. c_szRegValDescription, REG_SZ,
  327. (const BYTE*)pszDescription,
  328. CbOfSzAndTerm (pszDescription));
  329. TraceHr (ttidError, FAL, hr, FALSE,
  330. "AddAdapterToNt4Key: Setting Description in "
  331. "legacy registry");
  332. RegCloseKey (hkeyInstance);
  333. }
  334. }
  335. else
  336. {
  337. hr = HrRegDeleteKey (hkeyAdapters, szInstanceNumber);
  338. }
  339. RegCloseKey (hkeyAdapters);
  340. }
  341. }
  342. delete [] pszDriver;
  343. }
  344. }