1 /* WIN32.C 2 * 3 * (c) 1995 Microsoft Corporation. All rights reserved. 4 * Developed by hip communications inc. 5 * Portions (c) 1993 Intergraph Corporation. All rights reserved. 6 * 7 * You may distribute under the terms of either the GNU General Public 8 * License or the Artistic License, as specified in the README file. 9 */ 10 #define PERLIO_NOT_STDIO 0 11 #define WIN32_LEAN_AND_MEAN 12 #define WIN32IO_IS_STDIO 13 #include <tchar.h> 14 15 #ifdef __GNUC__ 16 # define Win32_Winsock 17 #endif 18 19 #ifndef _WIN32_WINNT 20 # define _WIN32_WINNT 0x0500 /* needed for CreateHardlink() etc. */ 21 #endif 22 23 #include <windows.h> 24 25 #ifndef HWND_MESSAGE 26 # define HWND_MESSAGE ((HWND)-3) 27 #endif 28 29 #ifndef PROCESSOR_ARCHITECTURE_AMD64 30 # define PROCESSOR_ARCHITECTURE_AMD64 9 31 #endif 32 33 #ifndef WC_NO_BEST_FIT_CHARS 34 # define WC_NO_BEST_FIT_CHARS 0x00000400 35 #endif 36 37 #include <winnt.h> 38 #include <commctrl.h> 39 #include <tlhelp32.h> 40 #include <io.h> 41 #include <signal.h> 42 43 /* #include "config.h" */ 44 45 46 #define PerlIO FILE 47 48 #include <sys/stat.h> 49 #include "EXTERN.h" 50 #include "perl.h" 51 52 #define NO_XSLOCKS 53 #define PERL_NO_GET_CONTEXT 54 #include "XSUB.h" 55 56 #include <fcntl.h> 57 #ifndef __GNUC__ 58 /* assert.h conflicts with #define of assert in perl.h */ 59 # include <assert.h> 60 #endif 61 62 #include <string.h> 63 #include <stdarg.h> 64 #include <float.h> 65 #include <time.h> 66 #include <sys/utime.h> 67 68 #ifdef __GNUC__ 69 /* Mingw32 defaults to globing command line 70 * So we turn it off like this: 71 */ 72 int _CRT_glob = 0; 73 #endif 74 75 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1) 76 /* Mingw32-1.1 is missing some prototypes */ 77 START_EXTERN_C 78 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode); 79 FILE * _wfdopen(int nFd, LPCWSTR wszMode); 80 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream); 81 int _flushall(); 82 int _fcloseall(); 83 END_EXTERN_C 84 #endif 85 86 #define EXECF_EXEC 1 87 #define EXECF_SPAWN 2 88 #define EXECF_SPAWN_NOWAIT 3 89 90 #if defined(PERL_IMPLICIT_SYS) 91 # undef getlogin 92 # define getlogin g_getlogin 93 #endif 94 95 /* VS2005 (MSC version 14) provides a mechanism to set an invalid 96 * parameter handler. This functionality is not available in the 97 * 64-bit compiler from the Platform SDK, which unfortunately also 98 * believes itself to be MSC version 14. 99 * 100 * There is no #define related to _set_invalid_parameter_handler(), 101 * but we can check for one of the constants defined for 102 * _set_abort_behavior(), which was introduced into stdlib.h at 103 * the same time. 104 */ 105 106 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG) 107 # define SET_INVALID_PARAMETER_HANDLER 108 #endif 109 110 #ifdef SET_INVALID_PARAMETER_HANDLER 111 static BOOL set_silent_invalid_parameter_handler(BOOL newvalue); 112 static void my_invalid_parameter_handler(const wchar_t* expression, 113 const wchar_t* function, const wchar_t* file, 114 unsigned int line, uintptr_t pReserved); 115 #endif 116 117 #ifndef WIN32_NO_REGISTRY 118 static char* get_regstr_from(HKEY hkey, const char *valuename, SV **svp); 119 static char* get_regstr(const char *valuename, SV **svp); 120 #endif 121 122 static char* get_emd_part(SV **prev_pathp, STRLEN *const len, 123 char *trailing, ...); 124 static char* win32_get_xlib(const char *pl, 125 WIN32_NO_REGISTRY_M_(const char *xlib) 126 const char *libname, STRLEN *const len); 127 128 static BOOL has_shell_metachars(const char *ptr); 129 static long tokenize(const char *str, char **dest, char ***destv); 130 static void get_shell(void); 131 static char* find_next_space(const char *s); 132 static int do_spawn2(pTHX_ const char *cmd, int exectype); 133 static int do_spawn2_handles(pTHX_ const char *cmd, int exectype, 134 const int *handles); 135 static int do_spawnvp_handles(int mode, const char *cmdname, 136 const char * const *argv, const int *handles); 137 static PerlIO * do_popen(const char *mode, const char *command, IV narg, 138 SV **args); 139 static long find_pid(pTHX_ int pid); 140 static void remove_dead_process(long child); 141 static int terminate_process(DWORD pid, HANDLE process_handle, int sig); 142 static int my_killpg(int pid, int sig); 143 static int my_kill(int pid, int sig); 144 static void out_of_memory(void); 145 static char* wstr_to_str(const wchar_t* wstr); 146 static long filetime_to_clock(PFILETIME ft); 147 static BOOL filetime_from_time(PFILETIME ft, time_t t); 148 static char* create_command_line(char *cname, STRLEN clen, 149 const char * const *args); 150 static char* qualified_path(const char *cmd, bool other_exts); 151 static void ansify_path(void); 152 static LRESULT win32_process_message(HWND hwnd, UINT msg, 153 WPARAM wParam, LPARAM lParam); 154 155 #ifdef USE_ITHREADS 156 static long find_pseudo_pid(pTHX_ int pid); 157 static void remove_dead_pseudo_process(long child); 158 static HWND get_hwnd_delay(pTHX, long child, DWORD tries); 159 #endif 160 161 #ifdef HAVE_INTERP_INTERN 162 static void win32_csighandler(int sig); 163 #endif 164 165 START_EXTERN_C 166 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE; 167 char w32_module_name[MAX_PATH+1]; 168 #ifdef WIN32_DYN_IOINFO_SIZE 169 Size_t w32_ioinfo_size;/* avoid 0 extend op b4 mul, otherwise could be a U8 */ 170 #endif 171 END_EXTERN_C 172 173 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""}; 174 175 #ifndef WIN32_NO_REGISTRY 176 /* initialized by Perl_win32_init/PERL_SYS_INIT */ 177 static HKEY HKCU_Perl_hnd; 178 static HKEY HKLM_Perl_hnd; 179 #endif 180 181 #ifdef SET_INVALID_PARAMETER_HANDLER 182 static BOOL silent_invalid_parameter_handler = FALSE; 183 184 static BOOL 185 set_silent_invalid_parameter_handler(BOOL newvalue) 186 { 187 BOOL oldvalue = silent_invalid_parameter_handler; 188 # ifdef _DEBUG 189 silent_invalid_parameter_handler = newvalue; 190 # endif 191 return oldvalue; 192 } 193 194 static void 195 my_invalid_parameter_handler(const wchar_t* expression, 196 const wchar_t* function, 197 const wchar_t* file, 198 unsigned int line, 199 uintptr_t pReserved) 200 { 201 # ifdef _DEBUG 202 char* ansi_expression; 203 char* ansi_function; 204 char* ansi_file; 205 if (silent_invalid_parameter_handler) 206 return; 207 ansi_expression = wstr_to_str(expression); 208 ansi_function = wstr_to_str(function); 209 ansi_file = wstr_to_str(file); 210 fprintf(stderr, "Invalid parameter detected in function %s. " 211 "File: %s, line: %d\n", ansi_function, ansi_file, line); 212 fprintf(stderr, "Expression: %s\n", ansi_expression); 213 free(ansi_expression); 214 free(ansi_function); 215 free(ansi_file); 216 # endif 217 } 218 #endif 219 220 EXTERN_C void 221 set_w32_module_name(void) 222 { 223 /* this function may be called at DLL_PROCESS_ATTACH time */ 224 char* ptr; 225 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE) 226 ? GetModuleHandle(NULL) 227 : w32_perldll_handle); 228 229 WCHAR modulename[MAX_PATH]; 230 WCHAR fullname[MAX_PATH]; 231 char *ansi; 232 233 DWORD (__stdcall *pfnGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD) = 234 (DWORD (__stdcall *)(LPCWSTR, LPWSTR, DWORD)) 235 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameW"); 236 237 GetModuleFileNameW(module, modulename, sizeof(modulename)/sizeof(WCHAR)); 238 239 /* Make sure we get an absolute pathname in case the module was loaded 240 * explicitly by LoadLibrary() with a relative path. */ 241 GetFullPathNameW(modulename, sizeof(fullname)/sizeof(WCHAR), fullname, NULL); 242 243 /* Make sure we start with the long path name of the module because we 244 * later scan for pathname components to match "5.xx" to locate 245 * compatible sitelib directories, and the short pathname might mangle 246 * this path segment (e.g. by removing the dot on NTFS to something 247 * like "5xx~1.yy") */ 248 if (pfnGetLongPathNameW) 249 pfnGetLongPathNameW(fullname, fullname, sizeof(fullname)/sizeof(WCHAR)); 250 251 /* remove \\?\ prefix */ 252 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0) 253 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR)); 254 255 ansi = win32_ansipath(fullname); 256 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name)); 257 win32_free(ansi); 258 259 /* normalize to forward slashes */ 260 ptr = w32_module_name; 261 while (*ptr) { 262 if (*ptr == '\\') 263 *ptr = '/'; 264 ++ptr; 265 } 266 } 267 268 #ifndef WIN32_NO_REGISTRY 269 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */ 270 static char* 271 get_regstr_from(HKEY handle, const char *valuename, SV **svp) 272 { 273 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */ 274 DWORD type; 275 char *str = NULL; 276 long retval; 277 DWORD datalen; 278 279 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen); 280 if (retval == ERROR_SUCCESS 281 && (type == REG_SZ || type == REG_EXPAND_SZ)) 282 { 283 dTHX; 284 if (!*svp) 285 *svp = sv_2mortal(newSVpvs("")); 286 SvGROW(*svp, datalen); 287 retval = RegQueryValueEx(handle, valuename, 0, NULL, 288 (PBYTE)SvPVX(*svp), &datalen); 289 if (retval == ERROR_SUCCESS) { 290 str = SvPVX(*svp); 291 SvCUR_set(*svp,datalen-1); 292 } 293 } 294 return str; 295 } 296 297 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */ 298 static char* 299 get_regstr(const char *valuename, SV **svp) 300 { 301 char *str; 302 if (HKCU_Perl_hnd) { 303 str = get_regstr_from(HKCU_Perl_hnd, valuename, svp); 304 if (!str) 305 goto try_HKLM; 306 } 307 else { 308 try_HKLM: 309 if (HKLM_Perl_hnd) 310 str = get_regstr_from(HKLM_Perl_hnd, valuename, svp); 311 else 312 str = NULL; 313 } 314 return str; 315 } 316 #endif /* ifndef WIN32_NO_REGISTRY */ 317 318 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */ 319 static char * 320 get_emd_part(SV **prev_pathp, STRLEN *const len, char *trailing_path, ...) 321 { 322 char base[10]; 323 va_list ap; 324 char mod_name[MAX_PATH+1]; 325 char *ptr; 326 char *optr; 327 char *strip; 328 STRLEN baselen; 329 330 va_start(ap, trailing_path); 331 strip = va_arg(ap, char *); 332 333 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION); 334 baselen = strlen(base); 335 336 if (!*w32_module_name) { 337 set_w32_module_name(); 338 } 339 strcpy(mod_name, w32_module_name); 340 ptr = strrchr(mod_name, '/'); 341 while (ptr && strip) { 342 /* look for directories to skip back */ 343 optr = ptr; 344 *ptr = '\0'; 345 ptr = strrchr(mod_name, '/'); 346 /* avoid stripping component if there is no slash, 347 * or it doesn't match ... */ 348 if (!ptr || stricmp(ptr+1, strip) != 0) { 349 /* ... but not if component matches m|5\.$patchlevel.*| */ 350 if (!ptr || !(*strip == '5' && *(ptr+1) == '5' 351 && strnEQ(strip, base, baselen) 352 && strnEQ(ptr+1, base, baselen))) 353 { 354 *optr = '/'; 355 ptr = optr; 356 } 357 } 358 strip = va_arg(ap, char *); 359 } 360 if (!ptr) { 361 ptr = mod_name; 362 *ptr++ = '.'; 363 *ptr = '/'; 364 } 365 va_end(ap); 366 strcpy(++ptr, trailing_path); 367 368 /* only add directory if it exists */ 369 if (GetFileAttributes(mod_name) != (DWORD) -1) { 370 /* directory exists */ 371 dTHX; 372 if (!*prev_pathp) 373 *prev_pathp = sv_2mortal(newSVpvs("")); 374 else if (SvPVX(*prev_pathp)) 375 sv_catpvs(*prev_pathp, ";"); 376 sv_catpv(*prev_pathp, mod_name); 377 if(len) 378 *len = SvCUR(*prev_pathp); 379 return SvPVX(*prev_pathp); 380 } 381 382 return NULL; 383 } 384 385 EXTERN_C char * 386 win32_get_privlib(WIN32_NO_REGISTRY_M_(const char *pl) STRLEN *const len) 387 { 388 char *stdlib = "lib"; 389 SV *sv = NULL; 390 #ifndef WIN32_NO_REGISTRY 391 char buffer[MAX_PATH+1]; 392 393 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */ 394 sprintf(buffer, "%s-%s", stdlib, pl); 395 if (!get_regstr(buffer, &sv)) 396 (void)get_regstr(stdlib, &sv); 397 #endif 398 399 /* $stdlib .= ";$EMD/../../lib" */ 400 return get_emd_part(&sv, len, stdlib, ARCHNAME, "bin", NULL); 401 } 402 403 static char * 404 win32_get_xlib(const char *pl, WIN32_NO_REGISTRY_M_(const char *xlib) 405 const char *libname, STRLEN *const len) 406 { 407 #ifndef WIN32_NO_REGISTRY 408 char regstr[40]; 409 #endif 410 char pathstr[MAX_PATH+1]; 411 SV *sv1 = NULL; 412 SV *sv2 = NULL; 413 414 #ifndef WIN32_NO_REGISTRY 415 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */ 416 sprintf(regstr, "%s-%s", xlib, pl); 417 (void)get_regstr(regstr, &sv1); 418 #endif 419 420 /* $xlib .= 421 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */ 422 sprintf(pathstr, "%s/%s/lib", libname, pl); 423 (void)get_emd_part(&sv1, NULL, pathstr, ARCHNAME, "bin", pl, NULL); 424 425 #ifndef WIN32_NO_REGISTRY 426 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */ 427 (void)get_regstr(xlib, &sv2); 428 #endif 429 430 /* $xlib .= 431 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */ 432 sprintf(pathstr, "%s/lib", libname); 433 (void)get_emd_part(&sv2, NULL, pathstr, ARCHNAME, "bin", pl, NULL); 434 435 if (!sv1 && !sv2) 436 return NULL; 437 if (!sv1) { 438 sv1 = sv2; 439 } else if (sv2) { 440 dTHX; 441 sv_catpvs(sv1, ";"); 442 sv_catsv(sv1, sv2); 443 } 444 445 if (len) 446 *len = SvCUR(sv1); 447 return SvPVX(sv1); 448 } 449 450 EXTERN_C char * 451 win32_get_sitelib(const char *pl, STRLEN *const len) 452 { 453 return win32_get_xlib(pl, WIN32_NO_REGISTRY_M_("sitelib") "site", len); 454 } 455 456 #ifndef PERL_VENDORLIB_NAME 457 # define PERL_VENDORLIB_NAME "vendor" 458 #endif 459 460 EXTERN_C char * 461 win32_get_vendorlib(const char *pl, STRLEN *const len) 462 { 463 return win32_get_xlib(pl, WIN32_NO_REGISTRY_M_("vendorlib") PERL_VENDORLIB_NAME, len); 464 } 465 466 static BOOL 467 has_shell_metachars(const char *ptr) 468 { 469 int inquote = 0; 470 char quote = '\0'; 471 472 /* 473 * Scan string looking for redirection (< or >) or pipe 474 * characters (|) that are not in a quoted string. 475 * Shell variable interpolation (%VAR%) can also happen inside strings. 476 */ 477 while (*ptr) { 478 switch(*ptr) { 479 case '%': 480 return TRUE; 481 case '\'': 482 case '\"': 483 if (inquote) { 484 if (quote == *ptr) { 485 inquote = 0; 486 quote = '\0'; 487 } 488 } 489 else { 490 quote = *ptr; 491 inquote++; 492 } 493 break; 494 case '>': 495 case '<': 496 case '|': 497 if (!inquote) 498 return TRUE; 499 default: 500 break; 501 } 502 ++ptr; 503 } 504 return FALSE; 505 } 506 507 #if !defined(PERL_IMPLICIT_SYS) 508 /* since the current process environment is being updated in util.c 509 * the library functions will get the correct environment 510 */ 511 PerlIO * 512 Perl_my_popen(pTHX_ const char *cmd, const char *mode) 513 { 514 PERL_FLUSHALL_FOR_CHILD; 515 return win32_popen(cmd, mode); 516 } 517 518 long 519 Perl_my_pclose(pTHX_ PerlIO *fp) 520 { 521 return win32_pclose(fp); 522 } 523 #endif 524 525 DllExport unsigned long 526 win32_os_id(void) 527 { 528 return (unsigned long)g_osver.dwPlatformId; 529 } 530 531 DllExport int 532 win32_getpid(void) 533 { 534 #ifdef USE_ITHREADS 535 dTHX; 536 if (w32_pseudo_id) 537 return -((int)w32_pseudo_id); 538 #endif 539 return _getpid(); 540 } 541 542 /* Tokenize a string. Words are null-separated, and the list 543 * ends with a doubled null. Any character (except null and 544 * including backslash) may be escaped by preceding it with a 545 * backslash (the backslash will be stripped). 546 * Returns number of words in result buffer. 547 */ 548 static long 549 tokenize(const char *str, char **dest, char ***destv) 550 { 551 char *retstart = NULL; 552 char **retvstart = 0; 553 int items = -1; 554 if (str) { 555 int slen = strlen(str); 556 char *ret; 557 char **retv; 558 Newx(ret, slen+2, char); 559 Newx(retv, (slen+3)/2, char*); 560 561 retstart = ret; 562 retvstart = retv; 563 *retv = ret; 564 items = 0; 565 while (*str) { 566 *ret = *str++; 567 if (*ret == '\\' && *str) 568 *ret = *str++; 569 else if (*ret == ' ') { 570 while (*str == ' ') 571 str++; 572 if (ret == retstart) 573 ret--; 574 else { 575 *ret = '\0'; 576 ++items; 577 if (*str) 578 *++retv = ret+1; 579 } 580 } 581 else if (!*str) 582 ++items; 583 ret++; 584 } 585 retvstart[items] = NULL; 586 *ret++ = '\0'; 587 *ret = '\0'; 588 } 589 *dest = retstart; 590 *destv = retvstart; 591 return items; 592 } 593 594 static void 595 get_shell(void) 596 { 597 dTHX; 598 if (!w32_perlshell_tokens) { 599 /* we don't use COMSPEC here for two reasons: 600 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and 601 * uncontrolled unportability of the ensuing scripts. 602 * 2. PERL5SHELL could be set to a shell that may not be fit for 603 * interactive use (which is what most programs look in COMSPEC 604 * for). 605 */ 606 const char* defaultshell = "cmd.exe /x/d/c"; 607 const char *usershell = PerlEnv_getenv("PERL5SHELL"); 608 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell, 609 &w32_perlshell_tokens, 610 &w32_perlshell_vec); 611 } 612 } 613 614 int 615 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp) 616 { 617 char **argv; 618 char *str; 619 int status; 620 int flag = P_WAIT; 621 int index = 0; 622 int eno; 623 624 PERL_ARGS_ASSERT_DO_ASPAWN; 625 626 if (sp <= mark) 627 return -1; 628 629 get_shell(); 630 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*); 631 632 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) { 633 ++mark; 634 flag = SvIVx(*mark); 635 } 636 637 while (++mark <= sp) { 638 if (*mark && (str = SvPV_nolen(*mark))) 639 argv[index++] = str; 640 else 641 argv[index++] = ""; 642 } 643 argv[index++] = 0; 644 645 status = win32_spawnvp(flag, 646 (const char*)(really ? SvPV_nolen(really) : argv[0]), 647 (const char* const*)argv); 648 649 if (status < 0 && (eno = errno, (eno == ENOEXEC || eno == ENOENT))) { 650 /* possible shell-builtin, invoke with shell */ 651 int sh_items; 652 sh_items = w32_perlshell_items; 653 while (--index >= 0) 654 argv[index+sh_items] = argv[index]; 655 while (--sh_items >= 0) 656 argv[sh_items] = w32_perlshell_vec[sh_items]; 657 658 status = win32_spawnvp(flag, 659 (const char*)(really ? SvPV_nolen(really) : argv[0]), 660 (const char* const*)argv); 661 } 662 663 if (flag == P_NOWAIT) { 664 PL_statusvalue = -1; /* >16bits hint for pp_system() */ 665 } 666 else { 667 if (status < 0) { 668 if (ckWARN(WARN_EXEC)) 669 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno)); 670 status = 255 * 256; 671 } 672 else 673 status *= 256; 674 PL_statusvalue = status; 675 } 676 Safefree(argv); 677 return (status); 678 } 679 680 /* returns pointer to the next unquoted space or the end of the string */ 681 static char* 682 find_next_space(const char *s) 683 { 684 bool in_quotes = FALSE; 685 while (*s) { 686 /* ignore doubled backslashes, or backslash+quote */ 687 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) { 688 s += 2; 689 } 690 /* keep track of when we're within quotes */ 691 else if (*s == '"') { 692 s++; 693 in_quotes = !in_quotes; 694 } 695 /* break it up only at spaces that aren't in quotes */ 696 else if (!in_quotes && isSPACE(*s)) 697 return (char*)s; 698 else 699 s++; 700 } 701 return (char*)s; 702 } 703 704 static int 705 do_spawn2(pTHX_ const char *cmd, int exectype) { 706 return do_spawn2_handles(aTHX_ cmd, exectype, NULL); 707 } 708 709 static int 710 do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles) 711 { 712 char **a; 713 char *s; 714 char **argv; 715 int status = -1; 716 BOOL needToTry = TRUE; 717 char *cmd2; 718 719 /* Save an extra exec if possible. See if there are shell 720 * metacharacters in it */ 721 if (!has_shell_metachars(cmd)) { 722 Newx(argv, strlen(cmd) / 2 + 2, char*); 723 Newx(cmd2, strlen(cmd) + 1, char); 724 strcpy(cmd2, cmd); 725 a = argv; 726 for (s = cmd2; *s;) { 727 while (*s && isSPACE(*s)) 728 s++; 729 if (*s) 730 *(a++) = s; 731 s = find_next_space(s); 732 if (*s) 733 *s++ = '\0'; 734 } 735 *a = NULL; 736 if (argv[0]) { 737 switch (exectype) { 738 case EXECF_SPAWN: 739 status = win32_spawnvp(P_WAIT, argv[0], 740 (const char* const*)argv); 741 break; 742 case EXECF_SPAWN_NOWAIT: 743 status = do_spawnvp_handles(P_NOWAIT, argv[0], 744 (const char* const*)argv, handles); 745 break; 746 case EXECF_EXEC: 747 status = win32_execvp(argv[0], (const char* const*)argv); 748 break; 749 } 750 if (status != -1 || errno == 0) 751 needToTry = FALSE; 752 } 753 Safefree(argv); 754 Safefree(cmd2); 755 } 756 if (needToTry) { 757 char **argv; 758 int i = -1; 759 get_shell(); 760 Newx(argv, w32_perlshell_items + 2, char*); 761 while (++i < w32_perlshell_items) 762 argv[i] = w32_perlshell_vec[i]; 763 argv[i++] = (char *)cmd; 764 argv[i] = NULL; 765 switch (exectype) { 766 case EXECF_SPAWN: 767 status = win32_spawnvp(P_WAIT, argv[0], 768 (const char* const*)argv); 769 break; 770 case EXECF_SPAWN_NOWAIT: 771 status = do_spawnvp_handles(P_NOWAIT, argv[0], 772 (const char* const*)argv, handles); 773 break; 774 case EXECF_EXEC: 775 status = win32_execvp(argv[0], (const char* const*)argv); 776 break; 777 } 778 cmd = argv[0]; 779 Safefree(argv); 780 } 781 if (exectype == EXECF_SPAWN_NOWAIT) { 782 PL_statusvalue = -1; /* >16bits hint for pp_system() */ 783 } 784 else { 785 if (status < 0) { 786 if (ckWARN(WARN_EXEC)) 787 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s", 788 (exectype == EXECF_EXEC ? "exec" : "spawn"), 789 cmd, strerror(errno)); 790 status = 255 * 256; 791 } 792 else 793 status *= 256; 794 PL_statusvalue = status; 795 } 796 return (status); 797 } 798 799 int 800 Perl_do_spawn(pTHX_ char *cmd) 801 { 802 PERL_ARGS_ASSERT_DO_SPAWN; 803 804 return do_spawn2(aTHX_ cmd, EXECF_SPAWN); 805 } 806 807 int 808 Perl_do_spawn_nowait(pTHX_ char *cmd) 809 { 810 PERL_ARGS_ASSERT_DO_SPAWN_NOWAIT; 811 812 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT); 813 } 814 815 bool 816 Perl_do_exec(pTHX_ const char *cmd) 817 { 818 PERL_ARGS_ASSERT_DO_EXEC; 819 820 do_spawn2(aTHX_ cmd, EXECF_EXEC); 821 return FALSE; 822 } 823 824 /* The idea here is to read all the directory names into a string table 825 * (separated by nulls) and when one of the other dir functions is called 826 * return the pointer to the current file name. 827 */ 828 DllExport DIR * 829 win32_opendir(const char *filename) 830 { 831 dTHXa(NULL); 832 DIR *dirp; 833 long len; 834 long idx; 835 char scanname[MAX_PATH+3]; 836 WCHAR wscanname[sizeof(scanname)]; 837 WIN32_FIND_DATAW wFindData; 838 char buffer[MAX_PATH*2]; 839 BOOL use_default; 840 841 len = strlen(filename); 842 if (len == 0) { 843 errno = ENOENT; 844 return NULL; 845 } 846 if (len > MAX_PATH) { 847 errno = ENAMETOOLONG; 848 return NULL; 849 } 850 851 /* Get us a DIR structure */ 852 Newxz(dirp, 1, DIR); 853 854 /* Create the search pattern */ 855 strcpy(scanname, filename); 856 857 /* bare drive name means look in cwd for drive */ 858 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') { 859 scanname[len++] = '.'; 860 scanname[len++] = '/'; 861 } 862 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') { 863 scanname[len++] = '/'; 864 } 865 scanname[len++] = '*'; 866 scanname[len] = '\0'; 867 868 /* do the FindFirstFile call */ 869 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR)); 870 aTHXa(PERL_GET_THX); 871 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData); 872 873 if (dirp->handle == INVALID_HANDLE_VALUE) { 874 DWORD err = GetLastError(); 875 /* FindFirstFile() fails on empty drives! */ 876 switch (err) { 877 case ERROR_FILE_NOT_FOUND: 878 return dirp; 879 case ERROR_NO_MORE_FILES: 880 case ERROR_PATH_NOT_FOUND: 881 errno = ENOENT; 882 break; 883 case ERROR_NOT_ENOUGH_MEMORY: 884 errno = ENOMEM; 885 break; 886 default: 887 errno = EINVAL; 888 break; 889 } 890 Safefree(dirp); 891 return NULL; 892 } 893 894 use_default = FALSE; 895 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 896 wFindData.cFileName, -1, 897 buffer, sizeof(buffer), NULL, &use_default); 898 if (use_default && *wFindData.cAlternateFileName) { 899 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 900 wFindData.cAlternateFileName, -1, 901 buffer, sizeof(buffer), NULL, NULL); 902 } 903 904 /* now allocate the first part of the string table for 905 * the filenames that we find. 906 */ 907 idx = strlen(buffer)+1; 908 if (idx < 256) 909 dirp->size = 256; 910 else 911 dirp->size = idx; 912 Newx(dirp->start, dirp->size, char); 913 strcpy(dirp->start, buffer); 914 dirp->nfiles++; 915 dirp->end = dirp->curr = dirp->start; 916 dirp->end += idx; 917 return dirp; 918 } 919 920 921 /* Readdir just returns the current string pointer and bumps the 922 * string pointer to the nDllExport entry. 923 */ 924 DllExport struct direct * 925 win32_readdir(DIR *dirp) 926 { 927 long len; 928 929 if (dirp->curr) { 930 /* first set up the structure to return */ 931 len = strlen(dirp->curr); 932 strcpy(dirp->dirstr.d_name, dirp->curr); 933 dirp->dirstr.d_namlen = len; 934 935 /* Fake an inode */ 936 dirp->dirstr.d_ino = dirp->curr - dirp->start; 937 938 /* Now set up for the next call to readdir */ 939 dirp->curr += len + 1; 940 if (dirp->curr >= dirp->end) { 941 BOOL res; 942 char buffer[MAX_PATH*2]; 943 944 if (dirp->handle == INVALID_HANDLE_VALUE) { 945 res = 0; 946 } 947 /* finding the next file that matches the wildcard 948 * (which should be all of them in this directory!). 949 */ 950 else { 951 WIN32_FIND_DATAW wFindData; 952 res = FindNextFileW(dirp->handle, &wFindData); 953 if (res) { 954 BOOL use_default = FALSE; 955 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 956 wFindData.cFileName, -1, 957 buffer, sizeof(buffer), NULL, &use_default); 958 if (use_default && *wFindData.cAlternateFileName) { 959 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 960 wFindData.cAlternateFileName, -1, 961 buffer, sizeof(buffer), NULL, NULL); 962 } 963 } 964 } 965 if (res) { 966 long endpos = dirp->end - dirp->start; 967 long newsize = endpos + strlen(buffer) + 1; 968 /* bump the string table size by enough for the 969 * new name and its null terminator */ 970 while (newsize > dirp->size) { 971 long curpos = dirp->curr - dirp->start; 972 Renew(dirp->start, dirp->size * 2, char); 973 dirp->size *= 2; 974 dirp->curr = dirp->start + curpos; 975 } 976 strcpy(dirp->start + endpos, buffer); 977 dirp->end = dirp->start + newsize; 978 dirp->nfiles++; 979 } 980 else { 981 dirp->curr = NULL; 982 if (dirp->handle != INVALID_HANDLE_VALUE) { 983 FindClose(dirp->handle); 984 dirp->handle = INVALID_HANDLE_VALUE; 985 } 986 } 987 } 988 return &(dirp->dirstr); 989 } 990 else 991 return NULL; 992 } 993 994 /* Telldir returns the current string pointer position */ 995 DllExport long 996 win32_telldir(DIR *dirp) 997 { 998 return dirp->curr ? (dirp->curr - dirp->start) : -1; 999 } 1000 1001 1002 /* Seekdir moves the string pointer to a previously saved position 1003 * (returned by telldir). 1004 */ 1005 DllExport void 1006 win32_seekdir(DIR *dirp, long loc) 1007 { 1008 dirp->curr = loc == -1 ? NULL : dirp->start + loc; 1009 } 1010 1011 /* Rewinddir resets the string pointer to the start */ 1012 DllExport void 1013 win32_rewinddir(DIR *dirp) 1014 { 1015 dirp->curr = dirp->start; 1016 } 1017 1018 /* free the memory allocated by opendir */ 1019 DllExport int 1020 win32_closedir(DIR *dirp) 1021 { 1022 if (dirp->handle != INVALID_HANDLE_VALUE) 1023 FindClose(dirp->handle); 1024 Safefree(dirp->start); 1025 Safefree(dirp); 1026 return 1; 1027 } 1028 1029 /* duplicate a open DIR* for interpreter cloning */ 1030 DllExport DIR * 1031 win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param) 1032 { 1033 dVAR; 1034 PerlInterpreter *const from = param->proto_perl; 1035 PerlInterpreter *const to = (PerlInterpreter *)PERL_GET_THX; 1036 1037 long pos; 1038 DIR *dup; 1039 1040 /* switch back to original interpreter because win32_readdir() 1041 * might Renew(dirp->start). 1042 */ 1043 if (from != to) { 1044 PERL_SET_THX(from); 1045 } 1046 1047 /* mark current position; read all remaining entries into the 1048 * cache, and then restore to current position. 1049 */ 1050 pos = win32_telldir(dirp); 1051 while (win32_readdir(dirp)) { 1052 /* read all entries into cache */ 1053 } 1054 win32_seekdir(dirp, pos); 1055 1056 /* switch back to new interpreter to allocate new DIR structure */ 1057 if (from != to) { 1058 PERL_SET_THX(to); 1059 } 1060 1061 Newx(dup, 1, DIR); 1062 memcpy(dup, dirp, sizeof(DIR)); 1063 1064 Newx(dup->start, dirp->size, char); 1065 memcpy(dup->start, dirp->start, dirp->size); 1066 1067 dup->end = dup->start + (dirp->end - dirp->start); 1068 if (dirp->curr) 1069 dup->curr = dup->start + (dirp->curr - dirp->start); 1070 1071 return dup; 1072 } 1073 1074 /* 1075 * various stubs 1076 */ 1077 1078 1079 /* Ownership 1080 * 1081 * Just pretend that everyone is a superuser. NT will let us know if 1082 * we don\'t really have permission to do something. 1083 */ 1084 1085 #define ROOT_UID ((uid_t)0) 1086 #define ROOT_GID ((gid_t)0) 1087 1088 uid_t 1089 getuid(void) 1090 { 1091 return ROOT_UID; 1092 } 1093 1094 uid_t 1095 geteuid(void) 1096 { 1097 return ROOT_UID; 1098 } 1099 1100 gid_t 1101 getgid(void) 1102 { 1103 return ROOT_GID; 1104 } 1105 1106 gid_t 1107 getegid(void) 1108 { 1109 return ROOT_GID; 1110 } 1111 1112 int 1113 setuid(uid_t auid) 1114 { 1115 return (auid == ROOT_UID ? 0 : -1); 1116 } 1117 1118 int 1119 setgid(gid_t agid) 1120 { 1121 return (agid == ROOT_GID ? 0 : -1); 1122 } 1123 1124 EXTERN_C char * 1125 getlogin(void) 1126 { 1127 dTHX; 1128 char *buf = w32_getlogin_buffer; 1129 DWORD size = sizeof(w32_getlogin_buffer); 1130 if (GetUserName(buf,&size)) 1131 return buf; 1132 return (char*)NULL; 1133 } 1134 1135 int 1136 chown(const char *path, uid_t owner, gid_t group) 1137 { 1138 /* XXX noop */ 1139 return 0; 1140 } 1141 1142 /* 1143 * XXX this needs strengthening (for PerlIO) 1144 * -- BKS, 11-11-200 1145 */ 1146 #if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4 1147 int mkstemp(const char *path) 1148 { 1149 dTHX; 1150 char buf[MAX_PATH+1]; 1151 int i = 0, fd = -1; 1152 1153 retry: 1154 if (i++ > 10) { /* give up */ 1155 errno = ENOENT; 1156 return -1; 1157 } 1158 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) { 1159 errno = ENOENT; 1160 return -1; 1161 } 1162 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600); 1163 if (fd == -1) 1164 goto retry; 1165 return fd; 1166 } 1167 #endif 1168 1169 static long 1170 find_pid(pTHX_ int pid) 1171 { 1172 long child = w32_num_children; 1173 while (--child >= 0) { 1174 if ((int)w32_child_pids[child] == pid) 1175 return child; 1176 } 1177 return -1; 1178 } 1179 1180 static void 1181 remove_dead_process(long child) 1182 { 1183 if (child >= 0) { 1184 dTHX; 1185 CloseHandle(w32_child_handles[child]); 1186 Move(&w32_child_handles[child+1], &w32_child_handles[child], 1187 (w32_num_children-child-1), HANDLE); 1188 Move(&w32_child_pids[child+1], &w32_child_pids[child], 1189 (w32_num_children-child-1), DWORD); 1190 w32_num_children--; 1191 } 1192 } 1193 1194 #ifdef USE_ITHREADS 1195 static long 1196 find_pseudo_pid(pTHX_ int pid) 1197 { 1198 long child = w32_num_pseudo_children; 1199 while (--child >= 0) { 1200 if ((int)w32_pseudo_child_pids[child] == pid) 1201 return child; 1202 } 1203 return -1; 1204 } 1205 1206 static void 1207 remove_dead_pseudo_process(long child) 1208 { 1209 if (child >= 0) { 1210 dTHX; 1211 CloseHandle(w32_pseudo_child_handles[child]); 1212 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child], 1213 (w32_num_pseudo_children-child-1), HANDLE); 1214 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child], 1215 (w32_num_pseudo_children-child-1), DWORD); 1216 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child], 1217 (w32_num_pseudo_children-child-1), HWND); 1218 Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child], 1219 (w32_num_pseudo_children-child-1), char); 1220 w32_num_pseudo_children--; 1221 } 1222 } 1223 1224 void 1225 win32_wait_for_children(pTHX) 1226 { 1227 if (w32_pseudo_children && w32_num_pseudo_children) { 1228 long child = 0; 1229 long count = 0; 1230 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 1231 1232 for (child = 0; child < w32_num_pseudo_children; ++child) { 1233 if (!w32_pseudo_child_sigterm[child]) 1234 handles[count++] = w32_pseudo_child_handles[child]; 1235 } 1236 /* XXX should use MsgWaitForMultipleObjects() to continue 1237 * XXX processing messages while we wait. 1238 */ 1239 WaitForMultipleObjects(count, handles, TRUE, INFINITE); 1240 1241 while (w32_num_pseudo_children) 1242 CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]); 1243 } 1244 } 1245 #endif 1246 1247 static int 1248 terminate_process(DWORD pid, HANDLE process_handle, int sig) 1249 { 1250 switch(sig) { 1251 case 0: 1252 /* "Does process exist?" use of kill */ 1253 return 1; 1254 case 2: 1255 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid)) 1256 return 1; 1257 break; 1258 case SIGBREAK: 1259 case SIGTERM: 1260 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)) 1261 return 1; 1262 break; 1263 default: /* For now be backwards compatible with perl 5.6 */ 1264 case 9: 1265 /* Note that we will only be able to kill processes owned by the 1266 * current process owner, even when we are running as an administrator. 1267 * To kill processes of other owners we would need to set the 1268 * 'SeDebugPrivilege' privilege before obtaining the process handle. 1269 */ 1270 if (TerminateProcess(process_handle, sig)) 1271 return 1; 1272 break; 1273 } 1274 return 0; 1275 } 1276 1277 /* returns number of processes killed */ 1278 static int 1279 my_killpg(int pid, int sig) 1280 { 1281 HANDLE process_handle; 1282 HANDLE snapshot_handle; 1283 int killed = 0; 1284 1285 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid); 1286 if (process_handle == NULL) 1287 return 0; 1288 1289 killed += terminate_process(pid, process_handle, sig); 1290 1291 snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 1292 if (snapshot_handle != INVALID_HANDLE_VALUE) { 1293 PROCESSENTRY32 entry; 1294 1295 entry.dwSize = sizeof(entry); 1296 if (Process32First(snapshot_handle, &entry)) { 1297 do { 1298 if (entry.th32ParentProcessID == (DWORD)pid) 1299 killed += my_killpg(entry.th32ProcessID, sig); 1300 entry.dwSize = sizeof(entry); 1301 } 1302 while (Process32Next(snapshot_handle, &entry)); 1303 } 1304 CloseHandle(snapshot_handle); 1305 } 1306 CloseHandle(process_handle); 1307 return killed; 1308 } 1309 1310 /* returns number of processes killed */ 1311 static int 1312 my_kill(int pid, int sig) 1313 { 1314 int retval = 0; 1315 HANDLE process_handle; 1316 1317 if (sig < 0) 1318 return my_killpg(pid, -sig); 1319 1320 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid); 1321 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */ 1322 if (process_handle != NULL) { 1323 retval = terminate_process(pid, process_handle, sig); 1324 CloseHandle(process_handle); 1325 } 1326 return retval; 1327 } 1328 1329 #ifdef USE_ITHREADS 1330 /* Get a child pseudo-process HWND, with retrying and delaying/yielding. 1331 * The "tries" parameter is the number of retries to make, with a Sleep(1) 1332 * (waiting and yielding the time slot) between each try. Specifying 0 causes 1333 * only Sleep(0) (no waiting and potentially no yielding) to be used, so is not 1334 * recommended 1335 * Returns an hwnd != INVALID_HANDLE_VALUE (so be aware that NULL can be 1336 * returned) or croaks if the child pseudo-process doesn't schedule and deliver 1337 * a HWND in the time period allowed. 1338 */ 1339 static HWND 1340 get_hwnd_delay(pTHX, long child, DWORD tries) 1341 { 1342 HWND hwnd = w32_pseudo_child_message_hwnds[child]; 1343 if (hwnd != INVALID_HANDLE_VALUE) return hwnd; 1344 1345 /* Pseudo-process has not yet properly initialized since hwnd isn't set. 1346 * Fast sleep: On some NT kernels/systems, a Sleep(0) won't deschedule a 1347 * thread 100% of the time since threads are attached to a CPU for NUMA and 1348 * caching reasons, and the child thread was attached to a different CPU 1349 * therefore there is no workload on that CPU and Sleep(0) returns control 1350 * without yielding the time slot. 1351 * https://rt.perl.org/rt3/Ticket/Display.html?id=88840 1352 */ 1353 Sleep(0); 1354 win32_async_check(aTHX); 1355 hwnd = w32_pseudo_child_message_hwnds[child]; 1356 if (hwnd != INVALID_HANDLE_VALUE) return hwnd; 1357 1358 { 1359 unsigned int count = 0; 1360 /* No Sleep(1) if tries==0, just fail instead if we get this far. */ 1361 while (count++ < tries) { 1362 Sleep(1); 1363 win32_async_check(aTHX); 1364 hwnd = w32_pseudo_child_message_hwnds[child]; 1365 if (hwnd != INVALID_HANDLE_VALUE) return hwnd; 1366 } 1367 } 1368 1369 Perl_croak(aTHX_ "panic: child pseudo-process was never scheduled"); 1370 } 1371 #endif 1372 1373 DllExport int 1374 win32_kill(int pid, int sig) 1375 { 1376 dTHX; 1377 long child; 1378 #ifdef USE_ITHREADS 1379 if (pid < 0) { 1380 /* it is a pseudo-forked child */ 1381 child = find_pseudo_pid(aTHX_ -pid); 1382 if (child >= 0) { 1383 HANDLE hProcess = w32_pseudo_child_handles[child]; 1384 switch (sig) { 1385 case 0: 1386 /* "Does process exist?" use of kill */ 1387 return 0; 1388 1389 case 9: { 1390 /* kill -9 style un-graceful exit */ 1391 /* Do a wait to make sure child starts and isn't in DLL 1392 * Loader Lock */ 1393 HWND hwnd = get_hwnd_delay(aTHX, child, 5); 1394 if (TerminateThread(hProcess, sig)) { 1395 /* Allow the scheduler to finish cleaning up the other 1396 * thread. 1397 * Otherwise, if we ExitProcess() before another context 1398 * switch happens we will end up with a process exit 1399 * code of "sig" instead of our own exit status. 1400 * https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976 1401 */ 1402 Sleep(0); 1403 remove_dead_pseudo_process(child); 1404 return 0; 1405 } 1406 break; 1407 } 1408 1409 default: { 1410 HWND hwnd = get_hwnd_delay(aTHX, child, 5); 1411 /* We fake signals to pseudo-processes using Win32 1412 * message queue. */ 1413 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) || 1414 PostThreadMessage(-pid, WM_USER_KILL, sig, 0)) 1415 { 1416 /* Don't wait for child process to terminate after we send a 1417 * SIGTERM because the child may be blocked in a system call 1418 * and never receive the signal. 1419 */ 1420 if (sig == SIGTERM) { 1421 Sleep(0); 1422 w32_pseudo_child_sigterm[child] = 1; 1423 } 1424 /* It might be us ... */ 1425 PERL_ASYNC_CHECK(); 1426 return 0; 1427 } 1428 break; 1429 } 1430 } /* switch */ 1431 } 1432 } 1433 else 1434 #endif 1435 { 1436 child = find_pid(aTHX_ pid); 1437 if (child >= 0) { 1438 if (my_kill(pid, sig)) { 1439 DWORD exitcode = 0; 1440 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) && 1441 exitcode != STILL_ACTIVE) 1442 { 1443 remove_dead_process(child); 1444 } 1445 return 0; 1446 } 1447 } 1448 else { 1449 if (my_kill(pid, sig)) 1450 return 0; 1451 } 1452 } 1453 errno = EINVAL; 1454 return -1; 1455 } 1456 1457 DllExport int 1458 win32_stat(const char *path, Stat_t *sbuf) 1459 { 1460 char buffer[MAX_PATH+1]; 1461 int l = strlen(path); 1462 dTHX; 1463 int res; 1464 int nlink = 1; 1465 BOOL expect_dir = FALSE; 1466 1467 if (l > 1) { 1468 switch(path[l - 1]) { 1469 /* FindFirstFile() and stat() are buggy with a trailing 1470 * slashes, except for the root directory of a drive */ 1471 case '\\': 1472 case '/': 1473 if (l > sizeof(buffer)) { 1474 errno = ENAMETOOLONG; 1475 return -1; 1476 } 1477 --l; 1478 strncpy(buffer, path, l); 1479 /* remove additional trailing slashes */ 1480 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\')) 1481 --l; 1482 /* add back slash if we otherwise end up with just a drive letter */ 1483 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':') 1484 buffer[l++] = '\\'; 1485 buffer[l] = '\0'; 1486 path = buffer; 1487 expect_dir = TRUE; 1488 break; 1489 1490 /* FindFirstFile() is buggy with "x:", so add a dot :-( */ 1491 case ':': 1492 if (l == 2 && isALPHA(path[0])) { 1493 buffer[0] = path[0]; 1494 buffer[1] = ':'; 1495 buffer[2] = '.'; 1496 buffer[3] = '\0'; 1497 l = 3; 1498 path = buffer; 1499 } 1500 break; 1501 } 1502 } 1503 1504 path = PerlDir_mapA(path); 1505 l = strlen(path); 1506 1507 if (!w32_sloppystat) { 1508 /* We must open & close the file once; otherwise file attribute changes */ 1509 /* might not yet have propagated to "other" hard links of the same file. */ 1510 /* This also gives us an opportunity to determine the number of links. */ 1511 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL); 1512 if (handle != INVALID_HANDLE_VALUE) { 1513 BY_HANDLE_FILE_INFORMATION bhi; 1514 if (GetFileInformationByHandle(handle, &bhi)) 1515 nlink = bhi.nNumberOfLinks; 1516 CloseHandle(handle); 1517 } 1518 else { 1519 DWORD err = GetLastError(); 1520 /* very common case, skip CRT stat and its also failing syscalls */ 1521 if(err == ERROR_FILE_NOT_FOUND) { 1522 errno = ENOENT; 1523 return -1; 1524 } 1525 } 1526 } 1527 1528 /* path will be mapped correctly above */ 1529 #if defined(WIN64) || defined(USE_LARGE_FILES) 1530 res = _stati64(path, sbuf); 1531 #else 1532 res = stat(path, sbuf); 1533 #endif 1534 sbuf->st_nlink = nlink; 1535 1536 if (res < 0) { 1537 /* CRT is buggy on sharenames, so make sure it really isn't. 1538 * XXX using GetFileAttributesEx() will enable us to set 1539 * sbuf->st_*time (but note that's not available on the 1540 * Windows of 1995) */ 1541 DWORD r = GetFileAttributesA(path); 1542 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) { 1543 /* sbuf may still contain old garbage since stat() failed */ 1544 Zero(sbuf, 1, Stat_t); 1545 sbuf->st_mode = S_IFDIR | S_IREAD; 1546 errno = 0; 1547 if (!(r & FILE_ATTRIBUTE_READONLY)) 1548 sbuf->st_mode |= S_IWRITE | S_IEXEC; 1549 return 0; 1550 } 1551 } 1552 else { 1553 if (l == 3 && isALPHA(path[0]) && path[1] == ':' 1554 && (path[2] == '\\' || path[2] == '/')) 1555 { 1556 /* The drive can be inaccessible, some _stat()s are buggy */ 1557 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) { 1558 errno = ENOENT; 1559 return -1; 1560 } 1561 } 1562 if (expect_dir && !S_ISDIR(sbuf->st_mode)) { 1563 errno = ENOTDIR; 1564 return -1; 1565 } 1566 if (S_ISDIR(sbuf->st_mode)) { 1567 /* Ensure the "write" bit is switched off in the mode for 1568 * directories with the read-only attribute set. Some compilers 1569 * switch it on for directories, which is technically correct 1570 * (directories are indeed always writable unless denied by DACLs), 1571 * but we want stat() and -w to reflect the state of the read-only 1572 * attribute for symmetry with chmod(). */ 1573 DWORD r = GetFileAttributesA(path); 1574 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) { 1575 sbuf->st_mode &= ~S_IWRITE; 1576 } 1577 } 1578 } 1579 return res; 1580 } 1581 1582 #define isSLASH(c) ((c) == '/' || (c) == '\\') 1583 #define SKIP_SLASHES(s) \ 1584 STMT_START { \ 1585 while (*(s) && isSLASH(*(s))) \ 1586 ++(s); \ 1587 } STMT_END 1588 #define COPY_NONSLASHES(d,s) \ 1589 STMT_START { \ 1590 while (*(s) && !isSLASH(*(s))) \ 1591 *(d)++ = *(s)++; \ 1592 } STMT_END 1593 1594 /* Find the longname of a given path. path is destructively modified. 1595 * It should have space for at least MAX_PATH characters. */ 1596 DllExport char * 1597 win32_longpath(char *path) 1598 { 1599 WIN32_FIND_DATA fdata; 1600 HANDLE fhand; 1601 char tmpbuf[MAX_PATH+1]; 1602 char *tmpstart = tmpbuf; 1603 char *start = path; 1604 char sep; 1605 if (!path) 1606 return NULL; 1607 1608 /* drive prefix */ 1609 if (isALPHA(path[0]) && path[1] == ':') { 1610 start = path + 2; 1611 *tmpstart++ = path[0]; 1612 *tmpstart++ = ':'; 1613 } 1614 /* UNC prefix */ 1615 else if (isSLASH(path[0]) && isSLASH(path[1])) { 1616 start = path + 2; 1617 *tmpstart++ = path[0]; 1618 *tmpstart++ = path[1]; 1619 SKIP_SLASHES(start); 1620 COPY_NONSLASHES(tmpstart,start); /* copy machine name */ 1621 if (*start) { 1622 *tmpstart++ = *start++; 1623 SKIP_SLASHES(start); 1624 COPY_NONSLASHES(tmpstart,start); /* copy share name */ 1625 } 1626 } 1627 *tmpstart = '\0'; 1628 while (*start) { 1629 /* copy initial slash, if any */ 1630 if (isSLASH(*start)) { 1631 *tmpstart++ = *start++; 1632 *tmpstart = '\0'; 1633 SKIP_SLASHES(start); 1634 } 1635 1636 /* FindFirstFile() expands "." and "..", so we need to pass 1637 * those through unmolested */ 1638 if (*start == '.' 1639 && (!start[1] || isSLASH(start[1]) 1640 || (start[1] == '.' && (!start[2] || isSLASH(start[2]))))) 1641 { 1642 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */ 1643 *tmpstart = '\0'; 1644 continue; 1645 } 1646 1647 /* if this is the end, bust outta here */ 1648 if (!*start) 1649 break; 1650 1651 /* now we're at a non-slash; walk up to next slash */ 1652 while (*start && !isSLASH(*start)) 1653 ++start; 1654 1655 /* stop and find full name of component */ 1656 sep = *start; 1657 *start = '\0'; 1658 fhand = FindFirstFile(path,&fdata); 1659 *start = sep; 1660 if (fhand != INVALID_HANDLE_VALUE) { 1661 STRLEN len = strlen(fdata.cFileName); 1662 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) { 1663 strcpy(tmpstart, fdata.cFileName); 1664 tmpstart += len; 1665 FindClose(fhand); 1666 } 1667 else { 1668 FindClose(fhand); 1669 errno = ERANGE; 1670 return NULL; 1671 } 1672 } 1673 else { 1674 /* failed a step, just return without side effects */ 1675 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/ 1676 errno = EINVAL; 1677 return NULL; 1678 } 1679 } 1680 strcpy(path,tmpbuf); 1681 return path; 1682 } 1683 1684 static void 1685 out_of_memory(void) 1686 { 1687 dVAR; 1688 1689 if (PL_curinterp) 1690 croak_no_mem(); 1691 exit(1); 1692 } 1693 1694 void 1695 win32_croak_not_implemented(const char * fname) 1696 { 1697 PERL_ARGS_ASSERT_WIN32_CROAK_NOT_IMPLEMENTED; 1698 1699 Perl_croak_nocontext("%s not implemented!\n", fname); 1700 } 1701 1702 /* Converts a wide character (UTF-16) string to the Windows ANSI code page, 1703 * potentially using the system's default replacement character for any 1704 * unrepresentable characters. The caller must free() the returned string. */ 1705 static char* 1706 wstr_to_str(const wchar_t* wstr) 1707 { 1708 BOOL used_default = FALSE; 1709 size_t wlen = wcslen(wstr) + 1; 1710 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen, 1711 NULL, 0, NULL, NULL); 1712 char* str = (char*)malloc(len); 1713 if (!str) 1714 out_of_memory(); 1715 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen, 1716 str, len, NULL, &used_default); 1717 return str; 1718 } 1719 1720 /* The win32_ansipath() function takes a Unicode filename and converts it 1721 * into the current Windows codepage. If some characters cannot be mapped, 1722 * then it will convert the short name instead. 1723 * 1724 * The buffer to the ansi pathname must be freed with win32_free() when it 1725 * it no longer needed. 1726 * 1727 * The argument to win32_ansipath() must exist before this function is 1728 * called; otherwise there is no way to determine the short path name. 1729 * 1730 * Ideas for future refinement: 1731 * - Only convert those segments of the path that are not in the current 1732 * codepage, but leave the other segments in their long form. 1733 * - If the resulting name is longer than MAX_PATH, start converting 1734 * additional path segments into short names until the full name 1735 * is shorter than MAX_PATH. Shorten the filename part last! 1736 */ 1737 DllExport char * 1738 win32_ansipath(const WCHAR *widename) 1739 { 1740 char *name; 1741 BOOL use_default = FALSE; 1742 size_t widelen = wcslen(widename)+1; 1743 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen, 1744 NULL, 0, NULL, NULL); 1745 name = (char*)win32_malloc(len); 1746 if (!name) 1747 out_of_memory(); 1748 1749 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen, 1750 name, len, NULL, &use_default); 1751 if (use_default) { 1752 DWORD shortlen = GetShortPathNameW(widename, NULL, 0); 1753 if (shortlen) { 1754 WCHAR *shortname = (WCHAR*)win32_malloc(shortlen*sizeof(WCHAR)); 1755 if (!shortname) 1756 out_of_memory(); 1757 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1; 1758 1759 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen, 1760 NULL, 0, NULL, NULL); 1761 name = (char*)win32_realloc(name, len); 1762 if (!name) 1763 out_of_memory(); 1764 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen, 1765 name, len, NULL, NULL); 1766 win32_free(shortname); 1767 } 1768 } 1769 return name; 1770 } 1771 1772 /* the returned string must be freed with win32_freeenvironmentstrings which is 1773 * implemented as a macro 1774 * void win32_freeenvironmentstrings(void* block) 1775 */ 1776 DllExport char * 1777 win32_getenvironmentstrings(void) 1778 { 1779 LPWSTR lpWStr, lpWTmp; 1780 LPSTR lpStr, lpTmp; 1781 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0; 1782 1783 /* Get the process environment strings */ 1784 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW(); 1785 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) { 1786 env_len = wcslen(lpWTmp); 1787 /* calculate the size of the environment strings */ 1788 wenvstrings_len += env_len + 1; 1789 } 1790 1791 /* Get the number of bytes required to store the ACP encoded string */ 1792 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 1793 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL); 1794 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char)); 1795 if(!lpTmp) 1796 out_of_memory(); 1797 1798 /* Convert the string from UTF-16 encoding to ACP encoding */ 1799 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr, 1800 aenvstrings_len, NULL, NULL); 1801 1802 FreeEnvironmentStringsW(lpWStr); 1803 1804 return(lpStr); 1805 } 1806 1807 DllExport char * 1808 win32_getenv(const char *name) 1809 { 1810 dTHX; 1811 DWORD needlen; 1812 SV *curitem = NULL; 1813 DWORD last_err; 1814 1815 needlen = GetEnvironmentVariableA(name,NULL,0); 1816 if (needlen != 0) { 1817 curitem = sv_2mortal(newSVpvs("")); 1818 do { 1819 SvGROW(curitem, needlen+1); 1820 needlen = GetEnvironmentVariableA(name,SvPVX(curitem), 1821 needlen); 1822 } while (needlen >= SvLEN(curitem)); 1823 SvCUR_set(curitem, needlen); 1824 } 1825 else { 1826 last_err = GetLastError(); 1827 if (last_err == ERROR_NOT_ENOUGH_MEMORY) { 1828 /* It appears the variable is in the env, but the Win32 API 1829 doesn't have a canned way of getting it. So we fall back to 1830 grabbing the whole env and pulling this value out if possible */ 1831 char *envv = GetEnvironmentStrings(); 1832 char *cur = envv; 1833 STRLEN len; 1834 while (*cur) { 1835 char *end = strchr(cur,'='); 1836 if (end && end != cur) { 1837 *end = '\0'; 1838 if (strEQ(cur,name)) { 1839 curitem = sv_2mortal(newSVpv(end+1,0)); 1840 *end = '='; 1841 break; 1842 } 1843 *end = '='; 1844 cur = end + strlen(end+1)+2; 1845 } 1846 else if ((len = strlen(cur))) 1847 cur += len+1; 1848 } 1849 FreeEnvironmentStrings(envv); 1850 } 1851 #ifndef WIN32_NO_REGISTRY 1852 else { 1853 /* last ditch: allow any environment variables that begin with 'PERL' 1854 to be obtained from the registry, if found there */ 1855 if (strBEGINs(name, "PERL")) 1856 (void)get_regstr(name, &curitem); 1857 } 1858 #endif 1859 } 1860 if (curitem && SvCUR(curitem)) 1861 return SvPVX(curitem); 1862 1863 return NULL; 1864 } 1865 1866 DllExport int 1867 win32_putenv(const char *name) 1868 { 1869 char* curitem; 1870 char* val; 1871 int relval = -1; 1872 1873 if (name) { 1874 curitem = (char *) win32_malloc(strlen(name)+1); 1875 strcpy(curitem, name); 1876 val = strchr(curitem, '='); 1877 if (val) { 1878 /* The sane way to deal with the environment. 1879 * Has these advantages over putenv() & co.: 1880 * * enables us to store a truly empty value in the 1881 * environment (like in UNIX). 1882 * * we don't have to deal with RTL globals, bugs and leaks 1883 * (specifically, see http://support.microsoft.com/kb/235601). 1884 * * Much faster. 1885 * Why you may want to use the RTL environment handling 1886 * (previously enabled by USE_WIN32_RTL_ENV): 1887 * * environ[] and RTL functions will not reflect changes, 1888 * which might be an issue if extensions want to access 1889 * the env. via RTL. This cuts both ways, since RTL will 1890 * not see changes made by extensions that call the Win32 1891 * functions directly, either. 1892 * GSAR 97-06-07 1893 */ 1894 *val++ = '\0'; 1895 if (SetEnvironmentVariableA(curitem, *val ? val : NULL)) 1896 relval = 0; 1897 } 1898 win32_free(curitem); 1899 } 1900 return relval; 1901 } 1902 1903 static long 1904 filetime_to_clock(PFILETIME ft) 1905 { 1906 __int64 qw = ft->dwHighDateTime; 1907 qw <<= 32; 1908 qw |= ft->dwLowDateTime; 1909 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */ 1910 return (long) qw; 1911 } 1912 1913 DllExport int 1914 win32_times(struct tms *timebuf) 1915 { 1916 FILETIME user; 1917 FILETIME kernel; 1918 FILETIME dummy; 1919 clock_t process_time_so_far = clock(); 1920 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, 1921 &kernel,&user)) { 1922 timebuf->tms_utime = filetime_to_clock(&user); 1923 timebuf->tms_stime = filetime_to_clock(&kernel); 1924 timebuf->tms_cutime = 0; 1925 timebuf->tms_cstime = 0; 1926 } else { 1927 /* That failed - e.g. Win95 fallback to clock() */ 1928 timebuf->tms_utime = process_time_so_far; 1929 timebuf->tms_stime = 0; 1930 timebuf->tms_cutime = 0; 1931 timebuf->tms_cstime = 0; 1932 } 1933 return process_time_so_far; 1934 } 1935 1936 /* fix utime() so it works on directories in NT */ 1937 static BOOL 1938 filetime_from_time(PFILETIME pFileTime, time_t Time) 1939 { 1940 struct tm *pTM = localtime(&Time); 1941 SYSTEMTIME SystemTime; 1942 FILETIME LocalTime; 1943 1944 if (pTM == NULL) 1945 return FALSE; 1946 1947 SystemTime.wYear = pTM->tm_year + 1900; 1948 SystemTime.wMonth = pTM->tm_mon + 1; 1949 SystemTime.wDay = pTM->tm_mday; 1950 SystemTime.wHour = pTM->tm_hour; 1951 SystemTime.wMinute = pTM->tm_min; 1952 SystemTime.wSecond = pTM->tm_sec; 1953 SystemTime.wMilliseconds = 0; 1954 1955 return SystemTimeToFileTime(&SystemTime, &LocalTime) && 1956 LocalFileTimeToFileTime(&LocalTime, pFileTime); 1957 } 1958 1959 DllExport int 1960 win32_unlink(const char *filename) 1961 { 1962 dTHX; 1963 int ret; 1964 DWORD attrs; 1965 1966 filename = PerlDir_mapA(filename); 1967 attrs = GetFileAttributesA(filename); 1968 if (attrs == 0xFFFFFFFF) { 1969 errno = ENOENT; 1970 return -1; 1971 } 1972 if (attrs & FILE_ATTRIBUTE_READONLY) { 1973 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY); 1974 ret = unlink(filename); 1975 if (ret == -1) 1976 (void)SetFileAttributesA(filename, attrs); 1977 } 1978 else 1979 ret = unlink(filename); 1980 return ret; 1981 } 1982 1983 DllExport int 1984 win32_utime(const char *filename, struct utimbuf *times) 1985 { 1986 dTHX; 1987 HANDLE handle; 1988 FILETIME ftCreate; 1989 FILETIME ftAccess; 1990 FILETIME ftWrite; 1991 struct utimbuf TimeBuffer; 1992 int rc; 1993 1994 filename = PerlDir_mapA(filename); 1995 rc = utime(filename, times); 1996 1997 /* EACCES: path specifies directory or readonly file */ 1998 if (rc == 0 || errno != EACCES) 1999 return rc; 2000 2001 if (times == NULL) { 2002 times = &TimeBuffer; 2003 time(×->actime); 2004 times->modtime = times->actime; 2005 } 2006 2007 /* This will (and should) still fail on readonly files */ 2008 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 2009 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, 2010 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 2011 if (handle == INVALID_HANDLE_VALUE) 2012 return rc; 2013 2014 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) && 2015 filetime_from_time(&ftAccess, times->actime) && 2016 filetime_from_time(&ftWrite, times->modtime) && 2017 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite)) 2018 { 2019 rc = 0; 2020 } 2021 2022 CloseHandle(handle); 2023 return rc; 2024 } 2025 2026 typedef union { 2027 unsigned __int64 ft_i64; 2028 FILETIME ft_val; 2029 } FT_t; 2030 2031 #ifdef __GNUC__ 2032 #define Const64(x) x##LL 2033 #else 2034 #define Const64(x) x##i64 2035 #endif 2036 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */ 2037 #define EPOCH_BIAS Const64(116444736000000000) 2038 2039 /* NOTE: This does not compute the timezone info (doing so can be expensive, 2040 * and appears to be unsupported even by glibc) */ 2041 DllExport int 2042 win32_gettimeofday(struct timeval *tp, void *not_used) 2043 { 2044 FT_t ft; 2045 2046 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */ 2047 GetSystemTimeAsFileTime(&ft.ft_val); 2048 2049 /* seconds since epoch */ 2050 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000)); 2051 2052 /* microseconds remaining */ 2053 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000)); 2054 2055 return 0; 2056 } 2057 2058 DllExport int 2059 win32_uname(struct utsname *name) 2060 { 2061 struct hostent *hep; 2062 STRLEN nodemax = sizeof(name->nodename)-1; 2063 2064 /* sysname */ 2065 switch (g_osver.dwPlatformId) { 2066 case VER_PLATFORM_WIN32_WINDOWS: 2067 strcpy(name->sysname, "Windows"); 2068 break; 2069 case VER_PLATFORM_WIN32_NT: 2070 strcpy(name->sysname, "Windows NT"); 2071 break; 2072 case VER_PLATFORM_WIN32s: 2073 strcpy(name->sysname, "Win32s"); 2074 break; 2075 default: 2076 strcpy(name->sysname, "Win32 Unknown"); 2077 break; 2078 } 2079 2080 /* release */ 2081 sprintf(name->release, "%d.%d", 2082 g_osver.dwMajorVersion, g_osver.dwMinorVersion); 2083 2084 /* version */ 2085 sprintf(name->version, "Build %d", 2086 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT 2087 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff)); 2088 if (g_osver.szCSDVersion[0]) { 2089 char *buf = name->version + strlen(name->version); 2090 sprintf(buf, " (%s)", g_osver.szCSDVersion); 2091 } 2092 2093 /* nodename */ 2094 hep = win32_gethostbyname("localhost"); 2095 if (hep) { 2096 STRLEN len = strlen(hep->h_name); 2097 if (len <= nodemax) { 2098 strcpy(name->nodename, hep->h_name); 2099 } 2100 else { 2101 strncpy(name->nodename, hep->h_name, nodemax); 2102 name->nodename[nodemax] = '\0'; 2103 } 2104 } 2105 else { 2106 DWORD sz = nodemax; 2107 if (!GetComputerName(name->nodename, &sz)) 2108 *name->nodename = '\0'; 2109 } 2110 2111 /* machine (architecture) */ 2112 { 2113 SYSTEM_INFO info; 2114 DWORD procarch; 2115 char *arch; 2116 GetSystemInfo(&info); 2117 2118 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION)) 2119 procarch = info.u.s.wProcessorArchitecture; 2120 #else 2121 procarch = info.wProcessorArchitecture; 2122 #endif 2123 switch (procarch) { 2124 case PROCESSOR_ARCHITECTURE_INTEL: 2125 arch = "x86"; break; 2126 case PROCESSOR_ARCHITECTURE_IA64: 2127 arch = "ia64"; break; 2128 case PROCESSOR_ARCHITECTURE_AMD64: 2129 arch = "amd64"; break; 2130 case PROCESSOR_ARCHITECTURE_UNKNOWN: 2131 arch = "unknown"; break; 2132 default: 2133 sprintf(name->machine, "unknown(0x%x)", procarch); 2134 arch = name->machine; 2135 break; 2136 } 2137 if (name->machine != arch) 2138 strcpy(name->machine, arch); 2139 } 2140 return 0; 2141 } 2142 2143 /* Timing related stuff */ 2144 2145 int 2146 do_raise(pTHX_ int sig) 2147 { 2148 if (sig < SIG_SIZE) { 2149 Sighandler_t handler = w32_sighandler[sig]; 2150 if (handler == SIG_IGN) { 2151 return 0; 2152 } 2153 else if (handler != SIG_DFL) { 2154 (*handler)(sig); 2155 return 0; 2156 } 2157 else { 2158 /* Choose correct default behaviour */ 2159 switch (sig) { 2160 #ifdef SIGCLD 2161 case SIGCLD: 2162 #endif 2163 #ifdef SIGCHLD 2164 case SIGCHLD: 2165 #endif 2166 case 0: 2167 return 0; 2168 case SIGTERM: 2169 default: 2170 break; 2171 } 2172 } 2173 } 2174 /* Tell caller to exit thread/process as appropriate */ 2175 return 1; 2176 } 2177 2178 void 2179 sig_terminate(pTHX_ int sig) 2180 { 2181 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig); 2182 /* exit() seems to be safe, my_exit() or die() is a problem in ^C 2183 thread 2184 */ 2185 exit(sig); 2186 } 2187 2188 DllExport int 2189 win32_async_check(pTHX) 2190 { 2191 MSG msg; 2192 HWND hwnd = w32_message_hwnd; 2193 2194 /* Reset w32_poll_count before doing anything else, incase we dispatch 2195 * messages that end up calling back into perl */ 2196 w32_poll_count = 0; 2197 2198 if (hwnd != INVALID_HANDLE_VALUE) { 2199 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages 2200 * and ignores window messages - should co-exist better with windows apps e.g. Tk 2201 */ 2202 if (hwnd == NULL) 2203 hwnd = (HWND)-1; 2204 2205 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) || 2206 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD)) 2207 { 2208 /* re-post a WM_QUIT message (we'll mark it as read later) */ 2209 if(msg.message == WM_QUIT) { 2210 PostQuitMessage((int)msg.wParam); 2211 break; 2212 } 2213 2214 if(!CallMsgFilter(&msg, MSGF_USER)) 2215 { 2216 TranslateMessage(&msg); 2217 DispatchMessage(&msg); 2218 } 2219 } 2220 } 2221 2222 /* Call PeekMessage() to mark all pending messages in the queue as "old". 2223 * This is necessary when we are being called by win32_msgwait() to 2224 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting 2225 * message over and over. An example how this can happen is when 2226 * Perl is calling win32_waitpid() inside a GUI application and the GUI 2227 * is generating messages before the process terminated. 2228 */ 2229 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD); 2230 2231 /* Above or other stuff may have set a signal flag */ 2232 if (PL_sig_pending) 2233 despatch_signals(); 2234 2235 return 1; 2236 } 2237 2238 /* This function will not return until the timeout has elapsed, or until 2239 * one of the handles is ready. */ 2240 DllExport DWORD 2241 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp) 2242 { 2243 int retry = 0; 2244 /* We may need several goes at this - so compute when we stop */ 2245 FT_t ticks = {0}; 2246 unsigned __int64 endtime = timeout; 2247 if (timeout != INFINITE) { 2248 GetSystemTimeAsFileTime(&ticks.ft_val); 2249 ticks.ft_i64 /= 10000; 2250 endtime += ticks.ft_i64; 2251 } 2252 /* This was a race condition. Do not let a non INFINITE timeout to 2253 * MsgWaitForMultipleObjects roll under 0 creating a near 2254 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the 2255 * user who did a CORE perl function with a non infinity timeout, 2256 * sleep for example. This is 64 to 32 truncation minefield. 2257 * 2258 * This scenario can only be created if the timespan from the return of 2259 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To 2260 * generate the scenario, manual breakpoints in a C debugger are required, 2261 * or a context switch occurred in win32_async_check in PeekMessage, or random 2262 * messages are delivered to the *thread* message queue of the Perl thread 2263 * from another process (msctf.dll doing IPC among its instances, VS debugger 2264 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096]. 2265 */ 2266 while (ticks.ft_i64 <= endtime || retry) { 2267 /* if timeout's type is lengthened, remember to split 64b timeout 2268 * into multiple non-infinity runs of MWFMO */ 2269 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE, 2270 (DWORD)(endtime - ticks.ft_i64), 2271 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE); 2272 retry = 0; 2273 if (resultp) 2274 *resultp = result; 2275 if (result == WAIT_TIMEOUT) { 2276 /* Ran out of time - explicit return of zero to avoid -ve if we 2277 have scheduling issues 2278 */ 2279 return 0; 2280 } 2281 if (timeout != INFINITE) { 2282 GetSystemTimeAsFileTime(&ticks.ft_val); 2283 ticks.ft_i64 /= 10000; 2284 } 2285 if (result == WAIT_OBJECT_0 + count) { 2286 /* Message has arrived - check it */ 2287 (void)win32_async_check(aTHX); 2288 retry = 1; 2289 } 2290 else { 2291 /* Not timeout or message - one of handles is ready */ 2292 break; 2293 } 2294 } 2295 /* If we are past the end say zero */ 2296 if (!ticks.ft_i64 || ticks.ft_i64 > endtime) 2297 return 0; 2298 /* compute time left to wait */ 2299 ticks.ft_i64 = endtime - ticks.ft_i64; 2300 /* if more ms than DWORD, then return max DWORD */ 2301 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX; 2302 } 2303 2304 int 2305 win32_internal_wait(pTHX_ int *status, DWORD timeout) 2306 { 2307 /* XXX this wait emulation only knows about processes 2308 * spawned via win32_spawnvp(P_NOWAIT, ...). 2309 */ 2310 int i, retval; 2311 DWORD exitcode, waitcode; 2312 2313 #ifdef USE_ITHREADS 2314 if (w32_num_pseudo_children) { 2315 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles, 2316 timeout, &waitcode); 2317 /* Time out here if there are no other children to wait for. */ 2318 if (waitcode == WAIT_TIMEOUT) { 2319 if (!w32_num_children) { 2320 return 0; 2321 } 2322 } 2323 else if (waitcode != WAIT_FAILED) { 2324 if (waitcode >= WAIT_ABANDONED_0 2325 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children) 2326 i = waitcode - WAIT_ABANDONED_0; 2327 else 2328 i = waitcode - WAIT_OBJECT_0; 2329 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) { 2330 *status = (int)((exitcode & 0xff) << 8); 2331 retval = (int)w32_pseudo_child_pids[i]; 2332 remove_dead_pseudo_process(i); 2333 return -retval; 2334 } 2335 } 2336 } 2337 #endif 2338 2339 if (!w32_num_children) { 2340 errno = ECHILD; 2341 return -1; 2342 } 2343 2344 /* if a child exists, wait for it to die */ 2345 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode); 2346 if (waitcode == WAIT_TIMEOUT) { 2347 return 0; 2348 } 2349 if (waitcode != WAIT_FAILED) { 2350 if (waitcode >= WAIT_ABANDONED_0 2351 && waitcode < WAIT_ABANDONED_0 + w32_num_children) 2352 i = waitcode - WAIT_ABANDONED_0; 2353 else 2354 i = waitcode - WAIT_OBJECT_0; 2355 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) { 2356 *status = (int)((exitcode & 0xff) << 8); 2357 retval = (int)w32_child_pids[i]; 2358 remove_dead_process(i); 2359 return retval; 2360 } 2361 } 2362 2363 errno = GetLastError(); 2364 return -1; 2365 } 2366 2367 DllExport int 2368 win32_waitpid(int pid, int *status, int flags) 2369 { 2370 dTHX; 2371 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE; 2372 int retval = -1; 2373 long child; 2374 if (pid == -1) /* XXX threadid == 1 ? */ 2375 return win32_internal_wait(aTHX_ status, timeout); 2376 #ifdef USE_ITHREADS 2377 else if (pid < 0) { 2378 child = find_pseudo_pid(aTHX_ -pid); 2379 if (child >= 0) { 2380 HANDLE hThread = w32_pseudo_child_handles[child]; 2381 DWORD waitcode; 2382 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode); 2383 if (waitcode == WAIT_TIMEOUT) { 2384 return 0; 2385 } 2386 else if (waitcode == WAIT_OBJECT_0) { 2387 if (GetExitCodeThread(hThread, &waitcode)) { 2388 *status = (int)((waitcode & 0xff) << 8); 2389 retval = (int)w32_pseudo_child_pids[child]; 2390 remove_dead_pseudo_process(child); 2391 return -retval; 2392 } 2393 } 2394 else 2395 errno = ECHILD; 2396 } 2397 } 2398 #endif 2399 else { 2400 HANDLE hProcess; 2401 DWORD waitcode; 2402 child = find_pid(aTHX_ pid); 2403 if (child >= 0) { 2404 hProcess = w32_child_handles[child]; 2405 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode); 2406 if (waitcode == WAIT_TIMEOUT) { 2407 return 0; 2408 } 2409 else if (waitcode == WAIT_OBJECT_0) { 2410 if (GetExitCodeProcess(hProcess, &waitcode)) { 2411 *status = (int)((waitcode & 0xff) << 8); 2412 retval = (int)w32_child_pids[child]; 2413 remove_dead_process(child); 2414 return retval; 2415 } 2416 } 2417 else 2418 errno = ECHILD; 2419 } 2420 else { 2421 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); 2422 if (hProcess) { 2423 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode); 2424 if (waitcode == WAIT_TIMEOUT) { 2425 CloseHandle(hProcess); 2426 return 0; 2427 } 2428 else if (waitcode == WAIT_OBJECT_0) { 2429 if (GetExitCodeProcess(hProcess, &waitcode)) { 2430 *status = (int)((waitcode & 0xff) << 8); 2431 CloseHandle(hProcess); 2432 return pid; 2433 } 2434 } 2435 CloseHandle(hProcess); 2436 } 2437 else 2438 errno = ECHILD; 2439 } 2440 } 2441 return retval >= 0 ? pid : retval; 2442 } 2443 2444 DllExport int 2445 win32_wait(int *status) 2446 { 2447 dTHX; 2448 return win32_internal_wait(aTHX_ status, INFINITE); 2449 } 2450 2451 DllExport unsigned int 2452 win32_sleep(unsigned int t) 2453 { 2454 dTHX; 2455 /* Win32 times are in ms so *1000 in and /1000 out */ 2456 if (t > UINT_MAX / 1000) { 2457 Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW), 2458 "sleep(%lu) too large", t); 2459 } 2460 return win32_msgwait(aTHX_ 0, NULL, t * 1000, NULL) / 1000; 2461 } 2462 2463 DllExport int 2464 win32_pause(void) 2465 { 2466 dTHX; 2467 win32_msgwait(aTHX_ 0, NULL, INFINITE, NULL); 2468 return -1; 2469 } 2470 2471 DllExport unsigned int 2472 win32_alarm(unsigned int sec) 2473 { 2474 /* 2475 * the 'obvious' implentation is SetTimer() with a callback 2476 * which does whatever receiving SIGALRM would do 2477 * we cannot use SIGALRM even via raise() as it is not 2478 * one of the supported codes in <signal.h> 2479 */ 2480 dTHX; 2481 2482 if (w32_message_hwnd == INVALID_HANDLE_VALUE) 2483 w32_message_hwnd = win32_create_message_window(); 2484 2485 if (sec) { 2486 if (w32_message_hwnd == NULL) 2487 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL); 2488 else { 2489 w32_timerid = 1; 2490 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL); 2491 } 2492 } 2493 else { 2494 if (w32_timerid) { 2495 KillTimer(w32_message_hwnd, w32_timerid); 2496 w32_timerid = 0; 2497 } 2498 } 2499 return 0; 2500 } 2501 2502 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf); 2503 2504 DllExport char * 2505 win32_crypt(const char *txt, const char *salt) 2506 { 2507 dTHX; 2508 return des_fcrypt(txt, salt, w32_crypt_buffer); 2509 } 2510 2511 /* simulate flock by locking a range on the file */ 2512 2513 #define LK_LEN 0xffff0000 2514 2515 DllExport int 2516 win32_flock(int fd, int oper) 2517 { 2518 OVERLAPPED o; 2519 int i = -1; 2520 HANDLE fh; 2521 2522 fh = (HANDLE)_get_osfhandle(fd); 2523 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */ 2524 return -1; 2525 2526 memset(&o, 0, sizeof(o)); 2527 2528 switch(oper) { 2529 case LOCK_SH: /* shared lock */ 2530 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o)) 2531 i = 0; 2532 break; 2533 case LOCK_EX: /* exclusive lock */ 2534 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o)) 2535 i = 0; 2536 break; 2537 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */ 2538 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o)) 2539 i = 0; 2540 break; 2541 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */ 2542 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 2543 0, LK_LEN, 0, &o)) 2544 i = 0; 2545 break; 2546 case LOCK_UN: /* unlock lock */ 2547 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o)) 2548 i = 0; 2549 break; 2550 default: /* unknown */ 2551 errno = EINVAL; 2552 return -1; 2553 } 2554 if (i == -1) { 2555 if (GetLastError() == ERROR_LOCK_VIOLATION) 2556 errno = EWOULDBLOCK; 2557 else 2558 errno = EINVAL; 2559 } 2560 return i; 2561 } 2562 2563 #undef LK_LEN 2564 2565 extern int convert_wsa_error_to_errno(int wsaerr); /* in win32sck.c */ 2566 2567 /* Get the errno value corresponding to the given err. This function is not 2568 * intended to handle conversion of general GetLastError() codes. It only exists 2569 * to translate Windows sockets error codes from WSAGetLastError(). Such codes 2570 * used to be assigned to errno/$! in earlier versions of perl; this function is 2571 * used to catch any old Perl code which is still trying to assign such values 2572 * to $! and convert them to errno values instead. 2573 */ 2574 int 2575 win32_get_errno(int err) 2576 { 2577 return convert_wsa_error_to_errno(err); 2578 } 2579 2580 /* 2581 * redirected io subsystem for all XS modules 2582 * 2583 */ 2584 2585 DllExport int * 2586 win32_errno(void) 2587 { 2588 return (&errno); 2589 } 2590 2591 DllExport char *** 2592 win32_environ(void) 2593 { 2594 return (&(_environ)); 2595 } 2596 2597 /* the rest are the remapped stdio routines */ 2598 DllExport FILE * 2599 win32_stderr(void) 2600 { 2601 return (stderr); 2602 } 2603 2604 DllExport FILE * 2605 win32_stdin(void) 2606 { 2607 return (stdin); 2608 } 2609 2610 DllExport FILE * 2611 win32_stdout(void) 2612 { 2613 return (stdout); 2614 } 2615 2616 DllExport int 2617 win32_ferror(FILE *fp) 2618 { 2619 return (ferror(fp)); 2620 } 2621 2622 2623 DllExport int 2624 win32_feof(FILE *fp) 2625 { 2626 return (feof(fp)); 2627 } 2628 2629 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT 2630 extern int convert_errno_to_wsa_error(int err); /* in win32sck.c */ 2631 #endif 2632 2633 /* 2634 * Since the errors returned by the socket error function 2635 * WSAGetLastError() are not known by the library routine strerror 2636 * we have to roll our own to cover the case of socket errors 2637 * that could not be converted to regular errno values by 2638 * get_last_socket_error() in win32/win32sck.c. 2639 */ 2640 2641 DllExport char * 2642 win32_strerror(int e) 2643 { 2644 #if !defined __MINGW32__ /* compiler intolerance */ 2645 extern int sys_nerr; 2646 #endif 2647 2648 if (e < 0 || e > sys_nerr) { 2649 dTHXa(NULL); 2650 if (e < 0) 2651 e = GetLastError(); 2652 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT 2653 /* VC10+ and some MinGW/gcc-4.8+ define a "POSIX supplement" of errno 2654 * values ranging from EADDRINUSE (100) to EWOULDBLOCK (140), but 2655 * sys_nerr is still 43 and strerror() returns "Unknown error" for them. 2656 * We must therefore still roll our own messages for these codes, and 2657 * additionally map them to corresponding Windows (sockets) error codes 2658 * first to avoid getting the wrong system message. 2659 */ 2660 else if (e >= EADDRINUSE && e <= EWOULDBLOCK) { 2661 e = convert_errno_to_wsa_error(e); 2662 } 2663 #endif 2664 2665 aTHXa(PERL_GET_THX); 2666 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 2667 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0, 2668 w32_strerror_buffer, sizeof(w32_strerror_buffer), 2669 NULL) == 0) 2670 { 2671 strcpy(w32_strerror_buffer, "Unknown Error"); 2672 } 2673 return w32_strerror_buffer; 2674 } 2675 #undef strerror 2676 return strerror(e); 2677 #define strerror win32_strerror 2678 } 2679 2680 DllExport void 2681 win32_str_os_error(void *sv, DWORD dwErr) 2682 { 2683 DWORD dwLen; 2684 char *sMsg; 2685 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 2686 |FORMAT_MESSAGE_IGNORE_INSERTS 2687 |FORMAT_MESSAGE_FROM_SYSTEM, NULL, 2688 dwErr, 0, (char *)&sMsg, 1, NULL); 2689 /* strip trailing whitespace and period */ 2690 if (0 < dwLen) { 2691 do { 2692 --dwLen; /* dwLen doesn't include trailing null */ 2693 } while (0 < dwLen && isSPACE(sMsg[dwLen])); 2694 if ('.' != sMsg[dwLen]) 2695 dwLen++; 2696 sMsg[dwLen] = '\0'; 2697 } 2698 if (0 == dwLen) { 2699 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/); 2700 if (sMsg) 2701 dwLen = sprintf(sMsg, 2702 "Unknown error #0x%lX (lookup 0x%lX)", 2703 dwErr, GetLastError()); 2704 } 2705 if (sMsg) { 2706 dTHX; 2707 sv_setpvn((SV*)sv, sMsg, dwLen); 2708 LocalFree(sMsg); 2709 } 2710 } 2711 2712 DllExport int 2713 win32_fprintf(FILE *fp, const char *format, ...) 2714 { 2715 va_list marker; 2716 va_start(marker, format); /* Initialize variable arguments. */ 2717 2718 return (vfprintf(fp, format, marker)); 2719 } 2720 2721 DllExport int 2722 win32_printf(const char *format, ...) 2723 { 2724 va_list marker; 2725 va_start(marker, format); /* Initialize variable arguments. */ 2726 2727 return (vprintf(format, marker)); 2728 } 2729 2730 DllExport int 2731 win32_vfprintf(FILE *fp, const char *format, va_list args) 2732 { 2733 return (vfprintf(fp, format, args)); 2734 } 2735 2736 DllExport int 2737 win32_vprintf(const char *format, va_list args) 2738 { 2739 return (vprintf(format, args)); 2740 } 2741 2742 DllExport size_t 2743 win32_fread(void *buf, size_t size, size_t count, FILE *fp) 2744 { 2745 return fread(buf, size, count, fp); 2746 } 2747 2748 DllExport size_t 2749 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp) 2750 { 2751 return fwrite(buf, size, count, fp); 2752 } 2753 2754 #define MODE_SIZE 10 2755 2756 DllExport FILE * 2757 win32_fopen(const char *filename, const char *mode) 2758 { 2759 dTHXa(NULL); 2760 FILE *f; 2761 2762 if (!*filename) 2763 return NULL; 2764 2765 if (stricmp(filename, "/dev/null")==0) 2766 filename = "NUL"; 2767 2768 aTHXa(PERL_GET_THX); 2769 f = fopen(PerlDir_mapA(filename), mode); 2770 /* avoid buffering headaches for child processes */ 2771 if (f && *mode == 'a') 2772 win32_fseek(f, 0, SEEK_END); 2773 return f; 2774 } 2775 2776 DllExport FILE * 2777 win32_fdopen(int handle, const char *mode) 2778 { 2779 FILE *f; 2780 f = fdopen(handle, (char *) mode); 2781 /* avoid buffering headaches for child processes */ 2782 if (f && *mode == 'a') 2783 win32_fseek(f, 0, SEEK_END); 2784 return f; 2785 } 2786 2787 DllExport FILE * 2788 win32_freopen(const char *path, const char *mode, FILE *stream) 2789 { 2790 dTHXa(NULL); 2791 if (stricmp(path, "/dev/null")==0) 2792 path = "NUL"; 2793 2794 aTHXa(PERL_GET_THX); 2795 return freopen(PerlDir_mapA(path), mode, stream); 2796 } 2797 2798 DllExport int 2799 win32_fclose(FILE *pf) 2800 { 2801 #ifdef WIN32_NO_SOCKETS 2802 return fclose(pf); 2803 #else 2804 return my_fclose(pf); /* defined in win32sck.c */ 2805 #endif 2806 } 2807 2808 DllExport int 2809 win32_fputs(const char *s,FILE *pf) 2810 { 2811 return fputs(s, pf); 2812 } 2813 2814 DllExport int 2815 win32_fputc(int c,FILE *pf) 2816 { 2817 return fputc(c,pf); 2818 } 2819 2820 DllExport int 2821 win32_ungetc(int c,FILE *pf) 2822 { 2823 return ungetc(c,pf); 2824 } 2825 2826 DllExport int 2827 win32_getc(FILE *pf) 2828 { 2829 return getc(pf); 2830 } 2831 2832 DllExport int 2833 win32_fileno(FILE *pf) 2834 { 2835 return fileno(pf); 2836 } 2837 2838 DllExport void 2839 win32_clearerr(FILE *pf) 2840 { 2841 clearerr(pf); 2842 return; 2843 } 2844 2845 DllExport int 2846 win32_fflush(FILE *pf) 2847 { 2848 return fflush(pf); 2849 } 2850 2851 DllExport Off_t 2852 win32_ftell(FILE *pf) 2853 { 2854 #if defined(WIN64) || defined(USE_LARGE_FILES) 2855 fpos_t pos; 2856 if (fgetpos(pf, &pos)) 2857 return -1; 2858 return (Off_t)pos; 2859 #else 2860 return ftell(pf); 2861 #endif 2862 } 2863 2864 DllExport int 2865 win32_fseek(FILE *pf, Off_t offset,int origin) 2866 { 2867 #if defined(WIN64) || defined(USE_LARGE_FILES) 2868 fpos_t pos; 2869 switch (origin) { 2870 case SEEK_CUR: 2871 if (fgetpos(pf, &pos)) 2872 return -1; 2873 offset += pos; 2874 break; 2875 case SEEK_END: 2876 fseek(pf, 0, SEEK_END); 2877 pos = _telli64(fileno(pf)); 2878 offset += pos; 2879 break; 2880 case SEEK_SET: 2881 break; 2882 default: 2883 errno = EINVAL; 2884 return -1; 2885 } 2886 return fsetpos(pf, &offset); 2887 #else 2888 return fseek(pf, (long)offset, origin); 2889 #endif 2890 } 2891 2892 DllExport int 2893 win32_fgetpos(FILE *pf,fpos_t *p) 2894 { 2895 return fgetpos(pf, p); 2896 } 2897 2898 DllExport int 2899 win32_fsetpos(FILE *pf,const fpos_t *p) 2900 { 2901 return fsetpos(pf, p); 2902 } 2903 2904 DllExport void 2905 win32_rewind(FILE *pf) 2906 { 2907 rewind(pf); 2908 return; 2909 } 2910 2911 DllExport int 2912 win32_tmpfd(void) 2913 { 2914 char prefix[MAX_PATH+1]; 2915 char filename[MAX_PATH+1]; 2916 DWORD len = GetTempPath(MAX_PATH, prefix); 2917 if (len && len < MAX_PATH) { 2918 if (GetTempFileName(prefix, "plx", 0, filename)) { 2919 HANDLE fh = CreateFile(filename, 2920 DELETE | GENERIC_READ | GENERIC_WRITE, 2921 0, 2922 NULL, 2923 CREATE_ALWAYS, 2924 FILE_ATTRIBUTE_NORMAL 2925 | FILE_FLAG_DELETE_ON_CLOSE, 2926 NULL); 2927 if (fh != INVALID_HANDLE_VALUE) { 2928 int fd = win32_open_osfhandle((intptr_t)fh, 0); 2929 if (fd >= 0) { 2930 PERL_DEB(dTHX;) 2931 DEBUG_p(PerlIO_printf(Perl_debug_log, 2932 "Created tmpfile=%s\n",filename)); 2933 return fd; 2934 } 2935 } 2936 } 2937 } 2938 return -1; 2939 } 2940 2941 DllExport FILE* 2942 win32_tmpfile(void) 2943 { 2944 int fd = win32_tmpfd(); 2945 if (fd >= 0) 2946 return win32_fdopen(fd, "w+b"); 2947 return NULL; 2948 } 2949 2950 DllExport void 2951 win32_abort(void) 2952 { 2953 abort(); 2954 return; 2955 } 2956 2957 DllExport int 2958 win32_fstat(int fd, Stat_t *sbufptr) 2959 { 2960 #if defined(WIN64) || defined(USE_LARGE_FILES) 2961 return _fstati64(fd, sbufptr); 2962 #else 2963 return fstat(fd, sbufptr); 2964 #endif 2965 } 2966 2967 DllExport int 2968 win32_pipe(int *pfd, unsigned int size, int mode) 2969 { 2970 return _pipe(pfd, size, mode); 2971 } 2972 2973 DllExport PerlIO* 2974 win32_popenlist(const char *mode, IV narg, SV **args) 2975 { 2976 get_shell(); 2977 2978 return do_popen(mode, NULL, narg, args); 2979 } 2980 2981 STATIC PerlIO* 2982 do_popen(const char *mode, const char *command, IV narg, SV **args) { 2983 int p[2]; 2984 int handles[3]; 2985 int parent, child; 2986 int stdfd; 2987 int ourmode; 2988 int childpid; 2989 DWORD nhandle; 2990 int lock_held = 0; 2991 const char **args_pvs = NULL; 2992 2993 /* establish which ends read and write */ 2994 if (strchr(mode,'w')) { 2995 stdfd = 0; /* stdin */ 2996 parent = 1; 2997 child = 0; 2998 nhandle = STD_INPUT_HANDLE; 2999 } 3000 else if (strchr(mode,'r')) { 3001 stdfd = 1; /* stdout */ 3002 parent = 0; 3003 child = 1; 3004 nhandle = STD_OUTPUT_HANDLE; 3005 } 3006 else 3007 return NULL; 3008 3009 /* set the correct mode */ 3010 if (strchr(mode,'b')) 3011 ourmode = O_BINARY; 3012 else if (strchr(mode,'t')) 3013 ourmode = O_TEXT; 3014 else 3015 ourmode = _fmode & (O_TEXT | O_BINARY); 3016 3017 /* the child doesn't inherit handles */ 3018 ourmode |= O_NOINHERIT; 3019 3020 if (win32_pipe(p, 512, ourmode) == -1) 3021 return NULL; 3022 3023 /* Previously this code redirected stdin/out temporarily so the 3024 child process inherited those handles, this caused race 3025 conditions when another thread was writing/reading those 3026 handles. 3027 3028 To avoid that we just feed the handles to CreateProcess() so 3029 the handles are redirected only in the child. 3030 */ 3031 handles[child] = p[child]; 3032 handles[parent] = -1; 3033 handles[2] = -1; 3034 3035 /* CreateProcess() requires inheritable handles */ 3036 if (!SetHandleInformation((HANDLE)_get_osfhandle(p[child]), HANDLE_FLAG_INHERIT, 3037 HANDLE_FLAG_INHERIT)) { 3038 goto cleanup; 3039 } 3040 3041 /* start the child */ 3042 { 3043 dTHX; 3044 3045 if (command) { 3046 if ((childpid = do_spawn2_handles(aTHX_ command, EXECF_SPAWN_NOWAIT, handles)) == -1) 3047 goto cleanup; 3048 3049 } 3050 else { 3051 int i; 3052 const char *exe_name; 3053 3054 Newx(args_pvs, narg + 1 + w32_perlshell_items, const char *); 3055 SAVEFREEPV(args_pvs); 3056 for (i = 0; i < narg; ++i) 3057 args_pvs[i] = SvPV_nolen(args[i]); 3058 args_pvs[i] = NULL; 3059 exe_name = qualified_path(args_pvs[0], TRUE); 3060 if (!exe_name) 3061 /* let CreateProcess() try to find it instead */ 3062 exe_name = args_pvs[0]; 3063 3064 if ((childpid = do_spawnvp_handles(P_NOWAIT, exe_name, args_pvs, handles)) == -1) { 3065 goto cleanup; 3066 } 3067 } 3068 3069 win32_close(p[child]); 3070 3071 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid); 3072 3073 /* set process id so that it can be returned by perl's open() */ 3074 PL_forkprocess = childpid; 3075 } 3076 3077 /* we have an fd, return a file stream */ 3078 return (PerlIO_fdopen(p[parent], (char *)mode)); 3079 3080 cleanup: 3081 /* we don't need to check for errors here */ 3082 win32_close(p[0]); 3083 win32_close(p[1]); 3084 3085 return (NULL); 3086 } 3087 3088 /* 3089 * a popen() clone that respects PERL5SHELL 3090 * 3091 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000 3092 */ 3093 3094 DllExport PerlIO* 3095 win32_popen(const char *command, const char *mode) 3096 { 3097 #ifdef USE_RTL_POPEN 3098 return _popen(command, mode); 3099 #else 3100 return do_popen(mode, command, 0, NULL); 3101 #endif /* USE_RTL_POPEN */ 3102 } 3103 3104 /* 3105 * pclose() clone 3106 */ 3107 3108 DllExport int 3109 win32_pclose(PerlIO *pf) 3110 { 3111 #ifdef USE_RTL_POPEN 3112 return _pclose(pf); 3113 #else 3114 dTHX; 3115 int childpid, status; 3116 SV *sv; 3117 3118 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE); 3119 3120 if (SvIOK(sv)) 3121 childpid = SvIVX(sv); 3122 else 3123 childpid = 0; 3124 3125 if (!childpid) { 3126 errno = EBADF; 3127 return -1; 3128 } 3129 3130 #ifdef USE_PERLIO 3131 PerlIO_close(pf); 3132 #else 3133 fclose(pf); 3134 #endif 3135 SvIVX(sv) = 0; 3136 3137 if (win32_waitpid(childpid, &status, 0) == -1) 3138 return -1; 3139 3140 return status; 3141 3142 #endif /* USE_RTL_POPEN */ 3143 } 3144 3145 DllExport int 3146 win32_link(const char *oldname, const char *newname) 3147 { 3148 dTHXa(NULL); 3149 WCHAR wOldName[MAX_PATH+1]; 3150 WCHAR wNewName[MAX_PATH+1]; 3151 3152 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) && 3153 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) && 3154 ((aTHXa(PERL_GET_THX)), wcscpy(wOldName, PerlDir_mapW(wOldName)), 3155 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL))) 3156 { 3157 return 0; 3158 } 3159 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for 3160 both permissions errors and if the source is a directory, while 3161 POSIX wants EACCES and EPERM respectively. 3162 3163 Determined by experimentation on Windows 7 x64 SP1, since MS 3164 don't document what error codes are returned. 3165 */ 3166 switch (GetLastError()) { 3167 case ERROR_BAD_NET_NAME: 3168 case ERROR_BAD_NETPATH: 3169 case ERROR_BAD_PATHNAME: 3170 case ERROR_FILE_NOT_FOUND: 3171 case ERROR_FILENAME_EXCED_RANGE: 3172 case ERROR_INVALID_DRIVE: 3173 case ERROR_PATH_NOT_FOUND: 3174 errno = ENOENT; 3175 break; 3176 case ERROR_ALREADY_EXISTS: 3177 errno = EEXIST; 3178 break; 3179 case ERROR_ACCESS_DENIED: 3180 errno = EACCES; 3181 break; 3182 case ERROR_NOT_SAME_DEVICE: 3183 errno = EXDEV; 3184 break; 3185 case ERROR_DISK_FULL: 3186 errno = ENOSPC; 3187 break; 3188 case ERROR_NOT_ENOUGH_QUOTA: 3189 errno = EDQUOT; 3190 break; 3191 default: 3192 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */ 3193 errno = EINVAL; 3194 break; 3195 } 3196 return -1; 3197 } 3198 3199 DllExport int 3200 win32_rename(const char *oname, const char *newname) 3201 { 3202 char szOldName[MAX_PATH+1]; 3203 BOOL bResult; 3204 DWORD dwFlags = MOVEFILE_COPY_ALLOWED; 3205 dTHX; 3206 3207 if (stricmp(newname, oname)) 3208 dwFlags |= MOVEFILE_REPLACE_EXISTING; 3209 strcpy(szOldName, PerlDir_mapA(oname)); 3210 3211 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags); 3212 if (!bResult) { 3213 DWORD err = GetLastError(); 3214 switch (err) { 3215 case ERROR_BAD_NET_NAME: 3216 case ERROR_BAD_NETPATH: 3217 case ERROR_BAD_PATHNAME: 3218 case ERROR_FILE_NOT_FOUND: 3219 case ERROR_FILENAME_EXCED_RANGE: 3220 case ERROR_INVALID_DRIVE: 3221 case ERROR_NO_MORE_FILES: 3222 case ERROR_PATH_NOT_FOUND: 3223 errno = ENOENT; 3224 break; 3225 case ERROR_DISK_FULL: 3226 errno = ENOSPC; 3227 break; 3228 case ERROR_NOT_ENOUGH_QUOTA: 3229 errno = EDQUOT; 3230 break; 3231 default: 3232 errno = EACCES; 3233 break; 3234 } 3235 return -1; 3236 } 3237 return 0; 3238 } 3239 3240 DllExport int 3241 win32_setmode(int fd, int mode) 3242 { 3243 return setmode(fd, mode); 3244 } 3245 3246 DllExport int 3247 win32_chsize(int fd, Off_t size) 3248 { 3249 #if defined(WIN64) || defined(USE_LARGE_FILES) 3250 int retval = 0; 3251 Off_t cur, end, extend; 3252 3253 cur = win32_tell(fd); 3254 if (cur < 0) 3255 return -1; 3256 end = win32_lseek(fd, 0, SEEK_END); 3257 if (end < 0) 3258 return -1; 3259 extend = size - end; 3260 if (extend == 0) { 3261 /* do nothing */ 3262 } 3263 else if (extend > 0) { 3264 /* must grow the file, padding with nulls */ 3265 char b[4096]; 3266 int oldmode = win32_setmode(fd, O_BINARY); 3267 size_t count; 3268 memset(b, '\0', sizeof(b)); 3269 do { 3270 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend; 3271 count = win32_write(fd, b, count); 3272 if ((int)count < 0) { 3273 retval = -1; 3274 break; 3275 } 3276 } while ((extend -= count) > 0); 3277 win32_setmode(fd, oldmode); 3278 } 3279 else { 3280 /* shrink the file */ 3281 win32_lseek(fd, size, SEEK_SET); 3282 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) { 3283 errno = EACCES; 3284 retval = -1; 3285 } 3286 } 3287 win32_lseek(fd, cur, SEEK_SET); 3288 return retval; 3289 #else 3290 return chsize(fd, (long)size); 3291 #endif 3292 } 3293 3294 DllExport Off_t 3295 win32_lseek(int fd, Off_t offset, int origin) 3296 { 3297 #if defined(WIN64) || defined(USE_LARGE_FILES) 3298 return _lseeki64(fd, offset, origin); 3299 #else 3300 return lseek(fd, (long)offset, origin); 3301 #endif 3302 } 3303 3304 DllExport Off_t 3305 win32_tell(int fd) 3306 { 3307 #if defined(WIN64) || defined(USE_LARGE_FILES) 3308 return _telli64(fd); 3309 #else 3310 return tell(fd); 3311 #endif 3312 } 3313 3314 DllExport int 3315 win32_open(const char *path, int flag, ...) 3316 { 3317 dTHXa(NULL); 3318 va_list ap; 3319 int pmode; 3320 3321 va_start(ap, flag); 3322 pmode = va_arg(ap, int); 3323 va_end(ap); 3324 3325 if (stricmp(path, "/dev/null")==0) 3326 path = "NUL"; 3327 3328 aTHXa(PERL_GET_THX); 3329 return open(PerlDir_mapA(path), flag, pmode); 3330 } 3331 3332 /* close() that understands socket */ 3333 extern int my_close(int); /* in win32sck.c */ 3334 3335 DllExport int 3336 win32_close(int fd) 3337 { 3338 #ifdef WIN32_NO_SOCKETS 3339 return close(fd); 3340 #else 3341 return my_close(fd); 3342 #endif 3343 } 3344 3345 DllExport int 3346 win32_eof(int fd) 3347 { 3348 return eof(fd); 3349 } 3350 3351 DllExport int 3352 win32_isatty(int fd) 3353 { 3354 /* The Microsoft isatty() function returns true for *all* 3355 * character mode devices, including "nul". Our implementation 3356 * should only return true if the handle has a console buffer. 3357 */ 3358 DWORD mode; 3359 HANDLE fh = (HANDLE)_get_osfhandle(fd); 3360 if (fh == (HANDLE)-1) { 3361 /* errno is already set to EBADF */ 3362 return 0; 3363 } 3364 3365 if (GetConsoleMode(fh, &mode)) 3366 return 1; 3367 3368 errno = ENOTTY; 3369 return 0; 3370 } 3371 3372 DllExport int 3373 win32_dup(int fd) 3374 { 3375 return dup(fd); 3376 } 3377 3378 DllExport int 3379 win32_dup2(int fd1,int fd2) 3380 { 3381 return dup2(fd1,fd2); 3382 } 3383 3384 DllExport int 3385 win32_read(int fd, void *buf, unsigned int cnt) 3386 { 3387 return read(fd, buf, cnt); 3388 } 3389 3390 DllExport int 3391 win32_write(int fd, const void *buf, unsigned int cnt) 3392 { 3393 return write(fd, buf, cnt); 3394 } 3395 3396 DllExport int 3397 win32_mkdir(const char *dir, int mode) 3398 { 3399 dTHX; 3400 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */ 3401 } 3402 3403 DllExport int 3404 win32_rmdir(const char *dir) 3405 { 3406 dTHX; 3407 return rmdir(PerlDir_mapA(dir)); 3408 } 3409 3410 DllExport int 3411 win32_chdir(const char *dir) 3412 { 3413 if (!dir || !*dir) { 3414 errno = ENOENT; 3415 return -1; 3416 } 3417 return chdir(dir); 3418 } 3419 3420 DllExport int 3421 win32_access(const char *path, int mode) 3422 { 3423 dTHX; 3424 return access(PerlDir_mapA(path), mode); 3425 } 3426 3427 DllExport int 3428 win32_chmod(const char *path, int mode) 3429 { 3430 dTHX; 3431 return chmod(PerlDir_mapA(path), mode); 3432 } 3433 3434 3435 static char * 3436 create_command_line(char *cname, STRLEN clen, const char * const *args) 3437 { 3438 PERL_DEB(dTHX;) 3439 int index, argc; 3440 char *cmd, *ptr; 3441 const char *arg; 3442 STRLEN len = 0; 3443 bool bat_file = FALSE; 3444 bool cmd_shell = FALSE; 3445 bool dumb_shell = FALSE; 3446 bool extra_quotes = FALSE; 3447 bool quote_next = FALSE; 3448 3449 if (!cname) 3450 cname = (char*)args[0]; 3451 3452 /* The NT cmd.exe shell has the following peculiarity that needs to be 3453 * worked around. It strips a leading and trailing dquote when any 3454 * of the following is true: 3455 * 1. the /S switch was used 3456 * 2. there are more than two dquotes 3457 * 3. there is a special character from this set: &<>()@^| 3458 * 4. no whitespace characters within the two dquotes 3459 * 5. string between two dquotes isn't an executable file 3460 * To work around this, we always add a leading and trailing dquote 3461 * to the string, if the first argument is either "cmd.exe" or "cmd", 3462 * and there were at least two or more arguments passed to cmd.exe 3463 * (not including switches). 3464 * XXX the above rules (from "cmd /?") don't seem to be applied 3465 * always, making for the convolutions below :-( 3466 */ 3467 if (cname) { 3468 if (!clen) 3469 clen = strlen(cname); 3470 3471 if (clen > 4 3472 && (stricmp(&cname[clen-4], ".bat") == 0 3473 || (stricmp(&cname[clen-4], ".cmd") == 0))) 3474 { 3475 bat_file = TRUE; 3476 len += 3; 3477 } 3478 else { 3479 char *exe = strrchr(cname, '/'); 3480 char *exe2 = strrchr(cname, '\\'); 3481 if (exe2 > exe) 3482 exe = exe2; 3483 if (exe) 3484 ++exe; 3485 else 3486 exe = cname; 3487 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) { 3488 cmd_shell = TRUE; 3489 len += 3; 3490 } 3491 else if (stricmp(exe, "command.com") == 0 3492 || stricmp(exe, "command") == 0) 3493 { 3494 dumb_shell = TRUE; 3495 } 3496 } 3497 } 3498 3499 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args ")); 3500 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) { 3501 STRLEN curlen = strlen(arg); 3502 if (!(arg[0] == '"' && arg[curlen-1] == '"')) 3503 len += 2; /* assume quoting needed (worst case) */ 3504 len += curlen + 1; 3505 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg)); 3506 } 3507 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n")); 3508 3509 argc = index; 3510 Newx(cmd, len, char); 3511 ptr = cmd; 3512 3513 if (bat_file) { 3514 *ptr++ = '"'; 3515 extra_quotes = TRUE; 3516 } 3517 3518 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) { 3519 bool do_quote = 0; 3520 STRLEN curlen = strlen(arg); 3521 3522 /* we want to protect empty arguments and ones with spaces with 3523 * dquotes, but only if they aren't already there */ 3524 if (!dumb_shell) { 3525 if (!curlen) { 3526 do_quote = 1; 3527 } 3528 else if (quote_next) { 3529 /* see if it really is multiple arguments pretending to 3530 * be one and force a set of quotes around it */ 3531 if (*find_next_space(arg)) 3532 do_quote = 1; 3533 } 3534 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) { 3535 STRLEN i = 0; 3536 while (i < curlen) { 3537 if (isSPACE(arg[i])) { 3538 do_quote = 1; 3539 } 3540 else if (arg[i] == '"') { 3541 do_quote = 0; 3542 break; 3543 } 3544 i++; 3545 } 3546 } 3547 } 3548 3549 if (do_quote) 3550 *ptr++ = '"'; 3551 3552 strcpy(ptr, arg); 3553 ptr += curlen; 3554 3555 if (do_quote) 3556 *ptr++ = '"'; 3557 3558 if (args[index+1]) 3559 *ptr++ = ' '; 3560 3561 if (!extra_quotes 3562 && cmd_shell 3563 && curlen >= 2 3564 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */ 3565 && stricmp(arg+curlen-2, "/c") == 0) 3566 { 3567 /* is there a next argument? */ 3568 if (args[index+1]) { 3569 /* are there two or more next arguments? */ 3570 if (args[index+2]) { 3571 *ptr++ = '"'; 3572 extra_quotes = TRUE; 3573 } 3574 else { 3575 /* single argument, force quoting if it has spaces */ 3576 quote_next = TRUE; 3577 } 3578 } 3579 } 3580 } 3581 3582 if (extra_quotes) 3583 *ptr++ = '"'; 3584 3585 *ptr = '\0'; 3586 3587 return cmd; 3588 } 3589 3590 static const char *exe_extensions[] = 3591 { 3592 ".exe", /* this must be first */ 3593 ".cmd", 3594 ".bat" 3595 }; 3596 3597 static char * 3598 qualified_path(const char *cmd, bool other_exts) 3599 { 3600 char *pathstr; 3601 char *fullcmd, *curfullcmd; 3602 STRLEN cmdlen = 0; 3603 int has_slash = 0; 3604 3605 if (!cmd) 3606 return NULL; 3607 fullcmd = (char*)cmd; 3608 while (*fullcmd) { 3609 if (*fullcmd == '/' || *fullcmd == '\\') 3610 has_slash++; 3611 fullcmd++; 3612 cmdlen++; 3613 } 3614 3615 /* look in PATH */ 3616 { 3617 dTHX; 3618 pathstr = PerlEnv_getenv("PATH"); 3619 } 3620 /* worst case: PATH is a single directory; we need additional space 3621 * to append "/", ".exe" and trailing "\0" */ 3622 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char); 3623 curfullcmd = fullcmd; 3624 3625 while (1) { 3626 DWORD res; 3627 3628 /* start by appending the name to the current prefix */ 3629 strcpy(curfullcmd, cmd); 3630 curfullcmd += cmdlen; 3631 3632 /* if it doesn't end with '.', or has no extension, try adding 3633 * a trailing .exe first */ 3634 if (cmd[cmdlen-1] != '.' 3635 && (cmdlen < 4 || cmd[cmdlen-4] != '.')) 3636 { 3637 int i; 3638 /* first extension is .exe */ 3639 int ext_limit = other_exts ? C_ARRAY_LENGTH(exe_extensions) : 1; 3640 for (i = 0; i < ext_limit; ++i) { 3641 strcpy(curfullcmd, exe_extensions[i]); 3642 res = GetFileAttributes(fullcmd); 3643 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY)) 3644 return fullcmd; 3645 } 3646 3647 *curfullcmd = '\0'; 3648 } 3649 3650 /* that failed, try the bare name */ 3651 res = GetFileAttributes(fullcmd); 3652 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY)) 3653 return fullcmd; 3654 3655 /* quit if no other path exists, or if cmd already has path */ 3656 if (!pathstr || !*pathstr || has_slash) 3657 break; 3658 3659 /* skip leading semis */ 3660 while (*pathstr == ';') 3661 pathstr++; 3662 3663 /* build a new prefix from scratch */ 3664 curfullcmd = fullcmd; 3665 while (*pathstr && *pathstr != ';') { 3666 if (*pathstr == '"') { /* foo;"baz;etc";bar */ 3667 pathstr++; /* skip initial '"' */ 3668 while (*pathstr && *pathstr != '"') { 3669 *curfullcmd++ = *pathstr++; 3670 } 3671 if (*pathstr) 3672 pathstr++; /* skip trailing '"' */ 3673 } 3674 else { 3675 *curfullcmd++ = *pathstr++; 3676 } 3677 } 3678 if (*pathstr) 3679 pathstr++; /* skip trailing semi */ 3680 if (curfullcmd > fullcmd /* append a dir separator */ 3681 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\') 3682 { 3683 *curfullcmd++ = '\\'; 3684 } 3685 } 3686 3687 Safefree(fullcmd); 3688 return NULL; 3689 } 3690 3691 /* The following are just place holders. 3692 * Some hosts may provide and environment that the OS is 3693 * not tracking, therefore, these host must provide that 3694 * environment and the current directory to CreateProcess 3695 */ 3696 3697 DllExport void* 3698 win32_get_childenv(void) 3699 { 3700 return NULL; 3701 } 3702 3703 DllExport void 3704 win32_free_childenv(void* d) 3705 { 3706 } 3707 3708 DllExport void 3709 win32_clearenv(void) 3710 { 3711 char *envv = GetEnvironmentStrings(); 3712 char *cur = envv; 3713 STRLEN len; 3714 while (*cur) { 3715 char *end = strchr(cur,'='); 3716 if (end && end != cur) { 3717 *end = '\0'; 3718 SetEnvironmentVariable(cur, NULL); 3719 *end = '='; 3720 cur = end + strlen(end+1)+2; 3721 } 3722 else if ((len = strlen(cur))) 3723 cur += len+1; 3724 } 3725 FreeEnvironmentStrings(envv); 3726 } 3727 3728 DllExport char* 3729 win32_get_childdir(void) 3730 { 3731 char* ptr; 3732 char szfilename[MAX_PATH+1]; 3733 3734 GetCurrentDirectoryA(MAX_PATH+1, szfilename); 3735 Newx(ptr, strlen(szfilename)+1, char); 3736 strcpy(ptr, szfilename); 3737 return ptr; 3738 } 3739 3740 DllExport void 3741 win32_free_childdir(char* d) 3742 { 3743 Safefree(d); 3744 } 3745 3746 3747 /* XXX this needs to be made more compatible with the spawnvp() 3748 * provided by the various RTLs. In particular, searching for 3749 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented. 3750 * This doesn't significantly affect perl itself, because we 3751 * always invoke things using PERL5SHELL if a direct attempt to 3752 * spawn the executable fails. 3753 * 3754 * XXX splitting and rejoining the commandline between do_aspawn() 3755 * and win32_spawnvp() could also be avoided. 3756 */ 3757 3758 DllExport int 3759 win32_spawnvp(int mode, const char *cmdname, const char *const *argv) 3760 { 3761 #ifdef USE_RTL_SPAWNVP 3762 return _spawnvp(mode, cmdname, (char * const *)argv); 3763 #else 3764 return do_spawnvp_handles(mode, cmdname, argv, NULL); 3765 #endif 3766 } 3767 3768 static int 3769 do_spawnvp_handles(int mode, const char *cmdname, const char *const *argv, 3770 const int *handles) { 3771 dTHXa(NULL); 3772 int ret; 3773 void* env; 3774 char* dir; 3775 child_IO_table tbl; 3776 STARTUPINFO StartupInfo; 3777 PROCESS_INFORMATION ProcessInformation; 3778 DWORD create = 0; 3779 char *cmd; 3780 char *fullcmd = NULL; 3781 char *cname = (char *)cmdname; 3782 STRLEN clen = 0; 3783 3784 if (cname) { 3785 clen = strlen(cname); 3786 /* if command name contains dquotes, must remove them */ 3787 if (strchr(cname, '"')) { 3788 cmd = cname; 3789 Newx(cname,clen+1,char); 3790 clen = 0; 3791 while (*cmd) { 3792 if (*cmd != '"') { 3793 cname[clen] = *cmd; 3794 ++clen; 3795 } 3796 ++cmd; 3797 } 3798 cname[clen] = '\0'; 3799 } 3800 } 3801 3802 cmd = create_command_line(cname, clen, argv); 3803 3804 aTHXa(PERL_GET_THX); 3805 env = PerlEnv_get_childenv(); 3806 dir = PerlEnv_get_childdir(); 3807 3808 switch(mode) { 3809 case P_NOWAIT: /* asynch + remember result */ 3810 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) { 3811 errno = EAGAIN; 3812 ret = -1; 3813 goto RETVAL; 3814 } 3815 /* Create a new process group so we can use GenerateConsoleCtrlEvent() 3816 * in win32_kill() 3817 */ 3818 create |= CREATE_NEW_PROCESS_GROUP; 3819 /* FALL THROUGH */ 3820 3821 case P_WAIT: /* synchronous execution */ 3822 break; 3823 default: /* invalid mode */ 3824 errno = EINVAL; 3825 ret = -1; 3826 goto RETVAL; 3827 } 3828 3829 memset(&StartupInfo,0,sizeof(StartupInfo)); 3830 StartupInfo.cb = sizeof(StartupInfo); 3831 memset(&tbl,0,sizeof(tbl)); 3832 PerlEnv_get_child_IO(&tbl); 3833 StartupInfo.dwFlags = tbl.dwFlags; 3834 StartupInfo.dwX = tbl.dwX; 3835 StartupInfo.dwY = tbl.dwY; 3836 StartupInfo.dwXSize = tbl.dwXSize; 3837 StartupInfo.dwYSize = tbl.dwYSize; 3838 StartupInfo.dwXCountChars = tbl.dwXCountChars; 3839 StartupInfo.dwYCountChars = tbl.dwYCountChars; 3840 StartupInfo.dwFillAttribute = tbl.dwFillAttribute; 3841 StartupInfo.wShowWindow = tbl.wShowWindow; 3842 StartupInfo.hStdInput = handles && handles[0] != -1 ? 3843 (HANDLE)_get_osfhandle(handles[0]) : tbl.childStdIn; 3844 StartupInfo.hStdOutput = handles && handles[1] != -1 ? 3845 (HANDLE)_get_osfhandle(handles[1]) : tbl.childStdOut; 3846 StartupInfo.hStdError = handles && handles[2] != -1 ? 3847 (HANDLE)_get_osfhandle(handles[2]) : tbl.childStdErr; 3848 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE && 3849 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE && 3850 StartupInfo.hStdError == INVALID_HANDLE_VALUE) 3851 { 3852 create |= CREATE_NEW_CONSOLE; 3853 } 3854 else { 3855 StartupInfo.dwFlags |= STARTF_USESTDHANDLES; 3856 } 3857 if (w32_use_showwindow) { 3858 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; 3859 StartupInfo.wShowWindow = w32_showwindow; 3860 } 3861 3862 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n", 3863 cname,cmd)); 3864 RETRY: 3865 if (!CreateProcess(cname, /* search PATH to find executable */ 3866 cmd, /* executable, and its arguments */ 3867 NULL, /* process attributes */ 3868 NULL, /* thread attributes */ 3869 TRUE, /* inherit handles */ 3870 create, /* creation flags */ 3871 (LPVOID)env, /* inherit environment */ 3872 dir, /* inherit cwd */ 3873 &StartupInfo, 3874 &ProcessInformation)) 3875 { 3876 /* initial NULL argument to CreateProcess() does a PATH 3877 * search, but it always first looks in the directory 3878 * where the current process was started, which behavior 3879 * is undesirable for backward compatibility. So we 3880 * jump through our own hoops by picking out the path 3881 * we really want it to use. */ 3882 if (!fullcmd) { 3883 fullcmd = qualified_path(cname, FALSE); 3884 if (fullcmd) { 3885 if (cname != cmdname) 3886 Safefree(cname); 3887 cname = fullcmd; 3888 DEBUG_p(PerlIO_printf(Perl_debug_log, 3889 "Retrying [%s] with same args\n", 3890 cname)); 3891 goto RETRY; 3892 } 3893 } 3894 errno = ENOENT; 3895 ret = -1; 3896 goto RETVAL; 3897 } 3898 3899 if (mode == P_NOWAIT) { 3900 /* asynchronous spawn -- store handle, return PID */ 3901 ret = (int)ProcessInformation.dwProcessId; 3902 3903 w32_child_handles[w32_num_children] = ProcessInformation.hProcess; 3904 w32_child_pids[w32_num_children] = (DWORD)ret; 3905 ++w32_num_children; 3906 } 3907 else { 3908 DWORD status; 3909 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL); 3910 /* FIXME: if msgwait returned due to message perhaps forward the 3911 "signal" to the process 3912 */ 3913 GetExitCodeProcess(ProcessInformation.hProcess, &status); 3914 ret = (int)status; 3915 CloseHandle(ProcessInformation.hProcess); 3916 } 3917 3918 CloseHandle(ProcessInformation.hThread); 3919 3920 RETVAL: 3921 PerlEnv_free_childenv(env); 3922 PerlEnv_free_childdir(dir); 3923 Safefree(cmd); 3924 if (cname != cmdname) 3925 Safefree(cname); 3926 return ret; 3927 } 3928 3929 DllExport int 3930 win32_execv(const char *cmdname, const char *const *argv) 3931 { 3932 #ifdef USE_ITHREADS 3933 dTHX; 3934 /* if this is a pseudo-forked child, we just want to spawn 3935 * the new program, and return */ 3936 if (w32_pseudo_id) 3937 return _spawnv(P_WAIT, cmdname, argv); 3938 #endif 3939 return _execv(cmdname, argv); 3940 } 3941 3942 DllExport int 3943 win32_execvp(const char *cmdname, const char *const *argv) 3944 { 3945 #ifdef USE_ITHREADS 3946 dTHX; 3947 /* if this is a pseudo-forked child, we just want to spawn 3948 * the new program, and return */ 3949 if (w32_pseudo_id) { 3950 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv); 3951 if (status != -1) { 3952 my_exit(status); 3953 return 0; 3954 } 3955 else 3956 return status; 3957 } 3958 #endif 3959 return _execvp(cmdname, argv); 3960 } 3961 3962 DllExport void 3963 win32_perror(const char *str) 3964 { 3965 perror(str); 3966 } 3967 3968 DllExport void 3969 win32_setbuf(FILE *pf, char *buf) 3970 { 3971 setbuf(pf, buf); 3972 } 3973 3974 DllExport int 3975 win32_setvbuf(FILE *pf, char *buf, int type, size_t size) 3976 { 3977 return setvbuf(pf, buf, type, size); 3978 } 3979 3980 DllExport int 3981 win32_flushall(void) 3982 { 3983 return flushall(); 3984 } 3985 3986 DllExport int 3987 win32_fcloseall(void) 3988 { 3989 return fcloseall(); 3990 } 3991 3992 DllExport char* 3993 win32_fgets(char *s, int n, FILE *pf) 3994 { 3995 return fgets(s, n, pf); 3996 } 3997 3998 DllExport char* 3999 win32_gets(char *s) 4000 { 4001 return gets(s); 4002 } 4003 4004 DllExport int 4005 win32_fgetc(FILE *pf) 4006 { 4007 return fgetc(pf); 4008 } 4009 4010 DllExport int 4011 win32_putc(int c, FILE *pf) 4012 { 4013 return putc(c,pf); 4014 } 4015 4016 DllExport int 4017 win32_puts(const char *s) 4018 { 4019 return puts(s); 4020 } 4021 4022 DllExport int 4023 win32_getchar(void) 4024 { 4025 return getchar(); 4026 } 4027 4028 DllExport int 4029 win32_putchar(int c) 4030 { 4031 return putchar(c); 4032 } 4033 4034 #ifdef MYMALLOC 4035 4036 #ifndef USE_PERL_SBRK 4037 4038 static char *committed = NULL; /* XXX threadead */ 4039 static char *base = NULL; /* XXX threadead */ 4040 static char *reserved = NULL; /* XXX threadead */ 4041 static char *brk = NULL; /* XXX threadead */ 4042 static DWORD pagesize = 0; /* XXX threadead */ 4043 4044 void * 4045 sbrk(ptrdiff_t need) 4046 { 4047 void *result; 4048 if (!pagesize) 4049 {SYSTEM_INFO info; 4050 GetSystemInfo(&info); 4051 /* Pretend page size is larger so we don't perpetually 4052 * call the OS to commit just one page ... 4053 */ 4054 pagesize = info.dwPageSize << 3; 4055 } 4056 if (brk+need >= reserved) 4057 { 4058 DWORD size = brk+need-reserved; 4059 char *addr; 4060 char *prev_committed = NULL; 4061 if (committed && reserved && committed < reserved) 4062 { 4063 /* Commit last of previous chunk cannot span allocations */ 4064 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE); 4065 if (addr) 4066 { 4067 /* Remember where we committed from in case we want to decommit later */ 4068 prev_committed = committed; 4069 committed = reserved; 4070 } 4071 } 4072 /* Reserve some (more) space 4073 * Contiguous blocks give us greater efficiency, so reserve big blocks - 4074 * this is only address space not memory... 4075 * Note this is a little sneaky, 1st call passes NULL as reserved 4076 * so lets system choose where we start, subsequent calls pass 4077 * the old end address so ask for a contiguous block 4078 */ 4079 sbrk_reserve: 4080 if (size < 64*1024*1024) 4081 size = 64*1024*1024; 4082 size = ((size + pagesize - 1) / pagesize) * pagesize; 4083 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS); 4084 if (addr) 4085 { 4086 reserved = addr+size; 4087 if (!base) 4088 base = addr; 4089 if (!committed) 4090 committed = base; 4091 if (!brk) 4092 brk = committed; 4093 } 4094 else if (reserved) 4095 { 4096 /* The existing block could not be extended far enough, so decommit 4097 * anything that was just committed above and start anew */ 4098 if (prev_committed) 4099 { 4100 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT)) 4101 return (void *) -1; 4102 } 4103 reserved = base = committed = brk = NULL; 4104 size = need; 4105 goto sbrk_reserve; 4106 } 4107 else 4108 { 4109 return (void *) -1; 4110 } 4111 } 4112 result = brk; 4113 brk += need; 4114 if (brk > committed) 4115 { 4116 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize; 4117 char *addr; 4118 if (committed+size > reserved) 4119 size = reserved-committed; 4120 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE); 4121 if (addr) 4122 committed += size; 4123 else 4124 return (void *) -1; 4125 } 4126 return result; 4127 } 4128 4129 #endif 4130 #endif 4131 4132 DllExport void* 4133 win32_malloc(size_t size) 4134 { 4135 return malloc(size); 4136 } 4137 4138 DllExport void* 4139 win32_calloc(size_t numitems, size_t size) 4140 { 4141 return calloc(numitems,size); 4142 } 4143 4144 DllExport void* 4145 win32_realloc(void *block, size_t size) 4146 { 4147 return realloc(block,size); 4148 } 4149 4150 DllExport void 4151 win32_free(void *block) 4152 { 4153 free(block); 4154 } 4155 4156 4157 DllExport int 4158 win32_open_osfhandle(intptr_t handle, int flags) 4159 { 4160 return _open_osfhandle(handle, flags); 4161 } 4162 4163 DllExport intptr_t 4164 win32_get_osfhandle(int fd) 4165 { 4166 return (intptr_t)_get_osfhandle(fd); 4167 } 4168 4169 DllExport FILE * 4170 win32_fdupopen(FILE *pf) 4171 { 4172 FILE* pfdup; 4173 fpos_t pos; 4174 char mode[3]; 4175 int fileno = win32_dup(win32_fileno(pf)); 4176 4177 /* open the file in the same mode */ 4178 if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RD) { 4179 mode[0] = 'r'; 4180 mode[1] = 0; 4181 } 4182 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_WR) { 4183 mode[0] = 'a'; 4184 mode[1] = 0; 4185 } 4186 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RW) { 4187 mode[0] = 'r'; 4188 mode[1] = '+'; 4189 mode[2] = 0; 4190 } 4191 4192 /* it appears that the binmode is attached to the 4193 * file descriptor so binmode files will be handled 4194 * correctly 4195 */ 4196 pfdup = win32_fdopen(fileno, mode); 4197 4198 /* move the file pointer to the same position */ 4199 if (!fgetpos(pf, &pos)) { 4200 fsetpos(pfdup, &pos); 4201 } 4202 return pfdup; 4203 } 4204 4205 DllExport void* 4206 win32_dynaload(const char* filename) 4207 { 4208 dTHXa(NULL); 4209 char buf[MAX_PATH+1]; 4210 const char *first; 4211 4212 /* LoadLibrary() doesn't recognize forward slashes correctly, 4213 * so turn 'em back. */ 4214 first = strchr(filename, '/'); 4215 if (first) { 4216 STRLEN len = strlen(filename); 4217 if (len <= MAX_PATH) { 4218 strcpy(buf, filename); 4219 filename = &buf[first - filename]; 4220 while (*filename) { 4221 if (*filename == '/') 4222 *(char*)filename = '\\'; 4223 ++filename; 4224 } 4225 filename = buf; 4226 } 4227 } 4228 aTHXa(PERL_GET_THX); 4229 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 4230 } 4231 4232 XS(w32_SetChildShowWindow) 4233 { 4234 dXSARGS; 4235 BOOL use_showwindow = w32_use_showwindow; 4236 /* use "unsigned short" because Perl has redefined "WORD" */ 4237 unsigned short showwindow = w32_showwindow; 4238 4239 if (items > 1) 4240 croak_xs_usage(cv, "[showwindow]"); 4241 4242 if (items == 0 || !SvOK(ST(0))) 4243 w32_use_showwindow = FALSE; 4244 else { 4245 w32_use_showwindow = TRUE; 4246 w32_showwindow = (unsigned short)SvIV(ST(0)); 4247 } 4248 4249 EXTEND(SP, 1); 4250 if (use_showwindow) 4251 ST(0) = sv_2mortal(newSViv(showwindow)); 4252 else 4253 ST(0) = &PL_sv_undef; 4254 XSRETURN(1); 4255 } 4256 4257 4258 #ifdef PERL_IS_MINIPERL 4259 /* shelling out is much slower, full perl uses Win32.pm */ 4260 XS(w32_GetCwd) 4261 { 4262 dXSARGS; 4263 /* Make the host for current directory */ 4264 char* ptr = PerlEnv_get_childdir(); 4265 /* 4266 * If ptr != Nullch 4267 * then it worked, set PV valid, 4268 * else return 'undef' 4269 */ 4270 if (ptr) { 4271 SV *sv = sv_newmortal(); 4272 sv_setpv(sv, ptr); 4273 PerlEnv_free_childdir(ptr); 4274 4275 #ifndef INCOMPLETE_TAINTS 4276 SvTAINTED_on(sv); 4277 #endif 4278 4279 ST(0) = sv; 4280 XSRETURN(1); 4281 } 4282 XSRETURN_UNDEF; 4283 } 4284 #endif 4285 4286 void 4287 Perl_init_os_extras(void) 4288 { 4289 dTHXa(NULL); 4290 char *file = __FILE__; 4291 4292 /* Initialize Win32CORE if it has been statically linked. */ 4293 #ifndef PERL_IS_MINIPERL 4294 void (*pfn_init)(pTHX); 4295 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE) 4296 ? GetModuleHandle(NULL) 4297 : w32_perldll_handle); 4298 pfn_init = (void (*)(pTHX))GetProcAddress(module, "init_Win32CORE"); 4299 aTHXa(PERL_GET_THX); 4300 if (pfn_init) 4301 pfn_init(aTHX); 4302 #else 4303 aTHXa(PERL_GET_THX); 4304 #endif 4305 4306 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file); 4307 #ifdef PERL_IS_MINIPERL 4308 newXS("Win32::GetCwd", w32_GetCwd, file); 4309 #endif 4310 } 4311 4312 void * 4313 win32_signal_context(void) 4314 { 4315 dTHX; 4316 #ifdef MULTIPLICITY 4317 if (!my_perl) { 4318 my_perl = PL_curinterp; 4319 PERL_SET_THX(my_perl); 4320 } 4321 return my_perl; 4322 #else 4323 return PL_curinterp; 4324 #endif 4325 } 4326 4327 4328 BOOL WINAPI 4329 win32_ctrlhandler(DWORD dwCtrlType) 4330 { 4331 #ifdef MULTIPLICITY 4332 dTHXa(PERL_GET_SIG_CONTEXT); 4333 4334 if (!my_perl) 4335 return FALSE; 4336 #endif 4337 4338 switch(dwCtrlType) { 4339 case CTRL_CLOSE_EVENT: 4340 /* A signal that the system sends to all processes attached to a console when 4341 the user closes the console (either by choosing the Close command from the 4342 console window's System menu, or by choosing the End Task command from the 4343 Task List 4344 */ 4345 if (do_raise(aTHX_ 1)) /* SIGHUP */ 4346 sig_terminate(aTHX_ 1); 4347 return TRUE; 4348 4349 case CTRL_C_EVENT: 4350 /* A CTRL+c signal was received */ 4351 if (do_raise(aTHX_ SIGINT)) 4352 sig_terminate(aTHX_ SIGINT); 4353 return TRUE; 4354 4355 case CTRL_BREAK_EVENT: 4356 /* A CTRL+BREAK signal was received */ 4357 if (do_raise(aTHX_ SIGBREAK)) 4358 sig_terminate(aTHX_ SIGBREAK); 4359 return TRUE; 4360 4361 case CTRL_LOGOFF_EVENT: 4362 /* A signal that the system sends to all console processes when a user is logging 4363 off. This signal does not indicate which user is logging off, so no 4364 assumptions can be made. 4365 */ 4366 break; 4367 case CTRL_SHUTDOWN_EVENT: 4368 /* A signal that the system sends to all console processes when the system is 4369 shutting down. 4370 */ 4371 if (do_raise(aTHX_ SIGTERM)) 4372 sig_terminate(aTHX_ SIGTERM); 4373 return TRUE; 4374 default: 4375 break; 4376 } 4377 return FALSE; 4378 } 4379 4380 4381 #ifdef SET_INVALID_PARAMETER_HANDLER 4382 # include <crtdbg.h> 4383 #endif 4384 4385 static void 4386 ansify_path(void) 4387 { 4388 size_t len; 4389 char *ansi_path; 4390 WCHAR *wide_path; 4391 WCHAR *wide_dir; 4392 4393 /* fetch Unicode version of PATH */ 4394 len = 2000; 4395 wide_path = (WCHAR*)win32_malloc(len*sizeof(WCHAR)); 4396 while (wide_path) { 4397 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len); 4398 if (newlen == 0) { 4399 win32_free(wide_path); 4400 return; 4401 } 4402 if (newlen < len) 4403 break; 4404 len = newlen; 4405 wide_path = (WCHAR*)win32_realloc(wide_path, len*sizeof(WCHAR)); 4406 } 4407 if (!wide_path) 4408 return; 4409 4410 /* convert to ANSI pathnames */ 4411 wide_dir = wide_path; 4412 ansi_path = NULL; 4413 while (wide_dir) { 4414 WCHAR *sep = wcschr(wide_dir, ';'); 4415 char *ansi_dir; 4416 size_t ansi_len; 4417 size_t wide_len; 4418 4419 if (sep) 4420 *sep++ = '\0'; 4421 4422 /* remove quotes around pathname */ 4423 if (*wide_dir == '"') 4424 ++wide_dir; 4425 wide_len = wcslen(wide_dir); 4426 if (wide_len && wide_dir[wide_len-1] == '"') 4427 wide_dir[wide_len-1] = '\0'; 4428 4429 /* append ansi_dir to ansi_path */ 4430 ansi_dir = win32_ansipath(wide_dir); 4431 ansi_len = strlen(ansi_dir); 4432 if (ansi_path) { 4433 size_t newlen = len + 1 + ansi_len; 4434 ansi_path = (char*)win32_realloc(ansi_path, newlen+1); 4435 if (!ansi_path) 4436 break; 4437 ansi_path[len] = ';'; 4438 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1); 4439 len = newlen; 4440 } 4441 else { 4442 len = ansi_len; 4443 ansi_path = (char*)win32_malloc(5+len+1); 4444 if (!ansi_path) 4445 break; 4446 memcpy(ansi_path, "PATH=", 5); 4447 memcpy(ansi_path+5, ansi_dir, len+1); 4448 len += 5; 4449 } 4450 win32_free(ansi_dir); 4451 wide_dir = sep; 4452 } 4453 4454 if (ansi_path) { 4455 /* Update C RTL environ array. This will only have full effect if 4456 * perl_parse() is later called with `environ` as the `env` argument. 4457 * Otherwise S_init_postdump_symbols() will overwrite PATH again. 4458 * 4459 * We do have to ansify() the PATH before Perl has been fully 4460 * initialized because S_find_script() uses the PATH when perl 4461 * is being invoked with the -S option. This happens before %ENV 4462 * is initialized in S_init_postdump_symbols(). 4463 * 4464 * XXX Is this a bug? Should S_find_script() use the environment 4465 * XXX passed in the `env` arg to parse_perl()? 4466 */ 4467 putenv(ansi_path); 4468 /* Keep system environment in sync because S_init_postdump_symbols() 4469 * will not call mg_set() if it initializes %ENV from `environ`. 4470 */ 4471 SetEnvironmentVariableA("PATH", ansi_path+5); 4472 win32_free(ansi_path); 4473 } 4474 win32_free(wide_path); 4475 } 4476 4477 void 4478 Perl_win32_init(int *argcp, char ***argvp) 4479 { 4480 #ifdef SET_INVALID_PARAMETER_HANDLER 4481 _invalid_parameter_handler oldHandler, newHandler; 4482 newHandler = my_invalid_parameter_handler; 4483 oldHandler = _set_invalid_parameter_handler(newHandler); 4484 _CrtSetReportMode(_CRT_ASSERT, 0); 4485 #endif 4486 /* Disable floating point errors, Perl will trap the ones we 4487 * care about. VC++ RTL defaults to switching these off 4488 * already, but some RTLs don't. Since we don't 4489 * want to be at the vendor's whim on the default, we set 4490 * it explicitly here. 4491 */ 4492 #if !defined(__GNUC__) 4493 _control87(MCW_EM, MCW_EM); 4494 #endif 4495 MALLOC_INIT; 4496 4497 /* When the manifest resource requests Common-Controls v6 then 4498 * user32.dll no longer registers all the Windows classes used for 4499 * standard controls but leaves some of them to be registered by 4500 * comctl32.dll. InitCommonControls() doesn't do anything but calling 4501 * it makes sure comctl32.dll gets loaded into the process and registers 4502 * the standard control classes. Without this even normal Windows APIs 4503 * like MessageBox() can fail under some versions of Windows XP. 4504 */ 4505 InitCommonControls(); 4506 4507 g_osver.dwOSVersionInfoSize = sizeof(g_osver); 4508 GetVersionEx(&g_osver); 4509 4510 #ifdef WIN32_DYN_IOINFO_SIZE 4511 { 4512 Size_t ioinfo_size = _msize((void*)__pioinfo[0]);; 4513 if((SSize_t)ioinfo_size <= 0) { /* -1 is err */ 4514 fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */ 4515 exit(1); 4516 } 4517 ioinfo_size /= IOINFO_ARRAY_ELTS; 4518 w32_ioinfo_size = ioinfo_size; 4519 } 4520 #endif 4521 4522 ansify_path(); 4523 4524 #ifndef WIN32_NO_REGISTRY 4525 { 4526 LONG retval; 4527 retval = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Perl", 0, KEY_READ, &HKCU_Perl_hnd); 4528 if (retval != ERROR_SUCCESS) { 4529 HKCU_Perl_hnd = NULL; 4530 } 4531 retval = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", 0, KEY_READ, &HKLM_Perl_hnd); 4532 if (retval != ERROR_SUCCESS) { 4533 HKLM_Perl_hnd = NULL; 4534 } 4535 } 4536 #endif 4537 } 4538 4539 void 4540 Perl_win32_term(void) 4541 { 4542 HINTS_REFCNT_TERM; 4543 OP_REFCNT_TERM; 4544 PERLIO_TERM; 4545 MALLOC_TERM; 4546 LOCALE_TERM; 4547 #ifndef WIN32_NO_REGISTRY 4548 /* handles might be NULL, RegCloseKey then returns ERROR_INVALID_HANDLE 4549 but no point of checking and we can't die() at this point */ 4550 RegCloseKey(HKLM_Perl_hnd); 4551 RegCloseKey(HKCU_Perl_hnd); 4552 /* the handles are in an undefined state until the next PERL_SYS_INIT3 */ 4553 #endif 4554 } 4555 4556 void 4557 win32_get_child_IO(child_IO_table* ptbl) 4558 { 4559 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE); 4560 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 4561 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE); 4562 } 4563 4564 Sighandler_t 4565 win32_signal(int sig, Sighandler_t subcode) 4566 { 4567 dTHXa(NULL); 4568 if (sig < SIG_SIZE) { 4569 int save_errno = errno; 4570 Sighandler_t result; 4571 #ifdef SET_INVALID_PARAMETER_HANDLER 4572 /* Silence our invalid parameter handler since we expect to make some 4573 * calls with invalid signal numbers giving a SIG_ERR result. */ 4574 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE); 4575 #endif 4576 result = signal(sig, subcode); 4577 #ifdef SET_INVALID_PARAMETER_HANDLER 4578 set_silent_invalid_parameter_handler(oldvalue); 4579 #endif 4580 aTHXa(PERL_GET_THX); 4581 if (result == SIG_ERR) { 4582 result = w32_sighandler[sig]; 4583 errno = save_errno; 4584 } 4585 w32_sighandler[sig] = subcode; 4586 return result; 4587 } 4588 else { 4589 errno = EINVAL; 4590 return SIG_ERR; 4591 } 4592 } 4593 4594 /* The PerlMessageWindowClass's WindowProc */ 4595 LRESULT CALLBACK 4596 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 4597 { 4598 return win32_process_message(hwnd, msg, wParam, lParam) ? 4599 0 : DefWindowProc(hwnd, msg, wParam, lParam); 4600 } 4601 4602 /* The real message handler. Can be called with 4603 * hwnd == NULL to process our thread messages. Returns TRUE for any messages 4604 * that it processes */ 4605 static LRESULT 4606 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 4607 { 4608 /* BEWARE. The context retrieved using dTHX; is the context of the 4609 * 'parent' thread during the CreateWindow() phase - i.e. for all messages 4610 * up to and including WM_CREATE. If it ever happens that you need the 4611 * 'child' context before this, then it needs to be passed into 4612 * win32_create_message_window(), and passed to the WM_NCCREATE handler 4613 * from the lparam of CreateWindow(). It could then be stored/retrieved 4614 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating 4615 * the dTHX calls here. */ 4616 /* XXX For now it is assumed that the overhead of the dTHX; for what 4617 * are relativley infrequent code-paths, is better than the added 4618 * complexity of getting the correct context passed into 4619 * win32_create_message_window() */ 4620 dTHX; 4621 4622 switch(msg) { 4623 4624 #ifdef USE_ITHREADS 4625 case WM_USER_MESSAGE: { 4626 long child = find_pseudo_pid(aTHX_ (int)wParam); 4627 if (child >= 0) { 4628 w32_pseudo_child_message_hwnds[child] = (HWND)lParam; 4629 return 1; 4630 } 4631 break; 4632 } 4633 #endif 4634 4635 case WM_USER_KILL: { 4636 /* We use WM_USER_KILL to fake kill() with other signals */ 4637 int sig = (int)wParam; 4638 if (do_raise(aTHX_ sig)) 4639 sig_terminate(aTHX_ sig); 4640 4641 return 1; 4642 } 4643 4644 case WM_TIMER: { 4645 /* alarm() is a one-shot but SetTimer() repeats so kill it */ 4646 if (w32_timerid && w32_timerid==(UINT)wParam) { 4647 KillTimer(w32_message_hwnd, w32_timerid); 4648 w32_timerid=0; 4649 4650 /* Now fake a call to signal handler */ 4651 if (do_raise(aTHX_ 14)) 4652 sig_terminate(aTHX_ 14); 4653 4654 return 1; 4655 } 4656 break; 4657 } 4658 4659 default: 4660 break; 4661 4662 } /* switch */ 4663 4664 /* Above or other stuff may have set a signal flag, and we may not have 4665 * been called from win32_async_check() (e.g. some other GUI's message 4666 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM 4667 * handler that die's, and the message loop that calls here is wrapped 4668 * in an eval, then you may well end up with orphaned windows - signals 4669 * are dispatched by win32_async_check() */ 4670 4671 return 0; 4672 } 4673 4674 void 4675 win32_create_message_window_class(void) 4676 { 4677 /* create the window class for "message only" windows */ 4678 WNDCLASS wc; 4679 4680 Zero(&wc, 1, wc); 4681 wc.lpfnWndProc = win32_message_window_proc; 4682 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL); 4683 wc.lpszClassName = "PerlMessageWindowClass"; 4684 4685 /* second and subsequent calls will fail, but class 4686 * will already be registered */ 4687 RegisterClass(&wc); 4688 } 4689 4690 HWND 4691 win32_create_message_window(void) 4692 { 4693 win32_create_message_window_class(); 4694 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow", 4695 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); 4696 } 4697 4698 #ifdef HAVE_INTERP_INTERN 4699 4700 static void 4701 win32_csighandler(int sig) 4702 { 4703 #if 0 4704 dTHXa(PERL_GET_SIG_CONTEXT); 4705 Perl_warn(aTHX_ "Got signal %d",sig); 4706 #endif 4707 /* Does nothing */ 4708 } 4709 4710 #if defined(__MINGW32__) && defined(__cplusplus) 4711 #define CAST_HWND__(x) (HWND__*)(x) 4712 #else 4713 #define CAST_HWND__(x) x 4714 #endif 4715 4716 void 4717 Perl_sys_intern_init(pTHX) 4718 { 4719 dVAR; 4720 int i; 4721 4722 w32_perlshell_tokens = NULL; 4723 w32_perlshell_vec = (char**)NULL; 4724 w32_perlshell_items = 0; 4725 w32_fdpid = newAV(); 4726 Newx(w32_children, 1, child_tab); 4727 w32_num_children = 0; 4728 # ifdef USE_ITHREADS 4729 w32_pseudo_id = 0; 4730 Newx(w32_pseudo_children, 1, pseudo_child_tab); 4731 w32_num_pseudo_children = 0; 4732 # endif 4733 w32_timerid = 0; 4734 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE); 4735 w32_poll_count = 0; 4736 #ifdef PERL_IS_MINIPERL 4737 w32_sloppystat = TRUE; 4738 #else 4739 w32_sloppystat = FALSE; 4740 #endif 4741 for (i=0; i < SIG_SIZE; i++) { 4742 w32_sighandler[i] = SIG_DFL; 4743 } 4744 # ifdef MULTIPLICITY 4745 if (my_perl == PL_curinterp) { 4746 # else 4747 { 4748 # endif 4749 /* Force C runtime signal stuff to set its console handler */ 4750 signal(SIGINT,win32_csighandler); 4751 signal(SIGBREAK,win32_csighandler); 4752 4753 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP 4754 * flag. This has the side-effect of disabling Ctrl-C events in all 4755 * processes in this group. 4756 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler() 4757 * with a NULL handler. 4758 */ 4759 SetConsoleCtrlHandler(NULL,FALSE); 4760 4761 /* Push our handler on top */ 4762 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE); 4763 } 4764 } 4765 4766 void 4767 Perl_sys_intern_clear(pTHX) 4768 { 4769 dVAR; 4770 4771 Safefree(w32_perlshell_tokens); 4772 Safefree(w32_perlshell_vec); 4773 /* NOTE: w32_fdpid is freed by sv_clean_all() */ 4774 Safefree(w32_children); 4775 if (w32_timerid) { 4776 KillTimer(w32_message_hwnd, w32_timerid); 4777 w32_timerid = 0; 4778 } 4779 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE) 4780 DestroyWindow(w32_message_hwnd); 4781 # ifdef MULTIPLICITY 4782 if (my_perl == PL_curinterp) { 4783 # else 4784 { 4785 # endif 4786 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE); 4787 } 4788 # ifdef USE_ITHREADS 4789 Safefree(w32_pseudo_children); 4790 # endif 4791 } 4792 4793 # ifdef USE_ITHREADS 4794 4795 void 4796 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst) 4797 { 4798 PERL_ARGS_ASSERT_SYS_INTERN_DUP; 4799 4800 dst->perlshell_tokens = NULL; 4801 dst->perlshell_vec = (char**)NULL; 4802 dst->perlshell_items = 0; 4803 dst->fdpid = newAV(); 4804 Newxz(dst->children, 1, child_tab); 4805 dst->pseudo_id = 0; 4806 Newxz(dst->pseudo_children, 1, pseudo_child_tab); 4807 dst->timerid = 0; 4808 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE); 4809 dst->poll_count = 0; 4810 dst->sloppystat = src->sloppystat; 4811 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t); 4812 } 4813 # endif /* USE_ITHREADS */ 4814 #endif /* HAVE_INTERP_INTERN */ 4815