├── adb_api.h ├── build.bat ├── readme.md ├── test_fastboot.c ├── test_speed.c ├── unlockhwbl_cmdline.c ├── unlockhwbl_protocol.c └── util.c /adb_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef ANDROID_USB_API_ADBWINAPI_H__ 18 | #define ANDROID_USB_API_ADBWINAPI_H__ 19 | 20 | #include 21 | #include 22 | 23 | /** \file 24 | This file consists of declarations of routines exported by the API as well 25 | as types, structures, and constants definitions used in the API. 26 | */ 27 | 28 | // Enables compillation for "straight" C 29 | #ifdef __cplusplus 30 | #define EXTERN_C extern "C" 31 | #else 32 | #define EXTERN_C extern 33 | typedef int bool; 34 | #define true 1 35 | #define false 0 36 | #endif 37 | 38 | /** \brief Enumerates ADB endpoint types. 39 | 40 | This enum is taken from WDF_USB_PIPE_TYPE enum found in WDK. 41 | */ 42 | typedef enum _AdbEndpointType { 43 | /// Unknown (invalid, or not initialized) endpoint type. 44 | AdbEndpointTypeInvalid = 0, 45 | 46 | /// Endpoint is device control pipe. 47 | AdbEndpointTypeControl, 48 | 49 | /// Endpoint is isochronous r/w pipe. 50 | AdbEndpointTypeIsochronous, 51 | 52 | /// Endpoint is a bulk r/w pipe. 53 | AdbEndpointTypeBulk, 54 | 55 | /// Endpoint is an interrupt r/w pipe. 56 | AdbEndpointTypeInterrupt, 57 | } AdbEndpointType; 58 | 59 | /** \brief Endpoint desriptor. 60 | 61 | This structure is based on WDF_USB_PIPE_INFORMATION structure found in WDK. 62 | */ 63 | typedef struct _AdbEndpointInformation { 64 | /// Maximum packet size this endpoint is capable of. 65 | unsigned long max_packet_size; 66 | 67 | /// Maximum size of one transfer which should be sent to the host controller. 68 | unsigned long max_transfer_size; 69 | 70 | /// ADB endpoint type. 71 | AdbEndpointType endpoint_type; 72 | 73 | /// Raw endpoint address on the device as described by its descriptor. 74 | unsigned char endpoint_address; 75 | 76 | /// Polling interval. 77 | unsigned char polling_interval; 78 | 79 | /// Which alternate setting this structure is relevant for. 80 | unsigned char setting_index; 81 | } AdbEndpointInformation; 82 | 83 | /// Shortcut to default write bulk endpoint in zero-based endpoint index API. 84 | #define ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX 0xFC 85 | 86 | /// Shortcut to default read bulk endpoint in zero-based endpoint index API. 87 | #define ADB_QUERY_BULK_READ_ENDPOINT_INDEX 0xFE 88 | 89 | // {F72FE0D4-CBCB-407d-8814-9ED673D0DD6B} 90 | /// Our USB class id that driver uses to register our device. 91 | #define ANDROID_USB_CLASS_ID \ 92 | {0xf72fe0d4, 0xcbcb, 0x407d, {0x88, 0x14, 0x9e, 0xd6, 0x73, 0xd0, 0xdd, 0x6b}}; 93 | 94 | // The following ifdef block is the standard way of creating macros which make 95 | // exporting from a DLL simpler. All files within this DLL are compiled with 96 | // the ADBWIN_EXPORTS symbol defined on the command line. this symbol should 97 | // not be defined on any project that uses this DLL. This way any other project 98 | // whose source files include this file see ADBWIN_API functions as being 99 | // imported from a DLL, whereas this DLL sees symbols defined with this macro 100 | // as being exported. 101 | #ifdef ADBWIN_EXPORTS 102 | #define ADBWIN_API EXTERN_C __declspec(dllexport) 103 | #define ADBWIN_API_CLASS __declspec(dllexport) 104 | #else 105 | #define ADBWIN_API EXTERN_C __declspec(dllimport) 106 | #define ADBWIN_API_CLASS __declspec(dllimport) 107 | #endif 108 | 109 | //补丁:只需要typedef即可 110 | #undef ADBWIN_API 111 | #define ADBWIN_API typedef 112 | 113 | /** \brief Handle to an API object. 114 | 115 | To access USB interface and its components clients must first obtain a 116 | handle to the required object. API Objects that are represented by a 117 | handle are: 118 | 1. Interface enumerator that provides access to a list of interfaces that 119 | match certain criterias that were specified when interface enumerator 120 | has been created. This handle is created in AdbEnumInterfaces routine. 121 | 2. Interface that is the major object this API deals with. In Windows 122 | model of the USB stack each USB device (that is physical device, 123 | attached to a USB port) exposes one or more interfaces that become the 124 | major entities through which that device gets accessed. Each of these 125 | interfaces are represented as Windows Device Objects on the USB stack. 126 | So, to this extent, at least as this API is concerned, terms "interface" 127 | and "device" are interchangeable, since each interface is represented by 128 | a device object on the Windows USB stack. This handle is created in 129 | either AdbCreateInterface or AdbCreateInterfaceByName routines. 130 | 3. Endpoint object (also called a pipe) represents an endpoint on interface 131 | through which all I/O operations are performed. This handle is created in 132 | one of these routines: AdbOpenEndpoint, AdbOpenDefaultBulkReadEndpoint, 133 | or AdbOpenDefaultBulkWriteEndpoint. 134 | 4. I/O completion object that tracks completion information of asynchronous 135 | I/O performed on an endpoint. When an endpoint object gets opened through 136 | this API it is opened for asynchronous (or overlapped) I/O. And each time 137 | an asynchronous I/O is performed by this API an I/O completion object is 138 | created to track the result of that I/O when it gets completed. Clients 139 | of the API can then use a handle to I/O completion object to query for 140 | the status and result of asynchronous I/O as well as wait for this I/O 141 | completion. This handle is created in one of these routines: 142 | AdbReadEndpointAsync, or AdbWriteEndpointAsync. 143 | After object is no longer needed by the client, its handle must be closed 144 | using AdbCloseHandle routine. 145 | */ 146 | typedef void* ADBAPIHANDLE; 147 | 148 | /** \brief Defines access type with which an I/O object (endpoint) 149 | should be opened. 150 | */ 151 | typedef enum _AdbOpenAccessType { 152 | /// Opens for read and write access. 153 | AdbOpenAccessTypeReadWrite, 154 | 155 | /// Opens for read only access. 156 | AdbOpenAccessTypeRead, 157 | 158 | /// Opens for write only access. 159 | AdbOpenAccessTypeWrite, 160 | 161 | /// Opens for querying information. 162 | AdbOpenAccessTypeQueryInfo, 163 | } AdbOpenAccessType; 164 | 165 | /** \brief Defines sharing mode with which an I/O object (endpoint) 166 | should be opened. 167 | */ 168 | typedef enum _AdbOpenSharingMode { 169 | /// Shares read and write. 170 | AdbOpenSharingModeReadWrite, 171 | 172 | /// Shares only read. 173 | AdbOpenSharingModeRead, 174 | 175 | /// Shares only write. 176 | AdbOpenSharingModeWrite, 177 | 178 | /// Opens exclusive. 179 | AdbOpenSharingModeExclusive, 180 | } AdbOpenSharingMode; 181 | 182 | /** \brief Provides information about an interface. 183 | */ 184 | typedef struct _AdbInterfaceInfo { 185 | /// Inteface's class id (see SP_DEVICE_INTERFACE_DATA for details) 186 | GUID class_id; 187 | 188 | /// Interface flags (see SP_DEVICE_INTERFACE_DATA for details) 189 | unsigned long flags; 190 | 191 | /// Device name for the interface (see SP_DEVICE_INTERFACE_DETAIL_DATA 192 | /// for details) 193 | wchar_t device_name[1]; 194 | } AdbInterfaceInfo; 195 | 196 | /** \brief Creates USB interface enumerator 197 | 198 | This routine enumerates all USB interfaces that match provided class ID. 199 | This routine uses SetupDiGetClassDevs SDK routine to enumerate devices that 200 | match class ID and then SetupDiEnumDeviceInterfaces SDK routine is called 201 | to enumerate interfaces on the devices. 202 | @param[in] class_id Device class ID, assigned by the driver. 203 | @param[in] exclude_not_present If true enumation will include only those 204 | devices that are currently present. 205 | @param[in] exclude_removed If true interfaces with SPINT_REMOVED flag set 206 | will be not included in the enumeration. 207 | @param[in] active_only If true only active interfaces (with flag 208 | SPINT_ACTIVE set) will be included in the enumeration. 209 | @return Handle to the enumerator object or NULL on failure. If NULL is 210 | returned GetLastError() provides extended error information. 211 | */ 212 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbEnumInterfaces(GUID class_id, 213 | bool exclude_not_present, 214 | bool exclude_removed, 215 | bool active_only); 216 | 217 | /** \brief Gets next interface information 218 | 219 | @param[in] adb_handle Handle to interface enumerator object obtained via 220 | AdbEnumInterfaces call. 221 | @param[out] info Upon successful completion will receive interface 222 | information. Can be NULL. If it is NULL, upon return from this 223 | routine size parameter will contain memory size required for the 224 | next entry. 225 | @param[in,out] size On the way in provides size of the memory buffer 226 | addressed by info parameter. On the way out (only if buffer was not 227 | big enough) will provide memory size required for the next entry. 228 | @return true on success, false on error. If false is returned 229 | GetLastError() provides extended error information. 230 | ERROR_INSUFFICIENT_BUFFER indicates that buffer provided in info 231 | parameter was not big enough and size parameter contains memory size 232 | required for the next entry. ERROR_NO_MORE_ITEMS indicates that 233 | enumeration is over and there are no more entries to return. 234 | */ 235 | ADBWIN_API bool __cdecl FAdbNextInterface(ADBAPIHANDLE adb_handle, 236 | AdbInterfaceInfo* info, 237 | unsigned long* size); 238 | 239 | /** \brief Resets enumerator so next call to AdbNextInterface will start 240 | from the beginning. 241 | 242 | @param[in] adb_handle Handle to interface enumerator object obtained via 243 | AdbEnumInterfaces call. 244 | @return true on success, false on error. If false is returned GetLastError() 245 | provides extended error information. 246 | */ 247 | ADBWIN_API bool __cdecl FAdbResetInterfaceEnum(ADBAPIHANDLE adb_handle); 248 | 249 | /** \brief Creates USB interface object 250 | 251 | This routine creates an object that represents a USB interface. 252 | @param[in] interface_name Name of the interface. 253 | @return Handle to the interface object or NULL on failure. If NULL is 254 | returned GetLastError() provides extended error information. 255 | */ 256 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbCreateInterfaceByName(const wchar_t* interface_name); 257 | 258 | /** \brief Creates USB interface object based on vendor, product and 259 | interface IDs. 260 | 261 | This routine creates and object that represents a USB interface on our 262 | device. It uses AdbCreateInterfaceByName to actually do the create. 263 | @param[in] class_id Device class ID, assigned by the driver. 264 | @param[in] vendor_id Device vendor ID 265 | @param[in] product_id Device product ID 266 | @param[in] interface_id Device interface ID. This parameter is optional. 267 | Value 0xFF indicates that interface should be addressed by vendor 268 | and product IDs only. 269 | @return Handle to the interface object or NULL on failure. If NULL is 270 | returned GetLastError() provides extended error information. 271 | */ 272 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbCreateInterface(GUID class_id, 273 | unsigned short vendor_id, 274 | unsigned short product_id, 275 | unsigned char interface_id); 276 | 277 | /** \brief Gets interface name. 278 | 279 | @param[in] adb_interface A handle to interface object created with 280 | AdbCreateInterface call. 281 | @param[out] buffer Buffer for the name. Can be NULL in which case 282 | buffer_char_size will contain number of characters required for 283 | the name. 284 | @param[in,out] buffer_char_size On the way in supplies size (in characters) 285 | of the buffer. On the way out, if method failed and GetLastError 286 | reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters 287 | required for the name. 288 | @param[in] ansi If true the name will be returned as single character 289 | string. Otherwise name will be returned as wide character string. 290 | @return true on success, false on failure. If false is returned 291 | GetLastError() provides extended error information. 292 | */ 293 | ADBWIN_API bool __cdecl FAdbGetInterfaceName(ADBAPIHANDLE adb_interface, 294 | void* buffer, 295 | unsigned long* buffer_char_size, 296 | bool ansi); 297 | 298 | /** \brief Gets serial number for interface's device. 299 | 300 | @param[in] adb_interface A handle to interface object created with 301 | AdbCreateInterface call. 302 | @param[out] buffer Buffer for the serail number string. Can be NULL in which 303 | case buffer_char_size will contain number of characters required for 304 | the string. 305 | @param[in,out] buffer_char_size On the way in supplies size (in characters) 306 | of the buffer. On the way out, if method failed and GetLastError 307 | reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters 308 | required for the name. 309 | @param[in] ansi If true the name will be returned as single character 310 | string. Otherwise name will be returned as wide character string. 311 | @return true on success, false on failure. If false is returned 312 | GetLastError() provides extended error information. 313 | */ 314 | ADBWIN_API bool __cdecl FAdbGetSerialNumber(ADBAPIHANDLE adb_interface, 315 | void* buffer, 316 | unsigned long* buffer_char_size, 317 | bool ansi); 318 | 319 | /** \brief Gets device descriptor for the USB device associated with 320 | the given interface. 321 | 322 | @param[in] adb_interface A handle to interface object created with 323 | AdbCreateInterface call. 324 | @param[out] desc Upon successful completion will have usb device 325 | descriptor. 326 | @return true on success, false on failure. If false is returned 327 | GetLastError() provides extended error information. 328 | */ 329 | ADBWIN_API bool __cdecl FAdbGetUsbDeviceDescriptor(ADBAPIHANDLE adb_interface, 330 | USB_DEVICE_DESCRIPTOR* desc); 331 | 332 | /** \brief Gets descriptor for the selected USB device configuration. 333 | 334 | @param[in] adb_interface A handle to interface object created with 335 | AdbCreateInterface call. 336 | @param[out] desc Upon successful completion will have usb device 337 | configuration descriptor. 338 | @return true on success, false on failure. If false is returned 339 | GetLastError() provides extended error information. 340 | */ 341 | ADBWIN_API bool __cdecl FAdbGetUsbConfigurationDescriptor( 342 | ADBAPIHANDLE adb_interface, 343 | USB_CONFIGURATION_DESCRIPTOR* desc); 344 | 345 | /** \brief Gets descriptor for the given interface. 346 | 347 | @param[in] adb_interface A handle to interface object created with 348 | AdbCreateInterface call. 349 | @param[out] desc Upon successful completion will have usb device 350 | configuration descriptor. 351 | @return true on success, false on failure. If false is returned 352 | GetLastError() provides extended error information. 353 | */ 354 | ADBWIN_API bool __cdecl FAdbGetUsbInterfaceDescriptor(ADBAPIHANDLE adb_interface, 355 | USB_INTERFACE_DESCRIPTOR* desc); 356 | 357 | /** \brief Gets information about an endpoint on the given interface. 358 | 359 | @param[in] adb_interface A handle to interface object created with 360 | AdbCreateInterface call. 361 | @param[in] endpoint_index Zero-based endpoint index. There are two 362 | shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX 363 | and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide information 364 | about bulk write and bulk read endpoints respectively. 365 | @param[out] info Upon successful completion will have endpoint information. 366 | @return true on success, false on failure. If false is returned 367 | GetLastError() provides extended error information. 368 | */ 369 | ADBWIN_API bool __cdecl FAdbGetEndpointInformation(ADBAPIHANDLE adb_interface, 370 | unsigned char endpoint_index, 371 | AdbEndpointInformation* info); 372 | 373 | /** \brief Gets information about default bulk read endpoint on the given 374 | interface. 375 | 376 | @param[in] adb_interface A handle to interface object created with 377 | AdbCreateInterface call. 378 | @param[out] info Upon successful completion will have endpoint information. 379 | @return true on success, false on failure. If false is returned 380 | GetLastError() provides extended error information. 381 | */ 382 | ADBWIN_API bool __cdecl FAdbGetDefaultBulkReadEndpointInformation( 383 | ADBAPIHANDLE adb_interface, 384 | AdbEndpointInformation* info); 385 | 386 | /** \brief Gets information about default bulk write endpoint on the given 387 | interface. 388 | 389 | @param[in] adb_interface A handle to interface object created with 390 | AdbCreateInterface call. 391 | @param[out] info Upon successful completion will have endpoint information. 392 | @return true on success, false on failure. If false is returned 393 | GetLastError() provides extended error information. 394 | */ 395 | ADBWIN_API bool __cdecl FAdbGetDefaultBulkWriteEndpointInformation( 396 | ADBAPIHANDLE adb_interface, 397 | AdbEndpointInformation* info); 398 | 399 | /** \brief Opens an endpoint on the given interface. 400 | 401 | Endpoints are always opened for overlapped I/O. 402 | @param[in] adb_interface A handle to interface object created with 403 | AdbCreateInterface call. 404 | @param[in] endpoint_index Zero-based endpoint index. There are two 405 | shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX 406 | and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide information 407 | about bulk write and bulk read endpoints respectively. 408 | @param[in] access_type Desired access type. In the current implementation 409 | this parameter has no effect on the way endpoint is opened. It's 410 | always read / write access. 411 | @param[in] sharing_mode Desired share mode. In the current implementation 412 | this parameter has no effect on the way endpoint is opened. It's 413 | always shared for read / write. 414 | @return Handle to the opened endpoint object or NULL on failure. If NULL is 415 | returned GetLastError() provides extended error information. 416 | */ 417 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbOpenEndpoint(ADBAPIHANDLE adb_interface, 418 | unsigned char endpoint_index, 419 | AdbOpenAccessType access_type, 420 | AdbOpenSharingMode sharing_mode); 421 | 422 | /** \brief Opens default bulk read endpoint on the given interface. 423 | 424 | Endpoints are always opened for overlapped I/O. 425 | @param[in] adb_interface A handle to interface object created with 426 | AdbCreateInterface call. 427 | @param[in] access_type Desired access type. In the current implementation 428 | this parameter has no effect on the way endpoint is opened. It's 429 | always read / write access. 430 | @param[in] sharing_mode Desired share mode. In the current implementation 431 | this parameter has no effect on the way endpoint is opened. It's 432 | always shared for read / write. 433 | @return Handle to the opened endpoint object or NULL on failure. If NULL is 434 | returned GetLastError() provides extended error information. 435 | */ 436 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbOpenDefaultBulkReadEndpoint( 437 | ADBAPIHANDLE adb_interface, 438 | AdbOpenAccessType access_type, 439 | AdbOpenSharingMode sharing_mode); 440 | 441 | /** \brief Opens default bulk write endpoint on the given interface. 442 | 443 | Endpoints are always opened for overlapped I/O. 444 | @param[in] adb_interface A handle to interface object created with 445 | AdbCreateInterface call. 446 | @param[in] access_type Desired access type. In the current implementation 447 | this parameter has no effect on the way endpoint is opened. It's 448 | always read / write access. 449 | @param[in] sharing_mode Desired share mode. In the current implementation 450 | this parameter has no effect on the way endpoint is opened. It's 451 | always shared for read / write. 452 | @return Handle to the opened endpoint object or NULL on failure. If NULL is 453 | returned GetLastError() provides extended error information. 454 | */ 455 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbOpenDefaultBulkWriteEndpoint( 456 | ADBAPIHANDLE adb_interface, 457 | AdbOpenAccessType access_type, 458 | AdbOpenSharingMode sharing_mode); 459 | 460 | /** \brief Gets handle to interface object for the given endpoint 461 | 462 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 463 | of the AdbOpenXxxEndpoint calls. 464 | @return Handle to the interface for this endpoint or NULL on failure. If NULL 465 | is returned GetLastError() provides extended error information. 466 | */ 467 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbGetEndpointInterface(ADBAPIHANDLE adb_endpoint); 468 | 469 | /** \brief Gets information about the given endpoint. 470 | 471 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 472 | of the AdbOpenXxxEndpoint calls. 473 | @param[out] info Upon successful completion will have endpoint information. 474 | @return true on success, false on failure. If false is returned 475 | GetLastError() provides extended error information. 476 | */ 477 | ADBWIN_API bool __cdecl FAdbQueryInformationEndpoint(ADBAPIHANDLE adb_endpoint, 478 | AdbEndpointInformation* info); 479 | 480 | /** \brief Asynchronously reads from the given endpoint. 481 | 482 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 483 | of the AdbOpenXxxEndpoint calls. 484 | @param[out] buffer Pointer to the buffer that receives the data. 485 | @param[in] bytes_to_read Number of bytes to be read. 486 | @param[out] bytes_read Number of bytes read. Can be NULL. 487 | @param[in] event_handle Event handle that should be signaled when async I/O 488 | completes. Can be NULL. If it's not NULL this handle will be used to 489 | initialize OVERLAPPED structure for this I/O. 490 | @param[in] time_out A timeout (in milliseconds) required for this I/O to 491 | complete. Zero value for this parameter means that there is no 492 | timeout for this I/O. 493 | @return A handle to IO completion object or NULL on failure. If NULL is 494 | returned GetLastError() provides extended error information. 495 | */ 496 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbReadEndpointAsync(ADBAPIHANDLE adb_endpoint, 497 | void* buffer, 498 | unsigned long bytes_to_read, 499 | unsigned long* bytes_read, 500 | unsigned long time_out, 501 | HANDLE event_handle); 502 | 503 | /** \brief Asynchronously writes to the given endpoint. 504 | 505 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 506 | of the AdbOpenXxxEndpoint calls. 507 | @param[in] buffer Pointer to the buffer containing the data to be written. 508 | @param[in] bytes_to_write Number of bytes to be written. 509 | @param[out] bytes_written Number of bytes written. Can be NULL. 510 | @param[in] event_handle Event handle that should be signaled when async I/O 511 | completes. Can be NULL. If it's not NULL this handle will be used to 512 | initialize OVERLAPPED structure for this I/O. 513 | @param[in] time_out A timeout (in milliseconds) required for this I/O to 514 | complete. Zero value for this parameter means that there is no 515 | timeout for this I/O. 516 | @return A handle to IO completion object or NULL on failure. If NULL is 517 | returned GetLastError() provides extended error information. 518 | */ 519 | ADBWIN_API ADBAPIHANDLE __cdecl FAdbWriteEndpointAsync(ADBAPIHANDLE adb_endpoint, 520 | void* buffer, 521 | unsigned long bytes_to_write, 522 | unsigned long* bytes_written, 523 | unsigned long time_out, 524 | HANDLE event_handle); 525 | 526 | /** \brief Synchronously reads from the given endpoint. 527 | 528 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 529 | of the AdbOpenXxxEndpoint calls. 530 | @param[out] buffer Pointer to the buffer that receives the data. 531 | @param[in] bytes_to_read Number of bytes to be read. 532 | @param[out] bytes_read Number of bytes read. Can be NULL. 533 | @param[in] time_out A timeout (in milliseconds) required for this I/O to 534 | complete. Zero value for this parameter means that there is no 535 | timeout for this I/O. 536 | @return true on success and false on failure. If false is 537 | returned GetLastError() provides extended error information. 538 | */ 539 | ADBWIN_API bool __cdecl FAdbReadEndpointSync(ADBAPIHANDLE adb_endpoint, 540 | void* buffer, 541 | unsigned long bytes_to_read, 542 | unsigned long* bytes_read, 543 | unsigned long time_out); 544 | 545 | /** \brief Synchronously writes to the given endpoint. 546 | 547 | @param[in] adb_endpoint A handle to opened endpoint object, obtained via one 548 | of the AdbOpenXxxEndpoint calls. 549 | @param[in] buffer Pointer to the buffer containing the data to be written. 550 | @param[in] bytes_to_write Number of bytes to be written. 551 | @param[out] bytes_written Number of bytes written. Can be NULL. 552 | @param[in] time_out A timeout (in milliseconds) required for this I/O to 553 | complete. Zero value for this parameter means that there is no 554 | timeout for this I/O. 555 | @return true on success and false on failure. If false is 556 | returned GetLastError() provides extended error information. 557 | */ 558 | ADBWIN_API bool __cdecl FAdbWriteEndpointSync(ADBAPIHANDLE adb_endpoint, 559 | void* buffer, 560 | unsigned long bytes_to_write, 561 | unsigned long* bytes_written, 562 | unsigned long time_out); 563 | 564 | /** \brief Gets overlapped I/O result for async I/O performed on the 565 | given endpoint. 566 | 567 | @param[in] adb_io_completion A handle to an I/O completion object returned 568 | from AdbRead/WriteAsync routines. 569 | @param[out] ovl_data Buffer for the copy of this object's OVERLAPPED 570 | structure. Can be NULL. 571 | @param[out] bytes_transferred Pointer to a variable that receives the 572 | number of bytes that were actually transferred by a read or write 573 | operation. See SDK doc on GetOvelappedResult for more information. 574 | Unlike regular GetOvelappedResult call this parameter can be NULL. 575 | @param[in] wait If this parameter is true, the method does not return 576 | until the operation has been completed. If this parameter is false 577 | and the operation is still pending, the method returns false and 578 | the GetLastError function returns ERROR_IO_INCOMPLETE. 579 | @return true if I/O has been completed or false on failure or if request 580 | is not yet completed. If false is returned GetLastError() provides 581 | extended error information. If GetLastError returns 582 | ERROR_IO_INCOMPLETE it means that I/O is not yet completed. 583 | */ 584 | ADBWIN_API bool __cdecl FAdbGetOvelappedIoResult(ADBAPIHANDLE adb_io_completion, 585 | LPOVERLAPPED overlapped, 586 | unsigned long* bytes_transferred, 587 | bool wait); 588 | 589 | /** \brief Checks if overlapped I/O has been completed. 590 | 591 | @param[in] adb_io_completion A handle to an I/O completion object returned 592 | from AdbRead/WriteAsync routines. 593 | @return true if I/O has been completed or false if it's still 594 | incomplete. Regardless of the returned value, caller should 595 | check GetLastError to validate that handle was OK. 596 | */ 597 | ADBWIN_API bool __cdecl FAdbHasOvelappedIoComplated(ADBAPIHANDLE adb_io_completion); 598 | 599 | /** \brief Closes handle previously opened with one of the API calls 600 | 601 | @param[in] adb_handle ADB handle previously opened with one of the API calls 602 | @return true on success or false on failure. If false is returned 603 | GetLastError() provides extended error information. 604 | */ 605 | ADBWIN_API bool __cdecl FAdbCloseHandle(ADBAPIHANDLE adb_handle); 606 | 607 | #endif // ANDROID_USB_API_ADBWINAPI_H__ 608 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rmdir build\ /s /q 3 | ::https://github.com/mstorsjo/llvm-mingw/releases/tag/20230919 4 | set CLANG_OPTION=-Xlinker /SECTION:.all,ERW -Xlinker /MERGE:.text=.all -Xlinker /MERGE:.rdata=.all -Xlinker /MERGE:.data=.all -Xlinker /STACK:0x40000,0x40000 -Wl,--entry=Main,-O3,-icf=all,-s,--strip-all,--gc-sections,--disable-dynamicbase,--disable-high-entropy-va,--disable-nxcompat,--disable-reloc-section,--disable-runtime-pseudo-reloc,--no-guard-cf,--no-guard-longjmp,--no-insert-timestamp,--no-seh -fno-addrsig -fno-split-stack -fno-stack-clash-protection -fno-stack-protector -mno-stack-arg-probe -nostartfiles -nodefaultlibs -lkernel32 -O3 -flto=full -ffunction-sections -fdata-sections -fno-exceptions -fdwarf-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables 5 | ::-Xlinker /SECTION:.all,ERW -Xlinker /MERGE:.text=.all -Xlinker /MERGE:.rdata=.all -Xlinker /MERGE:.data=.all 6 | ::native 7 | set CLANG_TARGET=-march=native 8 | set BUILD_DIR=build\native 9 | mkdir %BUILD_DIR% 10 | clang unlockhwbl_cmdline.c -o %BUILD_DIR%\unlockhwbl_cmdline.exe %CLANG_TARGET% %CLANG_OPTION% 11 | clang test_speed.c -o %BUILD_DIR%\test_speed.exe %CLANG_TARGET% %CLANG_OPTION% 12 | clang unlockhwbl_protocol.c -o %BUILD_DIR%\unlockhwbl_protocol.exe %CLANG_TARGET% %CLANG_OPTION% 13 | ::x86_64 14 | set CLANG_TARGET=-m64 -target x86_64-windows-gnu 15 | set BUILD_DIR=build\x86_64 16 | mkdir %BUILD_DIR% 17 | clang unlockhwbl_cmdline.c -o %BUILD_DIR%\unlockhwbl_cmdline.exe %CLANG_TARGET% %CLANG_OPTION% 18 | clang test_speed.c -o %BUILD_DIR%\test_speed.exe %CLANG_TARGET% %CLANG_OPTION% 19 | clang unlockhwbl_protocol.c -o %BUILD_DIR%\unlockhwbl_protocol.exe %CLANG_TARGET% %CLANG_OPTION% 20 | ::i686(x86) 21 | set CLANG_TARGET=-m32 -target i686-windows-gnu 22 | set BUILD_DIR=build\i686 23 | mkdir %BUILD_DIR% 24 | clang unlockhwbl_cmdline.c -o %BUILD_DIR%\unlockhwbl_cmdline.exe %CLANG_TARGET% %CLANG_OPTION% 25 | clang test_speed.c -o %BUILD_DIR%\test_speed.exe %CLANG_TARGET% %CLANG_OPTION% 26 | clang unlockhwbl_protocol.c -o %BUILD_DIR%\unlockhwbl_protocol.exe %CLANG_TARGET% %CLANG_OPTION% 27 | pause -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 重要 2 | 3 | 0. 可能随platform-tools更新而失效 4 | 5 | 1. 新版本依赖AdbWinApi.dll,老版本依赖fastboot.exe 6 | 7 | 3. 因为platform-tools没有x86_64的,所以新版本的x86_64可能无法运行,老版本则同时支持两种 8 | 9 | # 这是什么 10 | 11 | 用于解锁华为bootloader,它需要向fastboot输入`oem unlock <16位解锁码>`这条命令 12 | 13 | 你也可以自定义命令格式,此工具帮助你高效的用枚举法来不断的尝试16位解锁码 14 | 15 | 我们的工具是纯c写的,且使用比较底层的api,虽代码质量一般,但得益于clang llvm,它又小又快 16 | 17 | 在之前的版本(称为老版本,现在重命名为cmdline),它使用CreateProcess来运行命令行解锁 18 | 19 | (protocol,称为新版本)现在则直接使用fastboot协议通信,避免一些创建进程,连接/断开的开销 20 | 21 | 老版本的优势是命令行调用,具有高兼容性,并且相对于脚本语言来说具有高性能 22 | 23 | 新版本的优势是超高性能,但兼容性可能不好,且仅支持原版fastboot的一小部分功能(usb) 24 | 25 | platform-tools是cpp写的,这让我非常头疼,幸好最终我完成了新版本的工作 26 | 27 | 参考(官方的python和cpp版本,cpp版本就是我们常用的工具包): 28 | 29 | https://github.com/google/python-adb 30 | 31 | https://github.com/aosp-mirror/platform_system_core 32 | 33 | ps:我没有可供测试的设备,有问题欢迎反馈 34 | 35 | # 运行要求 36 | 37 | windows xp及以上 38 | 39 | release提供x86(i686)和x86_64体系的可执行文件 40 | 41 | 同时编译脚本里有编译native(专为本机)的命令,可以自己编译 42 | 43 | 注:native不一定是性能最好的,请根据实际情况为准 44 | 45 | # platform-tools 46 | 47 | 安卓提供的工具包,无论新老版本都需要,且不要改任何文件的名字(包括这个目录名) 48 | 49 | https://dl.google.com/android/repository/platform-tools-latest-windows.zip 50 | 51 | # build.bat 52 | 53 | 用于编译二进制文件,输出到build文件夹,里面的子文件夹标识了适用于什么机器 54 | 55 | temp文件夹编译结束后可以安全删除(如果有) 56 | 57 | 提供了clang的命令,脚本很短,只是为我自己写的! :) 58 | 59 | 使用的版本: 60 | 61 | https://github.com/mstorsjo/llvm-mingw/releases/tag/20230919 62 | 63 | # test_speed.exe 64 | 65 | 一个速度测试程序,测试更新解锁码的速度,不依赖platform-tools,Exit前会Sleep两秒 66 | 67 | 会不断记录更新10w次解锁码的耗时,然后打印10w次的平均耗时,可以读取通用的环境变量和写入log 68 | 69 | 使用了windows的高分辨率计时器,并且没有错误检查,耗时的单位需要自己想办法获取 70 | 71 | (因为新版本的加入,我将两个版本共同的部分单独抽出来了(初始化,程序退出和更新解锁码)) 72 | 73 | (而每个版本只专注于自己如何呼叫fastboot,这样还可以减小主函数和代码段的大小,有助于优化) 74 | 75 | 它可以测试源代码中新老版本共同部分的正确性,还可以测试/比较运行速度 76 | 77 | 这只是一个小demo,对于有些人来说可能有用,如果你不知道它是干嘛的,忽略就好 78 | 79 | # test_fastboot.exe 80 | 81 | 一个测试cmdline版本的程序,不依赖platform-tools,它只有i686版本,并且不在构建脚本里 82 | 83 | 把它复制到platform-tools\fastboot.exe即可 84 | 85 | 会从自己的stdin读取4字节数据,然后把读取到的数据写入自己的stdout 86 | 87 | 随后打印出数据长度(printf("%lu\n"))并退出 88 | 89 | cmdine版本从fastboot的stdout读取到OKAY四个字节时会视作解锁成功 90 | 91 | 它可以测试cmdline的进程间通信是否正确,以及等待超时是否正确等 92 | 93 | 这只是一个小demo,对于有些人来说可能有用,如果你不知道它是干嘛的,忽略就好 94 | 95 | # unlockhwbl_(cmdline | protocol).exe 96 | 97 | 主程序,程序运行完毕后不会暂停,如果需要查看信息请不要双击运行 98 | 99 | 没有打印信息的时候说明正在解锁,不要关闭,有几种情况会打印信息: 100 | 101 | 0. 会打印一段开头告诉你程序是活的(包括CODE_ORDER,CHAR_ORDER和第一个开始的解锁码) 102 | 103 | 1. 错误,然后退出程序(仅致命错误) 104 | 105 | 2. 解锁成功,打印成功的命令,然后退出程序(已经解锁,不需要再次输入命令) 106 | 107 | 3. 结尾会打印一个Exit告诉你程序是优雅关闭的(不论错误与否) 108 | 109 | 如果程序没有显示任何东西,可能是你的标准输出句柄有问题 110 | 111 | 如果程序直接退出,可能是出错了 112 | 113 | ## 重要 114 | 115 | 不需要命令行参数,我们使用环境变量传递参数 116 | 117 | 多余输入会被忽略,且程序内没有过多的错误检查 118 | 119 | 一切输入请参考文档,如果不规范可能导致严重问题 120 | 121 | ## 非致命错误有哪些 122 | 123 | 1. 获取标准输出句柄失败,此时程序不会显示任何内容 124 | 125 | 2. 打开log文件失败,此时会导致读取和写入log文件失败 126 | 127 | 3. 读取log文件失败,此时会从头开始枚举解锁码(视为没有log) 128 | 129 | 4. 写入log文件失败(此操作包括文件指针设置为0),此时log文件可能会损坏,或记录没有被保存等 130 | 131 | 5. 获取某个环境变量失败(包括不存在),此时这个环境变量使用默认值 132 | 133 | 7. SetConsoleCtrlHandler失败,此时程序可能不会尽可能优雅退出 134 | 135 | # code.log 136 | 137 | 由程序运行产生,储存了最后的code记录(索引表),用于实现保存进度功能 138 | 139 | 并不会储存你的CODE_ORDER,CHAR_ORDER,PRE_STRING和END_STRING,请自己妥善保管 140 | 141 | 程序仅在结束时写入一次log,但使用了SetConsoleCtrlHandler注册了一个优雅结束程序的函数 142 | 143 | 注册的这个函数收到任何信号都会结束程序,在以后的windows版本中可能导致程序神奇退出 144 | 145 | 经过测试,程序运行时(打印Exit时已经写入log)使用ctrl+c/break是安全的,直接关闭窗口不安全 146 | 147 | 参考"windows控制台程序如何优雅退出"文章,这做不到,至少很难,目前ctrl+c/break就足够了 148 | 149 | # 环境变量 150 | 151 | 注:如果输入了奇怪的值导致奇怪的问题,那么不是程序的问题 152 | 153 | ## 这两个是用于自定义枚举行为 154 | 155 | 自定义枚举行为的程序结构是这样(伪代码): 156 | 157 | ``` 158 | 159 | CHAR 解锁码[16]; 160 | 161 | CHAR CODE_ORDER[16]; 162 | 163 | LPSTR CHAR_ORDER = 获取环境变量("CHAR_ORDER"); 164 | 165 | CHAR 索引表[16] = {0}; 166 | 167 | CHAR 最大索引 = strlen(CHAR_ORDER)-1; 168 | 169 | //初始化CODE_ORDER 170 | 171 | LPSTR temp = 获取环境变量("CODE_ORDER"); 172 | 173 | for(i=0 ; i<16 ; i++){ 174 | 175 | CODE_ORDER[i] = temp[i]-'a'; 176 | 177 | } 178 | 179 | //更新解锁码 180 | 181 | for(i=0 ; i<16 ; i++){ 182 | 183 | //实际上并不会每次都刷新每一位,我们会判断,如果当前索引是最大索引 184 | 185 | //即需要进位,就将当前索引归0,然后再处理下一位 186 | 187 | //否则是不需要进位的,只需要把当前索引+1,然后退出循环 188 | 189 | //更新解锁码的速度是很快的,十几年前的cpu也可以每毫秒更新数万次,不要低估现代cpu的速度 190 | 191 | 解锁码[CODE_ORDER[i]] = CHAR_ORDER[idx[i]]; 192 | 193 | } 194 | 195 | ``` 196 | 197 | 1. "CODE_ORDER" 198 | 199 | 一个16字节字符串,每个字节代表一个索引(0-15),默认为"abcdefghijklmnop" 200 | 201 | 每个索引的数值+97就是这16个字符"abcdefghijklmnop"(可以理解为另一种十六进制!) 202 | 203 | 这个索引表代表了枚举解锁码中字节进位的顺序,长度应至少为16,超长的忽略 204 | 205 | 2. "CHAR_ORDER" 206 | 207 | 一个n字节字符串,代表解锁码每字节的字符枚举顺序,默认为"0123456789" 208 | 209 | 例如默认的0123456789代表每个字节从0枚举到9,然后进位 210 | 211 | 而9876543210则从9枚举到0,然后进位 212 | 213 | 这个参数让解锁码的可用字符不再局限于0123456789,长度不能超过255(正常情况下) 214 | 215 | 注:fastboot协议除了DATA之后的数据流,其他都是ascii文本,所以正常情况绝不会超长 216 | 217 | ## 接下来这两个是为了自定义命令而来 218 | 219 | 我们将一条fastboot命令视为四个部分: 220 | 221 | `<前置字符串><16位解锁码><后置字符串>\x00` 222 | 223 | 其中16位解锁码和结尾的空字节由程序填充,整条命令中有且只有结尾的一个空字节 224 | 225 | 用户想要自定义命令只需要修改前置字符串和后置字符串即可 226 | 227 | 注:整条命令(不包括空字节)长度不能超过256,也就是这两个变量的有效部分总共不超过240字节 228 | 229 | 3. "PRE_STRING" 230 | 231 | 前置字符串,默认"oem unlock " 232 | 233 | 4. "END_STRING" 234 | 235 | 后置字符串,默认"" 236 | 237 | 是的,就是空字符串!因为默认的命令是`oem unlock <16位解锁码>` 238 | 239 | (fastboot协议中并不需要这个空字节,但引入它可以极大简化某些操作) 240 | 241 | # 老版本的变量 242 | 243 | 暂无 244 | 245 | 注:fastboot进程完全继承环境变量和stdin,当前目录是platform-tools 246 | 247 | # 新版本的变量 248 | 249 | 1. "ANDROID_SERIAL" 250 | 251 | fastboot设备字符串(现版本为usb的serial number,即序列号),长度不可超过255 252 | 253 | 默认没有,尝试使用最后连接的usb设备(fastboot文档是这样写的,但源码里是第一个枚举到的设备) 254 | 255 | 注:0字节的环境变量内容(如果可以设置这种的话)和"没有"是不一样的 256 | 257 | (fastboot里是这样检查此变量的:如果没有则不检查,如果有则把它和usb的序列号和设备路径比较) 258 | 259 | (两者中有一个和它完全相同就可以,而设备路径目前未使用,所以此变量目前含义是usb序列号) 260 | 261 | (当然匹配设备并不只有这一个匹配即可,还需要一些其他参数的匹配,~~fastboot代码写的真丑啊~~) -------------------------------------------------------------------------------- /test_fastboot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(void){ 4 | HANDLE w,r; 5 | w=GetStdHandle(STD_OUTPUT_HANDLE); 6 | r=GetStdHandle(STD_INPUT_HANDLE); 7 | DWORD temp; 8 | char data[64]; 9 | ReadFile(r,data,4,&temp,0); 10 | printf("%lu\n",temp); 11 | WriteFile(w,data,4,&temp,0); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /test_speed.c: -------------------------------------------------------------------------------- 1 | #include "util.c" 2 | DWORD PrintNumber(int64_t i,char *data){ 3 | DWORD a=i; 4 | char temp; 5 | uint8_t b=0; 6 | while(a){ 7 | data[b]=(a%10)+'0'; 8 | a/=10; 9 | b++; 10 | } 11 | uint8_t c=b; 12 | data[b]=0; 13 | for(a=0,b--;adevice_name(应该是UNICODE) 90 | 转为ANSI拷贝到栈上2kb缓冲区(和entry_buffer一样大)的代码,但这个转换并不严谨 91 | 只是(char)wchar转换(还有个TODO:最好修改AdbWinApi.dll让它直接返回ANSI) 92 | 这段代码在find_usb_device函数,并且转换完的内容(是interface_name吗?)并没有被使用 93 | 同时在下面(do_usb_open,打开三个句柄后)里使用了AdbGetInterfaceName(包含错误检查) 94 | 将interface_name保存到usb_handle结尾的变长空间中,但它同样没有被使用 95 | 我将这两段多余的都去掉了,唯一的副作用应该是去除了AdbGetInterfaceName的错误检查 96 | 其实应该将AdbGetInterfaceName的内容保存到栈上空间,但我不知道分配多大的空间合适 97 | 因为它使用了变长空间而不是和entry_buffer一样大的2kb空间,并且使用u32表示空间大小 98 | 一个较为合理的猜测是同样分配2kb空间,但毕竟是猜测,所以我还是决定把这段删掉 99 | */ 100 | //打开interface,失败则枚举下一个设备 101 | handle.adb_interface=AdbCreateInterfaceByName(next_interface->device_name); 102 | if(handle.adb_interface == 0){ 103 | errmsg="AdbCreateInterfaceByName"; 104 | goto close_device_and_reset; 105 | } 106 | //打开读端管道(endpoint),失败则枚举下一个设备 107 | handle.adb_read_pipe = AdbOpenDefaultBulkReadEndpoint( 108 | handle.adb_interface, 109 | AdbOpenAccessTypeReadWrite, 110 | AdbOpenSharingModeReadWrite 111 | ); 112 | if(handle.adb_read_pipe == 0){ 113 | errmsg="AdbOpenDefaultBulkReadEndpoint"; 114 | goto close_device_and_reset; 115 | } 116 | //打开写端管道(endpoint),失败则枚举下一个设备 117 | handle.adb_write_pipe = AdbOpenDefaultBulkWriteEndpoint( 118 | handle.adb_interface, 119 | AdbOpenAccessTypeReadWrite, 120 | AdbOpenSharingModeReadWrite 121 | ); 122 | if(handle.adb_write_pipe == 0){ 123 | errmsg="AdbOpenDefaultBulkWriteEndpoint"; 124 | goto close_device_and_reset; 125 | } 126 | /*没用上,但包含错误检查 127 | //Check vendor and product id first(获取供应商和产品id?),失败则枚举下一个设备 128 | USB_DEVICE_DESCRIPTOR device_desc; 129 | if(AdbGetUsbDeviceDescriptor(handle.adb_interface,&device_desc)==0){ 130 | errmsg="AdbGetUsbDeviceDescriptor"; 131 | goto close_device_and_reset; 132 | } 133 | */ 134 | //Then check interface properties(获取接口属性),失败则枚举下一个设备 135 | if(AdbGetUsbInterfaceDescriptor(handle.adb_interface,&interf_desc)==0){ 136 | errmsg="AdbGetUsbInterfaceDescriptor"; 137 | goto close_device_and_reset; 138 | } 139 | //检查刚才获取的内容,不匹配则枚举下一个设备 140 | if( 141 | //必须有两个endpoint 142 | (interf_desc.bNumEndpoints != 2)|| 143 | //检查类型(属性?) 144 | (interf_desc.bInterfaceClass != 0xff)|| 145 | (interf_desc.bInterfaceSubClass != 0x42)|| 146 | (interf_desc.bInterfaceProtocol != 0x03) 147 | ){ 148 | errmsg="InterfaceDescriptorNotMatched"; 149 | goto close_device_and_reset; 150 | } 151 | //如果指定了设备名称,则需要匹配相同的usb名称(serial_number),不匹配则枚举下一个设备 152 | if(a){ 153 | //获取当前usb的序列号(serial_number),获取失败则枚举下一个设备 154 | temp=256; 155 | if(AdbGetSerialNumber( 156 | handle.adb_interface, 157 | serial_number, 158 | &temp, 159 | true 160 | )==0){ 161 | errmsg="AdbGetSerialNumber"; 162 | goto close_device_and_reset; 163 | } 164 | //比较两块储存序列号的内存(包括结尾0,即比较字符串),不相等则枚举下一个设备 165 | for(b=0;b 8 | #include 9 | //标准输出句柄,log文件句柄 10 | static HANDLE stdo,idxl; 11 | //一些局部变量的浅拷贝 12 | static uint8_t *__cidx,*__cmax,*__fcmd,*__clen,*__work; 13 | 14 | //终止程序的函数,尝试优雅的退出程序 15 | __attribute__((cold)) 16 | __attribute__((minsize)) 17 | static BOOL WINAPI Stop(DWORD dwCtrlType){ 18 | (*__work)=0; 19 | return TRUE; 20 | } 21 | 22 | //Read/WriteFile的简易同步包装 23 | __attribute__((noinline)) 24 | __attribute__((cold)) 25 | __attribute__((minsize)) 26 | DWORD Read(HANDLE file,void *data,DWORD len){ 27 | //Write/ReadFile在执行错误检查之前将len设置为0,而原始函数的错误返回也是0 28 | ReadFile(file,data,len,&len,0); 29 | return len; 30 | } 31 | 32 | __attribute__((noinline)) 33 | __attribute__((cold)) 34 | __attribute__((minsize)) 35 | DWORD Write(HANDLE file,void *data,DWORD len){ 36 | //所以这样只是不能进行null写入了,可以选择判断返回值==0为错误,或忽略 37 | WriteFile(file,data,len,&len,0); 38 | return len; 39 | } 40 | 41 | //打印字符串 42 | __attribute__((noinline)) 43 | __attribute__((cold)) 44 | __attribute__((minsize)) 45 | void Print(LPSTR str){ 46 | while(*str){ 47 | Write(stdo,str,1); 48 | str++; 49 | } 50 | Write(stdo,"\n",1); 51 | } 52 | 53 | //退出程序 54 | __attribute__((noinline)) 55 | __attribute__((cold)) 56 | __attribute__((minsize)) 57 | __attribute__((noreturn)) 58 | void Exit(void){ 59 | //执行附加的结束操作 60 | #ifdef __ExitEx 61 | __ExitEx; 62 | #endif 63 | //把索引表写入log文件 64 | SetFilePointer(idxl,0,0,0); 65 | Write(idxl,__cidx,16); 66 | //清理资源 67 | CloseHandle(idxl); 68 | Print("Exit"); 69 | //结束程序 70 | ExitProcess(0); 71 | } 72 | 73 | //程序的异常退出 74 | __attribute__((noinline)) 75 | __attribute__((cold)) 76 | __attribute__((minsize)) 77 | __attribute__((noreturn)) 78 | void Error(LPSTR str){ 79 | Print(str); 80 | Print("Error"); 81 | /* 82 | //弹出一个错误窗口,调试用 83 | LPSTR lpMsgBuf; 84 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,0,GetLastError(),0,&lpMsgBuf,0,0); 85 | MessageBoxA(0,lpMsgBuf,0,0); 86 | */ 87 | Exit(); 88 | } 89 | 90 | //将环境变量的值拷贝到缓冲区(包括0),失败则拷贝默认值(不检查长度),返回内容长度(不包括0) 91 | __attribute__((noinline)) 92 | __attribute__((cold)) 93 | __attribute__((minsize)) 94 | DWORD EnvGetA(LPSTR lpKey,LPSTR lpDefault,LPSTR lpBuffer,DWORD dwSize){ 95 | dwSize=GetEnvironmentVariableA(lpKey,lpBuffer,dwSize); 96 | if(dwSize==0){ 97 | do{ 98 | lpBuffer[dwSize]=lpDefault[dwSize]; 99 | }while(lpDefault[dwSize++]); 100 | } 101 | return dwSize-1; 102 | } 103 | 104 | //公用的初始化 105 | __attribute__((noinline)) 106 | __attribute__((cold)) 107 | __attribute__((minsize)) 108 | void UtilInit(LPSTR *__cseq,uint8_t *__cord){ 109 | #define cord (__cord) 110 | #define cseq (__cseq) 111 | #define fcmd (__fcmd) 112 | #define cidx (__cidx) 113 | #define cmax (*__cmax) 114 | #define clen (*__clen) 115 | DWORD temp; 116 | LPSTR code; 117 | //收到控制台信号时调用Stop函数 118 | SetConsoleCtrlHandler(Stop,TRUE); 119 | //初始化标准输出句柄 120 | stdo=GetStdHandle(STD_OUTPUT_HANDLE); 121 | //从环境变量获取自定义命令格式 122 | { 123 | DWORD lenp=EnvGetA("PRE_STRING","oem unlock ",fcmd,241); 124 | code=fcmd+lenp; 125 | DWORD lene=EnvGetA("END_STRING","",code+16,241-lenp); 126 | clen=lenp+16+lene; 127 | } 128 | //从环境变量获取自定义枚举行为 129 | { 130 | uint8_t env_cseq[17]; 131 | EnvGetA("CODE_ORDER","abcdefghijklmnop",env_cseq,17); 132 | Print(env_cseq); 133 | for(temp=0;temp<16;temp++) 134 | //储存code每一位的指针 135 | cseq[temp] = code+(env_cseq[temp]-'a'); 136 | } 137 | cmax=EnvGetA("CHAR_ORDER","0123456789",cord,256)-1; 138 | Print(cord); 139 | //打开储存索引表的文件 140 | idxl=CreateFileA( 141 | "code.log", 142 | FILE_READ_DATA|FILE_WRITE_DATA, 143 | FILE_SHARE_READ,0,OPEN_ALWAYS, 144 | FILE_FLAG_WRITE_THROUGH,0 145 | ); 146 | if( 147 | //文件是新建的(而不是已存在的),或者打开失败也算 148 | (GetLastError()!=ERROR_ALREADY_EXISTS)|| 149 | //或者读取失败,读取字节数不对也算 150 | (Read(idxl,cidx,16)!=16) 151 | ){ 152 | //将索引表全部归0(从头开始) 153 | for(temp=0;temp<16;temp++) 154 | cidx[temp]=0; 155 | } 156 | //把索引对应到解锁码 157 | for(temp=0;temp<16;temp++) 158 | *(cseq[temp]) = cord[cidx[temp]]; 159 | Print(fcmd); 160 | #undef cord 161 | #undef cseq 162 | #undef fcmd 163 | #undef cidx 164 | #undef cmax 165 | #undef clen 166 | } 167 | 168 | //更新解锁码,这个循环被展开会导致性能大幅下降,必须显示声明#pragma nounroll 169 | #define CodeUpdate() /*循环结束后不判断进位溢出*/\ 170 | for(cup_temp=0;cup_temp<16;cup_temp++){\ 171 | /*需要进位,这一位归0后继续处理下一位*/\ 172 | if(cidx[cup_temp]==cmax){\ 173 | cidx[cup_temp]=0;\ 174 | *(cseq[cup_temp]) = cord[0];\ 175 | /*不需要进位,这一位++后不再处理下一位*/\ 176 | }else{\ 177 | cidx[cup_temp]++;\ 178 | *(cseq[cup_temp]) = cord[cidx[cup_temp]];\ 179 | break;\ 180 | }\ 181 | } 182 | 183 | //使用UtilInit 184 | #define Init() \ 185 | /*CODE_ORDER*/\ 186 | LPSTR cseq[16];\ 187 | /*解锁码索引表,每个索引的最大值,CHAR_ORDER,fastboot命令和长度,temp,运行标识*/\ 188 | uint8_t cidx[16],cmax,cord[256],fcmd[257],clen,cup_temp,work=1;\ 189 | __cidx=cidx;\ 190 | __cmax=&cmax;\ 191 | __fcmd=fcmd;\ 192 | __clen=&clen;\ 193 | __work=&work;\ 194 | UtilInit(cseq,cord); --------------------------------------------------------------------------------