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.
11 #define WIN32_LEAN_AND_MEAN
12 #define WIN32IO_IS_STDIO
19 /* #include "config.h" */
21 #define PERLIO_NOT_STDIO 0
22 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
32 /* assert.h conflicts with #define of assert in perl.h */
40 /* Mingw32 defaults to globing command line
41 * So we turn it off like this:
48 #define EXECF_SPAWN_NOWAIT 3
50 static DWORD IdOS(void);
52 BOOL ProbeEnv = FALSE;
53 DWORD Win32System = (DWORD)-1;
54 char szShellPath[MAX_PATH+1];
55 char szPerlLibRoot[MAX_PATH+1];
56 HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
59 # ifdef USE_DECLSPEC_THREAD
60 __declspec(thread) char strerror_buffer[512];
61 __declspec(thread) char getlogin_buffer[128];
62 # ifdef HAVE_DES_FCRYPT
63 __declspec(thread) char crypt_buffer[30];
66 # define strerror_buffer (thr->i.Wstrerror_buffer)
67 # define getlogin_buffer (thr->i.Wgetlogin_buffer)
68 # define crypt_buffer (thr->i.Wcrypt_buffer)
71 char strerror_buffer[512];
72 char getlogin_buffer[128];
73 # ifdef HAVE_DES_FCRYPT
74 char crypt_buffer[30];
78 static int do_spawn2(char *cmd, int exectype);
82 return (IdOS() == VER_PLATFORM_WIN32_WINDOWS);
87 return (IdOS() == VER_PLATFORM_WIN32_NT);
91 win32PerlLibPath(char *sfx,...)
96 GetModuleFileName((PerlDllHandle == INVALID_HANDLE_VALUE)
97 ? GetModuleHandle(NULL)
100 sizeof(szPerlLibRoot));
101 *(end = strrchr(szPerlLibRoot, '\\')) = '\0';
102 if (stricmp(end-4,"\\bin") == 0)
109 sfx = va_arg(ap,char *);
112 return (szPerlLibRoot);
117 HasRedirection(char *ptr)
123 * Scan string looking for redirection (< or >) or pipe
124 * characters (|) that are not in a quoted string
154 /* since the current process environment is being updated in util.c
155 * the library functions will get the correct environment
158 my_popen(char *cmd, char *mode)
161 #define fixcmd(x) { \
162 char *pspace = strchr((x),' '); \
165 while (p < pspace) { \
176 #ifdef __BORLANDC__ /* workaround a Borland stdio bug */
177 win32_fflush(stdout);
178 win32_fflush(stderr);
180 return win32_popen(cmd, mode);
184 my_pclose(PerlIO *fp)
186 return win32_pclose(fp);
192 static OSVERSIONINFO osver;
194 if (osver.dwPlatformId != Win32System) {
195 memset(&osver, 0, sizeof(OSVERSIONINFO));
196 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
197 GetVersionEx(&osver);
198 Win32System = osver.dwPlatformId;
200 return (Win32System);
207 char* defaultshell = (IsWinNT() ? "cmd.exe" : "command.com");
208 /* we don't use COMSPEC here for two reasons:
209 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
210 * uncontrolled unportability of the ensuing scripts.
211 * 2. PERL5SHELL could be set to a shell that may not be fit for
212 * interactive use (which is what most programs look in COMSPEC
215 char *usershell = getenv("PERL5SHELL");
218 strcpy(szShellPath, usershell ? usershell : defaultshell);
224 do_aspawn(void* really, void ** mark, void ** arglast)
232 SV *sv = (SV*)really;
233 SV** pSv = (SV**)mark;
235 New(1310, argv, (arglast - mark) + 4, char*);
238 cmd = SvPV(sv, length);
241 argv[index++] = cmd = GetShell();
243 argv[index++] = "/x"; /* always enable command extensions */
244 argv[index++] = "/c";
247 while(++pSv <= (SV**)arglast) {
249 strPtr = SvPV(sv, length);
250 if(strPtr != NULL && *strPtr != '\0')
251 argv[index++] = strPtr;
255 status = win32_spawnvp(P_WAIT, cmd, (const char* const*)argv);
261 warn("Can't spawn \"%s\": %s", cmd, strerror(errno));
264 return (statusvalue = status*256);
268 do_spawn2(char *cmd, int exectype)
274 BOOL needToTry = TRUE;
277 /* save an extra exec if possible */
280 /* see if there are shell metacharacters in it */
281 if(!HasRedirection(cmd)) {
282 New(1301,argv, strlen(cmd) / 2 + 2, char*);
283 New(1302,cmd2, strlen(cmd) + 1, char);
286 for (s = cmd2; *s;) {
287 while (*s && isspace(*s))
291 while(*s && !isspace(*s))
300 status = win32_spawnvp(P_WAIT, argv[0],
301 (const char* const*)argv);
303 case EXECF_SPAWN_NOWAIT:
304 status = win32_spawnvp(P_NOWAIT, argv[0],
305 (const char* const*)argv);
308 status = win32_execvp(argv[0], (const char* const*)argv);
311 if(status != -1 || errno == 0)
323 argv[i++] = "/c"; argv[i++] = cmd; argv[i] = Nullch;
326 status = win32_spawnvp(P_WAIT, argv[0],
327 (const char* const*)argv);
329 case EXECF_SPAWN_NOWAIT:
330 status = win32_spawnvp(P_NOWAIT, argv[0],
331 (const char* const*)argv);
334 status = win32_execvp(argv[0], (const char* const*)argv);
340 warn("Can't %s \"%s\": %s",
341 (exectype == EXECF_EXEC ? "exec" : "spawn"),
342 needToTry ? shell : argv[0],
346 return (statusvalue = status*256);
352 return do_spawn2(cmd, EXECF_SPAWN);
358 do_spawn2(cmd, EXECF_EXEC);
365 /* The idea here is to read all the directory names into a string table
366 * (separated by nulls) and when one of the other dir functions is called
367 * return the pointer to the current file name.
370 opendir(char *filename)
375 char scannamespc[PATHLEN];
376 char *scanname = scannamespc;
378 WIN32_FIND_DATA FindData;
380 /* char root[_MAX_PATH];*/
381 /* char volname[_MAX_PATH];*/
382 /* DWORD serial, maxname, flags;*/
386 /* check to see if filename is a directory */
387 if (win32_stat(filename, &sbuf) < 0 || (sbuf.st_mode & S_IFDIR) == 0) {
391 /* get the file system characteristics */
392 /* if(GetFullPathName(filename, MAX_PATH, root, &dummy)) {
393 * if(dummy = strchr(root, '\\'))
395 * if(GetVolumeInformation(root, volname, MAX_PATH, &serial,
396 * &maxname, &flags, 0, 0)) {
397 * downcase = !(flags & FS_CASE_IS_PRESERVED);
404 /* Get us a DIR structure */
405 Newz(1303, p, 1, DIR);
409 /* Create the search pattern */
410 strcpy(scanname, filename);
412 if(index("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
413 strcat(scanname, "/*");
415 strcat(scanname, "*");
417 /* do the FindFirstFile call */
418 fh = FindFirstFile(scanname, &FindData);
419 if(fh == INVALID_HANDLE_VALUE) {
423 /* now allocate the first part of the string table for
424 * the filenames that we find.
426 idx = strlen(FindData.cFileName)+1;
427 New(1304, p->start, idx, char);
428 if(p->start == NULL) {
429 croak("opendir: malloc failed!\n");
431 strcpy(p->start, FindData.cFileName);
437 /* loop finding all the files that match the wildcard
438 * (which should be all of them in this directory!).
439 * the variable idx should point one past the null terminator
440 * of the previous string found.
442 while (FindNextFile(fh, &FindData)) {
443 len = strlen(FindData.cFileName);
444 /* bump the string table size by enough for the
445 * new name and it's null terminator
447 Renew(p->start, idx+len+1, char);
448 if(p->start == NULL) {
449 croak("opendir: malloc failed!\n");
451 strcpy(&p->start[idx], FindData.cFileName);
453 * strlwr(&p->start[idx]);
465 /* Readdir just returns the current string pointer and bumps the
466 * string pointer to the nDllExport entry.
472 static int dummy = 0;
475 /* first set up the structure to return */
476 len = strlen(dirp->curr);
477 strcpy(dirp->dirstr.d_name, dirp->curr);
478 dirp->dirstr.d_namlen = len;
481 dirp->dirstr.d_ino = dummy++;
483 /* Now set up for the nDllExport call to readdir */
484 dirp->curr += len + 1;
485 if (dirp->curr >= (dirp->start + dirp->size)) {
489 return &(dirp->dirstr);
495 /* Telldir returns the current string pointer position */
499 return (long) dirp->curr;
503 /* Seekdir moves the string pointer to a previously saved position
507 seekdir(DIR *dirp, long loc)
509 dirp->curr = (char *)loc;
512 /* Rewinddir resets the string pointer to the start */
516 dirp->curr = dirp->start;
519 /* free the memory allocated by opendir */
523 Safefree(dirp->start);
536 * Just pretend that everyone is a superuser. NT will let us know if
537 * we don\'t really have permission to do something.
540 #define ROOT_UID ((uid_t)0)
541 #define ROOT_GID ((gid_t)0)
570 return (auid == ROOT_UID ? 0 : -1);
576 return (agid == ROOT_GID ? 0 : -1);
583 char *buf = getlogin_buffer;
584 DWORD size = sizeof(getlogin_buffer);
585 if (GetUserName(buf,&size))
594 kill(int pid, int sig)
596 HANDLE hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
598 if (hProcess == NULL) {
599 croak("kill process failed!\n");
602 if (!TerminateProcess(hProcess, sig))
603 croak("kill process failed!\n");
604 CloseHandle(hProcess);
613 DllExport unsigned int
614 win32_sleep(unsigned int t)
621 win32_stat(const char *path, struct stat *buffer)
624 const char *p = path;
625 int l = strlen(path);
629 switch(path[l - 1]) {
632 if (path[l - 2] != ':') {
633 strncpy(t, path, l - 1);
639 res = stat(p,buffer);
642 if (S_ISDIR(buffer->st_mode))
643 buffer->st_mode |= S_IWRITE | S_IEXEC;
644 else if (S_ISREG(buffer->st_mode)) {
645 if (l >= 4 && path[l-4] == '.') {
646 const char *e = path + l - 3;
647 if (strnicmp(e,"exe",3)
648 && strnicmp(e,"bat",3)
649 && strnicmp(e,"com",3)
650 && (IsWin95() || strnicmp(e,"cmd",3)))
651 buffer->st_mode &= ~S_IEXEC;
653 buffer->st_mode |= S_IEXEC;
656 buffer->st_mode &= ~S_IEXEC;
663 #ifndef USE_WIN32_RTL_ENV
666 win32_getenv(const char *name)
668 static char *curitem = Nullch;
669 static DWORD curlen = 512;
672 New(1305,curitem,curlen,char);
673 if (!(needlen = GetEnvironmentVariable(name,curitem,curlen)))
675 while (needlen > curlen) {
676 Renew(curitem,needlen,char);
678 needlen = GetEnvironmentVariable(name,curitem,curlen);
686 FileTimeToClock(PFILETIME ft)
688 __int64 qw = ft->dwHighDateTime;
690 qw |= ft->dwLowDateTime;
691 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
696 win32_times(struct tms *timebuf)
701 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
703 timebuf->tms_utime = FileTimeToClock(&user);
704 timebuf->tms_stime = FileTimeToClock(&kernel);
705 timebuf->tms_cutime = 0;
706 timebuf->tms_cstime = 0;
709 /* That failed - e.g. Win95 fallback to clock() */
711 timebuf->tms_utime = t;
712 timebuf->tms_stime = 0;
713 timebuf->tms_cutime = 0;
714 timebuf->tms_cstime = 0;
719 static UINT timerid = 0;
722 static VOID CALLBACK TimerProc(HWND win, UINT msg, UINT id, DWORD time)
724 KillTimer(NULL,timerid);
729 DllExport unsigned int
730 win32_alarm(unsigned int sec)
733 * the 'obvious' implentation is SetTimer() with a callback
734 * which does whatever receiving SIGALRM would do
735 * we cannot use SIGALRM even via raise() as it is not
736 * one of the supported codes in <signal.h>
738 * Snag is unless something is looking at the message queue
739 * nothing happens :-(
743 timerid = SetTimer(NULL,timerid,sec*1000,(TIMERPROC)TimerProc);
745 croak("Cannot set timer");
751 KillTimer(NULL,timerid);
758 #ifdef HAVE_DES_FCRYPT
759 extern char * des_fcrypt(char *cbuf, const char *txt, const char *salt);
762 win32_crypt(const char *txt, const char *salt)
765 return des_fcrypt(crypt_buffer, txt, salt);
769 #ifdef USE_FIXED_OSFHANDLE
771 EXTERN_C int __cdecl _alloc_osfhnd(void);
772 EXTERN_C int __cdecl _set_osfhnd(int fh, long value);
773 EXTERN_C void __cdecl _lock_fhandle(int);
774 EXTERN_C void __cdecl _unlock_fhandle(int);
775 EXTERN_C void __cdecl _unlock(int);
777 #if (_MSC_VER >= 1000)
779 long osfhnd; /* underlying OS file HANDLE */
780 char osfile; /* attributes of file (e.g., open in text mode?) */
781 char pipech; /* one char buffer for handles opened on pipes */
782 #if defined (_MT) && !defined (DLL_FOR_WIN32S)
784 CRITICAL_SECTION lock;
785 #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
788 EXTERN_C ioinfo * __pioinfo[];
791 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
792 #define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
793 #define _osfile(i) (_pioinfo(i)->osfile)
795 #else /* (_MSC_VER >= 1000) */
796 extern char _osfile[];
797 #endif /* (_MSC_VER >= 1000) */
799 #define FOPEN 0x01 /* file handle open */
800 #define FAPPEND 0x20 /* file handle opened O_APPEND */
801 #define FDEV 0x40 /* file handle refers to device */
802 #define FTEXT 0x80 /* file handle is in text mode */
804 #define _STREAM_LOCKS 26 /* Table of stream locks */
805 #define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */
806 #define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */
809 *int my_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
812 * This function allocates a free C Runtime file handle and associates
813 * it with the Win32 HANDLE specified by the first parameter. This is a
814 * temperary fix for WIN95's brain damage GetFileType() error on socket
815 * we just bypass that call for socket
818 * long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
819 * int flags - flags to associate with C Runtime file handle.
822 * returns index of entry in fh, if successful
823 * return -1, if no free entry is found
827 *******************************************************************************/
830 my_open_osfhandle(long osfhandle, int flags)
833 char fileflags; /* _osfile flags */
835 /* copy relevant flags from second parameter */
839 fileflags |= FAPPEND;
844 /* attempt to allocate a C Runtime file handle */
845 if((fh = _alloc_osfhnd()) == -1) {
846 errno = EMFILE; /* too many open files */
847 _doserrno = 0L; /* not an OS error */
848 return -1; /* return error to caller */
851 /* the file is open. now, set the info in _osfhnd array */
852 _set_osfhnd(fh, osfhandle);
854 fileflags |= FOPEN; /* mark as open */
856 #if (_MSC_VER >= 1000)
857 _osfile(fh) = fileflags; /* set osfile entry */
860 _osfile[fh] = fileflags; /* set osfile entry */
861 _unlock(fh+_FH_LOCKS); /* unlock handle */
864 return fh; /* return handle */
867 #define _open_osfhandle my_open_osfhandle
868 #endif /* USE_FIXED_OSFHANDLE */
870 /* simulate flock by locking a range on the file */
872 #define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
873 #define LK_LEN 0xffff0000
876 win32_flock(int fd, int oper)
883 croak("flock() unimplemented on this platform");
886 fh = (HANDLE)_get_osfhandle(fd);
887 memset(&o, 0, sizeof(o));
890 case LOCK_SH: /* shared lock */
891 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
893 case LOCK_EX: /* exclusive lock */
894 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
896 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
897 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
899 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
900 LK_ERR(LockFileEx(fh,
901 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
902 0, LK_LEN, 0, &o),i);
904 case LOCK_UN: /* unlock lock */
905 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
907 default: /* unknown */
918 * redirected io subsystem for all XS modules
931 return (&(_environ));
934 /* the rest are the remapped stdio routines */
954 win32_ferror(FILE *fp)
967 * Since the errors returned by the socket error function
968 * WSAGetLastError() are not known by the library routine strerror
969 * we have to roll our own.
973 win32_strerror(int e)
975 #ifndef __BORLANDC__ /* Borland intolerance */
980 if(e < 0 || e > sys_nerr) {
985 if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0,
986 strerror_buffer, sizeof(strerror_buffer), NULL) == 0)
987 strcpy(strerror_buffer, "Unknown Error");
989 return strerror_buffer;
995 win32_fprintf(FILE *fp, const char *format, ...)
998 va_start(marker, format); /* Initialize variable arguments. */
1000 return (vfprintf(fp, format, marker));
1004 win32_printf(const char *format, ...)
1007 va_start(marker, format); /* Initialize variable arguments. */
1009 return (vprintf(format, marker));
1013 win32_vfprintf(FILE *fp, const char *format, va_list args)
1015 return (vfprintf(fp, format, args));
1019 win32_vprintf(const char *format, va_list args)
1021 return (vprintf(format, args));
1025 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
1027 return fread(buf, size, count, fp);
1031 win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
1033 return fwrite(buf, size, count, fp);
1037 win32_fopen(const char *filename, const char *mode)
1039 if (stricmp(filename, "/dev/null")==0)
1040 return fopen("NUL", mode);
1041 return fopen(filename, mode);
1044 #ifndef USE_SOCKETS_AS_HANDLES
1046 #define fdopen my_fdopen
1050 win32_fdopen( int handle, const char *mode)
1052 return fdopen(handle, (char *) mode);
1056 win32_freopen( const char *path, const char *mode, FILE *stream)
1058 if (stricmp(path, "/dev/null")==0)
1059 return freopen("NUL", mode, stream);
1060 return freopen(path, mode, stream);
1064 win32_fclose(FILE *pf)
1066 return my_fclose(pf); /* defined in win32sck.c */
1070 win32_fputs(const char *s,FILE *pf)
1072 return fputs(s, pf);
1076 win32_fputc(int c,FILE *pf)
1082 win32_ungetc(int c,FILE *pf)
1084 return ungetc(c,pf);
1088 win32_getc(FILE *pf)
1094 win32_fileno(FILE *pf)
1100 win32_clearerr(FILE *pf)
1107 win32_fflush(FILE *pf)
1113 win32_ftell(FILE *pf)
1119 win32_fseek(FILE *pf,long offset,int origin)
1121 return fseek(pf, offset, origin);
1125 win32_fgetpos(FILE *pf,fpos_t *p)
1127 return fgetpos(pf, p);
1131 win32_fsetpos(FILE *pf,const fpos_t *p)
1133 return fsetpos(pf, p);
1137 win32_rewind(FILE *pf)
1157 win32_fstat(int fd,struct stat *sbufptr)
1159 return fstat(fd,sbufptr);
1163 win32_pipe(int *pfd, unsigned int size, int mode)
1165 return _pipe(pfd, size, mode);
1169 win32_popen(const char *command, const char *mode)
1171 return _popen(command, mode);
1175 win32_pclose(FILE *pf)
1181 win32_setmode(int fd, int mode)
1183 return setmode(fd, mode);
1187 win32_lseek(int fd, long offset, int origin)
1189 return lseek(fd, offset, origin);
1199 win32_open(const char *path, int flag, ...)
1205 pmode = va_arg(ap, int);
1208 if (stricmp(path, "/dev/null")==0)
1209 return open("NUL", flag, pmode);
1210 return open(path,flag,pmode);
1232 win32_dup2(int fd1,int fd2)
1234 return dup2(fd1,fd2);
1238 win32_read(int fd, void *buf, unsigned int cnt)
1240 return read(fd, buf, cnt);
1244 win32_write(int fd, const void *buf, unsigned int cnt)
1246 return write(fd, buf, cnt);
1250 win32_mkdir(const char *dir, int mode)
1252 return mkdir(dir); /* just ignore mode */
1256 win32_rmdir(const char *dir)
1262 win32_chdir(const char *dir)
1268 win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
1270 return spawnvp(mode, cmdname, (char * const *) argv);
1274 win32_execvp(const char *cmdname, const char *const *argv)
1276 return execvp(cmdname, (char *const *)argv);
1280 win32_perror(const char *str)
1286 win32_setbuf(FILE *pf, char *buf)
1292 win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
1294 return setvbuf(pf, buf, type, size);
1298 win32_flushall(void)
1304 win32_fcloseall(void)
1310 win32_fgets(char *s, int n, FILE *pf)
1312 return fgets(s, n, pf);
1322 win32_fgetc(FILE *pf)
1328 win32_putc(int c, FILE *pf)
1334 win32_puts(const char *s)
1346 win32_putchar(int c)
1353 #ifndef USE_PERL_SBRK
1355 static char *committed = NULL;
1356 static char *base = NULL;
1357 static char *reserved = NULL;
1358 static char *brk = NULL;
1359 static DWORD pagesize = 0;
1360 static DWORD allocsize = 0;
1368 GetSystemInfo(&info);
1369 /* Pretend page size is larger so we don't perpetually
1370 * call the OS to commit just one page ...
1372 pagesize = info.dwPageSize << 3;
1373 allocsize = info.dwAllocationGranularity;
1375 /* This scheme fails eventually if request for contiguous
1376 * block is denied so reserve big blocks - this is only
1377 * address space not memory ...
1379 if (brk+need >= reserved)
1381 DWORD size = 64*1024*1024;
1383 if (committed && reserved && committed < reserved)
1385 /* Commit last of previous chunk cannot span allocations */
1386 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
1388 committed = reserved;
1390 /* Reserve some (more) space
1391 * Note this is a little sneaky, 1st call passes NULL as reserved
1392 * so lets system choose where we start, subsequent calls pass
1393 * the old end address so ask for a contiguous block
1395 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
1398 reserved = addr+size;
1413 if (brk > committed)
1415 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
1416 char *addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
1431 win32_malloc(size_t size)
1433 return malloc(size);
1437 win32_calloc(size_t numitems, size_t size)
1439 return calloc(numitems,size);
1443 win32_realloc(void *block, size_t size)
1445 return realloc(block,size);
1449 win32_free(void *block)
1456 win32_open_osfhandle(long handle, int flags)
1458 return _open_osfhandle(handle, flags);
1462 win32_get_osfhandle(int fd)
1464 return _get_osfhandle(fd);
1475 SV *sv = sv_newmortal();
1476 /* Make one call with zero size - return value is required size */
1477 DWORD len = GetCurrentDirectory((DWORD)0,NULL);
1478 SvUPGRADE(sv,SVt_PV);
1480 SvCUR(sv) = GetCurrentDirectory((DWORD) SvLEN(sv), SvPVX(sv));
1483 * then it worked, set PV valid,
1484 * else leave it 'undef'
1498 croak("usage: Win32::SetCurrentDirectory($cwd)");
1499 if (SetCurrentDirectory(SvPV(ST(0),na)))
1506 XS(w32_GetNextAvailDrive)
1510 char root[] = "_:\\";
1513 if (GetDriveType(root) == 1) {
1522 XS(w32_GetLastError)
1525 XSRETURN_IV(GetLastError());
1532 char *name = getlogin_buffer;
1533 DWORD size = sizeof(getlogin_buffer);
1534 if (GetUserName(name,&size)) {
1535 /* size includes NULL */
1536 ST(0) = sv_2mortal(newSVpv(name,size-1));
1546 char name[MAX_COMPUTERNAME_LENGTH+1];
1547 DWORD size = sizeof(name);
1548 if (GetComputerName(name,&size)) {
1549 /* size does NOT include NULL :-( */
1550 ST(0) = sv_2mortal(newSVpv(name,size));
1562 DWORD size = sizeof(name);
1563 if (GetUserName(name,&size)) {
1565 DWORD sidlen = sizeof(sid);
1567 DWORD dnamelen = sizeof(dname);
1569 if (LookupAccountName(NULL, name, &sid, &sidlen,
1570 dname, &dnamelen, &snu)) {
1571 XSRETURN_PV(dname); /* all that for this */
1582 DWORD flags, filecomplen;
1583 if (GetVolumeInformation(NULL, NULL, 0, NULL, &filecomplen,
1584 &flags, fsname, sizeof(fsname))) {
1585 if (GIMME == G_ARRAY) {
1586 XPUSHs(sv_2mortal(newSVpv(fsname,0)));
1587 XPUSHs(sv_2mortal(newSViv(flags)));
1588 XPUSHs(sv_2mortal(newSViv(filecomplen)));
1592 XSRETURN_PV(fsname);
1598 XS(w32_GetOSVersion)
1601 OSVERSIONINFO osver;
1603 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1604 if (GetVersionEx(&osver)) {
1605 XPUSHs(newSVpv(osver.szCSDVersion, 0));
1606 XPUSHs(newSViv(osver.dwMajorVersion));
1607 XPUSHs(newSViv(osver.dwMinorVersion));
1608 XPUSHs(newSViv(osver.dwBuildNumber));
1609 XPUSHs(newSViv(osver.dwPlatformId));
1620 XSRETURN_IV(IsWinNT());
1627 XSRETURN_IV(IsWin95());
1631 XS(w32_FormatMessage)
1638 croak("usage: Win32::FormatMessage($errno)");
1640 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1641 &source, SvIV(ST(0)), 0,
1642 msgbuf, sizeof(msgbuf)-1, NULL))
1643 XSRETURN_PV(msgbuf);
1653 PROCESS_INFORMATION stProcInfo;
1654 STARTUPINFO stStartInfo;
1655 BOOL bSuccess = FALSE;
1658 croak("usage: Win32::Spawn($cmdName, $args, $PID)");
1660 cmd = SvPV(ST(0),na);
1661 args = SvPV(ST(1), na);
1663 memset(&stStartInfo, 0, sizeof(stStartInfo)); /* Clear the block */
1664 stStartInfo.cb = sizeof(stStartInfo); /* Set the structure size */
1665 stStartInfo.dwFlags = STARTF_USESHOWWINDOW; /* Enable wShowWindow control */
1666 stStartInfo.wShowWindow = SW_SHOWMINNOACTIVE; /* Start min (normal) */
1669 cmd, /* Image path */
1670 args, /* Arguments for command line */
1671 NULL, /* Default process security */
1672 NULL, /* Default thread security */
1673 FALSE, /* Must be TRUE to use std handles */
1674 NORMAL_PRIORITY_CLASS, /* No special scheduling */
1675 NULL, /* Inherit our environment block */
1676 NULL, /* Inherit our currrent directory */
1677 &stStartInfo, /* -> Startup info */
1678 &stProcInfo)) /* <- Process info (if OK) */
1680 CloseHandle(stProcInfo.hThread);/* library source code does this. */
1681 sv_setiv(ST(2), stProcInfo.dwProcessId);
1684 XSRETURN_IV(bSuccess);
1688 XS(w32_GetTickCount)
1691 XSRETURN_IV(GetTickCount());
1695 XS(w32_GetShortPathName)
1702 croak("usage: Win32::GetShortPathName($longPathName)");
1704 shortpath = sv_mortalcopy(ST(0));
1705 SvUPGRADE(shortpath, SVt_PV);
1706 /* src == target is allowed */
1708 len = GetShortPathName(SvPVX(shortpath),
1711 } while (len >= SvLEN(shortpath) && sv_grow(shortpath,len+1));
1713 SvCUR_set(shortpath,len);
1722 Perl_init_os_extras()
1724 char *file = __FILE__;
1727 /* XXX should be removed after checking with Nick */
1728 newXS("Win32::GetCurrentDirectory", w32_GetCwd, file);
1730 /* these names are Activeware compatible */
1731 newXS("Win32::GetCwd", w32_GetCwd, file);
1732 newXS("Win32::SetCwd", w32_SetCwd, file);
1733 newXS("Win32::GetNextAvailDrive", w32_GetNextAvailDrive, file);
1734 newXS("Win32::GetLastError", w32_GetLastError, file);
1735 newXS("Win32::LoginName", w32_LoginName, file);
1736 newXS("Win32::NodeName", w32_NodeName, file);
1737 newXS("Win32::DomainName", w32_DomainName, file);
1738 newXS("Win32::FsType", w32_FsType, file);
1739 newXS("Win32::GetOSVersion", w32_GetOSVersion, file);
1740 newXS("Win32::IsWinNT", w32_IsWinNT, file);
1741 newXS("Win32::IsWin95", w32_IsWin95, file);
1742 newXS("Win32::FormatMessage", w32_FormatMessage, file);
1743 newXS("Win32::Spawn", w32_Spawn, file);
1744 newXS("Win32::GetTickCount", w32_GetTickCount, file);
1745 newXS("Win32::GetShortPathName", w32_GetShortPathName, file);
1747 /* XXX Bloat Alert! The following Activeware preloads really
1748 * ought to be part of Win32::Sys::*, so they're not included
1751 /* LookupAccountName
1753 * InitiateSystemShutdown
1754 * AbortSystemShutdown
1755 * ExpandEnvrironmentStrings
1760 Perl_win32_init(int *argcp, char ***argvp)
1762 /* Disable floating point errors, Perl will trap the ones we
1763 * care about. VC++ RTL defaults to switching these off
1764 * already, but the Borland RTL doesn't. Since we don't
1765 * want to be at the vendor's whim on the default, we set
1766 * it explicitly here.
1768 #if !defined(_ALPHA_) && !defined(__GNUC__)
1769 _control87(MCW_EM, MCW_EM);
1774 #ifdef USE_BINMODE_SCRIPTS
1777 win32_strip_return(SV *sv)
1779 char *s = SvPVX(sv);
1780 char *e = s+SvCUR(sv);
1784 if (*s == '\r' && s[1] == '\n')
1794 SvCUR_set(sv,d-SvPVX(sv));