1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2014 Karlson2k (Evgeny Grin) 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library. 17 If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /** 21 * @file platform/w32functions.h 22 * @brief internal functions for W32 systems 23 * @author Karlson2k (Evgeny Grin) 24 */ 25 26 #include "w32functions.h" 27 #include <errno.h> 28 #include <winsock2.h> 29 #include <string.h> 30 #include <stdint.h> 31 #include <time.h> 32 #include <stdio.h> 33 #include <stdarg.h> 34 35 36 /** 37 * Return errno equivalent of last winsock error 38 * @return errno equivalent of last winsock error 39 */ 40 int MHD_W32_errno_from_winsock_(void) 41 { 42 switch(WSAGetLastError()) 43 { 44 case 0: return 0; 45 case WSA_INVALID_HANDLE: return EBADF; 46 case WSA_NOT_ENOUGH_MEMORY: return ENOMEM; 47 case WSA_INVALID_PARAMETER: return EINVAL; 48 case WSAEINTR: return EINTR; 49 case WSAEWOULDBLOCK: return EWOULDBLOCK; 50 case WSAEINPROGRESS: return EINPROGRESS; 51 case WSAEALREADY: return EALREADY; 52 case WSAENOTSOCK: return ENOTSOCK; 53 case WSAEDESTADDRREQ: return EDESTADDRREQ; 54 case WSAEMSGSIZE: return EMSGSIZE; 55 case WSAEPROTOTYPE: return EPROTOTYPE; 56 case WSAENOPROTOOPT: return ENOPROTOOPT; 57 case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT; 58 case WSAESOCKTNOSUPPORT: return ESOCKTNOSUPPORT; 59 case WSAEOPNOTSUPP: return EOPNOTSUPP; 60 case WSAEPFNOSUPPORT: return EPFNOSUPPORT; 61 case WSAEAFNOSUPPORT: return EAFNOSUPPORT; 62 case WSAEADDRINUSE: return EADDRINUSE; 63 case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL; 64 case WSAENETDOWN: return ENETDOWN; 65 case WSAENETUNREACH: return ENETUNREACH; 66 case WSAENETRESET: return ENETRESET; 67 case WSAECONNABORTED: return ECONNABORTED; 68 case WSAECONNRESET: return ECONNRESET; 69 case WSAENOBUFS: return ENOBUFS; 70 case WSAEISCONN: return EISCONN; 71 case WSAENOTCONN: return ENOTCONN; 72 case WSAESHUTDOWN: return ESHUTDOWN; 73 case WSAETOOMANYREFS: return ETOOMANYREFS; 74 case WSAETIMEDOUT: return ETIMEDOUT; 75 case WSAECONNREFUSED: return ECONNREFUSED; 76 case WSAELOOP: return ELOOP; 77 case WSAENAMETOOLONG: return ENAMETOOLONG; 78 case WSAEHOSTDOWN: return EHOSTDOWN; 79 case WSAEHOSTUNREACH: return EHOSTUNREACH; 80 case WSAENOTEMPTY: return ENOTEMPTY; 81 case WSAEPROCLIM: return EPROCLIM; 82 case WSAEUSERS: return EUSERS; 83 case WSAEDQUOT: return EDQUOT; 84 case WSAESTALE: return ESTALE; 85 case WSAEREMOTE: return EREMOTE; 86 case WSAEINVAL: return EINVAL; 87 case WSAEFAULT: return EFAULT; 88 case WSANO_DATA: return ENODATA; 89 /* Rough equivalents */ 90 case WSAEDISCON: return ECONNRESET; 91 case WSAEINVALIDPROCTABLE: return EFAULT; 92 case WSASYSNOTREADY: 93 case WSANOTINITIALISED: 94 case WSASYSCALLFAILURE: return ENOBUFS; 95 case WSAVERNOTSUPPORTED: return EOPNOTSUPP; 96 case WSAEREFUSED: return EIO; 97 } 98 return EINVAL; 99 } 100 101 /** 102 * Return pointer to string description of errnum error 103 * Works fine with both standard errno errnums 104 * and errnums from MHD_W32_errno_from_winsock_ 105 * @param errnum the errno or value from MHD_W32_errno_from_winsock_() 106 * @return pointer to string description of error 107 */ 108 const char* MHD_W32_strerror_(int errnum) 109 { 110 switch(errnum) 111 { 112 case 0: 113 return "No error"; 114 case EWOULDBLOCK: 115 return "Operation would block"; 116 case EINPROGRESS: 117 return "Connection already in progress"; 118 case EALREADY: 119 return "Socket already connected"; 120 case ENOTSOCK: 121 return "Socket operation on non-socket"; 122 case EDESTADDRREQ: 123 return "Destination address required"; 124 case EMSGSIZE: 125 return "Message too long"; 126 case EPROTOTYPE: 127 return "Protocol wrong type for socket"; 128 case ENOPROTOOPT: 129 return "Protocol not available"; 130 case EPROTONOSUPPORT: 131 return "Unknown protocol"; 132 case ESOCKTNOSUPPORT: 133 return "Socket type not supported"; 134 case EOPNOTSUPP: 135 return "Operation not supported on socket"; 136 case EPFNOSUPPORT: 137 return "Protocol family not supported"; 138 case EAFNOSUPPORT: 139 return "Address family not supported by protocol family"; 140 case EADDRINUSE: 141 return "Address already in use"; 142 case EADDRNOTAVAIL: 143 return "Cannot assign requested address"; 144 case ENETDOWN: 145 return "Network is down"; 146 case ENETUNREACH: 147 return "Network is unreachable"; 148 case ENETRESET: 149 return "Network dropped connection on reset"; 150 case ECONNABORTED: 151 return "Software caused connection abort"; 152 case ECONNRESET: 153 return "Connection reset by peer"; 154 case ENOBUFS: 155 return "No system resources available"; 156 case EISCONN: 157 return "Socket is already connected"; 158 case ENOTCONN: 159 return "Socket is not connected"; 160 case ESHUTDOWN: 161 return "Can't send after socket shutdown"; 162 case ETOOMANYREFS: 163 return "Too many references: cannot splice"; 164 case ETIMEDOUT: 165 return "Connection timed out"; 166 case ECONNREFUSED: 167 return "Connection refused"; 168 case ELOOP: 169 return "Cannot translate name"; 170 case EHOSTDOWN: 171 return "Host is down"; 172 case EHOSTUNREACH: 173 return "Host is unreachable"; 174 case EPROCLIM: 175 return "Too many processes"; 176 case EUSERS: 177 return "Too many users"; 178 case EDQUOT: 179 return "Disk quota exceeded"; 180 case ESTALE: 181 return "Stale file handle reference"; 182 case EREMOTE: 183 return "Resource is remote"; 184 case ENODATA: 185 return "No data available"; 186 } 187 return strerror(errnum); 188 } 189 190 /** 191 * Return pointer to string description of last winsock error 192 * @return pointer to string description of last winsock error 193 */ 194 const char* MHD_W32_strerror_last_winsock_(void) 195 { 196 switch (WSAGetLastError()) 197 { 198 case 0: 199 return "No error"; 200 case WSA_INVALID_HANDLE: 201 return "Specified event object handle is invalid"; 202 case WSA_NOT_ENOUGH_MEMORY: 203 return "Insufficient memory available"; 204 case WSA_INVALID_PARAMETER: 205 return "One or more parameters are invalid"; 206 case WSA_OPERATION_ABORTED: 207 return "Overlapped operation aborted"; 208 case WSA_IO_INCOMPLETE: 209 return "Overlapped I/O event object not in signaled state"; 210 case WSA_IO_PENDING: 211 return "Overlapped operations will complete later"; 212 case WSAEINTR: 213 return "Interrupted function call"; 214 case WSAEBADF: 215 return "File handle is not valid"; 216 case WSAEACCES: 217 return "Permission denied"; 218 case WSAEFAULT: 219 return "Bad address"; 220 case WSAEINVAL: 221 return "Invalid argument"; 222 case WSAEMFILE: 223 return "Too many open files"; 224 case WSAEWOULDBLOCK: 225 return "Resource temporarily unavailable"; 226 case WSAEINPROGRESS: 227 return "Operation now in progress"; 228 case WSAEALREADY: 229 return "Operation already in progress"; 230 case WSAENOTSOCK: 231 return "Socket operation on nonsocket"; 232 case WSAEDESTADDRREQ: 233 return "Destination address required"; 234 case WSAEMSGSIZE: 235 return "Message too long"; 236 case WSAEPROTOTYPE: 237 return "Protocol wrong type for socket"; 238 case WSAENOPROTOOPT: 239 return "Bad protocol option"; 240 case WSAEPROTONOSUPPORT: 241 return "Protocol not supported"; 242 case WSAESOCKTNOSUPPORT: 243 return "Socket type not supported"; 244 case WSAEOPNOTSUPP: 245 return "Operation not supported"; 246 case WSAEPFNOSUPPORT: 247 return "Protocol family not supported"; 248 case WSAEAFNOSUPPORT: 249 return "Address family not supported by protocol family"; 250 case WSAEADDRINUSE: 251 return "Address already in use"; 252 case WSAEADDRNOTAVAIL: 253 return "Cannot assign requested address"; 254 case WSAENETDOWN: 255 return "Network is down"; 256 case WSAENETUNREACH: 257 return "Network is unreachable"; 258 case WSAENETRESET: 259 return "Network dropped connection on reset"; 260 case WSAECONNABORTED: 261 return "Software caused connection abort"; 262 case WSAECONNRESET: 263 return "Connection reset by peer"; 264 case WSAENOBUFS: 265 return "No buffer space available"; 266 case WSAEISCONN: 267 return "Socket is already connected"; 268 case WSAENOTCONN: 269 return "Socket is not connected"; 270 case WSAESHUTDOWN: 271 return "Cannot send after socket shutdown"; 272 case WSAETOOMANYREFS: 273 return "Too many references"; 274 case WSAETIMEDOUT: 275 return "Connection timed out"; 276 case WSAECONNREFUSED: 277 return "Connection refused"; 278 case WSAELOOP: 279 return "Cannot translate name"; 280 case WSAENAMETOOLONG: 281 return "Name too long"; 282 case WSAEHOSTDOWN: 283 return "Host is down"; 284 case WSAEHOSTUNREACH: 285 return "No route to host"; 286 case WSAENOTEMPTY: 287 return "Directory not empty"; 288 case WSAEPROCLIM: 289 return "Too many processes"; 290 case WSAEUSERS: 291 return "User quota exceeded"; 292 case WSAEDQUOT: 293 return "Disk quota exceeded"; 294 case WSAESTALE: 295 return "Stale file handle reference"; 296 case WSAEREMOTE: 297 return "Item is remote"; 298 case WSASYSNOTREADY: 299 return "Network subsystem is unavailable"; 300 case WSAVERNOTSUPPORTED: 301 return "Winsock.dll version out of range"; 302 case WSANOTINITIALISED: 303 return "Successful WSAStartup not yet performed"; 304 case WSAEDISCON: 305 return "Graceful shutdown in progress"; 306 case WSAENOMORE: 307 return "No more results"; 308 case WSAECANCELLED: 309 return "Call has been canceled"; 310 case WSAEINVALIDPROCTABLE: 311 return "Procedure call table is invalid"; 312 case WSAEINVALIDPROVIDER: 313 return "Service provider is invalid"; 314 case WSAEPROVIDERFAILEDINIT: 315 return "Service provider failed to initialize"; 316 case WSASYSCALLFAILURE: 317 return "System call failure"; 318 case WSASERVICE_NOT_FOUND: 319 return "Service not found"; 320 case WSATYPE_NOT_FOUND: 321 return "Class type not found"; 322 case WSA_E_NO_MORE: 323 return "No more results"; 324 case WSA_E_CANCELLED: 325 return "Call was canceled"; 326 case WSAEREFUSED: 327 return "Database query was refused"; 328 case WSAHOST_NOT_FOUND: 329 return "Host not found"; 330 case WSATRY_AGAIN: 331 return "Nonauthoritative host not found"; 332 case WSANO_RECOVERY: 333 return "This is a nonrecoverable error"; 334 case WSANO_DATA: 335 return "Valid name, no data record of requested type"; 336 case WSA_QOS_RECEIVERS: 337 return "QoS receivers"; 338 case WSA_QOS_SENDERS: 339 return "QoS senders"; 340 case WSA_QOS_NO_SENDERS: 341 return "No QoS senders"; 342 case WSA_QOS_NO_RECEIVERS: 343 return "QoS no receivers"; 344 case WSA_QOS_REQUEST_CONFIRMED: 345 return "QoS request confirmed"; 346 case WSA_QOS_ADMISSION_FAILURE: 347 return "QoS admission error"; 348 case WSA_QOS_POLICY_FAILURE: 349 return "QoS policy failure"; 350 case WSA_QOS_BAD_STYLE: 351 return "QoS bad style"; 352 case WSA_QOS_BAD_OBJECT: 353 return "QoS bad object"; 354 case WSA_QOS_TRAFFIC_CTRL_ERROR: 355 return "QoS traffic control error"; 356 case WSA_QOS_GENERIC_ERROR: 357 return "QoS generic error"; 358 case WSA_QOS_ESERVICETYPE: 359 return "QoS service type error"; 360 case WSA_QOS_EFLOWSPEC: 361 return "QoS flowspec error"; 362 case WSA_QOS_EPROVSPECBUF: 363 return "Invalid QoS provider buffer"; 364 case WSA_QOS_EFILTERSTYLE: 365 return "Invalid QoS filter style"; 366 case WSA_QOS_EFILTERTYPE: 367 return "Invalid QoS filter type"; 368 case WSA_QOS_EFILTERCOUNT: 369 return "Incorrect QoS filter count"; 370 case WSA_QOS_EOBJLENGTH: 371 return "Invalid QoS object length"; 372 case WSA_QOS_EFLOWCOUNT: 373 return "Incorrect QoS flow count"; 374 case WSA_QOS_EUNKOWNPSOBJ: 375 return "Unrecognized QoS object"; 376 case WSA_QOS_EPOLICYOBJ: 377 return "Invalid QoS policy object"; 378 case WSA_QOS_EFLOWDESC: 379 return "Invalid QoS flow descriptor"; 380 case WSA_QOS_EPSFLOWSPEC: 381 return "Invalid QoS provider-specific flowspec"; 382 case WSA_QOS_EPSFILTERSPEC: 383 return "Invalid QoS provider-specific filterspec"; 384 case WSA_QOS_ESDMODEOBJ: 385 return "Invalid QoS shape discard mode object"; 386 case WSA_QOS_ESHAPERATEOBJ: 387 return "Invalid QoS shaping rate object"; 388 case WSA_QOS_RESERVED_PETYPE: 389 return "Reserved policy QoS element type"; 390 } 391 return "Unknown winsock error"; 392 } 393 394 /** 395 * Set last winsock error to equivalent of given errno value 396 * @param errnum the errno value to set 397 */ 398 void MHD_W32_set_last_winsock_error_(int errnum) 399 { 400 switch (errnum) 401 { 402 case 0: 403 WSASetLastError(0); 404 break; 405 case EBADF: 406 WSASetLastError(WSA_INVALID_HANDLE); 407 break; 408 case ENOMEM: 409 WSASetLastError(WSA_NOT_ENOUGH_MEMORY); 410 break; 411 case EINVAL: 412 WSASetLastError(WSA_INVALID_PARAMETER); 413 break; 414 case EINTR: 415 WSASetLastError(WSAEINTR); 416 break; 417 case EWOULDBLOCK: 418 WSASetLastError(WSAEWOULDBLOCK); 419 break; 420 case EINPROGRESS: 421 WSASetLastError(WSAEINPROGRESS); 422 break; 423 case EALREADY: 424 WSASetLastError(WSAEALREADY); 425 break; 426 case ENOTSOCK: 427 WSASetLastError(WSAENOTSOCK); 428 break; 429 case EDESTADDRREQ: 430 WSASetLastError(WSAEDESTADDRREQ); 431 break; 432 case EMSGSIZE: 433 WSASetLastError(WSAEMSGSIZE); 434 break; 435 case EPROTOTYPE: 436 WSASetLastError(WSAEPROTOTYPE); 437 break; 438 case ENOPROTOOPT: 439 WSASetLastError(WSAENOPROTOOPT); 440 break; 441 case EPROTONOSUPPORT: 442 WSASetLastError(WSAEPROTONOSUPPORT); 443 break; 444 case ESOCKTNOSUPPORT: 445 WSASetLastError(WSAESOCKTNOSUPPORT); 446 break; 447 case EOPNOTSUPP: 448 WSASetLastError(WSAEOPNOTSUPP); 449 break; 450 case EPFNOSUPPORT: 451 WSASetLastError(WSAEPFNOSUPPORT); 452 break; 453 case EAFNOSUPPORT: 454 WSASetLastError(WSAEAFNOSUPPORT); 455 break; 456 case EADDRINUSE: 457 WSASetLastError(WSAEADDRINUSE); 458 break; 459 case EADDRNOTAVAIL: 460 WSASetLastError(WSAEADDRNOTAVAIL); 461 break; 462 case ENETDOWN: 463 WSASetLastError(WSAENETDOWN); 464 break; 465 case ENETUNREACH: 466 WSASetLastError(WSAENETUNREACH); 467 break; 468 case ENETRESET: 469 WSASetLastError(WSAENETRESET); 470 break; 471 case ECONNABORTED: 472 WSASetLastError(WSAECONNABORTED); 473 break; 474 case ECONNRESET: 475 WSASetLastError(WSAECONNRESET); 476 break; 477 case ENOBUFS: 478 WSASetLastError(WSAENOBUFS); 479 break; 480 case EISCONN: 481 WSASetLastError(WSAEISCONN); 482 break; 483 case ENOTCONN: 484 WSASetLastError(WSAENOTCONN); 485 break; 486 case ESHUTDOWN: 487 WSASetLastError(WSAESHUTDOWN); 488 break; 489 case ETOOMANYREFS: 490 WSASetLastError(WSAETOOMANYREFS); 491 break; 492 case ETIMEDOUT: 493 WSASetLastError(WSAETIMEDOUT); 494 break; 495 case ECONNREFUSED: 496 WSASetLastError(WSAECONNREFUSED); 497 break; 498 case ELOOP: 499 WSASetLastError(WSAELOOP); 500 break; 501 case ENAMETOOLONG: 502 WSASetLastError(WSAENAMETOOLONG); 503 break; 504 case EHOSTDOWN: 505 WSASetLastError(WSAEHOSTDOWN); 506 break; 507 case EHOSTUNREACH: 508 WSASetLastError(WSAEHOSTUNREACH); 509 break; 510 case ENOTEMPTY: 511 WSASetLastError(WSAENOTEMPTY); 512 break; 513 case EPROCLIM: 514 WSASetLastError(WSAEPROCLIM); 515 break; 516 case EUSERS: 517 WSASetLastError(WSAEUSERS); 518 break; 519 case EDQUOT: 520 WSASetLastError(WSAEDQUOT); 521 break; 522 case ESTALE: 523 WSASetLastError(WSAESTALE); 524 break; 525 case EREMOTE: 526 WSASetLastError(WSAEREMOTE); 527 break; 528 case EFAULT: 529 WSASetLastError(WSAEFAULT); 530 break; 531 case ENODATA: 532 WSASetLastError(WSANO_DATA); 533 break; 534 #if EAGAIN != EWOULDBLOCK 535 case EAGAIN: 536 WSASetLastError(WSAEWOULDBLOCK); 537 break; 538 #endif 539 /* Rough equivalent */ 540 case EIO: 541 WSASetLastError(WSAEREFUSED); 542 break; 543 544 default: /* Unmapped errors */ 545 WSASetLastError(WSAENOBUFS); 546 break; 547 } 548 } 549 550 /** 551 * Create pair of mutually connected TCP/IP sockets on loopback address 552 * @param sockets_pair array to receive resulted sockets 553 * @return zero on success, -1 otherwise 554 */ 555 int MHD_W32_pair_of_sockets_(SOCKET sockets_pair[2]) 556 { 557 int i; 558 if (!sockets_pair) 559 { 560 errno = EINVAL; 561 return -1; 562 } 563 564 #define PAIRMAXTRYIES 800 565 for (i = 0; i < PAIRMAXTRYIES; i++) 566 { 567 struct sockaddr_in listen_addr; 568 SOCKET listen_s; 569 static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */ 570 int addr_len = c_addinlen; 571 int opt = 1; 572 573 listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 574 if (INVALID_SOCKET == listen_s) 575 break; /* can't create even single socket */ 576 577 listen_addr.sin_family = AF_INET; 578 listen_addr.sin_port = htons(0); 579 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 580 if (0 == bind(listen_s, (struct sockaddr*) &listen_addr, c_addinlen) 581 && 0 == listen(listen_s, 1) 582 && 0 == getsockname(listen_s, (struct sockaddr*) &listen_addr, 583 &addr_len)) 584 { 585 SOCKET client_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 586 if (INVALID_SOCKET != client_s) 587 { 588 if (0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt) 589 && (0 == connect(client_s, (struct sockaddr*) &listen_addr, c_addinlen) 590 || WSAGetLastError() == WSAEWOULDBLOCK)) 591 { 592 struct sockaddr_in accepted_from_addr; 593 addr_len = c_addinlen; 594 SOCKET server_s = accept(listen_s, 595 (struct sockaddr*) &accepted_from_addr, &addr_len); 596 if (INVALID_SOCKET != server_s) 597 { 598 struct sockaddr_in client_addr; 599 addr_len = c_addinlen; 600 opt = 0; 601 if (0 == getsockname(client_s, (struct sockaddr*) &client_addr, &addr_len) 602 && accepted_from_addr.sin_family == client_addr.sin_family 603 && accepted_from_addr.sin_port == client_addr.sin_port 604 && accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr 605 && 0 == ioctlsocket(client_s, FIONBIO, (u_long*) &opt) 606 && 0 == ioctlsocket(server_s, FIONBIO, (u_long*) &opt)) 607 { 608 closesocket(listen_s); 609 sockets_pair[0] = client_s; 610 sockets_pair[1] = server_s; 611 return 0; 612 } 613 closesocket(server_s); 614 } 615 } 616 closesocket(client_s); 617 } 618 } 619 closesocket(listen_s); 620 } 621 622 sockets_pair[0] = INVALID_SOCKET; 623 sockets_pair[1] = INVALID_SOCKET; 624 return -1; 625 } 626 627 /** 628 * Static variable used by pseudo random number generator 629 */ 630 static int32_t rnd_val = 0; 631 /** 632 * Generate 31-bit pseudo random number. 633 * Function initialize itself at first call to current time. 634 * @return 31-bit pseudo random number. 635 */ 636 int MHD_W32_random_(void) 637 { 638 if (0 == rnd_val) 639 rnd_val = (int32_t)time(NULL); 640 /* stolen from winsup\cygwin\random.cc */ 641 rnd_val = (16807 * (rnd_val % 127773) - 2836 * (rnd_val / 127773)) 642 & 0x7fffffff; 643 return (int)rnd_val; 644 } 645 646 /* Emulate snprintf function on W32 */ 647 int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ...) 648 { 649 int ret; 650 va_list args; 651 if (0 != n && NULL != s ) 652 { 653 va_start(args, format); 654 ret = _vsnprintf(s, n, format, args); 655 va_end(args); 656 if (n == ret) 657 s[n - 1] = 0; 658 if (ret >= 0) 659 return ret; 660 } 661 va_start(args, format); 662 ret = _vscprintf(format, args); 663 va_end(args); 664 if (0 <= ret && 0 != n && NULL == s) 665 return -1; 666 667 return ret; 668 } 669 670 #ifdef _MSC_FULL_VER 671 /** 672 * Set thread name 673 * @param thread_id ID of thread, -1 for current thread 674 * @param thread_name name to set 675 */ 676 void W32_SetThreadName(const DWORD thread_id, const char *thread_name) 677 { 678 static const DWORD VC_SETNAME_EXC = 0x406D1388; 679 #pragma pack(push,8) 680 struct thread_info_struct 681 { 682 DWORD type; // Must be 0x1000. 683 LPCSTR name; // Pointer to name (in user address space). 684 DWORD ID; // Thread ID (-1=caller thread). 685 DWORD flags; // Reserved for future use, must be zero. 686 } thread_info; 687 #pragma pack(pop) 688 689 if (NULL == thread_name) 690 return; 691 692 thread_info.type = 0x1000; 693 thread_info.name = thread_name; 694 thread_info.ID = thread_id; 695 thread_info.flags = 0; 696 697 __try 698 { /* This exception is intercepted by debugger */ 699 RaiseException(VC_SETNAME_EXC, 0, sizeof(thread_info) / sizeof(ULONG_PTR), (ULONG_PTR*)&thread_info); 700 } 701 __except (EXCEPTION_EXECUTE_HANDLER) 702 {} 703 } 704 #endif /* _MSC_FULL_VER */ 705