extern "C" DWORD InstallLoopBack(LPCTSTR pConnectionName, LPCTSTR ip, LPCTSTR mask) { BOOL ok; DWORD ret = 0; GUID netGuid; HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DeviceInfoData; SP_DRVINFO_DATA DriverInfoData; SP_DEVINSTALL_PARAMS DeviceInstallParams; TCHAR className[MAX_PATH]; TCHAR temp[MAX_PATH]; DWORD index = 0; BOOL found = FALSE; BOOL registered = FALSE; BOOL destroyList = FALSE; PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail; DWORD detailBuf[2048]; // for our purposes, 8k buffer is more // than enough to obtain the hardware ID // of the loopback driver. HKEY hkey = NULL; DWORD cbSize; DWORD dwValueType; TCHAR pCfgGuidString[40]; // initialize the structure size DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); // copy the net class GUID memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET)); // create an empty device info set associated with the net class GUID hDeviceInfo = SetupDiCreateDeviceInfoList(&netGuid, NULL); if (hDeviceInfo == INVALID_HANDLE_VALUE) return GetLastError(); // get the class name from GUID ok = SetupDiClassNameFromGuid(&netGuid, className, MAX_PATH, NULL); if (!ok) { ret = GetLastError(); goto cleanup; } // create a device info element and add the new device instance // key to registry ok = SetupDiCreateDeviceInfo(hDeviceInfo, className, &netGuid, NULL, NULL, DICD_GENERATE_ID, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // select the newly created device info to be the currently // selected member ok = SetupDiSetSelectedDevice(hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // build a list of class drivers ok = SetupDiBuildDriverInfoList(hDeviceInfo, &DeviceInfoData, SPDIT_CLASSDRIVER); if (!ok) { ret = GetLastError(); goto cleanup; } destroyList = TRUE; // enumerate the driver info list while (TRUE) { BOOL ret; ret = SetupDiEnumDriverInfo(hDeviceInfo, &DeviceInfoData, SPDIT_CLASSDRIVER, index, &DriverInfoData); // if the function failed and GetLastError() returned // ERROR_NO_MORE_ITEMS, then we have reached the end of the // list. Othewise there was something wrong with this // particular driver. if(!ret) { if(GetLastError() == ERROR_NO_MORE_ITEMS) break; else { index++; continue; } } pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf; pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); // if we successfully find the hardware ID and it turns out to // be the one for the loopback driver, then we are done. if (SetupDiGetDriverInfoDetail(hDeviceInfo, &DeviceInfoData, &DriverInfoData, pDriverInfoDetail, sizeof(detailBuf), NULL)) { TCHAR * t; // pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the // whole list and see if there is a match somewhere. t = pDriverInfoDetail->HardwareID; while (t && *t && t < (TCHAR *) &detailBuf[sizeof(detailBuf)/sizeof(detailBuf[0])]) { if (!_tcsicmp(t, DRIVERHWID)) break; t += _tcslen(t) + 1; } if (t && *t && t < (TCHAR *) &detailBuf[sizeof(detailBuf)/sizeof(detailBuf[0])]) { found = TRUE; break; } } index++; } if (!found) { ret = GetLastError(); ReportMessage(0,"Could not find the driver to install", DRIVER_DESC, NULL, 0); goto cleanup; } // set the loopback driver to be the currently selected ok = SetupDiSetSelectedDriver(hDeviceInfo, &DeviceInfoData, &DriverInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // register the phantom device to repare for install ok = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // registered, but remove if errors occur in the following code registered = TRUE; // ask the installer if we can install the device ok = SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); if (ret != ERROR_DI_DO_DEFAULT) { goto cleanup; } else ret = 0; } // install the files first ok = SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // get the device install parameters and disable filecopy DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); ok = SetupDiGetDeviceInstallParams(hDeviceInfo, &DeviceInfoData, &DeviceInstallParams); if (ok) { DeviceInstallParams.Flags |= DI_NOFILECOPY; ok = SetupDiSetDeviceInstallParams(hDeviceInfo, &DeviceInfoData, &DeviceInstallParams); if (!ok) { ret = GetLastError(); goto cleanup; } } // // Register any device-specific co-installers for this device, // ok = SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } // // install any installer-specified interfaces. // and then do the real install // ok = SetupDiCallClassInstaller(DIF_INSTALLINTERFACES, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); goto cleanup; } PAUSE; ok = SetupDiCallClassInstaller(DIF_INSTALLDEVICE, hDeviceInfo, &DeviceInfoData); if (!ok) { ret = GetLastError(); PAUSE; goto cleanup; } /* Skip to the end if we aren't setting the name */ if (!pConnectionName) goto cleanup; // Figure out NetCfgInstanceId hkey = SetupDiOpenDevRegKey(hDeviceInfo, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); if (hkey == INVALID_HANDLE_VALUE) { ret = GetLastError(); goto cleanup; } cbSize = sizeof(pCfgGuidString); ret = RegQueryValueEx(hkey, _T("NetCfgInstanceId"), NULL, &dwValueType, (LPBYTE)pCfgGuidString, &cbSize); RegCloseKey(hkey); ret = RenameConnection(pCfgGuidString, pConnectionName); if (ret) { ReportMessage(0,"Could not set the connection name", NULL, pConnectionName, 0); goto cleanup; } if (!ip) goto cleanup; ret = SetIpAddress(pCfgGuidString, ip, mask); if (ret) { ReportMessage(0,"Could not set the ip address and network mask",NULL,NULL,ret); goto cleanup; } ret = LoopbackBindings(pCfgGuidString); if (ret) { ReportMessage(0,"Could not properly set the bindings",NULL,NULL,0); goto cleanup; } ret = !UpdateHostsFile( pConnectionName, ip, "hosts", FALSE ); if (ret) { ReportMessage(0,"Could not update hosts file",NULL,NULL,0); goto cleanup; } ret = !UpdateHostsFile( pConnectionName, ip, "lmhosts", TRUE ); if (ret) { ReportMessage(0,"Could not update lmhosts file",NULL,NULL,0); goto cleanup; } cleanup: // an error has occured, but the device is registered, we must remove it if (ret != 0 && registered) SetupDiCallClassInstaller(DIF_REMOVE, hDeviceInfo, &DeviceInfoData); found = SetupDiDeleteDeviceInfo(hDeviceInfo, &DeviceInfoData); // destroy the driver info list if (destroyList) SetupDiDestroyDriverInfoList(hDeviceInfo, &DeviceInfoData, SPDIT_CLASSDRIVER); // clean up the device info set if (hDeviceInfo != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList(hDeviceInfo); return ret; };
HRESULT xDiEnumDriverFiles( __in_opt HWND Owner, __in LPCWSTR OemInfFullPath, __in DWORD Flags, __in XDI_ENUM_DRIVER_FILE_CALLBACK EnumCallback, __in LPVOID EnumContext) { HRESULT hr; BOOL success; WCHAR infFullPath[MAX_PATH]; DWORD n = GetFullPathNameW(OemInfFullPath, MAX_PATH, infFullPath, NULL); if (0 == n) { hr = HRESULT_FROM_WIN32(GetLastError()); hr = (SUCCEEDED(hr)) ? E_FAIL : hr; goto error0; } HDEVINFO devInfoSet = SetupDiCreateDeviceInfoList(NULL, Owner); if (INVALID_HANDLE_VALUE == devInfoSet) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error0; } SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) }; success = SetupDiCreateDeviceInfoW( devInfoSet, L"XDI_Temporary_Enumerator", &GUID_NULL, NULL, NULL, DICD_GENERATE_ID, &devInfoData); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error1; } HSPFILEQ fileQueueHandle = SetupOpenFileQueue(); if (INVALID_HANDLE_VALUE == fileQueueHandle) { // Error from SetupOpenFileQueue is only from out-of-memory situation // without the last error set hr = E_OUTOFMEMORY; goto error2; } SP_DEVINSTALL_PARAMS devInstallParams = {sizeof(SP_DEVINSTALL_PARAMS)}; success = SetupDiGetDeviceInstallParamsW( devInfoSet, &devInfoData, &devInstallParams); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error3; } // // Specify the search path // hr = StringCchCopyW( devInstallParams.DriverPath, MAX_PATH, infFullPath); if (FAILED(hr)) { goto error3; } devInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; devInstallParams.FileQueue = fileQueueHandle; devInstallParams.Flags |= DI_NOVCP; devInstallParams.Flags |= DI_ENUMSINGLEINF; success = SetupDiSetDeviceInstallParamsW( devInfoSet, &devInfoData, &devInstallParams); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error3; } // // use DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE if possible // to ensure we look at duplicate nodes (which is broken in itself) // #ifndef DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE #define DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE 0x08000000L // Don't remove identical driver nodes from the class list #endif if (xDipWindowsXPOrLater()) { devInstallParams.FlagsEx |= DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE; success = SetupDiSetDeviceInstallParamsW( devInfoSet, &devInfoData, &devInstallParams); if (!success) { devInstallParams.FlagsEx &= ~DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE; } } // // Build a class driver list with every driver // success = SetupDiBuildDriverInfoList( devInfoSet, &devInfoData, SPDIT_CLASSDRIVER); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error3; } SP_DRVINFO_DATA drvInfoData = { sizeof(SP_DRVINFO_DATA) }; for (DWORD index = 0; ; ++index) { success = SetupDiEnumDriverInfoW( devInfoSet, &devInfoData, SPDIT_CLASSDRIVER, index, &drvInfoData); if (!success) { break; } SP_DRVINFO_DETAIL_DATA drvInfoDetail = { sizeof(SP_DRVINFO_DETAIL_DATA) }; success = SetupDiGetDriverInfoDetailW( devInfoSet, &devInfoData, &drvInfoData, &drvInfoDetail, sizeof(SP_DRVINFO_DETAIL_DATA), NULL); if (!success && ERROR_INSUFFICIENT_BUFFER != GetLastError()) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error4; } success = SetupDiSetSelectedDriverW( devInfoSet, &devInfoData, &drvInfoData); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error4; } if (Flags & XDI_EDF_NO_CLASS_INSTALLER) { success = SetupDiInstallDriverFiles( devInfoSet, &devInfoData); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error4; } } else { success = SetupDiCallClassInstaller( DIF_INSTALLDEVICEFILES, devInfoSet, &devInfoData); if (!success) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error4; } } } // // SPQ_SCAN_USE_CALLBACK_EX checks the digital signature of the file // We do not want to check the signature here. // // SPQ_SCAN_FILE_PRESENCE avoids checking the digital signature of the file // in Windows XP or later. (Not in Windows 2000) when used // with SPQ_SCAN_USE_CALLBACK_EX // XDI_ENUM_FQS_CONTEXT fqsContext = {0}; fqsContext.Callback = EnumCallback; fqsContext.CallbackContext = EnumContext; DWORD scanResult; success = SetupScanFileQueueW( fileQueueHandle, SPQ_SCAN_USE_CALLBACK, // SPQ_SCAN_USE_CALLBACKEX | SPQ_SCAN_FILE_PRESENCE, Owner, xDipEnumFileQueueScanCallback, &fqsContext, &scanResult); if (!success) { // // SetupScanFileQueue may fail using SPQ_SCAN_FILE_PRESENSE flag // Try again without SPQ_SCAN_FILE_PRESENSE // (when using SPQ_SCAN_USE_CALLBACKEX) // hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto error4; } hr = S_OK; #pragma warning(disable: 4533) // to use goto in cpp error4: SetupDiDestroyDriverInfoList( devInfoSet, &devInfoData, SPDIT_CLASSDRIVER); error3: SetupCloseFileQueue(fileQueueHandle); error2: SetupDiDeleteDeviceInfo(devInfoSet, &devInfoData); error1: SetupDiDestroyDeviceInfoList(devInfoSet); error0: #pragma warning(default: 4533) return hr; }