3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc.
5 * Portions (c) 1993 Intergraph Corporation. All rights reserved.
7 * You may distribute under the terms of either the GNU General Public
8 * License or the Artistic License, as specified in the README file.
10 #define PERLIO_NOT_STDIO 0
11 #define WIN32_LEAN_AND_MEAN
12 #define WIN32IO_IS_STDIO
16 # define Win32_Winsock
20 # define _WIN32_WINNT 0x0500 /* needed for CreateHardlink() etc. */
26 # define HWND_MESSAGE ((HWND)-3)
29 #ifndef PROCESSOR_ARCHITECTURE_AMD64
30 # define PROCESSOR_ARCHITECTURE_AMD64 9
33 #ifndef WC_NO_BEST_FIT_CHARS
34 # define WC_NO_BEST_FIT_CHARS 0x00000400
43 /* #include "config.h" */
53 #define PERL_NO_GET_CONTEXT
58 /* assert.h conflicts with #define of assert in perl.h */
66 #include <sys/utime.h>
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)
93 # define getlogin g_getlogin
96 /* VS2005 (MSC version 14) provides a mechanism to set an invalid
97 * parameter handler. This functionality is not available in the
98 * 64-bit compiler from the Platform SDK, which unfortunately also
99 * believes itself to be MSC version 14.
101 * There is no #define related to _set_invalid_parameter_handler(),
102 * but we can check for one of the constants defined for
103 * _set_abort_behavior(), which was introduced into stdlib.h at
107 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG)
108 # define SET_INVALID_PARAMETER_HANDLER
111 #ifdef SET_INVALID_PARAMETER_HANDLER
112 static BOOL set_silent_invalid_parameter_handler(BOOL newvalue);
113 static void my_invalid_parameter_handler(const wchar_t* expression,
114 const wchar_t* function, const wchar_t* file,
115 unsigned int line, uintptr_t pReserved);
118 #ifndef WIN32_NO_REGISTRY
119 static char* get_regstr_from(HKEY hkey, const char *valuename, SV **svp);
120 static char* get_regstr(const char *valuename, SV **svp);
123 static char* get_emd_part(SV **prev_pathp, STRLEN *const len,
124 char *trailing, ...);
125 static char* win32_get_xlib(const char *pl,
126 WIN32_NO_REGISTRY_M_(const char *xlib)
127 const char *libname, STRLEN *const len);
129 static BOOL has_shell_metachars(const char *ptr);
130 static long tokenize(const char *str, char **dest, char ***destv);
131 static void get_shell(void);
132 static char* find_next_space(const char *s);
133 static int do_spawn2(pTHX_ const char *cmd, int exectype);
134 static int do_spawn2_handles(pTHX_ const char *cmd, int exectype,
136 static int do_spawnvp_handles(int mode, const char *cmdname,
137 const char * const *argv, const int *handles);
138 static PerlIO * do_popen(const char *mode, const char *command, IV narg,
140 static long find_pid(pTHX_ int pid);
141 static void remove_dead_process(long child);
142 static int terminate_process(DWORD pid, HANDLE process_handle, int sig);
143 static int my_killpg(int pid, int sig);
144 static int my_kill(int pid, int sig);
145 static void out_of_memory(void);
146 static char* wstr_to_str(const wchar_t* wstr);
147 static long filetime_to_clock(PFILETIME ft);
148 static BOOL filetime_from_time(PFILETIME ft, time_t t);
149 static char* create_command_line(char *cname, STRLEN clen,
150 const char * const *args);
151 static char* qualified_path(const char *cmd, bool other_exts);
152 static void ansify_path(void);
153 static LRESULT win32_process_message(HWND hwnd, UINT msg,
154 WPARAM wParam, LPARAM lParam);
157 static long find_pseudo_pid(pTHX_ int pid);
158 static void remove_dead_pseudo_process(long child);
159 static HWND get_hwnd_delay(pTHX, long child, DWORD tries);
162 #ifdef HAVE_INTERP_INTERN
163 static void win32_csighandler(int sig);
167 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
168 char w32_module_name[MAX_PATH+1];
169 #ifdef WIN32_DYN_IOINFO_SIZE
170 Size_t w32_ioinfo_size;/* avoid 0 extend op b4 mul, otherwise could be a U8 */
174 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
176 #ifndef WIN32_NO_REGISTRY
177 /* initialized by Perl_win32_init/PERL_SYS_INIT */
178 static HKEY HKCU_Perl_hnd;
179 static HKEY HKLM_Perl_hnd;
182 #ifdef SET_INVALID_PARAMETER_HANDLER
183 static BOOL silent_invalid_parameter_handler = FALSE;
186 set_silent_invalid_parameter_handler(BOOL newvalue)
188 BOOL oldvalue = silent_invalid_parameter_handler;
190 silent_invalid_parameter_handler = newvalue;
196 my_invalid_parameter_handler(const wchar_t* expression,
197 const wchar_t* function,
203 char* ansi_expression;
206 if (silent_invalid_parameter_handler)
208 ansi_expression = wstr_to_str(expression);
209 ansi_function = wstr_to_str(function);
210 ansi_file = wstr_to_str(file);
211 fprintf(stderr, "Invalid parameter detected in function %s. "
212 "File: %s, line: %d\n", ansi_function, ansi_file, line);
213 fprintf(stderr, "Expression: %s\n", ansi_expression);
214 free(ansi_expression);
222 set_w32_module_name(void)
224 /* this function may be called at DLL_PROCESS_ATTACH time */
226 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
227 ? GetModuleHandle(NULL)
228 : w32_perldll_handle);
230 WCHAR modulename[MAX_PATH];
231 WCHAR fullname[MAX_PATH];
234 DWORD (__stdcall *pfnGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD) =
235 (DWORD (__stdcall *)(LPCWSTR, LPWSTR, DWORD))
236 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameW");
238 GetModuleFileNameW(module, modulename, sizeof(modulename)/sizeof(WCHAR));
240 /* Make sure we get an absolute pathname in case the module was loaded
241 * explicitly by LoadLibrary() with a relative path. */
242 GetFullPathNameW(modulename, sizeof(fullname)/sizeof(WCHAR), fullname, NULL);
244 /* Make sure we start with the long path name of the module because we
245 * later scan for pathname components to match "5.xx" to locate
246 * compatible sitelib directories, and the short pathname might mangle
247 * this path segment (e.g. by removing the dot on NTFS to something
248 * like "5xx~1.yy") */
249 if (pfnGetLongPathNameW)
250 pfnGetLongPathNameW(fullname, fullname, sizeof(fullname)/sizeof(WCHAR));
252 /* remove \\?\ prefix */
253 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0)
254 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR));
256 ansi = win32_ansipath(fullname);
257 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name));
260 /* normalize to forward slashes */
261 ptr = w32_module_name;
269 #ifndef WIN32_NO_REGISTRY
270 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
272 get_regstr_from(HKEY handle, const char *valuename, SV **svp)
274 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
280 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen);
281 if (retval == ERROR_SUCCESS
282 && (type == REG_SZ || type == REG_EXPAND_SZ))
286 *svp = sv_2mortal(newSVpvs(""));
287 SvGROW(*svp, datalen);
288 retval = RegQueryValueEx(handle, valuename, 0, NULL,
289 (PBYTE)SvPVX(*svp), &datalen);
290 if (retval == ERROR_SUCCESS) {
292 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)
304 str = get_regstr_from(HKCU_Perl_hnd, valuename, svp);
311 str = get_regstr_from(HKLM_Perl_hnd, valuename, svp);
317 #endif /* ifndef WIN32_NO_REGISTRY */
319 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
321 get_emd_part(SV **prev_pathp, STRLEN *const len, char *trailing_path, ...)
325 char mod_name[MAX_PATH+1];
331 va_start(ap, trailing_path);
332 strip = va_arg(ap, char *);
334 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
335 baselen = strlen(base);
337 if (!*w32_module_name) {
338 set_w32_module_name();
340 strcpy(mod_name, w32_module_name);
341 ptr = strrchr(mod_name, '/');
342 while (ptr && strip) {
343 /* look for directories to skip back */
346 ptr = strrchr(mod_name, '/');
347 /* avoid stripping component if there is no slash,
348 * or it doesn't match ... */
349 if (!ptr || stricmp(ptr+1, strip) != 0) {
350 /* ... but not if component matches m|5\.$patchlevel.*| */
351 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
352 && strnEQ(strip, base, baselen)
353 && strnEQ(ptr+1, base, baselen)))
359 strip = va_arg(ap, char *);
367 strcpy(++ptr, trailing_path);
369 /* only add directory if it exists */
370 if (GetFileAttributes(mod_name) != (DWORD) -1) {
371 /* directory exists */
374 *prev_pathp = sv_2mortal(newSVpvs(""));
375 else if (SvPVX(*prev_pathp))
376 sv_catpvs(*prev_pathp, ";");
377 sv_catpv(*prev_pathp, mod_name);
379 *len = SvCUR(*prev_pathp);
380 return SvPVX(*prev_pathp);
387 win32_get_privlib(WIN32_NO_REGISTRY_M_(const char *pl) STRLEN *const len)
389 char *stdlib = "lib";
391 #ifndef WIN32_NO_REGISTRY
392 char buffer[MAX_PATH+1];
394 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
395 sprintf(buffer, "%s-%s", stdlib, pl);
396 if (!get_regstr(buffer, &sv))
397 (void)get_regstr(stdlib, &sv);
400 /* $stdlib .= ";$EMD/../../lib" */
401 return get_emd_part(&sv, len, stdlib, ARCHNAME, "bin", NULL);
405 win32_get_xlib(const char *pl, WIN32_NO_REGISTRY_M_(const char *xlib)
406 const char *libname, STRLEN *const len)
408 #ifndef WIN32_NO_REGISTRY
411 char pathstr[MAX_PATH+1];
415 #ifndef WIN32_NO_REGISTRY
416 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
417 sprintf(regstr, "%s-%s", xlib, pl);
418 (void)get_regstr(regstr, &sv1);
422 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
423 sprintf(pathstr, "%s/%s/lib", libname, pl);
424 (void)get_emd_part(&sv1, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
426 #ifndef WIN32_NO_REGISTRY
427 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
428 (void)get_regstr(xlib, &sv2);
432 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
433 sprintf(pathstr, "%s/lib", libname);
434 (void)get_emd_part(&sv2, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
452 win32_get_sitelib(const char *pl, STRLEN *const len)
454 return win32_get_xlib(pl, WIN32_NO_REGISTRY_M_("sitelib") "site", len);
457 #ifndef PERL_VENDORLIB_NAME
458 # define PERL_VENDORLIB_NAME "vendor"
462 win32_get_vendorlib(const char *pl, STRLEN *const len)
464 return win32_get_xlib(pl, WIN32_NO_REGISTRY_M_("vendorlib") PERL_VENDORLIB_NAME, len);
468 has_shell_metachars(const char *ptr)
474 * Scan string looking for redirection (< or >) or pipe
475 * characters (|) that are not in a quoted string.
476 * Shell variable interpolation (%VAR%) can also happen inside strings.
508 #if !defined(PERL_IMPLICIT_SYS)
509 /* since the current process environment is being updated in util.c
510 * the library functions will get the correct environment
513 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
515 PERL_FLUSHALL_FOR_CHILD;
516 return win32_popen(cmd, mode);
520 Perl_my_pclose(pTHX_ PerlIO *fp)
522 return win32_pclose(fp);
526 DllExport unsigned long
529 return (unsigned long)g_osver.dwPlatformId;
538 return -((int)w32_pseudo_id);
543 /* Tokenize a string. Words are null-separated, and the list
544 * ends with a doubled null. Any character (except null and
545 * including backslash) may be escaped by preceding it with a
546 * backslash (the backslash will be stripped).
547 * Returns number of words in result buffer.
550 tokenize(const char *str, char **dest, char ***destv)
552 char *retstart = NULL;
553 char **retvstart = 0;
556 int slen = strlen(str);
559 Newx(ret, slen+2, char);
560 Newx(retv, (slen+3)/2, char*);
568 if (*ret == '\\' && *str)
570 else if (*ret == ' ') {
586 retvstart[items] = NULL;
599 if (!w32_perlshell_tokens) {
600 /* we don't use COMSPEC here for two reasons:
601 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
602 * uncontrolled unportability of the ensuing scripts.
603 * 2. PERL5SHELL could be set to a shell that may not be fit for
604 * interactive use (which is what most programs look in COMSPEC
607 const char* defaultshell = "cmd.exe /x/d/c";
608 const char *usershell = PerlEnv_getenv("PERL5SHELL");
609 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
610 &w32_perlshell_tokens,
616 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
625 PERL_ARGS_ASSERT_DO_ASPAWN;
631 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*);
633 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
638 while (++mark <= sp) {
639 if (*mark && (str = SvPV_nolen(*mark)))
646 status = win32_spawnvp(flag,
647 (const char*)(really ? SvPV_nolen(really) : argv[0]),
648 (const char* const*)argv);
650 if (status < 0 && (eno = errno, (eno == ENOEXEC || eno == ENOENT))) {
651 /* possible shell-builtin, invoke with shell */
653 sh_items = w32_perlshell_items;
655 argv[index+sh_items] = argv[index];
656 while (--sh_items >= 0)
657 argv[sh_items] = w32_perlshell_vec[sh_items];
659 status = win32_spawnvp(flag,
660 (const char*)(really ? SvPV_nolen(really) : argv[0]),
661 (const char* const*)argv);
664 if (flag == P_NOWAIT) {
665 PL_statusvalue = -1; /* >16bits hint for pp_system() */
669 if (ckWARN(WARN_EXEC))
670 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
675 PL_statusvalue = status;
681 /* returns pointer to the next unquoted space or the end of the string */
683 find_next_space(const char *s)
685 bool in_quotes = FALSE;
687 /* ignore doubled backslashes, or backslash+quote */
688 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) {
691 /* keep track of when we're within quotes */
692 else if (*s == '"') {
694 in_quotes = !in_quotes;
696 /* break it up only at spaces that aren't in quotes */
697 else if (!in_quotes && isSPACE(*s))
706 do_spawn2(pTHX_ const char *cmd, int exectype) {
707 return do_spawn2_handles(aTHX_ cmd, exectype, NULL);
711 do_spawn2_handles(pTHX_ const char *cmd, int exectype, const int *handles)
717 BOOL needToTry = TRUE;
720 /* Save an extra exec if possible. See if there are shell
721 * metacharacters in it */
722 if (!has_shell_metachars(cmd)) {
723 Newx(argv, strlen(cmd) / 2 + 2, char*);
724 Newx(cmd2, strlen(cmd) + 1, char);
727 for (s = cmd2; *s;) {
728 while (*s && isSPACE(*s))
732 s = find_next_space(s);
740 status = win32_spawnvp(P_WAIT, argv[0],
741 (const char* const*)argv);
743 case EXECF_SPAWN_NOWAIT:
744 status = do_spawnvp_handles(P_NOWAIT, argv[0],
745 (const char* const*)argv, handles);
748 status = win32_execvp(argv[0], (const char* const*)argv);
751 if (status != -1 || errno == 0)
761 Newx(argv, w32_perlshell_items + 2, char*);
762 while (++i < w32_perlshell_items)
763 argv[i] = w32_perlshell_vec[i];
764 argv[i++] = (char *)cmd;
768 status = win32_spawnvp(P_WAIT, argv[0],
769 (const char* const*)argv);
771 case EXECF_SPAWN_NOWAIT:
772 status = do_spawnvp_handles(P_NOWAIT, argv[0],
773 (const char* const*)argv, handles);
776 status = win32_execvp(argv[0], (const char* const*)argv);
782 if (exectype == EXECF_SPAWN_NOWAIT) {
783 PL_statusvalue = -1; /* >16bits hint for pp_system() */
787 if (ckWARN(WARN_EXEC))
788 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s",
789 (exectype == EXECF_EXEC ? "exec" : "spawn"),
790 cmd, strerror(errno));
795 PL_statusvalue = status;
801 Perl_do_spawn(pTHX_ char *cmd)
803 PERL_ARGS_ASSERT_DO_SPAWN;
805 return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
809 Perl_do_spawn_nowait(pTHX_ char *cmd)
811 PERL_ARGS_ASSERT_DO_SPAWN_NOWAIT;
813 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
817 Perl_do_exec(pTHX_ const char *cmd)
819 PERL_ARGS_ASSERT_DO_EXEC;
821 do_spawn2(aTHX_ cmd, EXECF_EXEC);
825 /* The idea here is to read all the directory names into a string table
826 * (separated by nulls) and when one of the other dir functions is called
827 * return the pointer to the current file name.
830 win32_opendir(const char *filename)
836 char scanname[MAX_PATH+3];
837 WCHAR wscanname[sizeof(scanname)];
838 WIN32_FIND_DATAW wFindData;
839 char buffer[MAX_PATH*2];
842 len = strlen(filename);
847 if (len > MAX_PATH) {
848 errno = ENAMETOOLONG;
852 /* Get us a DIR structure */
855 /* Create the search pattern */
856 strcpy(scanname, filename);
858 /* bare drive name means look in cwd for drive */
859 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') {
860 scanname[len++] = '.';
861 scanname[len++] = '/';
863 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') {
864 scanname[len++] = '/';
866 scanname[len++] = '*';
867 scanname[len] = '\0';
869 /* do the FindFirstFile call */
870 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR));
872 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData);
874 if (dirp->handle == INVALID_HANDLE_VALUE) {
875 DWORD err = GetLastError();
876 /* FindFirstFile() fails on empty drives! */
878 case ERROR_FILE_NOT_FOUND:
880 case ERROR_NO_MORE_FILES:
881 case ERROR_PATH_NOT_FOUND:
884 case ERROR_NOT_ENOUGH_MEMORY:
896 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
897 wFindData.cFileName, -1,
898 buffer, sizeof(buffer), NULL, &use_default);
899 if (use_default && *wFindData.cAlternateFileName) {
900 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
901 wFindData.cAlternateFileName, -1,
902 buffer, sizeof(buffer), NULL, NULL);
905 /* now allocate the first part of the string table for
906 * the filenames that we find.
908 idx = strlen(buffer)+1;
913 Newx(dirp->start, dirp->size, char);
914 strcpy(dirp->start, buffer);
916 dirp->end = dirp->curr = dirp->start;
922 /* Readdir just returns the current string pointer and bumps the
923 * string pointer to the nDllExport entry.
925 DllExport struct direct *
926 win32_readdir(DIR *dirp)
931 /* first set up the structure to return */
932 len = strlen(dirp->curr);
933 strcpy(dirp->dirstr.d_name, dirp->curr);
934 dirp->dirstr.d_namlen = len;
937 dirp->dirstr.d_ino = dirp->curr - dirp->start;
939 /* Now set up for the next call to readdir */
940 dirp->curr += len + 1;
941 if (dirp->curr >= dirp->end) {
943 char buffer[MAX_PATH*2];
945 if (dirp->handle == INVALID_HANDLE_VALUE) {
948 /* finding the next file that matches the wildcard
949 * (which should be all of them in this directory!).
952 WIN32_FIND_DATAW wFindData;
953 res = FindNextFileW(dirp->handle, &wFindData);
955 BOOL use_default = FALSE;
956 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
957 wFindData.cFileName, -1,
958 buffer, sizeof(buffer), NULL, &use_default);
959 if (use_default && *wFindData.cAlternateFileName) {
960 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
961 wFindData.cAlternateFileName, -1,
962 buffer, sizeof(buffer), NULL, NULL);
967 long endpos = dirp->end - dirp->start;
968 long newsize = endpos + strlen(buffer) + 1;
969 /* bump the string table size by enough for the
970 * new name and its null terminator */
971 while (newsize > dirp->size) {
972 long curpos = dirp->curr - dirp->start;
973 Renew(dirp->start, dirp->size * 2, char);
975 dirp->curr = dirp->start + curpos;
977 strcpy(dirp->start + endpos, buffer);
978 dirp->end = dirp->start + newsize;
983 if (dirp->handle != INVALID_HANDLE_VALUE) {
984 FindClose(dirp->handle);
985 dirp->handle = INVALID_HANDLE_VALUE;
989 return &(dirp->dirstr);
995 /* Telldir returns the current string pointer position */
997 win32_telldir(DIR *dirp)
999 return dirp->curr ? (dirp->curr - dirp->start) : -1;
1003 /* Seekdir moves the string pointer to a previously saved position
1004 * (returned by telldir).
1007 win32_seekdir(DIR *dirp, long loc)
1009 dirp->curr = loc == -1 ? NULL : dirp->start + loc;
1012 /* Rewinddir resets the string pointer to the start */
1014 win32_rewinddir(DIR *dirp)
1016 dirp->curr = dirp->start;
1019 /* free the memory allocated by opendir */
1021 win32_closedir(DIR *dirp)
1023 if (dirp->handle != INVALID_HANDLE_VALUE)
1024 FindClose(dirp->handle);
1025 Safefree(dirp->start);
1030 /* duplicate a open DIR* for interpreter cloning */
1032 win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param)
1034 PerlInterpreter *const from = param->proto_perl;
1035 PerlInterpreter *const to = (PerlInterpreter *)PERL_GET_THX;
1040 /* switch back to original interpreter because win32_readdir()
1041 * might Renew(dirp->start).
1047 /* mark current position; read all remaining entries into the
1048 * cache, and then restore to current position.
1050 pos = win32_telldir(dirp);
1051 while (win32_readdir(dirp)) {
1052 /* read all entries into cache */
1054 win32_seekdir(dirp, pos);
1056 /* switch back to new interpreter to allocate new DIR structure */
1062 memcpy(dup, dirp, sizeof(DIR));
1064 Newx(dup->start, dirp->size, char);
1065 memcpy(dup->start, dirp->start, dirp->size);
1067 dup->end = dup->start + (dirp->end - dirp->start);
1069 dup->curr = dup->start + (dirp->curr - dirp->start);
1081 * Just pretend that everyone is a superuser. NT will let us know if
1082 * we don\'t really have permission to do something.
1085 #define ROOT_UID ((uid_t)0)
1086 #define ROOT_GID ((gid_t)0)
1115 return (auid == ROOT_UID ? 0 : -1);
1121 return (agid == ROOT_GID ? 0 : -1);
1128 char *buf = w32_getlogin_buffer;
1129 DWORD size = sizeof(w32_getlogin_buffer);
1130 if (GetUserName(buf,&size))
1136 chown(const char *path, uid_t owner, gid_t group)
1143 * XXX this needs strengthening (for PerlIO)
1146 #if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4
1147 int mkstemp(const char *path)
1150 char buf[MAX_PATH+1];
1154 if (i++ > 10) { /* give up */
1158 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
1162 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
1170 find_pid(pTHX_ int pid)
1172 long child = w32_num_children;
1173 while (--child >= 0) {
1174 if ((int)w32_child_pids[child] == pid)
1181 remove_dead_process(long child)
1185 CloseHandle(w32_child_handles[child]);
1186 Move(&w32_child_handles[child+1], &w32_child_handles[child],
1187 (w32_num_children-child-1), HANDLE);
1188 Move(&w32_child_pids[child+1], &w32_child_pids[child],
1189 (w32_num_children-child-1), DWORD);
1196 find_pseudo_pid(pTHX_ int pid)
1198 long child = w32_num_pseudo_children;
1199 while (--child >= 0) {
1200 if ((int)w32_pseudo_child_pids[child] == pid)
1207 remove_dead_pseudo_process(long child)
1211 CloseHandle(w32_pseudo_child_handles[child]);
1212 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
1213 (w32_num_pseudo_children-child-1), HANDLE);
1214 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
1215 (w32_num_pseudo_children-child-1), DWORD);
1216 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
1217 (w32_num_pseudo_children-child-1), HWND);
1218 Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child],
1219 (w32_num_pseudo_children-child-1), char);
1220 w32_num_pseudo_children--;
1225 win32_wait_for_children(pTHX)
1227 if (w32_pseudo_children && w32_num_pseudo_children) {
1230 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1232 for (child = 0; child < w32_num_pseudo_children; ++child) {
1233 if (!w32_pseudo_child_sigterm[child])
1234 handles[count++] = w32_pseudo_child_handles[child];
1236 /* XXX should use MsgWaitForMultipleObjects() to continue
1237 * XXX processing messages while we wait.
1239 WaitForMultipleObjects(count, handles, TRUE, INFINITE);
1241 while (w32_num_pseudo_children)
1242 CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]);
1248 terminate_process(DWORD pid, HANDLE process_handle, int sig)
1252 /* "Does process exist?" use of kill */
1255 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid))
1260 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
1263 default: /* For now be backwards compatible with perl 5.6 */
1265 /* Note that we will only be able to kill processes owned by the
1266 * current process owner, even when we are running as an administrator.
1267 * To kill processes of other owners we would need to set the
1268 * 'SeDebugPrivilege' privilege before obtaining the process handle.
1270 if (TerminateProcess(process_handle, sig))
1277 /* returns number of processes killed */
1279 my_killpg(int pid, int sig)
1281 HANDLE process_handle;
1282 HANDLE snapshot_handle;
1285 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1286 if (process_handle == NULL)
1289 killed += terminate_process(pid, process_handle, sig);
1291 snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1292 if (snapshot_handle != INVALID_HANDLE_VALUE) {
1293 PROCESSENTRY32 entry;
1295 entry.dwSize = sizeof(entry);
1296 if (Process32First(snapshot_handle, &entry)) {
1298 if (entry.th32ParentProcessID == (DWORD)pid)
1299 killed += my_killpg(entry.th32ProcessID, sig);
1300 entry.dwSize = sizeof(entry);
1302 while (Process32Next(snapshot_handle, &entry));
1304 CloseHandle(snapshot_handle);
1306 CloseHandle(process_handle);
1310 /* returns number of processes killed */
1312 my_kill(int pid, int sig)
1315 HANDLE process_handle;
1318 return my_killpg(pid, -sig);
1320 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1321 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
1322 if (process_handle != NULL) {
1323 retval = terminate_process(pid, process_handle, sig);
1324 CloseHandle(process_handle);
1330 /* Get a child pseudo-process HWND, with retrying and delaying/yielding.
1331 * The "tries" parameter is the number of retries to make, with a Sleep(1)
1332 * (waiting and yielding the time slot) between each try. Specifying 0 causes
1333 * only Sleep(0) (no waiting and potentially no yielding) to be used, so is not
1335 * Returns an hwnd != INVALID_HANDLE_VALUE (so be aware that NULL can be
1336 * returned) or croaks if the child pseudo-process doesn't schedule and deliver
1337 * a HWND in the time period allowed.
1340 get_hwnd_delay(pTHX, long child, DWORD tries)
1342 HWND hwnd = w32_pseudo_child_message_hwnds[child];
1343 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1345 /* Pseudo-process has not yet properly initialized since hwnd isn't set.
1346 * Fast sleep: On some NT kernels/systems, a Sleep(0) won't deschedule a
1347 * thread 100% of the time since threads are attached to a CPU for NUMA and
1348 * caching reasons, and the child thread was attached to a different CPU
1349 * therefore there is no workload on that CPU and Sleep(0) returns control
1350 * without yielding the time slot.
1351 * https://github.com/Perl/perl5/issues/11267
1354 win32_async_check(aTHX);
1355 hwnd = w32_pseudo_child_message_hwnds[child];
1356 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1359 unsigned int count = 0;
1360 /* No Sleep(1) if tries==0, just fail instead if we get this far. */
1361 while (count++ < tries) {
1363 win32_async_check(aTHX);
1364 hwnd = w32_pseudo_child_message_hwnds[child];
1365 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1369 Perl_croak(aTHX_ "panic: child pseudo-process was never scheduled");
1374 win32_kill(int pid, int sig)
1380 /* it is a pseudo-forked child */
1381 child = find_pseudo_pid(aTHX_ -pid);
1383 HANDLE hProcess = w32_pseudo_child_handles[child];
1386 /* "Does process exist?" use of kill */
1390 /* kill -9 style un-graceful exit */
1391 /* Do a wait to make sure child starts and isn't in DLL
1393 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1394 if (TerminateThread(hProcess, sig)) {
1395 /* Allow the scheduler to finish cleaning up the other
1397 * Otherwise, if we ExitProcess() before another context
1398 * switch happens we will end up with a process exit
1399 * code of "sig" instead of our own exit status.
1400 * https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
1403 remove_dead_pseudo_process(child);
1410 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1411 /* We fake signals to pseudo-processes using Win32
1413 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) ||
1414 PostThreadMessage(-pid, WM_USER_KILL, sig, 0))
1416 /* Don't wait for child process to terminate after we send a
1417 * SIGTERM because the child may be blocked in a system call
1418 * and never receive the signal.
1420 if (sig == SIGTERM) {
1422 w32_pseudo_child_sigterm[child] = 1;
1424 /* It might be us ... */
1436 child = find_pid(aTHX_ pid);
1438 if (my_kill(pid, sig)) {
1440 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) &&
1441 exitcode != STILL_ACTIVE)
1443 remove_dead_process(child);
1449 if (my_kill(pid, sig))
1458 win32_stat(const char *path, Stat_t *sbuf)
1460 char buffer[MAX_PATH+1];
1461 int l = strlen(path);
1465 BOOL expect_dir = FALSE;
1468 switch(path[l - 1]) {
1469 /* FindFirstFile() and stat() are buggy with a trailing
1470 * slashes, except for the root directory of a drive */
1473 if (l > sizeof(buffer)) {
1474 errno = ENAMETOOLONG;
1478 strncpy(buffer, path, l);
1479 /* remove additional trailing slashes */
1480 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\'))
1482 /* add back slash if we otherwise end up with just a drive letter */
1483 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':')
1490 /* FindFirstFile() is buggy with "x:", so add a dot :-( */
1492 if (l == 2 && isALPHA(path[0])) {
1493 buffer[0] = path[0];
1504 path = PerlDir_mapA(path);
1507 if (!w32_sloppystat) {
1508 /* We must open & close the file once; otherwise file attribute changes */
1509 /* might not yet have propagated to "other" hard links of the same file. */
1510 /* This also gives us an opportunity to determine the number of links. */
1511 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1512 if (handle != INVALID_HANDLE_VALUE) {
1513 BY_HANDLE_FILE_INFORMATION bhi;
1514 if (GetFileInformationByHandle(handle, &bhi))
1515 nlink = bhi.nNumberOfLinks;
1516 CloseHandle(handle);
1519 DWORD err = GetLastError();
1520 /* very common case, skip CRT stat and its also failing syscalls */
1521 if(err == ERROR_FILE_NOT_FOUND) {
1528 /* path will be mapped correctly above */
1529 res = _stati64(path, sbuf);
1530 sbuf->st_nlink = nlink;
1533 /* CRT is buggy on sharenames, so make sure it really isn't.
1534 * XXX using GetFileAttributesEx() will enable us to set
1535 * sbuf->st_*time (but note that's not available on the
1536 * Windows of 1995) */
1537 DWORD r = GetFileAttributesA(path);
1538 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1539 /* sbuf may still contain old garbage since stat() failed */
1540 Zero(sbuf, 1, Stat_t);
1541 sbuf->st_mode = S_IFDIR | S_IREAD;
1543 if (!(r & FILE_ATTRIBUTE_READONLY))
1544 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1549 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1550 && (path[2] == '\\' || path[2] == '/'))
1552 /* The drive can be inaccessible, some _stat()s are buggy */
1553 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1558 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1562 if (S_ISDIR(sbuf->st_mode)) {
1563 /* Ensure the "write" bit is switched off in the mode for
1564 * directories with the read-only attribute set. Some compilers
1565 * switch it on for directories, which is technically correct
1566 * (directories are indeed always writable unless denied by DACLs),
1567 * but we want stat() and -w to reflect the state of the read-only
1568 * attribute for symmetry with chmod(). */
1569 DWORD r = GetFileAttributesA(path);
1570 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
1571 sbuf->st_mode &= ~S_IWRITE;
1578 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1579 #define SKIP_SLASHES(s) \
1581 while (*(s) && isSLASH(*(s))) \
1584 #define COPY_NONSLASHES(d,s) \
1586 while (*(s) && !isSLASH(*(s))) \
1590 /* Find the longname of a given path. path is destructively modified.
1591 * It should have space for at least MAX_PATH characters. */
1593 win32_longpath(char *path)
1595 WIN32_FIND_DATA fdata;
1597 char tmpbuf[MAX_PATH+1];
1598 char *tmpstart = tmpbuf;
1605 if (isALPHA(path[0]) && path[1] == ':') {
1607 *tmpstart++ = path[0];
1611 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1613 *tmpstart++ = path[0];
1614 *tmpstart++ = path[1];
1615 SKIP_SLASHES(start);
1616 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1618 *tmpstart++ = *start++;
1619 SKIP_SLASHES(start);
1620 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1625 /* copy initial slash, if any */
1626 if (isSLASH(*start)) {
1627 *tmpstart++ = *start++;
1629 SKIP_SLASHES(start);
1632 /* FindFirstFile() expands "." and "..", so we need to pass
1633 * those through unmolested */
1635 && (!start[1] || isSLASH(start[1])
1636 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1638 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1643 /* if this is the end, bust outta here */
1647 /* now we're at a non-slash; walk up to next slash */
1648 while (*start && !isSLASH(*start))
1651 /* stop and find full name of component */
1654 fhand = FindFirstFile(path,&fdata);
1656 if (fhand != INVALID_HANDLE_VALUE) {
1657 STRLEN len = strlen(fdata.cFileName);
1658 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1659 strcpy(tmpstart, fdata.cFileName);
1670 /* failed a step, just return without side effects */
1671 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1676 strcpy(path,tmpbuf);
1690 win32_croak_not_implemented(const char * fname)
1692 PERL_ARGS_ASSERT_WIN32_CROAK_NOT_IMPLEMENTED;
1694 Perl_croak_nocontext("%s not implemented!\n", fname);
1697 /* Converts a wide character (UTF-16) string to the Windows ANSI code page,
1698 * potentially using the system's default replacement character for any
1699 * unrepresentable characters. The caller must free() the returned string. */
1701 wstr_to_str(const wchar_t* wstr)
1703 BOOL used_default = FALSE;
1704 size_t wlen = wcslen(wstr) + 1;
1705 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1706 NULL, 0, NULL, NULL);
1707 char* str = (char*)malloc(len);
1710 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1711 str, len, NULL, &used_default);
1715 /* The win32_ansipath() function takes a Unicode filename and converts it
1716 * into the current Windows codepage. If some characters cannot be mapped,
1717 * then it will convert the short name instead.
1719 * The buffer to the ansi pathname must be freed with win32_free() when it
1720 * is no longer needed.
1722 * The argument to win32_ansipath() must exist before this function is
1723 * called; otherwise there is no way to determine the short path name.
1725 * Ideas for future refinement:
1726 * - Only convert those segments of the path that are not in the current
1727 * codepage, but leave the other segments in their long form.
1728 * - If the resulting name is longer than MAX_PATH, start converting
1729 * additional path segments into short names until the full name
1730 * is shorter than MAX_PATH. Shorten the filename part last!
1733 win32_ansipath(const WCHAR *widename)
1736 BOOL use_default = FALSE;
1737 size_t widelen = wcslen(widename)+1;
1738 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1739 NULL, 0, NULL, NULL);
1740 name = (char*)win32_malloc(len);
1744 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1745 name, len, NULL, &use_default);
1747 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1749 WCHAR *shortname = (WCHAR*)win32_malloc(shortlen*sizeof(WCHAR));
1752 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1754 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1755 NULL, 0, NULL, NULL);
1756 name = (char*)win32_realloc(name, len);
1759 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1760 name, len, NULL, NULL);
1761 win32_free(shortname);
1767 /* the returned string must be freed with win32_freeenvironmentstrings which is
1768 * implemented as a macro
1769 * void win32_freeenvironmentstrings(void* block)
1772 win32_getenvironmentstrings(void)
1774 LPWSTR lpWStr, lpWTmp;
1776 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1778 /* Get the process environment strings */
1779 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1780 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1781 env_len = wcslen(lpWTmp);
1782 /* calculate the size of the environment strings */
1783 wenvstrings_len += env_len + 1;
1786 /* Get the number of bytes required to store the ACP encoded string */
1787 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1788 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL);
1789 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1793 /* Convert the string from UTF-16 encoding to ACP encoding */
1794 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1795 aenvstrings_len, NULL, NULL);
1797 FreeEnvironmentStringsW(lpWStr);
1803 win32_getenv(const char *name)
1810 needlen = GetEnvironmentVariableA(name,NULL,0);
1812 curitem = sv_2mortal(newSVpvs(""));
1814 SvGROW(curitem, needlen+1);
1815 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1817 } while (needlen >= SvLEN(curitem));
1818 SvCUR_set(curitem, needlen);
1821 last_err = GetLastError();
1822 if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
1823 /* It appears the variable is in the env, but the Win32 API
1824 doesn't have a canned way of getting it. So we fall back to
1825 grabbing the whole env and pulling this value out if possible */
1826 char *envv = GetEnvironmentStrings();
1830 char *end = strchr(cur,'=');
1831 if (end && end != cur) {
1833 if (strEQ(cur,name)) {
1834 curitem = sv_2mortal(newSVpv(end+1,0));
1839 cur = end + strlen(end+1)+2;
1841 else if ((len = strlen(cur)))
1844 FreeEnvironmentStrings(envv);
1846 #ifndef WIN32_NO_REGISTRY
1848 /* last ditch: allow any environment variables that begin with 'PERL'
1849 to be obtained from the registry, if found there */
1850 if (strBEGINs(name, "PERL"))
1851 (void)get_regstr(name, &curitem);
1855 if (curitem && SvCUR(curitem))
1856 return SvPVX(curitem);
1862 win32_putenv(const char *name)
1869 curitem = (char *) win32_malloc(strlen(name)+1);
1870 strcpy(curitem, name);
1871 val = strchr(curitem, '=');
1873 /* The sane way to deal with the environment.
1874 * Has these advantages over putenv() & co.:
1875 * * enables us to store a truly empty value in the
1876 * environment (like in UNIX).
1877 * * we don't have to deal with RTL globals, bugs and leaks
1878 * (specifically, see http://support.microsoft.com/kb/235601).
1880 * Why you may want to use the RTL environment handling
1881 * (previously enabled by USE_WIN32_RTL_ENV):
1882 * * environ[] and RTL functions will not reflect changes,
1883 * which might be an issue if extensions want to access
1884 * the env. via RTL. This cuts both ways, since RTL will
1885 * not see changes made by extensions that call the Win32
1886 * functions directly, either.
1890 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1893 win32_free(curitem);
1899 filetime_to_clock(PFILETIME ft)
1901 __int64 qw = ft->dwHighDateTime;
1903 qw |= ft->dwLowDateTime;
1904 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1909 win32_times(struct tms *timebuf)
1914 clock_t process_time_so_far = clock();
1915 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1917 timebuf->tms_utime = filetime_to_clock(&user);
1918 timebuf->tms_stime = filetime_to_clock(&kernel);
1919 timebuf->tms_cutime = 0;
1920 timebuf->tms_cstime = 0;
1922 /* That failed - e.g. Win95 fallback to clock() */
1923 timebuf->tms_utime = process_time_so_far;
1924 timebuf->tms_stime = 0;
1925 timebuf->tms_cutime = 0;
1926 timebuf->tms_cstime = 0;
1928 return process_time_so_far;
1931 /* fix utime() so it works on directories in NT */
1933 filetime_from_time(PFILETIME pFileTime, time_t Time)
1935 struct tm *pTM = localtime(&Time);
1936 SYSTEMTIME SystemTime;
1942 SystemTime.wYear = pTM->tm_year + 1900;
1943 SystemTime.wMonth = pTM->tm_mon + 1;
1944 SystemTime.wDay = pTM->tm_mday;
1945 SystemTime.wHour = pTM->tm_hour;
1946 SystemTime.wMinute = pTM->tm_min;
1947 SystemTime.wSecond = pTM->tm_sec;
1948 SystemTime.wMilliseconds = 0;
1950 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1951 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1955 win32_unlink(const char *filename)
1961 filename = PerlDir_mapA(filename);
1962 attrs = GetFileAttributesA(filename);
1963 if (attrs == 0xFFFFFFFF) {
1967 if (attrs & FILE_ATTRIBUTE_READONLY) {
1968 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1969 ret = unlink(filename);
1971 (void)SetFileAttributesA(filename, attrs);
1974 ret = unlink(filename);
1979 win32_utime(const char *filename, struct utimbuf *times)
1986 struct utimbuf TimeBuffer;
1989 filename = PerlDir_mapA(filename);
1990 rc = utime(filename, times);
1992 /* EACCES: path specifies directory or readonly file */
1993 if (rc == 0 || errno != EACCES)
1996 if (times == NULL) {
1997 times = &TimeBuffer;
1998 time(×->actime);
1999 times->modtime = times->actime;
2002 /* This will (and should) still fail on readonly files */
2003 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
2004 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
2005 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2006 if (handle == INVALID_HANDLE_VALUE)
2009 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
2010 filetime_from_time(&ftAccess, times->actime) &&
2011 filetime_from_time(&ftWrite, times->modtime) &&
2012 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
2017 CloseHandle(handle);
2022 unsigned __int64 ft_i64;
2027 #define Const64(x) x##LL
2029 #define Const64(x) x##i64
2031 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
2032 #define EPOCH_BIAS Const64(116444736000000000)
2034 /* NOTE: This does not compute the timezone info (doing so can be expensive,
2035 * and appears to be unsupported even by glibc) */
2037 win32_gettimeofday(struct timeval *tp, void *not_used)
2041 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
2042 GetSystemTimeAsFileTime(&ft.ft_val);
2044 /* seconds since epoch */
2045 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
2047 /* microseconds remaining */
2048 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
2054 win32_uname(struct utsname *name)
2056 struct hostent *hep;
2057 STRLEN nodemax = sizeof(name->nodename)-1;
2060 switch (g_osver.dwPlatformId) {
2061 case VER_PLATFORM_WIN32_WINDOWS:
2062 strcpy(name->sysname, "Windows");
2064 case VER_PLATFORM_WIN32_NT:
2065 strcpy(name->sysname, "Windows NT");
2067 case VER_PLATFORM_WIN32s:
2068 strcpy(name->sysname, "Win32s");
2071 strcpy(name->sysname, "Win32 Unknown");
2076 sprintf(name->release, "%d.%d",
2077 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
2080 sprintf(name->version, "Build %d",
2081 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
2082 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
2083 if (g_osver.szCSDVersion[0]) {
2084 char *buf = name->version + strlen(name->version);
2085 sprintf(buf, " (%s)", g_osver.szCSDVersion);
2089 hep = win32_gethostbyname("localhost");
2091 STRLEN len = strlen(hep->h_name);
2092 if (len <= nodemax) {
2093 strcpy(name->nodename, hep->h_name);
2096 strncpy(name->nodename, hep->h_name, nodemax);
2097 name->nodename[nodemax] = '\0';
2102 if (!GetComputerName(name->nodename, &sz))
2103 *name->nodename = '\0';
2106 /* machine (architecture) */
2111 GetSystemInfo(&info);
2113 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION))
2114 procarch = info.u.s.wProcessorArchitecture;
2116 procarch = info.wProcessorArchitecture;
2119 case PROCESSOR_ARCHITECTURE_INTEL:
2120 arch = "x86"; break;
2121 case PROCESSOR_ARCHITECTURE_IA64:
2122 arch = "ia64"; break;
2123 case PROCESSOR_ARCHITECTURE_AMD64:
2124 arch = "amd64"; break;
2125 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2126 arch = "unknown"; break;
2128 sprintf(name->machine, "unknown(0x%x)", procarch);
2129 arch = name->machine;
2132 if (name->machine != arch)
2133 strcpy(name->machine, arch);
2138 /* Timing related stuff */
2141 do_raise(pTHX_ int sig)
2143 if (sig < SIG_SIZE) {
2144 Sighandler_t handler = w32_sighandler[sig];
2145 if (handler == SIG_IGN) {
2148 else if (handler != SIG_DFL) {
2153 /* Choose correct default behaviour */
2169 /* Tell caller to exit thread/process as appropriate */
2174 sig_terminate(pTHX_ int sig)
2176 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2177 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2184 win32_async_check(pTHX)
2187 HWND hwnd = w32_message_hwnd;
2189 /* Reset w32_poll_count before doing anything else, incase we dispatch
2190 * messages that end up calling back into perl */
2193 if (hwnd != INVALID_HANDLE_VALUE) {
2194 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2195 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2200 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2201 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2203 /* re-post a WM_QUIT message (we'll mark it as read later) */
2204 if(msg.message == WM_QUIT) {
2205 PostQuitMessage((int)msg.wParam);
2209 if(!CallMsgFilter(&msg, MSGF_USER))
2211 TranslateMessage(&msg);
2212 DispatchMessage(&msg);
2217 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2218 * This is necessary when we are being called by win32_msgwait() to
2219 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2220 * message over and over. An example how this can happen is when
2221 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2222 * is generating messages before the process terminated.
2224 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD);
2226 /* Above or other stuff may have set a signal flag */
2233 /* This function will not return until the timeout has elapsed, or until
2234 * one of the handles is ready. */
2236 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2238 /* We may need several goes at this - so compute when we stop */
2240 unsigned __int64 endtime = timeout;
2241 if (timeout != INFINITE) {
2242 GetSystemTimeAsFileTime(&ticks.ft_val);
2243 ticks.ft_i64 /= 10000;
2244 endtime += ticks.ft_i64;
2246 /* This was a race condition. Do not let a non INFINITE timeout to
2247 * MsgWaitForMultipleObjects roll under 0 creating a near
2248 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the
2249 * user who did a CORE perl function with a non infinity timeout,
2250 * sleep for example. This is 64 to 32 truncation minefield.
2252 * This scenario can only be created if the timespan from the return of
2253 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To
2254 * generate the scenario, manual breakpoints in a C debugger are required,
2255 * or a context switch occurred in win32_async_check in PeekMessage, or random
2256 * messages are delivered to the *thread* message queue of the Perl thread
2257 * from another process (msctf.dll doing IPC among its instances, VS debugger
2258 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096].
2260 while (ticks.ft_i64 <= endtime) {
2261 /* if timeout's type is lengthened, remember to split 64b timeout
2262 * into multiple non-infinity runs of MWFMO */
2263 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE,
2264 (DWORD)(endtime - ticks.ft_i64),
2265 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2268 if (result == WAIT_TIMEOUT) {
2269 /* Ran out of time - explicit return of zero to avoid -ve if we
2270 have scheduling issues
2274 if (timeout != INFINITE) {
2275 GetSystemTimeAsFileTime(&ticks.ft_val);
2276 ticks.ft_i64 /= 10000;
2278 if (result == WAIT_OBJECT_0 + count) {
2279 /* Message has arrived - check it */
2280 (void)win32_async_check(aTHX);
2283 if (ticks.ft_i64 > endtime)
2284 endtime = ticks.ft_i64;
2289 /* Not timeout or message - one of handles is ready */
2293 /* If we are past the end say zero */
2294 if (!ticks.ft_i64 || ticks.ft_i64 > endtime)
2296 /* compute time left to wait */
2297 ticks.ft_i64 = endtime - ticks.ft_i64;
2298 /* if more ms than DWORD, then return max DWORD */
2299 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX;
2303 win32_internal_wait(pTHX_ int *status, DWORD timeout)
2305 /* XXX this wait emulation only knows about processes
2306 * spawned via win32_spawnvp(P_NOWAIT, ...).
2309 DWORD exitcode, waitcode;
2312 if (w32_num_pseudo_children) {
2313 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2314 timeout, &waitcode);
2315 /* Time out here if there are no other children to wait for. */
2316 if (waitcode == WAIT_TIMEOUT) {
2317 if (!w32_num_children) {
2321 else if (waitcode != WAIT_FAILED) {
2322 if (waitcode >= WAIT_ABANDONED_0
2323 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2324 i = waitcode - WAIT_ABANDONED_0;
2326 i = waitcode - WAIT_OBJECT_0;
2327 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2328 *status = (int)((exitcode & 0xff) << 8);
2329 retval = (int)w32_pseudo_child_pids[i];
2330 remove_dead_pseudo_process(i);
2337 if (!w32_num_children) {
2342 /* if a child exists, wait for it to die */
2343 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2344 if (waitcode == WAIT_TIMEOUT) {
2347 if (waitcode != WAIT_FAILED) {
2348 if (waitcode >= WAIT_ABANDONED_0
2349 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2350 i = waitcode - WAIT_ABANDONED_0;
2352 i = waitcode - WAIT_OBJECT_0;
2353 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2354 *status = (int)((exitcode & 0xff) << 8);
2355 retval = (int)w32_child_pids[i];
2356 remove_dead_process(i);
2361 errno = GetLastError();
2366 win32_waitpid(int pid, int *status, int flags)
2369 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2372 if (pid == -1) /* XXX threadid == 1 ? */
2373 return win32_internal_wait(aTHX_ status, timeout);
2376 child = find_pseudo_pid(aTHX_ -pid);
2378 HANDLE hThread = w32_pseudo_child_handles[child];
2380 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2381 if (waitcode == WAIT_TIMEOUT) {
2384 else if (waitcode == WAIT_OBJECT_0) {
2385 if (GetExitCodeThread(hThread, &waitcode)) {
2386 *status = (int)((waitcode & 0xff) << 8);
2387 retval = (int)w32_pseudo_child_pids[child];
2388 remove_dead_pseudo_process(child);
2400 child = find_pid(aTHX_ pid);
2402 hProcess = w32_child_handles[child];
2403 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2404 if (waitcode == WAIT_TIMEOUT) {
2407 else if (waitcode == WAIT_OBJECT_0) {
2408 if (GetExitCodeProcess(hProcess, &waitcode)) {
2409 *status = (int)((waitcode & 0xff) << 8);
2410 retval = (int)w32_child_pids[child];
2411 remove_dead_process(child);
2419 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
2421 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2422 if (waitcode == WAIT_TIMEOUT) {
2423 CloseHandle(hProcess);
2426 else if (waitcode == WAIT_OBJECT_0) {
2427 if (GetExitCodeProcess(hProcess, &waitcode)) {
2428 *status = (int)((waitcode & 0xff) << 8);
2429 CloseHandle(hProcess);
2433 CloseHandle(hProcess);
2439 return retval >= 0 ? pid : retval;
2443 win32_wait(int *status)
2446 return win32_internal_wait(aTHX_ status, INFINITE);
2449 DllExport unsigned int
2450 win32_sleep(unsigned int t)
2453 /* Win32 times are in ms so *1000 in and /1000 out */
2454 if (t > UINT_MAX / 1000) {
2455 Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
2456 "sleep(%lu) too large", t);
2458 return win32_msgwait(aTHX_ 0, NULL, t * 1000, NULL) / 1000;
2465 win32_msgwait(aTHX_ 0, NULL, INFINITE, NULL);
2469 DllExport unsigned int
2470 win32_alarm(unsigned int sec)
2473 * the 'obvious' implentation is SetTimer() with a callback
2474 * which does whatever receiving SIGALRM would do
2475 * we cannot use SIGALRM even via raise() as it is not
2476 * one of the supported codes in <signal.h>
2480 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2481 w32_message_hwnd = win32_create_message_window();
2484 if (w32_message_hwnd == NULL)
2485 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2488 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2493 KillTimer(w32_message_hwnd, w32_timerid);
2500 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2503 win32_crypt(const char *txt, const char *salt)
2506 return des_fcrypt(txt, salt, w32_crypt_buffer);
2509 /* simulate flock by locking a range on the file */
2511 #define LK_LEN 0xffff0000
2514 win32_flock(int fd, int oper)
2520 fh = (HANDLE)_get_osfhandle(fd);
2521 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */
2524 memset(&o, 0, sizeof(o));
2527 case LOCK_SH: /* shared lock */
2528 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
2531 case LOCK_EX: /* exclusive lock */
2532 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
2535 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2536 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
2539 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2540 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2544 case LOCK_UN: /* unlock lock */
2545 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o))
2548 default: /* unknown */
2553 if (GetLastError() == ERROR_LOCK_VIOLATION)
2554 errno = EWOULDBLOCK;
2563 extern int convert_wsa_error_to_errno(int wsaerr); /* in win32sck.c */
2565 /* Get the errno value corresponding to the given err. This function is not
2566 * intended to handle conversion of general GetLastError() codes. It only exists
2567 * to translate Windows sockets error codes from WSAGetLastError(). Such codes
2568 * used to be assigned to errno/$! in earlier versions of perl; this function is
2569 * used to catch any old Perl code which is still trying to assign such values
2570 * to $! and convert them to errno values instead.
2573 win32_get_errno(int err)
2575 return convert_wsa_error_to_errno(err);
2579 * redirected io subsystem for all XS modules
2592 return (&(_environ));
2595 /* the rest are the remapped stdio routines */
2615 win32_ferror(FILE *fp)
2617 return (ferror(fp));
2622 win32_feof(FILE *fp)
2627 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2628 extern int convert_errno_to_wsa_error(int err); /* in win32sck.c */
2632 * Since the errors returned by the socket error function
2633 * WSAGetLastError() are not known by the library routine strerror
2634 * we have to roll our own to cover the case of socket errors
2635 * that could not be converted to regular errno values by
2636 * get_last_socket_error() in win32/win32sck.c.
2640 win32_strerror(int e)
2642 #if !defined __MINGW32__ /* compiler intolerance */
2643 extern int sys_nerr;
2646 if (e < 0 || e > sys_nerr) {
2650 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2651 /* VC10+ and some MinGW/gcc-4.8+ define a "POSIX supplement" of errno
2652 * values ranging from EADDRINUSE (100) to EWOULDBLOCK (140), but
2653 * sys_nerr is still 43 and strerror() returns "Unknown error" for them.
2654 * We must therefore still roll our own messages for these codes, and
2655 * additionally map them to corresponding Windows (sockets) error codes
2656 * first to avoid getting the wrong system message.
2658 else if (inRANGE(e, EADDRINUSE, EWOULDBLOCK)) {
2659 e = convert_errno_to_wsa_error(e);
2663 aTHXa(PERL_GET_THX);
2664 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
2665 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0,
2666 w32_strerror_buffer, sizeof(w32_strerror_buffer),
2669 strcpy(w32_strerror_buffer, "Unknown Error");
2671 return w32_strerror_buffer;
2675 #define strerror win32_strerror
2679 win32_str_os_error(void *sv, DWORD dwErr)
2683 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2684 |FORMAT_MESSAGE_IGNORE_INSERTS
2685 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2686 dwErr, 0, (char *)&sMsg, 1, NULL);
2687 /* strip trailing whitespace and period */
2690 --dwLen; /* dwLen doesn't include trailing null */
2691 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2692 if ('.' != sMsg[dwLen])
2697 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2699 dwLen = sprintf(sMsg,
2700 "Unknown error #0x%lX (lookup 0x%lX)",
2701 dwErr, GetLastError());
2705 sv_setpvn((SV*)sv, sMsg, dwLen);
2711 win32_fprintf(FILE *fp, const char *format, ...)
2714 va_start(marker, format); /* Initialize variable arguments. */
2716 return (vfprintf(fp, format, marker));
2720 win32_printf(const char *format, ...)
2723 va_start(marker, format); /* Initialize variable arguments. */
2725 return (vprintf(format, marker));
2729 win32_vfprintf(FILE *fp, const char *format, va_list args)
2731 return (vfprintf(fp, format, args));
2735 win32_vprintf(const char *format, va_list args)
2737 return (vprintf(format, args));
2741 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2743 return fread(buf, size, count, fp);
2747 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2749 return fwrite(buf, size, count, fp);
2752 #define MODE_SIZE 10
2755 win32_fopen(const char *filename, const char *mode)
2763 if (stricmp(filename, "/dev/null")==0)
2766 aTHXa(PERL_GET_THX);
2767 f = fopen(PerlDir_mapA(filename), mode);
2768 /* avoid buffering headaches for child processes */
2769 if (f && *mode == 'a')
2770 win32_fseek(f, 0, SEEK_END);
2775 win32_fdopen(int handle, const char *mode)
2778 f = fdopen(handle, (char *) mode);
2779 /* avoid buffering headaches for child processes */
2780 if (f && *mode == 'a')
2781 win32_fseek(f, 0, SEEK_END);
2786 win32_freopen(const char *path, const char *mode, FILE *stream)
2789 if (stricmp(path, "/dev/null")==0)
2792 aTHXa(PERL_GET_THX);
2793 return freopen(PerlDir_mapA(path), mode, stream);
2797 win32_fclose(FILE *pf)
2799 #ifdef WIN32_NO_SOCKETS
2802 return my_fclose(pf); /* defined in win32sck.c */
2807 win32_fputs(const char *s,FILE *pf)
2809 return fputs(s, pf);
2813 win32_fputc(int c,FILE *pf)
2819 win32_ungetc(int c,FILE *pf)
2821 return ungetc(c,pf);
2825 win32_getc(FILE *pf)
2831 win32_fileno(FILE *pf)
2837 win32_clearerr(FILE *pf)
2844 win32_fflush(FILE *pf)
2850 win32_ftell(FILE *pf)
2853 if (fgetpos(pf, &pos))
2859 win32_fseek(FILE *pf, Off_t offset,int origin)
2864 if (fgetpos(pf, &pos))
2869 fseek(pf, 0, SEEK_END);
2870 pos = _telli64(fileno(pf));
2879 return fsetpos(pf, &offset);
2883 win32_fgetpos(FILE *pf,fpos_t *p)
2885 return fgetpos(pf, p);
2889 win32_fsetpos(FILE *pf,const fpos_t *p)
2891 return fsetpos(pf, p);
2895 win32_rewind(FILE *pf)
2904 return win32_tmpfd_mode(0);
2908 win32_tmpfd_mode(int mode)
2910 char prefix[MAX_PATH+1];
2911 char filename[MAX_PATH+1];
2912 DWORD len = GetTempPath(MAX_PATH, prefix);
2913 mode &= ~( O_ACCMODE | O_CREAT | O_EXCL );
2915 if (len && len < MAX_PATH) {
2916 if (GetTempFileName(prefix, "plx", 0, filename)) {
2917 HANDLE fh = CreateFile(filename,
2918 DELETE | GENERIC_READ | GENERIC_WRITE,
2922 FILE_ATTRIBUTE_NORMAL
2923 | FILE_FLAG_DELETE_ON_CLOSE,
2925 if (fh != INVALID_HANDLE_VALUE) {
2926 int fd = win32_open_osfhandle((intptr_t)fh, mode);
2929 DEBUG_p(PerlIO_printf(Perl_debug_log,
2930 "Created tmpfile=%s\n",filename));
2942 int fd = win32_tmpfd();
2944 return win32_fdopen(fd, "w+b");
2956 win32_fstat(int fd, Stat_t *sbufptr)
2958 return _fstati64(fd, sbufptr);
2962 win32_pipe(int *pfd, unsigned int size, int mode)
2964 return _pipe(pfd, size, mode);
2968 win32_popenlist(const char *mode, IV narg, SV **args)
2972 return do_popen(mode, NULL, narg, args);
2976 do_popen(const char *mode, const char *command, IV narg, SV **args) {
2985 const char **args_pvs = NULL;
2987 /* establish which ends read and write */
2988 if (strchr(mode,'w')) {
2989 stdfd = 0; /* stdin */
2992 nhandle = STD_INPUT_HANDLE;
2994 else if (strchr(mode,'r')) {
2995 stdfd = 1; /* stdout */
2998 nhandle = STD_OUTPUT_HANDLE;
3003 /* set the correct mode */
3004 if (strchr(mode,'b'))
3006 else if (strchr(mode,'t'))
3009 ourmode = _fmode & (O_TEXT | O_BINARY);
3011 /* the child doesn't inherit handles */
3012 ourmode |= O_NOINHERIT;
3014 if (win32_pipe(p, 512, ourmode) == -1)
3017 /* Previously this code redirected stdin/out temporarily so the
3018 child process inherited those handles, this caused race
3019 conditions when another thread was writing/reading those
3022 To avoid that we just feed the handles to CreateProcess() so
3023 the handles are redirected only in the child.
3025 handles[child] = p[child];
3026 handles[parent] = -1;
3029 /* CreateProcess() requires inheritable handles */
3030 if (!SetHandleInformation((HANDLE)_get_osfhandle(p[child]), HANDLE_FLAG_INHERIT,
3031 HANDLE_FLAG_INHERIT)) {
3035 /* start the child */
3040 if ((childpid = do_spawn2_handles(aTHX_ command, EXECF_SPAWN_NOWAIT, handles)) == -1)
3046 const char *exe_name;
3048 Newx(args_pvs, narg + 1 + w32_perlshell_items, const char *);
3049 SAVEFREEPV(args_pvs);
3050 for (i = 0; i < narg; ++i)
3051 args_pvs[i] = SvPV_nolen(args[i]);
3053 exe_name = qualified_path(args_pvs[0], TRUE);
3055 /* let CreateProcess() try to find it instead */
3056 exe_name = args_pvs[0];
3058 if ((childpid = do_spawnvp_handles(P_NOWAIT, exe_name, args_pvs, handles)) == -1) {
3063 win32_close(p[child]);
3065 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3067 /* set process id so that it can be returned by perl's open() */
3068 PL_forkprocess = childpid;
3071 /* we have an fd, return a file stream */
3072 return (PerlIO_fdopen(p[parent], (char *)mode));
3075 /* we don't need to check for errors here */
3083 * a popen() clone that respects PERL5SHELL
3085 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
3089 win32_popen(const char *command, const char *mode)
3091 #ifdef USE_RTL_POPEN
3092 return _popen(command, mode);
3094 return do_popen(mode, command, 0, NULL);
3095 #endif /* USE_RTL_POPEN */
3103 win32_pclose(PerlIO *pf)
3105 #ifdef USE_RTL_POPEN
3109 int childpid, status;
3112 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3115 childpid = SvIVX(sv);
3131 if (win32_waitpid(childpid, &status, 0) == -1)
3136 #endif /* USE_RTL_POPEN */
3140 win32_link(const char *oldname, const char *newname)
3143 WCHAR wOldName[MAX_PATH+1];
3144 WCHAR wNewName[MAX_PATH+1];
3146 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3147 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3148 ((aTHXa(PERL_GET_THX)), wcscpy(wOldName, PerlDir_mapW(wOldName)),
3149 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3153 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for
3154 both permissions errors and if the source is a directory, while
3155 POSIX wants EACCES and EPERM respectively.
3157 Determined by experimentation on Windows 7 x64 SP1, since MS
3158 don't document what error codes are returned.
3160 switch (GetLastError()) {
3161 case ERROR_BAD_NET_NAME:
3162 case ERROR_BAD_NETPATH:
3163 case ERROR_BAD_PATHNAME:
3164 case ERROR_FILE_NOT_FOUND:
3165 case ERROR_FILENAME_EXCED_RANGE:
3166 case ERROR_INVALID_DRIVE:
3167 case ERROR_PATH_NOT_FOUND:
3170 case ERROR_ALREADY_EXISTS:
3173 case ERROR_ACCESS_DENIED:
3176 case ERROR_NOT_SAME_DEVICE:
3179 case ERROR_DISK_FULL:
3182 case ERROR_NOT_ENOUGH_QUOTA:
3186 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */
3194 win32_rename(const char *oname, const char *newname)
3196 char szOldName[MAX_PATH+1];
3198 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3201 if (stricmp(newname, oname))
3202 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3203 strcpy(szOldName, PerlDir_mapA(oname));
3205 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3207 DWORD err = GetLastError();
3209 case ERROR_BAD_NET_NAME:
3210 case ERROR_BAD_NETPATH:
3211 case ERROR_BAD_PATHNAME:
3212 case ERROR_FILE_NOT_FOUND:
3213 case ERROR_FILENAME_EXCED_RANGE:
3214 case ERROR_INVALID_DRIVE:
3215 case ERROR_NO_MORE_FILES:
3216 case ERROR_PATH_NOT_FOUND:
3219 case ERROR_DISK_FULL:
3222 case ERROR_NOT_ENOUGH_QUOTA:
3235 win32_setmode(int fd, int mode)
3237 return setmode(fd, mode);
3241 win32_chsize(int fd, Off_t size)
3244 Off_t cur, end, extend;
3246 cur = win32_tell(fd);
3249 end = win32_lseek(fd, 0, SEEK_END);
3252 extend = size - end;
3256 else if (extend > 0) {
3257 /* must grow the file, padding with nulls */
3259 int oldmode = win32_setmode(fd, O_BINARY);
3261 memset(b, '\0', sizeof(b));
3263 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3264 count = win32_write(fd, b, count);
3265 if ((int)count < 0) {
3269 } while ((extend -= count) > 0);
3270 win32_setmode(fd, oldmode);
3273 /* shrink the file */
3274 win32_lseek(fd, size, SEEK_SET);
3275 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3280 win32_lseek(fd, cur, SEEK_SET);
3285 win32_lseek(int fd, Off_t offset, int origin)
3287 return _lseeki64(fd, offset, origin);
3293 return _telli64(fd);
3297 win32_open(const char *path, int flag, ...)
3304 pmode = va_arg(ap, int);
3307 if (stricmp(path, "/dev/null")==0)
3310 aTHXa(PERL_GET_THX);
3311 return open(PerlDir_mapA(path), flag, pmode);
3314 /* close() that understands socket */
3315 extern int my_close(int); /* in win32sck.c */
3320 #ifdef WIN32_NO_SOCKETS
3323 return my_close(fd);
3334 win32_isatty(int fd)
3336 /* The Microsoft isatty() function returns true for *all*
3337 * character mode devices, including "nul". Our implementation
3338 * should only return true if the handle has a console buffer.
3341 HANDLE fh = (HANDLE)_get_osfhandle(fd);
3342 if (fh == (HANDLE)-1) {
3343 /* errno is already set to EBADF */
3347 if (GetConsoleMode(fh, &mode))
3361 win32_dup2(int fd1,int fd2)
3363 return dup2(fd1,fd2);
3367 win32_read(int fd, void *buf, unsigned int cnt)
3369 return read(fd, buf, cnt);
3373 win32_write(int fd, const void *buf, unsigned int cnt)
3375 return write(fd, buf, cnt);
3379 win32_mkdir(const char *dir, int mode)
3382 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3386 win32_rmdir(const char *dir)
3389 return rmdir(PerlDir_mapA(dir));
3393 win32_chdir(const char *dir)
3395 if (!dir || !*dir) {
3403 win32_access(const char *path, int mode)
3406 return access(PerlDir_mapA(path), mode);
3410 win32_chmod(const char *path, int mode)
3413 return chmod(PerlDir_mapA(path), mode);
3418 create_command_line(char *cname, STRLEN clen, const char * const *args)
3425 bool bat_file = FALSE;
3426 bool cmd_shell = FALSE;
3427 bool dumb_shell = FALSE;
3428 bool extra_quotes = FALSE;
3429 bool quote_next = FALSE;
3432 cname = (char*)args[0];
3434 /* The NT cmd.exe shell has the following peculiarity that needs to be
3435 * worked around. It strips a leading and trailing dquote when any
3436 * of the following is true:
3437 * 1. the /S switch was used
3438 * 2. there are more than two dquotes
3439 * 3. there is a special character from this set: &<>()@^|
3440 * 4. no whitespace characters within the two dquotes
3441 * 5. string between two dquotes isn't an executable file
3442 * To work around this, we always add a leading and trailing dquote
3443 * to the string, if the first argument is either "cmd.exe" or "cmd",
3444 * and there were at least two or more arguments passed to cmd.exe
3445 * (not including switches).
3446 * XXX the above rules (from "cmd /?") don't seem to be applied
3447 * always, making for the convolutions below :-(
3451 clen = strlen(cname);
3454 && (stricmp(&cname[clen-4], ".bat") == 0
3455 || (stricmp(&cname[clen-4], ".cmd") == 0)))
3461 char *exe = strrchr(cname, '/');
3462 char *exe2 = strrchr(cname, '\\');
3469 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3473 else if (stricmp(exe, "command.com") == 0
3474 || stricmp(exe, "command") == 0)
3481 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3482 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3483 STRLEN curlen = strlen(arg);
3484 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3485 len += 2; /* assume quoting needed (worst case) */
3487 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3489 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3492 Newx(cmd, len, char);
3497 extra_quotes = TRUE;
3500 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3502 STRLEN curlen = strlen(arg);
3504 /* we want to protect empty arguments and ones with spaces with
3505 * dquotes, but only if they aren't already there */
3510 else if (quote_next) {
3511 /* see if it really is multiple arguments pretending to
3512 * be one and force a set of quotes around it */
3513 if (*find_next_space(arg))
3516 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3518 while (i < curlen) {
3519 if (isSPACE(arg[i])) {
3522 else if (arg[i] == '"') {
3546 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3547 && stricmp(arg+curlen-2, "/c") == 0)
3549 /* is there a next argument? */
3550 if (args[index+1]) {
3551 /* are there two or more next arguments? */
3552 if (args[index+2]) {
3554 extra_quotes = TRUE;
3557 /* single argument, force quoting if it has spaces */
3572 static const char *exe_extensions[] =
3574 ".exe", /* this must be first */
3580 qualified_path(const char *cmd, bool other_exts)
3583 char *fullcmd, *curfullcmd;
3589 fullcmd = (char*)cmd;
3591 if (*fullcmd == '/' || *fullcmd == '\\')
3600 pathstr = PerlEnv_getenv("PATH");
3602 /* worst case: PATH is a single directory; we need additional space
3603 * to append "/", ".exe" and trailing "\0" */
3604 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3605 curfullcmd = fullcmd;
3610 /* start by appending the name to the current prefix */
3611 strcpy(curfullcmd, cmd);
3612 curfullcmd += cmdlen;
3614 /* if it doesn't end with '.', or has no extension, try adding
3615 * a trailing .exe first */
3616 if (cmd[cmdlen-1] != '.'
3617 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3620 /* first extension is .exe */
3621 int ext_limit = other_exts ? C_ARRAY_LENGTH(exe_extensions) : 1;
3622 for (i = 0; i < ext_limit; ++i) {
3623 strcpy(curfullcmd, exe_extensions[i]);
3624 res = GetFileAttributes(fullcmd);
3625 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3632 /* that failed, try the bare name */
3633 res = GetFileAttributes(fullcmd);
3634 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3637 /* quit if no other path exists, or if cmd already has path */
3638 if (!pathstr || !*pathstr || has_slash)
3641 /* skip leading semis */
3642 while (*pathstr == ';')
3645 /* build a new prefix from scratch */
3646 curfullcmd = fullcmd;
3647 while (*pathstr && *pathstr != ';') {
3648 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3649 pathstr++; /* skip initial '"' */
3650 while (*pathstr && *pathstr != '"') {
3651 *curfullcmd++ = *pathstr++;
3654 pathstr++; /* skip trailing '"' */
3657 *curfullcmd++ = *pathstr++;
3661 pathstr++; /* skip trailing semi */
3662 if (curfullcmd > fullcmd /* append a dir separator */
3663 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3665 *curfullcmd++ = '\\';
3673 /* The following are just place holders.
3674 * Some hosts may provide and environment that the OS is
3675 * not tracking, therefore, these host must provide that
3676 * environment and the current directory to CreateProcess
3680 win32_get_childenv(void)
3686 win32_free_childenv(void* d)
3691 win32_clearenv(void)
3693 char *envv = GetEnvironmentStrings();
3697 char *end = strchr(cur,'=');
3698 if (end && end != cur) {
3700 SetEnvironmentVariable(cur, NULL);
3702 cur = end + strlen(end+1)+2;
3704 else if ((len = strlen(cur)))
3707 FreeEnvironmentStrings(envv);
3711 win32_get_childdir(void)
3714 char szfilename[MAX_PATH+1];
3716 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
3717 Newx(ptr, strlen(szfilename)+1, char);
3718 strcpy(ptr, szfilename);
3723 win32_free_childdir(char* d)
3729 /* XXX this needs to be made more compatible with the spawnvp()
3730 * provided by the various RTLs. In particular, searching for
3731 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
3732 * This doesn't significantly affect perl itself, because we
3733 * always invoke things using PERL5SHELL if a direct attempt to
3734 * spawn the executable fails.
3736 * XXX splitting and rejoining the commandline between do_aspawn()
3737 * and win32_spawnvp() could also be avoided.
3741 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
3743 #ifdef USE_RTL_SPAWNVP
3744 return _spawnvp(mode, cmdname, (char * const *)argv);
3746 return do_spawnvp_handles(mode, cmdname, argv, NULL);
3751 do_spawnvp_handles(int mode, const char *cmdname, const char *const *argv,
3752 const int *handles) {
3758 STARTUPINFO StartupInfo;
3759 PROCESS_INFORMATION ProcessInformation;
3762 char *fullcmd = NULL;
3763 char *cname = (char *)cmdname;
3767 clen = strlen(cname);
3768 /* if command name contains dquotes, must remove them */
3769 if (strchr(cname, '"')) {
3771 Newx(cname,clen+1,char);
3784 cmd = create_command_line(cname, clen, argv);
3786 aTHXa(PERL_GET_THX);
3787 env = PerlEnv_get_childenv();
3788 dir = PerlEnv_get_childdir();
3791 case P_NOWAIT: /* asynch + remember result */
3792 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
3797 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
3800 create |= CREATE_NEW_PROCESS_GROUP;
3803 case P_WAIT: /* synchronous execution */
3805 default: /* invalid mode */
3811 memset(&StartupInfo,0,sizeof(StartupInfo));
3812 StartupInfo.cb = sizeof(StartupInfo);
3813 memset(&tbl,0,sizeof(tbl));
3814 PerlEnv_get_child_IO(&tbl);
3815 StartupInfo.dwFlags = tbl.dwFlags;
3816 StartupInfo.dwX = tbl.dwX;
3817 StartupInfo.dwY = tbl.dwY;
3818 StartupInfo.dwXSize = tbl.dwXSize;
3819 StartupInfo.dwYSize = tbl.dwYSize;
3820 StartupInfo.dwXCountChars = tbl.dwXCountChars;
3821 StartupInfo.dwYCountChars = tbl.dwYCountChars;
3822 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
3823 StartupInfo.wShowWindow = tbl.wShowWindow;
3824 StartupInfo.hStdInput = handles && handles[0] != -1 ?
3825 (HANDLE)_get_osfhandle(handles[0]) : tbl.childStdIn;
3826 StartupInfo.hStdOutput = handles && handles[1] != -1 ?
3827 (HANDLE)_get_osfhandle(handles[1]) : tbl.childStdOut;
3828 StartupInfo.hStdError = handles && handles[2] != -1 ?
3829 (HANDLE)_get_osfhandle(handles[2]) : tbl.childStdErr;
3830 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
3831 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
3832 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
3834 create |= CREATE_NEW_CONSOLE;
3837 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3839 if (w32_use_showwindow) {
3840 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
3841 StartupInfo.wShowWindow = w32_showwindow;
3844 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
3847 if (!CreateProcess(cname, /* search PATH to find executable */
3848 cmd, /* executable, and its arguments */
3849 NULL, /* process attributes */
3850 NULL, /* thread attributes */
3851 TRUE, /* inherit handles */
3852 create, /* creation flags */
3853 (LPVOID)env, /* inherit environment */
3854 dir, /* inherit cwd */
3856 &ProcessInformation))
3858 /* initial NULL argument to CreateProcess() does a PATH
3859 * search, but it always first looks in the directory
3860 * where the current process was started, which behavior
3861 * is undesirable for backward compatibility. So we
3862 * jump through our own hoops by picking out the path
3863 * we really want it to use. */
3865 fullcmd = qualified_path(cname, FALSE);
3867 if (cname != cmdname)
3870 DEBUG_p(PerlIO_printf(Perl_debug_log,
3871 "Retrying [%s] with same args\n",
3881 if (mode == P_NOWAIT) {
3882 /* asynchronous spawn -- store handle, return PID */
3883 ret = (int)ProcessInformation.dwProcessId;
3885 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
3886 w32_child_pids[w32_num_children] = (DWORD)ret;
3891 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
3892 /* FIXME: if msgwait returned due to message perhaps forward the
3893 "signal" to the process
3895 GetExitCodeProcess(ProcessInformation.hProcess, &status);
3897 CloseHandle(ProcessInformation.hProcess);
3900 CloseHandle(ProcessInformation.hThread);
3903 PerlEnv_free_childenv(env);
3904 PerlEnv_free_childdir(dir);
3906 if (cname != cmdname)
3912 win32_execv(const char *cmdname, const char *const *argv)
3916 /* if this is a pseudo-forked child, we just want to spawn
3917 * the new program, and return */
3919 return _spawnv(P_WAIT, cmdname, argv);
3921 return _execv(cmdname, argv);
3925 win32_execvp(const char *cmdname, const char *const *argv)
3929 /* if this is a pseudo-forked child, we just want to spawn
3930 * the new program, and return */
3931 if (w32_pseudo_id) {
3932 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
3941 return _execvp(cmdname, argv);
3945 win32_perror(const char *str)
3951 win32_setbuf(FILE *pf, char *buf)
3957 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
3959 return setvbuf(pf, buf, type, size);
3963 win32_flushall(void)
3969 win32_fcloseall(void)
3975 win32_fgets(char *s, int n, FILE *pf)
3977 return fgets(s, n, pf);
3987 win32_fgetc(FILE *pf)
3993 win32_putc(int c, FILE *pf)
3999 win32_puts(const char *s)
4011 win32_putchar(int c)
4018 #ifndef USE_PERL_SBRK
4020 static char *committed = NULL; /* XXX threadead */
4021 static char *base = NULL; /* XXX threadead */
4022 static char *reserved = NULL; /* XXX threadead */
4023 static char *brk = NULL; /* XXX threadead */
4024 static DWORD pagesize = 0; /* XXX threadead */
4027 sbrk(ptrdiff_t need)
4032 GetSystemInfo(&info);
4033 /* Pretend page size is larger so we don't perpetually
4034 * call the OS to commit just one page ...
4036 pagesize = info.dwPageSize << 3;
4038 if (brk+need >= reserved)
4040 DWORD size = brk+need-reserved;
4042 char *prev_committed = NULL;
4043 if (committed && reserved && committed < reserved)
4045 /* Commit last of previous chunk cannot span allocations */
4046 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
4049 /* Remember where we committed from in case we want to decommit later */
4050 prev_committed = committed;
4051 committed = reserved;
4054 /* Reserve some (more) space
4055 * Contiguous blocks give us greater efficiency, so reserve big blocks -
4056 * this is only address space not memory...
4057 * Note this is a little sneaky, 1st call passes NULL as reserved
4058 * so lets system choose where we start, subsequent calls pass
4059 * the old end address so ask for a contiguous block
4062 if (size < 64*1024*1024)
4063 size = 64*1024*1024;
4064 size = ((size + pagesize - 1) / pagesize) * pagesize;
4065 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
4068 reserved = addr+size;
4078 /* The existing block could not be extended far enough, so decommit
4079 * anything that was just committed above and start anew */
4082 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
4085 reserved = base = committed = brk = NULL;
4096 if (brk > committed)
4098 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4100 if (committed+size > reserved)
4101 size = reserved-committed;
4102 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4115 win32_malloc(size_t size)
4117 return malloc(size);
4121 win32_calloc(size_t numitems, size_t size)
4123 return calloc(numitems,size);
4127 win32_realloc(void *block, size_t size)
4129 return realloc(block,size);
4133 win32_free(void *block)
4140 win32_open_osfhandle(intptr_t handle, int flags)
4142 return _open_osfhandle(handle, flags);
4146 win32_get_osfhandle(int fd)
4148 return (intptr_t)_get_osfhandle(fd);
4152 win32_fdupopen(FILE *pf)
4157 int fileno = win32_dup(win32_fileno(pf));
4159 /* open the file in the same mode */
4160 if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RD) {
4164 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_WR) {
4168 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RW) {
4174 /* it appears that the binmode is attached to the
4175 * file descriptor so binmode files will be handled
4178 pfdup = win32_fdopen(fileno, mode);
4180 /* move the file pointer to the same position */
4181 if (!fgetpos(pf, &pos)) {
4182 fsetpos(pfdup, &pos);
4188 win32_dynaload(const char* filename)
4191 char buf[MAX_PATH+1];
4194 /* LoadLibrary() doesn't recognize forward slashes correctly,
4195 * so turn 'em back. */
4196 first = strchr(filename, '/');
4198 STRLEN len = strlen(filename);
4199 if (len <= MAX_PATH) {
4200 strcpy(buf, filename);
4201 filename = &buf[first - filename];
4203 if (*filename == '/')
4204 *(char*)filename = '\\';
4210 aTHXa(PERL_GET_THX);
4211 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4214 XS(w32_SetChildShowWindow)
4217 BOOL use_showwindow = w32_use_showwindow;
4218 /* use "unsigned short" because Perl has redefined "WORD" */
4219 unsigned short showwindow = w32_showwindow;
4222 croak_xs_usage(cv, "[showwindow]");
4224 if (items == 0 || !SvOK(ST(0)))
4225 w32_use_showwindow = FALSE;
4227 w32_use_showwindow = TRUE;
4228 w32_showwindow = (unsigned short)SvIV(ST(0));
4233 ST(0) = sv_2mortal(newSViv(showwindow));
4235 ST(0) = &PL_sv_undef;
4240 #ifdef PERL_IS_MINIPERL
4241 /* shelling out is much slower, full perl uses Win32.pm */
4245 /* Make the host for current directory */
4246 char* ptr = PerlEnv_get_childdir();
4249 * then it worked, set PV valid,
4250 * else return 'undef'
4253 SV *sv = sv_newmortal();
4255 PerlEnv_free_childdir(ptr);
4257 #ifndef INCOMPLETE_TAINTS
4269 Perl_init_os_extras(void)
4272 char *file = __FILE__;
4274 /* Initialize Win32CORE if it has been statically linked. */
4275 #ifndef PERL_IS_MINIPERL
4276 void (*pfn_init)(pTHX);
4277 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
4278 ? GetModuleHandle(NULL)
4279 : w32_perldll_handle);
4280 pfn_init = (void (*)(pTHX))GetProcAddress(module, "init_Win32CORE");
4281 aTHXa(PERL_GET_THX);
4285 aTHXa(PERL_GET_THX);
4288 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4289 #ifdef PERL_IS_MINIPERL
4290 newXS("Win32::GetCwd", w32_GetCwd, file);
4295 win32_signal_context(void)
4300 my_perl = PL_curinterp;
4301 PERL_SET_THX(my_perl);
4305 return PL_curinterp;
4311 win32_ctrlhandler(DWORD dwCtrlType)
4314 dTHXa(PERL_GET_SIG_CONTEXT);
4320 switch(dwCtrlType) {
4321 case CTRL_CLOSE_EVENT:
4322 /* A signal that the system sends to all processes attached to a console when
4323 the user closes the console (either by choosing the Close command from the
4324 console window's System menu, or by choosing the End Task command from the
4327 if (do_raise(aTHX_ 1)) /* SIGHUP */
4328 sig_terminate(aTHX_ 1);
4332 /* A CTRL+c signal was received */
4333 if (do_raise(aTHX_ SIGINT))
4334 sig_terminate(aTHX_ SIGINT);
4337 case CTRL_BREAK_EVENT:
4338 /* A CTRL+BREAK signal was received */
4339 if (do_raise(aTHX_ SIGBREAK))
4340 sig_terminate(aTHX_ SIGBREAK);
4343 case CTRL_LOGOFF_EVENT:
4344 /* A signal that the system sends to all console processes when a user is logging
4345 off. This signal does not indicate which user is logging off, so no
4346 assumptions can be made.
4349 case CTRL_SHUTDOWN_EVENT:
4350 /* A signal that the system sends to all console processes when the system is
4353 if (do_raise(aTHX_ SIGTERM))
4354 sig_terminate(aTHX_ SIGTERM);
4363 #ifdef SET_INVALID_PARAMETER_HANDLER
4364 # include <crtdbg.h>
4375 /* fetch Unicode version of PATH */
4377 wide_path = (WCHAR*)win32_malloc(len*sizeof(WCHAR));
4379 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4381 win32_free(wide_path);
4387 wide_path = (WCHAR*)win32_realloc(wide_path, len*sizeof(WCHAR));
4392 /* convert to ANSI pathnames */
4393 wide_dir = wide_path;
4396 WCHAR *sep = wcschr(wide_dir, ';');
4404 /* remove quotes around pathname */
4405 if (*wide_dir == '"')
4407 wide_len = wcslen(wide_dir);
4408 if (wide_len && wide_dir[wide_len-1] == '"')
4409 wide_dir[wide_len-1] = '\0';
4411 /* append ansi_dir to ansi_path */
4412 ansi_dir = win32_ansipath(wide_dir);
4413 ansi_len = strlen(ansi_dir);
4415 size_t newlen = len + 1 + ansi_len;
4416 ansi_path = (char*)win32_realloc(ansi_path, newlen+1);
4419 ansi_path[len] = ';';
4420 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4425 ansi_path = (char*)win32_malloc(5+len+1);
4428 memcpy(ansi_path, "PATH=", 5);
4429 memcpy(ansi_path+5, ansi_dir, len+1);
4432 win32_free(ansi_dir);
4437 /* Update C RTL environ array. This will only have full effect if
4438 * perl_parse() is later called with `environ` as the `env` argument.
4439 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4441 * We do have to ansify() the PATH before Perl has been fully
4442 * initialized because S_find_script() uses the PATH when perl
4443 * is being invoked with the -S option. This happens before %ENV
4444 * is initialized in S_init_postdump_symbols().
4446 * XXX Is this a bug? Should S_find_script() use the environment
4447 * XXX passed in the `env` arg to parse_perl()?
4450 /* Keep system environment in sync because S_init_postdump_symbols()
4451 * will not call mg_set() if it initializes %ENV from `environ`.
4453 SetEnvironmentVariableA("PATH", ansi_path+5);
4454 win32_free(ansi_path);
4456 win32_free(wide_path);
4460 Perl_win32_init(int *argcp, char ***argvp)
4462 #ifdef SET_INVALID_PARAMETER_HANDLER
4463 _invalid_parameter_handler oldHandler, newHandler;
4464 newHandler = my_invalid_parameter_handler;
4465 oldHandler = _set_invalid_parameter_handler(newHandler);
4466 _CrtSetReportMode(_CRT_ASSERT, 0);
4468 /* Disable floating point errors, Perl will trap the ones we
4469 * care about. VC++ RTL defaults to switching these off
4470 * already, but some RTLs don't. Since we don't
4471 * want to be at the vendor's whim on the default, we set
4472 * it explicitly here.
4474 #if !defined(__GNUC__)
4475 _control87(MCW_EM, MCW_EM);
4479 /* When the manifest resource requests Common-Controls v6 then
4480 * user32.dll no longer registers all the Windows classes used for
4481 * standard controls but leaves some of them to be registered by
4482 * comctl32.dll. InitCommonControls() doesn't do anything but calling
4483 * it makes sure comctl32.dll gets loaded into the process and registers
4484 * the standard control classes. Without this even normal Windows APIs
4485 * like MessageBox() can fail under some versions of Windows XP.
4487 InitCommonControls();
4489 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4490 GetVersionEx(&g_osver);
4492 #ifdef WIN32_DYN_IOINFO_SIZE
4494 Size_t ioinfo_size = _msize((void*)__pioinfo[0]);;
4495 if((SSize_t)ioinfo_size <= 0) { /* -1 is err */
4496 fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */
4499 ioinfo_size /= IOINFO_ARRAY_ELTS;
4500 w32_ioinfo_size = ioinfo_size;
4506 #ifndef WIN32_NO_REGISTRY
4509 retval = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Perl", 0, KEY_READ, &HKCU_Perl_hnd);
4510 if (retval != ERROR_SUCCESS) {
4511 HKCU_Perl_hnd = NULL;
4513 retval = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", 0, KEY_READ, &HKLM_Perl_hnd);
4514 if (retval != ERROR_SUCCESS) {
4515 HKLM_Perl_hnd = NULL;
4522 Perl_win32_term(void)
4530 #ifndef WIN32_NO_REGISTRY
4531 /* handles might be NULL, RegCloseKey then returns ERROR_INVALID_HANDLE
4532 but no point of checking and we can't die() at this point */
4533 RegCloseKey(HKLM_Perl_hnd);
4534 RegCloseKey(HKCU_Perl_hnd);
4535 /* the handles are in an undefined state until the next PERL_SYS_INIT3 */
4540 win32_get_child_IO(child_IO_table* ptbl)
4542 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4543 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4544 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4548 win32_signal(int sig, Sighandler_t subcode)
4551 if (sig < SIG_SIZE) {
4552 int save_errno = errno;
4553 Sighandler_t result;
4554 #ifdef SET_INVALID_PARAMETER_HANDLER
4555 /* Silence our invalid parameter handler since we expect to make some
4556 * calls with invalid signal numbers giving a SIG_ERR result. */
4557 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE);
4559 result = signal(sig, subcode);
4560 #ifdef SET_INVALID_PARAMETER_HANDLER
4561 set_silent_invalid_parameter_handler(oldvalue);
4563 aTHXa(PERL_GET_THX);
4564 if (result == SIG_ERR) {
4565 result = w32_sighandler[sig];
4568 w32_sighandler[sig] = subcode;
4577 /* The PerlMessageWindowClass's WindowProc */
4579 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4581 return win32_process_message(hwnd, msg, wParam, lParam) ?
4582 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4585 /* The real message handler. Can be called with
4586 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4587 * that it processes */
4589 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4591 /* BEWARE. The context retrieved using dTHX; is the context of the
4592 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4593 * up to and including WM_CREATE. If it ever happens that you need the
4594 * 'child' context before this, then it needs to be passed into
4595 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4596 * from the lparam of CreateWindow(). It could then be stored/retrieved
4597 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4598 * the dTHX calls here. */
4599 /* XXX For now it is assumed that the overhead of the dTHX; for what
4600 * are relativley infrequent code-paths, is better than the added
4601 * complexity of getting the correct context passed into
4602 * win32_create_message_window() */
4608 case WM_USER_MESSAGE: {
4609 long child = find_pseudo_pid(aTHX_ (int)wParam);
4611 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4618 case WM_USER_KILL: {
4619 /* We use WM_USER_KILL to fake kill() with other signals */
4620 int sig = (int)wParam;
4621 if (do_raise(aTHX_ sig))
4622 sig_terminate(aTHX_ sig);
4628 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4629 if (w32_timerid && w32_timerid==(UINT)wParam) {
4630 KillTimer(w32_message_hwnd, w32_timerid);
4633 /* Now fake a call to signal handler */
4634 if (do_raise(aTHX_ 14))
4635 sig_terminate(aTHX_ 14);
4647 /* Above or other stuff may have set a signal flag, and we may not have
4648 * been called from win32_async_check() (e.g. some other GUI's message
4649 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4650 * handler that die's, and the message loop that calls here is wrapped
4651 * in an eval, then you may well end up with orphaned windows - signals
4652 * are dispatched by win32_async_check() */
4658 win32_create_message_window_class(void)
4660 /* create the window class for "message only" windows */
4664 wc.lpfnWndProc = win32_message_window_proc;
4665 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4666 wc.lpszClassName = "PerlMessageWindowClass";
4668 /* second and subsequent calls will fail, but class
4669 * will already be registered */
4674 win32_create_message_window(void)
4676 win32_create_message_window_class();
4677 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4678 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4681 #ifdef HAVE_INTERP_INTERN
4684 win32_csighandler(int sig)
4687 dTHXa(PERL_GET_SIG_CONTEXT);
4688 Perl_warn(aTHX_ "Got signal %d",sig);
4693 #if defined(__MINGW32__) && defined(__cplusplus)
4694 #define CAST_HWND__(x) (HWND__*)(x)
4696 #define CAST_HWND__(x) x
4700 Perl_sys_intern_init(pTHX)
4704 w32_perlshell_tokens = NULL;
4705 w32_perlshell_vec = (char**)NULL;
4706 w32_perlshell_items = 0;
4707 w32_fdpid = newAV();
4708 Newx(w32_children, 1, child_tab);
4709 w32_num_children = 0;
4710 # ifdef USE_ITHREADS
4712 Newx(w32_pseudo_children, 1, pseudo_child_tab);
4713 w32_num_pseudo_children = 0;
4716 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4718 #ifdef PERL_IS_MINIPERL
4719 w32_sloppystat = TRUE;
4721 w32_sloppystat = FALSE;
4723 for (i=0; i < SIG_SIZE; i++) {
4724 w32_sighandler[i] = SIG_DFL;
4726 # ifdef MULTIPLICITY
4727 if (my_perl == PL_curinterp) {
4731 /* Force C runtime signal stuff to set its console handler */
4732 signal(SIGINT,win32_csighandler);
4733 signal(SIGBREAK,win32_csighandler);
4735 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
4736 * flag. This has the side-effect of disabling Ctrl-C events in all
4737 * processes in this group.
4738 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
4739 * with a NULL handler.
4741 SetConsoleCtrlHandler(NULL,FALSE);
4743 /* Push our handler on top */
4744 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
4749 Perl_sys_intern_clear(pTHX)
4752 Safefree(w32_perlshell_tokens);
4753 Safefree(w32_perlshell_vec);
4754 /* NOTE: w32_fdpid is freed by sv_clean_all() */
4755 Safefree(w32_children);
4757 KillTimer(w32_message_hwnd, w32_timerid);
4760 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
4761 DestroyWindow(w32_message_hwnd);
4762 # ifdef MULTIPLICITY
4763 if (my_perl == PL_curinterp) {
4767 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
4769 # ifdef USE_ITHREADS
4770 Safefree(w32_pseudo_children);
4774 # ifdef USE_ITHREADS
4777 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
4779 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
4781 dst->perlshell_tokens = NULL;
4782 dst->perlshell_vec = (char**)NULL;
4783 dst->perlshell_items = 0;
4784 dst->fdpid = newAV();
4785 Newxz(dst->children, 1, child_tab);
4787 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
4789 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4790 dst->poll_count = 0;
4791 dst->sloppystat = src->sloppystat;
4792 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
4794 # endif /* USE_ITHREADS */
4795 #endif /* HAVE_INTERP_INTERN */