3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc.
5 * Portions (c) 1993 Intergraph Corporation. All rights reserved.
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.
10 #define PERLIO_NOT_STDIO 0
11 #define WIN32_LEAN_AND_MEAN
12 #define WIN32IO_IS_STDIO
16 # define Win32_Winsock
20 # define _WIN32_WINNT 0x0500 /* needed for CreateHardlink() etc. */
26 # define HWND_MESSAGE ((HWND)-3)
29 #ifndef PROCESSOR_ARCHITECTURE_AMD64
30 # define PROCESSOR_ARCHITECTURE_AMD64 9
33 #ifndef WC_NO_BEST_FIT_CHARS
34 # define WC_NO_BEST_FIT_CHARS 0x00000400
43 /* #include "config.h" */
53 #define PERL_NO_GET_CONTEXT
58 /* assert.h conflicts with #define of assert in perl.h */
66 #include <sys/utime.h>
69 /* Mingw32 defaults to globing command line
70 * So we turn it off like this:
75 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)
76 /* Mingw32-1.1 is missing some prototypes */
78 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
79 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
80 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
88 #define EXECF_SPAWN_NOWAIT 3
90 #if defined(PERL_IMPLICIT_SYS)
92 # define getlogin g_getlogin
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.
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
106 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG)
107 # define SET_INVALID_PARAMETER_HANDLER
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);
117 static char* get_regstr_from(HKEY hkey, const char *valuename, SV **svp);
118 static char* get_regstr(const char *valuename, SV **svp);
119 static char* get_emd_part(SV **prev_pathp, STRLEN *const len,
120 char *trailing, ...);
121 static char* win32_get_xlib(const char *pl, const char *xlib,
122 const char *libname, STRLEN *const len);
123 static BOOL has_shell_metachars(const char *ptr);
124 static long tokenize(const char *str, char **dest, char ***destv);
125 static void get_shell(void);
126 static char* find_next_space(const char *s);
127 static int do_spawn2(pTHX_ const char *cmd, int exectype);
128 static int do_spawn2_handles(pTHX_ const char *cmd, int exectype,
130 static int do_spawnvp_handles(int mode, const char *cmdname,
131 const char * const *argv, const int *handles);
132 static PerlIO * do_popen(const char *mode, const char *command, IV narg,
134 static long find_pid(pTHX_ int pid);
135 static void remove_dead_process(long child);
136 static int terminate_process(DWORD pid, HANDLE process_handle, int sig);
137 static int my_killpg(int pid, int sig);
138 static int my_kill(int pid, int sig);
139 static void out_of_memory(void);
140 static char* wstr_to_str(const wchar_t* wstr);
141 static long filetime_to_clock(PFILETIME ft);
142 static BOOL filetime_from_time(PFILETIME ft, time_t t);
143 static char* create_command_line(char *cname, STRLEN clen,
144 const char * const *args);
145 static char* qualified_path(const char *cmd, bool other_exts);
146 static void ansify_path(void);
147 static LRESULT win32_process_message(HWND hwnd, UINT msg,
148 WPARAM wParam, LPARAM lParam);
151 static long find_pseudo_pid(pTHX_ int pid);
152 static void remove_dead_pseudo_process(long child);
153 static HWND get_hwnd_delay(pTHX, long child, DWORD tries);
156 #ifdef HAVE_INTERP_INTERN
157 static void win32_csighandler(int sig);
161 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
162 char w32_module_name[MAX_PATH+1];
163 #ifdef WIN32_DYN_IOINFO_SIZE
164 Size_t w32_ioinfo_size;/* avoid 0 extend op b4 mul, otherwise could be a U8 */
168 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
170 #ifdef SET_INVALID_PARAMETER_HANDLER
171 static BOOL silent_invalid_parameter_handler = FALSE;
174 set_silent_invalid_parameter_handler(BOOL newvalue)
176 BOOL oldvalue = silent_invalid_parameter_handler;
178 silent_invalid_parameter_handler = newvalue;
184 my_invalid_parameter_handler(const wchar_t* expression,
185 const wchar_t* function,
191 char* ansi_expression;
194 if (silent_invalid_parameter_handler)
196 ansi_expression = wstr_to_str(expression);
197 ansi_function = wstr_to_str(function);
198 ansi_file = wstr_to_str(file);
199 fprintf(stderr, "Invalid parameter detected in function %s. "
200 "File: %s, line: %d\n", ansi_function, ansi_file, line);
201 fprintf(stderr, "Expression: %s\n", ansi_expression);
202 free(ansi_expression);
210 set_w32_module_name(void)
212 /* this function may be called at DLL_PROCESS_ATTACH time */
214 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
215 ? GetModuleHandle(NULL)
216 : w32_perldll_handle);
218 WCHAR modulename[MAX_PATH];
219 WCHAR fullname[MAX_PATH];
222 DWORD (__stdcall *pfnGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD) =
223 (DWORD (__stdcall *)(LPCWSTR, LPWSTR, DWORD))
224 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameW");
226 GetModuleFileNameW(module, modulename, sizeof(modulename)/sizeof(WCHAR));
228 /* Make sure we get an absolute pathname in case the module was loaded
229 * explicitly by LoadLibrary() with a relative path. */
230 GetFullPathNameW(modulename, sizeof(fullname)/sizeof(WCHAR), fullname, NULL);
232 /* Make sure we start with the long path name of the module because we
233 * later scan for pathname components to match "5.xx" to locate
234 * compatible sitelib directories, and the short pathname might mangle
235 * this path segment (e.g. by removing the dot on NTFS to something
236 * like "5xx~1.yy") */
237 if (pfnGetLongPathNameW)
238 pfnGetLongPathNameW(fullname, fullname, sizeof(fullname)/sizeof(WCHAR));
240 /* remove \\?\ prefix */
241 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0)
242 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR));
244 ansi = win32_ansipath(fullname);
245 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name));
248 /* normalize to forward slashes */
249 ptr = w32_module_name;
257 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
259 get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
261 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
264 const char *subkey = "Software\\Perl";
268 retval = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &handle);
269 if (retval == ERROR_SUCCESS) {
271 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen);
272 if (retval == ERROR_SUCCESS
273 && (type == REG_SZ || type == REG_EXPAND_SZ))
277 *svp = sv_2mortal(newSVpvs(""));
278 SvGROW(*svp, datalen);
279 retval = RegQueryValueEx(handle, valuename, 0, NULL,
280 (PBYTE)SvPVX(*svp), &datalen);
281 if (retval == ERROR_SUCCESS) {
283 SvCUR_set(*svp,datalen-1);
291 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
293 get_regstr(const char *valuename, SV **svp)
295 char *str = get_regstr_from(HKEY_CURRENT_USER, valuename, svp);
297 str = get_regstr_from(HKEY_LOCAL_MACHINE, valuename, svp);
301 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
303 get_emd_part(SV **prev_pathp, STRLEN *const len, char *trailing_path, ...)
307 char mod_name[MAX_PATH+1];
313 va_start(ap, trailing_path);
314 strip = va_arg(ap, char *);
316 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
317 baselen = strlen(base);
319 if (!*w32_module_name) {
320 set_w32_module_name();
322 strcpy(mod_name, w32_module_name);
323 ptr = strrchr(mod_name, '/');
324 while (ptr && strip) {
325 /* look for directories to skip back */
328 ptr = strrchr(mod_name, '/');
329 /* avoid stripping component if there is no slash,
330 * or it doesn't match ... */
331 if (!ptr || stricmp(ptr+1, strip) != 0) {
332 /* ... but not if component matches m|5\.$patchlevel.*| */
333 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
334 && strncmp(strip, base, baselen) == 0
335 && strncmp(ptr+1, base, baselen) == 0))
341 strip = va_arg(ap, char *);
349 strcpy(++ptr, trailing_path);
351 /* only add directory if it exists */
352 if (GetFileAttributes(mod_name) != (DWORD) -1) {
353 /* directory exists */
356 *prev_pathp = sv_2mortal(newSVpvs(""));
357 else if (SvPVX(*prev_pathp))
358 sv_catpvs(*prev_pathp, ";");
359 sv_catpv(*prev_pathp, mod_name);
361 *len = SvCUR(*prev_pathp);
362 return SvPVX(*prev_pathp);
369 win32_get_privlib(const char *pl, STRLEN *const len)
371 char *stdlib = "lib";
372 char buffer[MAX_PATH+1];
375 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
376 sprintf(buffer, "%s-%s", stdlib, pl);
377 if (!get_regstr(buffer, &sv))
378 (void)get_regstr(stdlib, &sv);
380 /* $stdlib .= ";$EMD/../../lib" */
381 return get_emd_part(&sv, len, stdlib, ARCHNAME, "bin", NULL);
385 win32_get_xlib(const char *pl, const char *xlib, const char *libname,
389 char pathstr[MAX_PATH+1];
393 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
394 sprintf(regstr, "%s-%s", xlib, pl);
395 (void)get_regstr(regstr, &sv1);
398 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
399 sprintf(pathstr, "%s/%s/lib", libname, pl);
400 (void)get_emd_part(&sv1, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
402 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
403 (void)get_regstr(xlib, &sv2);
406 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
407 sprintf(pathstr, "%s/lib", libname);
408 (void)get_emd_part(&sv2, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
426 win32_get_sitelib(const char *pl, STRLEN *const len)
428 return win32_get_xlib(pl, "sitelib", "site", len);
431 #ifndef PERL_VENDORLIB_NAME
432 # define PERL_VENDORLIB_NAME "vendor"
436 win32_get_vendorlib(const char *pl, STRLEN *const len)
438 return win32_get_xlib(pl, "vendorlib", PERL_VENDORLIB_NAME, len);
442 has_shell_metachars(const char *ptr)
448 * Scan string looking for redirection (< or >) or pipe
449 * characters (|) that are not in a quoted string.
450 * Shell variable interpolation (%VAR%) can also happen inside strings.
482 #if !defined(PERL_IMPLICIT_SYS)
483 /* since the current process environment is being updated in util.c
484 * the library functions will get the correct environment
487 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
489 PERL_FLUSHALL_FOR_CHILD;
490 return win32_popen(cmd, mode);
494 Perl_my_pclose(pTHX_ PerlIO *fp)
496 return win32_pclose(fp);
500 DllExport unsigned long
503 return (unsigned long)g_osver.dwPlatformId;
512 return -((int)w32_pseudo_id);
517 /* Tokenize a string. Words are null-separated, and the list
518 * ends with a doubled null. Any character (except null and
519 * including backslash) may be escaped by preceding it with a
520 * backslash (the backslash will be stripped).
521 * Returns number of words in result buffer.
524 tokenize(const char *str, char **dest, char ***destv)
526 char *retstart = NULL;
527 char **retvstart = 0;
530 int slen = strlen(str);
533 Newx(ret, slen+2, char);
534 Newx(retv, (slen+3)/2, char*);
542 if (*ret == '\\' && *str)
544 else if (*ret == ' ') {
560 retvstart[items] = NULL;
573 if (!w32_perlshell_tokens) {
574 /* we don't use COMSPEC here for two reasons:
575 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
576 * uncontrolled unportability of the ensuing scripts.
577 * 2. PERL5SHELL could be set to a shell that may not be fit for
578 * interactive use (which is what most programs look in COMSPEC
581 const char* defaultshell = "cmd.exe /x/d/c";
582 const char *usershell = PerlEnv_getenv("PERL5SHELL");
583 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
584 &w32_perlshell_tokens,
590 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
598 PERL_ARGS_ASSERT_DO_ASPAWN;
604 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*);
606 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
611 while (++mark <= sp) {
612 if (*mark && (str = SvPV_nolen(*mark)))
619 status = win32_spawnvp(flag,
620 (const char*)(really ? SvPV_nolen(really) : argv[0]),
621 (const char* const*)argv);
623 if (status < 0 && (errno == ENOEXEC || errno == ENOENT)) {
624 /* possible shell-builtin, invoke with shell */
626 sh_items = w32_perlshell_items;
628 argv[index+sh_items] = argv[index];
629 while (--sh_items >= 0)
630 argv[sh_items] = w32_perlshell_vec[sh_items];
632 status = win32_spawnvp(flag,
633 (const char*)(really ? SvPV_nolen(really) : argv[0]),
634 (const char* const*)argv);
637 if (flag == P_NOWAIT) {
638 PL_statusvalue = -1; /* >16bits hint for pp_system() */
642 if (ckWARN(WARN_EXEC))
643 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
648 PL_statusvalue = status;
654 /* returns pointer to the next unquoted space or the end of the string */
656 find_next_space(const char *s)
658 bool in_quotes = FALSE;
660 /* ignore doubled backslashes, or backslash+quote */
661 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) {
664 /* keep track of when we're within quotes */
665 else if (*s == '"') {
667 in_quotes = !in_quotes;
669 /* break it up only at spaces that aren't in quotes */
670 else if (!in_quotes && isSPACE(*s))
679 do_spawn2(pTHX_ const char *cmd, int exectype) {
680 return do_spawn2_handles(aTHX_ cmd, exectype, NULL);
684 do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles)
690 BOOL needToTry = TRUE;
693 /* Save an extra exec if possible. See if there are shell
694 * metacharacters in it */
695 if (!has_shell_metachars(cmd)) {
696 Newx(argv, strlen(cmd) / 2 + 2, char*);
697 Newx(cmd2, strlen(cmd) + 1, char);
700 for (s = cmd2; *s;) {
701 while (*s && isSPACE(*s))
705 s = find_next_space(s);
713 status = win32_spawnvp(P_WAIT, argv[0],
714 (const char* const*)argv);
716 case EXECF_SPAWN_NOWAIT:
717 status = do_spawnvp_handles(P_NOWAIT, argv[0],
718 (const char* const*)argv, handles);
721 status = win32_execvp(argv[0], (const char* const*)argv);
724 if (status != -1 || errno == 0)
734 Newx(argv, w32_perlshell_items + 2, char*);
735 while (++i < w32_perlshell_items)
736 argv[i] = w32_perlshell_vec[i];
737 argv[i++] = (char *)cmd;
741 status = win32_spawnvp(P_WAIT, argv[0],
742 (const char* const*)argv);
744 case EXECF_SPAWN_NOWAIT:
745 status = do_spawnvp_handles(P_NOWAIT, argv[0],
746 (const char* const*)argv, handles);
749 status = win32_execvp(argv[0], (const char* const*)argv);
755 if (exectype == EXECF_SPAWN_NOWAIT) {
756 PL_statusvalue = -1; /* >16bits hint for pp_system() */
760 if (ckWARN(WARN_EXEC))
761 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s",
762 (exectype == EXECF_EXEC ? "exec" : "spawn"),
763 cmd, strerror(errno));
768 PL_statusvalue = status;
774 Perl_do_spawn(pTHX_ char *cmd)
776 PERL_ARGS_ASSERT_DO_SPAWN;
778 return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
782 Perl_do_spawn_nowait(pTHX_ char *cmd)
784 PERL_ARGS_ASSERT_DO_SPAWN_NOWAIT;
786 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
790 Perl_do_exec(pTHX_ const char *cmd)
792 PERL_ARGS_ASSERT_DO_EXEC;
794 do_spawn2(aTHX_ cmd, EXECF_EXEC);
798 /* The idea here is to read all the directory names into a string table
799 * (separated by nulls) and when one of the other dir functions is called
800 * return the pointer to the current file name.
803 win32_opendir(const char *filename)
809 char scanname[MAX_PATH+3];
810 WCHAR wscanname[sizeof(scanname)];
811 WIN32_FIND_DATAW wFindData;
812 char buffer[MAX_PATH*2];
815 len = strlen(filename);
820 if (len > MAX_PATH) {
821 errno = ENAMETOOLONG;
825 /* Get us a DIR structure */
828 /* Create the search pattern */
829 strcpy(scanname, filename);
831 /* bare drive name means look in cwd for drive */
832 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') {
833 scanname[len++] = '.';
834 scanname[len++] = '/';
836 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') {
837 scanname[len++] = '/';
839 scanname[len++] = '*';
840 scanname[len] = '\0';
842 /* do the FindFirstFile call */
843 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR));
845 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData);
847 if (dirp->handle == INVALID_HANDLE_VALUE) {
848 DWORD err = GetLastError();
849 /* FindFirstFile() fails on empty drives! */
851 case ERROR_FILE_NOT_FOUND:
853 case ERROR_NO_MORE_FILES:
854 case ERROR_PATH_NOT_FOUND:
857 case ERROR_NOT_ENOUGH_MEMORY:
869 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
870 wFindData.cFileName, -1,
871 buffer, sizeof(buffer), NULL, &use_default);
872 if (use_default && *wFindData.cAlternateFileName) {
873 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
874 wFindData.cAlternateFileName, -1,
875 buffer, sizeof(buffer), NULL, NULL);
878 /* now allocate the first part of the string table for
879 * the filenames that we find.
881 idx = strlen(buffer)+1;
886 Newx(dirp->start, dirp->size, char);
887 strcpy(dirp->start, buffer);
889 dirp->end = dirp->curr = dirp->start;
895 /* Readdir just returns the current string pointer and bumps the
896 * string pointer to the nDllExport entry.
898 DllExport struct direct *
899 win32_readdir(DIR *dirp)
904 /* first set up the structure to return */
905 len = strlen(dirp->curr);
906 strcpy(dirp->dirstr.d_name, dirp->curr);
907 dirp->dirstr.d_namlen = len;
910 dirp->dirstr.d_ino = dirp->curr - dirp->start;
912 /* Now set up for the next call to readdir */
913 dirp->curr += len + 1;
914 if (dirp->curr >= dirp->end) {
916 char buffer[MAX_PATH*2];
918 if (dirp->handle == INVALID_HANDLE_VALUE) {
921 /* finding the next file that matches the wildcard
922 * (which should be all of them in this directory!).
925 WIN32_FIND_DATAW wFindData;
926 res = FindNextFileW(dirp->handle, &wFindData);
928 BOOL use_default = FALSE;
929 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
930 wFindData.cFileName, -1,
931 buffer, sizeof(buffer), NULL, &use_default);
932 if (use_default && *wFindData.cAlternateFileName) {
933 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
934 wFindData.cAlternateFileName, -1,
935 buffer, sizeof(buffer), NULL, NULL);
940 long endpos = dirp->end - dirp->start;
941 long newsize = endpos + strlen(buffer) + 1;
942 /* bump the string table size by enough for the
943 * new name and its null terminator */
944 while (newsize > dirp->size) {
945 long curpos = dirp->curr - dirp->start;
947 Renew(dirp->start, dirp->size, char);
948 dirp->curr = dirp->start + curpos;
950 strcpy(dirp->start + endpos, buffer);
951 dirp->end = dirp->start + newsize;
956 if (dirp->handle != INVALID_HANDLE_VALUE) {
957 FindClose(dirp->handle);
958 dirp->handle = INVALID_HANDLE_VALUE;
962 return &(dirp->dirstr);
968 /* Telldir returns the current string pointer position */
970 win32_telldir(DIR *dirp)
972 return dirp->curr ? (dirp->curr - dirp->start) : -1;
976 /* Seekdir moves the string pointer to a previously saved position
977 * (returned by telldir).
980 win32_seekdir(DIR *dirp, long loc)
982 dirp->curr = loc == -1 ? NULL : dirp->start + loc;
985 /* Rewinddir resets the string pointer to the start */
987 win32_rewinddir(DIR *dirp)
989 dirp->curr = dirp->start;
992 /* free the memory allocated by opendir */
994 win32_closedir(DIR *dirp)
996 if (dirp->handle != INVALID_HANDLE_VALUE)
997 FindClose(dirp->handle);
998 Safefree(dirp->start);
1003 /* duplicate a open DIR* for interpreter cloning */
1005 win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param)
1008 PerlInterpreter *const from = param->proto_perl;
1009 PerlInterpreter *const to = (PerlInterpreter *)PERL_GET_THX;
1014 /* switch back to original interpreter because win32_readdir()
1015 * might Renew(dirp->start).
1021 /* mark current position; read all remaining entries into the
1022 * cache, and then restore to current position.
1024 pos = win32_telldir(dirp);
1025 while (win32_readdir(dirp)) {
1026 /* read all entries into cache */
1028 win32_seekdir(dirp, pos);
1030 /* switch back to new interpreter to allocate new DIR structure */
1036 memcpy(dup, dirp, sizeof(DIR));
1038 Newx(dup->start, dirp->size, char);
1039 memcpy(dup->start, dirp->start, dirp->size);
1041 dup->end = dup->start + (dirp->end - dirp->start);
1043 dup->curr = dup->start + (dirp->curr - dirp->start);
1055 * Just pretend that everyone is a superuser. NT will let us know if
1056 * we don\'t really have permission to do something.
1059 #define ROOT_UID ((uid_t)0)
1060 #define ROOT_GID ((gid_t)0)
1089 return (auid == ROOT_UID ? 0 : -1);
1095 return (agid == ROOT_GID ? 0 : -1);
1102 char *buf = w32_getlogin_buffer;
1103 DWORD size = sizeof(w32_getlogin_buffer);
1104 if (GetUserName(buf,&size))
1110 chown(const char *path, uid_t owner, gid_t group)
1117 * XXX this needs strengthening (for PerlIO)
1120 #if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4
1121 int mkstemp(const char *path)
1124 char buf[MAX_PATH+1];
1128 if (i++ > 10) { /* give up */
1132 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
1136 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
1144 find_pid(pTHX_ int pid)
1146 long child = w32_num_children;
1147 while (--child >= 0) {
1148 if ((int)w32_child_pids[child] == pid)
1155 remove_dead_process(long child)
1159 CloseHandle(w32_child_handles[child]);
1160 Move(&w32_child_handles[child+1], &w32_child_handles[child],
1161 (w32_num_children-child-1), HANDLE);
1162 Move(&w32_child_pids[child+1], &w32_child_pids[child],
1163 (w32_num_children-child-1), DWORD);
1170 find_pseudo_pid(pTHX_ int pid)
1172 long child = w32_num_pseudo_children;
1173 while (--child >= 0) {
1174 if ((int)w32_pseudo_child_pids[child] == pid)
1181 remove_dead_pseudo_process(long child)
1185 CloseHandle(w32_pseudo_child_handles[child]);
1186 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
1187 (w32_num_pseudo_children-child-1), HANDLE);
1188 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
1189 (w32_num_pseudo_children-child-1), DWORD);
1190 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
1191 (w32_num_pseudo_children-child-1), HWND);
1192 Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child],
1193 (w32_num_pseudo_children-child-1), char);
1194 w32_num_pseudo_children--;
1199 win32_wait_for_children(pTHX)
1201 if (w32_pseudo_children && w32_num_pseudo_children) {
1204 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1206 for (child = 0; child < w32_num_pseudo_children; ++child) {
1207 if (!w32_pseudo_child_sigterm[child])
1208 handles[count++] = w32_pseudo_child_handles[child];
1210 /* XXX should use MsgWaitForMultipleObjects() to continue
1211 * XXX processing messages while we wait.
1213 WaitForMultipleObjects(count, handles, TRUE, INFINITE);
1215 while (w32_num_pseudo_children)
1216 CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]);
1222 terminate_process(DWORD pid, HANDLE process_handle, int sig)
1226 /* "Does process exist?" use of kill */
1229 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid))
1234 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
1237 default: /* For now be backwards compatible with perl 5.6 */
1239 /* Note that we will only be able to kill processes owned by the
1240 * current process owner, even when we are running as an administrator.
1241 * To kill processes of other owners we would need to set the
1242 * 'SeDebugPrivilege' privilege before obtaining the process handle.
1244 if (TerminateProcess(process_handle, sig))
1251 /* returns number of processes killed */
1253 my_killpg(int pid, int sig)
1255 HANDLE process_handle;
1256 HANDLE snapshot_handle;
1259 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1260 if (process_handle == NULL)
1263 killed += terminate_process(pid, process_handle, sig);
1265 snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1266 if (snapshot_handle != INVALID_HANDLE_VALUE) {
1267 PROCESSENTRY32 entry;
1269 entry.dwSize = sizeof(entry);
1270 if (Process32First(snapshot_handle, &entry)) {
1272 if (entry.th32ParentProcessID == (DWORD)pid)
1273 killed += my_killpg(entry.th32ProcessID, sig);
1274 entry.dwSize = sizeof(entry);
1276 while (Process32Next(snapshot_handle, &entry));
1278 CloseHandle(snapshot_handle);
1280 CloseHandle(process_handle);
1284 /* returns number of processes killed */
1286 my_kill(int pid, int sig)
1289 HANDLE process_handle;
1292 return my_killpg(pid, -sig);
1294 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1295 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
1296 if (process_handle != NULL) {
1297 retval = terminate_process(pid, process_handle, sig);
1298 CloseHandle(process_handle);
1304 /* Get a child pseudo-process HWND, with retrying and delaying/yielding.
1305 * The "tries" parameter is the number of retries to make, with a Sleep(1)
1306 * (waiting and yielding the time slot) between each try. Specifying 0 causes
1307 * only Sleep(0) (no waiting and potentially no yielding) to be used, so is not
1309 * Returns an hwnd != INVALID_HANDLE_VALUE (so be aware that NULL can be
1310 * returned) or croaks if the child pseudo-process doesn't schedule and deliver
1311 * a HWND in the time period allowed.
1314 get_hwnd_delay(pTHX, long child, DWORD tries)
1316 HWND hwnd = w32_pseudo_child_message_hwnds[child];
1317 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1319 /* Pseudo-process has not yet properly initialized since hwnd isn't set.
1320 * Fast sleep: On some NT kernels/systems, a Sleep(0) won't deschedule a
1321 * thread 100% of the time since threads are attached to a CPU for NUMA and
1322 * caching reasons, and the child thread was attached to a different CPU
1323 * therefore there is no workload on that CPU and Sleep(0) returns control
1324 * without yielding the time slot.
1325 * https://rt.perl.org/rt3/Ticket/Display.html?id=88840
1328 win32_async_check(aTHX);
1329 hwnd = w32_pseudo_child_message_hwnds[child];
1330 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1333 unsigned int count = 0;
1334 /* No Sleep(1) if tries==0, just fail instead if we get this far. */
1335 while (count++ < tries) {
1337 win32_async_check(aTHX);
1338 hwnd = w32_pseudo_child_message_hwnds[child];
1339 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1343 Perl_croak(aTHX_ "panic: child pseudo-process was never scheduled");
1348 win32_kill(int pid, int sig)
1354 /* it is a pseudo-forked child */
1355 child = find_pseudo_pid(aTHX_ -pid);
1357 HANDLE hProcess = w32_pseudo_child_handles[child];
1360 /* "Does process exist?" use of kill */
1364 /* kill -9 style un-graceful exit */
1365 /* Do a wait to make sure child starts and isn't in DLL
1367 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1368 if (TerminateThread(hProcess, sig)) {
1369 /* Allow the scheduler to finish cleaning up the other
1371 * Otherwise, if we ExitProcess() before another context
1372 * switch happens we will end up with a process exit
1373 * code of "sig" instead of our own exit status.
1374 * https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
1377 remove_dead_pseudo_process(child);
1384 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1385 /* We fake signals to pseudo-processes using Win32
1387 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) ||
1388 PostThreadMessage(-pid, WM_USER_KILL, sig, 0))
1390 /* Don't wait for child process to terminate after we send a
1391 * SIGTERM because the child may be blocked in a system call
1392 * and never receive the signal.
1394 if (sig == SIGTERM) {
1396 w32_pseudo_child_sigterm[child] = 1;
1398 /* It might be us ... */
1410 child = find_pid(aTHX_ pid);
1412 if (my_kill(pid, sig)) {
1414 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) &&
1415 exitcode != STILL_ACTIVE)
1417 remove_dead_process(child);
1423 if (my_kill(pid, sig))
1432 win32_stat(const char *path, Stat_t *sbuf)
1434 char buffer[MAX_PATH+1];
1435 int l = strlen(path);
1439 BOOL expect_dir = FALSE;
1441 GV *gv_sloppy = gv_fetchpvs("\027IN32_SLOPPY_STAT",
1442 GV_NOTQUAL, SVt_PV);
1443 BOOL sloppy = gv_sloppy && SvTRUE(GvSV(gv_sloppy));
1446 switch(path[l - 1]) {
1447 /* FindFirstFile() and stat() are buggy with a trailing
1448 * slashes, except for the root directory of a drive */
1451 if (l > sizeof(buffer)) {
1452 errno = ENAMETOOLONG;
1456 strncpy(buffer, path, l);
1457 /* remove additional trailing slashes */
1458 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\'))
1460 /* add back slash if we otherwise end up with just a drive letter */
1461 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':')
1468 /* FindFirstFile() is buggy with "x:", so add a dot :-( */
1470 if (l == 2 && isALPHA(path[0])) {
1471 buffer[0] = path[0];
1482 path = PerlDir_mapA(path);
1486 /* We must open & close the file once; otherwise file attribute changes */
1487 /* might not yet have propagated to "other" hard links of the same file. */
1488 /* This also gives us an opportunity to determine the number of links. */
1489 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1490 if (handle != INVALID_HANDLE_VALUE) {
1491 BY_HANDLE_FILE_INFORMATION bhi;
1492 if (GetFileInformationByHandle(handle, &bhi))
1493 nlink = bhi.nNumberOfLinks;
1494 CloseHandle(handle);
1498 /* path will be mapped correctly above */
1499 #if defined(WIN64) || defined(USE_LARGE_FILES)
1500 res = _stati64(path, sbuf);
1502 res = stat(path, sbuf);
1504 sbuf->st_nlink = nlink;
1507 /* CRT is buggy on sharenames, so make sure it really isn't.
1508 * XXX using GetFileAttributesEx() will enable us to set
1509 * sbuf->st_*time (but note that's not available on the
1510 * Windows of 1995) */
1511 DWORD r = GetFileAttributesA(path);
1512 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1513 /* sbuf may still contain old garbage since stat() failed */
1514 Zero(sbuf, 1, Stat_t);
1515 sbuf->st_mode = S_IFDIR | S_IREAD;
1517 if (!(r & FILE_ATTRIBUTE_READONLY))
1518 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1523 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1524 && (path[2] == '\\' || path[2] == '/'))
1526 /* The drive can be inaccessible, some _stat()s are buggy */
1527 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1532 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1536 if (S_ISDIR(sbuf->st_mode)) {
1537 /* Ensure the "write" bit is switched off in the mode for
1538 * directories with the read-only attribute set. Some compilers
1539 * switch it on for directories, which is technically correct
1540 * (directories are indeed always writable unless denied by DACLs),
1541 * but we want stat() and -w to reflect the state of the read-only
1542 * attribute for symmetry with chmod(). */
1543 DWORD r = GetFileAttributesA(path);
1544 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
1545 sbuf->st_mode &= ~S_IWRITE;
1552 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1553 #define SKIP_SLASHES(s) \
1555 while (*(s) && isSLASH(*(s))) \
1558 #define COPY_NONSLASHES(d,s) \
1560 while (*(s) && !isSLASH(*(s))) \
1564 /* Find the longname of a given path. path is destructively modified.
1565 * It should have space for at least MAX_PATH characters. */
1567 win32_longpath(char *path)
1569 WIN32_FIND_DATA fdata;
1571 char tmpbuf[MAX_PATH+1];
1572 char *tmpstart = tmpbuf;
1579 if (isALPHA(path[0]) && path[1] == ':') {
1581 *tmpstart++ = path[0];
1585 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1587 *tmpstart++ = path[0];
1588 *tmpstart++ = path[1];
1589 SKIP_SLASHES(start);
1590 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1592 *tmpstart++ = *start++;
1593 SKIP_SLASHES(start);
1594 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1599 /* copy initial slash, if any */
1600 if (isSLASH(*start)) {
1601 *tmpstart++ = *start++;
1603 SKIP_SLASHES(start);
1606 /* FindFirstFile() expands "." and "..", so we need to pass
1607 * those through unmolested */
1609 && (!start[1] || isSLASH(start[1])
1610 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1612 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1617 /* if this is the end, bust outta here */
1621 /* now we're at a non-slash; walk up to next slash */
1622 while (*start && !isSLASH(*start))
1625 /* stop and find full name of component */
1628 fhand = FindFirstFile(path,&fdata);
1630 if (fhand != INVALID_HANDLE_VALUE) {
1631 STRLEN len = strlen(fdata.cFileName);
1632 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1633 strcpy(tmpstart, fdata.cFileName);
1644 /* failed a step, just return without side effects */
1645 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1650 strcpy(path,tmpbuf);
1663 win32_croak_not_implemented(const char * fname)
1665 PERL_ARGS_ASSERT_WIN32_CROAK_NOT_IMPLEMENTED;
1667 Perl_croak_nocontext("%s not implemented!\n", fname);
1670 /* Converts a wide character (UTF-16) string to the Windows ANSI code page,
1671 * potentially using the system's default replacement character for any
1672 * unrepresentable characters. The caller must free() the returned string. */
1674 wstr_to_str(const wchar_t* wstr)
1676 BOOL used_default = FALSE;
1677 size_t wlen = wcslen(wstr) + 1;
1678 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1679 NULL, 0, NULL, NULL);
1680 char* str = (char*)malloc(len);
1683 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1684 str, len, NULL, &used_default);
1688 /* The win32_ansipath() function takes a Unicode filename and converts it
1689 * into the current Windows codepage. If some characters cannot be mapped,
1690 * then it will convert the short name instead.
1692 * The buffer to the ansi pathname must be freed with win32_free() when it
1693 * it no longer needed.
1695 * The argument to win32_ansipath() must exist before this function is
1696 * called; otherwise there is no way to determine the short path name.
1698 * Ideas for future refinement:
1699 * - Only convert those segments of the path that are not in the current
1700 * codepage, but leave the other segments in their long form.
1701 * - If the resulting name is longer than MAX_PATH, start converting
1702 * additional path segments into short names until the full name
1703 * is shorter than MAX_PATH. Shorten the filename part last!
1706 win32_ansipath(const WCHAR *widename)
1709 BOOL use_default = FALSE;
1710 size_t widelen = wcslen(widename)+1;
1711 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1712 NULL, 0, NULL, NULL);
1713 name = (char*)win32_malloc(len);
1717 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1718 name, len, NULL, &use_default);
1720 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1722 WCHAR *shortname = (WCHAR*)win32_malloc(shortlen*sizeof(WCHAR));
1725 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1727 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1728 NULL, 0, NULL, NULL);
1729 name = (char*)win32_realloc(name, len);
1732 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1733 name, len, NULL, NULL);
1734 win32_free(shortname);
1740 /* the returned string must be freed with win32_freeenvironmentstrings which is
1741 * implemented as a macro
1742 * void win32_freeenvironmentstrings(void* block)
1745 win32_getenvironmentstrings(void)
1747 LPWSTR lpWStr, lpWTmp;
1749 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1751 /* Get the process environment strings */
1752 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1753 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1754 env_len = wcslen(lpWTmp);
1755 /* calculate the size of the environment strings */
1756 wenvstrings_len += env_len + 1;
1759 /* Get the number of bytes required to store the ACP encoded string */
1760 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1761 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL);
1762 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1766 /* Convert the string from UTF-16 encoding to ACP encoding */
1767 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1768 aenvstrings_len, NULL, NULL);
1770 FreeEnvironmentStringsW(lpWStr);
1776 win32_getenv(const char *name)
1783 needlen = GetEnvironmentVariableA(name,NULL,0);
1785 curitem = sv_2mortal(newSVpvs(""));
1787 SvGROW(curitem, needlen+1);
1788 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1790 } while (needlen >= SvLEN(curitem));
1791 SvCUR_set(curitem, needlen);
1794 last_err = GetLastError();
1795 if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
1796 /* It appears the variable is in the env, but the Win32 API
1797 doesn't have a canned way of getting it. So we fall back to
1798 grabbing the whole env and pulling this value out if possible */
1799 char *envv = GetEnvironmentStrings();
1803 char *end = strchr(cur,'=');
1804 if (end && end != cur) {
1806 if (!strcmp(cur,name)) {
1807 curitem = sv_2mortal(newSVpv(end+1,0));
1812 cur = end + strlen(end+1)+2;
1814 else if ((len = strlen(cur)))
1817 FreeEnvironmentStrings(envv);
1820 /* last ditch: allow any environment variables that begin with 'PERL'
1821 to be obtained from the registry, if found there */
1822 if (strncmp(name, "PERL", 4) == 0)
1823 (void)get_regstr(name, &curitem);
1826 if (curitem && SvCUR(curitem))
1827 return SvPVX(curitem);
1833 win32_putenv(const char *name)
1840 curitem = (char *) win32_malloc(strlen(name)+1);
1841 strcpy(curitem, name);
1842 val = strchr(curitem, '=');
1844 /* The sane way to deal with the environment.
1845 * Has these advantages over putenv() & co.:
1846 * * enables us to store a truly empty value in the
1847 * environment (like in UNIX).
1848 * * we don't have to deal with RTL globals, bugs and leaks
1849 * (specifically, see http://support.microsoft.com/kb/235601).
1851 * Why you may want to use the RTL environment handling
1852 * (previously enabled by USE_WIN32_RTL_ENV):
1853 * * environ[] and RTL functions will not reflect changes,
1854 * which might be an issue if extensions want to access
1855 * the env. via RTL. This cuts both ways, since RTL will
1856 * not see changes made by extensions that call the Win32
1857 * functions directly, either.
1861 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1864 win32_free(curitem);
1870 filetime_to_clock(PFILETIME ft)
1872 __int64 qw = ft->dwHighDateTime;
1874 qw |= ft->dwLowDateTime;
1875 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1880 win32_times(struct tms *timebuf)
1885 clock_t process_time_so_far = clock();
1886 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1888 timebuf->tms_utime = filetime_to_clock(&user);
1889 timebuf->tms_stime = filetime_to_clock(&kernel);
1890 timebuf->tms_cutime = 0;
1891 timebuf->tms_cstime = 0;
1893 /* That failed - e.g. Win95 fallback to clock() */
1894 timebuf->tms_utime = process_time_so_far;
1895 timebuf->tms_stime = 0;
1896 timebuf->tms_cutime = 0;
1897 timebuf->tms_cstime = 0;
1899 return process_time_so_far;
1902 /* fix utime() so it works on directories in NT */
1904 filetime_from_time(PFILETIME pFileTime, time_t Time)
1906 struct tm *pTM = localtime(&Time);
1907 SYSTEMTIME SystemTime;
1913 SystemTime.wYear = pTM->tm_year + 1900;
1914 SystemTime.wMonth = pTM->tm_mon + 1;
1915 SystemTime.wDay = pTM->tm_mday;
1916 SystemTime.wHour = pTM->tm_hour;
1917 SystemTime.wMinute = pTM->tm_min;
1918 SystemTime.wSecond = pTM->tm_sec;
1919 SystemTime.wMilliseconds = 0;
1921 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1922 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1926 win32_unlink(const char *filename)
1932 filename = PerlDir_mapA(filename);
1933 attrs = GetFileAttributesA(filename);
1934 if (attrs == 0xFFFFFFFF) {
1938 if (attrs & FILE_ATTRIBUTE_READONLY) {
1939 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1940 ret = unlink(filename);
1942 (void)SetFileAttributesA(filename, attrs);
1945 ret = unlink(filename);
1950 win32_utime(const char *filename, struct utimbuf *times)
1957 struct utimbuf TimeBuffer;
1960 filename = PerlDir_mapA(filename);
1961 rc = utime(filename, times);
1963 /* EACCES: path specifies directory or readonly file */
1964 if (rc == 0 || errno != EACCES)
1967 if (times == NULL) {
1968 times = &TimeBuffer;
1969 time(×->actime);
1970 times->modtime = times->actime;
1973 /* This will (and should) still fail on readonly files */
1974 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
1975 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
1976 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1977 if (handle == INVALID_HANDLE_VALUE)
1980 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
1981 filetime_from_time(&ftAccess, times->actime) &&
1982 filetime_from_time(&ftWrite, times->modtime) &&
1983 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
1988 CloseHandle(handle);
1993 unsigned __int64 ft_i64;
1998 #define Const64(x) x##LL
2000 #define Const64(x) x##i64
2002 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
2003 #define EPOCH_BIAS Const64(116444736000000000)
2005 /* NOTE: This does not compute the timezone info (doing so can be expensive,
2006 * and appears to be unsupported even by glibc) */
2008 win32_gettimeofday(struct timeval *tp, void *not_used)
2012 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
2013 GetSystemTimeAsFileTime(&ft.ft_val);
2015 /* seconds since epoch */
2016 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
2018 /* microseconds remaining */
2019 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
2025 win32_uname(struct utsname *name)
2027 struct hostent *hep;
2028 STRLEN nodemax = sizeof(name->nodename)-1;
2031 switch (g_osver.dwPlatformId) {
2032 case VER_PLATFORM_WIN32_WINDOWS:
2033 strcpy(name->sysname, "Windows");
2035 case VER_PLATFORM_WIN32_NT:
2036 strcpy(name->sysname, "Windows NT");
2038 case VER_PLATFORM_WIN32s:
2039 strcpy(name->sysname, "Win32s");
2042 strcpy(name->sysname, "Win32 Unknown");
2047 sprintf(name->release, "%d.%d",
2048 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
2051 sprintf(name->version, "Build %d",
2052 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
2053 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
2054 if (g_osver.szCSDVersion[0]) {
2055 char *buf = name->version + strlen(name->version);
2056 sprintf(buf, " (%s)", g_osver.szCSDVersion);
2060 hep = win32_gethostbyname("localhost");
2062 STRLEN len = strlen(hep->h_name);
2063 if (len <= nodemax) {
2064 strcpy(name->nodename, hep->h_name);
2067 strncpy(name->nodename, hep->h_name, nodemax);
2068 name->nodename[nodemax] = '\0';
2073 if (!GetComputerName(name->nodename, &sz))
2074 *name->nodename = '\0';
2077 /* machine (architecture) */
2082 GetSystemInfo(&info);
2084 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION))
2085 procarch = info.u.s.wProcessorArchitecture;
2087 procarch = info.wProcessorArchitecture;
2090 case PROCESSOR_ARCHITECTURE_INTEL:
2091 arch = "x86"; break;
2092 case PROCESSOR_ARCHITECTURE_IA64:
2093 arch = "ia64"; break;
2094 case PROCESSOR_ARCHITECTURE_AMD64:
2095 arch = "amd64"; break;
2096 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2097 arch = "unknown"; break;
2099 sprintf(name->machine, "unknown(0x%x)", procarch);
2100 arch = name->machine;
2103 if (name->machine != arch)
2104 strcpy(name->machine, arch);
2109 /* Timing related stuff */
2112 do_raise(pTHX_ int sig)
2114 if (sig < SIG_SIZE) {
2115 Sighandler_t handler = w32_sighandler[sig];
2116 if (handler == SIG_IGN) {
2119 else if (handler != SIG_DFL) {
2124 /* Choose correct default behaviour */
2140 /* Tell caller to exit thread/process as appropriate */
2145 sig_terminate(pTHX_ int sig)
2147 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2148 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2155 win32_async_check(pTHX)
2158 HWND hwnd = w32_message_hwnd;
2160 /* Reset w32_poll_count before doing anything else, incase we dispatch
2161 * messages that end up calling back into perl */
2164 if (hwnd != INVALID_HANDLE_VALUE) {
2165 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2166 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2171 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2172 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2174 /* re-post a WM_QUIT message (we'll mark it as read later) */
2175 if(msg.message == WM_QUIT) {
2176 PostQuitMessage((int)msg.wParam);
2180 if(!CallMsgFilter(&msg, MSGF_USER))
2182 TranslateMessage(&msg);
2183 DispatchMessage(&msg);
2188 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2189 * This is necessary when we are being called by win32_msgwait() to
2190 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2191 * message over and over. An example how this can happen is when
2192 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2193 * is generating messages before the process terminated.
2195 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD);
2197 /* Above or other stuff may have set a signal flag */
2204 /* This function will not return until the timeout has elapsed, or until
2205 * one of the handles is ready. */
2207 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2209 /* We may need several goes at this - so compute when we stop */
2211 unsigned __int64 endtime = timeout;
2212 if (timeout != INFINITE) {
2213 GetSystemTimeAsFileTime(&ticks.ft_val);
2214 ticks.ft_i64 /= 10000;
2215 endtime += ticks.ft_i64;
2217 /* This was a race condition. Do not let a non INFINITE timeout to
2218 * MsgWaitForMultipleObjects roll under 0 creating a near
2219 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the
2220 * user who did a CORE perl function with a non infinity timeout,
2221 * sleep for example. This is 64 to 32 truncation minefield.
2223 * This scenario can only be created if the timespan from the return of
2224 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To
2225 * generate the scenario, manual breakpoints in a C debugger are required,
2226 * or a context switch occurred in win32_async_check in PeekMessage, or random
2227 * messages are delivered to the *thread* message queue of the Perl thread
2228 * from another process (msctf.dll doing IPC among its instances, VS debugger
2229 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096].
2231 while (ticks.ft_i64 <= endtime) {
2232 /* if timeout's type is lengthened, remember to split 64b timeout
2233 * into multiple non-infinity runs of MWFMO */
2234 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE,
2235 (DWORD)(endtime - ticks.ft_i64),
2236 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2239 if (result == WAIT_TIMEOUT) {
2240 /* Ran out of time - explicit return of zero to avoid -ve if we
2241 have scheduling issues
2245 if (timeout != INFINITE) {
2246 GetSystemTimeAsFileTime(&ticks.ft_val);
2247 ticks.ft_i64 /= 10000;
2249 if (result == WAIT_OBJECT_0 + count) {
2250 /* Message has arrived - check it */
2251 (void)win32_async_check(aTHX);
2254 /* Not timeout or message - one of handles is ready */
2258 /* If we are past the end say zero */
2259 if (!ticks.ft_i64 || ticks.ft_i64 > endtime)
2261 /* compute time left to wait */
2262 ticks.ft_i64 = endtime - ticks.ft_i64;
2263 /* if more ms than DWORD, then return max DWORD */
2264 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX;
2268 win32_internal_wait(pTHX_ int *status, DWORD timeout)
2270 /* XXX this wait emulation only knows about processes
2271 * spawned via win32_spawnvp(P_NOWAIT, ...).
2274 DWORD exitcode, waitcode;
2277 if (w32_num_pseudo_children) {
2278 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2279 timeout, &waitcode);
2280 /* Time out here if there are no other children to wait for. */
2281 if (waitcode == WAIT_TIMEOUT) {
2282 if (!w32_num_children) {
2286 else if (waitcode != WAIT_FAILED) {
2287 if (waitcode >= WAIT_ABANDONED_0
2288 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2289 i = waitcode - WAIT_ABANDONED_0;
2291 i = waitcode - WAIT_OBJECT_0;
2292 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2293 *status = (int)((exitcode & 0xff) << 8);
2294 retval = (int)w32_pseudo_child_pids[i];
2295 remove_dead_pseudo_process(i);
2302 if (!w32_num_children) {
2307 /* if a child exists, wait for it to die */
2308 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2309 if (waitcode == WAIT_TIMEOUT) {
2312 if (waitcode != WAIT_FAILED) {
2313 if (waitcode >= WAIT_ABANDONED_0
2314 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2315 i = waitcode - WAIT_ABANDONED_0;
2317 i = waitcode - WAIT_OBJECT_0;
2318 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2319 *status = (int)((exitcode & 0xff) << 8);
2320 retval = (int)w32_child_pids[i];
2321 remove_dead_process(i);
2326 errno = GetLastError();
2331 win32_waitpid(int pid, int *status, int flags)
2334 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2337 if (pid == -1) /* XXX threadid == 1 ? */
2338 return win32_internal_wait(aTHX_ status, timeout);
2341 child = find_pseudo_pid(aTHX_ -pid);
2343 HANDLE hThread = w32_pseudo_child_handles[child];
2345 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2346 if (waitcode == WAIT_TIMEOUT) {
2349 else if (waitcode == WAIT_OBJECT_0) {
2350 if (GetExitCodeThread(hThread, &waitcode)) {
2351 *status = (int)((waitcode & 0xff) << 8);
2352 retval = (int)w32_pseudo_child_pids[child];
2353 remove_dead_pseudo_process(child);
2365 child = find_pid(aTHX_ pid);
2367 hProcess = w32_child_handles[child];
2368 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2369 if (waitcode == WAIT_TIMEOUT) {
2372 else if (waitcode == WAIT_OBJECT_0) {
2373 if (GetExitCodeProcess(hProcess, &waitcode)) {
2374 *status = (int)((waitcode & 0xff) << 8);
2375 retval = (int)w32_child_pids[child];
2376 remove_dead_process(child);
2384 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
2386 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2387 if (waitcode == WAIT_TIMEOUT) {
2388 CloseHandle(hProcess);
2391 else if (waitcode == WAIT_OBJECT_0) {
2392 if (GetExitCodeProcess(hProcess, &waitcode)) {
2393 *status = (int)((waitcode & 0xff) << 8);
2394 CloseHandle(hProcess);
2398 CloseHandle(hProcess);
2404 return retval >= 0 ? pid : retval;
2408 win32_wait(int *status)
2411 return win32_internal_wait(aTHX_ status, INFINITE);
2414 DllExport unsigned int
2415 win32_sleep(unsigned int t)
2418 /* Win32 times are in ms so *1000 in and /1000 out */
2419 if (t > UINT_MAX / 1000) {
2420 Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
2421 "sleep(%lu) too large", t);
2423 return win32_msgwait(aTHX_ 0, NULL, t * 1000, NULL) / 1000;
2426 DllExport unsigned int
2427 win32_alarm(unsigned int sec)
2430 * the 'obvious' implentation is SetTimer() with a callback
2431 * which does whatever receiving SIGALRM would do
2432 * we cannot use SIGALRM even via raise() as it is not
2433 * one of the supported codes in <signal.h>
2437 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2438 w32_message_hwnd = win32_create_message_window();
2441 if (w32_message_hwnd == NULL)
2442 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2445 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2450 KillTimer(w32_message_hwnd, w32_timerid);
2457 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2460 win32_crypt(const char *txt, const char *salt)
2463 return des_fcrypt(txt, salt, w32_crypt_buffer);
2466 /* simulate flock by locking a range on the file */
2468 #define LK_LEN 0xffff0000
2471 win32_flock(int fd, int oper)
2477 fh = (HANDLE)_get_osfhandle(fd);
2478 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */
2481 memset(&o, 0, sizeof(o));
2484 case LOCK_SH: /* shared lock */
2485 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
2488 case LOCK_EX: /* exclusive lock */
2489 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
2492 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2493 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
2496 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2497 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2501 case LOCK_UN: /* unlock lock */
2502 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o))
2505 default: /* unknown */
2510 if (GetLastError() == ERROR_LOCK_VIOLATION)
2511 errno = EWOULDBLOCK;
2520 extern int convert_wsa_error_to_errno(int wsaerr); /* in win32sck.c */
2522 /* Get the errno value corresponding to the given err. This function is not
2523 * intended to handle conversion of general GetLastError() codes. It only exists
2524 * to translate Windows sockets error codes from WSAGetLastError(). Such codes
2525 * used to be assigned to errno/$! in earlier versions of perl; this function is
2526 * used to catch any old Perl code which is still trying to assign such values
2527 * to $! and convert them to errno values instead.
2530 win32_get_errno(int err)
2532 return convert_wsa_error_to_errno(err);
2536 * redirected io subsystem for all XS modules
2549 return (&(_environ));
2552 /* the rest are the remapped stdio routines */
2572 win32_ferror(FILE *fp)
2574 return (ferror(fp));
2579 win32_feof(FILE *fp)
2584 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2585 extern int convert_errno_to_wsa_error(int err); /* in win32sck.c */
2589 * Since the errors returned by the socket error function
2590 * WSAGetLastError() are not known by the library routine strerror
2591 * we have to roll our own to cover the case of socket errors
2592 * that could not be converted to regular errno values by
2593 * get_last_socket_error() in win32/win32sck.c.
2597 win32_strerror(int e)
2599 #if !defined __MINGW32__ /* compiler intolerance */
2600 extern int sys_nerr;
2603 if (e < 0 || e > sys_nerr) {
2607 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2608 /* VC10+ and some MinGW/gcc-4.8+ define a "POSIX supplement" of errno
2609 * values ranging from EADDRINUSE (100) to EWOULDBLOCK (140), but
2610 * sys_nerr is still 43 and strerror() returns "Unknown error" for them.
2611 * We must therefore still roll our own messages for these codes, and
2612 * additionally map them to corresponding Windows (sockets) error codes
2613 * first to avoid getting the wrong system message.
2615 else if (e >= EADDRINUSE && e <= EWOULDBLOCK) {
2616 e = convert_errno_to_wsa_error(e);
2620 aTHXa(PERL_GET_THX);
2621 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
2622 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0,
2623 w32_strerror_buffer, sizeof(w32_strerror_buffer),
2626 strcpy(w32_strerror_buffer, "Unknown Error");
2628 return w32_strerror_buffer;
2632 #define strerror win32_strerror
2636 win32_str_os_error(void *sv, DWORD dwErr)
2640 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2641 |FORMAT_MESSAGE_IGNORE_INSERTS
2642 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2643 dwErr, 0, (char *)&sMsg, 1, NULL);
2644 /* strip trailing whitespace and period */
2647 --dwLen; /* dwLen doesn't include trailing null */
2648 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2649 if ('.' != sMsg[dwLen])
2654 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2656 dwLen = sprintf(sMsg,
2657 "Unknown error #0x%lX (lookup 0x%lX)",
2658 dwErr, GetLastError());
2662 sv_setpvn((SV*)sv, sMsg, dwLen);
2668 win32_fprintf(FILE *fp, const char *format, ...)
2671 va_start(marker, format); /* Initialize variable arguments. */
2673 return (vfprintf(fp, format, marker));
2677 win32_printf(const char *format, ...)
2680 va_start(marker, format); /* Initialize variable arguments. */
2682 return (vprintf(format, marker));
2686 win32_vfprintf(FILE *fp, const char *format, va_list args)
2688 return (vfprintf(fp, format, args));
2692 win32_vprintf(const char *format, va_list args)
2694 return (vprintf(format, args));
2698 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2700 return fread(buf, size, count, fp);
2704 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2706 return fwrite(buf, size, count, fp);
2709 #define MODE_SIZE 10
2712 win32_fopen(const char *filename, const char *mode)
2720 if (stricmp(filename, "/dev/null")==0)
2723 aTHXa(PERL_GET_THX);
2724 f = fopen(PerlDir_mapA(filename), mode);
2725 /* avoid buffering headaches for child processes */
2726 if (f && *mode == 'a')
2727 win32_fseek(f, 0, SEEK_END);
2732 win32_fdopen(int handle, const char *mode)
2735 f = fdopen(handle, (char *) mode);
2736 /* avoid buffering headaches for child processes */
2737 if (f && *mode == 'a')
2738 win32_fseek(f, 0, SEEK_END);
2743 win32_freopen(const char *path, const char *mode, FILE *stream)
2746 if (stricmp(path, "/dev/null")==0)
2749 aTHXa(PERL_GET_THX);
2750 return freopen(PerlDir_mapA(path), mode, stream);
2754 win32_fclose(FILE *pf)
2756 #ifdef WIN32_NO_SOCKETS
2759 return my_fclose(pf); /* defined in win32sck.c */
2764 win32_fputs(const char *s,FILE *pf)
2766 return fputs(s, pf);
2770 win32_fputc(int c,FILE *pf)
2776 win32_ungetc(int c,FILE *pf)
2778 return ungetc(c,pf);
2782 win32_getc(FILE *pf)
2788 win32_fileno(FILE *pf)
2794 win32_clearerr(FILE *pf)
2801 win32_fflush(FILE *pf)
2807 win32_ftell(FILE *pf)
2809 #if defined(WIN64) || defined(USE_LARGE_FILES)
2811 if (fgetpos(pf, &pos))
2820 win32_fseek(FILE *pf, Off_t offset,int origin)
2822 #if defined(WIN64) || defined(USE_LARGE_FILES)
2826 if (fgetpos(pf, &pos))
2831 fseek(pf, 0, SEEK_END);
2832 pos = _telli64(fileno(pf));
2841 return fsetpos(pf, &offset);
2843 return fseek(pf, (long)offset, origin);
2848 win32_fgetpos(FILE *pf,fpos_t *p)
2850 return fgetpos(pf, p);
2854 win32_fsetpos(FILE *pf,const fpos_t *p)
2856 return fsetpos(pf, p);
2860 win32_rewind(FILE *pf)
2869 char prefix[MAX_PATH+1];
2870 char filename[MAX_PATH+1];
2871 DWORD len = GetTempPath(MAX_PATH, prefix);
2872 if (len && len < MAX_PATH) {
2873 if (GetTempFileName(prefix, "plx", 0, filename)) {
2874 HANDLE fh = CreateFile(filename,
2875 DELETE | GENERIC_READ | GENERIC_WRITE,
2879 FILE_ATTRIBUTE_NORMAL
2880 | FILE_FLAG_DELETE_ON_CLOSE,
2882 if (fh != INVALID_HANDLE_VALUE) {
2883 int fd = win32_open_osfhandle((intptr_t)fh, 0);
2886 DEBUG_p(PerlIO_printf(Perl_debug_log,
2887 "Created tmpfile=%s\n",filename));
2899 int fd = win32_tmpfd();
2901 return win32_fdopen(fd, "w+b");
2913 win32_fstat(int fd, Stat_t *sbufptr)
2915 #if defined(WIN64) || defined(USE_LARGE_FILES)
2916 return _fstati64(fd, sbufptr);
2918 return fstat(fd, sbufptr);
2923 win32_pipe(int *pfd, unsigned int size, int mode)
2925 return _pipe(pfd, size, mode);
2929 win32_popenlist(const char *mode, IV narg, SV **args)
2933 return do_popen(mode, NULL, narg, args);
2937 do_popen(const char *mode, const char *command, IV narg, SV **args) {
2946 const char **args_pvs = NULL;
2948 /* establish which ends read and write */
2949 if (strchr(mode,'w')) {
2950 stdfd = 0; /* stdin */
2953 nhandle = STD_INPUT_HANDLE;
2955 else if (strchr(mode,'r')) {
2956 stdfd = 1; /* stdout */
2959 nhandle = STD_OUTPUT_HANDLE;
2964 /* set the correct mode */
2965 if (strchr(mode,'b'))
2967 else if (strchr(mode,'t'))
2970 ourmode = _fmode & (O_TEXT | O_BINARY);
2972 /* the child doesn't inherit handles */
2973 ourmode |= O_NOINHERIT;
2975 if (win32_pipe(p, 512, ourmode) == -1)
2978 /* Previously this code redirected stdin/out temporarily so the
2979 child process inherited those handles, this caused race
2980 conditions when another thread was writing/reading those
2983 To avoid that we just feed the handles to CreateProcess() so
2984 the handles are redirected only in the child.
2986 handles[child] = p[child];
2987 handles[parent] = -1;
2990 /* CreateProcess() requires inheritable handles */
2991 if (!SetHandleInformation((HANDLE)_get_osfhandle(p[child]), HANDLE_FLAG_INHERIT,
2992 HANDLE_FLAG_INHERIT)) {
2996 /* start the child */
3001 if ((childpid = do_spawn2_handles(aTHX_ command, EXECF_SPAWN_NOWAIT, handles)) == -1)
3007 const char *exe_name;
3009 Newx(args_pvs, narg + 1 + w32_perlshell_items, const char *);
3010 SAVEFREEPV(args_pvs);
3011 for (i = 0; i < narg; ++i)
3012 args_pvs[i] = SvPV_nolen(args[i]);
3014 exe_name = qualified_path(args_pvs[0], TRUE);
3016 /* let CreateProcess() try to find it instead */
3017 exe_name = args_pvs[0];
3019 if ((childpid = do_spawnvp_handles(P_NOWAIT, exe_name, args_pvs, handles)) == -1) {
3024 win32_close(p[child]);
3026 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3028 /* set process id so that it can be returned by perl's open() */
3029 PL_forkprocess = childpid;
3032 /* we have an fd, return a file stream */
3033 return (PerlIO_fdopen(p[parent], (char *)mode));
3036 /* we don't need to check for errors here */
3044 * a popen() clone that respects PERL5SHELL
3046 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
3050 win32_popen(const char *command, const char *mode)
3052 #ifdef USE_RTL_POPEN
3053 return _popen(command, mode);
3055 return do_popen(mode, command, 0, NULL);
3056 #endif /* USE_RTL_POPEN */
3064 win32_pclose(PerlIO *pf)
3066 #ifdef USE_RTL_POPEN
3070 int childpid, status;
3073 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3076 childpid = SvIVX(sv);
3092 if (win32_waitpid(childpid, &status, 0) == -1)
3097 #endif /* USE_RTL_POPEN */
3101 win32_link(const char *oldname, const char *newname)
3104 WCHAR wOldName[MAX_PATH+1];
3105 WCHAR wNewName[MAX_PATH+1];
3107 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3108 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3109 ((aTHXa(PERL_GET_THX)), wcscpy(wOldName, PerlDir_mapW(wOldName)),
3110 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3114 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for
3115 both permissions errors and if the source is a directory, while
3116 POSIX wants EACCES and EPERM respectively.
3118 Determined by experimentation on Windows 7 x64 SP1, since MS
3119 don't document what error codes are returned.
3121 switch (GetLastError()) {
3122 case ERROR_BAD_NET_NAME:
3123 case ERROR_BAD_NETPATH:
3124 case ERROR_BAD_PATHNAME:
3125 case ERROR_FILE_NOT_FOUND:
3126 case ERROR_FILENAME_EXCED_RANGE:
3127 case ERROR_INVALID_DRIVE:
3128 case ERROR_PATH_NOT_FOUND:
3131 case ERROR_ALREADY_EXISTS:
3134 case ERROR_ACCESS_DENIED:
3137 case ERROR_NOT_SAME_DEVICE:
3140 case ERROR_DISK_FULL:
3143 case ERROR_NOT_ENOUGH_QUOTA:
3147 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */
3155 win32_rename(const char *oname, const char *newname)
3157 char szOldName[MAX_PATH+1];
3159 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3162 if (stricmp(newname, oname))
3163 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3164 strcpy(szOldName, PerlDir_mapA(oname));
3166 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3168 DWORD err = GetLastError();
3170 case ERROR_BAD_NET_NAME:
3171 case ERROR_BAD_NETPATH:
3172 case ERROR_BAD_PATHNAME:
3173 case ERROR_FILE_NOT_FOUND:
3174 case ERROR_FILENAME_EXCED_RANGE:
3175 case ERROR_INVALID_DRIVE:
3176 case ERROR_NO_MORE_FILES:
3177 case ERROR_PATH_NOT_FOUND:
3180 case ERROR_DISK_FULL:
3183 case ERROR_NOT_ENOUGH_QUOTA:
3196 win32_setmode(int fd, int mode)
3198 return setmode(fd, mode);
3202 win32_chsize(int fd, Off_t size)
3204 #if defined(WIN64) || defined(USE_LARGE_FILES)
3206 Off_t cur, end, extend;
3208 cur = win32_tell(fd);
3211 end = win32_lseek(fd, 0, SEEK_END);
3214 extend = size - end;
3218 else if (extend > 0) {
3219 /* must grow the file, padding with nulls */
3221 int oldmode = win32_setmode(fd, O_BINARY);
3223 memset(b, '\0', sizeof(b));
3225 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3226 count = win32_write(fd, b, count);
3227 if ((int)count < 0) {
3231 } while ((extend -= count) > 0);
3232 win32_setmode(fd, oldmode);
3235 /* shrink the file */
3236 win32_lseek(fd, size, SEEK_SET);
3237 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3242 win32_lseek(fd, cur, SEEK_SET);
3245 return chsize(fd, (long)size);
3250 win32_lseek(int fd, Off_t offset, int origin)
3252 #if defined(WIN64) || defined(USE_LARGE_FILES)
3253 return _lseeki64(fd, offset, origin);
3255 return lseek(fd, (long)offset, origin);
3262 #if defined(WIN64) || defined(USE_LARGE_FILES)
3263 return _telli64(fd);
3270 win32_open(const char *path, int flag, ...)
3277 pmode = va_arg(ap, int);
3280 if (stricmp(path, "/dev/null")==0)
3283 aTHXa(PERL_GET_THX);
3284 return open(PerlDir_mapA(path), flag, pmode);
3287 /* close() that understands socket */
3288 extern int my_close(int); /* in win32sck.c */
3293 #ifdef WIN32_NO_SOCKETS
3296 return my_close(fd);
3307 win32_isatty(int fd)
3309 /* The Microsoft isatty() function returns true for *all*
3310 * character mode devices, including "nul". Our implementation
3311 * should only return true if the handle has a console buffer.
3314 HANDLE fh = (HANDLE)_get_osfhandle(fd);
3315 if (fh == (HANDLE)-1) {
3316 /* errno is already set to EBADF */
3320 if (GetConsoleMode(fh, &mode))
3334 win32_dup2(int fd1,int fd2)
3336 return dup2(fd1,fd2);
3340 win32_read(int fd, void *buf, unsigned int cnt)
3342 return read(fd, buf, cnt);
3346 win32_write(int fd, const void *buf, unsigned int cnt)
3348 return write(fd, buf, cnt);
3352 win32_mkdir(const char *dir, int mode)
3355 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3359 win32_rmdir(const char *dir)
3362 return rmdir(PerlDir_mapA(dir));
3366 win32_chdir(const char *dir)
3368 if (!dir || !*dir) {
3376 win32_access(const char *path, int mode)
3379 return access(PerlDir_mapA(path), mode);
3383 win32_chmod(const char *path, int mode)
3386 return chmod(PerlDir_mapA(path), mode);
3391 create_command_line(char *cname, STRLEN clen, const char * const *args)
3398 bool bat_file = FALSE;
3399 bool cmd_shell = FALSE;
3400 bool dumb_shell = FALSE;
3401 bool extra_quotes = FALSE;
3402 bool quote_next = FALSE;
3405 cname = (char*)args[0];
3407 /* The NT cmd.exe shell has the following peculiarity that needs to be
3408 * worked around. It strips a leading and trailing dquote when any
3409 * of the following is true:
3410 * 1. the /S switch was used
3411 * 2. there are more than two dquotes
3412 * 3. there is a special character from this set: &<>()@^|
3413 * 4. no whitespace characters within the two dquotes
3414 * 5. string between two dquotes isn't an executable file
3415 * To work around this, we always add a leading and trailing dquote
3416 * to the string, if the first argument is either "cmd.exe" or "cmd",
3417 * and there were at least two or more arguments passed to cmd.exe
3418 * (not including switches).
3419 * XXX the above rules (from "cmd /?") don't seem to be applied
3420 * always, making for the convolutions below :-(
3424 clen = strlen(cname);
3427 && (stricmp(&cname[clen-4], ".bat") == 0
3428 || (stricmp(&cname[clen-4], ".cmd") == 0)))
3434 char *exe = strrchr(cname, '/');
3435 char *exe2 = strrchr(cname, '\\');
3442 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3446 else if (stricmp(exe, "command.com") == 0
3447 || stricmp(exe, "command") == 0)
3454 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3455 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3456 STRLEN curlen = strlen(arg);
3457 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3458 len += 2; /* assume quoting needed (worst case) */
3460 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3462 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3465 Newx(cmd, len, char);
3470 extra_quotes = TRUE;
3473 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3475 STRLEN curlen = strlen(arg);
3477 /* we want to protect empty arguments and ones with spaces with
3478 * dquotes, but only if they aren't already there */
3483 else if (quote_next) {
3484 /* see if it really is multiple arguments pretending to
3485 * be one and force a set of quotes around it */
3486 if (*find_next_space(arg))
3489 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3491 while (i < curlen) {
3492 if (isSPACE(arg[i])) {
3495 else if (arg[i] == '"') {
3519 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3520 && stricmp(arg+curlen-2, "/c") == 0)
3522 /* is there a next argument? */
3523 if (args[index+1]) {
3524 /* are there two or more next arguments? */
3525 if (args[index+2]) {
3527 extra_quotes = TRUE;
3530 /* single argument, force quoting if it has spaces */
3545 static const char *exe_extensions[] =
3547 ".exe", /* this must be first */
3553 qualified_path(const char *cmd, bool other_exts)
3556 char *fullcmd, *curfullcmd;
3562 fullcmd = (char*)cmd;
3564 if (*fullcmd == '/' || *fullcmd == '\\')
3573 pathstr = PerlEnv_getenv("PATH");
3575 /* worst case: PATH is a single directory; we need additional space
3576 * to append "/", ".exe" and trailing "\0" */
3577 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3578 curfullcmd = fullcmd;
3583 /* start by appending the name to the current prefix */
3584 strcpy(curfullcmd, cmd);
3585 curfullcmd += cmdlen;
3587 /* if it doesn't end with '.', or has no extension, try adding
3588 * a trailing .exe first */
3589 if (cmd[cmdlen-1] != '.'
3590 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3593 /* first extension is .exe */
3594 int ext_limit = other_exts ? C_ARRAY_LENGTH(exe_extensions) : 1;
3595 for (i = 0; i < ext_limit; ++i) {
3596 strcpy(curfullcmd, exe_extensions[i]);
3597 res = GetFileAttributes(fullcmd);
3598 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3605 /* that failed, try the bare name */
3606 res = GetFileAttributes(fullcmd);
3607 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3610 /* quit if no other path exists, or if cmd already has path */
3611 if (!pathstr || !*pathstr || has_slash)
3614 /* skip leading semis */
3615 while (*pathstr == ';')
3618 /* build a new prefix from scratch */
3619 curfullcmd = fullcmd;
3620 while (*pathstr && *pathstr != ';') {
3621 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3622 pathstr++; /* skip initial '"' */
3623 while (*pathstr && *pathstr != '"') {
3624 *curfullcmd++ = *pathstr++;
3627 pathstr++; /* skip trailing '"' */
3630 *curfullcmd++ = *pathstr++;
3634 pathstr++; /* skip trailing semi */
3635 if (curfullcmd > fullcmd /* append a dir separator */
3636 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3638 *curfullcmd++ = '\\';
3646 /* The following are just place holders.
3647 * Some hosts may provide and environment that the OS is
3648 * not tracking, therefore, these host must provide that
3649 * environment and the current directory to CreateProcess
3653 win32_get_childenv(void)
3659 win32_free_childenv(void* d)
3664 win32_clearenv(void)
3666 char *envv = GetEnvironmentStrings();
3670 char *end = strchr(cur,'=');
3671 if (end && end != cur) {
3673 SetEnvironmentVariable(cur, NULL);
3675 cur = end + strlen(end+1)+2;
3677 else if ((len = strlen(cur)))
3680 FreeEnvironmentStrings(envv);
3684 win32_get_childdir(void)
3687 char szfilename[MAX_PATH+1];
3689 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
3690 Newx(ptr, strlen(szfilename)+1, char);
3691 strcpy(ptr, szfilename);
3696 win32_free_childdir(char* d)
3702 /* XXX this needs to be made more compatible with the spawnvp()
3703 * provided by the various RTLs. In particular, searching for
3704 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
3705 * This doesn't significantly affect perl itself, because we
3706 * always invoke things using PERL5SHELL if a direct attempt to
3707 * spawn the executable fails.
3709 * XXX splitting and rejoining the commandline between do_aspawn()
3710 * and win32_spawnvp() could also be avoided.
3714 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
3716 #ifdef USE_RTL_SPAWNVP
3717 return _spawnvp(mode, cmdname, (char * const *)argv);
3719 return do_spawnvp_handles(mode, cmdname, argv, NULL);
3724 do_spawnvp_handles(int mode, const char *cmdname, const char *const *argv,
3725 const int *handles) {
3731 STARTUPINFO StartupInfo;
3732 PROCESS_INFORMATION ProcessInformation;
3735 char *fullcmd = NULL;
3736 char *cname = (char *)cmdname;
3740 clen = strlen(cname);
3741 /* if command name contains dquotes, must remove them */
3742 if (strchr(cname, '"')) {
3744 Newx(cname,clen+1,char);
3757 cmd = create_command_line(cname, clen, argv);
3759 aTHXa(PERL_GET_THX);
3760 env = PerlEnv_get_childenv();
3761 dir = PerlEnv_get_childdir();
3764 case P_NOWAIT: /* asynch + remember result */
3765 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
3770 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
3773 create |= CREATE_NEW_PROCESS_GROUP;
3776 case P_WAIT: /* synchronous execution */
3778 default: /* invalid mode */
3784 memset(&StartupInfo,0,sizeof(StartupInfo));
3785 StartupInfo.cb = sizeof(StartupInfo);
3786 memset(&tbl,0,sizeof(tbl));
3787 PerlEnv_get_child_IO(&tbl);
3788 StartupInfo.dwFlags = tbl.dwFlags;
3789 StartupInfo.dwX = tbl.dwX;
3790 StartupInfo.dwY = tbl.dwY;
3791 StartupInfo.dwXSize = tbl.dwXSize;
3792 StartupInfo.dwYSize = tbl.dwYSize;
3793 StartupInfo.dwXCountChars = tbl.dwXCountChars;
3794 StartupInfo.dwYCountChars = tbl.dwYCountChars;
3795 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
3796 StartupInfo.wShowWindow = tbl.wShowWindow;
3797 StartupInfo.hStdInput = handles && handles[0] != -1 ?
3798 (HANDLE)_get_osfhandle(handles[0]) : tbl.childStdIn;
3799 StartupInfo.hStdOutput = handles && handles[1] != -1 ?
3800 (HANDLE)_get_osfhandle(handles[1]) : tbl.childStdOut;
3801 StartupInfo.hStdError = handles && handles[2] != -1 ?
3802 (HANDLE)_get_osfhandle(handles[2]) : tbl.childStdErr;
3803 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
3804 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
3805 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
3807 create |= CREATE_NEW_CONSOLE;
3810 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3812 if (w32_use_showwindow) {
3813 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
3814 StartupInfo.wShowWindow = w32_showwindow;
3817 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
3820 if (!CreateProcess(cname, /* search PATH to find executable */
3821 cmd, /* executable, and its arguments */
3822 NULL, /* process attributes */
3823 NULL, /* thread attributes */
3824 TRUE, /* inherit handles */
3825 create, /* creation flags */
3826 (LPVOID)env, /* inherit environment */
3827 dir, /* inherit cwd */
3829 &ProcessInformation))
3831 /* initial NULL argument to CreateProcess() does a PATH
3832 * search, but it always first looks in the directory
3833 * where the current process was started, which behavior
3834 * is undesirable for backward compatibility. So we
3835 * jump through our own hoops by picking out the path
3836 * we really want it to use. */
3838 fullcmd = qualified_path(cname, FALSE);
3840 if (cname != cmdname)
3843 DEBUG_p(PerlIO_printf(Perl_debug_log,
3844 "Retrying [%s] with same args\n",
3854 if (mode == P_NOWAIT) {
3855 /* asynchronous spawn -- store handle, return PID */
3856 ret = (int)ProcessInformation.dwProcessId;
3858 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
3859 w32_child_pids[w32_num_children] = (DWORD)ret;
3864 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
3865 /* FIXME: if msgwait returned due to message perhaps forward the
3866 "signal" to the process
3868 GetExitCodeProcess(ProcessInformation.hProcess, &status);
3870 CloseHandle(ProcessInformation.hProcess);
3873 CloseHandle(ProcessInformation.hThread);
3876 PerlEnv_free_childenv(env);
3877 PerlEnv_free_childdir(dir);
3879 if (cname != cmdname)
3885 win32_execv(const char *cmdname, const char *const *argv)
3889 /* if this is a pseudo-forked child, we just want to spawn
3890 * the new program, and return */
3892 return _spawnv(P_WAIT, cmdname, argv);
3894 return _execv(cmdname, argv);
3898 win32_execvp(const char *cmdname, const char *const *argv)
3902 /* if this is a pseudo-forked child, we just want to spawn
3903 * the new program, and return */
3904 if (w32_pseudo_id) {
3905 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
3914 return _execvp(cmdname, argv);
3918 win32_perror(const char *str)
3924 win32_setbuf(FILE *pf, char *buf)
3930 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
3932 return setvbuf(pf, buf, type, size);
3936 win32_flushall(void)
3942 win32_fcloseall(void)
3948 win32_fgets(char *s, int n, FILE *pf)
3950 return fgets(s, n, pf);
3960 win32_fgetc(FILE *pf)
3966 win32_putc(int c, FILE *pf)
3972 win32_puts(const char *s)
3984 win32_putchar(int c)
3991 #ifndef USE_PERL_SBRK
3993 static char *committed = NULL; /* XXX threadead */
3994 static char *base = NULL; /* XXX threadead */
3995 static char *reserved = NULL; /* XXX threadead */
3996 static char *brk = NULL; /* XXX threadead */
3997 static DWORD pagesize = 0; /* XXX threadead */
4000 sbrk(ptrdiff_t need)
4005 GetSystemInfo(&info);
4006 /* Pretend page size is larger so we don't perpetually
4007 * call the OS to commit just one page ...
4009 pagesize = info.dwPageSize << 3;
4011 if (brk+need >= reserved)
4013 DWORD size = brk+need-reserved;
4015 char *prev_committed = NULL;
4016 if (committed && reserved && committed < reserved)
4018 /* Commit last of previous chunk cannot span allocations */
4019 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
4022 /* Remember where we committed from in case we want to decommit later */
4023 prev_committed = committed;
4024 committed = reserved;
4027 /* Reserve some (more) space
4028 * Contiguous blocks give us greater efficiency, so reserve big blocks -
4029 * this is only address space not memory...
4030 * Note this is a little sneaky, 1st call passes NULL as reserved
4031 * so lets system choose where we start, subsequent calls pass
4032 * the old end address so ask for a contiguous block
4035 if (size < 64*1024*1024)
4036 size = 64*1024*1024;
4037 size = ((size + pagesize - 1) / pagesize) * pagesize;
4038 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
4041 reserved = addr+size;
4051 /* The existing block could not be extended far enough, so decommit
4052 * anything that was just committed above and start anew */
4055 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
4058 reserved = base = committed = brk = NULL;
4069 if (brk > committed)
4071 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4073 if (committed+size > reserved)
4074 size = reserved-committed;
4075 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4088 win32_malloc(size_t size)
4090 return malloc(size);
4094 win32_calloc(size_t numitems, size_t size)
4096 return calloc(numitems,size);
4100 win32_realloc(void *block, size_t size)
4102 return realloc(block,size);
4106 win32_free(void *block)
4113 win32_open_osfhandle(intptr_t handle, int flags)
4115 return _open_osfhandle(handle, flags);
4119 win32_get_osfhandle(int fd)
4121 return (intptr_t)_get_osfhandle(fd);
4125 win32_fdupopen(FILE *pf)
4130 int fileno = win32_dup(win32_fileno(pf));
4132 /* open the file in the same mode */
4133 if((pf)->_flag & _IOREAD) {
4137 else if((pf)->_flag & _IOWRT) {
4141 else if((pf)->_flag & _IORW) {
4147 /* it appears that the binmode is attached to the
4148 * file descriptor so binmode files will be handled
4151 pfdup = win32_fdopen(fileno, mode);
4153 /* move the file pointer to the same position */
4154 if (!fgetpos(pf, &pos)) {
4155 fsetpos(pfdup, &pos);
4161 win32_dynaload(const char* filename)
4164 char buf[MAX_PATH+1];
4167 /* LoadLibrary() doesn't recognize forward slashes correctly,
4168 * so turn 'em back. */
4169 first = strchr(filename, '/');
4171 STRLEN len = strlen(filename);
4172 if (len <= MAX_PATH) {
4173 strcpy(buf, filename);
4174 filename = &buf[first - filename];
4176 if (*filename == '/')
4177 *(char*)filename = '\\';
4183 aTHXa(PERL_GET_THX);
4184 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4187 XS(w32_SetChildShowWindow)
4190 BOOL use_showwindow = w32_use_showwindow;
4191 /* use "unsigned short" because Perl has redefined "WORD" */
4192 unsigned short showwindow = w32_showwindow;
4195 croak_xs_usage(cv, "[showwindow]");
4197 if (items == 0 || !SvOK(ST(0)))
4198 w32_use_showwindow = FALSE;
4200 w32_use_showwindow = TRUE;
4201 w32_showwindow = (unsigned short)SvIV(ST(0));
4206 ST(0) = sv_2mortal(newSViv(showwindow));
4208 ST(0) = &PL_sv_undef;
4213 Perl_init_os_extras(void)
4216 char *file = __FILE__;
4218 /* Initialize Win32CORE if it has been statically linked. */
4219 #ifndef PERL_IS_MINIPERL
4220 void (*pfn_init)(pTHX);
4221 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
4222 ? GetModuleHandle(NULL)
4223 : w32_perldll_handle);
4224 pfn_init = (void (*)(pTHX))GetProcAddress(module, "init_Win32CORE");
4225 aTHXa(PERL_GET_THX);
4229 aTHXa(PERL_GET_THX);
4232 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4236 win32_signal_context(void)
4241 my_perl = PL_curinterp;
4242 PERL_SET_THX(my_perl);
4246 return PL_curinterp;
4252 win32_ctrlhandler(DWORD dwCtrlType)
4255 dTHXa(PERL_GET_SIG_CONTEXT);
4261 switch(dwCtrlType) {
4262 case CTRL_CLOSE_EVENT:
4263 /* A signal that the system sends to all processes attached to a console when
4264 the user closes the console (either by choosing the Close command from the
4265 console window's System menu, or by choosing the End Task command from the
4268 if (do_raise(aTHX_ 1)) /* SIGHUP */
4269 sig_terminate(aTHX_ 1);
4273 /* A CTRL+c signal was received */
4274 if (do_raise(aTHX_ SIGINT))
4275 sig_terminate(aTHX_ SIGINT);
4278 case CTRL_BREAK_EVENT:
4279 /* A CTRL+BREAK signal was received */
4280 if (do_raise(aTHX_ SIGBREAK))
4281 sig_terminate(aTHX_ SIGBREAK);
4284 case CTRL_LOGOFF_EVENT:
4285 /* A signal that the system sends to all console processes when a user is logging
4286 off. This signal does not indicate which user is logging off, so no
4287 assumptions can be made.
4290 case CTRL_SHUTDOWN_EVENT:
4291 /* A signal that the system sends to all console processes when the system is
4294 if (do_raise(aTHX_ SIGTERM))
4295 sig_terminate(aTHX_ SIGTERM);
4304 #ifdef SET_INVALID_PARAMETER_HANDLER
4305 # include <crtdbg.h>
4316 /* fetch Unicode version of PATH */
4318 wide_path = (WCHAR*)win32_malloc(len*sizeof(WCHAR));
4320 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4322 win32_free(wide_path);
4328 wide_path = (WCHAR*)win32_realloc(wide_path, len*sizeof(WCHAR));
4333 /* convert to ANSI pathnames */
4334 wide_dir = wide_path;
4337 WCHAR *sep = wcschr(wide_dir, ';');
4345 /* remove quotes around pathname */
4346 if (*wide_dir == '"')
4348 wide_len = wcslen(wide_dir);
4349 if (wide_len && wide_dir[wide_len-1] == '"')
4350 wide_dir[wide_len-1] = '\0';
4352 /* append ansi_dir to ansi_path */
4353 ansi_dir = win32_ansipath(wide_dir);
4354 ansi_len = strlen(ansi_dir);
4356 size_t newlen = len + 1 + ansi_len;
4357 ansi_path = (char*)win32_realloc(ansi_path, newlen+1);
4360 ansi_path[len] = ';';
4361 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4366 ansi_path = (char*)win32_malloc(5+len+1);
4369 memcpy(ansi_path, "PATH=", 5);
4370 memcpy(ansi_path+5, ansi_dir, len+1);
4373 win32_free(ansi_dir);
4378 /* Update C RTL environ array. This will only have full effect if
4379 * perl_parse() is later called with `environ` as the `env` argument.
4380 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4382 * We do have to ansify() the PATH before Perl has been fully
4383 * initialized because S_find_script() uses the PATH when perl
4384 * is being invoked with the -S option. This happens before %ENV
4385 * is initialized in S_init_postdump_symbols().
4387 * XXX Is this a bug? Should S_find_script() use the environment
4388 * XXX passed in the `env` arg to parse_perl()?
4391 /* Keep system environment in sync because S_init_postdump_symbols()
4392 * will not call mg_set() if it initializes %ENV from `environ`.
4394 SetEnvironmentVariableA("PATH", ansi_path+5);
4395 win32_free(ansi_path);
4397 win32_free(wide_path);
4401 Perl_win32_init(int *argcp, char ***argvp)
4403 #ifdef SET_INVALID_PARAMETER_HANDLER
4404 _invalid_parameter_handler oldHandler, newHandler;
4405 newHandler = my_invalid_parameter_handler;
4406 oldHandler = _set_invalid_parameter_handler(newHandler);
4407 _CrtSetReportMode(_CRT_ASSERT, 0);
4409 /* Disable floating point errors, Perl will trap the ones we
4410 * care about. VC++ RTL defaults to switching these off
4411 * already, but some RTLs don't. Since we don't
4412 * want to be at the vendor's whim on the default, we set
4413 * it explicitly here.
4415 #if !defined(__GNUC__)
4416 _control87(MCW_EM, MCW_EM);
4420 /* When the manifest resource requests Common-Controls v6 then
4421 * user32.dll no longer registers all the Windows classes used for
4422 * standard controls but leaves some of them to be registered by
4423 * comctl32.dll. InitCommonControls() doesn't do anything but calling
4424 * it makes sure comctl32.dll gets loaded into the process and registers
4425 * the standard control classes. Without this even normal Windows APIs
4426 * like MessageBox() can fail under some versions of Windows XP.
4428 InitCommonControls();
4430 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4431 GetVersionEx(&g_osver);
4433 #ifdef WIN32_DYN_IOINFO_SIZE
4435 Size_t ioinfo_size = _msize((void*)__pioinfo[0]);;
4436 if((SSize_t)ioinfo_size <= 0) { /* -1 is err */
4437 fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */
4440 ioinfo_size /= IOINFO_ARRAY_ELTS;
4441 w32_ioinfo_size = ioinfo_size;
4449 Perl_win32_term(void)
4458 win32_get_child_IO(child_IO_table* ptbl)
4460 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4461 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4462 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4466 win32_signal(int sig, Sighandler_t subcode)
4469 if (sig < SIG_SIZE) {
4470 int save_errno = errno;
4471 Sighandler_t result;
4472 #ifdef SET_INVALID_PARAMETER_HANDLER
4473 /* Silence our invalid parameter handler since we expect to make some
4474 * calls with invalid signal numbers giving a SIG_ERR result. */
4475 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE);
4477 result = signal(sig, subcode);
4478 #ifdef SET_INVALID_PARAMETER_HANDLER
4479 set_silent_invalid_parameter_handler(oldvalue);
4481 aTHXa(PERL_GET_THX);
4482 if (result == SIG_ERR) {
4483 result = w32_sighandler[sig];
4486 w32_sighandler[sig] = subcode;
4495 /* The PerlMessageWindowClass's WindowProc */
4497 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4499 return win32_process_message(hwnd, msg, wParam, lParam) ?
4500 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4503 /* The real message handler. Can be called with
4504 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4505 * that it processes */
4507 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4509 /* BEWARE. The context retrieved using dTHX; is the context of the
4510 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4511 * up to and including WM_CREATE. If it ever happens that you need the
4512 * 'child' context before this, then it needs to be passed into
4513 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4514 * from the lparam of CreateWindow(). It could then be stored/retrieved
4515 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4516 * the dTHX calls here. */
4517 /* XXX For now it is assumed that the overhead of the dTHX; for what
4518 * are relativley infrequent code-paths, is better than the added
4519 * complexity of getting the correct context passed into
4520 * win32_create_message_window() */
4526 case WM_USER_MESSAGE: {
4527 long child = find_pseudo_pid(aTHX_ (int)wParam);
4529 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4536 case WM_USER_KILL: {
4537 /* We use WM_USER_KILL to fake kill() with other signals */
4538 int sig = (int)wParam;
4539 if (do_raise(aTHX_ sig))
4540 sig_terminate(aTHX_ sig);
4546 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4547 if (w32_timerid && w32_timerid==(UINT)wParam) {
4548 KillTimer(w32_message_hwnd, w32_timerid);
4551 /* Now fake a call to signal handler */
4552 if (do_raise(aTHX_ 14))
4553 sig_terminate(aTHX_ 14);
4565 /* Above or other stuff may have set a signal flag, and we may not have
4566 * been called from win32_async_check() (e.g. some other GUI's message
4567 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4568 * handler that die's, and the message loop that calls here is wrapped
4569 * in an eval, then you may well end up with orphaned windows - signals
4570 * are dispatched by win32_async_check() */
4576 win32_create_message_window_class(void)
4578 /* create the window class for "message only" windows */
4582 wc.lpfnWndProc = win32_message_window_proc;
4583 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4584 wc.lpszClassName = "PerlMessageWindowClass";
4586 /* second and subsequent calls will fail, but class
4587 * will already be registered */
4592 win32_create_message_window(void)
4594 win32_create_message_window_class();
4595 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4596 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4599 #ifdef HAVE_INTERP_INTERN
4602 win32_csighandler(int sig)
4605 dTHXa(PERL_GET_SIG_CONTEXT);
4606 Perl_warn(aTHX_ "Got signal %d",sig);
4611 #if defined(__MINGW32__) && defined(__cplusplus)
4612 #define CAST_HWND__(x) (HWND__*)(x)
4614 #define CAST_HWND__(x) x
4618 Perl_sys_intern_init(pTHX)
4622 w32_perlshell_tokens = NULL;
4623 w32_perlshell_vec = (char**)NULL;
4624 w32_perlshell_items = 0;
4625 w32_fdpid = newAV();
4626 Newx(w32_children, 1, child_tab);
4627 w32_num_children = 0;
4628 # ifdef USE_ITHREADS
4630 Newx(w32_pseudo_children, 1, pseudo_child_tab);
4631 w32_num_pseudo_children = 0;
4634 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4636 for (i=0; i < SIG_SIZE; i++) {
4637 w32_sighandler[i] = SIG_DFL;
4639 # ifdef MULTIPLICITY
4640 if (my_perl == PL_curinterp) {
4644 /* Force C runtime signal stuff to set its console handler */
4645 signal(SIGINT,win32_csighandler);
4646 signal(SIGBREAK,win32_csighandler);
4648 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
4649 * flag. This has the side-effect of disabling Ctrl-C events in all
4650 * processes in this group.
4651 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
4652 * with a NULL handler.
4654 SetConsoleCtrlHandler(NULL,FALSE);
4656 /* Push our handler on top */
4657 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
4662 Perl_sys_intern_clear(pTHX)
4664 Safefree(w32_perlshell_tokens);
4665 Safefree(w32_perlshell_vec);
4666 /* NOTE: w32_fdpid is freed by sv_clean_all() */
4667 Safefree(w32_children);
4669 KillTimer(w32_message_hwnd, w32_timerid);
4672 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
4673 DestroyWindow(w32_message_hwnd);
4674 # ifdef MULTIPLICITY
4675 if (my_perl == PL_curinterp) {
4679 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
4681 # ifdef USE_ITHREADS
4682 Safefree(w32_pseudo_children);
4686 # ifdef USE_ITHREADS
4689 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
4691 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
4693 dst->perlshell_tokens = NULL;
4694 dst->perlshell_vec = (char**)NULL;
4695 dst->perlshell_items = 0;
4696 dst->fdpid = newAV();
4697 Newxz(dst->children, 1, child_tab);
4699 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
4701 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4702 dst->poll_count = 0;
4703 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
4705 # endif /* USE_ITHREADS */
4706 #endif /* HAVE_INTERP_INTERN */