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."); } }
DWORD WINAPI NetClassInstaller( IN DI_FUNCTION InstallFunction, IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) { SP_DRVINFO_DATA_W DriverInfoData; SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail; WCHAR SectionName[LINE_LEN]; HINF hInf = INVALID_HANDLE_VALUE; INFCONTEXT InfContext; UINT ErrorLine; INT CharacteristicsInt; DWORD Characteristics; LPWSTR BusType = NULL; RPC_STATUS RpcStatus; UUID Uuid; LPWSTR UuidRpcString = NULL; LPWSTR UuidString = NULL; LONG rc; DWORD dwLength; if (InstallFunction != DIF_INSTALLDEVICE) return ERROR_DI_DO_DEFAULT; DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); /* Get driver info details */ DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData)) { rc = GetLastError(); DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc); goto cleanup; } DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { rc = GetLastError(); DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc); goto cleanup; } hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine); if (hInf == INVALID_HANDLE_VALUE) { rc = GetLastError(); DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc); goto cleanup; } if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL)) { rc = GetLastError(); DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc); goto cleanup; } /* Get Characteristics and BusType (optional) from .inf file */ if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext)) { rc = GetLastError(); DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n", L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc); goto cleanup; } if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt)) { rc = GetLastError(); DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc); goto cleanup; } Characteristics = (DWORD)CharacteristicsInt; if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET)) { if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext)) { if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength)) { rc = GetLastError(); DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc); goto cleanup; } BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); if (!BusType) { DPRINT("HeapAlloc() failed\n"); rc = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL)) { rc = GetLastError(); DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc); goto cleanup; } } } /* Create a new UUID */ RpcStatus = UuidCreate(&Uuid); if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY) { DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus); rc = ERROR_GEN_FAILURE; goto cleanup; } RpcStatus = UuidToStringW(&Uuid, &UuidRpcString); if (RpcStatus != RPC_S_OK) { DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus); rc = ERROR_GEN_FAILURE; goto cleanup; } /* Add curly braces around Uuid */ UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); if (!UuidString) { DPRINT("HeapAlloc() failed\n"); rc = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } wcscpy(UuidString, L"{"); wcscat(UuidString, UuidRpcString); wcscat(UuidString, L"}"); if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET)) rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType); else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT)) rc = InstallNetClient(); else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE)) rc = InstallNetService(); else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS)) rc = InstallNetTransport(); else { DPRINT("Invalid class guid\n"); rc = ERROR_GEN_FAILURE; } cleanup: if (hInf != INVALID_HANDLE_VALUE) SetupCloseInfFile(hInf); if (UuidRpcString != NULL) RpcStringFreeW(&UuidRpcString); HeapFree(GetProcessHeap(), 0, BusType); HeapFree(GetProcessHeap(), 0, UuidString); if (rc == ERROR_SUCCESS) rc = ERROR_DI_DO_DEFAULT; DPRINT("Returning 0x%lx\n", rc); return rc; }
VOID InstallDeviceData(IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) { HKEY hKey = NULL; HINF hInf = INVALID_HANDLE_VALUE; SP_DRVINFO_DATA DriverInfoData; PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData; WCHAR InfSectionWithExt[256]; BYTE buffer[2048]; DWORD dwRequired; TRACE("InstallDeviceData()\n"); hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); if (hKey == NULL) goto done; DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData)) { goto done; } DriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)buffer; DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, DriverInfoDetailData, 2048, &dwRequired)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done; } TRACE("Inf file name: %S\n", DriverInfoDetailData->InfFileName); hInf = SetupOpenInfFileW(DriverInfoDetailData->InfFileName, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) goto done; TRACE("Section name: %S\n", DriverInfoDetailData->SectionName); SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetailData->SectionName, InfSectionWithExt, 256, NULL, NULL); TRACE("InfSectionWithExt: %S\n", InfSectionWithExt); SetupInstallFromInfSectionW(NULL, hInf, InfSectionWithExt, SPINST_REGISTRY, hKey, NULL, 0, NULL, NULL, NULL, NULL); TRACE("Done\n"); done:; if (hKey != NULL) RegCloseKey(hKey); if (hInf != INVALID_HANDLE_VALUE) SetupCloseInfFile(hInf); }