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