This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
added tainting for getcwd for Win32
[perl5.git] / win32 / win32.c
index 9fc83c1..eacb248 100644 (file)
@@ -91,13 +91,6 @@ int _fcloseall();
 #  define getlogin g_getlogin
 #endif
 
-#if defined(PERL_OBJECT)
-#  undef do_aspawn
-#  define do_aspawn g_do_aspawn
-#  undef Perl_do_exec
-#  define Perl_do_exec g_do_exec
-#endif
-
 static void            get_shell(void);
 static long            tokenize(const char *str, char **dest, char ***destv);
        int             do_spawn2(char *cmd, int exectype);
@@ -179,7 +172,7 @@ get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
        if (retval == ERROR_SUCCESS
            && (type == REG_SZ || type == REG_EXPAND_SZ))
        {
-           dTHXo;
+           dTHX;
            if (!*svp)
                *svp = sv_2mortal(newSVpvn("",0));
            SvGROW(*svp, datalen);
@@ -259,7 +252,7 @@ get_emd_part(SV **prev_pathp, char *trailing_path, ...)
     /* only add directory if it exists */
     if (GetFileAttributes(mod_name) != (DWORD) -1) {
        /* directory exists */
-       dTHXo;
+       dTHX;
        if (!*prev_pathp)
            *prev_pathp = sv_2mortal(newSVpvn("",0));
        sv_catpvn(*prev_pathp, ";", 1);
@@ -273,7 +266,7 @@ get_emd_part(SV **prev_pathp, char *trailing_path, ...)
 char *
 win32_get_privlib(const char *pl)
 {
-    dTHXo;
+    dTHX;
     char *stdlib = "lib";
     char buffer[MAX_PATH+1];
     SV *sv = Nullsv;
@@ -290,7 +283,7 @@ win32_get_privlib(const char *pl)
 static char *
 win32_get_xlib(const char *pl, const char *xlib, const char *libname)
 {
-    dTHXo;
+    dTHX;
     char regstr[40];
     char pathstr[MAX_PATH+1];
     DWORD datalen;
@@ -438,7 +431,7 @@ win32_getpid(void)
 {
     int pid;
 #ifdef USE_ITHREADS
-    dTHXo;
+    dTHX;
     if (w32_pseudo_id)
        return -((int)w32_pseudo_id);
 #endif
@@ -464,7 +457,7 @@ tokenize(const char *str, char **dest, char ***destv)
     char **retvstart = 0;
     int items = -1;
     if (str) {
-       dTHXo;
+       dTHX;
        int slen = strlen(str);
        register char *ret;
        register char **retv;
@@ -507,7 +500,7 @@ tokenize(const char *str, char **dest, char ***destv)
 static void
 get_shell(void)
 {
-    dTHXo;
+    dTHX;
     if (!w32_perlshell_tokens) {
        /* we don't use COMSPEC here for two reasons:
         *  1. the same reason perl on UNIX doesn't use SHELL--rampant and
@@ -518,7 +511,7 @@ get_shell(void)
         */
        const char* defaultshell = (IsWinNT()
                                    ? "cmd.exe /x/c" : "command.com /c");
-       const char *usershell = getenv("PERL5SHELL");
+       const char *usershell = PerlEnv_getenv("PERL5SHELL");
        w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
                                       &w32_perlshell_tokens,
                                       &w32_perlshell_vec);
@@ -528,7 +521,7 @@ get_shell(void)
 int
 do_aspawn(void *vreally, void **vmark, void **vsp)
 {
-    dTHXo;
+    dTHX;
     SV *really = (SV*)vreally;
     SV **mark = (SV**)vmark;
     SV **sp = (SV**)vsp;
@@ -581,7 +574,6 @@ do_aspawn(void *vreally, void **vmark, void **vsp)
     }
     else {
        if (status < 0) {
-           dTHR;
            if (ckWARN(WARN_EXEC))
                Perl_warner(aTHX_ WARN_EXEC, "Can't spawn \"%s\": %s", argv[0], strerror(errno));
            status = 255 * 256;
@@ -597,7 +589,7 @@ do_aspawn(void *vreally, void **vmark, void **vsp)
 int
 do_spawn2(char *cmd, int exectype)
 {
-    dTHXo;
+    dTHX;
     char **a;
     char *s;
     char **argv;
@@ -674,7 +666,6 @@ do_spawn2(char *cmd, int exectype)
     }
     else {
        if (status < 0) {
-           dTHR;
            if (ckWARN(WARN_EXEC))
                Perl_warner(aTHX_ WARN_EXEC, "Can't %s \"%s\": %s",
                     (exectype == EXECF_EXEC ? "exec" : "spawn"),
@@ -714,7 +705,7 @@ Perl_do_exec(pTHX_ char *cmd)
 DllExport DIR *
 win32_opendir(char *filename)
 {
-    dTHXo;
+    dTHX;
     DIR                        *dirp;
     long               len;
     long               idx;
@@ -826,7 +817,7 @@ win32_readdir(DIR *dirp)
        /* Now set up for the next call to readdir */
        dirp->curr += len + 1;
        if (dirp->curr >= dirp->end) {
-           dTHXo;
+           dTHX;
            char*               ptr;
            BOOL                res;
            WIN32_FIND_DATAW    wFindData;
@@ -852,7 +843,7 @@ win32_readdir(DIR *dirp)
                long endpos = dirp->end - dirp->start;
                long newsize = endpos + strlen(ptr) + 1;
                /* bump the string table size by enough for the
-                * new name and it's null terminator */
+                * new name and its null terminator */
                while (newsize > dirp->size) {
                    long curpos = dirp->curr - dirp->start;
                    dirp->size *= 2;
@@ -900,7 +891,7 @@ win32_rewinddir(DIR *dirp)
 DllExport int
 win32_closedir(DIR *dirp)
 {
-    dTHXo;
+    dTHX;
     if (dirp->handle != INVALID_HANDLE_VALUE)
        FindClose(dirp->handle);
     Safefree(dirp->start);
@@ -962,7 +953,7 @@ setgid(gid_t agid)
 char *
 getlogin(void)
 {
-    dTHXo;
+    dTHX;
     char *buf = w32_getlogin_buffer;
     DWORD size = sizeof(w32_getlogin_buffer);
     if (GetUserName(buf,&size))
@@ -977,10 +968,35 @@ chown(const char *path, uid_t owner, gid_t group)
     return 0;
 }
 
+/*
+ * XXX this needs strengthening  (for PerlIO)
+ *   -- BKS, 11-11-200
+*/
+int mkstemp(const char *path)
+{
+    dTHX;
+    char buf[MAX_PATH+1];
+    int i = 0, fd = -1;
+
+retry:
+    if (i++ > 10) { /* give up */
+       errno = ENOENT;
+       return -1;
+    }
+    if (!GetTempFileNameA((LPCSTR)path, "plr", 1, buf)) {
+       errno = ENOENT;
+       return -1;
+    }
+    fd = PerlLIO_open3(buf, O_CREAT|O_RDWR|O_EXCL, 0600);
+    if (fd == -1)
+       goto retry;
+    return fd;
+}
+
 static long
 find_pid(int pid)
 {
-    dTHXo;
+    dTHX;
     long child = w32_num_children;
     while (--child >= 0) {
        if (w32_child_pids[child] == pid)
@@ -993,7 +1009,7 @@ static void
 remove_dead_process(long child)
 {
     if (child >= 0) {
-       dTHXo;
+       dTHX;
        CloseHandle(w32_child_handles[child]);
        Move(&w32_child_handles[child+1], &w32_child_handles[child],
             (w32_num_children-child-1), HANDLE);
@@ -1007,7 +1023,7 @@ remove_dead_process(long child)
 static long
 find_pseudo_pid(int pid)
 {
-    dTHXo;
+    dTHX;
     long child = w32_num_pseudo_children;
     while (--child >= 0) {
        if (w32_pseudo_child_pids[child] == pid)
@@ -1020,7 +1036,7 @@ static void
 remove_dead_pseudo_process(long child)
 {
     if (child >= 0) {
-       dTHXo;
+       dTHX;
        CloseHandle(w32_pseudo_child_handles[child]);
        Move(&w32_pseudo_child_handles[child+1], &w32_pseudo_child_handles[child],
             (w32_num_pseudo_children-child-1), HANDLE);
@@ -1034,7 +1050,7 @@ remove_dead_pseudo_process(long child)
 DllExport int
 win32_kill(int pid, int sig)
 {
-    dTHXo;
+    dTHX;
     HANDLE hProcess;
     long child;
 #ifdef USE_ITHREADS
@@ -1100,7 +1116,7 @@ win32_sleep(unsigned int t)
 DllExport int
 win32_stat(const char *path, struct stat *sbuf)
 {
-    dTHXo;
+    dTHX;
     char       buffer[MAX_PATH+1]; 
     int                l = strlen(path);
     int                res;
@@ -1299,12 +1315,10 @@ win32_longpath(char *path)
     return path;
 }
 
-#ifndef USE_WIN32_RTL_ENV
-
 DllExport char *
 win32_getenv(const char *name)
 {
-    dTHXo;
+    dTHX;
     WCHAR wBuffer[MAX_PATH+1];
     DWORD needlen;
     SV *curitem = Nullsv;
@@ -1353,7 +1367,7 @@ win32_getenv(const char *name)
 DllExport int
 win32_putenv(const char *name)
 {
-    dTHXo;
+    dTHX;
     char* curitem;
     char* val;
     WCHAR* wCuritem;
@@ -1402,8 +1416,6 @@ win32_putenv(const char *name)
     return relval;
 }
 
-#endif
-
 static long
 filetime_to_clock(PFILETIME ft)
 {
@@ -1464,7 +1476,7 @@ filetime_from_time(PFILETIME pFileTime, time_t Time)
 DllExport int
 win32_unlink(const char *filename)
 {
-    dTHXo;
+    dTHX;
     int ret;
     DWORD attrs;
 
@@ -1509,7 +1521,7 @@ fail:
 DllExport int
 win32_utime(const char *filename, struct utimbuf *times)
 {
-    dTHXo;
+    dTHX;
     HANDLE handle;
     FILETIME ftCreate;
     FILETIME ftAccess;
@@ -1633,7 +1645,8 @@ win32_uname(struct utsname *name)
        char *arch;
        GetSystemInfo(&info);
 
-#if defined(__BORLANDC__) || defined(__MINGW32__)
+#if (defined(__BORLANDC__)&&(__BORLANDC__<=0x520)) \
+ || (defined(__MINGW32__) && !defined(_ANONYMOUS_UNION))
        switch (info.u.s.wProcessorArchitecture) {
 #else
        switch (info.wProcessorArchitecture) {
@@ -1657,7 +1670,7 @@ win32_uname(struct utsname *name)
 DllExport int
 win32_waitpid(int pid, int *status, int flags)
 {
-    dTHXo;
+    dTHX;
     DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
     int retval = -1;
     long child;
@@ -1741,7 +1754,7 @@ win32_wait(int *status)
     /* XXX this wait emulation only knows about processes
      * spawned via win32_spawnvp(P_NOWAIT, ...).
      */
-    dTHXo;
+    dTHX;
     int i, retval;
     DWORD exitcode, waitcode;
 
@@ -1796,23 +1809,19 @@ FAILED:
     return -1;
 }
 
-#ifndef PERL_OBJECT
-
 static UINT timerid = 0;
 
 static VOID CALLBACK TimerProc(HWND win, UINT msg, UINT id, DWORD time)
 {
-    dTHXo;
+    dTHX;
     KillTimer(NULL,timerid);
     timerid=0;  
     CALL_FPTR(PL_sighandlerp)(14);
 }
-#endif /* !PERL_OBJECT */
 
 DllExport unsigned int
 win32_alarm(unsigned int sec)
 {
-#ifndef PERL_OBJECT
     /* 
      * the 'obvious' implentation is SetTimer() with a callback
      * which does whatever receiving SIGALRM would do 
@@ -1822,7 +1831,7 @@ win32_alarm(unsigned int sec)
      * Snag is unless something is looking at the message queue
      * nothing happens :-(
      */ 
-    dTHXo;
+    dTHX;
     if (sec)
      {
       timerid = SetTimer(NULL,timerid,sec*1000,(TIMERPROC)TimerProc);
@@ -1837,7 +1846,6 @@ win32_alarm(unsigned int sec)
         timerid=0;  
        }
      }
-#endif /* !PERL_OBJECT */
     return 0;
 }
 
@@ -1848,9 +1856,8 @@ extern char *     des_fcrypt(const char *txt, const char *salt, char *cbuf);
 DllExport char *
 win32_crypt(const char *txt, const char *salt)
 {
-    dTHXo;
+    dTHX;
 #ifdef HAVE_DES_FCRYPT
-    dTHR;
     return des_fcrypt(txt, salt, w32_crypt_buffer);
 #else
     Perl_croak(aTHX_ "The crypt() function is unimplemented due to excessive paranoia.");
@@ -1858,53 +1865,6 @@ win32_crypt(const char *txt, const char *salt)
 #endif
 }
 
-/* C doesn't like repeat struct definitions */
-
-#if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX)
-
-#ifndef _CRTIMP
-#define _CRTIMP __declspec(dllimport)
-#endif
-
-/*
- * Control structure for lowio file handles
- */
-typedef struct {
-    long osfhnd;    /* underlying OS file HANDLE */
-    char osfile;    /* attributes of file (e.g., open in text mode?) */
-    char pipech;    /* one char buffer for handles opened on pipes */
-    int lockinitflag;
-    CRITICAL_SECTION lock;
-} ioinfo;
-
-
-/*
- * Array of arrays of control structures for lowio files.
- */
-EXTERN_C _CRTIMP ioinfo* __pioinfo[];
-
-/*
- * Definition of IOINFO_L2E, the log base 2 of the number of elements in each
- * array of ioinfo structs.
- */
-#define IOINFO_L2E         5
-
-/*
- * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array
- */
-#define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
-
-/*
- * Access macros for getting at an ioinfo struct and its fields from a
- * file handle
- */
-#define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)))
-#define _osfhnd(i)  (_pioinfo(i)->osfhnd)
-#define _osfile(i)  (_pioinfo(i)->osfile)
-#define _pipech(i)  (_pioinfo(i)->pipech)
-
-#endif
-
 #ifdef USE_FIXED_OSFHANDLE
 
 #define FOPEN                  0x01    /* file handle open */
@@ -1943,10 +1903,6 @@ EXTERN_C _CRTIMP ioinfo* __pioinfo[];
  *     -- BKS, 1-23-2000
 */
 
-/* since we are not doing a dup2(), this works fine */
-
-#define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = osfh)
-
 /* create an ioinfo entry, kill its handle, and steal the entry */
 
 static int
@@ -2012,7 +1968,7 @@ win32_flock(int fd, int oper)
     HANDLE fh;
 
     if (!IsWinNT()) {
-       dTHXo;
+       dTHX;
        Perl_croak_nocontext("flock() unimplemented on this platform");
        return -1;
     }
@@ -2105,13 +2061,13 @@ win32_feof(FILE *fp)
 DllExport char *
 win32_strerror(int e) 
 {
-#ifndef __BORLANDC__           /* Borland intolerance */
+#if !defined __BORLANDC__ && !defined __MINGW32__      /* compiler intolerance */
     extern int sys_nerr;
 #endif
     DWORD source = 0;
 
     if (e < 0 || e > sys_nerr) {
-        dTHXo;
+        dTHX;
        if (e < 0)
            e = GetLastError();
 
@@ -2151,13 +2107,12 @@ win32_str_os_error(void *sv, DWORD dwErr)
                            dwErr, GetLastError());
     }
     if (sMsg) {
-       dTHXo;
+       dTHX;
        sv_setpvn((SV*)sv, sMsg, dwLen);
        LocalFree(sMsg);
     }
 }
 
-
 DllExport int
 win32_fprintf(FILE *fp, const char *format, ...)
 {
@@ -2205,7 +2160,7 @@ win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
 DllExport FILE *
 win32_fopen(const char *filename, const char *mode)
 {
-    dTHXo;
+    dTHX;
     WCHAR wMode[MODE_SIZE], wBuffer[MAX_PATH+1];
     FILE *f;
     
@@ -2236,7 +2191,7 @@ win32_fopen(const char *filename, const char *mode)
 DllExport FILE *
 win32_fdopen(int handle, const char *mode)
 {
-    dTHXo;
+    dTHX;
     WCHAR wMode[MODE_SIZE];
     FILE *f;
     if (USING_WIDE()) {
@@ -2254,7 +2209,7 @@ win32_fdopen(int handle, const char *mode)
 DllExport FILE *
 win32_freopen(const char *path, const char *mode, FILE *stream)
 {
-    dTHXo;
+    dTHX;
     WCHAR wMode[MODE_SIZE], wBuffer[MAX_PATH+1];
     if (stricmp(path, "/dev/null")==0)
        path = "NUL";
@@ -2363,7 +2318,25 @@ win32_abort(void)
 DllExport int
 win32_fstat(int fd,struct stat *sbufptr)
 {
-    return fstat(fd,sbufptr);
+#ifdef __BORLANDC__
+    /* A file designated by filehandle is not shown as accessible
+     * for write operations, probably because it is opened for reading.
+     * --Vadim Konovalov
+     */ 
+    int rc = fstat(fd,sbufptr);
+    BY_HANDLE_FILE_INFORMATION bhfi;
+    if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &bhfi)) {
+        sbufptr->st_mode &= 0xFE00;
+        if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+            sbufptr->st_mode |= (S_IREAD + (S_IREAD >> 3) + (S_IREAD >> 6));
+        else
+            sbufptr->st_mode |= ((S_IREAD|S_IWRITE) + ((S_IREAD|S_IWRITE) >> 3)
+              + ((S_IREAD|S_IWRITE) >> 6));
+    }
+    return rc;
+#else
+    return my_fstat(fd,sbufptr);
+#endif
 }
 
 DllExport int
@@ -2372,11 +2345,21 @@ win32_pipe(int *pfd, unsigned int size, int mode)
     return _pipe(pfd, size, mode);
 }
 
+DllExport PerlIO*
+win32_popenlist(const char *mode, IV narg, SV **args)
+{
+ dTHX;
+ Perl_croak(aTHX_ "List form of pipe open not implemented");
+ return NULL;
+}
+
 /*
  * a popen() clone that respects PERL5SHELL
+ *
+ * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
  */
 
-DllExport FILE*
+DllExport PerlIO*
 win32_popen(const char *command, const char *mode)
 {
 #ifdef USE_RTL_POPEN
@@ -2430,7 +2413,7 @@ win32_popen(const char *command, const char *mode)
 
     /* start the child */
     {
-       dTHXo;
+       dTHX;
        if ((childpid = do_spawn_nowait((char*)command)) == -1)
            goto cleanup;
 
@@ -2450,7 +2433,7 @@ win32_popen(const char *command, const char *mode)
     }
 
     /* we have an fd, return a file stream */
-    return (win32_fdopen(p[parent], (char *)mode));
+    return (PerlIO_fdopen(p[parent], (char *)mode));
 
 cleanup:
     /* we don't need to check for errors here */
@@ -2470,17 +2453,17 @@ cleanup:
  */
 
 DllExport int
-win32_pclose(FILE *pf)
+win32_pclose(PerlIO *pf)
 {
 #ifdef USE_RTL_POPEN
     return _pclose(pf);
 #else
-    dTHXo;
+    dTHX;
     int childpid, status;
     SV *sv;
 
     LOCK_FDPID_MUTEX;
-    sv = *av_fetch(w32_fdpid, win32_fileno(pf), TRUE);
+    sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
 
     if (SvIOK(sv))
        childpid = SvIVX(sv);
@@ -2492,7 +2475,11 @@ win32_pclose(FILE *pf)
         return -1;
     }
 
-    win32_fclose(pf);
+#ifdef USE_PERLIO
+    PerlIO_close(pf);
+#else
+    fclose(pf);
+#endif
     SvIVX(sv) = 0;
     UNLOCK_FDPID_MUTEX;
 
@@ -2541,7 +2528,8 @@ Nt4CreateHardLinkW(
     StreamId.dwStreamId = BACKUP_LINK;
     StreamId.dwStreamAttributes = 0;
     StreamId.dwStreamNameSize = 0;
-#if defined(__BORLANDC__) || defined(__MINGW32__)
+#if defined(__BORLANDC__) \
+ ||(defined(__MINGW32__) && !defined(_ANONYMOUS_UNION))
     StreamId.Size.u.HighPart = 0;
     StreamId.Size.u.LowPart = dwLen;
 #else
@@ -2564,7 +2552,7 @@ Nt4CreateHardLinkW(
 DllExport int
 win32_link(const char *oldname, const char *newname)
 {
-    dTHXo;
+    dTHX;
     BOOL (__stdcall *pfnCreateHardLinkW)(LPCWSTR,LPCWSTR,LPSECURITY_ATTRIBUTES);
     WCHAR wOldName[MAX_PATH+1];
     WCHAR wNewName[MAX_PATH+1];
@@ -2597,7 +2585,7 @@ win32_rename(const char *oname, const char *newname)
     char szOldName[MAX_PATH+1];
     char szNewName[MAX_PATH+1];
     BOOL bResult;
-    dTHXo;
+    dTHX;
 
     /* XXX despite what the documentation says about MoveFileEx(),
      * it doesn't work under Windows95!
@@ -2735,7 +2723,7 @@ win32_tell(int fd)
 DllExport int
 win32_open(const char *path, int flag, ...)
 {
-    dTHXo;
+    dTHX;
     va_list ap;
     int pmode;
     WCHAR wBuffer[MAX_PATH+1];
@@ -2754,10 +2742,13 @@ win32_open(const char *path, int flag, ...)
     return open(PerlDir_mapA(path), flag, pmode);
 }
 
+/* close() that understands socket */
+extern int my_close(int);      /* in win32sck.c */
+
 DllExport int
 win32_close(int fd)
 {
-    return close(fd);
+    return my_close(fd);
 }
 
 DllExport int
@@ -2993,7 +2984,7 @@ win32_write(int fd, const void *buf, unsigned int cnt)
 DllExport int
 win32_mkdir(const char *dir, int mode)
 {
-    dTHXo;
+    dTHX;
     if (USING_WIDE()) {
        WCHAR wBuffer[MAX_PATH+1];
        A2WHELPER(dir, wBuffer, sizeof(wBuffer));
@@ -3005,7 +2996,7 @@ win32_mkdir(const char *dir, int mode)
 DllExport int
 win32_rmdir(const char *dir)
 {
-    dTHXo;
+    dTHX;
     if (USING_WIDE()) {
        WCHAR wBuffer[MAX_PATH+1];
        A2WHELPER(dir, wBuffer, sizeof(wBuffer));
@@ -3017,7 +3008,7 @@ win32_rmdir(const char *dir)
 DllExport int
 win32_chdir(const char *dir)
 {
-    dTHXo;
+    dTHX;
     if (USING_WIDE()) {
        WCHAR wBuffer[MAX_PATH+1];
        A2WHELPER(dir, wBuffer, sizeof(wBuffer));
@@ -3029,7 +3020,7 @@ win32_chdir(const char *dir)
 DllExport  int
 win32_access(const char *path, int mode)
 {
-    dTHXo;
+    dTHX;
     if (USING_WIDE()) {
        WCHAR wBuffer[MAX_PATH+1];
        A2WHELPER(path, wBuffer, sizeof(wBuffer));
@@ -3041,7 +3032,7 @@ win32_access(const char *path, int mode)
 DllExport  int
 win32_chmod(const char *path, int mode)
 {
-    dTHXo;
+    dTHX;
     if (USING_WIDE()) {
        WCHAR wBuffer[MAX_PATH+1];
        A2WHELPER(path, wBuffer, sizeof(wBuffer));
@@ -3054,7 +3045,7 @@ win32_chmod(const char *path, int mode)
 static char *
 create_command_line(const char* command, const char * const *args)
 {
-    dTHXo;
+    dTHX;
     int index;
     char *cmd, *ptr, *arg;
     STRLEN len = strlen(command) + 1;
@@ -3078,7 +3069,7 @@ create_command_line(const char* command, const char * const *args)
 static char *
 qualified_path(const char *cmd)
 {
-    dTHXo;
+    dTHX;
     char *pathstr;
     char *fullcmd, *curfullcmd;
     STRLEN cmdlen = 0;
@@ -3095,7 +3086,7 @@ qualified_path(const char *cmd)
     }
 
     /* look in PATH */
-    pathstr = win32_getenv("PATH");
+    pathstr = PerlEnv_getenv("PATH");
     New(0, fullcmd, MAX_PATH+1, char);
     curfullcmd = fullcmd;
 
@@ -3183,7 +3174,7 @@ free_childenv(void* d)
 char*
 get_childdir(void)
 {
-    dTHXo;
+    dTHX;
     char* ptr;
     char szfilename[(MAX_PATH+1)*2];
     if (USING_WIDE()) {
@@ -3203,7 +3194,7 @@ get_childdir(void)
 void
 free_childdir(char* d)
 {
-    dTHXo;
+    dTHX;
     Safefree(d);
 }
 
@@ -3225,7 +3216,7 @@ win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
 #ifdef USE_RTL_SPAWNVP
     return spawnvp(mode, cmdname, (char * const *)argv);
 #else
-    dTHXo;
+    dTHX;
     int ret;
     void* env;
     char* dir;
@@ -3345,7 +3336,7 @@ DllExport int
 win32_execv(const char *cmdname, const char *const *argv)
 {
 #ifdef USE_ITHREADS
-    dTHXo;
+    dTHX;
     /* if this is a pseudo-forked child, we just want to spawn
      * the new program, and return */
     if (w32_pseudo_id)
@@ -3358,11 +3349,18 @@ DllExport int
 win32_execvp(const char *cmdname, const char *const *argv)
 {
 #ifdef USE_ITHREADS
-    dTHXo;
+    dTHX;
     /* if this is a pseudo-forked child, we just want to spawn
      * the new program, and return */
-    if (w32_pseudo_id)
-       return win32_spawnvp(P_WAIT, cmdname, (char *const *)argv);
+    if (w32_pseudo_id) {
+       int status = win32_spawnvp(P_WAIT, cmdname, (char *const *)argv);
+       if (status != -1) {
+           my_exit(status);
+           return 0;
+       }
+       else
+           return status;
+    }
 #endif
     return execvp(cmdname, (char *const *)argv);
 }
@@ -3562,8 +3560,27 @@ win32_get_osfhandle(int fd)
 DllExport void*
 win32_dynaload(const char* filename)
 {
-    dTHXo;
+    dTHX;
     HMODULE hModule;
+    char buf[MAX_PATH+1];
+    char *first;
+
+    /* LoadLibrary() doesn't recognize forward slashes correctly,
+     * so turn 'em back. */
+    first = strchr(filename, '/');
+    if (first) {
+       STRLEN len = strlen(filename);
+       if (len <= MAX_PATH) {
+           strcpy(buf, filename);
+           filename = &buf[first - filename];
+           while (*filename) {
+               if (*filename == '/')
+                   *(char*)filename = '\\';
+               ++filename;
+           }
+           filename = buf;
+       }
+    }
     if (USING_WIDE()) {
        WCHAR wfilename[MAX_PATH+1];
        A2WHELPER(filename, wfilename, sizeof(wfilename));
@@ -3595,6 +3612,10 @@ XS(w32_GetCwd)
        sv_setpv(sv, ptr);
        PerlEnv_free_childdir(ptr);
 
+#ifndef INCOMPLETE_TAINTS
+       SvTAINTED_on(sv);
+#endif
+
        EXTEND(SP,1);
        SvPOK_on(sv);
        ST(0) = sv;
@@ -3852,6 +3873,8 @@ XS(w32_Spawn)
 {
     dXSARGS;
     char *cmd, *args;
+    void *env;
+    char *dir;
     PROCESS_INFORMATION stProcInfo;
     STARTUPINFO stStartInfo;
     BOOL bSuccess = FALSE;
@@ -3862,6 +3885,9 @@ XS(w32_Spawn)
     cmd = SvPV_nolen(ST(0));
     args = SvPV_nolen(ST(1));
 
+    env = PerlEnv_get_childenv();
+    dir = PerlEnv_get_childdir();
+
     memset(&stStartInfo, 0, sizeof(stStartInfo));   /* Clear the block */
     stStartInfo.cb = sizeof(stStartInfo);          /* Set the structure size */
     stStartInfo.dwFlags = STARTF_USESHOWWINDOW;            /* Enable wShowWindow control */
@@ -3874,8 +3900,8 @@ XS(w32_Spawn)
                NULL,                   /* Default thread security */
                FALSE,                  /* Must be TRUE to use std handles */
                NORMAL_PRIORITY_CLASS,  /* No special scheduling */
-               NULL,                   /* Inherit our environment block */
-               NULL,                   /* Inherit our currrent directory */
+               env,                    /* Inherit our environment block */
+               dir,                    /* Inherit our currrent directory */
                &stStartInfo,           /* -> Startup info */
                &stProcInfo))           /* <- Process info (if OK) */
     {
@@ -3886,6 +3912,8 @@ XS(w32_Spawn)
        CloseHandle(stProcInfo.hThread);/* library source code does this. */
        bSuccess = TRUE;
     }
+    PerlEnv_free_childenv(env);
+    PerlEnv_free_childdir(dir);
     XSRETURN_IV(bSuccess);
 }
 
@@ -4029,7 +4057,7 @@ XS(w32_CopyFile)
 void
 Perl_init_os_extras(void)
 {
-    dTHXo;
+    dTHX;
     char *file = __FILE__;
     dXSUB_SYS;
 
@@ -4092,16 +4120,6 @@ win32_get_child_IO(child_IO_table* ptbl)
 
 #ifdef HAVE_INTERP_INTERN
 
-#  ifdef PERL_OBJECT
-#    undef Perl_sys_intern_init
-#    define Perl_sys_intern_init CPerlObj::Perl_sys_intern_init
-#    undef Perl_sys_intern_dup
-#    define Perl_sys_intern_dup CPerlObj::Perl_sys_intern_dup
-#    undef Perl_sys_intern_clear
-#    define Perl_sys_intern_clear CPerlObj::Perl_sys_intern_clear
-#    define pPerl this
-#  endif
-
 void
 Perl_sys_intern_init(pTHX)
 {
@@ -4143,18 +4161,13 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
     Newz(1313, dst->children, 1, child_tab);
     dst->pseudo_id             = 0;
     Newz(1313, dst->pseudo_children, 1, child_tab);
-    dst->thr_intern.Winit_socktype = src->thr_intern.Winit_socktype;
+    dst->thr_intern.Winit_socktype = 0;
 }
 #  endif /* USE_ITHREADS */
 #endif /* HAVE_INTERP_INTERN */
 
-#ifdef PERL_OBJECT
-#  undef this
-#  define this pPerl
-#endif
-
 static void
-win32_free_argvw(pTHXo_ void *ptr)
+win32_free_argvw(pTHX_ void *ptr)
 {
     char** argv = (char**)ptr;
     while(*argv) {
@@ -4166,7 +4179,7 @@ win32_free_argvw(pTHXo_ void *ptr)
 void
 win32_argv2utf8(int argc, char** argv)
 {
-    dTHXo;
+    dTHX;
     char* psz;
     int length, wargc;
     LPWSTR* lpwStr = CommandLineToArgvW(GetCommandLineW(), &wargc);