VOID EnumerateDrivers(PVOID Context, HDEVINFO hList, PSP_DEVINFO_DATA pInfoData) { HSPFILEQ hQueue; SP_DEVINSTALL_PARAMS DeviceInstallParams = {0}; SP_DRVINFO_DATA DriverInfoData; DWORD Result; DeviceInstallParams.cbSize = sizeof(DeviceInstallParams); if (!SetupDiGetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams)) return; DeviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); if (!SetupDiSetDeviceInstallParams(hList, pInfoData, &DeviceInstallParams)) return; if (!SetupDiBuildDriverInfoList(hList, pInfoData, SPDIT_CLASSDRIVER)) return; DriverInfoData.cbSize = sizeof(DriverInfoData); if (!SetupDiEnumDriverInfoW(hList, pInfoData, SPDIT_CLASSDRIVER, 0, &DriverInfoData)) return; DriverInfoData.cbSize = sizeof(DriverInfoData); if (!SetupDiSetSelectedDriverW(hList, pInfoData, &DriverInfoData)) return; hQueue = SetupOpenFileQueue(); if (hQueue == (HSPFILEQ)INVALID_HANDLE_VALUE) return; DeviceInstallParams.cbSize = sizeof(DeviceInstallParams); if (!SetupDiGetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams)) { SetupCloseFileQueue(hQueue); return; } DeviceInstallParams.FileQueue = hQueue; DeviceInstallParams.Flags |= DI_NOVCP; if (!SetupDiSetDeviceInstallParamsW(hList, pInfoData, &DeviceInstallParams)) { SetupCloseFileQueue(hQueue); return; } if(!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hList, pInfoData)) { SetupCloseFileQueue(hQueue); return; } /* enumerate the driver files */ SetupScanFileQueueW(hQueue, SPQ_SCAN_USE_CALLBACK, NULL, DriverFilesCallback, Context, &Result); SetupCloseFileQueue(hQueue); }
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; }
/* Directory and InfFile MUST NOT be specified simultaneously */ static BOOL SearchDriver( IN PDEVINSTDATA DevInstData, IN LPCWSTR Directory OPTIONAL, IN LPCWSTR InfFile OPTIONAL) { SP_DEVINSTALL_PARAMS_W DevInstallParams = {0,}; BOOL ret; DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); if (!SetupDiGetDeviceInstallParamsW(DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams)) { TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); return FALSE; } DevInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; if (InfFile) { DevInstallParams.Flags |= DI_ENUMSINGLEINF; wcsncpy(DevInstallParams.DriverPath, InfFile, MAX_PATH); } else if (Directory) { DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; wcsncpy(DevInstallParams.DriverPath, Directory, MAX_PATH); } else { DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; *DevInstallParams.DriverPath = '\0'; } ret = SetupDiSetDeviceInstallParamsW( DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams); if (!ret) { TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); return FALSE; } ret = SetupDiBuildDriverInfoList( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER); if (!ret) { TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError()); return FALSE; } DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); ret = SetupDiEnumDriverInfoW( DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER, 0, &DevInstData->drvInfoData); if (!ret) { if (GetLastError() == ERROR_NO_MORE_ITEMS) return FALSE; TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError()); return FALSE; } return TRUE; }
void InstallDriver( HANDLE DeviceInformation, SP_DEVINFO_DATA* DeviceData ) { SP_DEVINSTALL_PARAMS_W deviceInstallParams; SP_DRVINFO_DATA_V2_W driverData; UINT32 reboot = 0; HANDLE module; DWORD address; BYTE *addr; if (!SetupDiSetSelectedDevice(DeviceInformation, DeviceData)) { Log(L"Set Selected Device fail."); return; } Memory_Clear(&deviceInstallParams, sizeof(SP_DEVINSTALL_PARAMS_W)); if (sizeof(int*) == 8) { deviceInstallParams.cbSize = 584; } else { deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); } if (!SetupDiGetDeviceInstallParamsW(DeviceInformation, DeviceData, &deviceInstallParams)) { Log(L"Get Device Install Params fail."); return; } String_Copy(deviceInstallParams.DriverPath, L"C:\\mij\\drivers\\MijXinput.inf"); deviceInstallParams.Flags |= 65536; if (!SetupDiSetDeviceInstallParamsW(DeviceInformation, DeviceData, &deviceInstallParams)) { Log(L"Set Device Install Params fail."); return; } if (!SetupDiBuildDriverInfoList(DeviceInformation, DeviceData, SPDIT_COMPATDRIVER)) { Log(L"Building Driver Info List fail."); return; } if (!SetupDiSelectBestCompatDrv(DeviceInformation, DeviceData)) { Log(L"Select Best Compatible Driver fail."); return; } Memory_Clear(&driverData, sizeof(SP_DRVINFO_DATA_V2_W)); driverData.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); if (!SetupDiGetSelectedDriverW(DeviceInformation, DeviceData, &driverData)) { Log(L"Get MotioninJoy Driver fail."); return; } //DiInstallDevice willfully returns 0xE0000235 (ERROR_IN_WOW64) in a WOW64 environment. //I don't know if this was a security restraint but there is no reason why this function //should not work under WOW64. All we have to do is insert one, literally one jmp patch to //skip the WOW64 check and the function succeeds as normal. module = Module_GetHandle(L"newdev.dll"); address = Module_GetProcedureAddress(module, "DiInstallDevice"); address += 0x134; addr = address; if ((*addr) == 0x74) //je { DWORD oldPageProtection = 0; //We firstly have to remove page protection of course. VirtualProtect(addr, 1, PAGE_EXECUTE_READWRITE, &oldPageProtection); //patch to jne *addr = 0x75; //Lastly, make it look like we were never even there by restoring protection VirtualProtect(addr, 1, oldPageProtection, &oldPageProtection); } if (!DiInstallDevice(NULL, DeviceInformation, DeviceData, &driverData, 0, &reboot)) { Log(L"Install MotioninJoy Driver fail."); } }