//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999. // // File: A D A P T E R. C P P // // Contents: Class installer functions for eumerated devices. // // Notes: // // Author: billbe 11 Nov 1996 // //--------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "adapter.h" #include "benchmrk.h" #include "classinst.h" #include "ncreg.h" #include "ncsvc.h" #include "netcomm.h" VOID CiSetFriendlyNameIfNeeded(IN const COMPONENT_INSTALL_INFO &cii); //+-------------------------------------------------------------------------- // // Function: HrCiGetBusInfoFromInf // // Purpose: Finds an adapter's bus information as listed in its inf // file. // // Arguments: // hinfFile [in] A handle to the component's inf file // szSectionName [in] The inf section to search in // peBusType [out] The bus type of the adapter // pulAdapterId [out] The AdapterId of the adapter (Eisa and Mca) // pulAdapterMask [out] The AdapterMask of the adapter (Eisa) // // Returns: HRESULT. S_OK if successful, error code otherwise // // Author: billbe 14 Jun 1997 // // Notes: // HRESULT HrCiGetBusInfoFromInf (HINF hinfFile, COMPONENT_INSTALL_INFO* pcii) { HRESULT hr = S_OK; if (InterfaceTypeUndefined == pcii->BusType) { // Find the inf line that contains BusType and retrieve it DWORD dwBusType; hr = HrSetupGetFirstDword(hinfFile, pcii->pszSectionName, L"BusType", &dwBusType); if (S_OK == hr) { pcii->BusType = EInterfaceTypeFromDword(dwBusType); } else { TraceTag (ttidError, "Inf missing BusType field."); } } TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetBusInfoFromInf"); return hr; } //+-------------------------------------------------------------------------- // // Function: HrCiInstallEnumeratedComponent // // Purpose: This function completes the install of an enumerated // device. // // Arguments: // hinf [in] SetupApi handle to an inf file // hkeyInstance [in] The registry instance key of the adapter // during inf processing. // pcai [in] A structure containing the component information // See compinst.h for definition // hwndParent [in] The handle to the parent, for displaying UI // hdi [in] See Device Installer Api for more info // pdeid [in] See Device Installer Api for more info // // Returns: HRESULT. S_OK if successful and no restart required, // NETCFG_S_REBOOT if a reboot is required, // or error code otherwise // // Author: billbe 28 Apr 1997 // // Notes: // HRESULT HrCiInstallEnumeratedComponent ( IN HINF hinf, IN HKEY hkeyInstance, IN const COMPONENT_INSTALL_INFO& cii) { Assert (IsValidHandle (hinf)); Assert (hkeyInstance); Assert (IsValidHandle (cii.hdi)); Assert (cii.pdeid); HRESULT hr; // Because adapters can share descriptions, we may need to append // instance info so the user and other apps can differentiate. // // If the following fcn fails, we can still go on and // install the adapter. CiSetFriendlyNameIfNeeded (cii); // Is this a PCI multiport adapter where each port has the same // PnP Id? This is indicated by the inf value Port1DeviceNumber or // Port1FunctionNumber in the main section. // if (PCIBus == cii.BusType) { INFCONTEXT ctx; DWORD dwPortNumber; BOOL fUseDeviceNumber; DWORD dwFirstPort; hr = HrSetupGetFirstDword (hinf, cii.pszSectionName, L"Port1DeviceNumber", &dwFirstPort); if (S_OK == hr) { // The port number is based on the device number. fUseDeviceNumber = TRUE; } else { hr = HrSetupGetFirstDword (hinf, cii.pszSectionName, L"Port1FunctionNumber", &dwFirstPort); if (S_OK == hr) { // The port number is based on the function number. fUseDeviceNumber = FALSE; } } if (S_OK == hr) { // We have a mapping so now we need to get the address of the // device (device and function number). // DWORD dwAddress; hr = HrSetupDiGetDeviceRegistryProperty(cii.hdi, cii.pdeid, SPDRP_ADDRESS, NULL, (BYTE*)&dwAddress, sizeof(dwAddress), NULL); if (S_OK == hr) { // Use our mapping to get the correct port number. // DWORD dwPortLocation; dwPortLocation = fUseDeviceNumber ? HIWORD(dwAddress) : LOWORD(dwAddress); // Make sure the port location (either device or // function number) is greater than or equal to the first // port number, otherwise we will get a bogus port number. // if (dwPortLocation >= dwFirstPort) { dwPortNumber = dwPortLocation - dwFirstPort + 1; // Now store the port number in the device key for internal // consumption. HKEY hkeyDev; hr = HrSetupDiCreateDevRegKey (cii.hdi, cii.pdeid, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL, &hkeyDev); if (S_OK == hr) { (VOID) HrRegSetDword (hkeyDev, L"Port", dwPortNumber); RegCloseKey (hkeyDev); } // Store the port in the driver key for public // consumption. // (VOID) HrRegSetDword (hkeyInstance, L"Port", dwPortNumber); } } } else { // No mapping available, so we won't display port number. hr = S_OK; } } // Update any advanced parameters that do not have a current value // with a default. UpdateAdvancedParametersIfNeeded (cii.hdi, cii.pdeid); // On fresh installs, INetCfg will be starting this adapter, // so we have to make sure we don't. // if (!cii.fPreviouslyInstalled) { (VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG, SDDFT_FLAGS, SDFBO_OR); } // Now finish the install of the adapter. // TraceTag(ttidClassInst, "Calling SetupDiInstallDevice"); #ifdef ENABLETRACE CBenchmark bmrk; bmrk.Start("SetupDiInstallDevice"); #endif //ENABLETRACE hr = HrSetupDiInstallDevice (cii.hdi, cii.pdeid); #ifdef ENABLETRACE bmrk.Stop(); TraceTag(ttidBenchmark, "%s : %s seconds", bmrk.SznDescription(), bmrk.SznBenchmarkSeconds (2)); #endif //ENABLETRACE if (!cii.fPreviouslyInstalled) { (VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG, SDDFT_FLAGS, SDFBO_XOR); } TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr, "HrCiInstallEnumeratedComponent"); return hr; } //+-------------------------------------------------------------------------- // // Function: HrCiRegOpenKeyFromEnumDevs // // Purpose: Enumerates through each device in an HDEVINFO and returns an // hkey to its driver key. // // Arguments: // hdi [in] See Device Installer Api // dwIndex [inout] The index of the device to retrieve // samDesired [in] The access level of the hkey // phkey [out] The device's driver key // // Returns: HRESULT. S_OK if successful, an error code otherwise // // Author: billbe 13 Jun 1997 // // Notes: // HRESULT HrCiRegOpenKeyFromEnumDevs(HDEVINFO hdi, DWORD* pIndex, REGSAM samDesired, HKEY* phkey) { Assert(IsValidHandle(hdi)); Assert (phkey); // Initialize output parameter. *phkey = NULL; SP_DEVINFO_DATA deid; HRESULT hr; // enumerate through the devices while ((S_OK == (hr = HrSetupDiEnumDeviceInfo(hdi, *pIndex, &deid)))) { // open the adapter's instance key HRESULT hrT; hrT = HrSetupDiOpenDevRegKey(hdi, &deid, DICS_FLAG_GLOBAL, 0, DIREG_DRV, samDesired, phkey); if (S_OK == hrT) { break; } else { // If the key does not exists this is a phantom device, // (or if this device is hosed, we want to ignore it too) // move on to the next one and delete this one from // our list (*pIndex)++; (VOID)SetupDiDeleteDeviceInfo(hdi, &deid); } } TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr, "HrCiRegOpenKeyFromEnumDevs"); return hr; } ///////////////Legacy NT4 app support/////////////////////////////////// VOID AddOrRemoveLegacyNt4AdapterKey ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN const GUID* pInstanceGuid, IN PCWSTR pszDescription, IN LEGACY_NT4_KEY_OP Op) { Assert (IsValidHandle (hdi)); Assert (pdeid); Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pInstanceGuid)); Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pszDescription)); extern const WCHAR c_szRegKeyNt4Adapters[]; const WCHAR c_szRegValDescription[] = L"Description"; const WCHAR c_szRegValServiceName[] = L"ServiceName"; PWSTR pszDriver; HRESULT hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc ( hdi, pdeid, SPDRP_DRIVER, NULL, (BYTE**)&pszDriver); if (S_OK == hr) { PWSTR pszNumber = wcsrchr (pszDriver, L'\\'); if (pszNumber && *(++pszNumber)) { PWSTR pszStopString; ULONG Instance = 0; HKEY hkeyAdapters; Instance = wcstoul (pszNumber, &pszStopString, c_nBase10); // The NT4 key was one based so increment the instance number. Instance++; DWORD Disp; hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNt4Adapters, 0, KEY_WRITE, NULL, &hkeyAdapters, &Disp); if (S_OK == hr) { WCHAR szInstanceNumber [12]; _snwprintf (szInstanceNumber, celems(szInstanceNumber) - 1, L"%d", Instance); HKEY hkeyInstance; if (LEGACY_NT4_KEY_ADD == Op) { hr = HrRegCreateKeyEx (hkeyAdapters, szInstanceNumber, 0, KEY_WRITE, NULL, &hkeyInstance, NULL); if (S_OK == hr) { WCHAR szGuid[c_cchGuidWithTerm]; StringFromGUID2 (*pInstanceGuid, szGuid, c_cchGuidWithTerm); hr = HrRegSetValueEx (hkeyInstance, c_szRegValServiceName, REG_SZ, (const BYTE*)szGuid, sizeof (szGuid)); TraceHr (ttidError, FAL, hr, FALSE, "AddAdapterToNt4Key: Setting Service Name " "in legacy registry"); hr = HrRegSetValueEx (hkeyInstance, c_szRegValDescription, REG_SZ, (const BYTE*)pszDescription, CbOfSzAndTerm (pszDescription)); TraceHr (ttidError, FAL, hr, FALSE, "AddAdapterToNt4Key: Setting Description in " "legacy registry"); RegCloseKey (hkeyInstance); } } else { hr = HrRegDeleteKey (hkeyAdapters, szInstanceNumber); } RegCloseKey (hkeyAdapters); } } delete [] pszDriver; } }