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; };
/** * Install the VBox video driver. * * @returns TRUE on success. * @returns FALSE on failure. * @param szDriverDir The base directory where we find the INF. */ BOOL installVideoDriver(TCHAR* szDriverDir) { HDEVINFO hDevInfo; SP_DEVINSTALL_PARAMS DeviceInstallParams={0}; SP_DRVINFO_DATA drvInfoData={0}; SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0}; DWORD cbReqSize; /* Vars used for reading the INF */ HINF hInf; TCHAR szServiceSection[LINE_LEN]; INFCONTEXT serviceContext; TCHAR szServiceData[LINE_LEN]; TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody... SP_DEVINFO_DATA deviceInfoData; DWORD configFlags; HKEY hkey; DWORD disp; TCHAR regKeyName[LINE_LEN]; BOOL rc; /* Create an empty list */ hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY, NULL); if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE; memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS)); DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); rc=SetupDiGetDeviceInstallParams(hDevInfo, NULL, &DeviceInstallParams); if(!rc) return FALSE; DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */ DI_DONOTCALLCONFIGMG | DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */ /* Path to inf file */ wsprintf(DeviceInstallParams.DriverPath, TEXT("%ws\\%ws"), szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); rc=SetupDiSetDeviceInstallParams(hDevInfo, NULL, &DeviceInstallParams); if(!rc) return FALSE; /* Read the drivers from the inf file */ if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER)) { SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* Get the first found driver. Our Inf file only contains one so this is fine */ drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER, 0, &drvInfoData)){ SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* Get necessary driver details */ DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if (!(!SetupDiGetDriverInfoDetail(hDevInfo, NULL, &drvInfoData, &DriverInfoDetailData, DriverInfoDetailData.cbSize, &cbReqSize) &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) ) { SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) { SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } /* First install the service */ wsprintf(szServiceSection, TEXT("%ws.Services"), DriverInfoDetailData.SectionName); if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext)) { /* No service line?? Can't be... */ closeAndDestroy(hDevInfo, hInf); return FALSE; } /* Get the name */ SetupGetStringField(&serviceContext, 1, szServiceData, sizeof(szServiceData), NULL); wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData); memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA)); deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr, //Create new (LPGUID) &GUID_DEVCLASS_DISPLAY, NULL, //Do we need a description here? NULL, //No user interface 0, &deviceInfoData) && SetupDiRegisterDeviceInfo(hDevInfo, &deviceInfoData, 0, NULL, NULL, NULL)) ) { /* We created a new key in the registry */ memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS)); DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); SetupDiGetDeviceInstallParams(hDevInfo, &deviceInfoData, &DeviceInstallParams); DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files DI_DONOTCALLCONFIGMG | DI_ENUMSINGLEINF; //Use our INF file only /* Path to inf file */ wsprintf(DeviceInstallParams.DriverPath, TEXT("%ws\\%ws"), szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); SetupDiSetDeviceInstallParams(hDevInfo, &deviceInfoData, &DeviceInstallParams); if(!SetupDiBuildDriverInfoList(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if (!SetupDiEnumDriverInfo(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER, 0, &drvInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } if(!SetupDiSetSelectedDriver(hDevInfo, &deviceInfoData, &drvInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } if(!SetupDiInstallDevice(hDevInfo, &deviceInfoData)) { closeAndDestroy(hDevInfo, hInf); return FALSE; } } /* Make sure the device is enabled */ if (SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, NULL, (LPBYTE) &configFlags, sizeof(DWORD), NULL) && (configFlags & CONFIGFLAG_DISABLED)) { configFlags &= ~CONFIGFLAG_DISABLED; SetupDiSetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, (LPBYTE) &configFlags, sizeof(DWORD)); } wsprintf(regKeyName, TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"), szServiceData, 0); //We only have one device if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { /* Insert description */ RegSetValueEx(hkey, TEXT("Device Description"), 0, REG_SZ, (LPBYTE) DriverInfoDetailData.DrvDescription, (lstrlen(DriverInfoDetailData.DrvDescription) + 1) * sizeof(TCHAR) ); TCHAR szSoftwareSection[LINE_LEN]; wsprintf(szSoftwareSection, TEXT("%ws.SoftwareSettings"), szServiceData); if (!SetupInstallFromInfSection(NULL, hInf, szSoftwareSection, SPINST_REGISTRY, hkey, NULL, 0, NULL, NULL, NULL, NULL)) { RegCloseKey(hkey); closeAndDestroy(hDevInfo, hInf); return FALSE; } RegCloseKey(hkey); } /* Install OpenGL stuff */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { /* Do installation here if ever necessary. Currently there is no OpenGL stuff */ RegCloseKey(hkey); } /* Cleanup */ closeAndDestroy(hDevInfo, hInf); #if 0 /* If this key is inserted into the registry, windows will show the desktop applet on next boot. We decide in the installer if we want that so the code is disabled here. */ /* Set registry keys so windows picks up the changes */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { RegCloseKey(hkey); } #endif /* We must reboot at some point */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp) == ERROR_SUCCESS) { RegCloseKey(hkey); } return TRUE; }
BOOL DumpDeviceDriverFiles(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) /*++ Routine Description: Dump information about what files were installed for driver package <tab>Installed using OEM123.INF section [abc.NT] <tab><tab>file... Arguments: Devs )_ uniquely identify device DevInfo ) Return Value: none --*/ { // // do this by 'searching' for the current driver // mimmicing a copy-only install to our own file queue // and then parsing that file queue // SP_DEVINSTALL_PARAMS deviceInstallParams; SP_DRVINFO_DATA driverInfoData; SP_DRVINFO_DETAIL_DATA driverInfoDetail; HSPFILEQ queueHandle = INVALID_HANDLE_VALUE; DWORD count; DWORD scanResult; BOOL success = FALSE; ZeroMemory(&driverInfoData,sizeof(driverInfoData)); driverInfoData.cbSize = sizeof(driverInfoData); if(!FindCurrentDriver(Devs,DevInfo,&driverInfoData)) { Padding(1); FormatToStream(stdout, MSG_DUMP_NO_DRIVER); return FALSE; } // // get useful driver information // driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { // // no information about driver or section // goto final; } if(!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) { goto final; } // // pretend to do the file-copy part of a driver install // to determine what files are used // the specified driver must be selected as the active driver // if(!SetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData)) { goto final; } // // create a file queue so we can look at this queue later // queueHandle = SetupOpenFileQueue(); if ( queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE ) { goto final; } // // modify flags to indicate we're providing our own queue // ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if ( !SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { goto final; } // // we want to add the files to the file queue, not install them! // deviceInstallParams.FileQueue = queueHandle; deviceInstallParams.Flags |= DI_NOVCP; if ( !SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { goto final; } // // now fill queue with files that are to be installed // this involves all class/co-installers // if ( !SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo) ) { goto final; } // // we now have a list of delete/rename/copy files // iterate the copy queue twice - 1st time to get # of files // 2nd time to get files // (WinXP has API to get # of files, but we want this to work // on Win2k too) // count = 0; scanResult = 0; // // call once to count // SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult); Padding(1); FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName); // // call again to dump the files // SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult); success = TRUE; final: