3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc., http://info.hip.com/info/
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
19 # define HWND_MESSAGE ((HWND)-3)
21 #ifndef WC_NO_BEST_FIT_CHARS
22 # define WC_NO_BEST_FIT_CHARS 0x00000400 /* requires Windows 2000 or later */
29 #define SystemProcessesAndThreadsInformation 5
31 /* Inline some definitions from the DDK */
42 LARGE_INTEGER CreateTime;
43 LARGE_INTEGER UserTime;
44 LARGE_INTEGER KernelTime;
45 UNICODE_STRING ProcessName;
48 ULONG InheritedFromProcessId;
49 /* Remainder of the structure depends on the Windows version,
50 * but we don't need those additional fields anyways... */
53 /* #include "config.h" */
55 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
64 #define PERL_NO_GET_CONTEXT
70 /* assert.h conflicts with #define of assert in perl.h */
77 #if defined(_MSC_VER) || defined(__MINGW32__)
78 #include <sys/utime.h>
83 /* Mingw32 defaults to globing command line
84 * So we turn it off like this:
89 #if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION==1)
90 /* Mingw32-1.1 is missing some prototypes */
92 FILE * _wfopen(LPCWSTR wszFileName, LPCWSTR wszMode);
93 FILE * _wfdopen(int nFd, LPCWSTR wszMode);
94 FILE * _freopen(LPCWSTR wszFileName, LPCWSTR wszMode, FILE * pOldStream);
100 #if defined(__BORLANDC__)
102 # define _utimbuf utimbuf
106 #define EXECF_SPAWN 2
107 #define EXECF_SPAWN_NOWAIT 3
109 #if defined(PERL_IMPLICIT_SYS)
110 # undef win32_get_privlib
111 # define win32_get_privlib g_win32_get_privlib
112 # undef win32_get_sitelib
113 # define win32_get_sitelib g_win32_get_sitelib
114 # undef win32_get_vendorlib
115 # define win32_get_vendorlib g_win32_get_vendorlib
117 # define getlogin g_getlogin
120 static void get_shell(void);
121 static long tokenize(const char *str, char **dest, char ***destv);
122 static int do_spawn2(pTHX_ const char *cmd, int exectype);
123 static BOOL has_shell_metachars(const char *ptr);
124 static long filetime_to_clock(PFILETIME ft);
125 static BOOL filetime_from_time(PFILETIME ft, time_t t);
126 static char * get_emd_part(SV **leading, char *trailing, ...);
127 static void remove_dead_process(long deceased);
128 static long find_pid(int pid);
129 static char * qualified_path(const char *cmd);
130 static char * win32_get_xlib(const char *pl, const char *xlib,
131 const char *libname);
132 static LRESULT win32_process_message(HWND hwnd, UINT msg,
133 WPARAM wParam, LPARAM lParam);
136 static void remove_dead_pseudo_process(long child);
137 static long find_pseudo_pid(int pid);
141 HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
142 char w32_module_name[MAX_PATH+1];
145 static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
147 static HANDLE (WINAPI *pfnCreateToolhelp32Snapshot)(DWORD, DWORD) = NULL;
148 static BOOL (WINAPI *pfnProcess32First)(HANDLE, PROCESSENTRY32*) = NULL;
149 static BOOL (WINAPI *pfnProcess32Next)(HANDLE, PROCESSENTRY32*) = NULL;
150 static LONG (WINAPI *pfnZwQuerySystemInformation)(UINT, PVOID, ULONG, PULONG);
153 /* Silence STDERR grumblings from Borland's math library. */
155 _matherr(struct _exception *a)
162 /* VS2005 (MSC version 14) provides a mechanism to set an invalid
163 * parameter handler. This functionality is not available in the
164 * 64-bit compiler from the Platform SDK, which unfortunately also
165 * believes itself to be MSC version 14.
167 * There is no #define related to _set_invalid_parameter_handler(),
168 * but we can check for one of the constants defined for
169 * _set_abort_behavior(), which was introduced into stdlib.h at
173 #if _MSC_VER >= 1400 && defined(_WRITE_ABORT_MSG)
174 # define SET_INVALID_PARAMETER_HANDLER
177 #ifdef SET_INVALID_PARAMETER_HANDLER
178 void my_invalid_parameter_handler(const wchar_t* expression,
179 const wchar_t* function,
185 wprintf(L"Invalid parameter detected in function %s."
186 L" File: %s Line: %d\n", function, file, line);
187 wprintf(L"Expression: %s\n", expression);
195 return (g_osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
201 return (g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT);
207 return (g_osver.dwMajorVersion > 4);
211 set_w32_module_name(void)
213 /* this function may be called at DLL_PROCESS_ATTACH time */
215 HMODULE module = (HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
216 ? GetModuleHandle(NULL)
217 : w32_perldll_handle);
219 OSVERSIONINFO osver; /* g_osver may not yet be initialized */
220 osver.dwOSVersionInfoSize = sizeof(osver);
221 GetVersionEx(&osver);
223 if (osver.dwMajorVersion > 4) {
224 WCHAR modulename[MAX_PATH];
225 WCHAR fullname[MAX_PATH];
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 /* remove \\?\ prefix */
235 if (memcmp(fullname, L"\\\\?\\", 4*sizeof(WCHAR)) == 0)
236 memmove(fullname, fullname+4, (wcslen(fullname+4)+1)*sizeof(WCHAR));
238 ansi = win32_ansipath(fullname);
239 my_strlcpy(w32_module_name, ansi, sizeof(w32_module_name));
243 GetModuleFileName(module, w32_module_name, sizeof(w32_module_name));
245 /* remove \\?\ prefix */
246 if (memcmp(w32_module_name, "\\\\?\\", 4) == 0)
247 memmove(w32_module_name, w32_module_name+4, strlen(w32_module_name+4)+1);
249 /* try to get full path to binary (which may be mangled when perl is
250 * run from a 16-bit app) */
251 /*PerlIO_printf(Perl_debug_log, "Before %s\n", w32_module_name);*/
252 win32_longpath(w32_module_name);
253 /*PerlIO_printf(Perl_debug_log, "After %s\n", w32_module_name);*/
256 /* normalize to forward slashes */
257 ptr = w32_module_name;
265 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
267 get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
269 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
272 const char *subkey = "Software\\Perl";
276 retval = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &handle);
277 if (retval == ERROR_SUCCESS) {
279 retval = RegQueryValueEx(handle, valuename, 0, &type, NULL, &datalen);
280 if (retval == ERROR_SUCCESS
281 && (type == REG_SZ || type == REG_EXPAND_SZ))
285 *svp = sv_2mortal(newSVpvn("",0));
286 SvGROW(*svp, datalen);
287 retval = RegQueryValueEx(handle, valuename, 0, NULL,
288 (PBYTE)SvPVX(*svp), &datalen);
289 if (retval == ERROR_SUCCESS) {
291 SvCUR_set(*svp,datalen-1);
299 /* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
301 get_regstr(const char *valuename, SV **svp)
303 char *str = get_regstr_from(HKEY_CURRENT_USER, valuename, svp);
305 str = get_regstr_from(HKEY_LOCAL_MACHINE, valuename, svp);
309 /* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
311 get_emd_part(SV **prev_pathp, char *trailing_path, ...)
315 char mod_name[MAX_PATH+1];
321 va_start(ap, trailing_path);
322 strip = va_arg(ap, char *);
324 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
325 baselen = strlen(base);
327 if (!*w32_module_name) {
328 set_w32_module_name();
330 strcpy(mod_name, w32_module_name);
331 ptr = strrchr(mod_name, '/');
332 while (ptr && strip) {
333 /* look for directories to skip back */
336 ptr = strrchr(mod_name, '/');
337 /* avoid stripping component if there is no slash,
338 * or it doesn't match ... */
339 if (!ptr || stricmp(ptr+1, strip) != 0) {
340 /* ... but not if component matches m|5\.$patchlevel.*| */
341 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
342 && strncmp(strip, base, baselen) == 0
343 && strncmp(ptr+1, base, baselen) == 0))
349 strip = va_arg(ap, char *);
357 strcpy(++ptr, trailing_path);
359 /* only add directory if it exists */
360 if (GetFileAttributes(mod_name) != (DWORD) -1) {
361 /* directory exists */
364 *prev_pathp = sv_2mortal(newSVpvn("",0));
365 else if (SvPVX(*prev_pathp))
366 sv_catpvn(*prev_pathp, ";", 1);
367 sv_catpv(*prev_pathp, mod_name);
368 return SvPVX(*prev_pathp);
375 win32_get_privlib(const char *pl)
378 char *stdlib = "lib";
379 char buffer[MAX_PATH+1];
382 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
383 sprintf(buffer, "%s-%s", stdlib, pl);
384 if (!get_regstr(buffer, &sv))
385 (void)get_regstr(stdlib, &sv);
387 /* $stdlib .= ";$EMD/../../lib" */
388 return get_emd_part(&sv, stdlib, ARCHNAME, "bin", NULL);
392 win32_get_xlib(const char *pl, const char *xlib, const char *libname)
396 char pathstr[MAX_PATH+1];
400 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
401 sprintf(regstr, "%s-%s", xlib, pl);
402 (void)get_regstr(regstr, &sv1);
405 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
406 sprintf(pathstr, "%s/%s/lib", libname, pl);
407 (void)get_emd_part(&sv1, pathstr, ARCHNAME, "bin", pl, NULL);
409 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
410 (void)get_regstr(xlib, &sv2);
413 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
414 sprintf(pathstr, "%s/lib", libname);
415 (void)get_emd_part(&sv2, pathstr, ARCHNAME, "bin", pl, NULL);
424 sv_catpvn(sv1, ";", 1);
431 win32_get_sitelib(const char *pl)
433 return win32_get_xlib(pl, "sitelib", "site");
436 #ifndef PERL_VENDORLIB_NAME
437 # define PERL_VENDORLIB_NAME "vendor"
441 win32_get_vendorlib(const char *pl)
443 return win32_get_xlib(pl, "vendorlib", PERL_VENDORLIB_NAME);
447 has_shell_metachars(const char *ptr)
453 * Scan string looking for redirection (< or >) or pipe
454 * characters (|) that are not in a quoted string.
455 * Shell variable interpolation (%VAR%) can also happen inside strings.
487 #if !defined(PERL_IMPLICIT_SYS)
488 /* since the current process environment is being updated in util.c
489 * the library functions will get the correct environment
492 Perl_my_popen(pTHX_ const char *cmd, const char *mode)
495 #define fixcmd(x) { \
496 char *pspace = strchr((x),' '); \
499 while (p < pspace) { \
510 PERL_FLUSHALL_FOR_CHILD;
511 return win32_popen(cmd, mode);
515 Perl_my_pclose(pTHX_ PerlIO *fp)
517 return win32_pclose(fp);
521 DllExport unsigned long
524 return (unsigned long)g_osver.dwPlatformId;
534 return -((int)w32_pseudo_id);
537 /* Windows 9x appears to always reports a pid for threads and processes
538 * that has the high bit set. So we treat the lower 31 bits as the
539 * "real" PID for Perl's purposes. */
540 if (IsWin95() && pid < 0)
545 /* Tokenize a string. Words are null-separated, and the list
546 * ends with a doubled null. Any character (except null and
547 * including backslash) may be escaped by preceding it with a
548 * backslash (the backslash will be stripped).
549 * Returns number of words in result buffer.
552 tokenize(const char *str, char **dest, char ***destv)
554 char *retstart = NULL;
555 char **retvstart = 0;
559 int slen = strlen(str);
561 register char **retv;
562 Newx(ret, slen+2, char);
563 Newx(retv, (slen+3)/2, char*);
571 if (*ret == '\\' && *str)
573 else if (*ret == ' ') {
589 retvstart[items] = NULL;
602 if (!w32_perlshell_tokens) {
603 /* we don't use COMSPEC here for two reasons:
604 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
605 * uncontrolled unportability of the ensuing scripts.
606 * 2. PERL5SHELL could be set to a shell that may not be fit for
607 * interactive use (which is what most programs look in COMSPEC
610 const char* defaultshell = (IsWinNT()
611 ? "cmd.exe /x/d/c" : "command.com /c");
612 const char *usershell = PerlEnv_getenv("PERL5SHELL");
613 w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
614 &w32_perlshell_tokens,
620 Perl_do_aspawn(pTHX_ SV *really, SV **mark, SV **sp)
632 Newx(argv, (sp - mark) + w32_perlshell_items + 2, char*);
634 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
639 while (++mark <= sp) {
640 if (*mark && (str = SvPV_nolen(*mark)))
647 status = win32_spawnvp(flag,
648 (const char*)(really ? SvPV_nolen(really) : argv[0]),
649 (const char* const*)argv);
651 if (status < 0 && (errno == ENOEXEC || errno == ENOENT)) {
652 /* possible shell-builtin, invoke with shell */
654 sh_items = w32_perlshell_items;
656 argv[index+sh_items] = argv[index];
657 while (--sh_items >= 0)
658 argv[sh_items] = w32_perlshell_vec[sh_items];
660 status = win32_spawnvp(flag,
661 (const char*)(really ? SvPV_nolen(really) : argv[0]),
662 (const char* const*)argv);
665 if (flag == P_NOWAIT) {
667 PL_statusvalue = -1; /* >16bits hint for pp_system() */
671 if (ckWARN(WARN_EXEC))
672 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
677 PL_statusvalue = status;
683 /* returns pointer to the next unquoted space or the end of the string */
685 find_next_space(const char *s)
687 bool in_quotes = FALSE;
689 /* ignore doubled backslashes, or backslash+quote */
690 if (*s == '\\' && (s[1] == '\\' || s[1] == '"')) {
693 /* keep track of when we're within quotes */
694 else if (*s == '"') {
696 in_quotes = !in_quotes;
698 /* break it up only at spaces that aren't in quotes */
699 else if (!in_quotes && isSPACE(*s))
708 do_spawn2(pTHX_ const char *cmd, int exectype)
714 BOOL needToTry = TRUE;
717 /* Save an extra exec if possible. See if there are shell
718 * metacharacters in it */
719 if (!has_shell_metachars(cmd)) {
720 Newx(argv, strlen(cmd) / 2 + 2, char*);
721 Newx(cmd2, strlen(cmd) + 1, char);
724 for (s = cmd2; *s;) {
725 while (*s && isSPACE(*s))
729 s = find_next_space(s);
737 status = win32_spawnvp(P_WAIT, argv[0],
738 (const char* const*)argv);
740 case EXECF_SPAWN_NOWAIT:
741 status = win32_spawnvp(P_NOWAIT, argv[0],
742 (const char* const*)argv);
745 status = win32_execvp(argv[0], (const char* const*)argv);
748 if (status != -1 || errno == 0)
758 Newx(argv, w32_perlshell_items + 2, char*);
759 while (++i < w32_perlshell_items)
760 argv[i] = w32_perlshell_vec[i];
761 argv[i++] = (char *)cmd;
765 status = win32_spawnvp(P_WAIT, argv[0],
766 (const char* const*)argv);
768 case EXECF_SPAWN_NOWAIT:
769 status = win32_spawnvp(P_NOWAIT, argv[0],
770 (const char* const*)argv);
773 status = win32_execvp(argv[0], (const char* const*)argv);
779 if (exectype == EXECF_SPAWN_NOWAIT) {
781 PL_statusvalue = -1; /* >16bits hint for pp_system() */
785 if (ckWARN(WARN_EXEC))
786 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't %s \"%s\": %s",
787 (exectype == EXECF_EXEC ? "exec" : "spawn"),
788 cmd, strerror(errno));
793 PL_statusvalue = status;
799 Perl_do_spawn(pTHX_ char *cmd)
801 return do_spawn2(aTHX_ cmd, EXECF_SPAWN);
805 Perl_do_spawn_nowait(pTHX_ char *cmd)
807 return do_spawn2(aTHX_ cmd, EXECF_SPAWN_NOWAIT);
811 Perl_do_exec(pTHX_ const char *cmd)
813 do_spawn2(aTHX_ cmd, EXECF_EXEC);
817 /* The idea here is to read all the directory names into a string table
818 * (separated by nulls) and when one of the other dir functions is called
819 * return the pointer to the current file name.
822 win32_opendir(const char *filename)
828 char scanname[MAX_PATH+3];
830 WIN32_FIND_DATAA aFindData;
831 WIN32_FIND_DATAW wFindData;
833 char buffer[MAX_PATH*2];
836 len = strlen(filename);
840 /* check to see if filename is a directory */
841 if (win32_stat(filename, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
844 /* Get us a DIR structure */
847 /* Create the search pattern */
848 strcpy(scanname, filename);
850 /* bare drive name means look in cwd for drive */
851 if (len == 2 && isALPHA(scanname[0]) && scanname[1] == ':') {
852 scanname[len++] = '.';
853 scanname[len++] = '/';
855 else if (scanname[len-1] != '/' && scanname[len-1] != '\\') {
856 scanname[len++] = '/';
858 scanname[len++] = '*';
859 scanname[len] = '\0';
861 /* do the FindFirstFile call */
863 WCHAR wscanname[sizeof(scanname)];
864 MultiByteToWideChar(CP_ACP, 0, scanname, -1, wscanname, sizeof(wscanname)/sizeof(WCHAR));
865 dirp->handle = FindFirstFileW(PerlDir_mapW(wscanname), &wFindData);
869 dirp->handle = FindFirstFileA(PerlDir_mapA(scanname), &aFindData);
871 if (dirp->handle == INVALID_HANDLE_VALUE) {
872 DWORD err = GetLastError();
873 /* FindFirstFile() fails on empty drives! */
875 case ERROR_FILE_NOT_FOUND:
877 case ERROR_NO_MORE_FILES:
878 case ERROR_PATH_NOT_FOUND:
881 case ERROR_NOT_ENOUGH_MEMORY:
893 BOOL use_default = FALSE;
894 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
895 wFindData.cFileName, -1,
896 buffer, sizeof(buffer), NULL, &use_default);
897 if (use_default && *wFindData.cAlternateFileName) {
898 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
899 wFindData.cAlternateFileName, -1,
900 buffer, sizeof(buffer), NULL, NULL);
905 ptr = aFindData.cFileName;
907 /* now allocate the first part of the string table for
908 * the filenames that we find.
915 Newx(dirp->start, dirp->size, char);
916 strcpy(dirp->start, ptr);
918 dirp->end = dirp->curr = dirp->start;
924 /* Readdir just returns the current string pointer and bumps the
925 * string pointer to the nDllExport entry.
927 DllExport struct direct *
928 win32_readdir(DIR *dirp)
933 /* first set up the structure to return */
934 len = strlen(dirp->curr);
935 strcpy(dirp->dirstr.d_name, dirp->curr);
936 dirp->dirstr.d_namlen = len;
939 dirp->dirstr.d_ino = dirp->curr - dirp->start;
941 /* Now set up for the next call to readdir */
942 dirp->curr += len + 1;
943 if (dirp->curr >= dirp->end) {
946 WIN32_FIND_DATAA aFindData;
947 char buffer[MAX_PATH*2];
950 /* finding the next file that matches the wildcard
951 * (which should be all of them in this directory!).
954 WIN32_FIND_DATAW wFindData;
955 res = FindNextFileW(dirp->handle, &wFindData);
957 BOOL use_default = FALSE;
958 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
959 wFindData.cFileName, -1,
960 buffer, sizeof(buffer), NULL, &use_default);
961 if (use_default && *wFindData.cAlternateFileName) {
962 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
963 wFindData.cAlternateFileName, -1,
964 buffer, sizeof(buffer), NULL, NULL);
970 res = FindNextFileA(dirp->handle, &aFindData);
971 ptr = aFindData.cFileName;
974 long endpos = dirp->end - dirp->start;
975 long newsize = endpos + strlen(ptr) + 1;
976 /* bump the string table size by enough for the
977 * new name and its null terminator */
978 while (newsize > dirp->size) {
979 long curpos = dirp->curr - dirp->start;
981 Renew(dirp->start, dirp->size, char);
982 dirp->curr = dirp->start + curpos;
984 strcpy(dirp->start + endpos, ptr);
985 dirp->end = dirp->start + newsize;
991 return &(dirp->dirstr);
997 /* Telldir returns the current string pointer position */
999 win32_telldir(DIR *dirp)
1001 return (dirp->curr - dirp->start);
1005 /* Seekdir moves the string pointer to a previously saved position
1006 * (returned by telldir).
1009 win32_seekdir(DIR *dirp, long loc)
1011 dirp->curr = dirp->start + loc;
1014 /* Rewinddir resets the string pointer to the start */
1016 win32_rewinddir(DIR *dirp)
1018 dirp->curr = dirp->start;
1021 /* free the memory allocated by opendir */
1023 win32_closedir(DIR *dirp)
1026 if (dirp->handle != INVALID_HANDLE_VALUE)
1027 FindClose(dirp->handle);
1028 Safefree(dirp->start);
1041 * Just pretend that everyone is a superuser. NT will let us know if
1042 * we don\'t really have permission to do something.
1045 #define ROOT_UID ((uid_t)0)
1046 #define ROOT_GID ((gid_t)0)
1075 return (auid == ROOT_UID ? 0 : -1);
1081 return (agid == ROOT_GID ? 0 : -1);
1088 char *buf = w32_getlogin_buffer;
1089 DWORD size = sizeof(w32_getlogin_buffer);
1090 if (GetUserName(buf,&size))
1096 chown(const char *path, uid_t owner, gid_t group)
1103 * XXX this needs strengthening (for PerlIO)
1106 int mkstemp(const char *path)
1109 char buf[MAX_PATH+1];
1113 if (i++ > 10) { /* give up */
1117 if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
1121 fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
1131 long child = w32_num_children;
1132 while (--child >= 0) {
1133 if ((int)w32_child_pids[child] == pid)
1140 remove_dead_process(long child)
1144 CloseHandle(w32_child_handles[child]);
1145 Move(&w32_child_handles[child+1], &w32_child_handles[child],
1146 (w32_num_children-child-1), HANDLE);
1147 Move(&w32_child_pids[child+1], &w32_child_pids[child],
1148 (w32_num_children-child-1), DWORD);
1155 find_pseudo_pid(int pid)
1158 long child = w32_num_pseudo_children;
1159 while (--child >= 0) {
1160 if ((int)w32_pseudo_child_pids[child] == pid)
1167 remove_dead_pseudo_process(long child)
1171 CloseHandle(w32_pseudo_child_handles[child]);
1172 Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
1173 (w32_num_pseudo_children-child-1), HANDLE);
1174 Move(&w32_pseudo_child_pids[child+1], &w32_pseudo_child_pids[child],
1175 (w32_num_pseudo_children-child-1), DWORD);
1176 Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
1177 (w32_num_pseudo_children-child-1), HWND);
1178 w32_num_pseudo_children--;
1184 terminate_process(DWORD pid, HANDLE process_handle, int sig)
1188 /* "Does process exist?" use of kill */
1191 if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid))
1196 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid))
1199 default: /* For now be backwards compatible with perl 5.6 */
1201 /* Note that we will only be able to kill processes owned by the
1202 * current process owner, even when we are running as an administrator.
1203 * To kill processes of other owners we would need to set the
1204 * 'SeDebugPrivilege' privilege before obtaining the process handle.
1206 if (TerminateProcess(process_handle, sig))
1213 /* Traverse process tree using ToolHelp functions */
1215 kill_process_tree_toolhelp(DWORD pid, int sig)
1217 HANDLE process_handle;
1218 HANDLE snapshot_handle;
1221 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1222 if (process_handle == NULL)
1225 killed += terminate_process(pid, process_handle, sig);
1227 snapshot_handle = pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1228 if (snapshot_handle != INVALID_HANDLE_VALUE) {
1229 PROCESSENTRY32 entry;
1231 entry.dwSize = sizeof(entry);
1232 if (pfnProcess32First(snapshot_handle, &entry)) {
1234 if (entry.th32ParentProcessID == pid)
1235 killed += kill_process_tree_toolhelp(entry.th32ProcessID, sig);
1236 entry.dwSize = sizeof(entry);
1238 while (pfnProcess32Next(snapshot_handle, &entry));
1240 CloseHandle(snapshot_handle);
1242 CloseHandle(process_handle);
1246 /* Traverse process tree using undocumented system information structures.
1247 * This is only necessary on Windows NT, which lacks the ToolHelp functions.
1250 kill_process_tree_sysinfo(SYSTEM_PROCESSES *process_info, DWORD pid, int sig)
1252 HANDLE process_handle;
1253 SYSTEM_PROCESSES *p = process_info;
1256 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1257 if (process_handle == NULL)
1260 killed += terminate_process(pid, process_handle, sig);
1263 if (p->InheritedFromProcessId == (DWORD)pid)
1264 killed += kill_process_tree_sysinfo(process_info, p->ProcessId, sig);
1266 if (p->NextEntryDelta == 0)
1269 p = (SYSTEM_PROCESSES*)((char*)p + p->NextEntryDelta);
1272 CloseHandle(process_handle);
1277 killpg(int pid, int sig)
1279 /* Use "documented" method whenever available */
1280 if (pfnCreateToolhelp32Snapshot && pfnProcess32First && pfnProcess32Next) {
1281 return kill_process_tree_toolhelp((DWORD)pid, sig);
1284 /* Fall back to undocumented Windows internals on Windows NT */
1285 if (pfnZwQuerySystemInformation) {
1290 pfnZwQuerySystemInformation(SystemProcessesAndThreadsInformation, NULL, 0, &size);
1291 Newx(buffer, size, char);
1293 if (pfnZwQuerySystemInformation(SystemProcessesAndThreadsInformation, buffer, size, NULL) >= 0) {
1294 int killed = kill_process_tree_sysinfo((SYSTEM_PROCESSES*)buffer, (DWORD)pid, sig);
1303 my_kill(int pid, int sig)
1306 HANDLE process_handle;
1309 return killpg(pid, -sig);
1311 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1312 /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
1313 if (process_handle != NULL) {
1314 retval = terminate_process(pid, process_handle, sig);
1315 CloseHandle(process_handle);
1321 win32_kill(int pid, int sig)
1327 /* it is a pseudo-forked child */
1328 child = find_pseudo_pid(-pid);
1330 HWND hwnd = w32_pseudo_child_message_hwnds[child];
1331 HANDLE hProcess = w32_pseudo_child_handles[child];
1334 /* "Does process exist?" use of kill */
1338 /* kill -9 style un-graceful exit */
1339 if (TerminateThread(hProcess, sig)) {
1340 remove_dead_pseudo_process(child);
1347 /* pseudo-process has not yet properly initialized if hwnd isn't set */
1348 while (hwnd == INVALID_HANDLE_VALUE && count < 5) {
1349 /* Yield and wait for the other thread to send us its message_hwnd */
1351 win32_async_check(aTHX);
1352 hwnd = w32_pseudo_child_message_hwnds[child];
1355 if (hwnd != INVALID_HANDLE_VALUE) {
1356 /* We fake signals to pseudo-processes using Win32
1357 * message queue. In Win9X the pids are negative already. */
1358 if ((hwnd != NULL && PostMessage(hwnd, WM_USER_KILL, sig, 0)) ||
1359 PostThreadMessage(IsWin95() ? pid : -pid, WM_USER_KILL, sig, 0))
1361 /* It might be us ... */
1370 else if (IsWin95()) {
1378 child = find_pid(pid);
1380 if (my_kill(pid, sig)) {
1382 if (GetExitCodeProcess(w32_child_handles[child], &exitcode) &&
1383 exitcode != STILL_ACTIVE)
1385 remove_dead_process(child);
1392 if (my_kill((IsWin95() ? -pid : pid), sig))
1401 win32_stat(const char *path, Stat_t *sbuf)
1404 char buffer[MAX_PATH+1];
1405 int l = strlen(path);
1408 BOOL expect_dir = FALSE;
1410 GV *gv_sloppy = gv_fetchpvs("\027IN32_SLOPPY_STAT",
1411 GV_NOTQUAL, SVt_PV);
1412 BOOL sloppy = gv_sloppy && SvTRUE(GvSV(gv_sloppy));
1415 switch(path[l - 1]) {
1416 /* FindFirstFile() and stat() are buggy with a trailing
1417 * slashes, except for the root directory of a drive */
1420 if (l > sizeof(buffer)) {
1421 errno = ENAMETOOLONG;
1425 strncpy(buffer, path, l);
1426 /* remove additional trailing slashes */
1427 while (l > 1 && (buffer[l-1] == '/' || buffer[l-1] == '\\'))
1429 /* add back slash if we otherwise end up with just a drive letter */
1430 if (l == 2 && isALPHA(buffer[0]) && buffer[1] == ':')
1437 /* FindFirstFile() is buggy with "x:", so add a dot :-( */
1439 if (l == 2 && isALPHA(path[0])) {
1440 buffer[0] = path[0];
1451 path = PerlDir_mapA(path);
1455 /* We must open & close the file once; otherwise file attribute changes */
1456 /* might not yet have propagated to "other" hard links of the same file. */
1457 /* This also gives us an opportunity to determine the number of links. */
1458 HANDLE handle = CreateFileA(path, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
1459 if (handle != INVALID_HANDLE_VALUE) {
1460 BY_HANDLE_FILE_INFORMATION bhi;
1461 if (GetFileInformationByHandle(handle, &bhi))
1462 nlink = bhi.nNumberOfLinks;
1463 CloseHandle(handle);
1467 /* path will be mapped correctly above */
1468 #if defined(WIN64) || defined(USE_LARGE_FILES)
1469 res = _stati64(path, sbuf);
1471 res = stat(path, sbuf);
1473 sbuf->st_nlink = nlink;
1476 /* CRT is buggy on sharenames, so make sure it really isn't.
1477 * XXX using GetFileAttributesEx() will enable us to set
1478 * sbuf->st_*time (but note that's not available on the
1479 * Windows of 1995) */
1480 DWORD r = GetFileAttributesA(path);
1481 if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
1482 /* sbuf may still contain old garbage since stat() failed */
1483 Zero(sbuf, 1, Stat_t);
1484 sbuf->st_mode = S_IFDIR | S_IREAD;
1486 if (!(r & FILE_ATTRIBUTE_READONLY))
1487 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1492 if (l == 3 && isALPHA(path[0]) && path[1] == ':'
1493 && (path[2] == '\\' || path[2] == '/'))
1495 /* The drive can be inaccessible, some _stat()s are buggy */
1496 if (!GetVolumeInformationA(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
1501 if (expect_dir && !S_ISDIR(sbuf->st_mode)) {
1506 if (S_ISDIR(sbuf->st_mode))
1507 sbuf->st_mode |= S_IWRITE | S_IEXEC;
1508 else if (S_ISREG(sbuf->st_mode)) {
1510 if (l >= 4 && path[l-4] == '.') {
1511 const char *e = path + l - 3;
1512 if (strnicmp(e,"exe",3)
1513 && strnicmp(e,"bat",3)
1514 && strnicmp(e,"com",3)
1515 && (IsWin95() || strnicmp(e,"cmd",3)))
1516 sbuf->st_mode &= ~S_IEXEC;
1518 sbuf->st_mode |= S_IEXEC;
1521 sbuf->st_mode &= ~S_IEXEC;
1522 /* Propagate permissions to _group_ and _others_ */
1523 perms = sbuf->st_mode & (S_IREAD|S_IWRITE|S_IEXEC);
1524 sbuf->st_mode |= (perms>>3) | (perms>>6);
1531 #define isSLASH(c) ((c) == '/' || (c) == '\\')
1532 #define SKIP_SLASHES(s) \
1534 while (*(s) && isSLASH(*(s))) \
1537 #define COPY_NONSLASHES(d,s) \
1539 while (*(s) && !isSLASH(*(s))) \
1543 /* Find the longname of a given path. path is destructively modified.
1544 * It should have space for at least MAX_PATH characters. */
1546 win32_longpath(char *path)
1548 WIN32_FIND_DATA fdata;
1550 char tmpbuf[MAX_PATH+1];
1551 char *tmpstart = tmpbuf;
1558 if (isALPHA(path[0]) && path[1] == ':') {
1560 *tmpstart++ = path[0];
1564 else if (isSLASH(path[0]) && isSLASH(path[1])) {
1566 *tmpstart++ = path[0];
1567 *tmpstart++ = path[1];
1568 SKIP_SLASHES(start);
1569 COPY_NONSLASHES(tmpstart,start); /* copy machine name */
1571 *tmpstart++ = *start++;
1572 SKIP_SLASHES(start);
1573 COPY_NONSLASHES(tmpstart,start); /* copy share name */
1578 /* copy initial slash, if any */
1579 if (isSLASH(*start)) {
1580 *tmpstart++ = *start++;
1582 SKIP_SLASHES(start);
1585 /* FindFirstFile() expands "." and "..", so we need to pass
1586 * those through unmolested */
1588 && (!start[1] || isSLASH(start[1])
1589 || (start[1] == '.' && (!start[2] || isSLASH(start[2])))))
1591 COPY_NONSLASHES(tmpstart,start); /* copy "." or ".." */
1596 /* if this is the end, bust outta here */
1600 /* now we're at a non-slash; walk up to next slash */
1601 while (*start && !isSLASH(*start))
1604 /* stop and find full name of component */
1607 fhand = FindFirstFile(path,&fdata);
1609 if (fhand != INVALID_HANDLE_VALUE) {
1610 STRLEN len = strlen(fdata.cFileName);
1611 if ((STRLEN)(tmpbuf + sizeof(tmpbuf) - tmpstart) > len) {
1612 strcpy(tmpstart, fdata.cFileName);
1623 /* failed a step, just return without side effects */
1624 /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
1629 strcpy(path,tmpbuf);
1638 /* Can't use PerlIO to write as it allocates memory */
1639 PerlLIO_write(PerlIO_fileno(Perl_error_log),
1640 PL_no_mem, strlen(PL_no_mem));
1646 /* The win32_ansipath() function takes a Unicode filename and converts it
1647 * into the current Windows codepage. If some characters cannot be mapped,
1648 * then it will convert the short name instead.
1650 * The buffer to the ansi pathname must be freed with win32_free() when it
1651 * it no longer needed.
1653 * The argument to win32_ansipath() must exist before this function is
1654 * called; otherwise there is no way to determine the short path name.
1656 * Ideas for future refinement:
1657 * - Only convert those segments of the path that are not in the current
1658 * codepage, but leave the other segments in their long form.
1659 * - If the resulting name is longer than MAX_PATH, start converting
1660 * additional path segments into short names until the full name
1661 * is shorter than MAX_PATH. Shorten the filename part last!
1664 win32_ansipath(const WCHAR *widename)
1667 BOOL use_default = FALSE;
1668 size_t widelen = wcslen(widename)+1;
1669 int len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1670 NULL, 0, NULL, NULL);
1671 name = win32_malloc(len);
1675 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, widename, widelen,
1676 name, len, NULL, &use_default);
1678 DWORD shortlen = GetShortPathNameW(widename, NULL, 0);
1680 WCHAR *shortname = win32_malloc(shortlen*sizeof(WCHAR));
1683 shortlen = GetShortPathNameW(widename, shortname, shortlen)+1;
1685 len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1686 NULL, 0, NULL, NULL);
1687 name = win32_realloc(name, len);
1690 WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortname, shortlen,
1691 name, len, NULL, NULL);
1692 win32_free(shortname);
1699 win32_getenv(const char *name)
1705 needlen = GetEnvironmentVariableA(name,NULL,0);
1707 curitem = sv_2mortal(newSVpvn("", 0));
1709 SvGROW(curitem, needlen+1);
1710 needlen = GetEnvironmentVariableA(name,SvPVX(curitem),
1712 } while (needlen >= SvLEN(curitem));
1713 SvCUR_set(curitem, needlen);
1716 /* allow any environment variables that begin with 'PERL'
1717 to be stored in the registry */
1718 if (strncmp(name, "PERL", 4) == 0)
1719 (void)get_regstr(name, &curitem);
1721 if (curitem && SvCUR(curitem))
1722 return SvPVX(curitem);
1728 win32_putenv(const char *name)
1736 Newx(curitem,strlen(name)+1,char);
1737 strcpy(curitem, name);
1738 val = strchr(curitem, '=');
1740 /* The sane way to deal with the environment.
1741 * Has these advantages over putenv() & co.:
1742 * * enables us to store a truly empty value in the
1743 * environment (like in UNIX).
1744 * * we don't have to deal with RTL globals, bugs and leaks.
1746 * Why you may want to enable USE_WIN32_RTL_ENV:
1747 * * environ[] and RTL functions will not reflect changes,
1748 * which might be an issue if extensions want to access
1749 * the env. via RTL. This cuts both ways, since RTL will
1750 * not see changes made by extensions that call the Win32
1751 * functions directly, either.
1755 if (SetEnvironmentVariableA(curitem, *val ? val : NULL))
1764 filetime_to_clock(PFILETIME ft)
1766 __int64 qw = ft->dwHighDateTime;
1768 qw |= ft->dwLowDateTime;
1769 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
1774 win32_times(struct tms *timebuf)
1779 clock_t process_time_so_far = clock();
1780 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
1782 timebuf->tms_utime = filetime_to_clock(&user);
1783 timebuf->tms_stime = filetime_to_clock(&kernel);
1784 timebuf->tms_cutime = 0;
1785 timebuf->tms_cstime = 0;
1787 /* That failed - e.g. Win95 fallback to clock() */
1788 timebuf->tms_utime = process_time_so_far;
1789 timebuf->tms_stime = 0;
1790 timebuf->tms_cutime = 0;
1791 timebuf->tms_cstime = 0;
1793 return process_time_so_far;
1796 /* fix utime() so it works on directories in NT */
1798 filetime_from_time(PFILETIME pFileTime, time_t Time)
1800 struct tm *pTM = localtime(&Time);
1801 SYSTEMTIME SystemTime;
1807 SystemTime.wYear = pTM->tm_year + 1900;
1808 SystemTime.wMonth = pTM->tm_mon + 1;
1809 SystemTime.wDay = pTM->tm_mday;
1810 SystemTime.wHour = pTM->tm_hour;
1811 SystemTime.wMinute = pTM->tm_min;
1812 SystemTime.wSecond = pTM->tm_sec;
1813 SystemTime.wMilliseconds = 0;
1815 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
1816 LocalFileTimeToFileTime(&LocalTime, pFileTime);
1820 win32_unlink(const char *filename)
1826 filename = PerlDir_mapA(filename);
1827 attrs = GetFileAttributesA(filename);
1828 if (attrs == 0xFFFFFFFF) {
1832 if (attrs & FILE_ATTRIBUTE_READONLY) {
1833 (void)SetFileAttributesA(filename, attrs & ~FILE_ATTRIBUTE_READONLY);
1834 ret = unlink(filename);
1836 (void)SetFileAttributesA(filename, attrs);
1839 ret = unlink(filename);
1844 win32_utime(const char *filename, struct utimbuf *times)
1851 struct utimbuf TimeBuffer;
1854 filename = PerlDir_mapA(filename);
1855 rc = utime(filename, times);
1857 /* EACCES: path specifies directory or readonly file */
1858 if (rc == 0 || errno != EACCES /* || !IsWinNT() */)
1861 if (times == NULL) {
1862 times = &TimeBuffer;
1863 time(×->actime);
1864 times->modtime = times->actime;
1867 /* This will (and should) still fail on readonly files */
1868 handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
1869 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
1870 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1871 if (handle == INVALID_HANDLE_VALUE)
1874 if (GetFileTime(handle, &ftCreate, &ftAccess, &ftWrite) &&
1875 filetime_from_time(&ftAccess, times->actime) &&
1876 filetime_from_time(&ftWrite, times->modtime) &&
1877 SetFileTime(handle, &ftCreate, &ftAccess, &ftWrite))
1882 CloseHandle(handle);
1887 unsigned __int64 ft_i64;
1892 #define Const64(x) x##LL
1894 #define Const64(x) x##i64
1896 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
1897 #define EPOCH_BIAS Const64(116444736000000000)
1899 /* NOTE: This does not compute the timezone info (doing so can be expensive,
1900 * and appears to be unsupported even by glibc) */
1902 win32_gettimeofday(struct timeval *tp, void *not_used)
1906 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
1907 GetSystemTimeAsFileTime(&ft.ft_val);
1909 /* seconds since epoch */
1910 tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000));
1912 /* microseconds remaining */
1913 tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000));
1919 win32_uname(struct utsname *name)
1921 struct hostent *hep;
1922 STRLEN nodemax = sizeof(name->nodename)-1;
1925 switch (g_osver.dwPlatformId) {
1926 case VER_PLATFORM_WIN32_WINDOWS:
1927 strcpy(name->sysname, "Windows");
1929 case VER_PLATFORM_WIN32_NT:
1930 strcpy(name->sysname, "Windows NT");
1932 case VER_PLATFORM_WIN32s:
1933 strcpy(name->sysname, "Win32s");
1936 strcpy(name->sysname, "Win32 Unknown");
1941 sprintf(name->release, "%d.%d",
1942 g_osver.dwMajorVersion, g_osver.dwMinorVersion);
1945 sprintf(name->version, "Build %d",
1946 g_osver.dwPlatformId == VER_PLATFORM_WIN32_NT
1947 ? g_osver.dwBuildNumber : (g_osver.dwBuildNumber & 0xffff));
1948 if (g_osver.szCSDVersion[0]) {
1949 char *buf = name->version + strlen(name->version);
1950 sprintf(buf, " (%s)", g_osver.szCSDVersion);
1954 hep = win32_gethostbyname("localhost");
1956 STRLEN len = strlen(hep->h_name);
1957 if (len <= nodemax) {
1958 strcpy(name->nodename, hep->h_name);
1961 strncpy(name->nodename, hep->h_name, nodemax);
1962 name->nodename[nodemax] = '\0';
1967 if (!GetComputerName(name->nodename, &sz))
1968 *name->nodename = '\0';
1971 /* machine (architecture) */
1976 GetSystemInfo(&info);
1978 #if (defined(__BORLANDC__)&&(__BORLANDC__<=0x520)) \
1979 || (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION))
1980 procarch = info.u.s.wProcessorArchitecture;
1982 procarch = info.wProcessorArchitecture;
1985 case PROCESSOR_ARCHITECTURE_INTEL:
1986 arch = "x86"; break;
1987 case PROCESSOR_ARCHITECTURE_MIPS:
1988 arch = "mips"; break;
1989 case PROCESSOR_ARCHITECTURE_ALPHA:
1990 arch = "alpha"; break;
1991 case PROCESSOR_ARCHITECTURE_PPC:
1992 arch = "ppc"; break;
1993 #ifdef PROCESSOR_ARCHITECTURE_SHX
1994 case PROCESSOR_ARCHITECTURE_SHX:
1995 arch = "shx"; break;
1997 #ifdef PROCESSOR_ARCHITECTURE_ARM
1998 case PROCESSOR_ARCHITECTURE_ARM:
1999 arch = "arm"; break;
2001 #ifdef PROCESSOR_ARCHITECTURE_IA64
2002 case PROCESSOR_ARCHITECTURE_IA64:
2003 arch = "ia64"; break;
2005 #ifdef PROCESSOR_ARCHITECTURE_ALPHA64
2006 case PROCESSOR_ARCHITECTURE_ALPHA64:
2007 arch = "alpha64"; break;
2009 #ifdef PROCESSOR_ARCHITECTURE_MSIL
2010 case PROCESSOR_ARCHITECTURE_MSIL:
2011 arch = "msil"; break;
2013 #ifdef PROCESSOR_ARCHITECTURE_AMD64
2014 case PROCESSOR_ARCHITECTURE_AMD64:
2015 arch = "amd64"; break;
2017 #ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
2018 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
2019 arch = "ia32-64"; break;
2021 #ifdef PROCESSOR_ARCHITECTURE_UNKNOWN
2022 case PROCESSOR_ARCHITECTURE_UNKNOWN:
2023 arch = "unknown"; break;
2026 sprintf(name->machine, "unknown(0x%x)", procarch);
2027 arch = name->machine;
2030 if (name->machine != arch)
2031 strcpy(name->machine, arch);
2036 /* Timing related stuff */
2039 do_raise(pTHX_ int sig)
2041 if (sig < SIG_SIZE) {
2042 Sighandler_t handler = w32_sighandler[sig];
2043 if (handler == SIG_IGN) {
2046 else if (handler != SIG_DFL) {
2051 /* Choose correct default behaviour */
2067 /* Tell caller to exit thread/process as approriate */
2072 sig_terminate(pTHX_ int sig)
2074 Perl_warn(aTHX_ "Terminating on signal SIG%s(%d)\n",PL_sig_name[sig], sig);
2075 /* exit() seems to be safe, my_exit() or die() is a problem in ^C
2082 win32_async_check(pTHX)
2085 HWND hwnd = w32_message_hwnd;
2087 /* Reset w32_poll_count before doing anything else, incase we dispatch
2088 * messages that end up calling back into perl */
2091 if (hwnd != INVALID_HANDLE_VALUE) {
2092 /* Passing PeekMessage -1 as HWND (2nd arg) only gets PostThreadMessage() messages
2093 * and ignores window messages - should co-exist better with windows apps e.g. Tk
2098 while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE|PM_NOYIELD) ||
2099 PeekMessage(&msg, hwnd, WM_USER_MIN, WM_USER_MAX, PM_REMOVE|PM_NOYIELD))
2101 /* re-post a WM_QUIT message (we'll mark it as read later) */
2102 if(msg.message == WM_QUIT) {
2103 PostQuitMessage((int)msg.wParam);
2107 if(!CallMsgFilter(&msg, MSGF_USER))
2109 TranslateMessage(&msg);
2110 DispatchMessage(&msg);
2115 /* Call PeekMessage() to mark all pending messages in the queue as "old".
2116 * This is necessary when we are being called by win32_msgwait() to
2117 * make sure MsgWaitForMultipleObjects() stops reporting the same waiting
2118 * message over and over. An example how this can happen is when
2119 * Perl is calling win32_waitpid() inside a GUI application and the GUI
2120 * is generating messages before the process terminated.
2122 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE|PM_NOYIELD))
2125 /* Above or other stuff may have set a signal flag */
2132 /* This function will not return until the timeout has elapsed, or until
2133 * one of the handles is ready. */
2135 win32_msgwait(pTHX_ DWORD count, LPHANDLE handles, DWORD timeout, LPDWORD resultp)
2137 /* We may need several goes at this - so compute when we stop */
2139 if (timeout != INFINITE) {
2140 ticks = GetTickCount();
2144 DWORD result = MsgWaitForMultipleObjects(count,handles,FALSE,timeout-ticks, QS_POSTMESSAGE|QS_TIMER|QS_SENDMESSAGE);
2147 if (result == WAIT_TIMEOUT) {
2148 /* Ran out of time - explicit return of zero to avoid -ve if we
2149 have scheduling issues
2153 if (timeout != INFINITE) {
2154 ticks = GetTickCount();
2156 if (result == WAIT_OBJECT_0 + count) {
2157 /* Message has arrived - check it */
2158 (void)win32_async_check(aTHX);
2161 /* Not timeout or message - one of handles is ready */
2165 /* compute time left to wait */
2166 ticks = timeout - ticks;
2167 /* If we are past the end say zero */
2168 return (ticks > 0) ? ticks : 0;
2172 win32_internal_wait(int *status, DWORD timeout)
2174 /* XXX this wait emulation only knows about processes
2175 * spawned via win32_spawnvp(P_NOWAIT, ...).
2179 DWORD exitcode, waitcode;
2182 if (w32_num_pseudo_children) {
2183 win32_msgwait(aTHX_ w32_num_pseudo_children, w32_pseudo_child_handles,
2184 timeout, &waitcode);
2185 /* Time out here if there are no other children to wait for. */
2186 if (waitcode == WAIT_TIMEOUT) {
2187 if (!w32_num_children) {
2191 else if (waitcode != WAIT_FAILED) {
2192 if (waitcode >= WAIT_ABANDONED_0
2193 && waitcode < WAIT_ABANDONED_0 + w32_num_pseudo_children)
2194 i = waitcode - WAIT_ABANDONED_0;
2196 i = waitcode - WAIT_OBJECT_0;
2197 if (GetExitCodeThread(w32_pseudo_child_handles[i], &exitcode)) {
2198 *status = (int)((exitcode & 0xff) << 8);
2199 retval = (int)w32_pseudo_child_pids[i];
2200 remove_dead_pseudo_process(i);
2207 if (!w32_num_children) {
2212 /* if a child exists, wait for it to die */
2213 win32_msgwait(aTHX_ w32_num_children, w32_child_handles, timeout, &waitcode);
2214 if (waitcode == WAIT_TIMEOUT) {
2217 if (waitcode != WAIT_FAILED) {
2218 if (waitcode >= WAIT_ABANDONED_0
2219 && waitcode < WAIT_ABANDONED_0 + w32_num_children)
2220 i = waitcode - WAIT_ABANDONED_0;
2222 i = waitcode - WAIT_OBJECT_0;
2223 if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
2224 *status = (int)((exitcode & 0xff) << 8);
2225 retval = (int)w32_child_pids[i];
2226 remove_dead_process(i);
2231 errno = GetLastError();
2236 win32_waitpid(int pid, int *status, int flags)
2239 DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
2242 if (pid == -1) /* XXX threadid == 1 ? */
2243 return win32_internal_wait(status, timeout);
2246 child = find_pseudo_pid(-pid);
2248 HANDLE hThread = w32_pseudo_child_handles[child];
2250 win32_msgwait(aTHX_ 1, &hThread, timeout, &waitcode);
2251 if (waitcode == WAIT_TIMEOUT) {
2254 else if (waitcode == WAIT_OBJECT_0) {
2255 if (GetExitCodeThread(hThread, &waitcode)) {
2256 *status = (int)((waitcode & 0xff) << 8);
2257 retval = (int)w32_pseudo_child_pids[child];
2258 remove_dead_pseudo_process(child);
2265 else if (IsWin95()) {
2274 child = find_pid(pid);
2276 hProcess = w32_child_handles[child];
2277 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2278 if (waitcode == WAIT_TIMEOUT) {
2281 else if (waitcode == WAIT_OBJECT_0) {
2282 if (GetExitCodeProcess(hProcess, &waitcode)) {
2283 *status = (int)((waitcode & 0xff) << 8);
2284 retval = (int)w32_child_pids[child];
2285 remove_dead_process(child);
2294 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE,
2295 (IsWin95() ? -pid : pid));
2297 win32_msgwait(aTHX_ 1, &hProcess, timeout, &waitcode);
2298 if (waitcode == WAIT_TIMEOUT) {
2299 CloseHandle(hProcess);
2302 else if (waitcode == WAIT_OBJECT_0) {
2303 if (GetExitCodeProcess(hProcess, &waitcode)) {
2304 *status = (int)((waitcode & 0xff) << 8);
2305 CloseHandle(hProcess);
2309 CloseHandle(hProcess);
2315 return retval >= 0 ? pid : retval;
2319 win32_wait(int *status)
2321 return win32_internal_wait(status, INFINITE);
2324 DllExport unsigned int
2325 win32_sleep(unsigned int t)
2328 /* Win32 times are in ms so *1000 in and /1000 out */
2329 return win32_msgwait(aTHX_ 0, NULL, t*1000, NULL)/1000;
2332 DllExport unsigned int
2333 win32_alarm(unsigned int sec)
2336 * the 'obvious' implentation is SetTimer() with a callback
2337 * which does whatever receiving SIGALRM would do
2338 * we cannot use SIGALRM even via raise() as it is not
2339 * one of the supported codes in <signal.h>
2343 if (w32_message_hwnd == INVALID_HANDLE_VALUE)
2344 w32_message_hwnd = win32_create_message_window();
2347 if (w32_message_hwnd == NULL)
2348 w32_timerid = SetTimer(NULL, w32_timerid, sec*1000, NULL);
2351 SetTimer(w32_message_hwnd, w32_timerid, sec*1000, NULL);
2356 KillTimer(w32_message_hwnd, w32_timerid);
2363 #ifdef HAVE_DES_FCRYPT
2364 extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
2368 win32_crypt(const char *txt, const char *salt)
2371 #ifdef HAVE_DES_FCRYPT
2372 return des_fcrypt(txt, salt, w32_crypt_buffer);
2374 Perl_croak(aTHX_ "The crypt() function is unimplemented due to excessive paranoia.");
2379 #ifdef USE_FIXED_OSFHANDLE
2381 #define FOPEN 0x01 /* file handle open */
2382 #define FNOINHERIT 0x10 /* file handle opened O_NOINHERIT */
2383 #define FAPPEND 0x20 /* file handle opened O_APPEND */
2384 #define FDEV 0x40 /* file handle refers to device */
2385 #define FTEXT 0x80 /* file handle is in text mode */
2388 *int my_open_osfhandle(intptr_t osfhandle, int flags) - open C Runtime file handle
2391 * This function allocates a free C Runtime file handle and associates
2392 * it with the Win32 HANDLE specified by the first parameter. This is a
2393 * temperary fix for WIN95's brain damage GetFileType() error on socket
2394 * we just bypass that call for socket
2396 * This works with MSVC++ 4.0+ or GCC/Mingw32
2399 * intptr_t osfhandle - Win32 HANDLE to associate with C Runtime file handle.
2400 * int flags - flags to associate with C Runtime file handle.
2403 * returns index of entry in fh, if successful
2404 * return -1, if no free entry is found
2408 *******************************************************************************/
2411 * we fake up some parts of the CRT that aren't exported by MSVCRT.dll
2412 * this lets sockets work on Win9X with GCC and should fix the problems
2417 /* create an ioinfo entry, kill its handle, and steal the entry */
2422 HANDLE hF = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
2423 int fh = _open_osfhandle((intptr_t)hF, 0);
2427 EnterCriticalSection(&(_pioinfo(fh)->lock));
2432 my_open_osfhandle(intptr_t osfhandle, int flags)
2435 char fileflags; /* _osfile flags */
2437 /* copy relevant flags from second parameter */
2440 if (flags & O_APPEND)
2441 fileflags |= FAPPEND;
2446 if (flags & O_NOINHERIT)
2447 fileflags |= FNOINHERIT;
2449 /* attempt to allocate a C Runtime file handle */
2450 if ((fh = _alloc_osfhnd()) == -1) {
2451 errno = EMFILE; /* too many open files */
2452 _doserrno = 0L; /* not an OS error */
2453 return -1; /* return error to caller */
2456 /* the file is open. now, set the info in _osfhnd array */
2457 _set_osfhnd(fh, osfhandle);
2459 fileflags |= FOPEN; /* mark as open */
2461 _osfile(fh) = fileflags; /* set osfile entry */
2462 LeaveCriticalSection(&_pioinfo(fh)->lock);
2464 return fh; /* return handle */
2467 #endif /* USE_FIXED_OSFHANDLE */
2469 /* simulate flock by locking a range on the file */
2471 #define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
2472 #define LK_LEN 0xffff0000
2475 win32_flock(int fd, int oper)
2483 Perl_croak_nocontext("flock() unimplemented on this platform");
2486 fh = (HANDLE)_get_osfhandle(fd);
2487 memset(&o, 0, sizeof(o));
2490 case LOCK_SH: /* shared lock */
2491 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
2493 case LOCK_EX: /* exclusive lock */
2494 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
2496 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
2497 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
2499 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
2500 LK_ERR(LockFileEx(fh,
2501 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
2502 0, LK_LEN, 0, &o),i);
2504 case LOCK_UN: /* unlock lock */
2505 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
2507 default: /* unknown */
2518 * redirected io subsystem for all XS modules
2531 return (&(_environ));
2534 /* the rest are the remapped stdio routines */
2554 win32_ferror(FILE *fp)
2556 return (ferror(fp));
2561 win32_feof(FILE *fp)
2567 * Since the errors returned by the socket error function
2568 * WSAGetLastError() are not known by the library routine strerror
2569 * we have to roll our own.
2573 win32_strerror(int e)
2575 #if !defined __BORLANDC__ && !defined __MINGW32__ /* compiler intolerance */
2576 extern int sys_nerr;
2580 if (e < 0 || e > sys_nerr) {
2585 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0,
2586 w32_strerror_buffer,
2587 sizeof(w32_strerror_buffer), NULL) == 0)
2588 strcpy(w32_strerror_buffer, "Unknown Error");
2590 return w32_strerror_buffer;
2596 win32_str_os_error(void *sv, DWORD dwErr)
2600 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
2601 |FORMAT_MESSAGE_IGNORE_INSERTS
2602 |FORMAT_MESSAGE_FROM_SYSTEM, NULL,
2603 dwErr, 0, (char *)&sMsg, 1, NULL);
2604 /* strip trailing whitespace and period */
2607 --dwLen; /* dwLen doesn't include trailing null */
2608 } while (0 < dwLen && isSPACE(sMsg[dwLen]));
2609 if ('.' != sMsg[dwLen])
2614 sMsg = (char*)LocalAlloc(0, 64/**sizeof(TCHAR)*/);
2616 dwLen = sprintf(sMsg,
2617 "Unknown error #0x%lX (lookup 0x%lX)",
2618 dwErr, GetLastError());
2622 sv_setpvn((SV*)sv, sMsg, dwLen);
2628 win32_fprintf(FILE *fp, const char *format, ...)
2631 va_start(marker, format); /* Initialize variable arguments. */
2633 return (vfprintf(fp, format, marker));
2637 win32_printf(const char *format, ...)
2640 va_start(marker, format); /* Initialize variable arguments. */
2642 return (vprintf(format, marker));
2646 win32_vfprintf(FILE *fp, const char *format, va_list args)
2648 return (vfprintf(fp, format, args));
2652 win32_vprintf(const char *format, va_list args)
2654 return (vprintf(format, args));
2658 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
2660 return fread(buf, size, count, fp);
2664 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
2666 return fwrite(buf, size, count, fp);
2669 #define MODE_SIZE 10
2672 win32_fopen(const char *filename, const char *mode)
2680 if (stricmp(filename, "/dev/null")==0)
2683 f = fopen(PerlDir_mapA(filename), mode);
2684 /* avoid buffering headaches for child processes */
2685 if (f && *mode == 'a')
2686 win32_fseek(f, 0, SEEK_END);
2690 #ifndef USE_SOCKETS_AS_HANDLES
2692 #define fdopen my_fdopen
2696 win32_fdopen(int handle, const char *mode)
2700 f = fdopen(handle, (char *) mode);
2701 /* avoid buffering headaches for child processes */
2702 if (f && *mode == 'a')
2703 win32_fseek(f, 0, SEEK_END);
2708 win32_freopen(const char *path, const char *mode, FILE *stream)
2711 if (stricmp(path, "/dev/null")==0)
2714 return freopen(PerlDir_mapA(path), mode, stream);
2718 win32_fclose(FILE *pf)
2720 return my_fclose(pf); /* defined in win32sck.c */
2724 win32_fputs(const char *s,FILE *pf)
2726 return fputs(s, pf);
2730 win32_fputc(int c,FILE *pf)
2736 win32_ungetc(int c,FILE *pf)
2738 return ungetc(c,pf);
2742 win32_getc(FILE *pf)
2748 win32_fileno(FILE *pf)
2754 win32_clearerr(FILE *pf)
2761 win32_fflush(FILE *pf)
2767 win32_ftell(FILE *pf)
2769 #if defined(WIN64) || defined(USE_LARGE_FILES)
2770 #if defined(__BORLANDC__) /* buk */
2771 return win32_tell( fileno( pf ) );
2774 if (fgetpos(pf, &pos))
2784 win32_fseek(FILE *pf, Off_t offset,int origin)
2786 #if defined(WIN64) || defined(USE_LARGE_FILES)
2787 #if defined(__BORLANDC__) /* buk */
2797 if (fgetpos(pf, &pos))
2802 fseek(pf, 0, SEEK_END);
2803 pos = _telli64(fileno(pf));
2812 return fsetpos(pf, &offset);
2815 return fseek(pf, (long)offset, origin);
2820 win32_fgetpos(FILE *pf,fpos_t *p)
2822 #if defined(__BORLANDC__) && defined(USE_LARGE_FILES) /* buk */
2823 if( win32_tell(fileno(pf)) == -1L ) {
2829 return fgetpos(pf, p);
2834 win32_fsetpos(FILE *pf,const fpos_t *p)
2836 #if defined(__BORLANDC__) && defined(USE_LARGE_FILES) /* buk */
2837 return win32_lseek(fileno(pf), *p, SEEK_CUR);
2839 return fsetpos(pf, p);
2844 win32_rewind(FILE *pf)
2854 char prefix[MAX_PATH+1];
2855 char filename[MAX_PATH+1];
2856 DWORD len = GetTempPath(MAX_PATH, prefix);
2857 if (len && len < MAX_PATH) {
2858 if (GetTempFileName(prefix, "plx", 0, filename)) {
2859 HANDLE fh = CreateFile(filename,
2860 DELETE | GENERIC_READ | GENERIC_WRITE,
2864 FILE_ATTRIBUTE_NORMAL
2865 | FILE_FLAG_DELETE_ON_CLOSE,
2867 if (fh != INVALID_HANDLE_VALUE) {
2868 int fd = win32_open_osfhandle((intptr_t)fh, 0);
2870 #if defined(__BORLANDC__)
2871 setmode(fd,O_BINARY);
2873 DEBUG_p(PerlIO_printf(Perl_debug_log,
2874 "Created tmpfile=%s\n",filename));
2886 int fd = win32_tmpfd();
2888 return win32_fdopen(fd, "w+b");
2900 win32_fstat(int fd, Stat_t *sbufptr)
2903 /* A file designated by filehandle is not shown as accessible
2904 * for write operations, probably because it is opened for reading.
2907 BY_HANDLE_FILE_INFORMATION bhfi;
2908 #if defined(WIN64) || defined(USE_LARGE_FILES)
2909 /* Borland 5.5.1 has a 64-bit stat, but only a 32-bit fstat */
2911 int rc = fstat(fd,&tmp);
2913 sbufptr->st_dev = tmp.st_dev;
2914 sbufptr->st_ino = tmp.st_ino;
2915 sbufptr->st_mode = tmp.st_mode;
2916 sbufptr->st_nlink = tmp.st_nlink;
2917 sbufptr->st_uid = tmp.st_uid;
2918 sbufptr->st_gid = tmp.st_gid;
2919 sbufptr->st_rdev = tmp.st_rdev;
2920 sbufptr->st_size = tmp.st_size;
2921 sbufptr->st_atime = tmp.st_atime;
2922 sbufptr->st_mtime = tmp.st_mtime;
2923 sbufptr->st_ctime = tmp.st_ctime;
2925 int rc = fstat(fd,sbufptr);
2928 if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &bhfi)) {
2929 #if defined(WIN64) || defined(USE_LARGE_FILES)
2930 sbufptr->st_size = (bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow ;
2932 sbufptr->st_mode &= 0xFE00;
2933 if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2934 sbufptr->st_mode |= (S_IREAD + (S_IREAD >> 3) + (S_IREAD >> 6));
2936 sbufptr->st_mode |= ((S_IREAD|S_IWRITE) + ((S_IREAD|S_IWRITE) >> 3)
2937 + ((S_IREAD|S_IWRITE) >> 6));
2941 return my_fstat(fd,sbufptr);
2946 win32_pipe(int *pfd, unsigned int size, int mode)
2948 return _pipe(pfd, size, mode);
2952 win32_popenlist(const char *mode, IV narg, SV **args)
2955 Perl_croak(aTHX_ "List form of pipe open not implemented");
2960 * a popen() clone that respects PERL5SHELL
2962 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
2966 win32_popen(const char *command, const char *mode)
2968 #ifdef USE_RTL_POPEN
2969 return _popen(command, mode);
2981 /* establish which ends read and write */
2982 if (strchr(mode,'w')) {
2983 stdfd = 0; /* stdin */
2986 nhandle = STD_INPUT_HANDLE;
2988 else if (strchr(mode,'r')) {
2989 stdfd = 1; /* stdout */
2992 nhandle = STD_OUTPUT_HANDLE;
2997 /* set the correct mode */
2998 if (strchr(mode,'b'))
3000 else if (strchr(mode,'t'))
3003 ourmode = _fmode & (O_TEXT | O_BINARY);
3005 /* the child doesn't inherit handles */
3006 ourmode |= O_NOINHERIT;
3008 if (win32_pipe(p, 512, ourmode) == -1)
3011 /* save the old std handle (this needs to happen before the
3012 * dup2(), since that might call SetStdHandle() too) */
3015 old_h = GetStdHandle(nhandle);
3017 /* save current stdfd */
3018 if ((oldfd = win32_dup(stdfd)) == -1)
3021 /* make stdfd go to child end of pipe (implicitly closes stdfd) */
3022 /* stdfd will be inherited by the child */
3023 if (win32_dup2(p[child], stdfd) == -1)
3026 /* close the child end in parent */
3027 win32_close(p[child]);
3029 /* set the new std handle (in case dup2() above didn't) */
3030 SetStdHandle(nhandle, (HANDLE)_get_osfhandle(stdfd));
3032 /* start the child */
3035 if ((childpid = do_spawn_nowait((char*)command)) == -1)
3038 /* revert stdfd to whatever it was before */
3039 if (win32_dup2(oldfd, stdfd) == -1)
3042 /* close saved handle */
3045 /* restore the old std handle (this needs to happen after the
3046 * dup2(), since that might call SetStdHandle() too */
3048 SetStdHandle(nhandle, old_h);
3054 sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3057 /* set process id so that it can be returned by perl's open() */
3058 PL_forkprocess = childpid;
3061 /* we have an fd, return a file stream */
3062 return (PerlIO_fdopen(p[parent], (char *)mode));
3065 /* we don't need to check for errors here */
3069 win32_dup2(oldfd, stdfd);
3073 SetStdHandle(nhandle, old_h);
3079 #endif /* USE_RTL_POPEN */
3087 win32_pclose(PerlIO *pf)
3089 #ifdef USE_RTL_POPEN
3093 int childpid, status;
3097 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3100 childpid = SvIVX(sv);
3118 if (win32_waitpid(childpid, &status, 0) == -1)
3123 #endif /* USE_RTL_POPEN */
3129 LPCWSTR lpExistingFileName,
3130 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
3133 WCHAR wFullName[MAX_PATH+1];
3134 LPVOID lpContext = NULL;
3135 WIN32_STREAM_ID StreamId;
3136 DWORD dwSize = (char*)&StreamId.cStreamName - (char*)&StreamId;
3141 BOOL (__stdcall *pfnBackupWrite)(HANDLE, LPBYTE, DWORD, LPDWORD,
3142 BOOL, BOOL, LPVOID*) =
3143 (BOOL (__stdcall *)(HANDLE, LPBYTE, DWORD, LPDWORD,
3144 BOOL, BOOL, LPVOID*))
3145 GetProcAddress(GetModuleHandle("kernel32.dll"), "BackupWrite");
3146 if (pfnBackupWrite == NULL)
3149 dwLen = GetFullPathNameW(lpFileName, MAX_PATH, wFullName, NULL);
3152 dwLen = (dwLen+1)*sizeof(WCHAR);
3154 handle = CreateFileW(lpExistingFileName, FILE_WRITE_ATTRIBUTES,
3155 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3156 NULL, OPEN_EXISTING, 0, NULL);
3157 if (handle == INVALID_HANDLE_VALUE)
3160 StreamId.dwStreamId = BACKUP_LINK;
3161 StreamId.dwStreamAttributes = 0;
3162 StreamId.dwStreamNameSize = 0;
3163 #if defined(__BORLANDC__) \
3164 ||(defined(__MINGW32__) && !defined(_ANONYMOUS_UNION))
3165 StreamId.Size.u.HighPart = 0;
3166 StreamId.Size.u.LowPart = dwLen;
3168 StreamId.Size.HighPart = 0;
3169 StreamId.Size.LowPart = dwLen;
3172 bSuccess = pfnBackupWrite(handle, (LPBYTE)&StreamId, dwSize, &dwWritten,
3173 FALSE, FALSE, &lpContext);
3175 bSuccess = pfnBackupWrite(handle, (LPBYTE)wFullName, dwLen, &dwWritten,
3176 FALSE, FALSE, &lpContext);
3177 pfnBackupWrite(handle, NULL, 0, &dwWritten, TRUE, FALSE, &lpContext);
3180 CloseHandle(handle);
3185 win32_link(const char *oldname, const char *newname)
3188 BOOL (__stdcall *pfnCreateHardLinkW)(LPCWSTR,LPCWSTR,LPSECURITY_ATTRIBUTES);
3189 WCHAR wOldName[MAX_PATH+1];
3190 WCHAR wNewName[MAX_PATH+1];
3193 Perl_croak(aTHX_ PL_no_func, "link");
3195 pfnCreateHardLinkW =
3196 (BOOL (__stdcall *)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES))
3197 GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateHardLinkW");
3198 if (pfnCreateHardLinkW == NULL)
3199 pfnCreateHardLinkW = Nt4CreateHardLinkW;
3201 if (MultiByteToWideChar(CP_ACP, 0, oldname, -1, wOldName, MAX_PATH+1) &&
3202 MultiByteToWideChar(CP_ACP, 0, newname, -1, wNewName, MAX_PATH+1) &&
3203 (wcscpy(wOldName, PerlDir_mapW(wOldName)),
3204 pfnCreateHardLinkW(PerlDir_mapW(wNewName), wOldName, NULL)))
3208 errno = (GetLastError() == ERROR_FILE_NOT_FOUND) ? ENOENT : EINVAL;
3213 win32_rename(const char *oname, const char *newname)
3215 char szOldName[MAX_PATH+1];
3216 char szNewName[MAX_PATH+1];
3220 /* XXX despite what the documentation says about MoveFileEx(),
3221 * it doesn't work under Windows95!
3224 DWORD dwFlags = MOVEFILE_COPY_ALLOWED;
3225 if (stricmp(newname, oname))
3226 dwFlags |= MOVEFILE_REPLACE_EXISTING;
3227 strcpy(szOldName, PerlDir_mapA(oname));
3228 bResult = MoveFileExA(szOldName,PerlDir_mapA(newname), dwFlags);
3230 DWORD err = GetLastError();
3232 case ERROR_BAD_NET_NAME:
3233 case ERROR_BAD_NETPATH:
3234 case ERROR_BAD_PATHNAME:
3235 case ERROR_FILE_NOT_FOUND:
3236 case ERROR_FILENAME_EXCED_RANGE:
3237 case ERROR_INVALID_DRIVE:
3238 case ERROR_NO_MORE_FILES:
3239 case ERROR_PATH_NOT_FOUND:
3252 char szTmpName[MAX_PATH+1];
3253 char dname[MAX_PATH+1];
3254 char *endname = NULL;
3256 DWORD from_attr, to_attr;
3258 strcpy(szOldName, PerlDir_mapA(oname));
3259 strcpy(szNewName, PerlDir_mapA(newname));
3261 /* if oname doesn't exist, do nothing */
3262 from_attr = GetFileAttributes(szOldName);
3263 if (from_attr == 0xFFFFFFFF) {
3268 /* if newname exists, rename it to a temporary name so that we
3269 * don't delete it in case oname happens to be the same file
3270 * (but perhaps accessed via a different path)
3272 to_attr = GetFileAttributes(szNewName);
3273 if (to_attr != 0xFFFFFFFF) {
3274 /* if newname is a directory, we fail
3275 * XXX could overcome this with yet more convoluted logic */
3276 if (to_attr & FILE_ATTRIBUTE_DIRECTORY) {
3280 tmplen = strlen(szNewName);
3281 strcpy(szTmpName,szNewName);
3282 endname = szTmpName+tmplen;
3283 for (; endname > szTmpName ; --endname) {
3284 if (*endname == '/' || *endname == '\\') {
3289 if (endname > szTmpName)
3290 endname = strcpy(dname,szTmpName);
3294 /* get a temporary filename in same directory
3295 * XXX is this really the best we can do? */
3296 if (!GetTempFileName((LPCTSTR)endname, "plr", 0, szTmpName)) {
3300 DeleteFile(szTmpName);
3302 retval = rename(szNewName, szTmpName);
3309 /* rename oname to newname */
3310 retval = rename(szOldName, szNewName);
3312 /* if we created a temporary file before ... */
3313 if (endname != NULL) {
3314 /* ...and rename succeeded, delete temporary file/directory */
3316 DeleteFile(szTmpName);
3317 /* else restore it to what it was */
3319 (void)rename(szTmpName, szNewName);
3326 win32_setmode(int fd, int mode)
3328 return setmode(fd, mode);
3332 win32_chsize(int fd, Off_t size)
3334 #if defined(WIN64) || defined(USE_LARGE_FILES)
3336 Off_t cur, end, extend;
3338 cur = win32_tell(fd);
3341 end = win32_lseek(fd, 0, SEEK_END);
3344 extend = size - end;
3348 else if (extend > 0) {
3349 /* must grow the file, padding with nulls */
3351 int oldmode = win32_setmode(fd, O_BINARY);
3353 memset(b, '\0', sizeof(b));
3355 count = extend >= sizeof(b) ? sizeof(b) : (size_t)extend;
3356 count = win32_write(fd, b, count);
3357 if ((int)count < 0) {
3361 } while ((extend -= count) > 0);
3362 win32_setmode(fd, oldmode);
3365 /* shrink the file */
3366 win32_lseek(fd, size, SEEK_SET);
3367 if (!SetEndOfFile((HANDLE)_get_osfhandle(fd))) {
3373 win32_lseek(fd, cur, SEEK_SET);
3376 return chsize(fd, (long)size);
3381 win32_lseek(int fd, Off_t offset, int origin)
3383 #if defined(WIN64) || defined(USE_LARGE_FILES)
3384 #if defined(__BORLANDC__) /* buk */
3386 pos.QuadPart = offset;
3387 pos.LowPart = SetFilePointer(
3388 (HANDLE)_get_osfhandle(fd),
3393 if (pos.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
3397 return pos.QuadPart;
3399 return _lseeki64(fd, offset, origin);
3402 return lseek(fd, (long)offset, origin);
3409 #if defined(WIN64) || defined(USE_LARGE_FILES)
3410 #if defined(__BORLANDC__) /* buk */
3413 pos.LowPart = SetFilePointer(
3414 (HANDLE)_get_osfhandle(fd),
3419 if (pos.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
3423 return pos.QuadPart;
3424 /* return tell(fd); */
3426 return _telli64(fd);
3434 win32_open(const char *path, int flag, ...)
3441 pmode = va_arg(ap, int);
3444 if (stricmp(path, "/dev/null")==0)
3447 return open(PerlDir_mapA(path), flag, pmode);
3450 /* close() that understands socket */
3451 extern int my_close(int); /* in win32sck.c */
3456 return my_close(fd);
3472 win32_dup2(int fd1,int fd2)
3474 return dup2(fd1,fd2);
3477 #ifdef PERL_MSVCRT_READFIX
3479 #define LF 10 /* line feed */
3480 #define CR 13 /* carriage return */
3481 #define CTRLZ 26 /* ctrl-z means eof for text */
3482 #define FOPEN 0x01 /* file handle open */
3483 #define FEOFLAG 0x02 /* end of file has been encountered */
3484 #define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */
3485 #define FPIPE 0x08 /* file handle refers to a pipe */
3486 #define FAPPEND 0x20 /* file handle opened O_APPEND */
3487 #define FDEV 0x40 /* file handle refers to device */
3488 #define FTEXT 0x80 /* file handle is in text mode */
3489 #define MAX_DESCRIPTOR_COUNT (64*32) /* this is the maximun that MSVCRT can handle */
3492 _fixed_read(int fh, void *buf, unsigned cnt)
3494 int bytes_read; /* number of bytes read */
3495 char *buffer; /* buffer to read to */
3496 int os_read; /* bytes read on OS call */
3497 char *p, *q; /* pointers into buffer */
3498 char peekchr; /* peek-ahead character */
3499 ULONG filepos; /* file position after seek */
3500 ULONG dosretval; /* o.s. return value */
3502 /* validate handle */
3503 if (((unsigned)fh >= (unsigned)MAX_DESCRIPTOR_COUNT) ||
3504 !(_osfile(fh) & FOPEN))
3506 /* out of range -- return error */
3508 _doserrno = 0; /* not o.s. error */
3513 * If lockinitflag is FALSE, assume fd is device
3514 * lockinitflag is set to TRUE by open.
3516 if (_pioinfo(fh)->lockinitflag)
3517 EnterCriticalSection(&(_pioinfo(fh)->lock)); /* lock file */
3519 bytes_read = 0; /* nothing read yet */
3520 buffer = (char*)buf;
3522 if (cnt == 0 || (_osfile(fh) & FEOFLAG)) {
3523 /* nothing to read or at EOF, so return 0 read */
3527 if ((_osfile(fh) & (FPIPE|FDEV)) && _pipech(fh) != LF) {
3528 /* a pipe/device and pipe lookahead non-empty: read the lookahead
3530 *buffer++ = _pipech(fh);
3533 _pipech(fh) = LF; /* mark as empty */
3538 if (!ReadFile((HANDLE)_osfhnd(fh), buffer, cnt, (LPDWORD)&os_read, NULL))
3540 /* ReadFile has reported an error. recognize two special cases.
3542 * 1. map ERROR_ACCESS_DENIED to EBADF
3544 * 2. just return 0 if ERROR_BROKEN_PIPE has occurred. it
3545 * means the handle is a read-handle on a pipe for which
3546 * all write-handles have been closed and all data has been
3549 if ((dosretval = GetLastError()) == ERROR_ACCESS_DENIED) {
3550 /* wrong read/write mode should return EBADF, not EACCES */
3552 _doserrno = dosretval;
3556 else if (dosretval == ERROR_BROKEN_PIPE) {
3566 bytes_read += os_read; /* update bytes read */
3568 if (_osfile(fh) & FTEXT) {
3569 /* now must translate CR-LFs to LFs in the buffer */
3571 /* set CRLF flag to indicate LF at beginning of buffer */
3572 /* if ((os_read != 0) && (*(char *)buf == LF)) */
3573 /* _osfile(fh) |= FCRLF; */
3575 /* _osfile(fh) &= ~FCRLF; */
3577 _osfile(fh) &= ~FCRLF;
3579 /* convert chars in the buffer: p is src, q is dest */
3581 while (p < (char *)buf + bytes_read) {
3583 /* if fh is not a device, set ctrl-z flag */
3584 if (!(_osfile(fh) & FDEV))
3585 _osfile(fh) |= FEOFLAG;
3586 break; /* stop translating */
3591 /* *p is CR, so must check next char for LF */
3592 if (p < (char *)buf + bytes_read - 1) {
3595 *q++ = LF; /* convert CR-LF to LF */
3598 *q++ = *p++; /* store char normally */
3601 /* This is the hard part. We found a CR at end of
3602 buffer. We must peek ahead to see if next char
3607 if (!ReadFile((HANDLE)_osfhnd(fh), &peekchr, 1,
3608 (LPDWORD)&os_read, NULL))
3609 dosretval = GetLastError();
3611 if (dosretval != 0 || os_read == 0) {
3612 /* couldn't read ahead, store CR */
3616 /* peekchr now has the extra character -- we now
3617 have several possibilities:
3618 1. disk file and char is not LF; just seek back
3620 2. disk file and char is LF; store LF, don't seek back
3621 3. pipe/device and char is LF; store LF.
3622 4. pipe/device and char isn't LF, store CR and
3623 put char in pipe lookahead buffer. */
3624 if (_osfile(fh) & (FDEV|FPIPE)) {
3625 /* non-seekable device */
3630 _pipech(fh) = peekchr;
3635 if (peekchr == LF) {
3636 /* nothing read yet; must make some
3639 /* turn on this flag for tell routine */
3640 _osfile(fh) |= FCRLF;
3643 HANDLE osHandle; /* o.s. handle value */
3645 if ((osHandle = (HANDLE)_get_osfhandle(fh)) != (HANDLE)-1)
3647 if ((filepos = SetFilePointer(osHandle, -1, NULL, FILE_CURRENT)) == -1)
3648 dosretval = GetLastError();
3659 /* we now change bytes_read to reflect the true number of chars
3661 bytes_read = q - (char *)buf;
3665 if (_pioinfo(fh)->lockinitflag)
3666 LeaveCriticalSection(&(_pioinfo(fh)->lock)); /* unlock file */
3671 #endif /* PERL_MSVCRT_READFIX */
3674 win32_read(int fd, void *buf, unsigned int cnt)
3676 #ifdef PERL_MSVCRT_READFIX
3677 return _fixed_read(fd, buf, cnt);
3679 return read(fd, buf, cnt);
3684 win32_write(int fd, const void *buf, unsigned int cnt)
3686 return write(fd, buf, cnt);
3690 win32_mkdir(const char *dir, int mode)
3693 return mkdir(PerlDir_mapA(dir)); /* just ignore mode */
3697 win32_rmdir(const char *dir)
3700 return rmdir(PerlDir_mapA(dir));
3704 win32_chdir(const char *dir)
3715 win32_access(const char *path, int mode)
3718 return access(PerlDir_mapA(path), mode);
3722 win32_chmod(const char *path, int mode)
3725 return chmod(PerlDir_mapA(path), mode);
3730 create_command_line(char *cname, STRLEN clen, const char * const *args)
3737 bool bat_file = FALSE;
3738 bool cmd_shell = FALSE;
3739 bool dumb_shell = FALSE;
3740 bool extra_quotes = FALSE;
3741 bool quote_next = FALSE;
3744 cname = (char*)args[0];
3746 /* The NT cmd.exe shell has the following peculiarity that needs to be
3747 * worked around. It strips a leading and trailing dquote when any
3748 * of the following is true:
3749 * 1. the /S switch was used
3750 * 2. there are more than two dquotes
3751 * 3. there is a special character from this set: &<>()@^|
3752 * 4. no whitespace characters within the two dquotes
3753 * 5. string between two dquotes isn't an executable file
3754 * To work around this, we always add a leading and trailing dquote
3755 * to the string, if the first argument is either "cmd.exe" or "cmd",
3756 * and there were at least two or more arguments passed to cmd.exe
3757 * (not including switches).
3758 * XXX the above rules (from "cmd /?") don't seem to be applied
3759 * always, making for the convolutions below :-(
3763 clen = strlen(cname);
3766 && (stricmp(&cname[clen-4], ".bat") == 0
3767 || (IsWinNT() && stricmp(&cname[clen-4], ".cmd") == 0)))
3774 char *exe = strrchr(cname, '/');
3775 char *exe2 = strrchr(cname, '\\');
3782 if (stricmp(exe, "cmd.exe") == 0 || stricmp(exe, "cmd") == 0) {
3786 else if (stricmp(exe, "command.com") == 0
3787 || stricmp(exe, "command") == 0)
3794 DEBUG_p(PerlIO_printf(Perl_debug_log, "Args "));
3795 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3796 STRLEN curlen = strlen(arg);
3797 if (!(arg[0] == '"' && arg[curlen-1] == '"'))
3798 len += 2; /* assume quoting needed (worst case) */
3800 DEBUG_p(PerlIO_printf(Perl_debug_log, "[%s]",arg));
3802 DEBUG_p(PerlIO_printf(Perl_debug_log, "\n"));
3805 Newx(cmd, len, char);
3808 if (bat_file && !IsWin95()) {
3810 extra_quotes = TRUE;
3813 for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
3815 STRLEN curlen = strlen(arg);
3817 /* we want to protect empty arguments and ones with spaces with
3818 * dquotes, but only if they aren't already there */
3823 else if (quote_next) {
3824 /* see if it really is multiple arguments pretending to
3825 * be one and force a set of quotes around it */
3826 if (*find_next_space(arg))
3829 else if (!(arg[0] == '"' && curlen > 1 && arg[curlen-1] == '"')) {
3831 while (i < curlen) {
3832 if (isSPACE(arg[i])) {
3835 else if (arg[i] == '"') {
3859 && *arg == '/' /* see if arg is "/c", "/x/c", "/x/d/c" etc. */
3860 && stricmp(arg+curlen-2, "/c") == 0)
3862 /* is there a next argument? */
3863 if (args[index+1]) {
3864 /* are there two or more next arguments? */
3865 if (args[index+2]) {
3867 extra_quotes = TRUE;
3870 /* single argument, force quoting if it has spaces */
3886 qualified_path(const char *cmd)
3890 char *fullcmd, *curfullcmd;
3896 fullcmd = (char*)cmd;
3898 if (*fullcmd == '/' || *fullcmd == '\\')
3905 pathstr = PerlEnv_getenv("PATH");
3907 /* worst case: PATH is a single directory; we need additional space
3908 * to append "/", ".exe" and trailing "\0" */
3909 Newx(fullcmd, (pathstr ? strlen(pathstr) : 0) + cmdlen + 6, char);
3910 curfullcmd = fullcmd;
3915 /* start by appending the name to the current prefix */
3916 strcpy(curfullcmd, cmd);
3917 curfullcmd += cmdlen;
3919 /* if it doesn't end with '.', or has no extension, try adding
3920 * a trailing .exe first */
3921 if (cmd[cmdlen-1] != '.'
3922 && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
3924 strcpy(curfullcmd, ".exe");
3925 res = GetFileAttributes(fullcmd);
3926 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3931 /* that failed, try the bare name */
3932 res = GetFileAttributes(fullcmd);
3933 if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
3936 /* quit if no other path exists, or if cmd already has path */
3937 if (!pathstr || !*pathstr || has_slash)
3940 /* skip leading semis */
3941 while (*pathstr == ';')
3944 /* build a new prefix from scratch */
3945 curfullcmd = fullcmd;
3946 while (*pathstr && *pathstr != ';') {
3947 if (*pathstr == '"') { /* foo;"baz;etc";bar */
3948 pathstr++; /* skip initial '"' */
3949 while (*pathstr && *pathstr != '"') {
3950 *curfullcmd++ = *pathstr++;
3953 pathstr++; /* skip trailing '"' */
3956 *curfullcmd++ = *pathstr++;
3960 pathstr++; /* skip trailing semi */
3961 if (curfullcmd > fullcmd /* append a dir separator */
3962 && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
3964 *curfullcmd++ = '\\';
3972 /* The following are just place holders.
3973 * Some hosts may provide and environment that the OS is
3974 * not tracking, therefore, these host must provide that
3975 * environment and the current directory to CreateProcess
3979 win32_get_childenv(void)
3985 win32_free_childenv(void* d)
3990 win32_clearenv(void)
3992 char *envv = GetEnvironmentStrings();
3996 char *end = strchr(cur,'=');
3997 if (end && end != cur) {
3999 SetEnvironmentVariable(cur, NULL);
4001 cur = end + strlen(end+1)+2;
4003 else if ((len = strlen(cur)))
4006 FreeEnvironmentStrings(envv);
4010 win32_get_childdir(void)
4014 char szfilename[MAX_PATH+1];
4016 GetCurrentDirectoryA(MAX_PATH+1, szfilename);
4017 Newx(ptr, strlen(szfilename)+1, char);
4018 strcpy(ptr, szfilename);
4023 win32_free_childdir(char* d)
4030 /* XXX this needs to be made more compatible with the spawnvp()
4031 * provided by the various RTLs. In particular, searching for
4032 * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
4033 * This doesn't significantly affect perl itself, because we
4034 * always invoke things using PERL5SHELL if a direct attempt to
4035 * spawn the executable fails.
4037 * XXX splitting and rejoining the commandline between do_aspawn()
4038 * and win32_spawnvp() could also be avoided.
4042 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
4044 #ifdef USE_RTL_SPAWNVP
4045 return spawnvp(mode, cmdname, (char * const *)argv);
4052 STARTUPINFO StartupInfo;
4053 PROCESS_INFORMATION ProcessInformation;
4056 char *fullcmd = NULL;
4057 char *cname = (char *)cmdname;
4061 clen = strlen(cname);
4062 /* if command name contains dquotes, must remove them */
4063 if (strchr(cname, '"')) {
4065 Newx(cname,clen+1,char);
4078 cmd = create_command_line(cname, clen, argv);
4080 env = PerlEnv_get_childenv();
4081 dir = PerlEnv_get_childdir();
4084 case P_NOWAIT: /* asynch + remember result */
4085 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
4090 /* Create a new process group so we can use GenerateConsoleCtrlEvent()
4093 create |= CREATE_NEW_PROCESS_GROUP;
4096 case P_WAIT: /* synchronous execution */
4098 default: /* invalid mode */
4103 memset(&StartupInfo,0,sizeof(StartupInfo));
4104 StartupInfo.cb = sizeof(StartupInfo);
4105 memset(&tbl,0,sizeof(tbl));
4106 PerlEnv_get_child_IO(&tbl);
4107 StartupInfo.dwFlags = tbl.dwFlags;
4108 StartupInfo.dwX = tbl.dwX;
4109 StartupInfo.dwY = tbl.dwY;
4110 StartupInfo.dwXSize = tbl.dwXSize;
4111 StartupInfo.dwYSize = tbl.dwYSize;
4112 StartupInfo.dwXCountChars = tbl.dwXCountChars;
4113 StartupInfo.dwYCountChars = tbl.dwYCountChars;
4114 StartupInfo.dwFillAttribute = tbl.dwFillAttribute;
4115 StartupInfo.wShowWindow = tbl.wShowWindow;
4116 StartupInfo.hStdInput = tbl.childStdIn;
4117 StartupInfo.hStdOutput = tbl.childStdOut;
4118 StartupInfo.hStdError = tbl.childStdErr;
4119 if (StartupInfo.hStdInput == INVALID_HANDLE_VALUE &&
4120 StartupInfo.hStdOutput == INVALID_HANDLE_VALUE &&
4121 StartupInfo.hStdError == INVALID_HANDLE_VALUE)
4123 create |= CREATE_NEW_CONSOLE;
4126 StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
4128 if (w32_use_showwindow) {
4129 StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
4130 StartupInfo.wShowWindow = w32_showwindow;
4133 DEBUG_p(PerlIO_printf(Perl_debug_log, "Spawning [%s] with [%s]\n",
4136 if (!CreateProcess(cname, /* search PATH to find executable */
4137 cmd, /* executable, and its arguments */
4138 NULL, /* process attributes */
4139 NULL, /* thread attributes */
4140 TRUE, /* inherit handles */
4141 create, /* creation flags */
4142 (LPVOID)env, /* inherit environment */
4143 dir, /* inherit cwd */
4145 &ProcessInformation))
4147 /* initial NULL argument to CreateProcess() does a PATH
4148 * search, but it always first looks in the directory
4149 * where the current process was started, which behavior
4150 * is undesirable for backward compatibility. So we
4151 * jump through our own hoops by picking out the path
4152 * we really want it to use. */
4154 fullcmd = qualified_path(cname);
4156 if (cname != cmdname)
4159 DEBUG_p(PerlIO_printf(Perl_debug_log,
4160 "Retrying [%s] with same args\n",
4170 if (mode == P_NOWAIT) {
4171 /* asynchronous spawn -- store handle, return PID */
4172 ret = (int)ProcessInformation.dwProcessId;
4173 if (IsWin95() && ret < 0)
4176 w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
4177 w32_child_pids[w32_num_children] = (DWORD)ret;
4182 win32_msgwait(aTHX_ 1, &ProcessInformation.hProcess, INFINITE, NULL);
4183 /* FIXME: if msgwait returned due to message perhaps forward the
4184 "signal" to the process
4186 GetExitCodeProcess(ProcessInformation.hProcess, &status);
4188 CloseHandle(ProcessInformation.hProcess);
4191 CloseHandle(ProcessInformation.hThread);
4194 PerlEnv_free_childenv(env);
4195 PerlEnv_free_childdir(dir);
4197 if (cname != cmdname)
4204 win32_execv(const char *cmdname, const char *const *argv)
4208 /* if this is a pseudo-forked child, we just want to spawn
4209 * the new program, and return */
4211 # ifdef __BORLANDC__
4212 return spawnv(P_WAIT, cmdname, (char *const *)argv);
4214 return spawnv(P_WAIT, cmdname, argv);
4218 return execv(cmdname, (char *const *)argv);
4220 return execv(cmdname, argv);
4225 win32_execvp(const char *cmdname, const char *const *argv)
4229 /* if this is a pseudo-forked child, we just want to spawn
4230 * the new program, and return */
4231 if (w32_pseudo_id) {
4232 int status = win32_spawnvp(P_WAIT, cmdname, (const char *const *)argv);
4242 return execvp(cmdname, (char *const *)argv);
4244 return execvp(cmdname, argv);
4249 win32_perror(const char *str)
4255 win32_setbuf(FILE *pf, char *buf)
4261 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
4263 return setvbuf(pf, buf, type, size);
4267 win32_flushall(void)
4273 win32_fcloseall(void)
4279 win32_fgets(char *s, int n, FILE *pf)
4281 return fgets(s, n, pf);
4291 win32_fgetc(FILE *pf)
4297 win32_putc(int c, FILE *pf)
4303 win32_puts(const char *s)
4315 win32_putchar(int c)
4322 #ifndef USE_PERL_SBRK
4324 static char *committed = NULL; /* XXX threadead */
4325 static char *base = NULL; /* XXX threadead */
4326 static char *reserved = NULL; /* XXX threadead */
4327 static char *brk = NULL; /* XXX threadead */
4328 static DWORD pagesize = 0; /* XXX threadead */
4331 sbrk(ptrdiff_t need)
4336 GetSystemInfo(&info);
4337 /* Pretend page size is larger so we don't perpetually
4338 * call the OS to commit just one page ...
4340 pagesize = info.dwPageSize << 3;
4342 if (brk+need >= reserved)
4344 DWORD size = brk+need-reserved;
4346 char *prev_committed = NULL;
4347 if (committed && reserved && committed < reserved)
4349 /* Commit last of previous chunk cannot span allocations */
4350 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
4353 /* Remember where we committed from in case we want to decommit later */
4354 prev_committed = committed;
4355 committed = reserved;
4358 /* Reserve some (more) space
4359 * Contiguous blocks give us greater efficiency, so reserve big blocks -
4360 * this is only address space not memory...
4361 * Note this is a little sneaky, 1st call passes NULL as reserved
4362 * so lets system choose where we start, subsequent calls pass
4363 * the old end address so ask for a contiguous block
4366 if (size < 64*1024*1024)
4367 size = 64*1024*1024;
4368 size = ((size + pagesize - 1) / pagesize) * pagesize;
4369 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
4372 reserved = addr+size;
4382 /* The existing block could not be extended far enough, so decommit
4383 * anything that was just committed above and start anew */
4386 if (!VirtualFree(prev_committed,reserved-prev_committed,MEM_DECOMMIT))
4389 reserved = base = committed = brk = NULL;
4400 if (brk > committed)
4402 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
4404 if (committed+size > reserved)
4405 size = reserved-committed;
4406 addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
4419 win32_malloc(size_t size)
4421 return malloc(size);
4425 win32_calloc(size_t numitems, size_t size)
4427 return calloc(numitems,size);
4431 win32_realloc(void *block, size_t size)
4433 return realloc(block,size);
4437 win32_free(void *block)
4444 win32_open_osfhandle(intptr_t handle, int flags)
4446 #ifdef USE_FIXED_OSFHANDLE
4448 return my_open_osfhandle(handle, flags);
4450 return _open_osfhandle(handle, flags);
4454 win32_get_osfhandle(int fd)
4456 return (intptr_t)_get_osfhandle(fd);
4460 win32_fdupopen(FILE *pf)
4465 int fileno = win32_dup(win32_fileno(pf));
4467 /* open the file in the same mode */
4469 if((pf)->flags & _F_READ) {
4473 else if((pf)->flags & _F_WRIT) {
4477 else if((pf)->flags & _F_RDWR) {
4483 if((pf)->_flag & _IOREAD) {
4487 else if((pf)->_flag & _IOWRT) {
4491 else if((pf)->_flag & _IORW) {
4498 /* it appears that the binmode is attached to the
4499 * file descriptor so binmode files will be handled
4502 pfdup = win32_fdopen(fileno, mode);
4504 /* move the file pointer to the same position */
4505 if (!fgetpos(pf, &pos)) {
4506 fsetpos(pfdup, &pos);
4512 win32_dynaload(const char* filename)
4515 char buf[MAX_PATH+1];
4518 /* LoadLibrary() doesn't recognize forward slashes correctly,
4519 * so turn 'em back. */
4520 first = strchr(filename, '/');
4522 STRLEN len = strlen(filename);
4523 if (len <= MAX_PATH) {
4524 strcpy(buf, filename);
4525 filename = &buf[first - filename];
4527 if (*filename == '/')
4528 *(char*)filename = '\\';
4534 return LoadLibraryExA(PerlDir_mapA(filename), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
4537 XS(w32_SetChildShowWindow)
4540 BOOL use_showwindow = w32_use_showwindow;
4541 /* use "unsigned short" because Perl has redefined "WORD" */
4542 unsigned short showwindow = w32_showwindow;
4545 Perl_croak(aTHX_ "usage: Win32::SetChildShowWindow($showwindow)");
4547 if (items == 0 || !SvOK(ST(0)))
4548 w32_use_showwindow = FALSE;
4550 w32_use_showwindow = TRUE;
4551 w32_showwindow = (unsigned short)SvIV(ST(0));
4556 ST(0) = sv_2mortal(newSViv(showwindow));
4558 ST(0) = &PL_sv_undef;
4563 Perl_init_os_extras(void)
4566 char *file = __FILE__;
4568 /* Initialize Win32CORE if it has been statically linked. */
4569 void (*pfn_init)(pTHX);
4570 #if defined(__BORLANDC__)
4571 /* makedef.pl seems to have given up on fixing this issue in the .def file */
4572 pfn_init = (void (*)(pTHX))GetProcAddress((HMODULE)w32_perldll_handle, "_init_Win32CORE");
4574 pfn_init = (void (*)(pTHX))GetProcAddress((HMODULE)w32_perldll_handle, "init_Win32CORE");
4579 newXS("Win32::SetChildShowWindow", w32_SetChildShowWindow, file);
4583 win32_signal_context(void)
4588 my_perl = PL_curinterp;
4589 PERL_SET_THX(my_perl);
4593 return PL_curinterp;
4599 win32_ctrlhandler(DWORD dwCtrlType)
4602 dTHXa(PERL_GET_SIG_CONTEXT);
4608 switch(dwCtrlType) {
4609 case CTRL_CLOSE_EVENT:
4610 /* A signal that the system sends to all processes attached to a console when
4611 the user closes the console (either by choosing the Close command from the
4612 console window's System menu, or by choosing the End Task command from the
4615 if (do_raise(aTHX_ 1)) /* SIGHUP */
4616 sig_terminate(aTHX_ 1);
4620 /* A CTRL+c signal was received */
4621 if (do_raise(aTHX_ SIGINT))
4622 sig_terminate(aTHX_ SIGINT);
4625 case CTRL_BREAK_EVENT:
4626 /* A CTRL+BREAK signal was received */
4627 if (do_raise(aTHX_ SIGBREAK))
4628 sig_terminate(aTHX_ SIGBREAK);
4631 case CTRL_LOGOFF_EVENT:
4632 /* A signal that the system sends to all console processes when a user is logging
4633 off. This signal does not indicate which user is logging off, so no
4634 assumptions can be made.
4637 case CTRL_SHUTDOWN_EVENT:
4638 /* A signal that the system sends to all console processes when the system is
4641 if (do_raise(aTHX_ SIGTERM))
4642 sig_terminate(aTHX_ SIGTERM);
4651 #ifdef SET_INVALID_PARAMETER_HANDLER
4652 # include <crtdbg.h>
4663 /* win32_ansipath() requires Windows 2000 or later */
4667 /* fetch Unicode version of PATH */
4669 wide_path = win32_malloc(len*sizeof(WCHAR));
4671 size_t newlen = GetEnvironmentVariableW(L"PATH", wide_path, len);
4675 wide_path = win32_realloc(wide_path, len*sizeof(WCHAR));
4680 /* convert to ANSI pathnames */
4681 wide_dir = wide_path;
4684 WCHAR *sep = wcschr(wide_dir, ';');
4692 /* remove quotes around pathname */
4693 if (*wide_dir == '"')
4695 wide_len = wcslen(wide_dir);
4696 if (wide_len && wide_dir[wide_len-1] == '"')
4697 wide_dir[wide_len-1] = '\0';
4699 /* append ansi_dir to ansi_path */
4700 ansi_dir = win32_ansipath(wide_dir);
4701 ansi_len = strlen(ansi_dir);
4703 size_t newlen = len + 1 + ansi_len;
4704 ansi_path = win32_realloc(ansi_path, newlen+1);
4707 ansi_path[len] = ';';
4708 memcpy(ansi_path+len+1, ansi_dir, ansi_len+1);
4713 ansi_path = win32_malloc(5+len+1);
4716 memcpy(ansi_path, "PATH=", 5);
4717 memcpy(ansi_path+5, ansi_dir, len+1);
4720 win32_free(ansi_dir);
4725 /* Update C RTL environ array. This will only have full effect if
4726 * perl_parse() is later called with `environ` as the `env` argument.
4727 * Otherwise S_init_postdump_symbols() will overwrite PATH again.
4729 * We do have to ansify() the PATH before Perl has been fully
4730 * initialized because S_find_script() uses the PATH when perl
4731 * is being invoked with the -S option. This happens before %ENV
4732 * is initialized in S_init_postdump_symbols().
4734 * XXX Is this a bug? Should S_find_script() use the environment
4735 * XXX passed in the `env` arg to parse_perl()?
4738 /* Keep system environment in sync because S_init_postdump_symbols()
4739 * will not call mg_set() if it initializes %ENV from `environ`.
4741 SetEnvironmentVariableA("PATH", ansi_path+5);
4742 /* We are intentionally leaking the ansi_path string here because
4743 * the Borland runtime library puts it directly into the environ
4744 * array. The Microsoft runtime library seems to make a copy,
4745 * but will leak the copy should it be replaced again later.
4746 * Since this code is only called once during PERL_SYS_INIT this
4747 * shouldn't really matter.
4750 win32_free(wide_path);
4754 Perl_win32_init(int *argcp, char ***argvp)
4758 #ifdef SET_INVALID_PARAMETER_HANDLER
4759 _invalid_parameter_handler oldHandler, newHandler;
4760 newHandler = my_invalid_parameter_handler;
4761 oldHandler = _set_invalid_parameter_handler(newHandler);
4762 _CrtSetReportMode(_CRT_ASSERT, 0);
4764 /* Disable floating point errors, Perl will trap the ones we
4765 * care about. VC++ RTL defaults to switching these off
4766 * already, but the Borland RTL doesn't. Since we don't
4767 * want to be at the vendor's whim on the default, we set
4768 * it explicitly here.
4770 #if !defined(_ALPHA_) && !defined(__GNUC__)
4771 _control87(MCW_EM, MCW_EM);
4775 module = GetModuleHandle("ntdll.dll");
4777 *(FARPROC*)&pfnZwQuerySystemInformation = GetProcAddress(module, "ZwQuerySystemInformation");
4780 module = GetModuleHandle("kernel32.dll");
4782 *(FARPROC*)&pfnCreateToolhelp32Snapshot = GetProcAddress(module, "CreateToolhelp32Snapshot");
4783 *(FARPROC*)&pfnProcess32First = GetProcAddress(module, "Process32First");
4784 *(FARPROC*)&pfnProcess32Next = GetProcAddress(module, "Process32Next");
4787 g_osver.dwOSVersionInfoSize = sizeof(g_osver);
4788 GetVersionEx(&g_osver);
4794 Perl_win32_term(void)
4804 win32_get_child_IO(child_IO_table* ptbl)
4806 ptbl->childStdIn = GetStdHandle(STD_INPUT_HANDLE);
4807 ptbl->childStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
4808 ptbl->childStdErr = GetStdHandle(STD_ERROR_HANDLE);
4812 win32_signal(int sig, Sighandler_t subcode)
4815 if (sig < SIG_SIZE) {
4816 int save_errno = errno;
4817 Sighandler_t result = signal(sig, subcode);
4818 if (result == SIG_ERR) {
4819 result = w32_sighandler[sig];
4822 w32_sighandler[sig] = subcode;
4831 /* The PerlMessageWindowClass's WindowProc */
4833 win32_message_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4835 return win32_process_message(hwnd, msg, wParam, lParam) ?
4836 0 : DefWindowProc(hwnd, msg, wParam, lParam);
4839 /* we use a message filter hook to process thread messages, passing any
4840 * messages that we don't process on to the rest of the hook chain
4841 * Anyone else writing a message loop that wants to play nicely with perl
4843 * CallMsgFilter(&msg, MSGF_***);
4844 * between their GetMessage and DispatchMessage calls. */
4846 win32_message_filter_proc(int code, WPARAM wParam, LPARAM lParam) {
4847 LPMSG pmsg = (LPMSG)lParam;
4849 /* we'll process it if code says we're allowed, and it's a thread message */
4850 if (code >= 0 && pmsg->hwnd == NULL
4851 && win32_process_message(pmsg->hwnd, pmsg->message,
4852 pmsg->wParam, pmsg->lParam))
4857 /* XXX: MSDN says that hhk is ignored, but we should really use the
4858 * return value from SetWindowsHookEx() in win32_create_message_window(). */
4859 return CallNextHookEx(NULL, code, wParam, lParam);
4862 /* The real message handler. Can be called with
4863 * hwnd == NULL to process our thread messages. Returns TRUE for any messages
4864 * that it processes */
4866 win32_process_message(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4868 /* BEWARE. The context retrieved using dTHX; is the context of the
4869 * 'parent' thread during the CreateWindow() phase - i.e. for all messages
4870 * up to and including WM_CREATE. If it ever happens that you need the
4871 * 'child' context before this, then it needs to be passed into
4872 * win32_create_message_window(), and passed to the WM_NCCREATE handler
4873 * from the lparam of CreateWindow(). It could then be stored/retrieved
4874 * using [GS]etWindowLongPtr(... GWLP_USERDATA ...), possibly eliminating
4875 * the dTHX calls here. */
4876 /* XXX For now it is assumed that the overhead of the dTHX; for what
4877 * are relativley infrequent code-paths, is better than the added
4878 * complexity of getting the correct context passed into
4879 * win32_create_message_window() */
4884 case WM_USER_MESSAGE: {
4885 long child = find_pseudo_pid((int)wParam);
4888 w32_pseudo_child_message_hwnds[child] = (HWND)lParam;
4895 case WM_USER_KILL: {
4897 /* We use WM_USER_KILL to fake kill() with other signals */
4898 int sig = (int)wParam;
4899 if (do_raise(aTHX_ sig))
4900 sig_terminate(aTHX_ sig);
4907 /* alarm() is a one-shot but SetTimer() repeats so kill it */
4908 if (w32_timerid && w32_timerid==(UINT)wParam) {
4909 KillTimer(w32_message_hwnd, w32_timerid);
4912 /* Now fake a call to signal handler */
4913 if (do_raise(aTHX_ 14))
4914 sig_terminate(aTHX_ 14);
4926 /* Above or other stuff may have set a signal flag, and we may not have
4927 * been called from win32_async_check() (e.g. some other GUI's message
4928 * loop. BUT DON'T dispatch signals here: If someone has set a SIGALRM
4929 * handler that die's, and the message loop that calls here is wrapped
4930 * in an eval, then you may well end up with orphaned windows - signals
4931 * are dispatched by win32_async_check() */
4937 win32_create_message_window_class()
4939 /* create the window class for "message only" windows */
4943 wc.lpfnWndProc = win32_message_window_proc;
4944 wc.hInstance = (HINSTANCE)GetModuleHandle(NULL);
4945 wc.lpszClassName = "PerlMessageWindowClass";
4947 /* second and subsequent calls will fail, but class
4948 * will already be registered */
4953 win32_create_message_window()
4957 /* "message-only" windows have been implemented in Windows 2000 and later.
4958 * On earlier versions we'll continue to post messages to a specific
4959 * thread and use hwnd==NULL. This is brittle when either an embedding
4960 * application or an XS module is also posting messages to hwnd=NULL
4961 * because once removed from the queue they cannot be delivered to the
4962 * "right" place with DispatchMessage() anymore, as there is no WindowProc
4963 * if there is no window handle.
4965 /* Using HWND_MESSAGE appears to work under Win98, despite MSDN
4966 * documentation to the contrary, however, there is some evidence that
4967 * there may be problems with the implementation on Win98. As it is not
4968 * officially supported we take the cautious route and stick with thread
4969 * messages (hwnd == NULL) on platforms prior to Win2k.
4972 win32_create_message_window_class();
4974 hwnd = CreateWindow("PerlMessageWindowClass", "PerlMessageWindow",
4975 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
4978 /* If we din't create a window for any reason, then we'll use thread
4979 * messages for our signalling, so we install a hook which
4980 * is called by CallMsgFilter in win32_async_check(), or any other
4981 * modal loop (e.g. Win32::MsgBox or any other GUI extention, or anything
4982 * that use OLE, etc. */
4984 SetWindowsHookEx(WH_MSGFILTER, win32_message_filter_proc,
4985 NULL, GetCurrentThreadId());
4991 #ifdef HAVE_INTERP_INTERN
4994 win32_csighandler(int sig)
4997 dTHXa(PERL_GET_SIG_CONTEXT);
4998 Perl_warn(aTHX_ "Got signal %d",sig);
5003 #if defined(__MINGW32__) && defined(__cplusplus)
5004 #define CAST_HWND__(x) (HWND__*)(x)
5006 #define CAST_HWND__(x) x
5010 Perl_sys_intern_init(pTHX)
5014 w32_perlshell_tokens = NULL;
5015 w32_perlshell_vec = (char**)NULL;
5016 w32_perlshell_items = 0;
5017 w32_fdpid = newAV();
5018 Newx(w32_children, 1, child_tab);
5019 w32_num_children = 0;
5020 # ifdef USE_ITHREADS
5022 Newx(w32_pseudo_children, 1, pseudo_child_tab);
5023 w32_num_pseudo_children = 0;
5026 w32_message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
5028 for (i=0; i < SIG_SIZE; i++) {
5029 w32_sighandler[i] = SIG_DFL;
5031 # ifdef MULTIPLICITY
5032 if (my_perl == PL_curinterp) {
5036 /* Force C runtime signal stuff to set its console handler */
5037 signal(SIGINT,win32_csighandler);
5038 signal(SIGBREAK,win32_csighandler);
5040 /* We spawn asynchronous processes with the CREATE_NEW_PROCESS_GROUP
5041 * flag. This has the side-effect of disabling Ctrl-C events in all
5042 * processes in this group. At least on Windows NT and later we
5043 * can re-enable Ctrl-C handling by calling SetConsoleCtrlHandler()
5044 * with a NULL handler. This is not valid on Windows 9X.
5047 SetConsoleCtrlHandler(NULL,FALSE);
5049 /* Push our handler on top */
5050 SetConsoleCtrlHandler(win32_ctrlhandler,TRUE);
5055 Perl_sys_intern_clear(pTHX)
5057 Safefree(w32_perlshell_tokens);
5058 Safefree(w32_perlshell_vec);
5059 /* NOTE: w32_fdpid is freed by sv_clean_all() */
5060 Safefree(w32_children);
5062 KillTimer(w32_message_hwnd, w32_timerid);
5065 if (w32_message_hwnd != NULL && w32_message_hwnd != INVALID_HANDLE_VALUE)
5066 DestroyWindow(w32_message_hwnd);
5067 # ifdef MULTIPLICITY
5068 if (my_perl == PL_curinterp) {
5072 SetConsoleCtrlHandler(win32_ctrlhandler,FALSE);
5074 # ifdef USE_ITHREADS
5075 Safefree(w32_pseudo_children);
5079 # ifdef USE_ITHREADS
5082 Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
5084 dst->perlshell_tokens = NULL;
5085 dst->perlshell_vec = (char**)NULL;
5086 dst->perlshell_items = 0;
5087 dst->fdpid = newAV();
5088 Newxz(dst->children, 1, child_tab);
5090 Newxz(dst->pseudo_children, 1, pseudo_child_tab);
5092 dst->message_hwnd = CAST_HWND__(INVALID_HANDLE_VALUE);
5093 dst->poll_count = 0;
5094 Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
5096 # endif /* USE_ITHREADS */
5097 #endif /* HAVE_INTERP_INTERN */