3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc.
5 * Portions (c) 1993 Intergraph Corporation. All rights reserved.
7 * You may distribute under the terms of either the GNU General Public
8 * License or the Artistic License, as specified in the README file.
10 #define PERLIO_NOT_STDIO 0
11 #define WIN32_LEAN_AND_MEAN
12 #define WIN32IO_IS_STDIO
16 # define Win32_Winsock
20 # define _WIN32_WINNT 0x0500 /* needed for CreateHardlink() etc. */
26 # define HWND_MESSAGE ((HWND)-3)
29 #ifndef PROCESSOR_ARCHITECTURE_AMD64
30 # define PROCESSOR_ARCHITECTURE_AMD64 9
33 #ifndef WC_NO_BEST_FIT_CHARS
34 # define WC_NO_BEST_FIT_CHARS 0x00000400
43 /* #include "config.h" */
45 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
54 #define PERL_NO_GET_CONTEXT
59 /* assert.h conflicts with #define of assert in perl.h */
67 #include <sys/utime.h>
70 /* Mingw32 defaults to globing command line
71 * So we turn it off like this:
76 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)
77 /* Mingw32-1.1 is missing some prototypes */
79 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
80 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
81 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
89 #define EXECF_SPAWN_NOWAIT 3
91 #if defined(PERL_IMPLICIT_SYS)
92 # undef win32_get_privlib
93 # define win32_get_privlib g_win32_get_privlib
94 # undef win32_get_sitelib
95 # define win32_get_sitelib g_win32_get_sitelib
96 # undef win32_get_vendorlib
97 # define win32_get_vendorlib g_win32_get_vendorlib
99 # define getlogin g_getlogin
102 /* VS2005 (MSC version 14) provides a mechanism to set an invalid
103 * parameter handler. This functionality is not available in the
104 * 64-bit compiler from the Platform SDK, which unfortunately also
105 * believes itself to be MSC version 14.
107 * There is no #define related to _set_invalid_parameter_handler(),
108 * but we can check for one of the constants defined for
109 * _set_abort_behavior(), which was introduced into stdlib.h at
113 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG)
114 # define SET_INVALID_PARAMETER_HANDLER
117 #ifdef SET_INVALID_PARAMETER_HANDLER
118 static BOOL set_silent_invalid_parameter_handler(BOOL newvalue);
119 static void my_invalid_parameter_handler(const wchar_t* expression,
120 const wchar_t* function, const wchar_t* file,
121 unsigned int line, uintptr_t pReserved);
124 static char* get_regstr_from(HKEY hkey, const char *valuename, SV **svp);
125 static char* get_regstr(const char *valuename, SV **svp);
126 static char* get_emd_part(SV **prev_pathp, STRLEN *const len,
127 char *trailing, ...);
128 static char* win32_get_xlib(const char *pl, const char *xlib,
129 const char *libname, STRLEN *const len);
130 static BOOL has_shell_metachars(const char *ptr);
131 static long tokenize(const char *str, char **dest, char ***destv);
132 static void get_shell(void);
133 static char* find_next_space(const char *s);
134 static int do_spawn2(pTHX_ const char *cmd, int exectype);
135 static long find_pid(int pid);
136 static void remove_dead_process(long child);
137 static int terminate_process(DWORD pid, HANDLE process_handle, int sig);
138 static int my_kill(int pid, int sig);
139 static void out_of_memory(void);
140 static char* wstr_to_str(const wchar_t* wstr);
141 static long filetime_to_clock(PFILETIME ft);
142 static BOOL filetime_from_time(PFILETIME ft, time_t t);
143 static char* create_command_line(char *cname, STRLEN clen,
144 const char * const *args);
145 static char* qualified_path(const char *cmd);
146 static void ansify_path(void);
147 static LRESULT win32_process_message(HWND hwnd, UINT msg,
148 WPARAM wParam, LPARAM lParam);
151 static long find_pseudo_pid(int pid);
152 static void remove_dead_pseudo_process(long child);
153 static HWND get_hwnd_delay(pTHX, long child, DWORD tries);
156 #ifdef HAVE_INTERP_INTERN
157 static void win32_csighandler(int sig);
161 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
162 char w32_module_name[MAX_PATH+1];
165 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
167 #ifdef SET_INVALID_PARAMETER_HANDLER
168 static BOOL silent_invalid_parameter_handler = FALSE;
171 set_silent_invalid_parameter_handler(BOOL newvalue)
174 BOOL oldvalue = silent_invalid_parameter_handler;
175 silent_invalid_parameter_handler = newvalue;
181 my_invalid_parameter_handler(const wchar_t* expression,
182 const wchar_t* function,
188 char* ansi_expression;
191 if (silent_invalid_parameter_handler)
193 ansi_expression = wstr_to_str(expression);
194 ansi_function = wstr_to_str(function);
195 ansi_file = wstr_to_str(file);
196 fprintf(stderr, "Invalid parameter detected in function %s. "
197 "File: %s, line: %d\n", ansi_function, ansi_file, line);
198 fprintf(stderr, "Expression: %s\n", ansi_expression);
199 free(ansi_expression);
207 set_w32_module_name(void)
209 /* this function may be called at DLL_PROCESS_ATTACH time */
211 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
212 ? GetModuleHandle(NULL)
213 : w32_perldll_handle);
215 OSVERSIONINFO osver; /* g_osver may not yet be initialized */
216 osver.dwOSVersionInfoSize = sizeof(osver);
217 GetVersionEx(&osver);
219 if (osver.dwMajorVersion > 4) {
220 WCHAR modulename[MAX_PATH];
221 WCHAR fullname[MAX_PATH];
224 DWORD (__stdcall *pfnGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD) =
225 (DWORD (__stdcall *)(LPCWSTR, LPWSTR, DWORD))
226 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetLongPathNameW");
228 GetModuleFileNameW(module, modulename, sizeof(modulename)/sizeof(WCHAR));
230 /* Make sure we get an absolute pathname in case the module was loaded
231 * explicitly by LoadLibrary() with a relative path. */
232 GetFullPathNameW(modulename, sizeof(fullname)/sizeof(WCHAR), fullname, NULL);
234 /* Make sure we start with the long path name of the module because we
235 * later scan for pathname components to match "5.xx" to locate
236 * compatible sitelib directories, and the short pathname might mangle
237 * this path segment (e.g. by removing the dot on NTFS to something
238 * like "5xx~1.yy") */
239 if (pfnGetLongPathNameW)
240 pfnGetLongPathNameW(fullname, fullname, sizeof(fullname)/sizeof(WCHAR));
242 /* remove \\?\ prefix */
243 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0)
244 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR));
246 ansi = win32_ansipath(fullname);
247 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name));
251 GetModuleFileName(module, w32_module_name, sizeof(w32_module_name));
253 /* remove \\?\ prefix */
254 if (memcmp(w32_module_name, "\\\\?\\", 4) == 0)
255 memmove(w32_module_name, w32_module_name+4, strlen(w32_module_name+4)+1);
257 /* try to get full path to binary (which may be mangled when perl is
258 * run from a 16-bit app) */
259 /*PerlIO_printf(Perl_debug_log, "Before %s\n", w32_module_name);*/
260 win32_longpath(w32_module_name);
261 /*PerlIO_printf(Perl_debug_log, "After %s\n", w32_module_name);*/
264 /* normalize to forward slashes */
265 ptr = w32_module_name;
273 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
275 get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
277 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
280 const char *subkey = "Software\\Perl";
284 retval = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &handle);
285 if (retval == ERROR_SUCCESS) {
287 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen);
288 if (retval == ERROR_SUCCESS
289 && (type == REG_SZ || type == REG_EXPAND_SZ))
293 *svp = sv_2mortal(newSVpvn("",0));
294 SvGROW(*svp, datalen);
295 retval = RegQueryValueEx(handle, valuename, 0, NULL,
296 (PBYTE)SvPVX(*svp), &datalen);
297 if (retval == ERROR_SUCCESS) {
299 SvCUR_set(*svp,datalen-1);
307 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
309 get_regstr(const char *valuename, SV **svp)
311 char *str = get_regstr_from(HKEY_CURRENT_USER, valuename, svp);
313 str = get_regstr_from(HKEY_LOCAL_MACHINE, valuename, svp);
317 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
319 get_emd_part(SV **prev_pathp, STRLEN *const len, char *trailing_path, ...)
323 char mod_name[MAX_PATH+1];
329 va_start(ap, trailing_path);
330 strip = va_arg(ap, char *);
332 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
333 baselen = strlen(base);
335 if (!*w32_module_name) {
336 set_w32_module_name();
338 strcpy(mod_name, w32_module_name);
339 ptr = strrchr(mod_name, '/');
340 while (ptr && strip) {
341 /* look for directories to skip back */
344 ptr = strrchr(mod_name, '/');
345 /* avoid stripping component if there is no slash,
346 * or it doesn't match ... */
347 if (!ptr || stricmp(ptr+1, strip) != 0) {
348 /* ... but not if component matches m|5\.$patchlevel.*| */
349 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
350 && strncmp(strip, base, baselen) == 0
351 && strncmp(ptr+1, base, baselen) == 0))
357 strip = va_arg(ap, char *);
365 strcpy(++ptr, trailing_path);
367 /* only add directory if it exists */
368 if (GetFileAttributes(mod_name) != (DWORD) -1) {
369 /* directory exists */
372 *prev_pathp = sv_2mortal(newSVpvn("",0));
373 else if (SvPVX(*prev_pathp))
374 sv_catpvn(*prev_pathp, ";", 1);
375 sv_catpv(*prev_pathp, mod_name);
377 *len = SvCUR(*prev_pathp);
378 return SvPVX(*prev_pathp);
385 win32_get_privlib(const char *pl, STRLEN *const len)
388 char *stdlib = "lib";
389 char buffer[MAX_PATH+1];
392 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
393 sprintf(buffer, "%s-%s", stdlib, pl);
394 if (!get_regstr(buffer, &sv))
395 (void)get_regstr(stdlib, &sv);
397 /* $stdlib .= ";$EMD/../../lib" */
398 return get_emd_part(&sv, len, stdlib, ARCHNAME, "bin", NULL);
402 win32_get_xlib(const char *pl, const char *xlib, const char *libname,
407 char pathstr[MAX_PATH+1];
411 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
412 sprintf(regstr, "%s-%s", xlib, pl);
413 (void)get_regstr(regstr, &sv1);
416 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
417 sprintf(pathstr, "%s/%s/lib", libname, pl);
418 (void)get_emd_part(&sv1, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
420 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
421 (void)get_regstr(xlib, &sv2);
424 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
425 sprintf(pathstr, "%s/lib", libname);
426 (void)get_emd_part(&sv2, NULL, pathstr, ARCHNAME, "bin", pl, NULL);
433 sv_catpvn(sv1, ";", 1);
443 win32_get_sitelib(const char *pl, STRLEN *const len)
445 return win32_get_xlib(pl, "sitelib", "site", len);
448 #ifndef PERL_VENDORLIB_NAME
449 # define PERL_VENDORLIB_NAME "vendor"
453 win32_get_vendorlib(const char *pl, STRLEN *const len)
455 return win32_get_xlib(pl, "vendorlib", PERL_VENDORLIB_NAME, len);
459 has_shell_metachars(const char *ptr)
465 * Scan string looking for redirection (< or >) or pipe
466 * characters (|) that are not in a quoted string.
467 * Shell variable interpolation (%VAR%) can also happen inside strings.
499 #if !defined(PERL_IMPLICIT_SYS)
500 /* since the current process environment is being updated in util.c
501 * the library functions will get the correct environment
504 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
506 PERL_FLUSHALL_FOR_CHILD;
507 return win32_popen(cmd, mode);
511 Perl_my_pclose(pTHX_ PerlIO *fp)
513 return win32_pclose(fp);
517 DllExport unsigned long
520 return (unsigned long)g_osver.dwPlatformId;
529 return -((int)w32_pseudo_id);
534 /* Tokenize a string. Words are null-separated, and the list
535 * ends with a doubled null. Any character (except null and
536 * including backslash) may be escaped by preceding it with a
537 * backslash (the backslash will be stripped).
538 * Returns number of words in result buffer.
541 tokenize(const char *str, char **dest, char ***destv)
543 char *retstart = NULL;
544 char **retvstart = 0;
548 int slen = strlen(str);
551 Newx(ret, slen+2, char);
552 Newx(retv, (slen+3)/2, char*);
560 if (*ret == '\\' && *str)
562 else if (*ret == ' ') {
578 retvstart[items] = NULL;
591 if (!w32_perlshell_tokens) {
592 /* we don't use COMSPEC here for two reasons:
593 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
594 * uncontrolled unportability of the ensuing scripts.
595 * 2. PERL5SHELL could be set to a shell that may not be fit for
596 * interactive use (which is what most programs look in COMSPEC
599 const char* defaultshell = "cmd.exe /x/d/c";
600 const char *usershell = PerlEnv_getenv("PERL5SHELL");
601 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
602 &w32_perlshell_tokens,
608 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
616 PERL_ARGS_ASSERT_DO_ASPAWN;
622 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*);
624 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
629 while (++mark <= sp) {
630 if (*mark && (str = SvPV_nolen(*mark)))
637 status = win32_spawnvp(flag,
638 (const char*)(really ? SvPV_nolen(really) : argv[0]),
639 (const char* const*)argv);
641 if (status < 0 && (errno == ENOEXEC || errno == ENOENT)) {
642 /* possible shell-builtin, invoke with shell */
644 sh_items = w32_perlshell_items;
646 argv[index+sh_items] = argv[index];
647 while (--sh_items >= 0)
648 argv[sh_items] = w32_perlshell_vec[sh_items];
650 status = win32_spawnvp(flag,
651 (const char*)(really ? SvPV_nolen(really) : argv[0]),
652 (const char* const*)argv);
655 if (flag == P_NOWAIT) {
656 PL_statusvalue = -1; /* >16bits hint for pp_system() */
660 if (ckWARN(WARN_EXEC))
661 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
666 PL_statusvalue = status;
672 /* returns pointer to the next unquoted space or the end of the string */
674 find_next_space(const char *s)
676 bool in_quotes = FALSE;
678 /* ignore doubled backslashes, or backslash+quote */
679 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) {
682 /* keep track of when we're within quotes */
683 else if (*s == '"') {
685 in_quotes = !in_quotes;
687 /* break it up only at spaces that aren't in quotes */
688 else if (!in_quotes && isSPACE(*s))
697 do_spawn2(pTHX_ const char *cmd, int exectype)
703 BOOL needToTry = TRUE;
706 /* Save an extra exec if possible. See if there are shell
707 * metacharacters in it */
708 if (!has_shell_metachars(cmd)) {
709 Newx(argv, strlen(cmd) / 2 + 2, char*);
710 Newx(cmd2, strlen(cmd) + 1, char);
713 for (s = cmd2; *s;) {
714 while (*s && isSPACE(*s))
718 s = find_next_space(s);
726 status = win32_spawnvp(P_WAIT, argv[0],
727 (const char* const*)argv);
729 case EXECF_SPAWN_NOWAIT:
730 status = win32_spawnvp(P_NOWAIT, argv[0],
731 (const char* const*)argv);
734 status = win32_execvp(argv[0], (const char* const*)argv);
737 if (status != -1 || errno == 0)
747 Newx(argv, w32_perlshell_items + 2, char*);
748 while (++i < w32_perlshell_items)
749 argv[i] = w32_perlshell_vec[i];
750 argv[i++] = (char *)cmd;
754 status = win32_spawnvp(P_WAIT, argv[0],
755 (const char* const*)argv);
757 case EXECF_SPAWN_NOWAIT:
758 status = win32_spawnvp(P_NOWAIT, argv[0],
759 (const char* const*)argv);
762 status = win32_execvp(argv[0], (const char* const*)argv);
768 if (exectype == EXECF_SPAWN_NOWAIT) {
769 PL_statusvalue = -1; /* >16bits hint for pp_system() */
773 if (ckWARN(WARN_EXEC))
774 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s",
775 (exectype == EXECF_EXEC ? "exec" : "spawn"),
776 cmd, strerror(errno));
781 PL_statusvalue = status;
787 Perl_do_spawn(pTHX_ char *cmd)
789 PERL_ARGS_ASSERT_DO_SPAWN;
791 return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
795 Perl_do_spawn_nowait(pTHX_ char *cmd)
797 PERL_ARGS_ASSERT_DO_SPAWN_NOWAIT;
799 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
803 Perl_do_exec(pTHX_ const char *cmd)
805 PERL_ARGS_ASSERT_DO_EXEC;
807 do_spawn2(aTHX_ cmd, EXECF_EXEC);
811 /* The idea here is to read all the directory names into a string table
812 * (separated by nulls) and when one of the other dir functions is called
813 * return the pointer to the current file name.
816 win32_opendir(const char *filename)
822 char scanname[MAX_PATH+3];
823 WCHAR wscanname[sizeof(scanname)];
824 WIN32_FIND_DATAW wFindData;
825 char buffer[MAX_PATH*2];
828 len = strlen(filename);
833 if (len > MAX_PATH) {
834 errno = ENAMETOOLONG;
838 /* Get us a DIR structure */
841 /* Create the search pattern */
842 strcpy(scanname, filename);
844 /* bare drive name means look in cwd for drive */
845 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') {
846 scanname[len++] = '.';
847 scanname[len++] = '/';
849 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') {
850 scanname[len++] = '/';
852 scanname[len++] = '*';
853 scanname[len] = '\0';
855 /* do the FindFirstFile call */
856 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR));
857 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData);
859 if (dirp->handle == INVALID_HANDLE_VALUE) {
860 DWORD err = GetLastError();
861 /* FindFirstFile() fails on empty drives! */
863 case ERROR_FILE_NOT_FOUND:
865 case ERROR_NO_MORE_FILES:
866 case ERROR_PATH_NOT_FOUND:
869 case ERROR_NOT_ENOUGH_MEMORY:
881 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
882 wFindData.cFileName, -1,
883 buffer, sizeof(buffer), NULL, &use_default);
884 if (use_default && *wFindData.cAlternateFileName) {
885 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
886 wFindData.cAlternateFileName, -1,
887 buffer, sizeof(buffer), NULL, NULL);
890 /* now allocate the first part of the string table for
891 * the filenames that we find.
893 idx = strlen(buffer)+1;
898 Newx(dirp->start, dirp->size, char);
899 strcpy(dirp->start, buffer);
901 dirp->end = dirp->curr = dirp->start;
907 /* Readdir just returns the current string pointer and bumps the
908 * string pointer to the nDllExport entry.
910 DllExport struct direct *
911 win32_readdir(DIR *dirp)
916 /* first set up the structure to return */
917 len = strlen(dirp->curr);
918 strcpy(dirp->dirstr.d_name, dirp->curr);
919 dirp->dirstr.d_namlen = len;
922 dirp->dirstr.d_ino = dirp->curr - dirp->start;
924 /* Now set up for the next call to readdir */
925 dirp->curr += len + 1;
926 if (dirp->curr >= dirp->end) {
929 char buffer[MAX_PATH*2];
931 if (dirp->handle == INVALID_HANDLE_VALUE) {
934 /* finding the next file that matches the wildcard
935 * (which should be all of them in this directory!).
938 WIN32_FIND_DATAW wFindData;
939 res = FindNextFileW(dirp->handle, &wFindData);
941 BOOL use_default = FALSE;
942 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
943 wFindData.cFileName, -1,
944 buffer, sizeof(buffer), NULL, &use_default);
945 if (use_default && *wFindData.cAlternateFileName) {
946 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
947 wFindData.cAlternateFileName, -1,
948 buffer, sizeof(buffer), NULL, NULL);
953 long endpos = dirp->end - dirp->start;
954 long newsize = endpos + strlen(buffer) + 1;
955 /* bump the string table size by enough for the
956 * new name and its null terminator */
957 while (newsize > dirp->size) {
958 long curpos = dirp->curr - dirp->start;
960 Renew(dirp->start, dirp->size, char);
961 dirp->curr = dirp->start + curpos;
963 strcpy(dirp->start + endpos, buffer);
964 dirp->end = dirp->start + newsize;
969 if (dirp->handle != INVALID_HANDLE_VALUE) {
970 FindClose(dirp->handle);
971 dirp->handle = INVALID_HANDLE_VALUE;
975 return &(dirp->dirstr);
981 /* Telldir returns the current string pointer position */
983 win32_telldir(DIR *dirp)
985 return dirp->curr ? (dirp->curr - dirp->start) : -1;
989 /* Seekdir moves the string pointer to a previously saved position
990 * (returned by telldir).
993 win32_seekdir(DIR *dirp, long loc)
995 dirp->curr = loc == -1 ? NULL : dirp->start + loc;
998 /* Rewinddir resets the string pointer to the start */
1000 win32_rewinddir(DIR *dirp)
1002 dirp->curr = dirp->start;
1005 /* free the memory allocated by opendir */
1007 win32_closedir(DIR *dirp)
1010 if (dirp->handle != INVALID_HANDLE_VALUE)
1011 FindClose(dirp->handle);
1012 Safefree(dirp->start);
1017 /* duplicate a open DIR* for interpreter cloning */
1019 win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param)
1022 PerlInterpreter *const from = param->proto_perl;
1023 PerlInterpreter *const to = PERL_GET_THX;
1028 /* switch back to original interpreter because win32_readdir()
1029 * might Renew(dirp->start).
1035 /* mark current position; read all remaining entries into the
1036 * cache, and then restore to current position.
1038 pos = win32_telldir(dirp);
1039 while (win32_readdir(dirp)) {
1040 /* read all entries into cache */
1042 win32_seekdir(dirp, pos);
1044 /* switch back to new interpreter to allocate new DIR structure */
1050 memcpy(dup, dirp, sizeof(DIR));
1052 Newx(dup->start, dirp->size, char);
1053 memcpy(dup->start, dirp->start, dirp->size);
1055 dup->end = dup->start + (dirp->end - dirp->start);
1057 dup->curr = dup->start + (dirp->curr - dirp->start);
1069 * Just pretend that everyone is a superuser. NT will let us know if
1070 * we don\'t really have permission to do something.
1073 #define ROOT_UID ((uid_t)0)
1074 #define ROOT_GID ((gid_t)0)
1103 return (auid == ROOT_UID ? 0 : -1);
1109 return (agid == ROOT_GID ? 0 : -1);
1116 char *buf = w32_getlogin_buffer;
1117 DWORD size = sizeof(w32_getlogin_buffer);
1118 if (GetUserName(buf,&size))
1124 chown(const char *path, uid_t owner, gid_t group)
1131 * XXX this needs strengthening (for PerlIO)
1134 int mkstemp(const char *path)
1137 char buf[MAX_PATH+1];
1141 if (i++ > 10) { /* give up */
1145 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
1149 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
1159 long child = w32_num_children;
1160 while (--child >= 0) {
1161 if ((int)w32_child_pids[child] == pid)
1168 remove_dead_process(long child)
1172 CloseHandle(w32_child_handles[child]);
1173 Move(&w32_child_handles[child+1], &w32_child_handles[child],
1174 (w32_num_children-child-1), HANDLE);
1175 Move(&w32_child_pids[child+1], &w32_child_pids[child],
1176 (w32_num_children-child-1), DWORD);
1183 find_pseudo_pid(int pid)
1186 long child = w32_num_pseudo_children;
1187 while (--child >= 0) {
1188 if ((int)w32_pseudo_child_pids[child] == pid)
1195 remove_dead_pseudo_process(long child)
1199 CloseHandle(w32_pseudo_child_handles[child]);
1200 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
1201 (w32_num_pseudo_children-child-1), HANDLE);
1202 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
1203 (w32_num_pseudo_children-child-1), DWORD);
1204 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
1205 (w32_num_pseudo_children-child-1), HWND);
1206 Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child],
1207 (w32_num_pseudo_children-child-1), char);
1208 w32_num_pseudo_children--;
1213 win32_wait_for_children(pTHX)
1215 if (w32_pseudo_children && w32_num_pseudo_children) {
1218 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1220 for (child = 0; child < w32_num_pseudo_children; ++child) {
1221 if (!w32_pseudo_child_sigterm[child])
1222 handles[count++] = w32_pseudo_child_handles[child];
1224 /* XXX should use MsgWaitForMultipleObjects() to continue
1225 * XXX processing messages while we wait.
1227 WaitForMultipleObjects(count, handles, TRUE, INFINITE);
1229 while (w32_num_pseudo_children)
1230 CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]);
1236 terminate_process(DWORD pid, HANDLE process_handle, int sig)
1240 /* "Does process exist?" use of kill */
1243 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid))
1248 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
1251 default: /* For now be backwards compatible with perl 5.6 */
1253 /* Note that we will only be able to kill processes owned by the
1254 * current process owner, even when we are running as an administrator.
1255 * To kill processes of other owners we would need to set the
1256 * 'SeDebugPrivilege' privilege before obtaining the process handle.
1258 if (TerminateProcess(process_handle, sig))
1266 killpg(int pid, int sig)
1268 HANDLE process_handle;
1269 HANDLE snapshot_handle;
1272 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1273 if (process_handle == NULL)
1276 killed += terminate_process(pid, process_handle, sig);
1278 snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1279 if (snapshot_handle != INVALID_HANDLE_VALUE) {
1280 PROCESSENTRY32 entry;
1282 entry.dwSize = sizeof(entry);
1283 if (Process32First(snapshot_handle, &entry)) {
1285 if (entry.th32ParentProcessID == (DWORD)pid)
1286 killed += killpg(entry.th32ProcessID, sig);
1287 entry.dwSize = sizeof(entry);
1289 while (Process32Next(snapshot_handle, &entry));
1291 CloseHandle(snapshot_handle);
1293 CloseHandle(process_handle);
1298 my_kill(int pid, int sig)
1301 HANDLE process_handle;
1304 return killpg(pid, -sig);
1306 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1307 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
1308 if (process_handle != NULL) {
1309 retval = terminate_process(pid, process_handle, sig);
1310 CloseHandle(process_handle);
1316 /* Get a child pseudo-process HWND, with retrying and delaying/yielding.
1317 * The "tries" parameter is the number of retries to make, with a Sleep(1)
1318 * (waiting and yielding the time slot) between each try. Specifying 0 causes
1319 * only Sleep(0) (no waiting and potentially no yielding) to be used, so is not
1321 * Returns an hwnd != INVALID_HANDLE_VALUE (so be aware that NULL can be
1322 * returned) or croaks if the child pseudo-process doesn't schedule and deliver
1323 * a HWND in the time period allowed.
1326 get_hwnd_delay(pTHX, long child, DWORD tries)
1328 HWND hwnd = w32_pseudo_child_message_hwnds[child];
1329 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1331 /* Pseudo-process has not yet properly initialized since hwnd isn't set.
1332 * Fast sleep: On some NT kernels/systems, a Sleep(0) won't deschedule a
1333 * thread 100% of the time since threads are attached to a CPU for NUMA and
1334 * caching reasons, and the child thread was attached to a different CPU
1335 * therefore there is no workload on that CPU and Sleep(0) returns control
1336 * without yielding the time slot.
1337 * https://rt.perl.org/rt3/Ticket/Display.html?id=88840
1340 win32_async_check(aTHX);
1341 hwnd = w32_pseudo_child_message_hwnds[child];
1342 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1346 /* No Sleep(1) if tries==0, just fail instead if we get this far. */
1347 while (count++ < tries) {
1349 win32_async_check(aTHX);
1350 hwnd = w32_pseudo_child_message_hwnds[child];
1351 if (hwnd != INVALID_HANDLE_VALUE) return hwnd;
1355 Perl_croak(aTHX_ "panic: child pseudo-process was never scheduled");
1360 win32_kill(int pid, int sig)
1366 /* it is a pseudo-forked child */
1367 child = find_pseudo_pid(-pid);
1369 HANDLE hProcess = w32_pseudo_child_handles[child];
1372 /* "Does process exist?" use of kill */
1376 /* kill -9 style un-graceful exit */
1377 /* Do a wait to make sure child starts and isn't in DLL
1379 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1380 if (TerminateThread(hProcess, sig)) {
1381 /* Allow the scheduler to finish cleaning up the other
1383 * Otherwise, if we ExitProcess() before another context
1384 * switch happens we will end up with a process exit
1385 * code of "sig" instead of our own exit status.
1386 * https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
1389 remove_dead_pseudo_process(child);
1396 HWND hwnd = get_hwnd_delay(aTHX, child, 5);
1397 /* We fake signals to pseudo-processes using Win32
1399 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) ||
1400 PostThreadMessage(-pid, WM_USER_KILL, sig, 0))
1402 /* Don't wait for child process to terminate after we send a
1403 * SIGTERM because the child may be blocked in a system call
1404 * and never receive the signal.
1406 if (sig == SIGTERM) {
1408 w32_pseudo_child_sigterm[child] = 1;
1410 /* It might be us ... */
1422 child = find_pid(pid);
1424 if (my_kill(pid, sig)) {
1426 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) &&
1427 exitcode != STILL_ACTIVE)
1429 remove_dead_process(child);
1435 if (my_kill(pid, sig))
1444 win32_stat(const char *path, Stat_t *sbuf)
1447 char buffer[MAX_PATH+1];
1448 int l = strlen(path);
1451 BOOL expect_dir = FALSE;
1453 GV *gv_sloppy = gv_fetchpvs("\027IN32_SLOPPY_STAT",
1454 GV_NOTQUAL, SVt_PV);
1455 BOOL sloppy = gv_sloppy && SvTRUE(GvSV(gv_sloppy));
1458 switch(path[l - 1]) {
1459 /* FindFirstFile() and stat() are buggy with a trailing
1460 * slashes, except for the root directory of a drive */
1463 if (l > sizeof(buffer)) {
1464 errno = ENAMETOOLONG;
1468 strncpy(buffer, path, l);
1469 /* remove additional trailing slashes */
1470 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\'))
1472 /* add back slash if we otherwise end up with just a drive letter */
1473 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':')
1480 /* FindFirstFile() is buggy with "x:", so add a dot :-( */
1482 if (l == 2 && isALPHA(path[0])) {
1483 buffer[0] = path[0];
1494 path = PerlDir_mapA(path);
1498 /* We must open & close the file once; otherwise file attribute changes */
1499 /* might not yet have propagated to "other" hard links of the same file. */
1500 /* This also gives us an opportunity to determine the number of links. */
1501 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1502 if (handle != INVALID_HANDLE_VALUE) {
1503 BY_HANDLE_FILE_INFORMATION bhi;
1504 if (GetFileInformationByHandle(handle, &bhi))
1505 nlink = bhi.nNumberOfLinks;
1506 CloseHandle(handle);
1510 /* path will be mapped correctly above */
1511 #if defined(WIN64) || defined(USE_LARGE_FILES)
1512 res = _stati64(path, sbuf);
1514 res = stat(path, sbuf);
1516 sbuf->st_nlink = nlink;
1519 /* CRT is buggy on sharenames, so make sure it really isn't.
1520 * XXX using GetFileAttributesEx() will enable us to set
1521 * sbuf->st_*time (but note that's not available on the
1522 * Windows of 1995) */
1523 DWORD r = GetFileAttributesA(path);
1524 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1525 /* sbuf may still contain old garbage since stat() failed */
1526 Zero(sbuf, 1, Stat_t);
1527 sbuf->st_mode = S_IFDIR | S_IREAD;
1529 if (!(r & FILE_ATTRIBUTE_READONLY))
1530 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1535 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1536 && (path[2] == '\\' || path[2] == '/'))
1538 /* The drive can be inaccessible, some _stat()s are buggy */
1539 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1544 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1548 if (S_ISDIR(sbuf->st_mode)) {
1549 /* Ensure the "write" bit is switched off in the mode for
1550 * directories with the read-only attribute set. Some compilers
1551 * switch it on for directories, which is technically correct
1552 * (directories are indeed always writable unless denied by DACLs),
1553 * but we want stat() and -w to reflect the state of the read-only
1554 * attribute for symmetry with chmod(). */
1555 DWORD r = GetFileAttributesA(path);
1556 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
1557 sbuf->st_mode &= ~S_IWRITE;
1564 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1565 #define SKIP_SLASHES(s) \
1567 while (*(s) && isSLASH(*(s))) \
1570 #define COPY_NONSLASHES(d,s) \
1572 while (*(s) && !isSLASH(*(s))) \
1576 /* Find the longname of a given path. path is destructively modified.
1577 * It should have space for at least MAX_PATH characters. */
1579 win32_longpath(char *path)
1581 WIN32_FIND_DATA fdata;
1583 char tmpbuf[MAX_PATH+1];
1584 char *tmpstart = tmpbuf;
1591 if (isALPHA(path[0]) && path[1] == ':') {
1593 *tmpstart++ = path[0];
1597 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1599 *tmpstart++ = path[0];
1600 *tmpstart++ = path[1];
1601 SKIP_SLASHES(start);
1602 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1604 *tmpstart++ = *start++;
1605 SKIP_SLASHES(start);
1606 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1611 /* copy initial slash, if any */
1612 if (isSLASH(*start)) {
1613 *tmpstart++ = *start++;
1615 SKIP_SLASHES(start);
1618 /* FindFirstFile() expands "." and "..", so we need to pass
1619 * those through unmolested */
1621 && (!start[1] || isSLASH(start[1])
1622 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1624 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1629 /* if this is the end, bust outta here */
1633 /* now we're at a non-slash; walk up to next slash */
1634 while (*start && !isSLASH(*start))
1637 /* stop and find full name of component */
1640 fhand = FindFirstFile(path,&fdata);
1642 if (fhand != INVALID_HANDLE_VALUE) {
1643 STRLEN len = strlen(fdata.cFileName);
1644 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1645 strcpy(tmpstart, fdata.cFileName);
1656 /* failed a step, just return without side effects */
1657 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1662 strcpy(path,tmpbuf);
1671 /* Can't use PerlIO to write as it allocates memory */
1672 PerlLIO_write(PerlIO_fileno(Perl_error_log),
1673 PL_no_mem, strlen(PL_no_mem));
1679 /* Converts a wide character (UTF-16) string to the Windows ANSI code page,
1680 * potentially using the system's default replacement character for any
1681 * unrepresentable characters. The caller must free() the returned string. */
1683 wstr_to_str(const wchar_t* wstr)
1685 BOOL used_default = FALSE;
1686 size_t wlen = wcslen(wstr) + 1;
1687 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1688 NULL, 0, NULL, NULL);
1689 char* str = malloc(len);
1692 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen,
1693 str, len, NULL, &used_default);
1697 /* The win32_ansipath() function takes a Unicode filename and converts it
1698 * into the current Windows codepage. If some characters cannot be mapped,
1699 * then it will convert the short name instead.
1701 * The buffer to the ansi pathname must be freed with win32_free() when it
1702 * it no longer needed.
1704 * The argument to win32_ansipath() must exist before this function is
1705 * called; otherwise there is no way to determine the short path name.
1707 * Ideas for future refinement:
1708 * - Only convert those segments of the path that are not in the current
1709 * codepage, but leave the other segments in their long form.
1710 * - If the resulting name is longer than MAX_PATH, start converting
1711 * additional path segments into short names until the full name
1712 * is shorter than MAX_PATH. Shorten the filename part last!
1715 win32_ansipath(const WCHAR *widename)
1718 BOOL use_default = FALSE;
1719 size_t widelen = wcslen(widename)+1;
1720 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1721 NULL, 0, NULL, NULL);
1722 name = win32_malloc(len);
1726 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1727 name, len, NULL, &use_default);
1729 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1731 WCHAR *shortname = win32_malloc(shortlen*sizeof(WCHAR));
1734 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1736 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1737 NULL, 0, NULL, NULL);
1738 name = win32_realloc(name, len);
1741 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1742 name, len, NULL, NULL);
1743 win32_free(shortname);
1750 win32_getenvironmentstrings(void)
1752 LPWSTR lpWStr, lpWTmp;
1754 DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1756 /* Get the process environment strings */
1757 lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1758 for (wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1759 env_len = wcslen(lpWTmp);
1760 /* calculate the size of the environment strings */
1761 wenvstrings_len += env_len + 1;
1764 /* Get the number of bytes required to store the ACP encoded string */
1765 aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1766 lpWStr, wenvstrings_len, NULL, 0, NULL, NULL);
1767 lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1771 /* Convert the string from UTF-16 encoding to ACP encoding */
1772 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1773 aenvstrings_len, NULL, NULL);
1779 win32_freeenvironmentstrings(void* block)
1785 win32_getenv(const char *name)
1792 needlen = GetEnvironmentVariableA(name,NULL,0);
1794 curitem = sv_2mortal(newSVpvn("", 0));
1796 SvGROW(curitem, needlen+1);
1797 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1799 } while (needlen >= SvLEN(curitem));
1800 SvCUR_set(curitem, needlen);
1803 last_err = GetLastError();
1804 if (last_err == ERROR_NOT_ENOUGH_MEMORY) {
1805 /* It appears the variable is in the env, but the Win32 API
1806 doesn't have a canned way of getting it. So we fall back to
1807 grabbing the whole env and pulling this value out if possible */
1808 char *envv = GetEnvironmentStrings();
1812 char *end = strchr(cur,'=');
1813 if (end && end != cur) {
1815 if (!strcmp(cur,name)) {
1816 curitem = sv_2mortal(newSVpv(end+1,0));
1821 cur = end + strlen(end+1)+2;
1823 else if ((len = strlen(cur)))
1826 FreeEnvironmentStrings(envv);
1829 /* last ditch: allow any environment variables that begin with 'PERL'
1830 to be obtained from the registry, if found there */
1831 if (strncmp(name, "PERL", 4) == 0)
1832 (void)get_regstr(name, &curitem);
1835 if (curitem && SvCUR(curitem))
1836 return SvPVX(curitem);
1842 win32_putenv(const char *name)
1850 Newx(curitem,strlen(name)+1,char);
1851 strcpy(curitem, name);
1852 val = strchr(curitem, '=');
1854 /* The sane way to deal with the environment.
1855 * Has these advantages over putenv() & co.:
1856 * * enables us to store a truly empty value in the
1857 * environment (like in UNIX).
1858 * * we don't have to deal with RTL globals, bugs and leaks
1859 * (specifically, see http://support.microsoft.com/kb/235601).
1861 * Why you may want to use the RTL environment handling
1862 * (previously enabled by USE_WIN32_RTL_ENV):
1863 * * environ[] and RTL functions will not reflect changes,
1864 * which might be an issue if extensions want to access
1865 * the env. via RTL. This cuts both ways, since RTL will
1866 * not see changes made by extensions that call the Win32
1867 * functions directly, either.
1871 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1880 filetime_to_clock(PFILETIME ft)
1882 __int64 qw = ft->dwHighDateTime;
1884 qw |= ft->dwLowDateTime;
1885 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1890 win32_times(struct tms *timebuf)
1895 clock_t process_time_so_far = clock();
1896 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1898 timebuf->tms_utime = filetime_to_clock(&user);
1899 timebuf->tms_stime = filetime_to_clock(&kernel);
1900 timebuf->tms_cutime = 0;
1901 timebuf->tms_cstime = 0;
1903 /* That failed - e.g. Win95 fallback to clock() */
1904 timebuf->tms_utime = process_time_so_far;
1905 timebuf->tms_stime = 0;
1906 timebuf->tms_cutime = 0;
1907 timebuf->tms_cstime = 0;
1909 return process_time_so_far;
1912 /* fix utime() so it works on directories in NT */
1914 filetime_from_time(PFILETIME pFileTime, time_t Time)
1916 struct tm *pTM = localtime(&Time);
1917 SYSTEMTIME SystemTime;
1923 SystemTime.wYear = pTM->tm_year + 1900;
1924 SystemTime.wMonth = pTM->tm_mon + 1;
1925 SystemTime.wDay = pTM->tm_mday;
1926 SystemTime.wHour = pTM->tm_hour;
1927 SystemTime.wMinute = pTM->tm_min;
1928 SystemTime.wSecond = pTM->tm_sec;
1929 SystemTime.wMilliseconds = 0;
1931 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1932 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1936 win32_unlink(const char *filename)
1942 filename = PerlDir_mapA(filename);
1943 attrs = GetFileAttributesA(filename);
1944 if (attrs == 0xFFFFFFFF) {
1948 if (attrs & FILE_ATTRIBUTE_READONLY) {
1949 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1950 ret = unlink(filename);
1952 (void)SetFileAttributesA(filename, attrs);
1955 ret = unlink(filename);
1960 win32_utime(const char *filename, struct utimbuf *times)
1967 struct utimbuf TimeBuffer;
1970 filename = PerlDir_mapA(filename);
1971 rc = utime(filename, times);
1973 /* EACCES: path specifies directory or readonly file */
1974 if (rc == 0 || errno != EACCES)
1977 if (times == NULL) {
1978 times = &TimeBuffer;
1979 time(×->actime);
1980 times->modtime = times->actime;
1983 /* This will (and should) still fail on readonly files */
1984 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
1985 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
1986 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1987 if (handle == INVALID_HANDLE_VALUE)
1990 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
1991 filetime_from_time(&ftAccess, times->actime) &&
1992 filetime_from_time(&ftWrite, times->modtime) &&
1993 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
1998 CloseHandle(handle);
2003 unsigned __int64 ft_i64;
2008 #define Const64(x) x##LL
2010 #define Const64(x) x##i64
2012 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
2013 #define EPOCH_BIAS Const64(116444736000000000)
2015 /* NOTE: This does not compute the timezone info (doing so can be expensive,
2016 * and appears to be unsupported even by glibc) */
2018 win32_gettimeofday(struct timeval *tp, void *not_used)
2022 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
2023 GetSystemTimeAsFileTime(&ft.ft_val);
2025 /* seconds since epoch */
2026 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
2028 /* microseconds remaining */
2029 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
2035 win32_uname(struct utsname *name)
2037 struct hostent *hep;
2038 STRLEN nodemax = sizeof(name->nodename)-1;
2041 switch (g_osver.dwPlatformId) {
2042 case VER_PLATFORM_WIN32_WINDOWS:
2043 strcpy(name->sysname, "Windows");
2045 case VER_PLATFORM_WIN32_NT:
2046 strcpy(name->sysname, "Windows NT");
2048 case VER_PLATFORM_WIN32s:
2049 strcpy(name->sysname, "Win32s");
2052 strcpy(name->sysname, "Win32 Unknown");
2057 sprintf(name->release, "%d.%d",
2058 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
2061 sprintf(name->version, "Build %d",
2062 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
2063 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
2064 if (g_osver.szCSDVersion[0]) {
2065 char *buf = name->version + strlen(name->version);
2066 sprintf(buf, " (%s)", g_osver.szCSDVersion);
2070 hep = win32_gethostbyname("localhost");
2072 STRLEN len = strlen(hep->h_name);
2073 if (len <= nodemax) {
2074 strcpy(name->nodename, hep->h_name);
2077 strncpy(name->nodename, hep->h_name, nodemax);
2078 name->nodename[nodemax] = '\0';
2083 if (!GetComputerName(name->nodename, &sz))
2084 *name->nodename = '\0';
2087 /* machine (architecture) */
2092 GetSystemInfo(&info);
2094 #if (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION) && !defined(__MINGW_EXTENSION))
2095 procarch = info.u.s.wProcessorArchitecture;
2097 procarch = info.wProcessorArchitecture;
2100 case PROCESSOR_ARCHITECTURE_INTEL:
2101 arch = "x86"; break;
2102 case PROCESSOR_ARCHITECTURE_IA64:
2103 arch = "ia64"; break;
2104 case PROCESSOR_ARCHITECTURE_AMD64:
2105 arch = "amd64"; break;
2106 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2107 arch = "unknown"; break;
2109 sprintf(name->machine, "unknown(0x%x)", procarch);
2110 arch = name->machine;
2113 if (name->machine != arch)
2114 strcpy(name->machine, arch);
2119 /* Timing related stuff */
2122 do_raise(pTHX_ int sig)
2124 if (sig < SIG_SIZE) {
2125 Sighandler_t handler = w32_sighandler[sig];
2126 if (handler == SIG_IGN) {
2129 else if (handler != SIG_DFL) {
2134 /* Choose correct default behaviour */
2150 /* Tell caller to exit thread/process as approriate */
2155 sig_terminate(pTHX_ int sig)
2157 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2158 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2165 win32_async_check(pTHX)
2168 HWND hwnd = w32_message_hwnd;
2170 /* Reset w32_poll_count before doing anything else, incase we dispatch
2171 * messages that end up calling back into perl */
2174 if (hwnd != INVALID_HANDLE_VALUE) {
2175 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2176 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2181 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2182 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2184 /* re-post a WM_QUIT message (we'll mark it as read later) */
2185 if(msg.message == WM_QUIT) {
2186 PostQuitMessage((int)msg.wParam);
2190 if(!CallMsgFilter(&msg, MSGF_USER))
2192 TranslateMessage(&msg);
2193 DispatchMessage(&msg);
2198 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2199 * This is necessary when we are being called by win32_msgwait() to
2200 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2201 * message over and over. An example how this can happen is when
2202 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2203 * is generating messages before the process terminated.
2205 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD);
2207 /* Above or other stuff may have set a signal flag */
2214 /* This function will not return until the timeout has elapsed, or until
2215 * one of the handles is ready. */
2217 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2219 /* We may need several goes at this - so compute when we stop */
2221 unsigned __int64 endtime = timeout;
2222 if (timeout != INFINITE) {
2223 GetSystemTimeAsFileTime(&ticks.ft_val);
2224 ticks.ft_i64 /= 10000;
2225 endtime += ticks.ft_i64;
2227 /* This was a race condition. Do not let a non INFINITE timeout to
2228 * MsgWaitForMultipleObjects roll under 0 creating a near
2229 * infinity/~(UINT32)0 timeout which will appear as a deadlock to the
2230 * user who did a CORE perl function with a non infinity timeout,
2231 * sleep for example. This is 64 to 32 truncation minefield.
2233 * This scenario can only be created if the timespan from the return of
2234 * MsgWaitForMultipleObjects to GetSystemTimeAsFileTime exceeds 1 ms. To
2235 * generate the scenario, manual breakpoints in a C debugger are required,
2236 * or a context switch occured in win32_async_check in PeekMessage, or random
2237 * messages are delivered to the *thread* message queue of the Perl thread
2238 * from another process (msctf.dll doing IPC among its instances, VS debugger
2239 * causes msctf.dll to be loaded into Perl by kernel), see [perl #33096].
2241 while (ticks.ft_i64 <= endtime) {
2242 /* if timeout's type is lengthened, remember to split 64b timeout
2243 * into multiple non-infinity runs of MWFMO */
2244 DWORD result = MsgWaitForMultipleObjects(count, handles, FALSE,
2245 (DWORD)(endtime - ticks.ft_i64),
2246 QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2249 if (result == WAIT_TIMEOUT) {
2250 /* Ran out of time - explicit return of zero to avoid -ve if we
2251 have scheduling issues
2255 if (timeout != INFINITE) {
2256 GetSystemTimeAsFileTime(&ticks.ft_val);
2257 ticks.ft_i64 /= 10000;
2259 if (result == WAIT_OBJECT_0 + count) {
2260 /* Message has arrived - check it */
2261 (void)win32_async_check(aTHX);
2264 /* Not timeout or message - one of handles is ready */
2268 /* If we are past the end say zero */
2269 if (!ticks.ft_i64 || ticks.ft_i64 > endtime)
2271 /* compute time left to wait */
2272 ticks.ft_i64 = endtime - ticks.ft_i64;
2273 /* if more ms than DWORD, then return max DWORD */
2274 return ticks.ft_i64 <= UINT_MAX ? (DWORD)ticks.ft_i64 : UINT_MAX;
2278 win32_internal_wait(int *status, DWORD timeout)
2280 /* XXX this wait emulation only knows about processes
2281 * spawned via win32_spawnvp(P_NOWAIT, ...).
2285 DWORD exitcode, waitcode;
2288 if (w32_num_pseudo_children) {
2289 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2290 timeout, &waitcode);
2291 /* Time out here if there are no other children to wait for. */
2292 if (waitcode == WAIT_TIMEOUT) {
2293 if (!w32_num_children) {
2297 else if (waitcode != WAIT_FAILED) {
2298 if (waitcode >= WAIT_ABANDONED_0
2299 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2300 i = waitcode - WAIT_ABANDONED_0;
2302 i = waitcode - WAIT_OBJECT_0;
2303 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2304 *status = (int)((exitcode & 0xff) << 8);
2305 retval = (int)w32_pseudo_child_pids[i];
2306 remove_dead_pseudo_process(i);
2313 if (!w32_num_children) {
2318 /* if a child exists, wait for it to die */
2319 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2320 if (waitcode == WAIT_TIMEOUT) {
2323 if (waitcode != WAIT_FAILED) {
2324 if (waitcode >= WAIT_ABANDONED_0
2325 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2326 i = waitcode - WAIT_ABANDONED_0;
2328 i = waitcode - WAIT_OBJECT_0;
2329 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2330 *status = (int)((exitcode & 0xff) << 8);
2331 retval = (int)w32_child_pids[i];
2332 remove_dead_process(i);
2337 errno = GetLastError();
2342 win32_waitpid(int pid, int *status, int flags)
2345 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2348 if (pid == -1) /* XXX threadid == 1 ? */
2349 return win32_internal_wait(status, timeout);
2352 child = find_pseudo_pid(-pid);
2354 HANDLE hThread = w32_pseudo_child_handles[child];
2356 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2357 if (waitcode == WAIT_TIMEOUT) {
2360 else if (waitcode == WAIT_OBJECT_0) {
2361 if (GetExitCodeThread(hThread, &waitcode)) {
2362 *status = (int)((waitcode & 0xff) << 8);
2363 retval = (int)w32_pseudo_child_pids[child];
2364 remove_dead_pseudo_process(child);
2376 child = find_pid(pid);
2378 hProcess = w32_child_handles[child];
2379 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2380 if (waitcode == WAIT_TIMEOUT) {
2383 else if (waitcode == WAIT_OBJECT_0) {
2384 if (GetExitCodeProcess(hProcess, &waitcode)) {
2385 *status = (int)((waitcode & 0xff) << 8);
2386 retval = (int)w32_child_pids[child];
2387 remove_dead_process(child);
2395 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
2397 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2398 if (waitcode == WAIT_TIMEOUT) {
2399 CloseHandle(hProcess);
2402 else if (waitcode == WAIT_OBJECT_0) {
2403 if (GetExitCodeProcess(hProcess, &waitcode)) {
2404 *status = (int)((waitcode & 0xff) << 8);
2405 CloseHandle(hProcess);
2409 CloseHandle(hProcess);
2415 return retval >= 0 ? pid : retval;
2419 win32_wait(int *status)
2421 return win32_internal_wait(status, INFINITE);
2424 DllExport unsigned int
2425 win32_sleep(unsigned int t)
2428 /* Win32 times are in ms so *1000 in and /1000 out */
2429 return win32_msgwait(aTHX_ 0, NULL, t*1000, NULL)/1000;
2432 DllExport unsigned int
2433 win32_alarm(unsigned int sec)
2436 * the 'obvious' implentation is SetTimer() with a callback
2437 * which does whatever receiving SIGALRM would do
2438 * we cannot use SIGALRM even via raise() as it is not
2439 * one of the supported codes in <signal.h>
2443 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2444 w32_message_hwnd = win32_create_message_window();
2447 if (w32_message_hwnd == NULL)
2448 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2451 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2456 KillTimer(w32_message_hwnd, w32_timerid);
2463 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2466 win32_crypt(const char *txt, const char *salt)
2469 return des_fcrypt(txt, salt, w32_crypt_buffer);
2472 /* simulate flock by locking a range on the file */
2474 #define LK_LEN 0xffff0000
2477 win32_flock(int fd, int oper)
2483 fh = (HANDLE)_get_osfhandle(fd);
2484 if (fh == (HANDLE)-1) /* _get_osfhandle() already sets errno to EBADF */
2487 memset(&o, 0, sizeof(o));
2490 case LOCK_SH: /* shared lock */
2491 if (LockFileEx(fh, 0, 0, LK_LEN, 0, &o))
2494 case LOCK_EX: /* exclusive lock */
2495 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o))
2498 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2499 if (LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o))
2502 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2503 if (LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2507 case LOCK_UN: /* unlock lock */
2508 if (UnlockFileEx(fh, 0, LK_LEN, 0, &o))
2511 default: /* unknown */
2516 if (GetLastError() == ERROR_LOCK_VIOLATION)
2517 errno = WSAEWOULDBLOCK;
2527 * redirected io subsystem for all XS modules
2540 return (&(_environ));
2543 /* the rest are the remapped stdio routines */
2563 win32_ferror(FILE *fp)
2565 return (ferror(fp));
2570 win32_feof(FILE *fp)
2576 * Since the errors returned by the socket error function
2577 * WSAGetLastError() are not known by the library routine strerror
2578 * we have to roll our own.
2582 win32_strerror(int e)
2584 #if !defined __MINGW32__ /* compiler intolerance */
2585 extern int sys_nerr;
2588 if (e < 0 || e > sys_nerr) {
2593 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
2594 |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0,
2595 w32_strerror_buffer, sizeof(w32_strerror_buffer),
2598 strcpy(w32_strerror_buffer, "Unknown Error");
2600 return w32_strerror_buffer;
2604 #define strerror win32_strerror
2608 win32_str_os_error(void *sv, DWORD dwErr)
2612 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2613 |FORMAT_MESSAGE_IGNORE_INSERTS
2614 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2615 dwErr, 0, (char *)&sMsg, 1, NULL);
2616 /* strip trailing whitespace and period */
2619 --dwLen; /* dwLen doesn't include trailing null */
2620 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2621 if ('.' != sMsg[dwLen])
2626 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2628 dwLen = sprintf(sMsg,
2629 "Unknown error #0x%lX (lookup 0x%lX)",
2630 dwErr, GetLastError());
2634 sv_setpvn((SV*)sv, sMsg, dwLen);
2640 win32_fprintf(FILE *fp, const char *format, ...)
2643 va_start(marker, format); /* Initialize variable arguments. */
2645 return (vfprintf(fp, format, marker));
2649 win32_printf(const char *format, ...)
2652 va_start(marker, format); /* Initialize variable arguments. */
2654 return (vprintf(format, marker));
2658 win32_vfprintf(FILE *fp, const char *format, va_list args)
2660 return (vfprintf(fp, format, args));
2664 win32_vprintf(const char *format, va_list args)
2666 return (vprintf(format, args));
2670 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2672 return fread(buf, size, count, fp);
2676 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2678 return fwrite(buf, size, count, fp);
2681 #define MODE_SIZE 10
2684 win32_fopen(const char *filename, const char *mode)
2692 if (stricmp(filename, "/dev/null")==0)
2695 f = fopen(PerlDir_mapA(filename), mode);
2696 /* avoid buffering headaches for child processes */
2697 if (f && *mode == 'a')
2698 win32_fseek(f, 0, SEEK_END);
2702 #ifndef USE_SOCKETS_AS_HANDLES
2704 #define fdopen my_fdopen
2708 win32_fdopen(int handle, const char *mode)
2712 f = fdopen(handle, (char *) mode);
2713 /* avoid buffering headaches for child processes */
2714 if (f && *mode == 'a')
2715 win32_fseek(f, 0, SEEK_END);
2720 win32_freopen(const char *path, const char *mode, FILE *stream)
2723 if (stricmp(path, "/dev/null")==0)
2726 return freopen(PerlDir_mapA(path), mode, stream);
2730 win32_fclose(FILE *pf)
2732 return my_fclose(pf); /* defined in win32sck.c */
2736 win32_fputs(const char *s,FILE *pf)
2738 return fputs(s, pf);
2742 win32_fputc(int c,FILE *pf)
2748 win32_ungetc(int c,FILE *pf)
2750 return ungetc(c,pf);
2754 win32_getc(FILE *pf)
2760 win32_fileno(FILE *pf)
2766 win32_clearerr(FILE *pf)
2773 win32_fflush(FILE *pf)
2779 win32_ftell(FILE *pf)
2781 #if defined(WIN64) || defined(USE_LARGE_FILES)
2783 if (fgetpos(pf, &pos))
2792 win32_fseek(FILE *pf, Off_t offset,int origin)
2794 #if defined(WIN64) || defined(USE_LARGE_FILES)
2798 if (fgetpos(pf, &pos))
2803 fseek(pf, 0, SEEK_END);
2804 pos = _telli64(fileno(pf));
2813 return fsetpos(pf, &offset);
2815 return fseek(pf, (long)offset, origin);
2820 win32_fgetpos(FILE *pf,fpos_t *p)
2822 return fgetpos(pf, p);
2826 win32_fsetpos(FILE *pf,const fpos_t *p)
2828 return fsetpos(pf, p);
2832 win32_rewind(FILE *pf)
2842 char prefix[MAX_PATH+1];
2843 char filename[MAX_PATH+1];
2844 DWORD len = GetTempPath(MAX_PATH, prefix);
2845 if (len && len < MAX_PATH) {
2846 if (GetTempFileName(prefix, "plx", 0, filename)) {
2847 HANDLE fh = CreateFile(filename,
2848 DELETE | GENERIC_READ | GENERIC_WRITE,
2852 FILE_ATTRIBUTE_NORMAL
2853 | FILE_FLAG_DELETE_ON_CLOSE,
2855 if (fh != INVALID_HANDLE_VALUE) {
2856 int fd = win32_open_osfhandle((intptr_t)fh, 0);
2858 DEBUG_p(PerlIO_printf(Perl_debug_log,
2859 "Created tmpfile=%s\n",filename));
2871 int fd = win32_tmpfd();
2873 return win32_fdopen(fd, "w+b");
2885 win32_fstat(int fd, Stat_t *sbufptr)
2887 #if defined(WIN64) || defined(USE_LARGE_FILES)
2888 return _fstati64(fd, sbufptr);
2890 return fstat(fd, sbufptr);
2895 win32_pipe(int *pfd, unsigned int size, int mode)
2897 return _pipe(pfd, size, mode);
2901 win32_popenlist(const char *mode, IV narg, SV **args)
2904 Perl_croak(aTHX_ "List form of pipe open not implemented");
2909 * a popen() clone that respects PERL5SHELL
2911 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
2915 win32_popen(const char *command, const char *mode)
2917 #ifdef USE_RTL_POPEN
2918 return _popen(command, mode);
2930 /* establish which ends read and write */
2931 if (strchr(mode,'w')) {
2932 stdfd = 0; /* stdin */
2935 nhandle = STD_INPUT_HANDLE;
2937 else if (strchr(mode,'r')) {
2938 stdfd = 1; /* stdout */
2941 nhandle = STD_OUTPUT_HANDLE;
2946 /* set the correct mode */
2947 if (strchr(mode,'b'))
2949 else if (strchr(mode,'t'))
2952 ourmode = _fmode & (O_TEXT | O_BINARY);
2954 /* the child doesn't inherit handles */
2955 ourmode |= O_NOINHERIT;
2957 if (win32_pipe(p, 512, ourmode) == -1)
2960 /* save the old std handle (this needs to happen before the
2961 * dup2(), since that might call SetStdHandle() too) */
2964 old_h = GetStdHandle(nhandle);
2966 /* save current stdfd */
2967 if ((oldfd = win32_dup(stdfd)) == -1)
2970 /* make stdfd go to child end of pipe (implicitly closes stdfd) */
2971 /* stdfd will be inherited by the child */
2972 if (win32_dup2(p[child], stdfd) == -1)
2975 /* close the child end in parent */
2976 win32_close(p[child]);
2978 /* set the new std handle (in case dup2() above didn't) */
2979 SetStdHandle(nhandle, (HANDLE)_get_osfhandle(stdfd));
2981 /* start the child */
2984 if ((childpid = do_spawn_nowait((char*)command)) == -1)
2987 /* revert stdfd to whatever it was before */
2988 if (win32_dup2(oldfd, stdfd) == -1)
2991 /* close saved handle */
2994 /* restore the old std handle (this needs to happen after the
2995 * dup2(), since that might call SetStdHandle() too */
2997 SetStdHandle(nhandle, old_h);
3002 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3004 /* set process id so that it can be returned by perl's open() */
3005 PL_forkprocess = childpid;
3008 /* we have an fd, return a file stream */
3009 return (PerlIO_fdopen(p[parent], (char *)mode));
3012 /* we don't need to check for errors here */
3016 win32_dup2(oldfd, stdfd);
3020 SetStdHandle(nhandle, old_h);
3026 #endif /* USE_RTL_POPEN */
3034 win32_pclose(PerlIO *pf)
3036 #ifdef USE_RTL_POPEN
3040 int childpid, status;
3043 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3046 childpid = SvIVX(sv);
3062 if (win32_waitpid(childpid, &status, 0) == -1)
3067 #endif /* USE_RTL_POPEN */
3071 win32_link(const char *oldname, const char *newname)
3074 WCHAR wOldName[MAX_PATH+1];
3075 WCHAR wNewName[MAX_PATH+1];
3077 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3078 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3079 (wcscpy(wOldName, PerlDir_mapW(wOldName)),
3080 CreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3084 /* This isn't perfect, eg. Win32 returns ERROR_ACCESS_DENIED for
3085 both permissions errors and if the source is a directory, while
3086 POSIX wants EACCES and EPERM respectively.
3088 Determined by experimentation on Windows 7 x64 SP1, since MS
3089 don't document what error codes are returned.
3091 switch (GetLastError()) {
3092 case ERROR_BAD_NET_NAME:
3093 case ERROR_BAD_NETPATH:
3094 case ERROR_BAD_PATHNAME:
3095 case ERROR_FILE_NOT_FOUND:
3096 case ERROR_FILENAME_EXCED_RANGE:
3097 case ERROR_INVALID_DRIVE:
3098 case ERROR_PATH_NOT_FOUND:
3101 case ERROR_ALREADY_EXISTS:
3104 case ERROR_ACCESS_DENIED:
3107 case ERROR_NOT_SAME_DEVICE:
3111 /* ERROR_INVALID_FUNCTION - eg. on a FAT volume */
3119 win32_rename(const char *oname, const char *newname)
3121 char szOldName[MAX_PATH+1];
3123 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3126 if (stricmp(newname, oname))
3127 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3128 strcpy(szOldName, PerlDir_mapA(oname));
3130 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3132 DWORD err = GetLastError();
3134 case ERROR_BAD_NET_NAME:
3135 case ERROR_BAD_NETPATH:
3136 case ERROR_BAD_PATHNAME:
3137 case ERROR_FILE_NOT_FOUND:
3138 case ERROR_FILENAME_EXCED_RANGE:
3139 case ERROR_INVALID_DRIVE:
3140 case ERROR_NO_MORE_FILES:
3141 case ERROR_PATH_NOT_FOUND:
3154 win32_setmode(int fd, int mode)
3156 return setmode(fd, mode);
3160 win32_chsize(int fd, Off_t size)
3162 #if defined(WIN64) || defined(USE_LARGE_FILES)
3164 Off_t cur, end, extend;
3166 cur = win32_tell(fd);
3169 end = win32_lseek(fd, 0, SEEK_END);
3172 extend = size - end;
3176 else if (extend > 0) {
3177 /* must grow the file, padding with nulls */
3179 int oldmode = win32_setmode(fd, O_BINARY);
3181 memset(b, '\0', sizeof(b));
3183 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3184 count = win32_write(fd, b, count);
3185 if ((int)count < 0) {
3189 } while ((extend -= count) > 0);
3190 win32_setmode(fd, oldmode);
3193 /* shrink the file */
3194 win32_lseek(fd, size, SEEK_SET);
3195 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3201 win32_lseek(fd, cur, SEEK_SET);
3204 return chsize(fd, (long)size);
3209 win32_lseek(int fd, Off_t offset, int origin)
3211 #if defined(WIN64) || defined(USE_LARGE_FILES)
3212 return _lseeki64(fd, offset, origin);
3214 return lseek(fd, (long)offset, origin);
3221 #if defined(WIN64) || defined(USE_LARGE_FILES)
3222 return _telli64(fd);
3229 win32_open(const char *path, int flag, ...)
3236 pmode = va_arg(ap, int);
3239 if (stricmp(path, "/dev/null")==0)
3242 return open(PerlDir_mapA(path), flag, pmode);
3245 /* close() that understands socket */
3246 extern int my_close(int); /* in win32sck.c */
3251 return my_close(fd);
3261 win32_isatty(int fd)
3263 /* The Microsoft isatty() function returns true for *all*
3264 * character mode devices, including "nul". Our implementation
3265 * should only return true if the handle has a console buffer.
3268 HANDLE fh = (HANDLE)_get_osfhandle(fd);
3269 if (fh == (HANDLE)-1) {
3270 /* errno is already set to EBADF */
3274 if (GetConsoleMode(fh, &mode))
3288 win32_dup2(int fd1,int fd2)
3290 return dup2(fd1,fd2);
3294 win32_read(int fd, void *buf, unsigned int cnt)
3296 return read(fd, buf, cnt);
3300 win32_write(int fd, const void *buf, unsigned int cnt)
3302 return write(fd, buf, cnt);
3306 win32_mkdir(const char *dir, int mode)
3309 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3313 win32_rmdir(const char *dir)
3316 return rmdir(PerlDir_mapA(dir));
3320 win32_chdir(const char *dir)
3331 win32_access(const char *path, int mode)
3334 return access(PerlDir_mapA(path), mode);
3338 win32_chmod(const char *path, int mode)
3341 return chmod(PerlDir_mapA(path), mode);
3346 create_command_line(char *cname, STRLEN clen, const char * const *args)
3353 bool bat_file = FALSE;
3354 bool cmd_shell = FALSE;
3355 bool dumb_shell = FALSE;
3356 bool extra_quotes = FALSE;
3357 bool quote_next = FALSE;
3360 cname = (char*)args[0];
3362 /* The NT cmd.exe shell has the following peculiarity that needs to be
3363 * worked around. It strips a leading and trailing dquote when any
3364 * of the following is true:
3365 * 1. the /S switch was used
3366 * 2. there are more than two dquotes
3367 * 3. there is a special character from this set: &<>()@^|
3368 * 4. no whitespace characters within the two dquotes
3369 * 5. string between two dquotes isn't an executable file
3370 * To work around this, we always add a leading and trailing dquote
3371 * to the string, if the first argument is either "cmd.exe" or "cmd",
3372 * and there were at least two or more arguments passed to cmd.exe
3373 * (not including switches).
3374 * XXX the above rules (from "cmd /?") don't seem to be applied
3375 * always, making for the convolutions below :-(
3379 clen = strlen(cname);
3382 && (stricmp(&cname[clen-4], ".bat") == 0
3383 || (stricmp(&cname[clen-4], ".cmd") == 0)))
3389 char *exe = strrchr(cname, '/');
3390 char *exe2 = strrchr(cname, '\\');
3397 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3401 else if (stricmp(exe, "command.com") == 0
3402 || stricmp(exe, "command") == 0)
3409 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3410 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3411 STRLEN curlen = strlen(arg);
3412 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3413 len += 2; /* assume quoting needed (worst case) */
3415 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3417 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3420 Newx(cmd, len, char);
3425 extra_quotes = TRUE;
3428 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3430 STRLEN curlen = strlen(arg);
3432 /* we want to protect empty arguments and ones with spaces with
3433 * dquotes, but only if they aren't already there */
3438 else if (quote_next) {
3439 /* see if it really is multiple arguments pretending to
3440 * be one and force a set of quotes around it */
3441 if (*find_next_space(arg))
3444 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3446 while (i < curlen) {
3447 if (isSPACE(arg[i])) {
3450 else if (arg[i] == '"') {
3474 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3475 && stricmp(arg+curlen-2, "/c") == 0)
3477 /* is there a next argument? */
3478 if (args[index+1]) {
3479 /* are there two or more next arguments? */
3480 if (args[index+2]) {
3482 extra_quotes = TRUE;
3485 /* single argument, force quoting if it has spaces */
3501 qualified_path(const char *cmd)
3505 char *fullcmd, *curfullcmd;
3511 fullcmd = (char*)cmd;
3513 if (*fullcmd == '/' || *fullcmd == '\\')
3520 pathstr = PerlEnv_getenv("PATH");
3522 /* worst case: PATH is a single directory; we need additional space
3523 * to append "/", ".exe" and trailing "\0" */
3524 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3525 curfullcmd = fullcmd;
3530 /* start by appending the name to the current prefix */
3531 strcpy(curfullcmd, cmd);
3532 curfullcmd += cmdlen;
3534 /* if it doesn't end with '.', or has no extension, try adding
3535 * a trailing .exe first */
3536 if (cmd[cmdlen-1] != '.'
3537 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3539 strcpy(curfullcmd, ".exe");
3540 res = GetFileAttributes(fullcmd);
3541 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3546 /* that failed, try the bare name */
3547 res = GetFileAttributes(fullcmd);
3548 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3551 /* quit if no other path exists, or if cmd already has path */
3552 if (!pathstr || !*pathstr || has_slash)
3555 /* skip leading semis */
3556 while (*pathstr == ';')
3559 /* build a new prefix from scratch */
3560 curfullcmd = fullcmd;
3561 while (*pathstr && *pathstr != ';') {
3562 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3563 pathstr++; /* skip initial '"' */
3564 while (*pathstr && *pathstr != '"') {
3565 *curfullcmd++ = *pathstr++;
3568 pathstr++; /* skip trailing '"' */
3571 *curfullcmd++ = *pathstr++;
3575 pathstr++; /* skip trailing semi */
3576 if (curfullcmd > fullcmd /* append a dir separator */
3577 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3579 *curfullcmd++ = '\\';
3587 /* The following are just place holders.
3588 * Some hosts may provide and environment that the OS is
3589 * not tracking, therefore, these host must provide that
3590 * environment and the current directory to CreateProcess
3594 win32_get_childenv(void)
3600 win32_free_childenv(void* d)
3605 win32_clearenv(void)
3607 char *envv = GetEnvironmentStrings();
3611 char *end = strchr(cur,'=');
3612 if (end && end != cur) {
3614 SetEnvironmentVariable(cur, NULL);
3616 cur = end + strlen(end+1)+2;
3618 else if ((len = strlen(cur)))
3621 FreeEnvironmentStrings(envv);
3625 win32_get_childdir(void)
3629 char szfilename[MAX_PATH+1];
3631 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
3632 Newx(ptr, strlen(szfilename)+1, char);
3633 strcpy(ptr, szfilename);
3638 win32_free_childdir(char* d)
3645 /* XXX this needs to be made more compatible with the spawnvp()
3646 * provided by the various RTLs. In particular, searching for
3647 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
3648 * This doesn't significantly affect perl itself, because we
3649 * always invoke things using PERL5SHELL if a direct attempt to
3650 * spawn the executable fails.
3652 * XXX splitting and rejoining the commandline between do_aspawn()
3653 * and win32_spawnvp() could also be avoided.
3657 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
3659 #ifdef USE_RTL_SPAWNVP
3660 return spawnvp(mode, cmdname, (char * const *)argv);
3667 STARTUPINFO StartupInfo;
3668 PROCESS_INFORMATION ProcessInformation;
3671 char *fullcmd = NULL;
3672 char *cname = (char *)cmdname;
3676 clen = strlen(cname);
3677 /* if command name contains dquotes, must remove them */
3678 if (strchr(cname, '"')) {
3680 Newx(cname,clen+1,char);
3693 cmd = create_command_line(cname, clen, argv);
3695 env = PerlEnv_get_childenv();
3696 dir = PerlEnv_get_childdir();
3699 case P_NOWAIT: /* asynch + remember result */
3700 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
3705 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
3708 create |= CREATE_NEW_PROCESS_GROUP;
3711 case P_WAIT: /* synchronous execution */
3713 default: /* invalid mode */
3718 memset(&StartupInfo,0,sizeof(StartupInfo));
3719 StartupInfo.cb = sizeof(StartupInfo);
3720 memset(&tbl,0,sizeof(tbl));
3721 PerlEnv_get_child_IO(&tbl);
3722 StartupInfo.dwFlags = tbl.dwFlags;
3723 StartupInfo.dwX = tbl.dwX;
3724 StartupInfo.dwY = tbl.dwY;
3725 StartupInfo.dwXSize = tbl.dwXSize;
3726 StartupInfo.dwYSize = tbl.dwYSize;
3727 StartupInfo.dwXCountChars = tbl.dwXCountChars;
3728 StartupInfo.dwYCountChars = tbl.dwYCountChars;
3729 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
3730 StartupInfo.wShowWindow = tbl.wShowWindow;
3731 StartupInfo.hStdInput = tbl.childStdIn;
3732 StartupInfo.hStdOutput = tbl.childStdOut;
3733 StartupInfo.hStdError = tbl.childStdErr;
3734 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
3735 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
3736 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
3738 create |= CREATE_NEW_CONSOLE;
3741 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3743 if (w32_use_showwindow) {
3744 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
3745 StartupInfo.wShowWindow = w32_showwindow;
3748 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
3751 if (!CreateProcess(cname, /* search PATH to find executable */
3752 cmd, /* executable, and its arguments */
3753 NULL, /* process attributes */
3754 NULL, /* thread attributes */
3755 TRUE, /* inherit handles */
3756 create, /* creation flags */
3757 (LPVOID)env, /* inherit environment */
3758 dir, /* inherit cwd */
3760 &ProcessInformation))
3762 /* initial NULL argument to CreateProcess() does a PATH
3763 * search, but it always first looks in the directory
3764 * where the current process was started, which behavior
3765 * is undesirable for backward compatibility. So we
3766 * jump through our own hoops by picking out the path
3767 * we really want it to use. */
3769 fullcmd = qualified_path(cname);
3771 if (cname != cmdname)
3774 DEBUG_p(PerlIO_printf(Perl_debug_log,
3775 "Retrying [%s] with same args\n",
3785 if (mode == P_NOWAIT) {
3786 /* asynchronous spawn -- store handle, return PID */
3787 ret = (int)ProcessInformation.dwProcessId;
3789 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
3790 w32_child_pids[w32_num_children] = (DWORD)ret;
3795 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
3796 /* FIXME: if msgwait returned due to message perhaps forward the
3797 "signal" to the process
3799 GetExitCodeProcess(ProcessInformation.hProcess, &status);
3801 CloseHandle(ProcessInformation.hProcess);
3804 CloseHandle(ProcessInformation.hThread);
3807 PerlEnv_free_childenv(env);
3808 PerlEnv_free_childdir(dir);
3810 if (cname != cmdname)
3817 win32_execv(const char *cmdname, const char *const *argv)
3821 /* if this is a pseudo-forked child, we just want to spawn
3822 * the new program, and return */
3824 return spawnv(P_WAIT, cmdname, argv);
3826 return execv(cmdname, argv);
3830 win32_execvp(const char *cmdname, const char *const *argv)
3834 /* if this is a pseudo-forked child, we just want to spawn
3835 * the new program, and return */
3836 if (w32_pseudo_id) {
3837 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
3846 return execvp(cmdname, argv);
3850 win32_perror(const char *str)
3856 win32_setbuf(FILE *pf, char *buf)
3862 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
3864 return setvbuf(pf, buf, type, size);
3868 win32_flushall(void)
3874 win32_fcloseall(void)
3880 win32_fgets(char *s, int n, FILE *pf)
3882 return fgets(s, n, pf);
3892 win32_fgetc(FILE *pf)
3898 win32_putc(int c, FILE *pf)
3904 win32_puts(const char *s)
3916 win32_putchar(int c)
3923 #ifndef USE_PERL_SBRK
3925 static char *committed = NULL; /* XXX threadead */
3926 static char *base = NULL; /* XXX threadead */
3927 static char *reserved = NULL; /* XXX threadead */
3928 static char *brk = NULL; /* XXX threadead */
3929 static DWORD pagesize = 0; /* XXX threadead */
3932 sbrk(ptrdiff_t need)
3937 GetSystemInfo(&info);
3938 /* Pretend page size is larger so we don't perpetually
3939 * call the OS to commit just one page ...
3941 pagesize = info.dwPageSize << 3;
3943 if (brk+need >= reserved)
3945 DWORD size = brk+need-reserved;
3947 char *prev_committed = NULL;
3948 if (committed && reserved && committed < reserved)
3950 /* Commit last of previous chunk cannot span allocations */
3951 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
3954 /* Remember where we committed from in case we want to decommit later */
3955 prev_committed = committed;
3956 committed = reserved;
3959 /* Reserve some (more) space
3960 * Contiguous blocks give us greater efficiency, so reserve big blocks -
3961 * this is only address space not memory...
3962 * Note this is a little sneaky, 1st call passes NULL as reserved
3963 * so lets system choose where we start, subsequent calls pass
3964 * the old end address so ask for a contiguous block
3967 if (size < 64*1024*1024)
3968 size = 64*1024*1024;
3969 size = ((size + pagesize - 1) / pagesize) * pagesize;
3970 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
3973 reserved = addr+size;
3983 /* The existing block could not be extended far enough, so decommit
3984 * anything that was just committed above and start anew */
3987 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
3990 reserved = base = committed = brk = NULL;
4001 if (brk > committed)
4003 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4005 if (committed+size > reserved)
4006 size = reserved-committed;
4007 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4020 win32_malloc(size_t size)
4022 return malloc(size);
4026 win32_calloc(size_t numitems, size_t size)
4028 return calloc(numitems,size);
4032 win32_realloc(void *block, size_t size)
4034 return realloc(block,size);
4038 win32_free(void *block)
4045 win32_open_osfhandle(intptr_t handle, int flags)
4047 return _open_osfhandle(handle, flags);
4051 win32_get_osfhandle(int fd)
4053 return (intptr_t)_get_osfhandle(fd);
4057 win32_fdupopen(FILE *pf)
4062 int fileno = win32_dup(win32_fileno(pf));
4064 /* open the file in the same mode */
4065 if((pf)->_flag & _IOREAD) {
4069 else if((pf)->_flag & _IOWRT) {
4073 else if((pf)->_flag & _IORW) {
4079 /* it appears that the binmode is attached to the
4080 * file descriptor so binmode files will be handled
4083 pfdup = win32_fdopen(fileno, mode);
4085 /* move the file pointer to the same position */
4086 if (!fgetpos(pf, &pos)) {
4087 fsetpos(pfdup, &pos);
4093 win32_dynaload(const char* filename)
4096 char buf[MAX_PATH+1];
4099 /* LoadLibrary() doesn't recognize forward slashes correctly,
4100 * so turn 'em back. */
4101 first = strchr(filename, '/');
4103 STRLEN len = strlen(filename);
4104 if (len <= MAX_PATH) {
4105 strcpy(buf, filename);
4106 filename = &buf[first - filename];
4108 if (*filename == '/')
4109 *(char*)filename = '\\';
4115 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4118 XS(w32_SetChildShowWindow)
4121 BOOL use_showwindow = w32_use_showwindow;
4122 /* use "unsigned short" because Perl has redefined "WORD" */
4123 unsigned short showwindow = w32_showwindow;
4126 Perl_croak(aTHX_ "usage: Win32::SetChildShowWindow($showwindow)");
4128 if (items == 0 || !SvOK(ST(0)))
4129 w32_use_showwindow = FALSE;
4131 w32_use_showwindow = TRUE;
4132 w32_showwindow = (unsigned short)SvIV(ST(0));
4137 ST(0) = sv_2mortal(newSViv(showwindow));
4139 ST(0) = &PL_sv_undef;
4144 Perl_init_os_extras(void)
4147 char *file = __FILE__;
4149 /* Initialize Win32CORE if it has been statically linked. */
4150 void (*pfn_init)(pTHX);
4151 pfn_init = (void (*)(pTHX))GetProcAddress((HMODULE)w32_perldll_handle, "init_Win32CORE");
4155 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4159 win32_signal_context(void)
4164 my_perl = PL_curinterp;
4165 PERL_SET_THX(my_perl);
4169 return PL_curinterp;
4175 win32_ctrlhandler(DWORD dwCtrlType)
4178 dTHXa(PERL_GET_SIG_CONTEXT);
4184 switch(dwCtrlType) {
4185 case CTRL_CLOSE_EVENT:
4186 /* A signal that the system sends to all processes attached to a console when
4187 the user closes the console (either by choosing the Close command from the
4188 console window's System menu, or by choosing the End Task command from the
4191 if (do_raise(aTHX_ 1)) /* SIGHUP */
4192 sig_terminate(aTHX_ 1);
4196 /* A CTRL+c signal was received */
4197 if (do_raise(aTHX_ SIGINT))
4198 sig_terminate(aTHX_ SIGINT);
4201 case CTRL_BREAK_EVENT:
4202 /* A CTRL+BREAK signal was received */
4203 if (do_raise(aTHX_ SIGBREAK))
4204 sig_terminate(aTHX_ SIGBREAK);
4207 case CTRL_LOGOFF_EVENT:
4208 /* A signal that the system sends to all console processes when a user is logging
4209 off. This signal does not indicate which user is logging off, so no
4210 assumptions can be made.
4213 case CTRL_SHUTDOWN_EVENT:
4214 /* A signal that the system sends to all console processes when the system is
4217 if (do_raise(aTHX_ SIGTERM))
4218 sig_terminate(aTHX_ SIGTERM);
4227 #ifdef SET_INVALID_PARAMETER_HANDLER
4228 # include <crtdbg.h>
4239 /* fetch Unicode version of PATH */
4241 wide_path = win32_malloc(len*sizeof(WCHAR));
4243 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4247 wide_path = win32_realloc(wide_path, len*sizeof(WCHAR));
4252 /* convert to ANSI pathnames */
4253 wide_dir = wide_path;
4256 WCHAR *sep = wcschr(wide_dir, ';');
4264 /* remove quotes around pathname */
4265 if (*wide_dir == '"')
4267 wide_len = wcslen(wide_dir);
4268 if (wide_len && wide_dir[wide_len-1] == '"')
4269 wide_dir[wide_len-1] = '\0';
4271 /* append ansi_dir to ansi_path */
4272 ansi_dir = win32_ansipath(wide_dir);
4273 ansi_len = strlen(ansi_dir);
4275 size_t newlen = len + 1 + ansi_len;
4276 ansi_path = win32_realloc(ansi_path, newlen+1);
4279 ansi_path[len] = ';';
4280 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4285 ansi_path = win32_malloc(5+len+1);
4288 memcpy(ansi_path, "PATH=", 5);
4289 memcpy(ansi_path+5, ansi_dir, len+1);
4292 win32_free(ansi_dir);
4297 /* Update C RTL environ array. This will only have full effect if
4298 * perl_parse() is later called with `environ` as the `env` argument.
4299 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4301 * We do have to ansify() the PATH before Perl has been fully
4302 * initialized because S_find_script() uses the PATH when perl
4303 * is being invoked with the -S option. This happens before %ENV
4304 * is initialized in S_init_postdump_symbols().
4306 * XXX Is this a bug? Should S_find_script() use the environment
4307 * XXX passed in the `env` arg to parse_perl()?
4310 /* Keep system environment in sync because S_init_postdump_symbols()
4311 * will not call mg_set() if it initializes %ENV from `environ`.
4313 SetEnvironmentVariableA("PATH", ansi_path+5);
4314 /* We are intentionally leaking the ansi_path string here because
4315 * the some runtime libraries puts it directly into the environ
4316 * array. The Microsoft runtime library seems to make a copy,
4317 * but will leak the copy should it be replaced again later.
4318 * Since this code is only called once during PERL_SYS_INIT this
4319 * shouldn't really matter.
4322 win32_free(wide_path);
4326 Perl_win32_init(int *argcp, char ***argvp)
4328 #ifdef SET_INVALID_PARAMETER_HANDLER
4329 _invalid_parameter_handler oldHandler, newHandler;
4330 newHandler = my_invalid_parameter_handler;
4331 oldHandler = _set_invalid_parameter_handler(newHandler);
4332 _CrtSetReportMode(_CRT_ASSERT, 0);
4334 /* Disable floating point errors, Perl will trap the ones we
4335 * care about. VC++ RTL defaults to switching these off
4336 * already, but some RTLs don't. Since we don't
4337 * want to be at the vendor's whim on the default, we set
4338 * it explicitly here.
4340 #if !defined(__GNUC__)
4341 _control87(MCW_EM, MCW_EM);
4345 /* When the manifest resource requests Common-Controls v6 then
4346 * user32.dll no longer registers all the Windows classes used for
4347 * standard controls but leaves some of them to be registered by
4348 * comctl32.dll. InitCommonControls() doesn't do anything but calling
4349 * it makes sure comctl32.dll gets loaded into the process and registers
4350 * the standard control classes. Without this even normal Windows APIs
4351 * like MessageBox() can fail under some versions of Windows XP.
4353 InitCommonControls();
4355 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4356 GetVersionEx(&g_osver);
4362 Perl_win32_term(void)
4372 win32_get_child_IO(child_IO_table* ptbl)
4374 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4375 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4376 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4380 win32_signal(int sig, Sighandler_t subcode)
4383 if (sig < SIG_SIZE) {
4384 int save_errno = errno;
4385 Sighandler_t result;
4386 #ifdef SET_INVALID_PARAMETER_HANDLER
4387 /* Silence our invalid parameter handler since we expect to make some
4388 * calls with invalid signal numbers giving a SIG_ERR result. */
4389 BOOL oldvalue = set_silent_invalid_parameter_handler(TRUE);
4391 result = signal(sig, subcode);
4392 #ifdef SET_INVALID_PARAMETER_HANDLER
4393 set_silent_invalid_parameter_handler(oldvalue);
4395 if (result == SIG_ERR) {
4396 result = w32_sighandler[sig];
4399 w32_sighandler[sig] = subcode;
4408 /* The PerlMessageWindowClass's WindowProc */
4410 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4412 return win32_process_message(hwnd, msg, wParam, lParam) ?
4413 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4416 /* The real message handler. Can be called with
4417 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4418 * that it processes */
4420 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4422 /* BEWARE. The context retrieved using dTHX; is the context of the
4423 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4424 * up to and including WM_CREATE. If it ever happens that you need the
4425 * 'child' context before this, then it needs to be passed into
4426 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4427 * from the lparam of CreateWindow(). It could then be stored/retrieved
4428 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4429 * the dTHX calls here. */
4430 /* XXX For now it is assumed that the overhead of the dTHX; for what
4431 * are relativley infrequent code-paths, is better than the added
4432 * complexity of getting the correct context passed into
4433 * win32_create_message_window() */
4438 case WM_USER_MESSAGE: {
4439 long child = find_pseudo_pid((int)wParam);
4442 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4449 case WM_USER_KILL: {
4451 /* We use WM_USER_KILL to fake kill() with other signals */
4452 int sig = (int)wParam;
4453 if (do_raise(aTHX_ sig))
4454 sig_terminate(aTHX_ sig);
4461 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4462 if (w32_timerid && w32_timerid==(UINT)wParam) {
4463 KillTimer(w32_message_hwnd, w32_timerid);
4466 /* Now fake a call to signal handler */
4467 if (do_raise(aTHX_ 14))
4468 sig_terminate(aTHX_ 14);
4480 /* Above or other stuff may have set a signal flag, and we may not have
4481 * been called from win32_async_check() (e.g. some other GUI's message
4482 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4483 * handler that die's, and the message loop that calls here is wrapped
4484 * in an eval, then you may well end up with orphaned windows - signals
4485 * are dispatched by win32_async_check() */
4491 win32_create_message_window_class(void)
4493 /* create the window class for "message only" windows */
4497 wc.lpfnWndProc = win32_message_window_proc;
4498 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4499 wc.lpszClassName = "PerlMessageWindowClass";
4501 /* second and subsequent calls will fail, but class
4502 * will already be registered */
4507 win32_create_message_window(void)
4509 win32_create_message_window_class();
4510 return CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4511 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4514 #ifdef HAVE_INTERP_INTERN
4517 win32_csighandler(int sig)
4520 dTHXa(PERL_GET_SIG_CONTEXT);
4521 Perl_warn(aTHX_ "Got signal %d",sig);
4526 #if defined(__MINGW32__) && defined(__cplusplus)
4527 #define CAST_HWND__(x) (HWND__*)(x)
4529 #define CAST_HWND__(x) x
4533 Perl_sys_intern_init(pTHX)
4537 w32_perlshell_tokens = NULL;
4538 w32_perlshell_vec = (char**)NULL;
4539 w32_perlshell_items = 0;
4540 w32_fdpid = newAV();
4541 Newx(w32_children, 1, child_tab);
4542 w32_num_children = 0;
4543 # ifdef USE_ITHREADS
4545 Newx(w32_pseudo_children, 1, pseudo_child_tab);
4546 w32_num_pseudo_children = 0;
4549 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4551 for (i=0; i < SIG_SIZE; i++) {
4552 w32_sighandler[i] = SIG_DFL;
4554 # ifdef MULTIPLICITY
4555 if (my_perl == PL_curinterp) {
4559 /* Force C runtime signal stuff to set its console handler */
4560 signal(SIGINT,win32_csighandler);
4561 signal(SIGBREAK,win32_csighandler);
4563 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
4564 * flag. This has the side-effect of disabling Ctrl-C events in all
4565 * processes in this group.
4566 * We re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
4567 * with a NULL handler.
4569 SetConsoleCtrlHandler(NULL,FALSE);
4571 /* Push our handler on top */
4572 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
4577 Perl_sys_intern_clear(pTHX)
4579 Safefree(w32_perlshell_tokens);
4580 Safefree(w32_perlshell_vec);
4581 /* NOTE: w32_fdpid is freed by sv_clean_all() */
4582 Safefree(w32_children);
4584 KillTimer(w32_message_hwnd, w32_timerid);
4587 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
4588 DestroyWindow(w32_message_hwnd);
4589 # ifdef MULTIPLICITY
4590 if (my_perl == PL_curinterp) {
4594 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
4596 # ifdef USE_ITHREADS
4597 Safefree(w32_pseudo_children);
4601 # ifdef USE_ITHREADS
4604 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
4606 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
4608 dst->perlshell_tokens = NULL;
4609 dst->perlshell_vec = (char**)NULL;
4610 dst->perlshell_items = 0;
4611 dst->fdpid = newAV();
4612 Newxz(dst->children, 1, child_tab);
4614 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
4616 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
4617 dst->poll_count = 0;
4618 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
4620 # endif /* USE_ITHREADS */
4621 #endif /* HAVE_INTERP_INTERN */