summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2023-12-21 10:13:29 +0100
committerGravatar Nikias Bassen2023-12-21 10:13:29 +0100
commit345ac620f2c13322328a51128f76383bf69c1e45 (patch)
tree0822ce60b88f47e233abab6601c70c2c3eaa6b90 /src
parent010b3b08c87bb3586e7b31668c62b8848a1bb759 (diff)
downloadlibirecovery-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.
Diffstat (limited to 'src')
-rw-r--r--src/libirecovery.c209
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
1092static 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
1125static 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
1137static irecv_error_t win32_open_with_ecid(irecv_client_t* client, uint64_t ecid) 1088static 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(&currentInterface, '\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(&currentInterface, '\0', sizeof(SP_DEVICE_INTERFACE_DATA));
1150 for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, &GUID_DEVINTERFACE_DFU, i, &currentInterface); i++) { 1102 currentInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
1151 free(_client->DfuPath); 1103 for (i = 0; usbDevices && SetupDiEnumDeviceInterfaces(usbDevices, NULL, guids[k], i, &currentInterface); 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, &currentInterface, NULL, 0, &requiredSize, NULL);
1156 SetupDiGetDeviceInterfaceDetailA(usbDevices, &currentInterface, 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, &currentInterface, details, requiredSize, NULL, NULL)) {
1159 if (!SetupDiGetDeviceInterfaceDetailA(usbDevices, &currentInterface, 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(&currentInterface, '\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, &currentInterface); 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, &currentInterface, 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, &currentInterface, 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);