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 #if defined(WIN64) || defined(USE_LARGE_FILES)
1530 res = _stati64(path, sbuf);
1532 res = stat(path, sbuf);
1534 sbuf->st_nlink = nlink;
1537 /* CRT is buggy on sharenames, so make sure it really isn't.
1538 * XXX using GetFileAttributesEx() will enable us to set
1539 * sbuf->st_*time (but note that's not available on the
1540 * Windows of 1995) */
1541 DWORD r = GetFileAttributesA(path);
1542 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1543 /* sbuf may still contain old garbage since stat() failed */
1544 Zero(sbuf, 1, Stat_t);
1545 sbuf->st_mode = S_IFDIR | S_IREAD;
1547 if (!(r & FILE_ATTRIBUTE_READONLY))
1548 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1553 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1554 && (path[2] == '\\' || path[2] == '/'))
1556 /* The drive can be inaccessible, some _stat()s are buggy */
1557 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1562 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1566 if (S_ISDIR(sbuf->st_mode)) {
1567 /* Ensure the "write" bit is switched off in the mode for
1568 * directories with the read-only attribute set. Some compilers
1569 * switch it on for directories, which is technically correct
1570 * (directories are indeed always writable unless denied by DACLs),
1571 * but we want stat() and -w to reflect the state of the read-only
1572 * attribute for symmetry with chmod(). */
1573 DWORD r = GetFileAttributesA(path);
1574 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
1575 sbuf->st_mode &= ~S_IWRITE;
1582 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1583 #define SKIP_SLASHES(s) \
1585 while (*(s) && isSLASH(*(s))) \
1588 #define COPY_NONSLASHES(d,s) \
1590 while (*(s) && !isSLASH(*(s))) \
1594 /* Find the longname of a given path. path is destructively modified.
1595 * It should have space for at least MAX_PATH characters. */
1597 win32_longpath(char *path)
1599 WIN32_FIND_DATA fdata;
1601 char tmpbuf[MAX_PATH+1];
1602 char *tmpstart = tmpbuf;
1609 if (isALPHA(path[0]) && path[1] == ':') {
1611 *tmpstart++ = path[0];
1615 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1617 *tmpstart++ = path[0];
1618 *tmpstart++ = path[1];
1619 SKIP_SLASHES(start);
1620 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1622 *tmpstart++ = *start++;
1623 SKIP_SLASHES(start);
1624 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1629 /* copy initial slash, if any */
1630 if (isSLASH(*start)) {
1631 *tmpstart++ = *start++;
1633 SKIP_SLASHES(start);
1636 /* FindFirstFile() expands "." and "..", so we need to pass
1637 * those through unmolested */
1639 && (!start[1] || isSLASH(start[1])
1640 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1642 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1647 /* if this is the end, bust outta here */
1651 /* now we're at a non-slash; walk up to next slash */
1652 while (*start && !isSLASH(*start))
1655 /* stop and find full name of component */
1658 fhand = FindFirstFile(path,&fdata);
1660 if (fhand != INVALID_HANDLE_VALUE) {
1661 STRLEN len = strlen(fdata.cFileName);
1662 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1663 strcpy(tmpstart, fdata.cFileName);
1674 /* failed a step, just return without side effects */
1675 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1680 strcpy(path,tmpbuf);
1694 win32_croak_not_implemented(const char * fname)
1696 PERL_ARGS_ASSERT_WIN32_CROAK_NOT_IMPLEMENTED;
1698 Perl_croak_nocontext("%s not implemented!\n", fname);
1701 /* Converts a wide character (UTF-16) string to the Windows ANSI code page,
1702 * potentially using the system's default replacement character for any
1703 * unrepresentable characters. The caller must free() the returned string. */
1705 wstr_to_str(const wchar_t* wstr)
1707 BOOL used_default = FALSE;
1708 size_t wlen = wcslen(wstr) + 1;
1709 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1710 NULL, 0, NULL, NULL);
1711 char* str = (char*)malloc(len);
1714 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1715 str, len, NULL, &used_default);
1719 /* The win32_ansipath() function takes a Unicode filename and converts it
1720 * into the current Windows codepage. If some characters cannot be mapped,
1721 * then it will convert the short name instead.
1723 * The buffer to the ansi pathname must be freed with win32_free() when it
1724 * is no longer needed.
1726 * The argument to win32_ansipath() must exist before this function is
1727 * called; otherwise there is no way to determine the short path name.
1729 * Ideas for future refinement:
1730 * - Only convert those segments of the path that are not in the current
1731 * codepage, but leave the other segments in their long form.
1732 * - If the resulting name is longer than MAX_PATH, start converting
1733 * additional path segments into short names until the full name
1734 * is shorter than MAX_PATH. Shorten the filename part last!
1737 win32_ansipath(const WCHAR *widename)
1740 BOOL use_default = FALSE;
1741 size_t widelen = wcslen(widename)+1;
1742 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1743 NULL, 0, NULL, NULL);
1744 name = (char*)win32_malloc(len);
1748 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1749 name, len, NULL, &use_default);
1751 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1753 WCHAR *shortname = (WCHAR*)win32_malloc(shortlen*sizeof(WCHAR));
1756 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1758 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1759 NULL, 0, NULL, NULL);
1760 name = (char*)win32_realloc(name, len);
1763 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1764 name, len, NULL, NULL);
1765 win32_free(shortname);
1771 /* the returned string must be freed with win32_freeenvironmentstrings which is
1772 * implemented as a macro
1773 * void win32_freeenvironmentstrings(void* block)
1776 win32_getenvironmentstrings(void)
1778 LPWSTR lpWStr, lpWTmp;
1780 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1782 /* Get the process environment strings */
1783 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1784 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1785 env_len = wcslen(lpWTmp);
1786 /* calculate the size of the environment strings */
1787 wenvstrings_len += env_len + 1;
1790 /* Get the number of bytes required to store the ACP encoded string */
1791 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1792 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL);
1793 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1797 /* Convert the string from UTF-16 encoding to ACP encoding */
1798 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1799 aenvstrings_len, NULL, NULL);
1801 FreeEnvironmentStringsW(lpWStr);
1807 win32_getenv(const char *name)
1814 needlen = GetEnvironmentVariableA(name,NULL,0);
1816 curitem = sv_2mortal(newSVpvs(""));
1818 SvGROW(curitem, needlen+1);
1819 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1821 } while (needlen >= SvLEN(curitem));
1822 SvCUR_set(curitem, needlen);
1825 last_err = GetLastError();
1826 if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
1827 /* It appears the variable is in the env, but the Win32 API
1828 doesn't have a canned way of getting it. So we fall back to
1829 grabbing the whole env and pulling this value out if possible */
1830 char *envv = GetEnvironmentStrings();
1834 char *end = strchr(cur,'=');
1835 if (end && end != cur) {
1837 if (strEQ(cur,name)) {
1838 curitem = sv_2mortal(newSVpv(end+1,0));
1843 cur = end + strlen(end+1)+2;
1845 else if ((len = strlen(cur)))
1848 FreeEnvironmentStrings(envv);
1850 #ifndef WIN32_NO_REGISTRY
1852 /* last ditch: allow any environment variables that begin with 'PERL'
1853 to be obtained from the registry, if found there */
1854 if (strBEGINs(name, "PERL"))
1855 (void)get_regstr(name, &curitem);
1859 if (curitem && SvCUR(curitem))
1860 return SvPVX(curitem);
1866 win32_putenv(const char *name)
1873 curitem = (char *) win32_malloc(strlen(name)+1);
1874 strcpy(curitem, name);
1875 val = strchr(curitem, '=');
1877 /* The sane way to deal with the environment.
1878 * Has these advantages over putenv() & co.:
1879 * * enables us to store a truly empty value in the
1880 * environment (like in UNIX).
1881 * * we don't have to deal with RTL globals, bugs and leaks
1882 * (specifically, see http://support.microsoft.com/kb/235601).
1884 * Why you may want to use the RTL environment handling
1885 * (previously enabled by USE_WIN32_RTL_ENV):
1886 * * environ[] and RTL functions will not reflect changes,
1887 * which might be an issue if extensions want to access
1888 * the env. via RTL. This cuts both ways, since RTL will
1889 * not see changes made by extensions that call the Win32
1890 * functions directly, either.
1894 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1897 win32_free(curitem);
1903 filetime_to_clock(PFILETIME ft)
1905 __int64 qw = ft->dwHighDateTime;
1907 qw |= ft->dwLowDateTime;
1908 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1913 win32_times(struct tms *timebuf)
1918 clock_t process_time_so_far = clock();
1919 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1921 timebuf->tms_utime = filetime_to_clock(&user);
1922 timebuf->tms_stime = filetime_to_clock(&kernel);
1923 timebuf->tms_cutime = 0;
1924 timebuf->tms_cstime = 0;
1926 /* That failed - e.g. Win95 fallback to clock() */
1927 timebuf->tms_utime = process_time_so_far;
1928 timebuf->tms_stime = 0;
1929 timebuf->tms_cutime = 0;
1930 timebuf->tms_cstime = 0;
1932 return process_time_so_far;
1935 /* fix utime() so it works on directories in NT */
1937 filetime_from_time(PFILETIME pFileTime, time_t Time)
1939 struct tm *pTM = localtime(&Time);
1940 SYSTEMTIME SystemTime;
1946 SystemTime.wYear = pTM->tm_year + 1900;
1947 SystemTime.wMonth = pTM->tm_mon + 1;
1948 SystemTime.wDay = pTM->tm_mday;
1949 SystemTime.wHour = pTM->tm_hour;
1950 SystemTime.wMinute = pTM->tm_min;
1951 SystemTime.wSecond = pTM->tm_sec;
1952 SystemTime.wMilliseconds = 0;
1954 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1955 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1959 win32_unlink(const char *filename)
1965 filename = PerlDir_mapA(filename);
1966 attrs = GetFileAttributesA(filename);
1967 if (attrs == 0xFFFFFFFF) {
1971 if (attrs & FILE_ATTRIBUTE_READONLY) {
1972 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1973 ret = unlink(filename);
1975 (void)SetFileAttributesA(filename, attrs);
1978 ret = unlink(filename);
1983 win32_utime(const char *filename, struct utimbuf *times)
1990 struct utimbuf TimeBuffer;
1993 filename = PerlDir_mapA(filename);
1994 rc = utime(filename, times);
1996 /* EACCES: path specifies directory or readonly file */
1997 if (rc == 0 || errno != EACCES)
2000 if (times == NULL) {
2001 times = &TimeBuffer;
2002 time(×->actime);
2003 times->modtime = times->actime;
2006 /* This will (and should) still fail on readonly files */
2007 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
2008 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
2009 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2010 if (handle == INVALID_HANDLE_VALUE)
2013 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
2014 filetime_from_time(&ftAccess, times->actime) &&
2015 filetime_from_time(&ftWrite, times->modtime) &&
2016 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
2021 CloseHandle(handle);
2026 unsigned __int64 ft_i64;
2031 #define Const64(x) x##LL
2033 #define Const64(x) x##i64
2035 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
2036 #define EPOCH_BIAS Const64(116444736000000000)
2038 /* NOTE: This does not compute the timezone info (doing so can be expensive,
2039 * and appears to be unsupported even by glibc) */
2041 win32_gettimeofday(struct timeval *tp, void *not_used)
2045 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
2046 GetSystemTimeAsFileTime(&ft.ft_val);
2048 /* seconds since epoch */
2049 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
2051 /* microseconds remaining */
2052 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
2058 win32_uname(struct utsname *name)
2060 struct hostent *hep;
2061 STRLEN nodemax = sizeof(name->nodename)-1;
2064 switch (g_osver.dwPlatformId) {
2065 case VER_PLATFORM_WIN32_WINDOWS:
2066 strcpy(name->sysname, "Windows");
2068 case VER_PLATFORM_WIN32_NT:
2069 strcpy(name->sysname, "Windows NT");
2071 case VER_PLATFORM_WIN32s:
2072 strcpy(name->sysname, "Win32s");
2075 strcpy(name->sysname, "Win32 Unknown");
2080 sprintf(name->release, "%d.%d",
2081 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
2084 sprintf(name->version, "Build %d",
2085 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
2086 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
2087 if (g_osver.szCSDVersion[0]) {
2088 char *buf = name->version + strlen(name->version);
2089 sprintf(buf, " (%s)", g_osver.szCSDVersion);
2093 hep = win32_gethostbyname("localhost");
2095 STRLEN len = strlen(hep->h_name);
2096 if (len <= nodemax) {
2097 strcpy(name->nodename, hep->h_name);
2100 strncpy(name->nodename, hep->h_name, nodemax);
2101 name->nodename[nodemax] = '\0';
2106 if (!GetComputerName(name->nodename, &sz))
2107 *name->nodename = '\0';
2110 /* machine (architecture) */
2115 GetSystemInfo(&info);
2117 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION))
2118 procarch = info.u.s.wProcessorArchitecture;
2120 procarch = info.wProcessorArchitecture;
2123 case PROCESSOR_ARCHITECTURE_INTEL:
2124 arch = "x86"; break;
2125 case PROCESSOR_ARCHITECTURE_IA64:
2126 arch = "ia64"; break;
2127 case PROCESSOR_ARCHITECTURE_AMD64:
2128 arch = "amd64"; break;
2129 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2130 arch = "unknown"; break;
2132 sprintf(name->machine, "unknown(0x%x)", procarch);
2133 arch = name->machine;
2136 if (name->machine != arch)
2137 strcpy(name->machine, arch);
2142 /* Timing related stuff */
2145 do_raise(pTHX_ int sig)
2147 if (sig < SIG_SIZE) {
2148 Sighandler_t handler = w32_sighandler[sig];
2149 if (handler == SIG_IGN) {
2152 else if (handler != SIG_DFL) {
2157 /* Choose correct default behaviour */
2173 /* Tell caller to exit thread/process as appropriate */
2178 sig_terminate(pTHX_ int sig)
2180 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2181 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2188 win32_async_check(pTHX)
2191 HWND hwnd = w32_message_hwnd;
2193 /* Reset w32_poll_count before doing anything else, incase we dispatch
2194 * messages that end up calling back into perl */
2197 if (hwnd != INVALID_HANDLE_VALUE) {
2198 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2199 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2204 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2205 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2207 /* re-post a WM_QUIT message (we'll mark it as read later) */
2208 if(msg.message == WM_QUIT) {
2209 PostQuitMessage((int)msg.wParam);
2213 if(!CallMsgFilter(&msg, MSGF_USER))
2215 TranslateMessage(&msg);
2216 DispatchMessage(&msg);
2221 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2222 * This is necessary when we are being called by win32_msgwait() to
2223 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2224 * message over and over. An example how this can happen is when
2225 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2226 * is generating messages before the process terminated.
2228 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD);
2230 /* Above or other stuff may have set a signal flag */
2237 /* This function will not return until the timeout has elapsed, or until
2238 * one of the handles is ready. */
2240 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2242 /* We may need several goes at this - so compute when we stop */
2244 unsigned __int64 endtime = timeout;
2245 if (timeout != INFINITE) {
2246 GetSystemTimeAsFileTime(&ticks.ft_val);
2247 ticks.ft_i64 /= 10000;
2248 endtime += ticks.ft_i64;
2250 /* This was a race condition. Do not let a non INFINITE timeout to
2251 * MsgWaitForMultipleObjects roll under 0 creating a near
2252 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the
2253 * user who did a CORE perl function with a non infinity timeout,
2254 * sleep for example. This is 64 to 32 truncation minefield.
2256 * This scenario can only be created if the timespan from the return of
2257 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To
2258 * generate the scenario, manual breakpoints in a C debugger are required,
2259 * or a context switch occurred in win32_async_check in PeekMessage, or random
2260 * messages are delivered to the *thread* message queue of the Perl thread
2261 * from another process (msctf.dll doing IPC among its instances, VS debugger
2262 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096].
2264 while (ticks.ft_i64 <= endtime) {
2265 /* if timeout's type is lengthened, remember to split 64b timeout
2266 * into multiple non-infinity runs of MWFMO */
2267 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE,
2268 (DWORD)(endtime - ticks.ft_i64),
2269 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2272 if (result == WAIT_TIMEOUT) {
2273 /* Ran out of time - explicit return of zero to avoid -ve if we
2274 have scheduling issues
2278 if (timeout != INFINITE) {
2279 GetSystemTimeAsFileTime(&ticks.ft_val);
2280 ticks.ft_i64 /= 10000;
2282 if (result == WAIT_OBJECT_0 + count) {
2283 /* Message has arrived - check it */
2284 (void)win32_async_check(aTHX);
2287 if (ticks.ft_i64 > endtime)
2288 endtime = ticks.ft_i64;
2293 /* Not timeout or message - one of handles is ready */
2297 /* If we are past the end say zero */
2298 if (!ticks.ft_i64 || ticks.ft_i64 > endtime)
2300 /* compute time left to wait */
2301 ticks.ft_i64 = endtime - ticks.ft_i64;
2302 /* if more ms than DWORD, then return max DWORD */
2303 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX;
2307 win32_internal_wait(pTHX_ int *status, DWORD timeout)
2309 /* XXX this wait emulation only knows about processes
2310 * spawned via win32_spawnvp(P_NOWAIT, ...).
2313 DWORD exitcode, waitcode;
2316 if (w32_num_pseudo_children) {
2317 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2318 timeout, &waitcode);
2319 /* Time out here if there are no other children to wait for. */
2320 if (waitcode == WAIT_TIMEOUT) {
2321 if (!w32_num_children) {
2325 else if (waitcode != WAIT_FAILED) {
2326 if (waitcode >= WAIT_ABANDONED_0
2327 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2328 i = waitcode - WAIT_ABANDONED_0;
2330 i = waitcode - WAIT_OBJECT_0;
2331 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2332 *status = (int)((exitcode & 0xff) << 8);
2333 retval = (int)w32_pseudo_child_pids[i];
2334 remove_dead_pseudo_process(i);
2341 if (!w32_num_children) {
2346 /* if a child exists, wait for it to die */
2347 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2348 if (waitcode == WAIT_TIMEOUT) {
2351 if (waitcode != WAIT_FAILED) {
2352 if (waitcode >= WAIT_ABANDONED_0
2353 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2354 i = waitcode - WAIT_ABANDONED_0;
2356 i = waitcode - WAIT_OBJECT_0;
2357 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2358 *status = (int)((exitcode & 0xff) << 8);
2359 retval = (int)w32_child_pids[i];
2360 remove_dead_process(i);
2365 errno = GetLastError();
2370 win32_waitpid(int pid, int *status, int flags)
2373 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2376 if (pid == -1) /* XXX threadid == 1 ? */
2377 return win32_internal_wait(aTHX_ status, timeout);
2380 child = find_pseudo_pid(aTHX_ -pid);
2382 HANDLE hThread = w32_pseudo_child_handles[child];
2384 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2385 if (waitcode == WAIT_TIMEOUT) {
2388 else if (waitcode == WAIT_OBJECT_0) {
2389 if (GetExitCodeThread(hThread, &waitcode)) {
2390 *status = (int)((waitcode & 0xff) << 8);
2391 retval = (int)w32_pseudo_child_pids[child];
2392 remove_dead_pseudo_process(child);
2404 child = find_pid(aTHX_ pid);
2406 hProcess = w32_child_handles[child];
2407 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2408 if (waitcode == WAIT_TIMEOUT) {
2411 else if (waitcode == WAIT_OBJECT_0) {
2412 if (GetExitCodeProcess(hProcess, &waitcode)) {
2413 *status = (int)((waitcode & 0xff) << 8);
2414 retval = (int)w32_child_pids[child];
2415 remove_dead_process(child);
2423 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
2425 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2426 if (waitcode == WAIT_TIMEOUT) {
2427 CloseHandle(hProcess);
2430 else if (waitcode == WAIT_OBJECT_0) {
2431 if (GetExitCodeProcess(hProcess, &waitcode)) {
2432 *status = (int)((waitcode & 0xff) << 8);
2433 CloseHandle(hProcess);
2437 CloseHandle(hProcess);
2443 return retval >= 0 ? pid : retval;
2447 win32_wait(int *status)
2450 return win32_internal_wait(aTHX_ status, INFINITE);
2453 DllExport unsigned int
2454 win32_sleep(unsigned int t)
2457 /* Win32 times are in ms so *1000 in and /1000 out */
2458 if (t > UINT_MAX / 1000) {
2459 Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
2460 "sleep(%lu) too large", t);
2462 return win32_msgwait(aTHX_ 0, NULL, t * 1000, NULL) / 1000;
2469 win32_msgwait(aTHX_ 0, NULL, INFINITE, NULL);
2473 DllExport unsigned int
2474 win32_alarm(unsigned int sec)
2477 * the 'obvious' implentation is SetTimer() with a callback
2478 * which does whatever receiving SIGALRM would do
2479 * we cannot use SIGALRM even via raise() as it is not
2480 * one of the supported codes in <signal.h>
2484 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2485 w32_message_hwnd = win32_create_message_window();
2488 if (w32_message_hwnd == NULL)
2489 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2492 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2497 KillTimer(w32_message_hwnd, w32_timerid);
2504 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2507 win32_crypt(const char *txt, const char *salt)
2510 return des_fcrypt(txt, salt, w32_crypt_buffer);
2513 /* simulate flock by locking a range on the file */
2515 #define LK_LEN 0xffff0000
2518 win32_flock(int fd, int oper)
2524 fh = (HANDLE)_get_osfhandle(fd);
2525 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */
2528 memset(&o, 0, sizeof(o));
2531 case LOCK_SH: /* shared lock */
2532 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
2535 case LOCK_EX: /* exclusive lock */
2536 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
2539 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2540 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
2543 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2544 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2548 case LOCK_UN: /* unlock lock */
2549 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o))
2552 default: /* unknown */
2557 if (GetLastError() == ERROR_LOCK_VIOLATION)
2558 errno = EWOULDBLOCK;
2567 extern int convert_wsa_error_to_errno(int wsaerr); /* in win32sck.c */
2569 /* Get the errno value corresponding to the given err. This function is not
2570 * intended to handle conversion of general GetLastError() codes. It only exists
2571 * to translate Windows sockets error codes from WSAGetLastError(). Such codes
2572 * used to be assigned to errno/$! in earlier versions of perl; this function is
2573 * used to catch any old Perl code which is still trying to assign such values
2574 * to $! and convert them to errno values instead.
2577 win32_get_errno(int err)
2579 return convert_wsa_error_to_errno(err);
2583 * redirected io subsystem for all XS modules
2596 return (&(_environ));
2599 /* the rest are the remapped stdio routines */
2619 win32_ferror(FILE *fp)
2621 return (ferror(fp));
2626 win32_feof(FILE *fp)
2631 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2632 extern int convert_errno_to_wsa_error(int err); /* in win32sck.c */
2636 * Since the errors returned by the socket error function
2637 * WSAGetLastError() are not known by the library routine strerror
2638 * we have to roll our own to cover the case of socket errors
2639 * that could not be converted to regular errno values by
2640 * get_last_socket_error() in win32/win32sck.c.
2644 win32_strerror(int e)
2646 #if !defined __MINGW32__ /* compiler intolerance */
2647 extern int sys_nerr;
2650 if (e < 0 || e > sys_nerr) {
2654 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT
2655 /* VC10+ and some MinGW/gcc-4.8+ define a "POSIX supplement" of errno
2656 * values ranging from EADDRINUSE (100) to EWOULDBLOCK (140), but
2657 * sys_nerr is still 43 and strerror() returns "Unknown error" for them.
2658 * We must therefore still roll our own messages for these codes, and
2659 * additionally map them to corresponding Windows (sockets) error codes
2660 * first to avoid getting the wrong system message.
2662 else if (inRANGE(e, EADDRINUSE, EWOULDBLOCK)) {
2663 e = convert_errno_to_wsa_error(e);
2667 aTHXa(PERL_GET_THX);
2668 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
2669 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0,
2670 w32_strerror_buffer, sizeof(w32_strerror_buffer),
2673 strcpy(w32_strerror_buffer, "Unknown Error");
2675 return w32_strerror_buffer;
2679 #define strerror win32_strerror
2683 win32_str_os_error(void *sv, DWORD dwErr)
2687 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2688 |FORMAT_MESSAGE_IGNORE_INSERTS
2689 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2690 dwErr, 0, (char *)&sMsg, 1, NULL);
2691 /* strip trailing whitespace and period */
2694 --dwLen; /* dwLen doesn't include trailing null */
2695 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2696 if ('.' != sMsg[dwLen])
2701 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2703 dwLen = sprintf(sMsg,
2704 "Unknown error #0x%lX (lookup 0x%lX)",
2705 dwErr, GetLastError());
2709 sv_setpvn((SV*)sv, sMsg, dwLen);
2715 win32_fprintf(FILE *fp, const char *format, ...)
2718 va_start(marker, format); /* Initialize variable arguments. */
2720 return (vfprintf(fp, format, marker));
2724 win32_printf(const char *format, ...)
2727 va_start(marker, format); /* Initialize variable arguments. */
2729 return (vprintf(format, marker));
2733 win32_vfprintf(FILE *fp, const char *format, va_list args)
2735 return (vfprintf(fp, format, args));
2739 win32_vprintf(const char *format, va_list args)
2741 return (vprintf(format, args));
2745 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2747 return fread(buf, size, count, fp);
2751 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2753 return fwrite(buf, size, count, fp);
2756 #define MODE_SIZE 10
2759 win32_fopen(const char *filename, const char *mode)
2767 if (stricmp(filename, "/dev/null")==0)
2770 aTHXa(PERL_GET_THX);
2771 f = fopen(PerlDir_mapA(filename), mode);
2772 /* avoid buffering headaches for child processes */
2773 if (f && *mode == 'a')
2774 win32_fseek(f, 0, SEEK_END);
2779 win32_fdopen(int handle, const char *mode)
2782 f = fdopen(handle, (char *) mode);
2783 /* avoid buffering headaches for child processes */
2784 if (f && *mode == 'a')
2785 win32_fseek(f, 0, SEEK_END);
2790 win32_freopen(const char *path, const char *mode, FILE *stream)
2793 if (stricmp(path, "/dev/null")==0)
2796 aTHXa(PERL_GET_THX);
2797 return freopen(PerlDir_mapA(path), mode, stream);
2801 win32_fclose(FILE *pf)
2803 #ifdef WIN32_NO_SOCKETS
2806 return my_fclose(pf); /* defined in win32sck.c */
2811 win32_fputs(const char *s,FILE *pf)
2813 return fputs(s, pf);
2817 win32_fputc(int c,FILE *pf)
2823 win32_ungetc(int c,FILE *pf)
2825 return ungetc(c,pf);
2829 win32_getc(FILE *pf)
2835 win32_fileno(FILE *pf)
2841 win32_clearerr(FILE *pf)
2848 win32_fflush(FILE *pf)
2854 win32_ftell(FILE *pf)
2856 #if defined(WIN64) || defined(USE_LARGE_FILES)
2858 if (fgetpos(pf, &pos))
2867 win32_fseek(FILE *pf, Off_t offset,int origin)
2869 #if defined(WIN64) || defined(USE_LARGE_FILES)
2873 if (fgetpos(pf, &pos))
2878 fseek(pf, 0, SEEK_END);
2879 pos = _telli64(fileno(pf));
2888 return fsetpos(pf, &offset);
2890 return fseek(pf, (long)offset, origin);
2895 win32_fgetpos(FILE *pf,fpos_t *p)
2897 return fgetpos(pf, p);
2901 win32_fsetpos(FILE *pf,const fpos_t *p)
2903 return fsetpos(pf, p);
2907 win32_rewind(FILE *pf)
2916 return win32_tmpfd_mode(0);
2920 win32_tmpfd_mode(int mode)
2922 char prefix[MAX_PATH+1];
2923 char filename[MAX_PATH+1];
2924 DWORD len = GetTempPath(MAX_PATH, prefix);
2925 mode &= ~( O_ACCMODE | O_CREAT | O_EXCL );
2927 if (len && len < MAX_PATH) {
2928 if (GetTempFileName(prefix, "plx", 0, filename)) {
2929 HANDLE fh = CreateFile(filename,
2930 DELETE | GENERIC_READ | GENERIC_WRITE,
2934 FILE_ATTRIBUTE_NORMAL
2935 | FILE_FLAG_DELETE_ON_CLOSE,
2937 if (fh != INVALID_HANDLE_VALUE) {
2938 int fd = win32_open_osfhandle((intptr_t)fh, mode);
2941 DEBUG_p(PerlIO_printf(Perl_debug_log,
2942 "Created tmpfile=%s\n",filename));
2954 int fd = win32_tmpfd();
2956 return win32_fdopen(fd, "w+b");
2968 win32_fstat(int fd, Stat_t *sbufptr)
2970 #if defined(WIN64) || defined(USE_LARGE_FILES)
2971 return _fstati64(fd, sbufptr);
2973 return fstat(fd, sbufptr);
2978 win32_pipe(int *pfd, unsigned int size, int mode)
2980 return _pipe(pfd, size, mode);
2984 win32_popenlist(const char *mode, IV narg, SV **args)
2988 return do_popen(mode, NULL, narg, args);
2992 do_popen(const char *mode, const char *command, IV narg, SV **args) {
3001 const char **args_pvs = NULL;
3003 /* establish which ends read and write */
3004 if (strchr(mode,'w')) {
3005 stdfd = 0; /* stdin */
3008 nhandle = STD_INPUT_HANDLE;
3010 else if (strchr(mode,'r')) {
3011 stdfd = 1; /* stdout */
3014 nhandle = STD_OUTPUT_HANDLE;
3019 /* set the correct mode */
3020 if (strchr(mode,'b'))
3022 else if (strchr(mode,'t'))
3025 ourmode = _fmode & (O_TEXT | O_BINARY);
3027 /* the child doesn't inherit handles */
3028 ourmode |= O_NOINHERIT;
3030 if (win32_pipe(p, 512, ourmode) == -1)
3033 /* Previously this code redirected stdin/out temporarily so the
3034 child process inherited those handles, this caused race
3035 conditions when another thread was writing/reading those
3038 To avoid that we just feed the handles to CreateProcess() so
3039 the handles are redirected only in the child.
3041 handles[child] = p[child];
3042 handles[parent] = -1;
3045 /* CreateProcess() requires inheritable handles */
3046 if (!SetHandleInformation((HANDLE)_get_osfhandle(p[child]), HANDLE_FLAG_INHERIT,
3047 HANDLE_FLAG_INHERIT)) {
3051 /* start the child */
3056 if ((childpid = do_spawn2_handles(aTHX_ command, EXECF_SPAWN_NOWAIT, handles)) == -1)
3062 const char *exe_name;
3064 Newx(args_pvs, narg + 1 + w32_perlshell_items, const char *);
3065 SAVEFREEPV(args_pvs);
3066 for (i = 0; i < narg; ++i)
3067 args_pvs[i] = SvPV_nolen(args[i]);
3069 exe_name = qualified_path(args_pvs[0], TRUE);
3071 /* let CreateProcess() try to find it instead */
3072 exe_name = args_pvs[0];
3074 if ((childpid = do_spawnvp_handles(P_NOWAIT, exe_name, args_pvs, handles)) == -1) {
3079 win32_close(p[child]);
3081 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3083 /* set process id so that it can be returned by perl's open() */
3084 PL_forkprocess = childpid;
3087 /* we have an fd, return a file stream */
3088 return (PerlIO_fdopen(p[parent], (char *)mode));
3091 /* we don't need to check for errors here */
3099 * a popen() clone that respects PERL5SHELL
3101 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
3105 win32_popen(const char *command, const char *mode)
3107 #ifdef USE_RTL_POPEN
3108 return _popen(command, mode);
3110 return do_popen(mode, command, 0, NULL);
3111 #endif /* USE_RTL_POPEN */
3119 win32_pclose(PerlIO *pf)
3121 #ifdef USE_RTL_POPEN
3125 int childpid, status;
3128 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3131 childpid = SvIVX(sv);
3147 if (win32_waitpid(childpid, &status, 0) == -1)
3152 #endif /* USE_RTL_POPEN */
3156 win32_link(const char *oldname, const char *newname)
3159 WCHAR wOldName[MAX_PATH+1];
3160 WCHAR wNewName[MAX_PATH+1];
3162 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3163 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3164 ((aTHXa(PERL_GET_THX)), wcscpy(wOldName, PerlDir_mapW(wOldName)),
3165 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3169 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for
3170 both permissions errors and if the source is a directory, while
3171 POSIX wants EACCES and EPERM respectively.
3173 Determined by experimentation on Windows 7 x64 SP1, since MS
3174 don't document what error codes are returned.
3176 switch (GetLastError()) {
3177 case ERROR_BAD_NET_NAME:
3178 case ERROR_BAD_NETPATH:
3179 case ERROR_BAD_PATHNAME:
3180 case ERROR_FILE_NOT_FOUND:
3181 case ERROR_FILENAME_EXCED_RANGE:
3182 case ERROR_INVALID_DRIVE:
3183 case ERROR_PATH_NOT_FOUND:
3186 case ERROR_ALREADY_EXISTS:
3189 case ERROR_ACCESS_DENIED:
3192 case ERROR_NOT_SAME_DEVICE:
3195 case ERROR_DISK_FULL:
3198 case ERROR_NOT_ENOUGH_QUOTA:
3202 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */
3210 win32_rename(const char *oname, const char *newname)
3212 char szOldName[MAX_PATH+1];
3214 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3217 if (stricmp(newname, oname))
3218 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3219 strcpy(szOldName, PerlDir_mapA(oname));
3221 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3223 DWORD err = GetLastError();
3225 case ERROR_BAD_NET_NAME:
3226 case ERROR_BAD_NETPATH:
3227 case ERROR_BAD_PATHNAME:
3228 case ERROR_FILE_NOT_FOUND:
3229 case ERROR_FILENAME_EXCED_RANGE:
3230 case ERROR_INVALID_DRIVE:
3231 case ERROR_NO_MORE_FILES:
3232 case ERROR_PATH_NOT_FOUND:
3235 case ERROR_DISK_FULL:
3238 case ERROR_NOT_ENOUGH_QUOTA:
3251 win32_setmode(int fd, int mode)
3253 return setmode(fd, mode);
3257 win32_chsize(int fd, Off_t size)
3259 #if defined(WIN64) || defined(USE_LARGE_FILES)
3261 Off_t cur, end, extend;
3263 cur = win32_tell(fd);
3266 end = win32_lseek(fd, 0, SEEK_END);
3269 extend = size - end;
3273 else if (extend > 0) {
3274 /* must grow the file, padding with nulls */
3276 int oldmode = win32_setmode(fd, O_BINARY);
3278 memset(b, '\0', sizeof(b));
3280 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3281 count = win32_write(fd, b, count);
3282 if ((int)count < 0) {
3286 } while ((extend -= count) > 0);
3287 win32_setmode(fd, oldmode);
3290 /* shrink the file */
3291 win32_lseek(fd, size, SEEK_SET);
3292 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3297 win32_lseek(fd, cur, SEEK_SET);
3300 return chsize(fd, (long)size);
3305 win32_lseek(int fd, Off_t offset, int origin)
3307 #if defined(WIN64) || defined(USE_LARGE_FILES)
3308 return _lseeki64(fd, offset, origin);
3310 return lseek(fd, (long)offset, origin);
3317 #if defined(WIN64) || defined(USE_LARGE_FILES)
3318 return _telli64(fd);
3325 win32_open(const char *path, int flag, ...)
3332 pmode = va_arg(ap, int);
3335 if (stricmp(path, "/dev/null")==0)
3338 aTHXa(PERL_GET_THX);
3339 return open(PerlDir_mapA(path), flag, pmode);
3342 /* close() that understands socket */
3343 extern int my_close(int); /* in win32sck.c */
3348 #ifdef WIN32_NO_SOCKETS
3351 return my_close(fd);
3362 win32_isatty(int fd)
3364 /* The Microsoft isatty() function returns true for *all*
3365 * character mode devices, including "nul". Our implementation
3366 * should only return true if the handle has a console buffer.
3369 HANDLE fh = (HANDLE)_get_osfhandle(fd);
3370 if (fh == (HANDLE)-1) {
3371 /* errno is already set to EBADF */
3375 if (GetConsoleMode(fh, &mode))
3389 win32_dup2(int fd1,int fd2)
3391 return dup2(fd1,fd2);
3395 win32_read(int fd, void *buf, unsigned int cnt)
3397 return read(fd, buf, cnt);
3401 win32_write(int fd, const void *buf, unsigned int cnt)
3403 return write(fd, buf, cnt);
3407 win32_mkdir(const char *dir, int mode)
3410 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3414 win32_rmdir(const char *dir)
3417 return rmdir(PerlDir_mapA(dir));
3421 win32_chdir(const char *dir)
3423 if (!dir || !*dir) {
3431 win32_access(const char *path, int mode)
3434 return access(PerlDir_mapA(path), mode);
3438 win32_chmod(const char *path, int mode)
3441 return chmod(PerlDir_mapA(path), mode);
3446 create_command_line(char *cname, STRLEN clen, const char * const *args)
3453 bool bat_file = FALSE;
3454 bool cmd_shell = FALSE;
3455 bool dumb_shell = FALSE;
3456 bool extra_quotes = FALSE;
3457 bool quote_next = FALSE;
3460 cname = (char*)args[0];
3462 /* The NT cmd.exe shell has the following peculiarity that needs to be
3463 * worked around. It strips a leading and trailing dquote when any
3464 * of the following is true:
3465 * 1. the /S switch was used
3466 * 2. there are more than two dquotes
3467 * 3. there is a special character from this set: &<>()@^|
3468 * 4. no whitespace characters within the two dquotes
3469 * 5. string between two dquotes isn't an executable file
3470 * To work around this, we always add a leading and trailing dquote
3471 * to the string, if the first argument is either "cmd.exe" or "cmd",
3472 * and there were at least two or more arguments passed to cmd.exe
3473 * (not including switches).
3474 * XXX the above rules (from "cmd /?") don't seem to be applied
3475 * always, making for the convolutions below :-(
3479 clen = strlen(cname);
3482 && (stricmp(&cname[clen-4], ".bat") == 0
3483 || (stricmp(&cname[clen-4], ".cmd") == 0)))
3489 char *exe = strrchr(cname, '/');
3490 char *exe2 = strrchr(cname, '\\');
3497 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3501 else if (stricmp(exe, "command.com") == 0
3502 || stricmp(exe, "command") == 0)
3509 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3510 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3511 STRLEN curlen = strlen(arg);
3512 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3513 len += 2; /* assume quoting needed (worst case) */
3515 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3517 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3520 Newx(cmd, len, char);
3525 extra_quotes = TRUE;
3528 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3530 STRLEN curlen = strlen(arg);
3532 /* we want to protect empty arguments and ones with spaces with
3533 * dquotes, but only if they aren't already there */
3538 else if (quote_next) {
3539 /* see if it really is multiple arguments pretending to
3540 * be one and force a set of quotes around it */
3541 if (*find_next_space(arg))
3544 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3546 while (i < curlen) {
3547 if (isSPACE(arg[i])) {
3550 else if (arg[i] == '"') {
3574 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3575 && stricmp(arg+curlen-2, "/c") == 0)
3577 /* is there a next argument? */
3578 if (args[index+1]) {
3579 /* are there two or more next arguments? */
3580 if (args[index+2]) {
3582 extra_quotes = TRUE;
3585 /* single argument, force quoting if it has spaces */
3600 static const char *exe_extensions[] =
3602 ".exe", /* this must be first */
3608 qualified_path(const char *cmd, bool other_exts)
3611 char *fullcmd, *curfullcmd;
3617 fullcmd = (char*)cmd;
3619 if (*fullcmd == '/' || *fullcmd == '\\')
3628 pathstr = PerlEnv_getenv("PATH");
3630 /* worst case: PATH is a single directory; we need additional space
3631 * to append "/", ".exe" and trailing "\0" */
3632 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3633 curfullcmd = fullcmd;
3638 /* start by appending the name to the current prefix */
3639 strcpy(curfullcmd, cmd);
3640 curfullcmd += cmdlen;
3642 /* if it doesn't end with '.', or has no extension, try adding
3643 * a trailing .exe first */
3644 if (cmd[cmdlen-1] != '.'
3645 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3648 /* first extension is .exe */
3649 int ext_limit = other_exts ? C_ARRAY_LENGTH(exe_extensions) : 1;
3650 for (i = 0; i < ext_limit; ++i) {
3651 strcpy(curfullcmd, exe_extensions[i]);
3652 res = GetFileAttributes(fullcmd);
3653 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3660 /* that failed, try the bare name */
3661 res = GetFileAttributes(fullcmd);
3662 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3665 /* quit if no other path exists, or if cmd already has path */
3666 if (!pathstr || !*pathstr || has_slash)
3669 /* skip leading semis */
3670 while (*pathstr == ';')
3673 /* build a new prefix from scratch */
3674 curfullcmd = fullcmd;
3675 while (*pathstr && *pathstr != ';') {
3676 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3677 pathstr++; /* skip initial '"' */
3678 while (*pathstr && *pathstr != '"') {
3679 *curfullcmd++ = *pathstr++;
3682 pathstr++; /* skip trailing '"' */
3685 *curfullcmd++ = *pathstr++;
3689 pathstr++; /* skip trailing semi */
3690 if (curfullcmd > fullcmd /* append a dir separator */
3691 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3693 *curfullcmd++ = '\\';
3701 /* The following are just place holders.
3702 * Some hosts may provide and environment that the OS is
3703 * not tracking, therefore, these host must provide that
3704 * environment and the current directory to CreateProcess
3708 win32_get_childenv(void)
3714 win32_free_childenv(void* d)
3719 win32_clearenv(void)
3721 char *envv = GetEnvironmentStrings();
3725 char *end = strchr(cur,'=');
3726 if (end && end != cur) {
3728 SetEnvironmentVariable(cur, NULL);
3730 cur = end + strlen(end+1)+2;
3732 else if ((len = strlen(cur)))
3735 FreeEnvironmentStrings(envv);
3739 win32_get_childdir(void)
3742 char szfilename[MAX_PATH+1];
3744 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
3745 Newx(ptr, strlen(szfilename)+1, char);
3746 strcpy(ptr, szfilename);
3751 win32_free_childdir(char* d)
3757 /* XXX this needs to be made more compatible with the spawnvp()
3758 * provided by the various RTLs. In particular, searching for
3759 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
3760 * This doesn't significantly affect perl itself, because we
3761 * always invoke things using PERL5SHELL if a direct attempt to
3762 * spawn the executable fails.
3764 * XXX splitting and rejoining the commandline between do_aspawn()
3765 * and win32_spawnvp() could also be avoided.
3769 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
3771 #ifdef USE_RTL_SPAWNVP
3772 return _spawnvp(mode, cmdname, (char * const *)argv);
3774 return do_spawnvp_handles(mode, cmdname, argv, NULL);
3779 do_spawnvp_handles(int mode, const char *cmdname, const char *const *argv,
3780 const int *handles) {
3786 STARTUPINFO StartupInfo;
3787 PROCESS_INFORMATION ProcessInformation;
3790 char *fullcmd = NULL;
3791 char *cname = (char *)cmdname;
3795 clen = strlen(cname);
3796 /* if command name contains dquotes, must remove them */
3797 if (strchr(cname, '"')) {
3799 Newx(cname,clen+1,char);
3812 cmd = create_command_line(cname, clen, argv);
3814 aTHXa(PERL_GET_THX);
3815 env = PerlEnv_get_childenv();
3816 dir = PerlEnv_get_childdir();
3819 case P_NOWAIT: /* asynch + remember result */
3820 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
3825 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
3828 create |= CREATE_NEW_PROCESS_GROUP;
3831 case P_WAIT: /* synchronous execution */
3833 default: /* invalid mode */
3839 memset(&StartupInfo,0,sizeof(StartupInfo));
3840 StartupInfo.cb = sizeof(StartupInfo);
3841 memset(&tbl,0,sizeof(tbl));
3842 PerlEnv_get_child_IO(&tbl);
3843 StartupInfo.dwFlags = tbl.dwFlags;
3844 StartupInfo.dwX = tbl.dwX;
3845 StartupInfo.dwY = tbl.dwY;
3846 StartupInfo.dwXSize = tbl.dwXSize;
3847 StartupInfo.dwYSize = tbl.dwYSize;
3848 StartupInfo.dwXCountChars = tbl.dwXCountChars;
3849 StartupInfo.dwYCountChars = tbl.dwYCountChars;
3850 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
3851 StartupInfo.wShowWindow = tbl.wShowWindow;
3852 StartupInfo.hStdInput = handles && handles[0] != -1 ?
3853 (HANDLE)_get_osfhandle(handles[0]) : tbl.childStdIn;
3854 StartupInfo.hStdOutput = handles && handles[1] != -1 ?
3855 (HANDLE)_get_osfhandle(handles[1]) : tbl.childStdOut;
3856 StartupInfo.hStdError = handles && handles[2] != -1 ?
3857 (HANDLE)_get_osfhandle(handles[2]) : tbl.childStdErr;
3858 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
3859 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
3860 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
3862 create |= CREATE_NEW_CONSOLE;
3865 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3867 if (w32_use_showwindow) {
3868 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
3869 StartupInfo.wShowWindow = w32_showwindow;
3872 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
3875 if (!CreateProcess(cname, /* search PATH to find executable */
3876 cmd, /* executable, and its arguments */
3877 NULL, /* process attributes */
3878 NULL, /* thread attributes */
3879 TRUE, /* inherit handles */
3880 create, /* creation flags */
3881 (LPVOID)env, /* inherit environment */
3882 dir, /* inherit cwd */
3884 &ProcessInformation))
3886 /* initial NULL argument to CreateProcess() does a PATH
3887 * search, but it always first looks in the directory
3888 * where the current process was started, which behavior
3889 * is undesirable for backward compatibility. So we
3890 * jump through our own hoops by picking out the path
3891 * we really want it to use. */
3893 fullcmd = qualified_path(cname, FALSE);
3895 if (cname != cmdname)
3898 DEBUG_p(PerlIO_printf(Perl_debug_log,
3899 "Retrying [%s] with same args\n",
3909 if (mode == P_NOWAIT) {
3910 /* asynchronous spawn -- store handle, return PID */
3911 ret = (int)ProcessInformation.dwProcessId;
3913 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
3914 w32_child_pids[w32_num_children] = (DWORD)ret;
3919 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
3920 /* FIXME: if msgwait returned due to message perhaps forward the
3921 "signal" to the process
3923 GetExitCodeProcess(ProcessInformation.hProcess, &status);
3925 CloseHandle(ProcessInformation.hProcess);
3928 CloseHandle(ProcessInformation.hThread);
3931 PerlEnv_free_childenv(env);
3932 PerlEnv_free_childdir(dir);
3934 if (cname != cmdname)
3940 win32_execv(const char *cmdname, const char *const *argv)
3944 /* if this is a pseudo-forked child, we just want to spawn
3945 * the new program, and return */
3947 return _spawnv(P_WAIT, cmdname, argv);
3949 return _execv(cmdname, argv);
3953 win32_execvp(const char *cmdname, const char *const *argv)
3957 /* if this is a pseudo-forked child, we just want to spawn
3958 * the new program, and return */
3959 if (w32_pseudo_id) {
3960 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
3969 return _execvp(cmdname, argv);
3973 win32_perror(const char *str)
3979 win32_setbuf(FILE *pf, char *buf)
3985 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
3987 return setvbuf(pf, buf, type, size);
3991 win32_flushall(void)
3997 win32_fcloseall(void)
4003 win32_fgets(char *s, int n, FILE *pf)
4005 return fgets(s, n, pf);
4015 win32_fgetc(FILE *pf)
4021 win32_putc(int c, FILE *pf)
4027 win32_puts(const char *s)
4039 win32_putchar(int c)
4046 #ifndef USE_PERL_SBRK
4048 static char *committed = NULL; /* XXX threadead */
4049 static char *base = NULL; /* XXX threadead */
4050 static char *reserved = NULL; /* XXX threadead */
4051 static char *brk = NULL; /* XXX threadead */
4052 static DWORD pagesize = 0; /* XXX threadead */
4055 sbrk(ptrdiff_t need)
4060 GetSystemInfo(&info);
4061 /* Pretend page size is larger so we don't perpetually
4062 * call the OS to commit just one page ...
4064 pagesize = info.dwPageSize << 3;
4066 if (brk+need >= reserved)
4068 DWORD size = brk+need-reserved;
4070 char *prev_committed = NULL;
4071 if (committed && reserved && committed < reserved)
4073 /* Commit last of previous chunk cannot span allocations */
4074 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
4077 /* Remember where we committed from in case we want to decommit later */
4078 prev_committed = committed;
4079 committed = reserved;
4082 /* Reserve some (more) space
4083 * Contiguous blocks give us greater efficiency, so reserve big blocks -
4084 * this is only address space not memory...
4085 * Note this is a little sneaky, 1st call passes NULL as reserved
4086 * so lets system choose where we start, subsequent calls pass
4087 * the old end address so ask for a contiguous block
4090 if (size < 64*1024*1024)
4091 size = 64*1024*1024;
4092 size = ((size + pagesize - 1) / pagesize) * pagesize;
4093 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
4096 reserved = addr+size;
4106 /* The existing block could not be extended far enough, so decommit
4107 * anything that was just committed above and start anew */
4110 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
4113 reserved = base = committed = brk = NULL;
4124 if (brk > committed)
4126 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4128 if (committed+size > reserved)
4129 size = reserved-committed;
4130 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4143 win32_malloc(size_t size)
4145 return malloc(size);
4149 win32_calloc(size_t numitems, size_t size)
4151 return calloc(numitems,size);
4155 win32_realloc(void *block, size_t size)
4157 return realloc(block,size);
4161 win32_free(void *block)
4168 win32_open_osfhandle(intptr_t handle, int flags)
4170 return _open_osfhandle(handle, flags);
4174 win32_get_osfhandle(int fd)
4176 return (intptr_t)_get_osfhandle(fd);
4180 win32_fdupopen(FILE *pf)
4185 int fileno = win32_dup(win32_fileno(pf));
4187 /* open the file in the same mode */
4188 if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RD) {
4192 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_WR) {
4196 else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RW) {
4202 /* it appears that the binmode is attached to the
4203 * file descriptor so binmode files will be handled
4206 pfdup = win32_fdopen(fileno, mode);
4208 /* move the file pointer to the same position */
4209 if (!fgetpos(pf, &pos)) {
4210 fsetpos(pfdup, &pos);
4216 win32_dynaload(const char* filename)
4219 char buf[MAX_PATH+1];
4222 /* LoadLibrary() doesn't recognize forward slashes correctly,
4223 * so turn 'em back. */
4224 first = strchr(filename, '/');
4226 STRLEN len = strlen(filename);
4227 if (len <= MAX_PATH) {
4228 strcpy(buf, filename);
4229 filename = &buf[first - filename];
4231 if (*filename == '/')
4232 *(char*)filename = '\\';
4238 aTHXa(PERL_GET_THX);
4239 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4242 XS(w32_SetChildShowWindow)
4245 BOOL use_showwindow = w32_use_showwindow;
4246 /* use "unsigned short" because Perl has redefined "WORD" */
4247 unsigned short showwindow = w32_showwindow;
4250 croak_xs_usage(cv, "[showwindow]");
4252 if (items == 0 || !SvOK(ST(0)))
4253 w32_use_showwindow = FALSE;
4255 w32_use_showwindow = TRUE;
4256 w32_showwindow = (unsigned short)SvIV(ST(0));
4261 ST(0) = sv_2mortal(newSViv(showwindow));
4263 ST(0) = &PL_sv_undef;
4268 #ifdef PERL_IS_MINIPERL
4269 /* shelling out is much slower, full perl uses Win32.pm */
4273 /* Make the host for current directory */
4274 char* ptr = PerlEnv_get_childdir();
4277 * then it worked, set PV valid,
4278 * else return 'undef'
4281 SV *sv = sv_newmortal();
4283 PerlEnv_free_childdir(ptr);
4285 #ifndef INCOMPLETE_TAINTS
4297 Perl_init_os_extras(void)
4300 char *file = __FILE__;
4302 /* Initialize Win32CORE if it has been statically linked. */
4303 #ifndef PERL_IS_MINIPERL
4304 void (*pfn_init)(pTHX);
4305 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
4306 ? GetModuleHandle(NULL)
4307 : w32_perldll_handle);
4308 pfn_init = (void (*)(pTHX))GetProcAddress(module, "init_Win32CORE");
4309 aTHXa(PERL_GET_THX);
4313 aTHXa(PERL_GET_THX);
4316 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4317 #ifdef PERL_IS_MINIPERL
4318 newXS("Win32::GetCwd", w32_GetCwd, file);
4323 win32_signal_context(void)
4328 my_perl = PL_curinterp;
4329 PERL_SET_THX(my_perl);
4333 return PL_curinterp;
4339 win32_ctrlhandler(DWORD dwCtrlType)
4342 dTHXa(PERL_GET_SIG_CONTEXT);
4348 switch(dwCtrlType) {
4349 case CTRL_CLOSE_EVENT:
4350 /* A signal that the system sends to all processes attached to a console when
4351 the user closes the console (either by choosing the Close command from the
4352 console window's System menu, or by choosing the End Task command from the
4355 if (do_raise(aTHX_ 1)) /* SIGHUP */
4356 sig_terminate(aTHX_ 1);
4360 /* A CTRL+c signal was received */
4361 if (do_raise(aTHX_ SIGINT))
4362 sig_terminate(aTHX_ SIGINT);
4365 case CTRL_BREAK_EVENT:
4366 /* A CTRL+BREAK signal was received */
4367 if (do_raise(aTHX_ SIGBREAK))
4368 sig_terminate(aTHX_ SIGBREAK);
4371 case CTRL_LOGOFF_EVENT:
4372 /* A signal that the system sends to all console processes when a user is logging
4373 off. This signal does not indicate which user is logging off, so no
4374 assumptions can be made.
4377 case CTRL_SHUTDOWN_EVENT:
4378 /* A signal that the system sends to all console processes when the system is
4381 if (do_raise(aTHX_ SIGTERM))
4382 sig_terminate(aTHX_ SIGTERM);
4391 #ifdef SET_INVALID_PARAMETER_HANDLER
4392 # include <crtdbg.h>
4403 /* fetch Unicode version of PATH */
4405 wide_path = (WCHAR*)win32_malloc(len*sizeof(WCHAR));
4407 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4409 win32_free(wide_path);
4415 wide_path = (WCHAR*)win32_realloc(wide_path, len*sizeof(WCHAR));
4420 /* convert to ANSI pathnames */
4421 wide_dir = wide_path;
4424 WCHAR *sep = wcschr(wide_dir, ';');
4432 /* remove quotes around pathname */
4433 if (*wide_dir == '"')
4435 wide_len = wcslen(wide_dir);
4436 if (wide_len && wide_dir[wide_len-1] == '"')
4437 wide_dir[wide_len-1] = '\0';
4439 /* append ansi_dir to ansi_path */
4440 ansi_dir = win32_ansipath(wide_dir);
4441 ansi_len = strlen(ansi_dir);
4443 size_t newlen = len + 1 + ansi_len;
4444 ansi_path = (char*)win32_realloc(ansi_path, newlen+1);
4447 ansi_path[len] = ';';
4448 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4453 ansi_path = (char*)win32_malloc(5+len+1);
4456 memcpy(ansi_path, "PATH=", 5);
4457 memcpy(ansi_path+5, ansi_dir, len+1);
4460 win32_free(ansi_dir);
4465 /* Update C RTL environ array. This will only have full effect if
4466 * perl_parse() is later called with `environ` as the `env` argument.
4467 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4469 * We do have to ansify() the PATH before Perl has been fully
4470 * initialized because S_find_script() uses the PATH when perl
4471 * is being invoked with the -S option. This happens before %ENV
4472 * is initialized in S_init_postdump_symbols().
4474 * XXX Is this a bug? Should S_find_script() use the environment
4475 * XXX passed in the `env` arg to parse_perl()?
4478 /* Keep system environment in sync because S_init_postdump_symbols()
4479 * will not call mg_set() if it initializes %ENV from `environ`.
4481 SetEnvironmentVariableA("PATH", ansi_path+5);
4482 win32_free(ansi_path);
4484 win32_free(wide_path);
4488 Perl_win32_init(int *argcp, char ***argvp)
4490 #ifdef SET_INVALID_PARAMETER_HANDLER
4491 _invalid_parameter_handler oldHandler, newHandler;
4492 newHandler = my_invalid_parameter_handler;
4493 oldHandler = _set_invalid_parameter_handler(newHandler);
4494 _CrtSetReportMode(_CRT_ASSERT, 0);
4496 /* Disable floating point errors, Perl will trap the ones we
4497 * care about. VC++ RTL defaults to switching these off
4498 * already, but some RTLs don't. Since we don't
4499 * want to be at the vendor's whim on the default, we set
4500 * it explicitly here.
4502 #if !defined(__GNUC__)
4503 _control87(MCW_EM, MCW_EM);
4507 /* When the manifest resource requests Common-Controls v6 then
4508 * user32.dll no longer registers all the Windows classes used for
4509 * standard controls but leaves some of them to be registered by
4510 * comctl32.dll. InitCommonControls() doesn't do anything but calling
4511 * it makes sure comctl32.dll gets loaded into the process and registers
4512 * the standard control classes. Without this even normal Windows APIs
4513 * like MessageBox() can fail under some versions of Windows XP.
4515 InitCommonControls();
4517 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4518 GetVersionEx(&g_osver);
4520 #ifdef WIN32_DYN_IOINFO_SIZE
4522 Size_t ioinfo_size = _msize((void*)__pioinfo[0]);;
4523 if((SSize_t)ioinfo_size <= 0) { /* -1 is err */
4524 fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */
4527 ioinfo_size /= IOINFO_ARRAY_ELTS;
4528 w32_ioinfo_size = ioinfo_size;
4534 #ifndef WIN32_NO_REGISTRY
4537 retval = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Perl", 0, KEY_READ, &HKCU_Perl_hnd);
4538 if (retval != ERROR_SUCCESS) {
4539 HKCU_Perl_hnd = NULL;
4541 retval = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", 0, KEY_READ, &HKLM_Perl_hnd);
4542 if (retval != ERROR_SUCCESS) {
4543 HKLM_Perl_hnd = NULL;
4550 Perl_win32_term(void)
4558 #ifndef WIN32_NO_REGISTRY
4559 /* handles might be NULL, RegCloseKey then returns ERROR_INVALID_HANDLE
4560 but no point of checking and we can't die() at this point */
4561 RegCloseKey(HKLM_Perl_hnd);
4562 RegCloseKey(HKCU_Perl_hnd);
4563 /* the handles are in an undefined state until the next PERL_SYS_INIT3 */
4568 win32_get_child_IO(child_IO_table* ptbl)
4570 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4571 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4572 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4576 win32_signal(int sig, Sighandler_t subcode)
4579 if (sig < SIG_SIZE) {
4580 int save_errno = errno;
4581 Sighandler_t result;
4582 #ifdef SET_INVALID_PARAMETER_HANDLER
4583 /* Silence our invalid parameter handler since we expect to make some
4584 * calls with invalid signal numbers giving a SIG_ERR result. */
4585 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE);
4587 result = signal(sig, subcode);
4588 #ifdef SET_INVALID_PARAMETER_HANDLER
4589 set_silent_invalid_parameter_handler(oldvalue);
4591 aTHXa(PERL_GET_THX);
4592 if (result == SIG_ERR) {
4593 result = w32_sighandler[sig];
4596 w32_sighandler[sig] = subcode;
4605 /* The PerlMessageWindowClass's WindowProc */
4607 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4609 return win32_process_message(hwnd, msg, wParam, lParam) ?
4610 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4613 /* The real message handler. Can be called with
4614 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4615 * that it processes */
4617 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4619 /* BEWARE. The context retrieved using dTHX; is the context of the
4620 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4621 * up to and including WM_CREATE. If it ever happens that you need the
4622 * 'child' context before this, then it needs to be passed into
4623 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4624 * from the lparam of CreateWindow(). It could then be stored/retrieved
4625 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4626 * the dTHX calls here. */
4627 /* XXX For now it is assumed that the overhead of the dTHX; for what
4628 * are relativley infrequent code-paths, is better than the added
4629 * complexity of getting the correct context passed into
4630 * win32_create_message_window() */
4636 case WM_USER_MESSAGE: {
4637 long child = find_pseudo_pid(aTHX_ (int)wParam);
4639 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4646 case WM_USER_KILL: {
4647 /* We use WM_USER_KILL to fake kill() with other signals */
4648 int sig = (int)wParam;
4649 if (do_raise(aTHX_ sig))
4650 sig_terminate(aTHX_ sig);
4656 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4657 if (w32_timerid && w32_timerid==(UINT)wParam) {
4658 KillTimer(w32_message_hwnd, w32_timerid);
4661 /* Now fake a call to signal handler */
4662 if (do_raise(aTHX_ 14))
4663 sig_terminate(aTHX_ 14);
4675 /* Above or other stuff may have set a signal flag, and we may not have
4676 * been called from win32_async_check() (e.g. some other GUI's message
4677 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4678 * handler that die's, and the message loop that calls here is wrapped
4679 * in an eval, then you may well end up with orphaned windows - signals
4680 * are dispatched by win32_async_check() */
4686 win32_create_message_window_class(void)
4688 /* create the window class for "message only" windows */
4692 wc.lpfnWndProc = win32_message_window_proc;
4693 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4694 wc.lpszClassName = "PerlMessageWindowClass";
4696 /* second and subsequent calls will fail, but class
4697 * will already be registered */
4702 win32_create_message_window(void)
4704 win32_create_message_window_class();
4705 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4706 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4709 #ifdef HAVE_INTERP_INTERN
4712 win32_csighandler(int sig)
4715 dTHXa(PERL_GET_SIG_CONTEXT);
4716 Perl_warn(aTHX_ "Got signal %d",sig);
4721 #if defined(__MINGW32__) && defined(__cplusplus)
4722 #define CAST_HWND__(x) (HWND__*)(x)
4724 #define CAST_HWND__(x) x
4728 Perl_sys_intern_init(pTHX)
4732 w32_perlshell_tokens = NULL;
4733 w32_perlshell_vec = (char**)NULL;
4734 w32_perlshell_items = 0;
4735 w32_fdpid = newAV();
4736 Newx(w32_children, 1, child_tab);
4737 w32_num_children = 0;
4738 # ifdef USE_ITHREADS
4740 Newx(w32_pseudo_children, 1, pseudo_child_tab);
4741 w32_num_pseudo_children = 0;
4744 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4746 #ifdef PERL_IS_MINIPERL
4747 w32_sloppystat = TRUE;
4749 w32_sloppystat = FALSE;
4751 for (i=0; i < SIG_SIZE; i++) {
4752 w32_sighandler[i] = SIG_DFL;
4754 # ifdef MULTIPLICITY
4755 if (my_perl == PL_curinterp) {
4759 /* Force C runtime signal stuff to set its console handler */
4760 signal(SIGINT,win32_csighandler);
4761 signal(SIGBREAK,win32_csighandler);
4763 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
4764 * flag. This has the side-effect of disabling Ctrl-C events in all
4765 * processes in this group.
4766 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
4767 * with a NULL handler.
4769 SetConsoleCtrlHandler(NULL,FALSE);
4771 /* Push our handler on top */
4772 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
4777 Perl_sys_intern_clear(pTHX)
4780 Safefree(w32_perlshell_tokens);
4781 Safefree(w32_perlshell_vec);
4782 /* NOTE: w32_fdpid is freed by sv_clean_all() */
4783 Safefree(w32_children);
4785 KillTimer(w32_message_hwnd, w32_timerid);
4788 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
4789 DestroyWindow(w32_message_hwnd);
4790 # ifdef MULTIPLICITY
4791 if (my_perl == PL_curinterp) {
4795 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
4797 # ifdef USE_ITHREADS
4798 Safefree(w32_pseudo_children);
4802 # ifdef USE_ITHREADS
4805 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
4807 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
4809 dst->perlshell_tokens = NULL;
4810 dst->perlshell_vec = (char**)NULL;
4811 dst->perlshell_items = 0;
4812 dst->fdpid = newAV();
4813 Newxz(dst->children, 1, child_tab);
4815 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
4817 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4818 dst->poll_count = 0;
4819 dst->sloppystat = src->sloppystat;
4820 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
4822 # endif /* USE_ITHREADS */
4823 #endif /* HAVE_INTERP_INTERN */