Add files and tweak others to get 'native' Mingw32 gcc port as
[p5sagit/p5-mst-13.2.git] / win32 / win32.c
CommitLineData
68dc0745 1/* WIN32.C
2 *
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.
6 *
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.
9 */
0a753a76 10
11#define WIN32_LEAN_AND_MEAN
12#define WIN32IO_IS_STDIO
13#include <tchar.h>
a835ef8a 14#ifdef __GNUC__
15#define Win32_Winsock
16#endif
0a753a76 17#include <windows.h>
18
68dc0745 19/* #include "config.h" */
0a753a76 20
21#define PERLIO_NOT_STDIO 0
22#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
23#define PerlIO FILE
24#endif
25
26#include "EXTERN.h"
27#include "perl.h"
ad2e33dc 28#include "XSUB.h"
0a753a76 29#include <fcntl.h>
30#include <sys/stat.h>
31#include <assert.h>
32#include <string.h>
33#include <stdarg.h>
ad2e33dc 34#include <float.h>
0a753a76 35
6890e559 36#define EXECF_EXEC 1
37#define EXECF_SPAWN 2
38#define EXECF_SPAWN_NOWAIT 3
39
8b10511d 40static DWORD IdOS(void);
41
0a753a76 42BOOL ProbeEnv = FALSE;
8b10511d 43DWORD Win32System = (DWORD)-1;
0a753a76 44char szShellPath[MAX_PATH+1];
45char szPerlLibRoot[MAX_PATH+1];
46HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
47
6890e559 48static int do_spawn2(char *cmd, int exectype);
49
3fe9a6f1 50int
51IsWin95(void) {
8b10511d 52 return (IdOS() == VER_PLATFORM_WIN32_WINDOWS);
3fe9a6f1 53}
54
55int
56IsWinNT(void) {
8b10511d 57 return (IdOS() == VER_PLATFORM_WIN32_NT);
3fe9a6f1 58}
0a753a76 59
68dc0745 60char *
acbc2db6 61win32PerlLibPath(char *sfx,...)
68dc0745 62{
acbc2db6 63 va_list ap;
68dc0745 64 char *end;
acbc2db6 65 va_start(ap,sfx);
68dc0745 66 GetModuleFileName((PerlDllHandle == INVALID_HANDLE_VALUE)
67 ? GetModuleHandle(NULL)
68 : PerlDllHandle,
69 szPerlLibRoot,
70 sizeof(szPerlLibRoot));
68dc0745 71 *(end = strrchr(szPerlLibRoot, '\\')) = '\0';
72 if (stricmp(end-4,"\\bin") == 0)
73 end -= 4;
74 strcpy(end,"\\lib");
acbc2db6 75 while (sfx)
76 {
77 strcat(end,"\\");
78 strcat(end,sfx);
79 sfx = va_arg(ap,char *);
80 }
81 va_end(ap);
68dc0745 82 return (szPerlLibRoot);
83}
0a753a76 84
b4793f7f 85
68dc0745 86BOOL
87HasRedirection(char *ptr)
88{
89 int inquote = 0;
90 char quote = '\0';
91
92 /*
93 * Scan string looking for redirection (< or >) or pipe
94 * characters (|) that are not in a quoted string
95 */
96 while(*ptr) {
97 switch(*ptr) {
98 case '\'':
99 case '\"':
100 if(inquote) {
101 if(quote == *ptr) {
102 inquote = 0;
103 quote = '\0';
0a753a76 104 }
68dc0745 105 }
106 else {
107 quote = *ptr;
108 inquote++;
109 }
110 break;
111 case '>':
112 case '<':
113 case '|':
114 if(!inquote)
115 return TRUE;
116 default:
117 break;
0a753a76 118 }
68dc0745 119 ++ptr;
120 }
121 return FALSE;
0a753a76 122}
123
68dc0745 124/* since the current process environment is being updated in util.c
125 * the library functions will get the correct environment
126 */
127PerlIO *
128my_popen(char *cmd, char *mode)
0a753a76 129{
130#ifdef FIXCMD
68dc0745 131#define fixcmd(x) { \
132 char *pspace = strchr((x),' '); \
133 if (pspace) { \
134 char *p = (x); \
135 while (p < pspace) { \
136 if (*p == '/') \
137 *p = '\\'; \
138 p++; \
139 } \
140 } \
141 }
0a753a76 142#else
143#define fixcmd(x)
144#endif
68dc0745 145 fixcmd(cmd);
3e3baf6d 146#ifdef __BORLANDC__ /* workaround a Borland stdio bug */
147 win32_fflush(stdout);
148 win32_fflush(stderr);
149#endif
0a753a76 150 return win32_popen(cmd, mode);
0a753a76 151}
152
68dc0745 153long
154my_pclose(PerlIO *fp)
0a753a76 155{
156 return win32_pclose(fp);
157}
158
8b10511d 159static DWORD
68dc0745 160IdOS(void)
0a753a76 161{
8b10511d 162 static OSVERSIONINFO osver;
0a753a76 163
8b10511d 164 if (osver.dwPlatformId != Win32System) {
165 memset(&osver, 0, sizeof(OSVERSIONINFO));
166 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
167 GetVersionEx(&osver);
168 Win32System = osver.dwPlatformId;
169 }
170 return (Win32System);
0a753a76 171}
172
68dc0745 173static char *
174GetShell(void)
0a753a76 175{
68dc0745 176 if (!ProbeEnv) {
174c211a 177 char* defaultshell = (IsWinNT() ? "cmd.exe" : "command.com");
178 /* we don't use COMSPEC here for two reasons:
179 * 1. the same reason perl on UNIX doesn't use SHELL--rampant and
180 * uncontrolled unportability of the ensuing scripts.
181 * 2. PERL5SHELL could be set to a shell that may not be fit for
182 * interactive use (which is what most programs look in COMSPEC
183 * for).
184 */
185 char *usershell = getenv("PERL5SHELL");
186
8b10511d 187 ProbeEnv = TRUE;
174c211a 188 strcpy(szShellPath, usershell ? usershell : defaultshell);
68dc0745 189 }
190 return szShellPath;
0a753a76 191}
192
68dc0745 193int
d55594ae 194do_aspawn(void* really, void ** mark, void ** arglast)
0a753a76 195{
68dc0745 196 char **argv;
197 char *strPtr;
198 char *cmd;
199 int status;
200 unsigned int length;
201 int index = 0;
0a753a76 202 SV *sv = (SV*)really;
68dc0745 203 SV** pSv = (SV**)mark;
204
fc36a67e 205 New(1310, argv, (arglast - mark) + 4, char*);
68dc0745 206
207 if(sv != Nullsv) {
208 cmd = SvPV(sv, length);
209 }
210 else {
3fe9a6f1 211 argv[index++] = cmd = GetShell();
0a9a032c 212 if (IsWinNT())
213 argv[index++] = "/x"; /* always enable command extensions */
68dc0745 214 argv[index++] = "/c";
215 }
216
5aabfad6 217 while(++pSv <= (SV**)arglast) {
218 sv = *pSv;
68dc0745 219 strPtr = SvPV(sv, length);
220 if(strPtr != NULL && *strPtr != '\0')
221 argv[index++] = strPtr;
222 }
223 argv[index++] = 0;
224
3e3baf6d 225 status = win32_spawnvp(P_WAIT, cmd, (const char* const*)argv);
68dc0745 226
227 Safefree(argv);
228
5aabfad6 229 if (status < 0) {
230 if (dowarn)
231 warn("Can't spawn \"%s\": %s", cmd, strerror(errno));
232 status = 255 << 8;
233 }
234 return (status);
68dc0745 235}
236
237int
6890e559 238do_spawn2(char *cmd, int exectype)
68dc0745 239{
240 char **a;
241 char *s;
242 char **argv;
243 int status = -1;
244 BOOL needToTry = TRUE;
245 char *shell, *cmd2;
246
247 /* save an extra exec if possible */
248 shell = GetShell();
249
250 /* see if there are shell metacharacters in it */
251 if(!HasRedirection(cmd)) {
fc36a67e 252 New(1301,argv, strlen(cmd) / 2 + 2, char*);
253 New(1302,cmd2, strlen(cmd) + 1, char);
68dc0745 254 strcpy(cmd2, cmd);
255 a = argv;
256 for (s = cmd2; *s;) {
257 while (*s && isspace(*s))
258 s++;
259 if (*s)
260 *(a++) = s;
261 while(*s && !isspace(*s))
262 s++;
263 if(*s)
264 *s++ = '\0';
0a753a76 265 }
68dc0745 266 *a = Nullch;
267 if(argv[0]) {
6890e559 268 switch (exectype) {
269 case EXECF_SPAWN:
270 status = win32_spawnvp(P_WAIT, argv[0],
271 (const char* const*)argv);
272 break;
273 case EXECF_SPAWN_NOWAIT:
274 status = win32_spawnvp(P_NOWAIT, argv[0],
275 (const char* const*)argv);
276 break;
277 case EXECF_EXEC:
278 status = win32_execvp(argv[0], (const char* const*)argv);
279 break;
280 }
68dc0745 281 if(status != -1 || errno == 0)
282 needToTry = FALSE;
0a753a76 283 }
0a753a76 284 Safefree(argv);
68dc0745 285 Safefree(cmd2);
286 }
287 if(needToTry) {
3e3baf6d 288 char *argv[5];
0a9a032c 289 int i = 0;
290 argv[i++] = shell;
291 if (IsWinNT())
292 argv[i++] = "/x";
293 argv[i++] = "/c"; argv[i++] = cmd; argv[i] = Nullch;
6890e559 294 switch (exectype) {
295 case EXECF_SPAWN:
296 status = win32_spawnvp(P_WAIT, argv[0],
297 (const char* const*)argv);
298 break;
299 case EXECF_SPAWN_NOWAIT:
300 status = win32_spawnvp(P_NOWAIT, argv[0],
301 (const char* const*)argv);
302 break;
303 case EXECF_EXEC:
304 status = win32_execvp(argv[0], (const char* const*)argv);
305 break;
306 }
68dc0745 307 }
5aabfad6 308 if (status < 0) {
309 if (dowarn)
6890e559 310 warn("Can't %s \"%s\": %s",
311 (exectype == EXECF_EXEC ? "exec" : "spawn"),
312 needToTry ? shell : argv[0],
5aabfad6 313 strerror(errno));
314 status = 255 << 8;
315 }
316 return (status);
0a753a76 317}
318
6890e559 319int
320do_spawn(char *cmd)
321{
322 return do_spawn2(cmd, EXECF_SPAWN);
323}
324
325bool
326do_exec(char *cmd)
327{
328 do_spawn2(cmd, EXECF_EXEC);
329 return FALSE;
330}
331
0a753a76 332
333#define PATHLEN 1024
334
68dc0745 335/* The idea here is to read all the directory names into a string table
336 * (separated by nulls) and when one of the other dir functions is called
337 * return the pointer to the current file name.
338 */
339DIR *
340opendir(char *filename)
0a753a76 341{
342 DIR *p;
68dc0745 343 long len;
344 long idx;
345 char scannamespc[PATHLEN];
346 char *scanname = scannamespc;
347 struct stat sbuf;
348 WIN32_FIND_DATA FindData;
349 HANDLE fh;
350/* char root[_MAX_PATH];*/
351/* char volname[_MAX_PATH];*/
352/* DWORD serial, maxname, flags;*/
353/* BOOL downcase;*/
354/* char *dummy;*/
355
356 /* check to see if filename is a directory */
d55594ae 357 if (win32_stat(filename, &sbuf) < 0 || (sbuf.st_mode & S_IFDIR) == 0) {
68dc0745 358 return NULL;
359 }
360
361 /* get the file system characteristics */
362/* if(GetFullPathName(filename, MAX_PATH, root, &dummy)) {
363 * if(dummy = strchr(root, '\\'))
364 * *++dummy = '\0';
365 * if(GetVolumeInformation(root, volname, MAX_PATH, &serial,
366 * &maxname, &flags, 0, 0)) {
367 * downcase = !(flags & FS_CASE_IS_PRESERVED);
368 * }
369 * }
370 * else {
371 * downcase = TRUE;
372 * }
373 */
374 /* Get us a DIR structure */
fc36a67e 375 Newz(1303, p, 1, DIR);
68dc0745 376 if(p == NULL)
377 return NULL;
378
379 /* Create the search pattern */
380 strcpy(scanname, filename);
381
382 if(index("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
383 strcat(scanname, "/*");
384 else
385 strcat(scanname, "*");
386
387 /* do the FindFirstFile call */
388 fh = FindFirstFile(scanname, &FindData);
389 if(fh == INVALID_HANDLE_VALUE) {
390 return NULL;
391 }
392
393 /* now allocate the first part of the string table for
394 * the filenames that we find.
395 */
396 idx = strlen(FindData.cFileName)+1;
fc36a67e 397 New(1304, p->start, idx, char);
68dc0745 398 if(p->start == NULL) {
65e48ea9 399 croak("opendir: malloc failed!\n");
68dc0745 400 }
401 strcpy(p->start, FindData.cFileName);
402/* if(downcase)
403 * strlwr(p->start);
404 */
405 p->nfiles++;
406
407 /* loop finding all the files that match the wildcard
408 * (which should be all of them in this directory!).
409 * the variable idx should point one past the null terminator
410 * of the previous string found.
411 */
412 while (FindNextFile(fh, &FindData)) {
413 len = strlen(FindData.cFileName);
414 /* bump the string table size by enough for the
415 * new name and it's null terminator
416 */
417 Renew(p->start, idx+len+1, char);
418 if(p->start == NULL) {
65e48ea9 419 croak("opendir: malloc failed!\n");
0a753a76 420 }
68dc0745 421 strcpy(&p->start[idx], FindData.cFileName);
422/* if (downcase)
423 * strlwr(&p->start[idx]);
424 */
0a753a76 425 p->nfiles++;
426 idx += len+1;
427 }
428 FindClose(fh);
429 p->size = idx;
430 p->curr = p->start;
431 return p;
432}
433
434
68dc0745 435/* Readdir just returns the current string pointer and bumps the
436 * string pointer to the nDllExport entry.
437 */
438struct direct *
439readdir(DIR *dirp)
0a753a76 440{
68dc0745 441 int len;
442 static int dummy = 0;
0a753a76 443
68dc0745 444 if (dirp->curr) {
445 /* first set up the structure to return */
446 len = strlen(dirp->curr);
447 strcpy(dirp->dirstr.d_name, dirp->curr);
448 dirp->dirstr.d_namlen = len;
0a753a76 449
68dc0745 450 /* Fake an inode */
451 dirp->dirstr.d_ino = dummy++;
0a753a76 452
68dc0745 453 /* Now set up for the nDllExport call to readdir */
454 dirp->curr += len + 1;
455 if (dirp->curr >= (dirp->start + dirp->size)) {
456 dirp->curr = NULL;
457 }
0a753a76 458
68dc0745 459 return &(dirp->dirstr);
460 }
461 else
462 return NULL;
0a753a76 463}
464
68dc0745 465/* Telldir returns the current string pointer position */
466long
467telldir(DIR *dirp)
0a753a76 468{
469 return (long) dirp->curr;
470}
471
472
68dc0745 473/* Seekdir moves the string pointer to a previously saved position
474 *(Saved by telldir).
475 */
476void
477seekdir(DIR *dirp, long loc)
0a753a76 478{
479 dirp->curr = (char *)loc;
480}
481
68dc0745 482/* Rewinddir resets the string pointer to the start */
483void
484rewinddir(DIR *dirp)
0a753a76 485{
486 dirp->curr = dirp->start;
487}
488
68dc0745 489/* free the memory allocated by opendir */
490int
491closedir(DIR *dirp)
0a753a76 492{
493 Safefree(dirp->start);
494 Safefree(dirp);
68dc0745 495 return 1;
0a753a76 496}
497
498
68dc0745 499/*
500 * various stubs
501 */
0a753a76 502
503
68dc0745 504/* Ownership
505 *
506 * Just pretend that everyone is a superuser. NT will let us know if
507 * we don\'t really have permission to do something.
508 */
0a753a76 509
510#define ROOT_UID ((uid_t)0)
511#define ROOT_GID ((gid_t)0)
512
68dc0745 513uid_t
514getuid(void)
0a753a76 515{
68dc0745 516 return ROOT_UID;
0a753a76 517}
518
68dc0745 519uid_t
520geteuid(void)
0a753a76 521{
68dc0745 522 return ROOT_UID;
0a753a76 523}
524
68dc0745 525gid_t
526getgid(void)
0a753a76 527{
68dc0745 528 return ROOT_GID;
0a753a76 529}
530
68dc0745 531gid_t
532getegid(void)
0a753a76 533{
68dc0745 534 return ROOT_GID;
0a753a76 535}
536
68dc0745 537int
538setuid(uid_t uid)
0a753a76 539{
68dc0745 540 return (uid == ROOT_UID ? 0 : -1);
0a753a76 541}
542
68dc0745 543int
544setgid(gid_t gid)
0a753a76 545{
68dc0745 546 return (gid == ROOT_GID ? 0 : -1);
0a753a76 547}
548
68dc0745 549/*
550 * pretended kill
551 */
552int
553kill(int pid, int sig)
0a753a76 554{
68dc0745 555 HANDLE hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
0a753a76 556
557 if (hProcess == NULL) {
65e48ea9 558 croak("kill process failed!\n");
68dc0745 559 }
560 else {
561 if (!TerminateProcess(hProcess, sig))
65e48ea9 562 croak("kill process failed!\n");
68dc0745 563 CloseHandle(hProcess);
564 }
565 return 0;
0a753a76 566}
567
68dc0745 568/*
569 * File system stuff
570 */
0a753a76 571
3e3baf6d 572#if 0
68dc0745 573int
574ioctl(int i, unsigned int u, char *data)
0a753a76 575{
65e48ea9 576 croak("ioctl not implemented!\n");
68dc0745 577 return -1;
0a753a76 578}
3e3baf6d 579#endif
0a753a76 580
f3986ebb 581DllExport unsigned int
582win32_sleep(unsigned int t)
0a753a76 583{
68dc0745 584 Sleep(t*1000);
585 return 0;
0a753a76 586}
587
68dc0745 588DllExport int
589win32_stat(const char *path, struct stat *buffer)
0a753a76 590{
68dc0745 591 char t[MAX_PATH];
592 const char *p = path;
593 int l = strlen(path);
67fbe06e 594 int res;
0a753a76 595
68dc0745 596 if (l > 1) {
597 switch(path[l - 1]) {
598 case '\\':
599 case '/':
600 if (path[l - 2] != ':') {
601 strncpy(t, path, l - 1);
602 t[l - 1] = 0;
603 p = t;
604 };
605 }
606 }
390b85e7 607 res = stat(p,buffer);
67fbe06e 608#ifdef __BORLANDC__
609 if (res == 0) {
610 if (S_ISDIR(buffer->st_mode))
611 buffer->st_mode |= S_IWRITE | S_IEXEC;
612 else if (S_ISREG(buffer->st_mode)) {
613 if (l >= 4 && path[l-4] == '.') {
614 const char *e = path + l - 3;
615 if (strnicmp(e,"exe",3)
616 && strnicmp(e,"bat",3)
617 && strnicmp(e,"com",3)
618 && (IsWin95() || strnicmp(e,"cmd",3)))
619 buffer->st_mode &= ~S_IEXEC;
620 else
621 buffer->st_mode |= S_IEXEC;
622 }
623 else
624 buffer->st_mode &= ~S_IEXEC;
625 }
626 }
627#endif
628 return res;
0a753a76 629}
630
0551aaa8 631#ifndef USE_WIN32_RTL_ENV
632
633DllExport char *
634win32_getenv(const char *name)
635{
636 static char *curitem = Nullch;
637 static DWORD curlen = 512;
638 DWORD needlen;
639 if (!curitem)
640 New(1305,curitem,curlen,char);
641 if (!(needlen = GetEnvironmentVariable(name,curitem,curlen)))
642 return Nullch;
643 while (needlen > curlen) {
644 Renew(curitem,needlen,char);
645 curlen = needlen;
646 needlen = GetEnvironmentVariable(name,curitem,curlen);
647 }
648 return curitem;
649}
650
651#endif
652
d55594ae 653static long
654FileTimeToClock(PFILETIME ft)
655{
656 __int64 qw = ft->dwHighDateTime;
657 qw <<= 32;
658 qw |= ft->dwLowDateTime;
659 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
660 return (long) qw;
661}
662
f3986ebb 663DllExport int
664win32_times(struct tms *timebuf)
0a753a76 665{
d55594ae 666 FILETIME user;
667 FILETIME kernel;
668 FILETIME dummy;
669 if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
670 &kernel,&user)) {
671 timebuf->tms_utime = FileTimeToClock(&user);
672 timebuf->tms_stime = FileTimeToClock(&kernel);
673 timebuf->tms_cutime = 0;
674 timebuf->tms_cstime = 0;
675
676 } else {
677 /* That failed - e.g. Win95 fallback to clock() */
678 clock_t t = clock();
679 timebuf->tms_utime = t;
680 timebuf->tms_stime = 0;
681 timebuf->tms_cutime = 0;
682 timebuf->tms_cstime = 0;
683 }
68dc0745 684 return 0;
0a753a76 685}
686
d55594ae 687static UINT timerid = 0;
688
689
690static VOID CALLBACK TimerProc(HWND win, UINT msg, UINT id, DWORD time)
691{
692 KillTimer(NULL,timerid);
693 timerid=0;
694 sighandler(14);
695}
696
f3986ebb 697DllExport unsigned int
698win32_alarm(unsigned int sec)
0a753a76 699{
d55594ae 700 /*
701 * the 'obvious' implentation is SetTimer() with a callback
702 * which does whatever receiving SIGALRM would do
703 * we cannot use SIGALRM even via raise() as it is not
704 * one of the supported codes in <signal.h>
705 *
706 * Snag is unless something is looking at the message queue
707 * nothing happens :-(
708 */
709 if (sec)
710 {
711 timerid = SetTimer(NULL,timerid,sec*1000,(TIMERPROC)TimerProc);
712 if (!timerid)
713 croak("Cannot set timer");
714 }
715 else
716 {
717 if (timerid)
718 {
719 KillTimer(NULL,timerid);
720 timerid=0;
721 }
722 }
68dc0745 723 return 0;
0a753a76 724}
725
f3986ebb 726#ifdef USE_FIXED_OSFHANDLE
390b85e7 727
728EXTERN_C int __cdecl _alloc_osfhnd(void);
729EXTERN_C int __cdecl _set_osfhnd(int fh, long value);
730EXTERN_C void __cdecl _lock_fhandle(int);
731EXTERN_C void __cdecl _unlock_fhandle(int);
732EXTERN_C void __cdecl _unlock(int);
733
734#if (_MSC_VER >= 1000)
735typedef struct {
736 long osfhnd; /* underlying OS file HANDLE */
737 char osfile; /* attributes of file (e.g., open in text mode?) */
738 char pipech; /* one char buffer for handles opened on pipes */
739#if defined (_MT) && !defined (DLL_FOR_WIN32S)
740 int lockinitflag;
741 CRITICAL_SECTION lock;
742#endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
743} ioinfo;
744
745EXTERN_C ioinfo * __pioinfo[];
746
747#define IOINFO_L2E 5
748#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
749#define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
750#define _osfile(i) (_pioinfo(i)->osfile)
751
752#else /* (_MSC_VER >= 1000) */
753extern char _osfile[];
754#endif /* (_MSC_VER >= 1000) */
755
756#define FOPEN 0x01 /* file handle open */
757#define FAPPEND 0x20 /* file handle opened O_APPEND */
758#define FDEV 0x40 /* file handle refers to device */
759#define FTEXT 0x80 /* file handle is in text mode */
760
761#define _STREAM_LOCKS 26 /* Table of stream locks */
762#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */
763#define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */
764
765/***
766*int my_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
767*
768*Purpose:
769* This function allocates a free C Runtime file handle and associates
770* it with the Win32 HANDLE specified by the first parameter. This is a
771* temperary fix for WIN95's brain damage GetFileType() error on socket
772* we just bypass that call for socket
773*
774*Entry:
775* long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
776* int flags - flags to associate with C Runtime file handle.
777*
778*Exit:
779* returns index of entry in fh, if successful
780* return -1, if no free entry is found
781*
782*Exceptions:
783*
784*******************************************************************************/
785
786static int
787my_open_osfhandle(long osfhandle, int flags)
788{
789 int fh;
790 char fileflags; /* _osfile flags */
791
792 /* copy relevant flags from second parameter */
793 fileflags = FDEV;
794
795 if(flags & O_APPEND)
796 fileflags |= FAPPEND;
797
798 if(flags & O_TEXT)
799 fileflags |= FTEXT;
800
801 /* attempt to allocate a C Runtime file handle */
802 if((fh = _alloc_osfhnd()) == -1) {
803 errno = EMFILE; /* too many open files */
804 _doserrno = 0L; /* not an OS error */
805 return -1; /* return error to caller */
806 }
807
808 /* the file is open. now, set the info in _osfhnd array */
809 _set_osfhnd(fh, osfhandle);
810
811 fileflags |= FOPEN; /* mark as open */
812
813#if (_MSC_VER >= 1000)
814 _osfile(fh) = fileflags; /* set osfile entry */
815 _unlock_fhandle(fh);
816#else
817 _osfile[fh] = fileflags; /* set osfile entry */
818 _unlock(fh+_FH_LOCKS); /* unlock handle */
819#endif
820
821 return fh; /* return handle */
822}
823
824#define _open_osfhandle my_open_osfhandle
f3986ebb 825#endif /* USE_FIXED_OSFHANDLE */
390b85e7 826
827/* simulate flock by locking a range on the file */
828
829#define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
830#define LK_LEN 0xffff0000
831
f3986ebb 832DllExport int
833win32_flock(int fd, int oper)
390b85e7 834{
835 OVERLAPPED o;
836 int i = -1;
837 HANDLE fh;
838
f3986ebb 839 if (!IsWinNT()) {
840 croak("flock() unimplemented on this platform");
841 return -1;
842 }
390b85e7 843 fh = (HANDLE)_get_osfhandle(fd);
844 memset(&o, 0, sizeof(o));
845
846 switch(oper) {
847 case LOCK_SH: /* shared lock */
848 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
849 break;
850 case LOCK_EX: /* exclusive lock */
851 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
852 break;
853 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
854 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
855 break;
856 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
857 LK_ERR(LockFileEx(fh,
858 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
859 0, LK_LEN, 0, &o),i);
860 break;
861 case LOCK_UN: /* unlock lock */
862 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
863 break;
864 default: /* unknown */
865 errno = EINVAL;
866 break;
867 }
868 return i;
869}
870
871#undef LK_ERR
872#undef LK_LEN
873
68dc0745 874/*
875 * redirected io subsystem for all XS modules
876 *
877 */
0a753a76 878
68dc0745 879DllExport int *
880win32_errno(void)
0a753a76 881{
390b85e7 882 return (&errno);
0a753a76 883}
884
dcb2879a 885DllExport char ***
886win32_environ(void)
887{
390b85e7 888 return (&(_environ));
dcb2879a 889}
890
68dc0745 891/* the rest are the remapped stdio routines */
892DllExport FILE *
893win32_stderr(void)
0a753a76 894{
390b85e7 895 return (stderr);
0a753a76 896}
897
68dc0745 898DllExport FILE *
899win32_stdin(void)
0a753a76 900{
390b85e7 901 return (stdin);
0a753a76 902}
903
68dc0745 904DllExport FILE *
905win32_stdout()
0a753a76 906{
390b85e7 907 return (stdout);
0a753a76 908}
909
68dc0745 910DllExport int
911win32_ferror(FILE *fp)
0a753a76 912{
390b85e7 913 return (ferror(fp));
0a753a76 914}
915
916
68dc0745 917DllExport int
918win32_feof(FILE *fp)
0a753a76 919{
390b85e7 920 return (feof(fp));
0a753a76 921}
922
68dc0745 923/*
924 * Since the errors returned by the socket error function
925 * WSAGetLastError() are not known by the library routine strerror
926 * we have to roll our own.
927 */
0a753a76 928
929__declspec(thread) char strerror_buffer[512];
930
68dc0745 931DllExport char *
932win32_strerror(int e)
0a753a76 933{
3e3baf6d 934#ifndef __BORLANDC__ /* Borland intolerance */
68dc0745 935 extern int sys_nerr;
3e3baf6d 936#endif
68dc0745 937 DWORD source = 0;
0a753a76 938
68dc0745 939 if(e < 0 || e > sys_nerr) {
940 if(e < 0)
941 e = GetLastError();
0a753a76 942
68dc0745 943 if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0,
944 strerror_buffer, sizeof(strerror_buffer), NULL) == 0)
945 strcpy(strerror_buffer, "Unknown Error");
0a753a76 946
68dc0745 947 return strerror_buffer;
948 }
390b85e7 949 return strerror(e);
0a753a76 950}
951
68dc0745 952DllExport int
953win32_fprintf(FILE *fp, const char *format, ...)
0a753a76 954{
68dc0745 955 va_list marker;
956 va_start(marker, format); /* Initialize variable arguments. */
0a753a76 957
390b85e7 958 return (vfprintf(fp, format, marker));
0a753a76 959}
960
68dc0745 961DllExport int
962win32_printf(const char *format, ...)
0a753a76 963{
68dc0745 964 va_list marker;
965 va_start(marker, format); /* Initialize variable arguments. */
0a753a76 966
390b85e7 967 return (vprintf(format, marker));
0a753a76 968}
969
68dc0745 970DllExport int
971win32_vfprintf(FILE *fp, const char *format, va_list args)
0a753a76 972{
390b85e7 973 return (vfprintf(fp, format, args));
0a753a76 974}
975
96e4d5b1 976DllExport int
977win32_vprintf(const char *format, va_list args)
978{
390b85e7 979 return (vprintf(format, args));
96e4d5b1 980}
981
68dc0745 982DllExport size_t
983win32_fread(void *buf, size_t size, size_t count, FILE *fp)
0a753a76 984{
390b85e7 985 return fread(buf, size, count, fp);
0a753a76 986}
987
68dc0745 988DllExport size_t
989win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
0a753a76 990{
390b85e7 991 return fwrite(buf, size, count, fp);
0a753a76 992}
993
68dc0745 994DllExport FILE *
995win32_fopen(const char *filename, const char *mode)
0a753a76 996{
68dc0745 997 if (stricmp(filename, "/dev/null")==0)
390b85e7 998 return fopen("NUL", mode);
999 return fopen(filename, mode);
0a753a76 1000}
1001
f3986ebb 1002#ifndef USE_SOCKETS_AS_HANDLES
1003#undef fdopen
1004#define fdopen my_fdopen
1005#endif
1006
68dc0745 1007DllExport FILE *
1008win32_fdopen( int handle, const char *mode)
0a753a76 1009{
390b85e7 1010 return fdopen(handle, (char *) mode);
0a753a76 1011}
1012
68dc0745 1013DllExport FILE *
1014win32_freopen( const char *path, const char *mode, FILE *stream)
0a753a76 1015{
68dc0745 1016 if (stricmp(path, "/dev/null")==0)
390b85e7 1017 return freopen("NUL", mode, stream);
1018 return freopen(path, mode, stream);
0a753a76 1019}
1020
68dc0745 1021DllExport int
1022win32_fclose(FILE *pf)
0a753a76 1023{
f3986ebb 1024 return my_fclose(pf); /* defined in win32sck.c */
0a753a76 1025}
1026
68dc0745 1027DllExport int
1028win32_fputs(const char *s,FILE *pf)
0a753a76 1029{
390b85e7 1030 return fputs(s, pf);
0a753a76 1031}
1032
68dc0745 1033DllExport int
1034win32_fputc(int c,FILE *pf)
0a753a76 1035{
390b85e7 1036 return fputc(c,pf);
0a753a76 1037}
1038
68dc0745 1039DllExport int
1040win32_ungetc(int c,FILE *pf)
0a753a76 1041{
390b85e7 1042 return ungetc(c,pf);
0a753a76 1043}
1044
68dc0745 1045DllExport int
1046win32_getc(FILE *pf)
0a753a76 1047{
390b85e7 1048 return getc(pf);
0a753a76 1049}
1050
68dc0745 1051DllExport int
1052win32_fileno(FILE *pf)
0a753a76 1053{
390b85e7 1054 return fileno(pf);
0a753a76 1055}
1056
68dc0745 1057DllExport void
1058win32_clearerr(FILE *pf)
0a753a76 1059{
390b85e7 1060 clearerr(pf);
68dc0745 1061 return;
0a753a76 1062}
1063
68dc0745 1064DllExport int
1065win32_fflush(FILE *pf)
0a753a76 1066{
390b85e7 1067 return fflush(pf);
0a753a76 1068}
1069
68dc0745 1070DllExport long
1071win32_ftell(FILE *pf)
0a753a76 1072{
390b85e7 1073 return ftell(pf);
0a753a76 1074}
1075
68dc0745 1076DllExport int
1077win32_fseek(FILE *pf,long offset,int origin)
0a753a76 1078{
390b85e7 1079 return fseek(pf, offset, origin);
0a753a76 1080}
1081
68dc0745 1082DllExport int
1083win32_fgetpos(FILE *pf,fpos_t *p)
0a753a76 1084{
390b85e7 1085 return fgetpos(pf, p);
0a753a76 1086}
1087
68dc0745 1088DllExport int
1089win32_fsetpos(FILE *pf,const fpos_t *p)
0a753a76 1090{
390b85e7 1091 return fsetpos(pf, p);
0a753a76 1092}
1093
68dc0745 1094DllExport void
1095win32_rewind(FILE *pf)
0a753a76 1096{
390b85e7 1097 rewind(pf);
68dc0745 1098 return;
0a753a76 1099}
1100
68dc0745 1101DllExport FILE*
1102win32_tmpfile(void)
0a753a76 1103{
390b85e7 1104 return tmpfile();
0a753a76 1105}
1106
68dc0745 1107DllExport void
1108win32_abort(void)
0a753a76 1109{
390b85e7 1110 abort();
68dc0745 1111 return;
0a753a76 1112}
1113
68dc0745 1114DllExport int
1115win32_fstat(int fd,struct stat *bufptr)
0a753a76 1116{
390b85e7 1117 return fstat(fd,bufptr);
0a753a76 1118}
1119
68dc0745 1120DllExport int
1121win32_pipe(int *pfd, unsigned int size, int mode)
0a753a76 1122{
390b85e7 1123 return _pipe(pfd, size, mode);
0a753a76 1124}
1125
68dc0745 1126DllExport FILE*
1127win32_popen(const char *command, const char *mode)
0a753a76 1128{
a835ef8a 1129#ifdef __GNUC__
1130 return NULL;
1131#else
390b85e7 1132 return _popen(command, mode);
a835ef8a 1133#endif
0a753a76 1134}
1135
68dc0745 1136DllExport int
1137win32_pclose(FILE *pf)
0a753a76 1138{
a835ef8a 1139#ifdef __GNUC__
1140 return fclose(pf);
1141#else
390b85e7 1142 return _pclose(pf);
a835ef8a 1143#endif
0a753a76 1144}
1145
68dc0745 1146DllExport int
1147win32_setmode(int fd, int mode)
0a753a76 1148{
390b85e7 1149 return setmode(fd, mode);
0a753a76 1150}
1151
96e4d5b1 1152DllExport long
1153win32_lseek(int fd, long offset, int origin)
1154{
390b85e7 1155 return lseek(fd, offset, origin);
96e4d5b1 1156}
1157
1158DllExport long
1159win32_tell(int fd)
1160{
390b85e7 1161 return tell(fd);
96e4d5b1 1162}
1163
68dc0745 1164DllExport int
1165win32_open(const char *path, int flag, ...)
0a753a76 1166{
68dc0745 1167 va_list ap;
1168 int pmode;
0a753a76 1169
1170 va_start(ap, flag);
1171 pmode = va_arg(ap, int);
1172 va_end(ap);
1173
68dc0745 1174 if (stricmp(path, "/dev/null")==0)
390b85e7 1175 return open("NUL", flag, pmode);
1176 return open(path,flag,pmode);
0a753a76 1177}
1178
68dc0745 1179DllExport int
1180win32_close(int fd)
0a753a76 1181{
390b85e7 1182 return close(fd);
0a753a76 1183}
1184
68dc0745 1185DllExport int
96e4d5b1 1186win32_eof(int fd)
1187{
390b85e7 1188 return eof(fd);
96e4d5b1 1189}
1190
1191DllExport int
68dc0745 1192win32_dup(int fd)
0a753a76 1193{
390b85e7 1194 return dup(fd);
0a753a76 1195}
1196
68dc0745 1197DllExport int
1198win32_dup2(int fd1,int fd2)
0a753a76 1199{
390b85e7 1200 return dup2(fd1,fd2);
0a753a76 1201}
1202
68dc0745 1203DllExport int
3e3baf6d 1204win32_read(int fd, void *buf, unsigned int cnt)
0a753a76 1205{
390b85e7 1206 return read(fd, buf, cnt);
0a753a76 1207}
1208
68dc0745 1209DllExport int
3e3baf6d 1210win32_write(int fd, const void *buf, unsigned int cnt)
0a753a76 1211{
390b85e7 1212 return write(fd, buf, cnt);
0a753a76 1213}
1214
68dc0745 1215DllExport int
5aabfad6 1216win32_mkdir(const char *dir, int mode)
1217{
390b85e7 1218 return mkdir(dir); /* just ignore mode */
5aabfad6 1219}
96e4d5b1 1220
5aabfad6 1221DllExport int
1222win32_rmdir(const char *dir)
1223{
390b85e7 1224 return rmdir(dir);
5aabfad6 1225}
96e4d5b1 1226
5aabfad6 1227DllExport int
1228win32_chdir(const char *dir)
1229{
390b85e7 1230 return chdir(dir);
5aabfad6 1231}
96e4d5b1 1232
5aabfad6 1233DllExport int
3e3baf6d 1234win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
0a753a76 1235{
390b85e7 1236 return spawnvp(mode, cmdname, (char * const *) argv);
0a753a76 1237}
1238
6890e559 1239DllExport int
1240win32_execvp(const char *cmdname, const char *const *argv)
1241{
390b85e7 1242 return execvp(cmdname, (char *const *)argv);
6890e559 1243}
1244
84902520 1245DllExport void
1246win32_perror(const char *str)
1247{
390b85e7 1248 perror(str);
84902520 1249}
1250
1251DllExport void
1252win32_setbuf(FILE *pf, char *buf)
1253{
390b85e7 1254 setbuf(pf, buf);
84902520 1255}
1256
1257DllExport int
1258win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
1259{
390b85e7 1260 return setvbuf(pf, buf, type, size);
84902520 1261}
1262
1263DllExport int
1264win32_flushall(void)
1265{
a835ef8a 1266#ifndef __GNUC__
390b85e7 1267 return flushall();
a835ef8a 1268#endif
84902520 1269}
1270
1271DllExport int
1272win32_fcloseall(void)
1273{
a835ef8a 1274#ifndef __GNUC__
390b85e7 1275 return fcloseall();
a835ef8a 1276#endif
84902520 1277}
1278
1279DllExport char*
1280win32_fgets(char *s, int n, FILE *pf)
1281{
390b85e7 1282 return fgets(s, n, pf);
84902520 1283}
1284
1285DllExport char*
1286win32_gets(char *s)
1287{
390b85e7 1288 return gets(s);
84902520 1289}
1290
1291DllExport int
1292win32_fgetc(FILE *pf)
1293{
390b85e7 1294 return fgetc(pf);
84902520 1295}
1296
1297DllExport int
1298win32_putc(int c, FILE *pf)
1299{
390b85e7 1300 return putc(c,pf);
84902520 1301}
1302
1303DllExport int
1304win32_puts(const char *s)
1305{
390b85e7 1306 return puts(s);
84902520 1307}
1308
1309DllExport int
1310win32_getchar(void)
1311{
390b85e7 1312 return getchar();
84902520 1313}
1314
1315DllExport int
1316win32_putchar(int c)
1317{
390b85e7 1318 return putchar(c);
84902520 1319}
1320
bbc8f9de 1321#ifdef MYMALLOC
1322
1323#ifndef USE_PERL_SBRK
1324
1325static char *committed = NULL;
1326static char *base = NULL;
1327static char *reserved = NULL;
1328static char *brk = NULL;
1329static DWORD pagesize = 0;
1330static DWORD allocsize = 0;
1331
1332void *
1333sbrk(int need)
1334{
1335 void *result;
1336 if (!pagesize)
1337 {SYSTEM_INFO info;
1338 GetSystemInfo(&info);
1339 /* Pretend page size is larger so we don't perpetually
1340 * call the OS to commit just one page ...
1341 */
1342 pagesize = info.dwPageSize << 3;
1343 allocsize = info.dwAllocationGranularity;
1344 }
1345 /* This scheme fails eventually if request for contiguous
1346 * block is denied so reserve big blocks - this is only
1347 * address space not memory ...
1348 */
1349 if (brk+need >= reserved)
1350 {
1351 DWORD size = 64*1024*1024;
1352 char *addr;
1353 if (committed && reserved && committed < reserved)
1354 {
1355 /* Commit last of previous chunk cannot span allocations */
161b471a 1356 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
bbc8f9de 1357 if (addr)
1358 committed = reserved;
1359 }
1360 /* Reserve some (more) space
1361 * Note this is a little sneaky, 1st call passes NULL as reserved
1362 * so lets system choose where we start, subsequent calls pass
1363 * the old end address so ask for a contiguous block
1364 */
161b471a 1365 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
bbc8f9de 1366 if (addr)
1367 {
1368 reserved = addr+size;
1369 if (!base)
1370 base = addr;
1371 if (!committed)
1372 committed = base;
1373 if (!brk)
1374 brk = committed;
1375 }
1376 else
1377 {
1378 return (void *) -1;
1379 }
1380 }
1381 result = brk;
1382 brk += need;
1383 if (brk > committed)
1384 {
1385 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
161b471a 1386 char *addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
bbc8f9de 1387 if (addr)
1388 {
1389 committed += size;
1390 }
1391 else
1392 return (void *) -1;
1393 }
1394 return result;
1395}
1396
1397#endif
1398#endif
1399
84902520 1400DllExport void*
1401win32_malloc(size_t size)
1402{
390b85e7 1403 return malloc(size);
84902520 1404}
1405
1406DllExport void*
1407win32_calloc(size_t numitems, size_t size)
1408{
390b85e7 1409 return calloc(numitems,size);
84902520 1410}
1411
1412DllExport void*
1413win32_realloc(void *block, size_t size)
1414{
390b85e7 1415 return realloc(block,size);
84902520 1416}
1417
1418DllExport void
1419win32_free(void *block)
1420{
390b85e7 1421 free(block);
84902520 1422}
1423
bbc8f9de 1424
68dc0745 1425int
65e48ea9 1426win32_open_osfhandle(long handle, int flags)
0a753a76 1427{
390b85e7 1428 return _open_osfhandle(handle, flags);
0a753a76 1429}
1430
68dc0745 1431long
65e48ea9 1432win32_get_osfhandle(int fd)
0a753a76 1433{
390b85e7 1434 return _get_osfhandle(fd);
0a753a76 1435}
7bac28a0 1436
7bac28a0 1437/*
1438 * Extras.
1439 */
1440
ad2e33dc 1441static
1442XS(w32_GetCwd)
1443{
1444 dXSARGS;
1445 SV *sv = sv_newmortal();
1446 /* Make one call with zero size - return value is required size */
1447 DWORD len = GetCurrentDirectory((DWORD)0,NULL);
1448 SvUPGRADE(sv,SVt_PV);
1449 SvGROW(sv,len);
1450 SvCUR(sv) = GetCurrentDirectory((DWORD) SvLEN(sv), SvPVX(sv));
1451 /*
1452 * If result != 0
1453 * then it worked, set PV valid,
1454 * else leave it 'undef'
1455 */
1456 if (SvCUR(sv))
1457 SvPOK_on(sv);
1458 EXTEND(sp,1);
1459 ST(0) = sv;
1460 XSRETURN(1);
1461}
1462
1463static
1464XS(w32_SetCwd)
1465{
1466 dXSARGS;
1467 if (items != 1)
1468 croak("usage: Win32::SetCurrentDirectory($cwd)");
1469 if (SetCurrentDirectory(SvPV(ST(0),na)))
1470 XSRETURN_YES;
1471
1472 XSRETURN_NO;
1473}
1474
1475static
1476XS(w32_GetNextAvailDrive)
1477{
1478 dXSARGS;
1479 char ix = 'C';
1480 char root[] = "_:\\";
1481 while (ix <= 'Z') {
1482 root[0] = ix++;
1483 if (GetDriveType(root) == 1) {
1484 root[2] = '\0';
1485 XSRETURN_PV(root);
1486 }
1487 }
1488 XSRETURN_UNDEF;
1489}
1490
1491static
1492XS(w32_GetLastError)
1493{
1494 dXSARGS;
1495 XSRETURN_IV(GetLastError());
1496}
1497
1498static
1499XS(w32_LoginName)
1500{
1501 dXSARGS;
1502 char name[256];
1503 DWORD size = sizeof(name);
1504 if (GetUserName(name,&size)) {
1505 /* size includes NULL */
1506 ST(0) = sv_2mortal(newSVpv(name,size-1));
1507 XSRETURN(1);
1508 }
1509 XSRETURN_UNDEF;
1510}
1511
1512static
1513XS(w32_NodeName)
1514{
1515 dXSARGS;
1516 char name[MAX_COMPUTERNAME_LENGTH+1];
1517 DWORD size = sizeof(name);
1518 if (GetComputerName(name,&size)) {
1519 /* size does NOT include NULL :-( */
1520 ST(0) = sv_2mortal(newSVpv(name,size));
1521 XSRETURN(1);
1522 }
1523 XSRETURN_UNDEF;
1524}
1525
1526
1527static
1528XS(w32_DomainName)
1529{
1530 dXSARGS;
1531 char name[256];
1532 DWORD size = sizeof(name);
1533 if (GetUserName(name,&size)) {
1534 char sid[1024];
1535 DWORD sidlen = sizeof(sid);
1536 char dname[256];
1537 DWORD dnamelen = sizeof(dname);
1538 SID_NAME_USE snu;
1539 if (LookupAccountName(NULL, name, &sid, &sidlen,
1540 dname, &dnamelen, &snu)) {
1541 XSRETURN_PV(dname); /* all that for this */
1542 }
1543 }
1544 XSRETURN_UNDEF;
1545}
1546
1547static
1548XS(w32_FsType)
1549{
1550 dXSARGS;
1551 char fsname[256];
1552 DWORD flags, filecomplen;
1553 if (GetVolumeInformation(NULL, NULL, 0, NULL, &filecomplen,
1554 &flags, fsname, sizeof(fsname))) {
1555 if (GIMME == G_ARRAY) {
1556 XPUSHs(sv_2mortal(newSVpv(fsname,0)));
1557 XPUSHs(sv_2mortal(newSViv(flags)));
1558 XPUSHs(sv_2mortal(newSViv(filecomplen)));
1559 PUTBACK;
1560 return;
1561 }
1562 XSRETURN_PV(fsname);
1563 }
1564 XSRETURN_UNDEF;
1565}
1566
1567static
1568XS(w32_GetOSVersion)
1569{
1570 dXSARGS;
1571 OSVERSIONINFO osver;
1572
1573 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1574 if (GetVersionEx(&osver)) {
1575 XPUSHs(newSVpv(osver.szCSDVersion, 0));
1576 XPUSHs(newSViv(osver.dwMajorVersion));
1577 XPUSHs(newSViv(osver.dwMinorVersion));
1578 XPUSHs(newSViv(osver.dwBuildNumber));
1579 XPUSHs(newSViv(osver.dwPlatformId));
1580 PUTBACK;
1581 return;
1582 }
1583 XSRETURN_UNDEF;
1584}
1585
1586static
1587XS(w32_IsWinNT)
1588{
1589 dXSARGS;
1590 XSRETURN_IV(IsWinNT());
1591}
1592
1593static
1594XS(w32_IsWin95)
1595{
1596 dXSARGS;
1597 XSRETURN_IV(IsWin95());
1598}
1599
1600static
1601XS(w32_FormatMessage)
1602{
1603 dXSARGS;
1604 DWORD source = 0;
1605 char msgbuf[1024];
1606
1607 if (items != 1)
1608 croak("usage: Win32::FormatMessage($errno)");
1609
1610 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1611 &source, SvIV(ST(0)), 0,
1612 msgbuf, sizeof(msgbuf)-1, NULL))
1613 XSRETURN_PV(msgbuf);
1614
1615 XSRETURN_UNDEF;
1616}
1617
1618static
1619XS(w32_Spawn)
1620{
1621 dXSARGS;
1622 char *cmd, *args;
1623 PROCESS_INFORMATION stProcInfo;
1624 STARTUPINFO stStartInfo;
1625 BOOL bSuccess = FALSE;
1626
1627 if(items != 3)
1628 croak("usage: Win32::Spawn($cmdName, $args, $PID)");
1629
1630 cmd = SvPV(ST(0),na);
1631 args = SvPV(ST(1), na);
1632
1633 memset(&stStartInfo, 0, sizeof(stStartInfo)); /* Clear the block */
1634 stStartInfo.cb = sizeof(stStartInfo); /* Set the structure size */
1635 stStartInfo.dwFlags = STARTF_USESHOWWINDOW; /* Enable wShowWindow control */
1636 stStartInfo.wShowWindow = SW_SHOWMINNOACTIVE; /* Start min (normal) */
1637
1638 if(CreateProcess(
1639 cmd, /* Image path */
1640 args, /* Arguments for command line */
1641 NULL, /* Default process security */
1642 NULL, /* Default thread security */
1643 FALSE, /* Must be TRUE to use std handles */
1644 NORMAL_PRIORITY_CLASS, /* No special scheduling */
1645 NULL, /* Inherit our environment block */
1646 NULL, /* Inherit our currrent directory */
1647 &stStartInfo, /* -> Startup info */
1648 &stProcInfo)) /* <- Process info (if OK) */
1649 {
1650 CloseHandle(stProcInfo.hThread);/* library source code does this. */
1651 sv_setiv(ST(2), stProcInfo.dwProcessId);
1652 bSuccess = TRUE;
1653 }
1654 XSRETURN_IV(bSuccess);
1655}
1656
1657static
1658XS(w32_GetTickCount)
1659{
1660 dXSARGS;
1661 XSRETURN_IV(GetTickCount());
1662}
1663
1664static
1665XS(w32_GetShortPathName)
1666{
1667 dXSARGS;
1668 SV *shortpath;
e8bab181 1669 DWORD len;
ad2e33dc 1670
1671 if(items != 1)
1672 croak("usage: Win32::GetShortPathName($longPathName)");
1673
1674 shortpath = sv_mortalcopy(ST(0));
1675 SvUPGRADE(shortpath, SVt_PV);
1676 /* src == target is allowed */
e8bab181 1677 do {
1678 len = GetShortPathName(SvPVX(shortpath),
1679 SvPVX(shortpath),
1680 SvLEN(shortpath));
1681 } while (len >= SvLEN(shortpath) && sv_grow(shortpath,len+1));
1682 if (len) {
1683 SvCUR_set(shortpath,len);
ad2e33dc 1684 ST(0) = shortpath;
e8bab181 1685 }
ad2e33dc 1686 else
1687 ST(0) = &sv_undef;
1688 XSRETURN(1);
1689}
1690
1691void
f3986ebb 1692Perl_init_os_extras()
ad2e33dc 1693{
1694 char *file = __FILE__;
1695 dXSUB_SYS;
1696
1697 /* XXX should be removed after checking with Nick */
1698 newXS("Win32::GetCurrentDirectory", w32_GetCwd, file);
1699
1700 /* these names are Activeware compatible */
1701 newXS("Win32::GetCwd", w32_GetCwd, file);
1702 newXS("Win32::SetCwd", w32_SetCwd, file);
1703 newXS("Win32::GetNextAvailDrive", w32_GetNextAvailDrive, file);
1704 newXS("Win32::GetLastError", w32_GetLastError, file);
1705 newXS("Win32::LoginName", w32_LoginName, file);
1706 newXS("Win32::NodeName", w32_NodeName, file);
1707 newXS("Win32::DomainName", w32_DomainName, file);
1708 newXS("Win32::FsType", w32_FsType, file);
1709 newXS("Win32::GetOSVersion", w32_GetOSVersion, file);
1710 newXS("Win32::IsWinNT", w32_IsWinNT, file);
1711 newXS("Win32::IsWin95", w32_IsWin95, file);
1712 newXS("Win32::FormatMessage", w32_FormatMessage, file);
1713 newXS("Win32::Spawn", w32_Spawn, file);
1714 newXS("Win32::GetTickCount", w32_GetTickCount, file);
1715 newXS("Win32::GetShortPathName", w32_GetShortPathName, file);
1716
1717 /* XXX Bloat Alert! The following Activeware preloads really
1718 * ought to be part of Win32::Sys::*, so they're not included
1719 * here.
1720 */
1721 /* LookupAccountName
1722 * LookupAccountSID
1723 * InitiateSystemShutdown
1724 * AbortSystemShutdown
1725 * ExpandEnvrironmentStrings
1726 */
1727}
1728
1729void
1730Perl_win32_init(int *argcp, char ***argvp)
1731{
1732 /* Disable floating point errors, Perl will trap the ones we
1733 * care about. VC++ RTL defaults to switching these off
1734 * already, but the Borland RTL doesn't. Since we don't
1735 * want to be at the vendor's whim on the default, we set
1736 * it explicitly here.
1737 */
a835ef8a 1738#if !defined(_ALPHA_) && !defined(__GNUC__)
ad2e33dc 1739 _control87(MCW_EM, MCW_EM);
3dc9191e 1740#endif
ad2e33dc 1741}
d55594ae 1742
a868473f 1743#ifdef USE_BINMODE_SCRIPTS
1744
1745void
1746win32_strip_return(SV *sv)
1747{
1748 char *s = SvPVX(sv);
1749 char *e = s+SvCUR(sv);
1750 char *d = s;
1751 while (s < e)
1752 {
1753 if (*s == '\r' && s[1] == '\n')
1754 {
1755 *d++ = '\n';
1756 s += 2;
1757 }
1758 else
1759 {
1760 *d++ = *s++;
1761 }
1762 }
1763 SvCUR_set(sv,d-SvPVX(sv));
1764}
1765
1766#endif
1767
1768
d55594ae 1769
1770
1771
161b471a 1772
a835ef8a 1773