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