diff options
-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); |