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