diff options
author | Nikias Bassen | 2023-12-21 10:13:29 +0100 |
---|---|---|
committer | Nikias Bassen | 2023-12-21 10:13:29 +0100 |
commit | 345ac620f2c13322328a51128f76383bf69c1e45 (patch) | |
tree | 0822ce60b88f47e233abab6601c70c2c3eaa6b90 | |
parent | 010b3b08c87bb3586e7b31668c62b8848a1bb759 (diff) | |
download | libirecovery-345ac620f2c13322328a51128f76383bf69c1e45.tar.gz libirecovery-345ac620f2c13322328a51128f76383bf69c1e45.tar.bz2 |
win32: Simplify code, and make sure to only use devices in correct mode
Devices in DFU mode should only be selected for the DFU driver interface,
and respectively, iBoot mode devices should only be selected for the iBoot
driver interface.
-rw-r--r-- | src/libirecovery.c | 209 |
1 files changed, 45 insertions, 164 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c index f6ff480..16330d2 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c @@ -77,10 +77,6 @@ struct irecv_client_private { #endif #else HANDLE handle; - HANDLE hDFU; - HANDLE hIB; - LPSTR iBootPath; - LPSTR DfuPath; #endif irecv_event_cb_t progress_callback; irecv_event_cb_t received_callback; @@ -1089,196 +1085,85 @@ typedef struct usb_control_request { char data[]; } usb_control_request; -static irecv_error_t win32_openpipes(irecv_client_t client) -{ - if (client->iBootPath && !(client->hIB = CreateFileA(client->iBootPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL))) { - irecv_close(client); - return IRECV_E_UNABLE_TO_CONNECT; - } - - if (client->DfuPath && !(client->hDFU = CreateFileA(client->DfuPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL))) { - irecv_close(client); - return IRECV_E_UNABLE_TO_CONNECT; - } - - client->mode = 0; - if (client->iBootPath == NULL) { - if (strncmp(client->DfuPath, "\\\\?\\usb#vid_05ac&pid_", 21) == 0) { - sscanf(client->DfuPath+21, "%x#", &client->mode); - } - client->handle = client->hDFU; - } else { - if (strncmp(client->iBootPath, "\\\\?\\usb#vid_05ac&pid_", 21) == 0) { - sscanf(client->iBootPath+21, "%x#", &client->mode); - } - client->handle = client->hIB; - } - - if (client->mode == 0) { - irecv_close(client); - return IRECV_E_UNABLE_TO_CONNECT; - } - - return IRECV_E_SUCCESS; -} - -static void win32_closepipes(irecv_client_t client) -{ - if (client->hDFU!=NULL) { - CloseHandle(client->hDFU); - client->hDFU = NULL; - } - if (client->hIB!=NULL) { - CloseHandle(client->hIB); - client->hIB = NULL; - } -} - static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) { int found = 0; + const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; SP_DEVICE_INTERFACE_DATA currentInterface; HDEVINFO usbDevices; DWORD i; irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); memset(_client, 0, sizeof(struct irecv_client_private)); - /* get DFU paths */ - usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DFU, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); - currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_DFU, i, ¤tInterface); i++) { - free(_client->DfuPath); - _client->DfuPath = NULL; - _client->handle = NULL; - DWORD requiredSize = 0; - PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; - SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); - details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); - details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { - free(details); - continue; - } else { - LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); - memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); - free(details); - - _client->DfuPath = result; - if (win32_openpipes(_client) != IRECV_E_SUCCESS) { - win32_closepipes(_client); + int k; + for (k = 0; !found && guids[k]; k++) { + usbDevices = SetupDiGetClassDevs(guids[k], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); + currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, guids[k], i, ¤tInterface); i++) { + _client->handle = INVALID_HANDLE_VALUE; + DWORD requiredSize = 0; + PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; + SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); + details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); + details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { + free(details); continue; } - if (ecid == IRECV_K_WTF_MODE) { - if (_client->mode != IRECV_K_WTF_MODE) { - /* special ecid case, ignore !IRECV_K_WTF_MODE */ - continue; - } else { - ecid = 0; - } - } - - if ((ecid != 0) && (_client->mode == IRECV_K_WTF_MODE)) { - /* we can't get ecid in WTF mode */ - win32_closepipes(_client); + unsigned int pid = 0; + if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) { + debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath); + free(details); continue; } - - char serial_str[256]; - serial_str[0] = '\0'; - - char *p = result; - while ((p = strstr(p, "\\usb"))) { - if (sscanf(p, "\\usb#vid_%*04x&pid_%*04x#%s", serial_str) == 1) - break; - p += 4; - } - - if (serial_str[0] == '\0') { - win32_closepipes(_client); + // make sure the current device is actually in the right mode for the given driver interface + if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) + || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) + ) { + free(details); continue; } - p = strchr(serial_str, '#'); - if (p) { - *p = '\0'; - } - - unsigned int j; - for (j = 0; j < strlen(serial_str); j++) { - if (serial_str[j] == '_') { - serial_str[j] = ' '; - } else { - serial_str[j] = toupper(serial_str[j]); - } + _client->handle = CreateFileA(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (_client->handle == INVALID_HANDLE_VALUE) { + free(details); + continue; } + _client->mode = pid; - irecv_load_device_info_from_iboot_string(_client, serial_str); - - if (ecid != 0) { - if (_client->device_info.ecid != ecid) { - win32_closepipes(_client); + if (ecid == IRECV_K_WTF_MODE) { + if (_client->mode != IRECV_K_WTF_MODE) { + /* special ecid case, ignore !IRECV_K_WTF_MODE */ + CloseHandle(_client->handle); + free(details); continue; + } else { + ecid = 0; } - debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); - } - found = 1; - break; - } - } - SetupDiDestroyDeviceInfoList(usbDevices); - - if (found) { - *client = _client; - return IRECV_E_SUCCESS; - } - - /* get iBoot path */ - usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IBOOT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); - currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_IBOOT, i, ¤tInterface); i++) { - free(_client->iBootPath); - _client->iBootPath = NULL; - _client->handle = NULL; - DWORD requiredSize = 0; - PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; - SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); - details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); - details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { - free(details); - continue; - } else { - LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); - memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); - free(details); - - _client->iBootPath = result; - if (win32_openpipes(_client) != IRECV_E_SUCCESS) { - win32_closepipes(_client); - continue; } if ((ecid != 0) && (_client->mode == IRECV_K_WTF_MODE)) { /* we can't get ecid in WTF mode */ - win32_closepipes(_client); + CloseHandle(_client->handle); + free(details); continue; } char serial_str[256]; serial_str[0] = '\0'; - char *p = result; + char *p = (char*)details->DevicePath; while ((p = strstr(p, "\\usb"))) { - if (sscanf(p, "\\usb#vid_%*04x&pid_%*04x#%s", serial_str) == 1) + if (sscanf(p, "\\usb#vid_05ac&pid_%*04x#%s", serial_str) == 1) break; p += 4; } + free(details); if (serial_str[0] == '\0') { - win32_closepipes(_client); + CloseHandle(_client->handle); continue; } @@ -1300,7 +1185,7 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) if (ecid != 0) { if (_client->device_info.ecid != ecid) { - win32_closepipes(_client); + CloseHandle(_client->handle); continue; } debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); @@ -2317,7 +2202,7 @@ static void* _irecv_handle_device_add(void *userdata) char *p = result; while ((p = strstr(p, "\\usb"))) { - if (sscanf(p, "\\usb#vid_%*04x&pid_%04x#%s", &pid, serial_str) == 2) + if (sscanf(p, "\\usb#vid_05ac&pid_%04x#%s", &pid, serial_str) == 2) break; p += 4; } @@ -2981,11 +2866,7 @@ irecv_error_t irecv_close(irecv_client_t client) } #endif #else - free(client->iBootPath); - client->iBootPath = NULL; - free(client->DfuPath); - client->DfuPath = NULL; - win32_closepipes(client); + CloseHandle(client->handle); #endif free(client->device_info.srnm); free(client->device_info.imei); |