diff options
author | 2023-12-21 10:13:29 +0100 | |
---|---|---|
committer | 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 { | |||
77 | #endif | 77 | #endif |
78 | #else | 78 | #else |
79 | HANDLE handle; | 79 | HANDLE handle; |
80 | HANDLE hDFU; | ||
81 | HANDLE hIB; | ||
82 | LPSTR iBootPath; | ||
83 | LPSTR DfuPath; | ||
84 | #endif | 80 | #endif |
85 | irecv_event_cb_t progress_callback; | 81 | irecv_event_cb_t progress_callback; |
86 | irecv_event_cb_t received_callback; | 82 | irecv_event_cb_t received_callback; |
@@ -1089,196 +1085,85 @@ typedef struct usb_control_request { | |||
1089 | char data[]; | 1085 | char data[]; |
1090 | } usb_control_request; | 1086 | } usb_control_request; |
1091 | 1087 | ||
1092 | static irecv_error_t win32_openpipes(irecv_client_t client) | ||
1093 | { | ||
1094 | 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))) { | ||
1095 | irecv_close(client); | ||
1096 | return IRECV_E_UNABLE_TO_CONNECT; | ||
1097 | } | ||
1098 | |||
1099 | 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))) { | ||
1100 | irecv_close(client); | ||
1101 | return IRECV_E_UNABLE_TO_CONNECT; | ||
1102 | } | ||
1103 | |||
1104 | client->mode = 0; | ||
1105 | if (client->iBootPath == NULL) { | ||
1106 | if (strncmp(client->DfuPath, "\\\\?\\usb#vid_05ac&pid_", 21) == 0) { | ||
1107 | sscanf(client->DfuPath+21, "%x#", &client->mode); | ||
1108 | } | ||
1109 | client->handle = client->hDFU; | ||
1110 | } else { | ||
1111 | if (strncmp(client->iBootPath, "\\\\?\\usb#vid_05ac&pid_", 21) == 0) { | ||
1112 | sscanf(client->iBootPath+21, "%x#", &client->mode); | ||
1113 | } | ||
1114 | client->handle = client->hIB; | ||
1115 | } | ||
1116 | |||
1117 | if (client->mode == 0) { | ||
1118 | irecv_close(client); | ||
1119 | return IRECV_E_UNABLE_TO_CONNECT; | ||
1120 | } | ||
1121 | |||
1122 | return IRECV_E_SUCCESS; | ||
1123 | } | ||
1124 | |||
1125 | static void win32_closepipes(irecv_client_t client) | ||
1126 | { | ||
1127 | if (client->hDFU!=NULL) { | ||
1128 | CloseHandle(client->hDFU); | ||
1129 | client->hDFU = NULL; | ||
1130 | } | ||
1131 | if (client->hIB!=NULL) { | ||
1132 | CloseHandle(client->hIB); | ||
1133 | client->hIB = NULL; | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) | 1088 | static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) |
1138 | { | 1089 | { |
1139 | int found = 0; | 1090 | int found = 0; |
1091 | const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; | ||
1140 | SP_DEVICE_INTERFACE_DATA currentInterface; | 1092 | SP_DEVICE_INTERFACE_DATA currentInterface; |
1141 | HDEVINFO usbDevices; | 1093 | HDEVINFO usbDevices; |
1142 | DWORD i; | 1094 | DWORD i; |
1143 | irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); | 1095 | irecv_client_t _client = (irecv_client_t) malloc(sizeof(struct irecv_client_private)); |
1144 | memset(_client, 0, sizeof(struct irecv_client_private)); | 1096 | memset(_client, 0, sizeof(struct irecv_client_private)); |
1145 | 1097 | ||
1146 | /* get DFU paths */ | 1098 | int k; |
1147 | usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DFU, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); | 1099 | for (k = 0; !found && guids[k]; k++) { |
1148 | memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); | 1100 | usbDevices = SetupDiGetClassDevs(guids[k], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); |
1149 | currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); | 1101 | memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); |
1150 | for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_DFU, i, ¤tInterface); i++) { | 1102 | currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); |
1151 | free(_client->DfuPath); | 1103 | for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, guids[k], i, ¤tInterface); i++) { |
1152 | _client->DfuPath = NULL; | 1104 | _client->handle = INVALID_HANDLE_VALUE; |
1153 | _client->handle = NULL; | 1105 | DWORD requiredSize = 0; |
1154 | DWORD requiredSize = 0; | 1106 | PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; |
1155 | PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; | 1107 | SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); |
1156 | SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); | 1108 | details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); |
1157 | details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); | 1109 | details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); |
1158 | details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); | 1110 | if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { |
1159 | if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { | 1111 | free(details); |
1160 | free(details); | ||
1161 | continue; | ||
1162 | } else { | ||
1163 | LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); | ||
1164 | memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); | ||
1165 | free(details); | ||
1166 | |||
1167 | _client->DfuPath = result; | ||
1168 | if (win32_openpipes(_client) != IRECV_E_SUCCESS) { | ||
1169 | win32_closepipes(_client); | ||
1170 | continue; | 1112 | continue; |
1171 | } | 1113 | } |
1172 | 1114 | ||
1173 | if (ecid == IRECV_K_WTF_MODE) { | 1115 | unsigned int pid = 0; |
1174 | if (_client->mode != IRECV_K_WTF_MODE) { | 1116 | if (sscanf(details->DevicePath, "\\\\?\\usb#vid_05ac&pid_%04x", &pid)!= 1) { |
1175 | /* special ecid case, ignore !IRECV_K_WTF_MODE */ | 1117 | debug("%s: ERROR: failed to parse PID! path: %s\n", __func__, details->DevicePath); |
1176 | continue; | 1118 | free(details); |
1177 | } else { | ||
1178 | ecid = 0; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | if ((ecid != 0) && (_client->mode == IRECV_K_WTF_MODE)) { | ||
1183 | /* we can't get ecid in WTF mode */ | ||
1184 | win32_closepipes(_client); | ||
1185 | continue; | 1119 | continue; |
1186 | } | 1120 | } |
1187 | 1121 | // make sure the current device is actually in the right mode for the given driver interface | |
1188 | char serial_str[256]; | 1122 | if ((guids[k] == &GUID_DEVINTERFACE_DFU && pid != IRECV_K_DFU_MODE && pid != IRECV_K_WTF_MODE) |
1189 | serial_str[0] = '\0'; | 1123 | || (guids[k] == &GUID_DEVINTERFACE_IBOOT && (pid < IRECV_K_RECOVERY_MODE_1 || pid > IRECV_K_RECOVERY_MODE_4)) |
1190 | 1124 | ) { | |
1191 | char *p = result; | 1125 | free(details); |
1192 | while ((p = strstr(p, "\\usb"))) { | ||
1193 | if (sscanf(p, "\\usb#vid_%*04x&pid_%*04x#%s", serial_str) == 1) | ||
1194 | break; | ||
1195 | p += 4; | ||
1196 | } | ||
1197 | |||
1198 | if (serial_str[0] == '\0') { | ||
1199 | win32_closepipes(_client); | ||
1200 | continue; | 1126 | continue; |
1201 | } | 1127 | } |
1202 | 1128 | ||
1203 | p = strchr(serial_str, '#'); | 1129 | _client->handle = CreateFileA(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); |
1204 | if (p) { | 1130 | if (_client->handle == INVALID_HANDLE_VALUE) { |
1205 | *p = '\0'; | 1131 | free(details); |
1206 | } | 1132 | continue; |
1207 | |||
1208 | unsigned int j; | ||
1209 | for (j = 0; j < strlen(serial_str); j++) { | ||
1210 | if (serial_str[j] == '_') { | ||
1211 | serial_str[j] = ' '; | ||
1212 | } else { | ||
1213 | serial_str[j] = toupper(serial_str[j]); | ||
1214 | } | ||
1215 | } | 1133 | } |
1134 | _client->mode = pid; | ||
1216 | 1135 | ||
1217 | irecv_load_device_info_from_iboot_string(_client, serial_str); | 1136 | if (ecid == IRECV_K_WTF_MODE) { |
1218 | 1137 | if (_client->mode != IRECV_K_WTF_MODE) { | |
1219 | if (ecid != 0) { | 1138 | /* special ecid case, ignore !IRECV_K_WTF_MODE */ |
1220 | if (_client->device_info.ecid != ecid) { | 1139 | CloseHandle(_client->handle); |
1221 | win32_closepipes(_client); | 1140 | free(details); |
1222 | continue; | 1141 | continue; |
1142 | } else { | ||
1143 | ecid = 0; | ||
1223 | } | 1144 | } |
1224 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); | ||
1225 | } | ||
1226 | found = 1; | ||
1227 | break; | ||
1228 | } | ||
1229 | } | ||
1230 | SetupDiDestroyDeviceInfoList(usbDevices); | ||
1231 | |||
1232 | if (found) { | ||
1233 | *client = _client; | ||
1234 | return IRECV_E_SUCCESS; | ||
1235 | } | ||
1236 | |||
1237 | /* get iBoot path */ | ||
1238 | usbDevices = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IBOOT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); | ||
1239 | memset(¤tInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA)); | ||
1240 | currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); | ||
1241 | for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_IBOOT, i, ¤tInterface); i++) { | ||
1242 | free(_client->iBootPath); | ||
1243 | _client->iBootPath = NULL; | ||
1244 | _client->handle = NULL; | ||
1245 | DWORD requiredSize = 0; | ||
1246 | PSP_DEVICE_INTERFACE_DETAIL_DATA_A details; | ||
1247 | SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, NULL, 0, &requiredSize, NULL); | ||
1248 | details = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A) malloc(requiredSize); | ||
1249 | details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); | ||
1250 | if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, ¤tInterface, details, requiredSize, NULL, NULL)) { | ||
1251 | free(details); | ||
1252 | continue; | ||
1253 | } else { | ||
1254 | LPSTR result = (LPSTR) malloc(requiredSize - sizeof(DWORD)); | ||
1255 | memcpy((void*) result, details->DevicePath, requiredSize - sizeof(DWORD)); | ||
1256 | free(details); | ||
1257 | |||
1258 | _client->iBootPath = result; | ||
1259 | if (win32_openpipes(_client) != IRECV_E_SUCCESS) { | ||
1260 | win32_closepipes(_client); | ||
1261 | continue; | ||
1262 | } | 1145 | } |
1263 | 1146 | ||
1264 | if ((ecid != 0) && (_client->mode == IRECV_K_WTF_MODE)) { | 1147 | if ((ecid != 0) && (_client->mode == IRECV_K_WTF_MODE)) { |
1265 | /* we can't get ecid in WTF mode */ | 1148 | /* we can't get ecid in WTF mode */ |
1266 | win32_closepipes(_client); | 1149 | CloseHandle(_client->handle); |
1150 | free(details); | ||
1267 | continue; | 1151 | continue; |
1268 | } | 1152 | } |
1269 | 1153 | ||
1270 | char serial_str[256]; | 1154 | char serial_str[256]; |
1271 | serial_str[0] = '\0'; | 1155 | serial_str[0] = '\0'; |
1272 | 1156 | ||
1273 | char *p = result; | 1157 | char *p = (char*)details->DevicePath; |
1274 | while ((p = strstr(p, "\\usb"))) { | 1158 | while ((p = strstr(p, "\\usb"))) { |
1275 | if (sscanf(p, "\\usb#vid_%*04x&pid_%*04x#%s", serial_str) == 1) | 1159 | if (sscanf(p, "\\usb#vid_05ac&pid_%*04x#%s", serial_str) == 1) |
1276 | break; | 1160 | break; |
1277 | p += 4; | 1161 | p += 4; |
1278 | } | 1162 | } |
1163 | free(details); | ||
1279 | 1164 | ||
1280 | if (serial_str[0] == '\0') { | 1165 | if (serial_str[0] == '\0') { |
1281 | win32_closepipes(_client); | 1166 | CloseHandle(_client->handle); |
1282 | continue; | 1167 | continue; |
1283 | } | 1168 | } |
1284 | 1169 | ||
@@ -1300,7 +1185,7 @@ static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) | |||
1300 | 1185 | ||
1301 | if (ecid != 0) { | 1186 | if (ecid != 0) { |
1302 | if (_client->device_info.ecid != ecid) { | 1187 | if (_client->device_info.ecid != ecid) { |
1303 | win32_closepipes(_client); | 1188 | CloseHandle(_client->handle); |
1304 | continue; | 1189 | continue; |
1305 | } | 1190 | } |
1306 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); | 1191 | debug("found device with ECID %016" PRIx64 "\n", (uint64_t)ecid); |
@@ -2317,7 +2202,7 @@ static void* _irecv_handle_device_add(void *userdata) | |||
2317 | 2202 | ||
2318 | char *p = result; | 2203 | char *p = result; |
2319 | while ((p = strstr(p, "\\usb"))) { | 2204 | while ((p = strstr(p, "\\usb"))) { |
2320 | if (sscanf(p, "\\usb#vid_%*04x&pid_%04x#%s", &pid, serial_str) == 2) | 2205 | if (sscanf(p, "\\usb#vid_05ac&pid_%04x#%s", &pid, serial_str) == 2) |
2321 | break; | 2206 | break; |
2322 | p += 4; | 2207 | p += 4; |
2323 | } | 2208 | } |
@@ -2981,11 +2866,7 @@ irecv_error_t irecv_close(irecv_client_t client) | |||
2981 | } | 2866 | } |
2982 | #endif | 2867 | #endif |
2983 | #else | 2868 | #else |
2984 | free(client->iBootPath); | 2869 | CloseHandle(client->handle); |
2985 | client->iBootPath = NULL; | ||
2986 | free(client->DfuPath); | ||
2987 | client->DfuPath = NULL; | ||
2988 | win32_closepipes(client); | ||
2989 | #endif | 2870 | #endif |
2990 | free(client->device_info.srnm); | 2871 | free(client->device_info.srnm); |
2991 | free(client->device_info.imei); | 2872 | free(client->device_info.imei); |