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" */
45 #if !defined(PERLIO_IS_STDIO)
54 #define PERL_NO_GET_CONTEXT
59 /* assert.h conflicts with #define of assert in perl.h */
67 #include <sys/utime.h>
70 /* Mingw32 defaults to globing command line
71 * So we turn it off like this:
76 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)
77 /* Mingw32-1.1 is missing some prototypes */
79 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
80 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
81 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
89 #define EXECF_SPAWN_NOWAIT 3
91 #if defined(PERL_IMPLICIT_SYS)
92 # undef win32_get_privlib
93 # define win32_get_privlib g_win32_get_privlib
94 # undef win32_get_sitelib
95 # define win32_get_sitelib g_win32_get_sitelib
96 # undef win32_get_vendorlib
97 # define win32_get_vendorlib g_win32_get_vendorlib
99 # define getlogin g_getlogin
102 /* VS2005 (MSC version 14) provides a mechanism to set an invalid
103 * parameter handler. This functionality is not available in the
104 * 64-bit compiler from the Platform SDK, which unfortunately also
105 * believes itself to be MSC version 14.
107 * There is no #define related to _set_invalid_parameter_handler(),
108 * but we can check for one of the constants defined for
109 * _set_abort_behavior(), which was introduced into stdlib.h at
113 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG)
114 # define SET_INVALID_PARAMETER_HANDLER
117 #ifdef SET_INVALID_PARAMETER_HANDLER
118 static BOOL set_silent_invalid_parameter_handler(BOOL newvalue);
119 static void my_invalid_parameter_handler(const wchar_t* expression,
120 const wchar_t* function, const wchar_t* file,
121 unsigned int line, uintptr_t pReserved);
124 static char* get_regstr_from(HKEY hkey, const char *valuename, SV **svp);
125 static char* get_regstr(const char *valuename, SV **svp);
126 static char* get_emd_part(SV **prev_pathp, STRLEN *const len,
127 char *trailing, ...);
128 static char* win32_get_xlib(const char *pl, const char *xlib,
129 const char *libname, STRLEN *const len);
130 static BOOL has_shell_metachars(const char *ptr);
131 static long tokenize(const char *str, char **dest, char ***destv);
132 static void get_shell(void);
133 static char* find_next_space(const char *s);
134 static int do_spawn2(pTHX_ const char *cmd, int exectype);
135 static int do_spawn2_handles(pTHX_ const char *cmd, int exectype,
137 static int do_spawnvp_handles(int mode, const char *cmdname,
138 const char * const *argv, const int *handles);
139 static PerlIO * do_popen(const char *mode, const char *command, IV narg,
141 static long find_pid(pTHX_ int pid);
142 static void remove_dead_process(long child);
143 static int terminate_process(DWORD pid, HANDLE process_handle, int sig);
144 static int my_killpg(int pid, int sig);
145 static int my_kill(int pid, int sig);
146 static void out_of_memory(void);
147 static char* wstr_to_str(const wchar_t* wstr);
148 static long filetime_to_clock(PFILETIME ft);
149 static BOOL filetime_from_time(PFILETIME ft, time_t t);
150 static char* create_command_line(char *cname, STRLEN clen,
151 const char * const *args);
152 static char* qualified_path(const char *cmd);
153 static void ansify_path(void);
154 static LRESULT win32_process_message(HWND hwnd, UINT msg,
155 WPARAM wParam, LPARAM lParam);
158 static long find_pseudo_pid(pTHX_ int pid);
159 static void remove_dead_pseudo_process(long child);
160 static HWND get_hwnd_delay(pTHX, long child, DWORD tries);
163 #ifdef HAVE_INTERP_INTERN
164 static void win32_csighandler(int sig);
168 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
169 char w32_module_name[MAX_PATH+1];
170 #ifdef WIN32_DYN_IOINFO_SIZE
171 Size_t w32_ioinfo_size;/* avoid 0 extend op b4 mul, otherwise could be a U8 */
175 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
177 #ifdef SET_INVALID_PARAMETER_HANDLER
178 static BOOL silent_invalid_parameter_handler = FALSE;
181 set_silent_invalid_parameter_handler(BOOL newvalue)
183 BOOL oldvalue = silent_invalid_parameter_handler;
185 silent_invalid_parameter_handler = newvalue;
191 my_invalid_parameter_handler(const wchar_t* expression,
192 const wchar_t* function,
198 char* ansi_expression;
201 if (silent_invalid_parameter_handler)
203 ansi_expression = wstr_to_str(expression);
204 ansi_function = wstr_to_str(function);
205 ansi_file = wstr_to_str(file);
206 fprintf(stderr, "Invalid parameter detected in function %s. "
207 "File: %s, line: %d\n", ansi_function, ansi_file, line);
208 fprintf(stderr, "Expression: %s\n", ansi_expression);
209 free(ansi_expression);
217 set_w32_module_name(void)
219 /* this function may be called at DLL_PROCESS_ATTACH time */
221 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
222 ? GetModuleHandle(NULL)
223 : w32_perldll_handle);
225 WCHAR modulename[MAX_PATH];
226 WCHAR fullname[MAX_PATH];
229 DWORD (__stdcall *pfnGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD) =
230 (DWORD (__stdcall *)(LPCWSTR, LPWSTR, DWORD))
231 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameW");
233 GetModuleFileNameW(module, modulename, sizeof(modulename)/sizeof(WCHAR));
235 /* Make sure we get an absolute pathname in case the module was loaded
236 * explicitly by LoadLibrary() with a relative path. */
237 GetFullPathNameW(modulename, sizeof(fullname)/sizeof(WCHAR), fullname, NULL);
239 /* Make sure we start with the long path name of the module because we
240 * later scan for pathname components to match "5.xx" to locate
241 * compatible sitelib directories, and the short pathname might mangle
242 * this path segment (e.g. by removing the dot on NTFS to something
243 * like "5xx~1.yy") */
244 if (pfnGetLongPathNameW)
245 pfnGetLongPathNameW(fullname, fullname, sizeof(fullname)/sizeof(WCHAR));
247 /* remove \\?\ prefix */
248 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0)
249 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR));
251 ansi = win32_ansipath(fullname);
252 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name));
255 /* normalize to forward slashes */
256 ptr = w32_module_name;
264 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
266 get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
268 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
271 const char *subkey = "Software\\Perl";
275 retval = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &handle);
276 if (retval == ERROR_SUCCESS) {
278 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen);
279 if (retval == ERROR_SUCCESS
280 && (type == REG_SZ || type == REG_EXPAND_SZ))
284 *svp = sv_2mortal(newSVpvs(""));
285 SvGROW(*svp, datalen);
286 retval = RegQueryValueEx(handle, valuename, 0, NULL,
287 (PBYTE)SvPVX(*svp), &datalen);
288 if (retval == ERROR_SUCCESS) {
290 SvCUR_set(*svp,datalen-1);
298 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
300 get_regstr(const char *valuename, SV **svp)
302 char *str = get_regstr_from(HKEY_CURRENT_USER, valuename, svp);
304 str = get_regstr_from(HKEY_LOCAL_MACHINE, valuename, svp);
308 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
310 get_emd_part(SV **prev_pathp, STRLEN *const len, char *trailing_path, ...)
314 char mod_name[MAX_PATH+1];
320 va_start(ap, trailing_path);
321 strip = va_arg(ap, char *);
323 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
324 baselen = strlen(base);
326 if (!*w32_module_name) {
327 set_w32_module_name();
329 strcpy(mod_name, w32_module_name);
330 ptr = strrchr(mod_name, '/');
331 while (ptr && strip) {
332 /* look for directories to skip back */
335 ptr = strrchr(mod_name, '/');
336 /* avoid stripping component if there is no slash,
337 * or it doesn't match ... */
338 if (!ptr || stricmp(ptr+1, strip) != 0) {
339 /* ... but not if component matches m|5\.$patchlevel.*| */
340 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
341 && strncmp(strip, base, baselen) == 0
342 && strncmp(ptr+1, base, baselen) == 0))
348 strip = va_arg(ap, char *);
356 strcpy(++ptr, trailing_path);
358 /* only add directory if it exists */
359 if (GetFileAttributes(mod_name) != (DWORD) -1) {
360 /* directory exists */
363 *prev_pathp = sv_2mortal(newSVpvs(""));
364 else if (SvPVX(*prev_pathp))
365 sv_catpvs(*prev_pathp, ";");
366 sv_catpv(*prev_pathp, mod_name);
368 *len = SvCUR(*prev_pathp);
369 return SvPVX(*prev_pathp);
376 win32_get_privlib(const char *pl, STRLEN *const len)
378 char *stdlib = "lib";
379 char buffer[MAX_PATH+1];
382 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
383 sprintf(buffer, "%s-%s", stdlib, pl);
384 if (!get_regstr(buffer, &sv))
385 (void)get_regstr(stdlib, &sv);
387 /* $stdlib .= ";$EMD/../../lib" */
388 return get_emd_part(&sv, len, stdlib, ARCHNAME, "bin", NULL);
392 win32_get_xlib(const char *pl, const char *xlib, const char *libname,
396 char pathstr[MAX_PATH+1];
400 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
401 sprintf(regstr, "%s-%s", xlib, pl);
402 (void)get_regstr(regstr, &sv1);
405 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
406 sprintf(pathstr, "%s/%s/lib", libname, pl);
407 (void)get_emd_part(&sv1, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
409 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
410 (void)get_regstr(xlib, &sv2);
413 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
414 sprintf(pathstr, "%s/lib", libname);
415 (void)get_emd_part(&sv2, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
433 win32_get_sitelib(const char *pl, STRLEN *const len)
435 return win32_get_xlib(pl, "sitelib", "site", len);
438 #ifndef PERL_VENDORLIB_NAME
439 # define PERL_VENDORLIB_NAME "vendor"
443 win32_get_vendorlib(const char *pl, STRLEN *const len)
445 return win32_get_xlib(pl, "vendorlib", PERL_VENDORLIB_NAME, len);
449 has_shell_metachars(const char *ptr)
455 * Scan string looking for redirection (< or >) or pipe
456 * characters (|) that are not in a quoted string.
457 * Shell variable interpolation (%VAR%) can also happen inside strings.
489 #if !defined(PERL_IMPLICIT_SYS)
490 /* since the current process environment is being updated in util.c
491 * the library functions will get the correct environment
494 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
496 PERL_FLUSHALL_FOR_CHILD;
497 return win32_popen(cmd, mode);
501 Perl_my_pclose(pTHX_ PerlIO *fp)
503 return win32_pclose(fp);
507 DllExport unsigned long
510 return (unsigned long)g_osver.dwPlatformId;
519 return -((int)w32_pseudo_id);
524 /* Tokenize a string. Words are null-separated, and the list
525 * ends with a doubled null. Any character (except null and
526 * including backslash) may be escaped by preceding it with a
527 * backslash (the backslash will be stripped).
528 * Returns number of words in result buffer.
531 tokenize(const char *str, char **dest, char ***destv)
533 char *retstart = NULL;
534 char **retvstart = 0;
537 int slen = strlen(str);
540 Newx(ret, slen+2, char);
541 Newx(retv, (slen+3)/2, char*);
549 if (*ret == '\\' && *str)
551 else if (*ret == ' ') {
567 retvstart[items] = NULL;
580 if (!w32_perlshell_tokens) {
581 /* we don't use COMSPEC here for two reasons:
582 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
583 * uncontrolled unportability of the ensuing scripts.
584 * 2. PERL5SHELL could be set to a shell that may not be fit for
585 * interactive use (which is what most programs look in COMSPEC
588 const char* defaultshell = "cmd.exe /x/d/c";
589 const char *usershell = PerlEnv_getenv("PERL5SHELL");
590 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
591 &w32_perlshell_tokens,
597 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
605 PERL_ARGS_ASSERT_DO_ASPAWN;
611 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*);
613 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
618 while (++mark <= sp) {
619 if (*mark && (str = SvPV_nolen(*mark)))
626 status = win32_spawnvp(flag,
627 (const char*)(really ? SvPV_nolen(really) : argv[0]),
628 (const char* const*)argv);
630 if (status < 0 && (errno == ENOEXEC || errno == ENOENT)) {
631 /* possible shell-builtin, invoke with shell */
633 sh_items = w32_perlshell_items;
635 argv[index+sh_items] = argv[index];
636 while (--sh_items >= 0)
637 argv[sh_items] = w32_perlshell_vec[sh_items];
639 status = win32_spawnvp(flag,
640 (const char*)(really ? SvPV_nolen(really) : argv[0]),
641 (const char* const*)argv);
644 if (flag == P_NOWAIT) {
645 PL_statusvalue = -1; /* >16bits hint for pp_system() */
649 if (ckWARN(WARN_EXEC))
650 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
655 PL_statusvalue = status;
661 /* returns pointer to the next unquoted space or the end of the string */
663 find_next_space(const char *s)
665 bool in_quotes = FALSE;
667 /* ignore doubled backslashes, or backslash+quote */
668 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) {
671 /* keep track of when we're within quotes */
672 else if (*s == '"') {
674 in_quotes = !in_quotes;
676 /* break it up only at spaces that aren't in quotes */
677 else if (!in_quotes && isSPACE(*s))
686 do_spawn2(pTHX_ const char *cmd, int exectype) {
687 return do_spawn2_handles(aTHX_ cmd, exectype, NULL);
691 do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles)
697 BOOL needToTry = TRUE;
700 /* Save an extra exec if possible. See if there are shell
701 * metacharacters in it */
702 if (!has_shell_metachars(cmd)) {
703 Newx(argv, strlen(cmd) / 2 + 2, char*);
704 Newx(cmd2, strlen(cmd) + 1, char);
707 for (s = cmd2; *s;) {
708 while (*s && isSPACE(*s))
712 s = find_next_space(s);
720 status = win32_spawnvp(P_WAIT, argv[0],
721 (const char* const*)argv);
723 case EXECF_SPAWN_NOWAIT:
724 status = do_spawnvp_handles(P_NOWAIT, argv[0],
725 (const char* const*)argv, handles);
728 status = win32_execvp(argv[0], (const char* const*)argv);
731 if (status != -1 || errno == 0)
741 Newx(argv, w32_perlshell_items + 2, char*);
742 while (++i < w32_perlshell_items)
743 argv[i] = w32_perlshell_vec[i];
744 argv[i++] = (char *)cmd;
748 status = win32_spawnvp(P_WAIT, argv[0],
749 (const char* const*)argv);
751 case EXECF_SPAWN_NOWAIT:
752 status = do_spawnvp_handles(P_NOWAIT, argv[0],
753 (const char* const*)argv, handles);
756 status = win32_execvp(argv[0], (const char* const*)argv);
762 if (exectype == EXECF_SPAWN_NOWAIT) {
763 PL_statusvalue = -1; /* >16bits hint for pp_system() */
767 if (ckWARN(WARN_EXEC))
768 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s",
769 (exectype == EXECF_EXEC ? "exec" : "spawn"),
770 cmd, strerror(errno));
775 PL_statusvalue = status;
781 Perl_do_spawn(pTHX_ char *cmd)
783 PERL_ARGS_ASSERT_DO_SPAWN;
785 return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
789 Perl_do_spawn_nowait(pTHX_ char *cmd)
791 PERL_ARGS_ASSERT_DO_SPAWN_NOWAIT;
793 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
797 Perl_do_exec(pTHX_ const char *cmd)
799 PERL_ARGS_ASSERT_DO_EXEC;
801 do_spawn2(aTHX_ cmd, EXECF_EXEC);
805 /* The idea here is to read all the directory names into a string table
806 * (separated by nulls) and when one of the other dir functions is called
807 * return the pointer to the current file name.
810 win32_opendir(const char *filename)
816 char scanname[MAX_PATH+3];
817 WCHAR wscanname[sizeof(scanname)];
818 WIN32_FIND_DATAW wFindData;
819 char buffer[MAX_PATH*2];
822 len = strlen(filename);
827 if (len > MAX_PATH) {
828 errno = ENAMETOOLONG;
832 /* Get us a DIR structure */
835 /* Create the search pattern */
836 strcpy(scanname, filename);
838 /* bare drive name means look in cwd for drive */
839 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') {
840 scanname[len++] = '.';
841 scanname[len++] = '/';
843 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') {
844 scanname[len++] = '/';
846 scanname[len++] = '*';
847 scanname[len] = '\0';
849 /* do the FindFirstFile call */
850 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR));
852 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData);
854 if (dirp->handle == INVALID_HANDLE_VALUE) {
855 DWORD err = GetLastError();
856 /* FindFirstFile() fails on empty drives! */
858 case ERROR_FILE_NOT_FOUND:
860 case ERROR_NO_MORE_FILES:
861 case ERROR_PATH_NOT_FOUND:
864 case ERROR_NOT_ENOUGH_MEMORY:
876 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
877 wFindData.cFileName, -1,
878 buffer, sizeof(buffer), NULL, &use_default);
879 if (use_default && *wFindData.cAlternateFileName) {
880 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
881 wFindData.cAlternateFileName, -1,
882 buffer, sizeof(buffer), NULL, NULL);
885 /* now allocate the first part of the string table for
886 * the filenames that we find.
888 idx = strlen(buffer)+1;
893 Newx(dirp->start, dirp->size, char);
894 strcpy(dirp->start, buffer);
896 dirp->end = dirp->curr = dirp->start;
902 /* Readdir just returns the current string pointer and bumps the
903 * string pointer to the nDllExport entry.
905 DllExport struct direct *
906 win32_readdir(DIR *dirp)
911 /* first set up the structure to return */
912 len = strlen(dirp->curr);
913 strcpy(dirp->dirstr.d_name, dirp->curr);
914 dirp->dirstr.d_namlen = len;
917 dirp->dirstr.d_ino = dirp->curr - dirp->start;
919 /* Now set up for the next call to readdir */
920 dirp->curr += len + 1;
921 if (dirp->curr >= dirp->end) {
923 char buffer[MAX_PATH*2];
925 if (dirp->handle == INVALID_HANDLE_VALUE) {
928 /* finding the next file that matches the wildcard
929 * (which should be all of them in this directory!).
932 WIN32_FIND_DATAW wFindData;
933 res = FindNextFileW(dirp->handle, &wFindData);
935 BOOL use_default = FALSE;
936 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
937 wFindData.cFileName, -1,
938 buffer, sizeof(buffer), NULL, &use_default);
939 if (use_default && *wFindData.cAlternateFileName) {
940 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
941 wFindData.cAlternateFileName, -1,
942 buffer, sizeof(buffer), NULL, NULL);
947 long endpos = dirp->end - dirp->start;
948 long newsize = endpos + strlen(buffer) + 1;
949 /* bump the string table size by enough for the
950 * new name and its null terminator */
951 while (newsize > dirp->size) {
952 long curpos = dirp->curr - dirp->start;
954 Renew(dirp->start, dirp->size, char);
955 dirp->curr = dirp->start + curpos;
957 strcpy(dirp->start + endpos, buffer);
958 dirp->end = dirp->start + newsize;
963 if (dirp->handle != INVALID_HANDLE_VALUE) {
964 FindClose(dirp->handle);
965 dirp->handle = INVALID_HANDLE_VALUE;
969 return &(dirp->dirstr);
975 /* Telldir returns the current string pointer position */
977 win32_telldir(DIR *dirp)
979 return dirp->curr ? (dirp->curr - dirp->start) : -1;
983 /* Seekdir moves the string pointer to a previously saved position
984 * (returned by telldir).
987 win32_seekdir(DIR *dirp, long loc)
989 dirp->curr = loc == -1 ? NULL : dirp->start + loc;
992 /* Rewinddir resets the string pointer to the start */
994 win32_rewinddir(DIR *dirp)
996 dirp->curr = dirp->start;
999 /* free the memory allocated by opendir */
1001 win32_closedir(DIR *dirp)
1003 if (dirp->handle != INVALID_HANDLE_VALUE)
1004 FindClose(dirp->handle);
1005 Safefree(dirp->start);
1010 /* duplicate a open DIR* for interpreter cloning */
1012 win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param)
1015 PerlInterpreter *const from = param->proto_perl;
1016 PerlInterpreter *const to = (PerlInterpreter *)PERL_GET_THX;
1021 /* switch back to original interpreter because win32_readdir()
1022 * might Renew(dirp->start).
1028 /* mark current position; read all remaining entries into the
1029 * cache, and then restore to current position.
1031 pos = win32_telldir(dirp);
1032 while (win32_readdir(dirp)) {
1033 /* read all entries into cache */
1035 win32_seekdir(dirp, pos);
1037 /* switch back to new interpreter to allocate new DIR structure */
1043 memcpy(dup, dirp, sizeof(DIR));
1045 Newx(dup->start, dirp->size, char);
1046 memcpy(dup->start, dirp->start, dirp->size);
1048 dup->end = dup->start + (dirp->end - dirp->start);
1050 dup->curr = dup->start + (dirp->curr - dirp->start);
1062 * Just pretend that everyone is a superuser. NT will let us know if
1063 * we don\'t really have permission to do something.
1066 #define ROOT_UID ((uid_t)0)
1067 #define ROOT_GID ((gid_t)0)
1096 return (auid == ROOT_UID ? 0 : -1);
1102 return (agid == ROOT_GID ? 0 : -1);
1109 char *buf = w32_getlogin_buffer;
1110 DWORD size = sizeof(w32_getlogin_buffer);
1111 if (GetUserName(buf,&size))
1117 chown(const char *path, uid_t owner, gid_t group)
1124 * XXX this needs strengthening (for PerlIO)
1127 int mkstemp(const char *path)
1130 char buf[MAX_PATH+1];
1134 if (i++ > 10) { /* give up */
1138 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
1142 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
1149 find_pid(pTHX_ int pid)
1151 long child = w32_num_children;
1152 while (--child >= 0) {
1153 if ((int)w32_child_pids[child] == pid)
1160 remove_dead_process(long child)
1164 CloseHandle(w32_child_handles[child]);
1165 Move(&w32_child_handles[child+1], &w32_child_handles[child],
1166 (w32_num_children-child-1), HANDLE);
1167 Move(&w32_child_pids[child+1], &w32_child_pids[child],
1168 (w32_num_children-child-1), DWORD);
1175 find_pseudo_pid(pTHX_ int pid)
1177 long child = w32_num_pseudo_children;
1178 while (--child >= 0) {
1179 if ((int)w32_pseudo_child_pids[child] == pid)
1186 remove_dead_pseudo_process(long child)
1190 CloseHandle(w32_pseudo_child_handles[child]);
1191 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
1192 (w32_num_pseudo_children-child-1), HANDLE);
1193 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
1194 (w32_num_pseudo_children-child-1), DWORD);
1195 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
1196 (w32_num_pseudo_children-child-1), HWND);
1197 Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child],
1198 (w32_num_pseudo_children-child-1), char);
1199 w32_num_pseudo_children--;
1204 win32_wait_for_children(pTHX)
1206 if (w32_pseudo_children && w32_num_pseudo_children) {
1209 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1211 for (child = 0; child < w32_num_pseudo_children; ++child) {
1212 if (!w32_pseudo_child_sigterm[child])
1213 handles[count++] = w32_pseudo_child_handles[child];
1215 /* XXX should use MsgWaitForMultipleObjects() to continue
1216 * XXX processing messages while we wait.
1218 WaitForMultipleObjects(count, handles, TRUE, INFINITE);
1220 while (w32_num_pseudo_children)
1221 CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]);
1227 terminate_process(DWORD pid, HANDLE process_handle, int sig)
1231 /* "Does process exist?" use of kill */
1234 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid))
1239 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
1242 default: /* For now be backwards compatible with perl 5.6 */
1244 /* Note that we will only be able to kill processes owned by the
1245 * current process owner, even when we are running as an administrator.
1246 * To kill processes of other owners we would need to set the
1247 * 'SeDebugPrivilege' privilege before obtaining the process handle.
1249 if (TerminateProcess(process_handle, sig))
1256 /* returns number of processes killed */
1258 my_killpg(int pid, int sig)
1260 HANDLE process_handle;
1261 HANDLE snapshot_handle;
1264 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1265 if (process_handle == NULL)
1268 killed += terminate_process(pid, process_handle, sig);
1270 snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1271 if (snapshot_handle != INVALID_HANDLE_VALUE) {
1272 PROCESSENTRY32 entry;
1274 entry.dwSize = sizeof(entry);
1275 if (Process32First(snapshot_handle, &entry)) {
1277 if (entry.th32ParentProcessID == (DWORD)pid)
1278 killed += my_killpg(entry.th32ProcessID, sig);
1279 entry.dwSize = sizeof(entry);
1281 while (Process32Next(snapshot_handle, &entry));
1283 CloseHandle(snapshot_handle);
1285 CloseHandle(process_handle);
1289 /* returns number of processes killed */
1291 my_kill(int pid, int sig)
1294 HANDLE process_handle;
1297 return my_killpg(pid, -sig);
1299 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1300 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
1301 if (process_handle != NULL) {
1302 retval = terminate_process(pid, process_handle, sig);
1303 CloseHandle(process_handle);
1309 /* Get a child pseudo-process HWND, with retrying and delaying/yielding.
1310 * The "tries" parameter is the number of retries to make, with a Sleep(1)
1311 * (waiting and yielding the time slot) between each try. Specifying 0 causes
1312 * only Sleep(0) (no waiting and potentially no yielding) to be used, so is not
1314 * Returns an hwnd != INVALID_HANDLE_VALUE (so be aware that NULL can be
1315 * returned) or croaks if the child pseudo-process doesn't schedule and deliver
1316 * a HWND in the time period allowed.
1319 get_hwnd_delay(pTHX, long child, DWORD tries)
1321 HWND hwnd = w32_pseudo_child_message_hwnds[child];
1322 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1324 /* Pseudo-process has not yet properly initialized since hwnd isn't set.
1325 * Fast sleep: On some NT kernels/systems, a Sleep(0) won't deschedule a
1326 * thread 100% of the time since threads are attached to a CPU for NUMA and
1327 * caching reasons, and the child thread was attached to a different CPU
1328 * therefore there is no workload on that CPU and Sleep(0) returns control
1329 * without yielding the time slot.
1330 * https://rt.perl.org/rt3/Ticket/Display.html?id=88840
1333 win32_async_check(aTHX);
1334 hwnd = w32_pseudo_child_message_hwnds[child];
1335 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1338 unsigned int count = 0;
1339 /* No Sleep(1) if tries==0, just fail instead if we get this far. */
1340 while (count++ < tries) {
1342 win32_async_check(aTHX);
1343 hwnd = w32_pseudo_child_message_hwnds[child];
1344 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1348 Perl_croak(aTHX_ "panic: child pseudo-process was never scheduled");
1353 win32_kill(int pid, int sig)
1359 /* it is a pseudo-forked child */
1360 child = find_pseudo_pid(aTHX_ -pid);
1362 HANDLE hProcess = w32_pseudo_child_handles[child];
1365 /* "Does process exist?" use of kill */
1369 /* kill -9 style un-graceful exit */
1370 /* Do a wait to make sure child starts and isn't in DLL
1372 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1373 if (TerminateThread(hProcess, sig)) {
1374 /* Allow the scheduler to finish cleaning up the other
1376 * Otherwise, if we ExitProcess() before another context
1377 * switch happens we will end up with a process exit
1378 * code of "sig" instead of our own exit status.
1379 * https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
1382 remove_dead_pseudo_process(child);
1389 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1390 /* We fake signals to pseudo-processes using Win32
1392 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) ||
1393 PostThreadMessage(-pid, WM_USER_KILL, sig, 0))
1395 /* Don't wait for child process to terminate after we send a
1396 * SIGTERM because the child may be blocked in a system call
1397 * and never receive the signal.
1399 if (sig == SIGTERM) {
1401 w32_pseudo_child_sigterm[child] = 1;
1403 /* It might be us ... */
1415 child = find_pid(aTHX_ pid);
1417 if (my_kill(pid, sig)) {
1419 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) &&
1420 exitcode != STILL_ACTIVE)
1422 remove_dead_process(child);
1428 if (my_kill(pid, sig))
1437 win32_stat(const char *path, Stat_t *sbuf)
1439 char buffer[MAX_PATH+1];
1440 int l = strlen(path);
1444 BOOL expect_dir = FALSE;
1446 GV *gv_sloppy = gv_fetchpvs("\027IN32_SLOPPY_STAT",
1447 GV_NOTQUAL, SVt_PV);
1448 BOOL sloppy = gv_sloppy && SvTRUE(GvSV(gv_sloppy));
1451 switch(path[l - 1]) {
1452 /* FindFirstFile() and stat() are buggy with a trailing
1453 * slashes, except for the root directory of a drive */
1456 if (l > sizeof(buffer)) {
1457 errno = ENAMETOOLONG;
1461 strncpy(buffer, path, l);
1462 /* remove additional trailing slashes */
1463 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\'))
1465 /* add back slash if we otherwise end up with just a drive letter */
1466 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':')
1473 /* FindFirstFile() is buggy with "x:", so add a dot :-( */
1475 if (l == 2 && isALPHA(path[0])) {
1476 buffer[0] = path[0];
1487 path = PerlDir_mapA(path);
1491 /* We must open & close the file once; otherwise file attribute changes */
1492 /* might not yet have propagated to "other" hard links of the same file. */
1493 /* This also gives us an opportunity to determine the number of links. */
1494 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1495 if (handle != INVALID_HANDLE_VALUE) {
1496 BY_HANDLE_FILE_INFORMATION bhi;
1497 if (GetFileInformationByHandle(handle, &bhi))
1498 nlink = bhi.nNumberOfLinks;
1499 CloseHandle(handle);
1503 /* path will be mapped correctly above */
1504 #if defined(WIN64) || defined(USE_LARGE_FILES)
1505 res = _stati64(path, sbuf);
1507 res = stat(path, sbuf);
1509 sbuf->st_nlink = nlink;
1512 /* CRT is buggy on sharenames, so make sure it really isn't.
1513 * XXX using GetFileAttributesEx() will enable us to set
1514 * sbuf->st_*time (but note that's not available on the
1515 * Windows of 1995) */
1516 DWORD r = GetFileAttributesA(path);
1517 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1518 /* sbuf may still contain old garbage since stat() failed */
1519 Zero(sbuf, 1, Stat_t);
1520 sbuf->st_mode = S_IFDIR | S_IREAD;
1522 if (!(r & FILE_ATTRIBUTE_READONLY))
1523 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1528 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1529 && (path[2] == '\\' || path[2] == '/'))
1531 /* The drive can be inaccessible, some _stat()s are buggy */
1532 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1537 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1541 if (S_ISDIR(sbuf->st_mode)) {
1542 /* Ensure the "write" bit is switched off in the mode for
1543 * directories with the read-only attribute set. Some compilers
1544 * switch it on for directories, which is technically correct
1545 * (directories are indeed always writable unless denied by DACLs),
1546 * but we want stat() and -w to reflect the state of the read-only
1547 * attribute for symmetry with chmod(). */
1548 DWORD r = GetFileAttributesA(path);
1549 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
1550 sbuf->st_mode &= ~S_IWRITE;
1557 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1558 #define SKIP_SLASHES(s) \
1560 while (*(s) && isSLASH(*(s))) \
1563 #define COPY_NONSLASHES(d,s) \
1565 while (*(s) && !isSLASH(*(s))) \
1569 /* Find the longname of a given path. path is destructively modified.
1570 * It should have space for at least MAX_PATH characters. */
1572 win32_longpath(char *path)
1574 WIN32_FIND_DATA fdata;
1576 char tmpbuf[MAX_PATH+1];
1577 char *tmpstart = tmpbuf;
1584 if (isALPHA(path[0]) && path[1] == ':') {
1586 *tmpstart++ = path[0];
1590 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1592 *tmpstart++ = path[0];
1593 *tmpstart++ = path[1];
1594 SKIP_SLASHES(start);
1595 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1597 *tmpstart++ = *start++;
1598 SKIP_SLASHES(start);
1599 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1604 /* copy initial slash, if any */
1605 if (isSLASH(*start)) {
1606 *tmpstart++ = *start++;
1608 SKIP_SLASHES(start);
1611 /* FindFirstFile() expands "." and "..", so we need to pass
1612 * those through unmolested */
1614 && (!start[1] || isSLASH(start[1])
1615 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1617 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1622 /* if this is the end, bust outta here */
1626 /* now we're at a non-slash; walk up to next slash */
1627 while (*start && !isSLASH(*start))
1630 /* stop and find full name of component */
1633 fhand = FindFirstFile(path,&fdata);
1635 if (fhand != INVALID_HANDLE_VALUE) {
1636 STRLEN len = strlen(fdata.cFileName);
1637 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1638 strcpy(tmpstart, fdata.cFileName);
1649 /* failed a step, just return without side effects */
1650 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1655 strcpy(path,tmpbuf);
1668 win32_croak_not_implemented(const char * fname)
1670 PERL_ARGS_ASSERT_WIN32_CROAK_NOT_IMPLEMENTED;
1672 Perl_croak_nocontext("%s not implemented!\n", fname);
1675 /* Converts a wide character (UTF-16) string to the Windows ANSI code page,
1676 * potentially using the system's default replacement character for any
1677 * unrepresentable characters. The caller must free() the returned string. */
1679 wstr_to_str(const wchar_t* wstr)
1681 BOOL used_default = FALSE;
1682 size_t wlen = wcslen(wstr) + 1;
1683 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1684 NULL, 0, NULL, NULL);
1685 char* str = (char*)malloc(len);
1688 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1689 str, len, NULL, &used_default);
1693 /* The win32_ansipath() function takes a Unicode filename and converts it
1694 * into the current Windows codepage. If some characters cannot be mapped,
1695 * then it will convert the short name instead.
1697 * The buffer to the ansi pathname must be freed with win32_free() when it
1698 * it no longer needed.
1700 * The argument to win32_ansipath() must exist before this function is
1701 * called; otherwise there is no way to determine the short path name.
1703 * Ideas for future refinement:
1704 * - Only convert those segments of the path that are not in the current
1705 * codepage, but leave the other segments in their long form.
1706 * - If the resulting name is longer than MAX_PATH, start converting
1707 * additional path segments into short names until the full name
1708 * is shorter than MAX_PATH. Shorten the filename part last!
1711 win32_ansipath(const WCHAR *widename)
1714 BOOL use_default = FALSE;
1715 size_t widelen = wcslen(widename)+1;
1716 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1717 NULL, 0, NULL, NULL);
1718 name = (char*)win32_malloc(len);
1722 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1723 name, len, NULL, &use_default);
1725 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1727 WCHAR *shortname = (WCHAR*)win32_malloc(shortlen*sizeof(WCHAR));
1730 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1732 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1733 NULL, 0, NULL, NULL);
1734 name = (char*)win32_realloc(name, len);
1737 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1738 name, len, NULL, NULL);
1739 win32_free(shortname);
1745 /* the returned string must be freed with win32_freeenvironmentstrings which is
1746 * implemented as a macro
1747 * void win32_freeenvironmentstrings(void* block)
1750 win32_getenvironmentstrings(void)
1752 LPWSTR lpWStr, lpWTmp;
1754 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1756 /* Get the process environment strings */
1757 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1758 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1759 env_len = wcslen(lpWTmp);
1760 /* calculate the size of the environment strings */
1761 wenvstrings_len += env_len + 1;
1764 /* Get the number of bytes required to store the ACP encoded string */
1765 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1766 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL);
1767 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1771 /* Convert the string from UTF-16 encoding to ACP encoding */
1772 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1773 aenvstrings_len, NULL, NULL);
1775 FreeEnvironmentStringsW(lpWStr);
1781 win32_getenv(const char *name)
1788 needlen = GetEnvironmentVariableA(name,NULL,0);
1790 curitem = sv_2mortal(newSVpvs(""));
1792 SvGROW(curitem, needlen+1);
1793 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1795 } while (needlen >= SvLEN(curitem));
1796 SvCUR_set(curitem, needlen);
1799 last_err = GetLastError();
1800 if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
1801 /* It appears the variable is in the env, but the Win32 API
1802 doesn't have a canned way of getting it. So we fall back to
1803 grabbing the whole env and pulling this value out if possible */
1804 char *envv = GetEnvironmentStrings();
1808 char *end = strchr(cur,'=');
1809 if (end && end != cur) {
1811 if (!strcmp(cur,name)) {
1812 curitem = sv_2mortal(newSVpv(end+1,0));
1817 cur = end + strlen(end+1)+2;
1819 else if ((len = strlen(cur)))
1822 FreeEnvironmentStrings(envv);
1825 /* last ditch: allow any environment variables that begin with 'PERL'
1826 to be obtained from the registry, if found there */
1827 if (strncmp(name, "PERL", 4) == 0)
1828 (void)get_regstr(name, &curitem);
1831 if (curitem && SvCUR(curitem))
1832 return SvPVX(curitem);
1838 win32_putenv(const char *name)
1845 curitem = (char *) win32_malloc(strlen(name)+1);
1846 strcpy(curitem, name);
1847 val = strchr(curitem, '=');
1849 /* The sane way to deal with the environment.
1850 * Has these advantages over putenv() & co.:
1851 * * enables us to store a truly empty value in the
1852 * environment (like in UNIX).
1853 * * we don't have to deal with RTL globals, bugs and leaks
1854 * (specifically, see http://support.microsoft.com/kb/235601).
1856 * Why you may want to use the RTL environment handling
1857 * (previously enabled by USE_WIN32_RTL_ENV):
1858 * * environ[] and RTL functions will not reflect changes,
1859 * which might be an issue if extensions want to access
1860 * the env. via RTL. This cuts both ways, since RTL will
1861 * not see changes made by extensions that call the Win32
1862 * functions directly, either.
1866 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1869 win32_free(curitem);
1875 filetime_to_clock(PFILETIME ft)
1877 __int64 qw = ft->dwHighDateTime;
1879 qw |= ft->dwLowDateTime;
1880 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1885 win32_times(struct tms *timebuf)
1890 clock_t process_time_so_far = clock();
1891 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1893 timebuf->tms_utime = filetime_to_clock(&user);
1894 timebuf->tms_stime = filetime_to_clock(&kernel);
1895 timebuf->tms_cutime = 0;
1896 timebuf->tms_cstime = 0;
1898 /* That failed - e.g. Win95 fallback to clock() */
1899 timebuf->tms_utime = process_time_so_far;
1900 timebuf->tms_stime = 0;
1901 timebuf->tms_cutime = 0;
1902 timebuf->tms_cstime = 0;
1904 return process_time_so_far;
1907 /* fix utime() so it works on directories in NT */
1909 filetime_from_time(PFILETIME pFileTime, time_t Time)
1911 struct tm *pTM = localtime(&Time);
1912 SYSTEMTIME SystemTime;
1918 SystemTime.wYear = pTM->tm_year + 1900;
1919 SystemTime.wMonth = pTM->tm_mon + 1;
1920 SystemTime.wDay = pTM->tm_mday;
1921 SystemTime.wHour = pTM->tm_hour;
1922 SystemTime.wMinute = pTM->tm_min;
1923 SystemTime.wSecond = pTM->tm_sec;
1924 SystemTime.wMilliseconds = 0;
1926 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1927 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1931 win32_unlink(const char *filename)
1937 filename = PerlDir_mapA(filename);
1938 attrs = GetFileAttributesA(filename);
1939 if (attrs == 0xFFFFFFFF) {
1943 if (attrs & FILE_ATTRIBUTE_READONLY) {
1944 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1945 ret = unlink(filename);
1947 (void)SetFileAttributesA(filename, attrs);
1950 ret = unlink(filename);
1955 win32_utime(const char *filename, struct utimbuf *times)
1962 struct utimbuf TimeBuffer;
1965 filename = PerlDir_mapA(filename);
1966 rc = utime(filename, times);
1968 /* EACCES: path specifies directory or readonly file */
1969 if (rc == 0 || errno != EACCES)
1972 if (times == NULL) {
1973 times = &TimeBuffer;
1974 time(×->actime);
1975 times->modtime = times->actime;
1978 /* This will (and should) still fail on readonly files */
1979 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
1980 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
1981 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1982 if (handle == INVALID_HANDLE_VALUE)
1985 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
1986 filetime_from_time(&ftAccess, times->actime) &&
1987 filetime_from_time(&ftWrite, times->modtime) &&
1988 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
1993 CloseHandle(handle);
1998 unsigned __int64 ft_i64;
2003 #define Const64(x) x##LL
2005 #define Const64(x) x##i64
2007 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
2008 #define EPOCH_BIAS Const64(116444736000000000)
2010 /* NOTE: This does not compute the timezone info (doing so can be expensive,
2011 * and appears to be unsupported even by glibc) */
2013 win32_gettimeofday(struct timeval *tp, void *not_used)
2017 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
2018 GetSystemTimeAsFileTime(&ft.ft_val);
2020 /* seconds since epoch */
2021 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
2023 /* microseconds remaining */
2024 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
2030 win32_uname(struct utsname *name)
2032 struct hostent *hep;
2033 STRLEN nodemax = sizeof(name->nodename)-1;
2036 switch (g_osver.dwPlatformId) {
2037 case VER_PLATFORM_WIN32_WINDOWS:
2038 strcpy(name->sysname, "Windows");
2040 case VER_PLATFORM_WIN32_NT:
2041 strcpy(name->sysname, "Windows NT");
2043 case VER_PLATFORM_WIN32s:
2044 strcpy(name->sysname, "Win32s");
2047 strcpy(name->sysname, "Win32 Unknown");
2052 sprintf(name->release, "%d.%d",
2053 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
2056 sprintf(name->version, "Build %d",
2057 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
2058 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
2059 if (g_osver.szCSDVersion[0]) {
2060 char *buf = name->version + strlen(name->version);
2061 sprintf(buf, " (%s)", g_osver.szCSDVersion);
2065 hep = win32_gethostbyname("localhost");
2067 STRLEN len = strlen(hep->h_name);
2068 if (len <= nodemax) {
2069 strcpy(name->nodename, hep->h_name);
2072 strncpy(name->nodename, hep->h_name, nodemax);
2073 name->nodename[nodemax] = '\0';
2078 if (!GetComputerName(name->nodename, &sz))
2079 *name->nodename = '\0';
2082 /* machine (architecture) */
2087 GetSystemInfo(&info);
2089 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION))
2090 procarch = info.u.s.wProcessorArchitecture;
2092 procarch = info.wProcessorArchitecture;
2095 case PROCESSOR_ARCHITECTURE_INTEL:
2096 arch = "x86"; break;
2097 case PROCESSOR_ARCHITECTURE_IA64:
2098 arch = "ia64"; break;
2099 case PROCESSOR_ARCHITECTURE_AMD64:
2100 arch = "amd64"; break;
2101 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2102 arch = "unknown"; break;
2104 sprintf(name->machine, "unknown(0x%x)", procarch);
2105 arch = name->machine;
2108 if (name->machine != arch)
2109 strcpy(name->machine, arch);
2114 /* Timing related stuff */
2117 do_raise(pTHX_ int sig)
2119 if (sig < SIG_SIZE) {
2120 Sighandler_t handler = w32_sighandler[sig];
2121 if (handler == SIG_IGN) {
2124 else if (handler != SIG_DFL) {
2129 /* Choose correct default behaviour */
2145 /* Tell caller to exit thread/process as approriate */
2150 sig_terminate(pTHX_ int sig)
2152 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2153 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2160 win32_async_check(pTHX)
2163 HWND hwnd = w32_message_hwnd;
2165 /* Reset w32_poll_count before doing anything else, incase we dispatch
2166 * messages that end up calling back into perl */
2169 if (hwnd != INVALID_HANDLE_VALUE) {
2170 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2171 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2176 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2177 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2179 /* re-post a WM_QUIT message (we'll mark it as read later) */
2180 if(msg.message == WM_QUIT) {
2181 PostQuitMessage((int)msg.wParam);
2185 if(!CallMsgFilter(&msg, MSGF_USER))
2187 TranslateMessage(&msg);
2188 DispatchMessage(&msg);
2193 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2194 * This is necessary when we are being called by win32_msgwait() to
2195 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2196 * message over and over. An example how this can happen is when
2197 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2198 * is generating messages before the process terminated.
2200 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD);
2202 /* Above or other stuff may have set a signal flag */
2209 /* This function will not return until the timeout has elapsed, or until
2210 * one of the handles is ready. */
2212 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2214 /* We may need several goes at this - so compute when we stop */
2216 unsigned __int64 endtime = timeout;
2217 if (timeout != INFINITE) {
2218 GetSystemTimeAsFileTime(&ticks.ft_val);
2219 ticks.ft_i64 /= 10000;
2220 endtime += ticks.ft_i64;
2222 /* This was a race condition. Do not let a non INFINITE timeout to
2223 * MsgWaitForMultipleObjects roll under 0 creating a near
2224 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the
2225 * user who did a CORE perl function with a non infinity timeout,
2226 * sleep for example. This is 64 to 32 truncation minefield.
2228 * This scenario can only be created if the timespan from the return of
2229 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To
2230 * generate the scenario, manual breakpoints in a C debugger are required,
2231 * or a context switch occured in win32_async_check in PeekMessage, or random
2232 * messages are delivered to the *thread* message queue of the Perl thread
2233 * from another process (msctf.dll doing IPC among its instances, VS debugger
2234 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096].
2236 while (ticks.ft_i64 <= endtime) {
2237 /* if timeout's type is lengthened, remember to split 64b timeout
2238 * into multiple non-infinity runs of MWFMO */
2239 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE,
2240 (DWORD)(endtime - ticks.ft_i64),
2241 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2244 if (result == WAIT_TIMEOUT) {
2245 /* Ran out of time - explicit return of zero to avoid -ve if we
2246 have scheduling issues
2250 if (timeout != INFINITE) {
2251 GetSystemTimeAsFileTime(&ticks.ft_val);
2252 ticks.ft_i64 /= 10000;
2254 if (result == WAIT_OBJECT_0 + count) {
2255 /* Message has arrived - check it */
2256 (void)win32_async_check(aTHX);
2259 /* Not timeout or message - one of handles is ready */
2263 /* If we are past the end say zero */
2264 if (!ticks.ft_i64 || ticks.ft_i64 > endtime)
2266 /* compute time left to wait */
2267 ticks.ft_i64 = endtime - ticks.ft_i64;
2268 /* if more ms than DWORD, then return max DWORD */
2269 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX;
2273 win32_internal_wait(pTHX_ int *status, DWORD timeout)
2275 /* XXX this wait emulation only knows about processes
2276 * spawned via win32_spawnvp(P_NOWAIT, ...).
2279 DWORD exitcode, waitcode;
2282 if (w32_num_pseudo_children) {
2283 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2284 timeout, &waitcode);
2285 /* Time out here if there are no other children to wait for. */
2286 if (waitcode == WAIT_TIMEOUT) {
2287 if (!w32_num_children) {
2291 else if (waitcode != WAIT_FAILED) {
2292 if (waitcode >= WAIT_ABANDONED_0
2293 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2294 i = waitcode - WAIT_ABANDONED_0;
2296 i = waitcode - WAIT_OBJECT_0;
2297 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2298 *status = (int)((exitcode & 0xff) << 8);
2299 retval = (int)w32_pseudo_child_pids[i];
2300 remove_dead_pseudo_process(i);
2307 if (!w32_num_children) {
2312 /* if a child exists, wait for it to die */
2313 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2314 if (waitcode == WAIT_TIMEOUT) {
2317 if (waitcode != WAIT_FAILED) {
2318 if (waitcode >= WAIT_ABANDONED_0
2319 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2320 i = waitcode - WAIT_ABANDONED_0;
2322 i = waitcode - WAIT_OBJECT_0;
2323 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2324 *status = (int)((exitcode & 0xff) << 8);
2325 retval = (int)w32_child_pids[i];
2326 remove_dead_process(i);
2331 errno = GetLastError();
2336 win32_waitpid(int pid, int *status, int flags)
2339 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2342 if (pid == -1) /* XXX threadid == 1 ? */
2343 return win32_internal_wait(aTHX_ status, timeout);
2346 child = find_pseudo_pid(aTHX_ -pid);
2348 HANDLE hThread = w32_pseudo_child_handles[child];
2350 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2351 if (waitcode == WAIT_TIMEOUT) {
2354 else if (waitcode == WAIT_OBJECT_0) {
2355 if (GetExitCodeThread(hThread, &waitcode)) {
2356 *status = (int)((waitcode & 0xff) << 8);
2357 retval = (int)w32_pseudo_child_pids[child];
2358 remove_dead_pseudo_process(child);
2370 child = find_pid(aTHX_ pid);
2372 hProcess = w32_child_handles[child];
2373 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2374 if (waitcode == WAIT_TIMEOUT) {
2377 else if (waitcode == WAIT_OBJECT_0) {
2378 if (GetExitCodeProcess(hProcess, &waitcode)) {
2379 *status = (int)((waitcode & 0xff) << 8);
2380 retval = (int)w32_child_pids[child];
2381 remove_dead_process(child);
2389 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
2391 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2392 if (waitcode == WAIT_TIMEOUT) {
2393 CloseHandle(hProcess);
2396 else if (waitcode == WAIT_OBJECT_0) {
2397 if (GetExitCodeProcess(hProcess, &waitcode)) {
2398 *status = (int)((waitcode & 0xff) << 8);
2399 CloseHandle(hProcess);
2403 CloseHandle(hProcess);
2409 return retval >= 0 ? pid : retval;
2413 win32_wait(int *status)
2416 return win32_internal_wait(aTHX_ status, INFINITE);
2419 DllExport unsigned int
2420 win32_sleep(unsigned int t)
2423 /* Win32 times are in ms so *1000 in and /1000 out */
2424 if (t > UINT_MAX / 1000) {
2425 Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
2426 "sleep(%lu) too large", t);
2428 return win32_msgwait(aTHX_ 0, NULL, t * 1000, NULL) / 1000;
2431 DllExport unsigned int
2432 win32_alarm(unsigned int sec)
2435 * the 'obvious' implentation is SetTimer() with a callback
2436 * which does whatever receiving SIGALRM would do
2437 * we cannot use SIGALRM even via raise() as it is not
2438 * one of the supported codes in <signal.h>
2442 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2443 w32_message_hwnd = win32_create_message_window();
2446 if (w32_message_hwnd == NULL)
2447 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2450 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2455 KillTimer(w32_message_hwnd, w32_timerid);
2462 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2465 win32_crypt(const char *txt, const char *salt)
2468 return des_fcrypt(txt, salt, w32_crypt_buffer);
2471 /* simulate flock by locking a range on the file */
2473 #define LK_LEN 0xffff0000
2476 win32_flock(int fd, int oper)
2482 fh = (HANDLE)_get_osfhandle(fd);
2483 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */
2486 memset(&o, 0, sizeof(o));
2489 case LOCK_SH: /* shared lock */
2490 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
2493 case LOCK_EX: /* exclusive lock */
2494 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
2497 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2498 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
2501 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2502 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2506 case LOCK_UN: /* unlock lock */
2507 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o))
2510 default: /* unknown */
2515 if (GetLastError() == ERROR_LOCK_VIOLATION)
2516 errno = EWOULDBLOCK;
2525 extern int convert_wsa_error_to_errno(int wsaerr); /* in win32sck.c */
2527 /* Get the errno value corresponding to the given err. This function is not
2528 * intended to handle conversion of general GetLastError() codes. It only exists
2529 * to translate Windows sockets error codes from WSAGetLastError(). Such codes
2530 * used to be assigned to errno/$! in earlier versions of perl; this function is
2531 * used to catch any old Perl code which is still trying to assign such values
2532 * to $! and convert them to errno values instead.
2535 win32_get_errno(int err)
2537 return convert_wsa_error_to_errno(err);
2541 * redirected io subsystem for all XS modules
2554 return (&(_environ));
2557 /* the rest are the remapped stdio routines */
2577 win32_ferror(FILE *fp)
2579 return (ferror(fp));
2584 win32_feof(FILE *fp)
2589 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2590 extern int convert_errno_to_wsa_error(int err); /* in win32sck.c */
2594 * Since the errors returned by the socket error function
2595 * WSAGetLastError() are not known by the library routine strerror
2596 * we have to roll our own to cover the case of socket errors
2597 * that could not be converted to regular errno values by
2598 * get_last_socket_error() in win32/win32sck.c.
2602 win32_strerror(int e)
2604 #if !defined __MINGW32__ /* compiler intolerance */
2605 extern int sys_nerr;
2608 if (e < 0 || e > sys_nerr) {
2612 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2613 /* VC10+ and some MinGW/gcc-4.8+ define a "POSIX supplement" of errno
2614 * values ranging from EADDRINUSE (100) to EWOULDBLOCK (140), but
2615 * sys_nerr is still 43 and strerror() returns "Unknown error" for them.
2616 * We must therefore still roll our own messages for these codes, and
2617 * additionally map them to corresponding Windows (sockets) error codes
2618 * first to avoid getting the wrong system message.
2620 else if (e >= EADDRINUSE && e <= EWOULDBLOCK) {
2621 e = convert_errno_to_wsa_error(e);
2625 aTHXa(PERL_GET_THX);
2626 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
2627 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0,
2628 w32_strerror_buffer, sizeof(w32_strerror_buffer),
2631 strcpy(w32_strerror_buffer, "Unknown Error");
2633 return w32_strerror_buffer;
2637 #define strerror win32_strerror
2641 win32_str_os_error(void *sv, DWORD dwErr)
2645 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2646 |FORMAT_MESSAGE_IGNORE_INSERTS
2647 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2648 dwErr, 0, (char *)&sMsg, 1, NULL);
2649 /* strip trailing whitespace and period */
2652 --dwLen; /* dwLen doesn't include trailing null */
2653 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2654 if ('.' != sMsg[dwLen])
2659 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2661 dwLen = sprintf(sMsg,
2662 "Unknown error #0x%lX (lookup 0x%lX)",
2663 dwErr, GetLastError());
2667 sv_setpvn((SV*)sv, sMsg, dwLen);
2673 win32_fprintf(FILE *fp, const char *format, ...)
2676 va_start(marker, format); /* Initialize variable arguments. */
2678 return (vfprintf(fp, format, marker));
2682 win32_printf(const char *format, ...)
2685 va_start(marker, format); /* Initialize variable arguments. */
2687 return (vprintf(format, marker));
2691 win32_vfprintf(FILE *fp, const char *format, va_list args)
2693 return (vfprintf(fp, format, args));
2697 win32_vprintf(const char *format, va_list args)
2699 return (vprintf(format, args));
2703 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2705 return fread(buf, size, count, fp);
2709 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2711 return fwrite(buf, size, count, fp);
2714 #define MODE_SIZE 10
2717 win32_fopen(const char *filename, const char *mode)
2725 if (stricmp(filename, "/dev/null")==0)
2728 aTHXa(PERL_GET_THX);
2729 f = fopen(PerlDir_mapA(filename), mode);
2730 /* avoid buffering headaches for child processes */
2731 if (f && *mode == 'a')
2732 win32_fseek(f, 0, SEEK_END);
2737 win32_fdopen(int handle, const char *mode)
2740 f = fdopen(handle, (char *) mode);
2741 /* avoid buffering headaches for child processes */
2742 if (f && *mode == 'a')
2743 win32_fseek(f, 0, SEEK_END);
2748 win32_freopen(const char *path, const char *mode, FILE *stream)
2751 if (stricmp(path, "/dev/null")==0)
2754 aTHXa(PERL_GET_THX);
2755 return freopen(PerlDir_mapA(path), mode, stream);
2759 win32_fclose(FILE *pf)
2761 #ifdef WIN32_NO_SOCKETS
2764 return my_fclose(pf); /* defined in win32sck.c */
2769 win32_fputs(const char *s,FILE *pf)
2771 return fputs(s, pf);
2775 win32_fputc(int c,FILE *pf)
2781 win32_ungetc(int c,FILE *pf)
2783 return ungetc(c,pf);
2787 win32_getc(FILE *pf)
2793 win32_fileno(FILE *pf)
2799 win32_clearerr(FILE *pf)
2806 win32_fflush(FILE *pf)
2812 win32_ftell(FILE *pf)
2814 #if defined(WIN64) || defined(USE_LARGE_FILES)
2816 if (fgetpos(pf, &pos))
2825 win32_fseek(FILE *pf, Off_t offset,int origin)
2827 #if defined(WIN64) || defined(USE_LARGE_FILES)
2831 if (fgetpos(pf, &pos))
2836 fseek(pf, 0, SEEK_END);
2837 pos = _telli64(fileno(pf));
2846 return fsetpos(pf, &offset);
2848 return fseek(pf, (long)offset, origin);
2853 win32_fgetpos(FILE *pf,fpos_t *p)
2855 return fgetpos(pf, p);
2859 win32_fsetpos(FILE *pf,const fpos_t *p)
2861 return fsetpos(pf, p);
2865 win32_rewind(FILE *pf)
2874 char prefix[MAX_PATH+1];
2875 char filename[MAX_PATH+1];
2876 DWORD len = GetTempPath(MAX_PATH, prefix);
2877 if (len && len < MAX_PATH) {
2878 if (GetTempFileName(prefix, "plx", 0, filename)) {
2879 HANDLE fh = CreateFile(filename,
2880 DELETE | GENERIC_READ | GENERIC_WRITE,
2884 FILE_ATTRIBUTE_NORMAL
2885 | FILE_FLAG_DELETE_ON_CLOSE,
2887 if (fh != INVALID_HANDLE_VALUE) {
2888 int fd = win32_open_osfhandle((intptr_t)fh, 0);
2891 DEBUG_p(PerlIO_printf(Perl_debug_log,
2892 "Created tmpfile=%s\n",filename));
2904 int fd = win32_tmpfd();
2906 return win32_fdopen(fd, "w+b");
2918 win32_fstat(int fd, Stat_t *sbufptr)
2920 #if defined(WIN64) || defined(USE_LARGE_FILES)
2921 return _fstati64(fd, sbufptr);
2923 return fstat(fd, sbufptr);
2928 win32_pipe(int *pfd, unsigned int size, int mode)
2930 return _pipe(pfd, size, mode);
2934 win32_popenlist(const char *mode, IV narg, SV **args)
2938 return do_popen(mode, NULL, narg, args);
2942 do_popen(const char *mode, const char *command, IV narg, SV **args) {
2951 const char **args_pvs = NULL;
2953 /* establish which ends read and write */
2954 if (strchr(mode,'w')) {
2955 stdfd = 0; /* stdin */
2958 nhandle = STD_INPUT_HANDLE;
2960 else if (strchr(mode,'r')) {
2961 stdfd = 1; /* stdout */
2964 nhandle = STD_OUTPUT_HANDLE;
2969 /* set the correct mode */
2970 if (strchr(mode,'b'))
2972 else if (strchr(mode,'t'))
2975 ourmode = _fmode & (O_TEXT | O_BINARY);
2977 /* the child doesn't inherit handles */
2978 ourmode |= O_NOINHERIT;
2980 if (win32_pipe(p, 512, ourmode) == -1)
2983 /* Previously this code redirected stdin/out temporarily so the
2984 child process inherited those handles, this caused race
2985 conditions when another thread was writing/reading those
2988 To avoid that we just feed the handles to CreateProcess() so
2989 the handles are redirected only in the child.
2991 handles[child] = p[child];
2992 handles[parent] = -1;
2995 /* CreateProcess() requires inheritable handles */
2996 if (!SetHandleInformation((HANDLE)_get_osfhandle(p[child]), HANDLE_FLAG_INHERIT,
2997 HANDLE_FLAG_INHERIT)) {
3001 /* start the child */
3006 if ((childpid = do_spawn2_handles(aTHX_ command, EXECF_SPAWN_NOWAIT, handles)) == -1)
3013 Newx(args_pvs, narg + 1 + w32_perlshell_items, const char *);
3014 SAVEFREEPV(args_pvs);
3015 for (i = 0; i < narg; ++i)
3016 args_pvs[i] = SvPV_nolen(args[i]);
3019 if ((childpid = do_spawnvp_handles(P_NOWAIT, args_pvs[0], args_pvs, handles)) == -1) {
3020 if (errno == ENOEXEC || errno == ENOENT) {
3021 /* possible shell-builtin, invoke with shell */
3022 Move(args_pvs, args_pvs+w32_perlshell_items, narg+1, const char *);
3023 Copy(w32_perlshell_vec, args_pvs, w32_perlshell_items, const char *);
3024 if ((childpid = do_spawnvp_handles(P_NOWAIT, args_pvs[0], args_pvs, handles)) == -1)
3032 win32_close(p[child]);
3034 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3036 /* set process id so that it can be returned by perl's open() */
3037 PL_forkprocess = childpid;
3040 /* we have an fd, return a file stream */
3041 return (PerlIO_fdopen(p[parent], (char *)mode));
3044 /* we don't need to check for errors here */
3052 * a popen() clone that respects PERL5SHELL
3054 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
3058 win32_popen(const char *command, const char *mode)
3060 #ifdef USE_RTL_POPEN
3061 return _popen(command, mode);
3063 return do_popen(mode, command, 0, NULL);
3064 #endif /* USE_RTL_POPEN */
3072 win32_pclose(PerlIO *pf)
3074 #ifdef USE_RTL_POPEN
3078 int childpid, status;
3081 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3084 childpid = SvIVX(sv);
3100 if (win32_waitpid(childpid, &status, 0) == -1)
3105 #endif /* USE_RTL_POPEN */
3109 win32_link(const char *oldname, const char *newname)
3112 WCHAR wOldName[MAX_PATH+1];
3113 WCHAR wNewName[MAX_PATH+1];
3115 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3116 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3117 ((aTHXa(PERL_GET_THX)), wcscpy(wOldName, PerlDir_mapW(wOldName)),
3118 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3122 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for
3123 both permissions errors and if the source is a directory, while
3124 POSIX wants EACCES and EPERM respectively.
3126 Determined by experimentation on Windows 7 x64 SP1, since MS
3127 don't document what error codes are returned.
3129 switch (GetLastError()) {
3130 case ERROR_BAD_NET_NAME:
3131 case ERROR_BAD_NETPATH:
3132 case ERROR_BAD_PATHNAME:
3133 case ERROR_FILE_NOT_FOUND:
3134 case ERROR_FILENAME_EXCED_RANGE:
3135 case ERROR_INVALID_DRIVE:
3136 case ERROR_PATH_NOT_FOUND:
3139 case ERROR_ALREADY_EXISTS:
3142 case ERROR_ACCESS_DENIED:
3145 case ERROR_NOT_SAME_DEVICE:
3148 case ERROR_DISK_FULL:
3151 case ERROR_NOT_ENOUGH_QUOTA:
3155 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */
3163 win32_rename(const char *oname, const char *newname)
3165 char szOldName[MAX_PATH+1];
3167 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3170 if (stricmp(newname, oname))
3171 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3172 strcpy(szOldName, PerlDir_mapA(oname));
3174 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3176 DWORD err = GetLastError();
3178 case ERROR_BAD_NET_NAME:
3179 case ERROR_BAD_NETPATH:
3180 case ERROR_BAD_PATHNAME:
3181 case ERROR_FILE_NOT_FOUND:
3182 case ERROR_FILENAME_EXCED_RANGE:
3183 case ERROR_INVALID_DRIVE:
3184 case ERROR_NO_MORE_FILES:
3185 case ERROR_PATH_NOT_FOUND:
3188 case ERROR_DISK_FULL:
3191 case ERROR_NOT_ENOUGH_QUOTA:
3204 win32_setmode(int fd, int mode)
3206 return setmode(fd, mode);
3210 win32_chsize(int fd, Off_t size)
3212 #if defined(WIN64) || defined(USE_LARGE_FILES)
3214 Off_t cur, end, extend;
3216 cur = win32_tell(fd);
3219 end = win32_lseek(fd, 0, SEEK_END);
3222 extend = size - end;
3226 else if (extend > 0) {
3227 /* must grow the file, padding with nulls */
3229 int oldmode = win32_setmode(fd, O_BINARY);
3231 memset(b, '\0', sizeof(b));
3233 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3234 count = win32_write(fd, b, count);
3235 if ((int)count < 0) {
3239 } while ((extend -= count) > 0);
3240 win32_setmode(fd, oldmode);
3243 /* shrink the file */
3244 win32_lseek(fd, size, SEEK_SET);
3245 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3251 win32_lseek(fd, cur, SEEK_SET);
3254 return chsize(fd, (long)size);
3259 win32_lseek(int fd, Off_t offset, int origin)
3261 #if defined(WIN64) || defined(USE_LARGE_FILES)
3262 return _lseeki64(fd, offset, origin);
3264 return lseek(fd, (long)offset, origin);
3271 #if defined(WIN64) || defined(USE_LARGE_FILES)
3272 return _telli64(fd);
3279 win32_open(const char *path, int flag, ...)
3286 pmode = va_arg(ap, int);
3289 if (stricmp(path, "/dev/null")==0)
3292 aTHXa(PERL_GET_THX);
3293 return open(PerlDir_mapA(path), flag, pmode);
3296 /* close() that understands socket */
3297 extern int my_close(int); /* in win32sck.c */
3302 #ifdef WIN32_NO_SOCKETS
3305 return my_close(fd);
3316 win32_isatty(int fd)
3318 /* The Microsoft isatty() function returns true for *all*
3319 * character mode devices, including "nul". Our implementation
3320 * should only return true if the handle has a console buffer.
3323 HANDLE fh = (HANDLE)_get_osfhandle(fd);
3324 if (fh == (HANDLE)-1) {
3325 /* errno is already set to EBADF */
3329 if (GetConsoleMode(fh, &mode))
3343 win32_dup2(int fd1,int fd2)
3345 return dup2(fd1,fd2);
3349 win32_read(int fd, void *buf, unsigned int cnt)
3351 return read(fd, buf, cnt);
3355 win32_write(int fd, const void *buf, unsigned int cnt)
3357 return write(fd, buf, cnt);
3361 win32_mkdir(const char *dir, int mode)
3364 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3368 win32_rmdir(const char *dir)
3371 return rmdir(PerlDir_mapA(dir));
3375 win32_chdir(const char *dir)
3385 win32_access(const char *path, int mode)
3388 return access(PerlDir_mapA(path), mode);
3392 win32_chmod(const char *path, int mode)
3395 return chmod(PerlDir_mapA(path), mode);
3400 create_command_line(char *cname, STRLEN clen, const char * const *args)
3407 bool bat_file = FALSE;
3408 bool cmd_shell = FALSE;
3409 bool dumb_shell = FALSE;
3410 bool extra_quotes = FALSE;
3411 bool quote_next = FALSE;
3414 cname = (char*)args[0];
3416 /* The NT cmd.exe shell has the following peculiarity that needs to be
3417 * worked around. It strips a leading and trailing dquote when any
3418 * of the following is true:
3419 * 1. the /S switch was used
3420 * 2. there are more than two dquotes
3421 * 3. there is a special character from this set: &<>()@^|
3422 * 4. no whitespace characters within the two dquotes
3423 * 5. string between two dquotes isn't an executable file
3424 * To work around this, we always add a leading and trailing dquote
3425 * to the string, if the first argument is either "cmd.exe" or "cmd",
3426 * and there were at least two or more arguments passed to cmd.exe
3427 * (not including switches).
3428 * XXX the above rules (from "cmd /?") don't seem to be applied
3429 * always, making for the convolutions below :-(
3433 clen = strlen(cname);
3436 && (stricmp(&cname[clen-4], ".bat") == 0
3437 || (stricmp(&cname[clen-4], ".cmd") == 0)))
3443 char *exe = strrchr(cname, '/');
3444 char *exe2 = strrchr(cname, '\\');
3451 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3455 else if (stricmp(exe, "command.com") == 0
3456 || stricmp(exe, "command") == 0)
3463 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3464 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3465 STRLEN curlen = strlen(arg);
3466 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3467 len += 2; /* assume quoting needed (worst case) */
3469 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3471 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3474 Newx(cmd, len, char);
3479 extra_quotes = TRUE;
3482 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3484 STRLEN curlen = strlen(arg);
3486 /* we want to protect empty arguments and ones with spaces with
3487 * dquotes, but only if they aren't already there */
3492 else if (quote_next) {
3493 /* see if it really is multiple arguments pretending to
3494 * be one and force a set of quotes around it */
3495 if (*find_next_space(arg))
3498 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3500 while (i < curlen) {
3501 if (isSPACE(arg[i])) {
3504 else if (arg[i] == '"') {
3528 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3529 && stricmp(arg+curlen-2, "/c") == 0)
3531 /* is there a next argument? */
3532 if (args[index+1]) {
3533 /* are there two or more next arguments? */
3534 if (args[index+2]) {
3536 extra_quotes = TRUE;
3539 /* single argument, force quoting if it has spaces */
3555 qualified_path(const char *cmd)
3558 char *fullcmd, *curfullcmd;
3564 fullcmd = (char*)cmd;
3566 if (*fullcmd == '/' || *fullcmd == '\\')
3575 pathstr = PerlEnv_getenv("PATH");
3577 /* worst case: PATH is a single directory; we need additional space
3578 * to append "/", ".exe" and trailing "\0" */
3579 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3580 curfullcmd = fullcmd;
3585 /* start by appending the name to the current prefix */
3586 strcpy(curfullcmd, cmd);
3587 curfullcmd += cmdlen;
3589 /* if it doesn't end with '.', or has no extension, try adding
3590 * a trailing .exe first */
3591 if (cmd[cmdlen-1] != '.'
3592 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3594 strcpy(curfullcmd, ".exe");
3595 res = GetFileAttributes(fullcmd);
3596 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3601 /* that failed, try the bare name */
3602 res = GetFileAttributes(fullcmd);
3603 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3606 /* quit if no other path exists, or if cmd already has path */
3607 if (!pathstr || !*pathstr || has_slash)
3610 /* skip leading semis */
3611 while (*pathstr == ';')
3614 /* build a new prefix from scratch */
3615 curfullcmd = fullcmd;
3616 while (*pathstr && *pathstr != ';') {
3617 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3618 pathstr++; /* skip initial '"' */
3619 while (*pathstr && *pathstr != '"') {
3620 *curfullcmd++ = *pathstr++;
3623 pathstr++; /* skip trailing '"' */
3626 *curfullcmd++ = *pathstr++;
3630 pathstr++; /* skip trailing semi */
3631 if (curfullcmd > fullcmd /* append a dir separator */
3632 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3634 *curfullcmd++ = '\\';
3642 /* The following are just place holders.
3643 * Some hosts may provide and environment that the OS is
3644 * not tracking, therefore, these host must provide that
3645 * environment and the current directory to CreateProcess
3649 win32_get_childenv(void)
3655 win32_free_childenv(void* d)
3660 win32_clearenv(void)
3662 char *envv = GetEnvironmentStrings();
3666 char *end = strchr(cur,'=');
3667 if (end && end != cur) {
3669 SetEnvironmentVariable(cur, NULL);
3671 cur = end + strlen(end+1)+2;
3673 else if ((len = strlen(cur)))
3676 FreeEnvironmentStrings(envv);
3680 win32_get_childdir(void)
3683 char szfilename[MAX_PATH+1];
3685 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
3686 Newx(ptr, strlen(szfilename)+1, char);
3687 strcpy(ptr, szfilename);
3692 win32_free_childdir(char* d)
3698 /* XXX this needs to be made more compatible with the spawnvp()
3699 * provided by the various RTLs. In particular, searching for
3700 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
3701 * This doesn't significantly affect perl itself, because we
3702 * always invoke things using PERL5SHELL if a direct attempt to
3703 * spawn the executable fails.
3705 * XXX splitting and rejoining the commandline between do_aspawn()
3706 * and win32_spawnvp() could also be avoided.
3710 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
3712 #ifdef USE_RTL_SPAWNVP
3713 return _spawnvp(mode, cmdname, (char * const *)argv);
3715 return do_spawnvp_handles(mode, cmdname, argv, NULL);
3720 do_spawnvp_handles(int mode, const char *cmdname, const char *const *argv,
3721 const int *handles) {
3727 STARTUPINFO StartupInfo;
3728 PROCESS_INFORMATION ProcessInformation;
3731 char *fullcmd = NULL;
3732 char *cname = (char *)cmdname;
3736 clen = strlen(cname);
3737 /* if command name contains dquotes, must remove them */
3738 if (strchr(cname, '"')) {
3740 Newx(cname,clen+1,char);
3753 cmd = create_command_line(cname, clen, argv);
3755 aTHXa(PERL_GET_THX);
3756 env = PerlEnv_get_childenv();
3757 dir = PerlEnv_get_childdir();
3760 case P_NOWAIT: /* asynch + remember result */
3761 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
3766 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
3769 create |= CREATE_NEW_PROCESS_GROUP;
3772 case P_WAIT: /* synchronous execution */
3774 default: /* invalid mode */
3780 memset(&StartupInfo,0,sizeof(StartupInfo));
3781 StartupInfo.cb = sizeof(StartupInfo);
3782 memset(&tbl,0,sizeof(tbl));
3783 PerlEnv_get_child_IO(&tbl);
3784 StartupInfo.dwFlags = tbl.dwFlags;
3785 StartupInfo.dwX = tbl.dwX;
3786 StartupInfo.dwY = tbl.dwY;
3787 StartupInfo.dwXSize = tbl.dwXSize;
3788 StartupInfo.dwYSize = tbl.dwYSize;
3789 StartupInfo.dwXCountChars = tbl.dwXCountChars;
3790 StartupInfo.dwYCountChars = tbl.dwYCountChars;
3791 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
3792 StartupInfo.wShowWindow = tbl.wShowWindow;
3793 StartupInfo.hStdInput = handles && handles[0] != -1 ?
3794 (HANDLE)_get_osfhandle(handles[0]) : tbl.childStdIn;
3795 StartupInfo.hStdOutput = handles && handles[1] != -1 ?
3796 (HANDLE)_get_osfhandle(handles[1]) : tbl.childStdOut;
3797 StartupInfo.hStdError = handles && handles[2] != -1 ?
3798 (HANDLE)_get_osfhandle(handles[2]) : tbl.childStdErr;
3799 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
3800 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
3801 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
3803 create |= CREATE_NEW_CONSOLE;
3806 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3808 if (w32_use_showwindow) {
3809 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
3810 StartupInfo.wShowWindow = w32_showwindow;
3813 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
3816 if (!CreateProcess(cname, /* search PATH to find executable */
3817 cmd, /* executable, and its arguments */
3818 NULL, /* process attributes */
3819 NULL, /* thread attributes */
3820 TRUE, /* inherit handles */
3821 create, /* creation flags */
3822 (LPVOID)env, /* inherit environment */
3823 dir, /* inherit cwd */
3825 &ProcessInformation))
3827 /* initial NULL argument to CreateProcess() does a PATH
3828 * search, but it always first looks in the directory
3829 * where the current process was started, which behavior
3830 * is undesirable for backward compatibility. So we
3831 * jump through our own hoops by picking out the path
3832 * we really want it to use. */
3834 fullcmd = qualified_path(cname);
3836 if (cname != cmdname)
3839 DEBUG_p(PerlIO_printf(Perl_debug_log,
3840 "Retrying [%s] with same args\n",
3850 if (mode == P_NOWAIT) {
3851 /* asynchronous spawn -- store handle, return PID */
3852 ret = (int)ProcessInformation.dwProcessId;
3854 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
3855 w32_child_pids[w32_num_children] = (DWORD)ret;
3860 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
3861 /* FIXME: if msgwait returned due to message perhaps forward the
3862 "signal" to the process
3864 GetExitCodeProcess(ProcessInformation.hProcess, &status);
3866 CloseHandle(ProcessInformation.hProcess);
3869 CloseHandle(ProcessInformation.hThread);
3872 PerlEnv_free_childenv(env);
3873 PerlEnv_free_childdir(dir);
3875 if (cname != cmdname)
3881 win32_execv(const char *cmdname, const char *const *argv)
3885 /* if this is a pseudo-forked child, we just want to spawn
3886 * the new program, and return */
3888 return _spawnv(P_WAIT, cmdname, argv);
3890 return _execv(cmdname, argv);
3894 win32_execvp(const char *cmdname, const char *const *argv)
3898 /* if this is a pseudo-forked child, we just want to spawn
3899 * the new program, and return */
3900 if (w32_pseudo_id) {
3901 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
3910 return _execvp(cmdname, argv);
3914 win32_perror(const char *str)
3920 win32_setbuf(FILE *pf, char *buf)
3926 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
3928 return setvbuf(pf, buf, type, size);
3932 win32_flushall(void)
3938 win32_fcloseall(void)
3944 win32_fgets(char *s, int n, FILE *pf)
3946 return fgets(s, n, pf);
3956 win32_fgetc(FILE *pf)
3962 win32_putc(int c, FILE *pf)
3968 win32_puts(const char *s)
3980 win32_putchar(int c)
3987 #ifndef USE_PERL_SBRK
3989 static char *committed = NULL; /* XXX threadead */
3990 static char *base = NULL; /* XXX threadead */
3991 static char *reserved = NULL; /* XXX threadead */
3992 static char *brk = NULL; /* XXX threadead */
3993 static DWORD pagesize = 0; /* XXX threadead */
3996 sbrk(ptrdiff_t need)
4001 GetSystemInfo(&info);
4002 /* Pretend page size is larger so we don't perpetually
4003 * call the OS to commit just one page ...
4005 pagesize = info.dwPageSize << 3;
4007 if (brk+need >= reserved)
4009 DWORD size = brk+need-reserved;
4011 char *prev_committed = NULL;
4012 if (committed && reserved && committed < reserved)
4014 /* Commit last of previous chunk cannot span allocations */
4015 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
4018 /* Remember where we committed from in case we want to decommit later */
4019 prev_committed = committed;
4020 committed = reserved;
4023 /* Reserve some (more) space
4024 * Contiguous blocks give us greater efficiency, so reserve big blocks -
4025 * this is only address space not memory...
4026 * Note this is a little sneaky, 1st call passes NULL as reserved
4027 * so lets system choose where we start, subsequent calls pass
4028 * the old end address so ask for a contiguous block
4031 if (size < 64*1024*1024)
4032 size = 64*1024*1024;
4033 size = ((size + pagesize - 1) / pagesize) * pagesize;
4034 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
4037 reserved = addr+size;
4047 /* The existing block could not be extended far enough, so decommit
4048 * anything that was just committed above and start anew */
4051 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
4054 reserved = base = committed = brk = NULL;
4065 if (brk > committed)
4067 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4069 if (committed+size > reserved)
4070 size = reserved-committed;
4071 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4084 win32_malloc(size_t size)
4086 return malloc(size);
4090 win32_calloc(size_t numitems, size_t size)
4092 return calloc(numitems,size);
4096 win32_realloc(void *block, size_t size)
4098 return realloc(block,size);
4102 win32_free(void *block)
4109 win32_open_osfhandle(intptr_t handle, int flags)
4111 return _open_osfhandle(handle, flags);
4115 win32_get_osfhandle(int fd)
4117 return (intptr_t)_get_osfhandle(fd);
4121 win32_fdupopen(FILE *pf)
4126 int fileno = win32_dup(win32_fileno(pf));
4128 /* open the file in the same mode */
4129 if((pf)->_flag & _IOREAD) {
4133 else if((pf)->_flag & _IOWRT) {
4137 else if((pf)->_flag & _IORW) {
4143 /* it appears that the binmode is attached to the
4144 * file descriptor so binmode files will be handled
4147 pfdup = win32_fdopen(fileno, mode);
4149 /* move the file pointer to the same position */
4150 if (!fgetpos(pf, &pos)) {
4151 fsetpos(pfdup, &pos);
4157 win32_dynaload(const char* filename)
4160 char buf[MAX_PATH+1];
4163 /* LoadLibrary() doesn't recognize forward slashes correctly,
4164 * so turn 'em back. */
4165 first = strchr(filename, '/');
4167 STRLEN len = strlen(filename);
4168 if (len <= MAX_PATH) {
4169 strcpy(buf, filename);
4170 filename = &buf[first - filename];
4172 if (*filename == '/')
4173 *(char*)filename = '\\';
4179 aTHXa(PERL_GET_THX);
4180 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4183 XS(w32_SetChildShowWindow)
4186 BOOL use_showwindow = w32_use_showwindow;
4187 /* use "unsigned short" because Perl has redefined "WORD" */
4188 unsigned short showwindow = w32_showwindow;
4191 croak_xs_usage(cv, "[showwindow]");
4193 if (items == 0 || !SvOK(ST(0)))
4194 w32_use_showwindow = FALSE;
4196 w32_use_showwindow = TRUE;
4197 w32_showwindow = (unsigned short)SvIV(ST(0));
4202 ST(0) = sv_2mortal(newSViv(showwindow));
4204 ST(0) = &PL_sv_undef;
4209 Perl_init_os_extras(void)
4212 char *file = __FILE__;
4214 /* Initialize Win32CORE if it has been statically linked. */
4215 #ifndef PERL_IS_MINIPERL
4216 void (*pfn_init)(pTHX);
4217 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
4218 ? GetModuleHandle(NULL)
4219 : w32_perldll_handle);
4220 pfn_init = (void (*)(pTHX))GetProcAddress(module, "init_Win32CORE");
4221 aTHXa(PERL_GET_THX);
4225 aTHXa(PERL_GET_THX);
4228 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4232 win32_signal_context(void)
4237 my_perl = PL_curinterp;
4238 PERL_SET_THX(my_perl);
4242 return PL_curinterp;
4248 win32_ctrlhandler(DWORD dwCtrlType)
4251 dTHXa(PERL_GET_SIG_CONTEXT);
4257 switch(dwCtrlType) {
4258 case CTRL_CLOSE_EVENT:
4259 /* A signal that the system sends to all processes attached to a console when
4260 the user closes the console (either by choosing the Close command from the
4261 console window's System menu, or by choosing the End Task command from the
4264 if (do_raise(aTHX_ 1)) /* SIGHUP */
4265 sig_terminate(aTHX_ 1);
4269 /* A CTRL+c signal was received */
4270 if (do_raise(aTHX_ SIGINT))
4271 sig_terminate(aTHX_ SIGINT);
4274 case CTRL_BREAK_EVENT:
4275 /* A CTRL+BREAK signal was received */
4276 if (do_raise(aTHX_ SIGBREAK))
4277 sig_terminate(aTHX_ SIGBREAK);
4280 case CTRL_LOGOFF_EVENT:
4281 /* A signal that the system sends to all console processes when a user is logging
4282 off. This signal does not indicate which user is logging off, so no
4283 assumptions can be made.
4286 case CTRL_SHUTDOWN_EVENT:
4287 /* A signal that the system sends to all console processes when the system is
4290 if (do_raise(aTHX_ SIGTERM))
4291 sig_terminate(aTHX_ SIGTERM);
4300 #ifdef SET_INVALID_PARAMETER_HANDLER
4301 # include <crtdbg.h>
4312 /* fetch Unicode version of PATH */
4314 wide_path = (WCHAR*)win32_malloc(len*sizeof(WCHAR));
4316 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4318 win32_free(wide_path);
4324 wide_path = (WCHAR*)win32_realloc(wide_path, len*sizeof(WCHAR));
4329 /* convert to ANSI pathnames */
4330 wide_dir = wide_path;
4333 WCHAR *sep = wcschr(wide_dir, ';');
4341 /* remove quotes around pathname */
4342 if (*wide_dir == '"')
4344 wide_len = wcslen(wide_dir);
4345 if (wide_len && wide_dir[wide_len-1] == '"')
4346 wide_dir[wide_len-1] = '\0';
4348 /* append ansi_dir to ansi_path */
4349 ansi_dir = win32_ansipath(wide_dir);
4350 ansi_len = strlen(ansi_dir);
4352 size_t newlen = len + 1 + ansi_len;
4353 ansi_path = (char*)win32_realloc(ansi_path, newlen+1);
4356 ansi_path[len] = ';';
4357 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4362 ansi_path = (char*)win32_malloc(5+len+1);
4365 memcpy(ansi_path, "PATH=", 5);
4366 memcpy(ansi_path+5, ansi_dir, len+1);
4369 win32_free(ansi_dir);
4374 /* Update C RTL environ array. This will only have full effect if
4375 * perl_parse() is later called with `environ` as the `env` argument.
4376 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4378 * We do have to ansify() the PATH before Perl has been fully
4379 * initialized because S_find_script() uses the PATH when perl
4380 * is being invoked with the -S option. This happens before %ENV
4381 * is initialized in S_init_postdump_symbols().
4383 * XXX Is this a bug? Should S_find_script() use the environment
4384 * XXX passed in the `env` arg to parse_perl()?
4387 /* Keep system environment in sync because S_init_postdump_symbols()
4388 * will not call mg_set() if it initializes %ENV from `environ`.
4390 SetEnvironmentVariableA("PATH", ansi_path+5);
4391 win32_free(ansi_path);
4393 win32_free(wide_path);
4397 Perl_win32_init(int *argcp, char ***argvp)
4399 #ifdef SET_INVALID_PARAMETER_HANDLER
4400 _invalid_parameter_handler oldHandler, newHandler;
4401 newHandler = my_invalid_parameter_handler;
4402 oldHandler = _set_invalid_parameter_handler(newHandler);
4403 _CrtSetReportMode(_CRT_ASSERT, 0);
4405 /* Disable floating point errors, Perl will trap the ones we
4406 * care about. VC++ RTL defaults to switching these off
4407 * already, but some RTLs don't. Since we don't
4408 * want to be at the vendor's whim on the default, we set
4409 * it explicitly here.
4411 #if !defined(__GNUC__)
4412 _control87(MCW_EM, MCW_EM);
4416 /* When the manifest resource requests Common-Controls v6 then
4417 * user32.dll no longer registers all the Windows classes used for
4418 * standard controls but leaves some of them to be registered by
4419 * comctl32.dll. InitCommonControls() doesn't do anything but calling
4420 * it makes sure comctl32.dll gets loaded into the process and registers
4421 * the standard control classes. Without this even normal Windows APIs
4422 * like MessageBox() can fail under some versions of Windows XP.
4424 InitCommonControls();
4426 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4427 GetVersionEx(&g_osver);
4429 #ifdef WIN32_DYN_IOINFO_SIZE
4431 Size_t ioinfo_size = _msize((void*)__pioinfo[0]);;
4432 if((SSize_t)ioinfo_size <= 0) { /* -1 is err */
4433 fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */
4436 ioinfo_size /= IOINFO_ARRAY_ELTS;
4437 w32_ioinfo_size = ioinfo_size;
4445 Perl_win32_term(void)
4454 win32_get_child_IO(child_IO_table* ptbl)
4456 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4457 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4458 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4462 win32_signal(int sig, Sighandler_t subcode)
4465 if (sig < SIG_SIZE) {
4466 int save_errno = errno;
4467 Sighandler_t result;
4468 #ifdef SET_INVALID_PARAMETER_HANDLER
4469 /* Silence our invalid parameter handler since we expect to make some
4470 * calls with invalid signal numbers giving a SIG_ERR result. */
4471 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE);
4473 result = signal(sig, subcode);
4474 #ifdef SET_INVALID_PARAMETER_HANDLER
4475 set_silent_invalid_parameter_handler(oldvalue);
4477 aTHXa(PERL_GET_THX);
4478 if (result == SIG_ERR) {
4479 result = w32_sighandler[sig];
4482 w32_sighandler[sig] = subcode;
4491 /* The PerlMessageWindowClass's WindowProc */
4493 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4495 return win32_process_message(hwnd, msg, wParam, lParam) ?
4496 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4499 /* The real message handler. Can be called with
4500 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4501 * that it processes */
4503 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4505 /* BEWARE. The context retrieved using dTHX; is the context of the
4506 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4507 * up to and including WM_CREATE. If it ever happens that you need the
4508 * 'child' context before this, then it needs to be passed into
4509 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4510 * from the lparam of CreateWindow(). It could then be stored/retrieved
4511 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4512 * the dTHX calls here. */
4513 /* XXX For now it is assumed that the overhead of the dTHX; for what
4514 * are relativley infrequent code-paths, is better than the added
4515 * complexity of getting the correct context passed into
4516 * win32_create_message_window() */
4522 case WM_USER_MESSAGE: {
4523 long child = find_pseudo_pid(aTHX_ (int)wParam);
4525 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4532 case WM_USER_KILL: {
4533 /* We use WM_USER_KILL to fake kill() with other signals */
4534 int sig = (int)wParam;
4535 if (do_raise(aTHX_ sig))
4536 sig_terminate(aTHX_ sig);
4542 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4543 if (w32_timerid && w32_timerid==(UINT)wParam) {
4544 KillTimer(w32_message_hwnd, w32_timerid);
4547 /* Now fake a call to signal handler */
4548 if (do_raise(aTHX_ 14))
4549 sig_terminate(aTHX_ 14);
4561 /* Above or other stuff may have set a signal flag, and we may not have
4562 * been called from win32_async_check() (e.g. some other GUI's message
4563 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4564 * handler that die's, and the message loop that calls here is wrapped
4565 * in an eval, then you may well end up with orphaned windows - signals
4566 * are dispatched by win32_async_check() */
4572 win32_create_message_window_class(void)
4574 /* create the window class for "message only" windows */
4578 wc.lpfnWndProc = win32_message_window_proc;
4579 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4580 wc.lpszClassName = "PerlMessageWindowClass";
4582 /* second and subsequent calls will fail, but class
4583 * will already be registered */
4588 win32_create_message_window(void)
4590 win32_create_message_window_class();
4591 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4592 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4595 #ifdef HAVE_INTERP_INTERN
4598 win32_csighandler(int sig)
4601 dTHXa(PERL_GET_SIG_CONTEXT);
4602 Perl_warn(aTHX_ "Got signal %d",sig);
4607 #if defined(__MINGW32__) && defined(__cplusplus)
4608 #define CAST_HWND__(x) (HWND__*)(x)
4610 #define CAST_HWND__(x) x
4614 Perl_sys_intern_init(pTHX)
4618 w32_perlshell_tokens = NULL;
4619 w32_perlshell_vec = (char**)NULL;
4620 w32_perlshell_items = 0;
4621 w32_fdpid = newAV();
4622 Newx(w32_children, 1, child_tab);
4623 w32_num_children = 0;
4624 # ifdef USE_ITHREADS
4626 Newx(w32_pseudo_children, 1, pseudo_child_tab);
4627 w32_num_pseudo_children = 0;
4630 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4632 for (i=0; i < SIG_SIZE; i++) {
4633 w32_sighandler[i] = SIG_DFL;
4635 # ifdef MULTIPLICITY
4636 if (my_perl == PL_curinterp) {
4640 /* Force C runtime signal stuff to set its console handler */
4641 signal(SIGINT,win32_csighandler);
4642 signal(SIGBREAK,win32_csighandler);
4644 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
4645 * flag. This has the side-effect of disabling Ctrl-C events in all
4646 * processes in this group.
4647 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
4648 * with a NULL handler.
4650 SetConsoleCtrlHandler(NULL,FALSE);
4652 /* Push our handler on top */
4653 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
4658 Perl_sys_intern_clear(pTHX)
4660 Safefree(w32_perlshell_tokens);
4661 Safefree(w32_perlshell_vec);
4662 /* NOTE: w32_fdpid is freed by sv_clean_all() */
4663 Safefree(w32_children);
4665 KillTimer(w32_message_hwnd, w32_timerid);
4668 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
4669 DestroyWindow(w32_message_hwnd);
4670 # ifdef MULTIPLICITY
4671 if (my_perl == PL_curinterp) {
4675 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
4677 # ifdef USE_ITHREADS
4678 Safefree(w32_pseudo_children);
4682 # ifdef USE_ITHREADS
4685 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
4687 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
4689 dst->perlshell_tokens = NULL;
4690 dst->perlshell_vec = (char**)NULL;
4691 dst->perlshell_items = 0;
4692 dst->fdpid = newAV();
4693 Newxz(dst->children, 1, child_tab);
4695 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
4697 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4698 dst->poll_count = 0;
4699 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
4701 # endif /* USE_ITHREADS */
4702 #endif /* HAVE_INTERP_INTERN */