integrate makefile.mk changes into Makefile
[p5sagit/p5-mst-13.2.git] / wince / wince.c
CommitLineData
e1caacb4 1/* WINCE.C - stuff for Windows CE
2 *
ca6c63e1 3 * Time-stamp: <26/10/01 15:25:20 keuchel@keuchelnt>
e1caacb4 4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 */
8
9#define WIN32_LEAN_AND_MEAN
10#define WIN32IO_IS_STDIO
11#include <windows.h>
12
13#define PERLIO_NOT_STDIO 0
14
15#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
16#define PerlIO FILE
17#endif
18
19#define wince_private
20#include "errno.h"
21
22#include "EXTERN.h"
23#include "perl.h"
24
25#define NO_XSLOCKS
26#define PERL_NO_GET_CONTEXT
27#include "XSUB.h"
28
29#include "win32iop.h"
30#include <string.h>
31#include <stdarg.h>
32#include <float.h>
33#include <shellapi.h>
34
35#define perl
36#include "celib_defs.h"
37#include "cewin32.h"
38#include "cecrt.h"
39#include "cewin32_defs.h"
40#include "cecrt_defs.h"
41
42#ifdef PALM_SIZE
43#include "stdio-palmsize.h"
44#endif
45
46#define EXECF_EXEC 1
47#define EXECF_SPAWN 2
48#define EXECF_SPAWN_NOWAIT 3
49
50#if defined(PERL_IMPLICIT_SYS)
51# undef win32_get_privlib
52# define win32_get_privlib g_win32_get_privlib
53# undef win32_get_sitelib
54# define win32_get_sitelib g_win32_get_sitelib
55# undef win32_get_vendorlib
56# define win32_get_vendorlib g_win32_get_vendorlib
57# undef do_spawn
58# define do_spawn g_do_spawn
59# undef getlogin
60# define getlogin g_getlogin
61#endif
62
e1caacb4 63static long filetime_to_clock(PFILETIME ft);
64static BOOL filetime_from_time(PFILETIME ft, time_t t);
65static char * get_emd_part(SV **leading, char *trailing, ...);
66static char * win32_get_xlib(const char *pl, const char *xlib,
67 const char *libname);
68
69START_EXTERN_C
70HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
71char w32_module_name[MAX_PATH+1];
72END_EXTERN_C
73
74static DWORD w32_platform = (DWORD)-1;
75
76int
77IsWin95(void)
78{
79 return (win32_os_id() == VER_PLATFORM_WIN32_WINDOWS);
80}
81
82int
83IsWinNT(void)
84{
85 return (win32_os_id() == VER_PLATFORM_WIN32_NT);
86}
87
88int
89IsWinCE(void)
90{
91 return (win32_os_id() == VER_PLATFORM_WIN32_CE);
92}
93
94EXTERN_C void
95set_w32_module_name(void)
96{
97 char* ptr;
98 XCEGetModuleFileNameA((HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
99 ? XCEGetModuleHandleA(NULL)
100 : w32_perldll_handle),
101 w32_module_name, sizeof(w32_module_name));
102
103 /* normalize to forward slashes */
104 ptr = w32_module_name;
105 while (*ptr) {
106 if (*ptr == '\\')
107 *ptr = '/';
108 ++ptr;
109 }
110}
111
112/* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
113static char*
114get_regstr_from(HKEY hkey, const char *valuename, SV **svp)
115{
116 /* Retrieve a REG_SZ or REG_EXPAND_SZ from the registry */
117 HKEY handle;
118 DWORD type;
119 const char *subkey = "Software\\Perl";
120 char *str = Nullch;
121 long retval;
122
123 retval = XCERegOpenKeyExA(hkey, subkey, 0, KEY_READ, &handle);
124 if (retval == ERROR_SUCCESS) {
125 DWORD datalen;
126 retval = XCERegQueryValueExA(handle, valuename, 0, &type, NULL, &datalen);
127 if (retval == ERROR_SUCCESS && type == REG_SZ) {
acfe0abc 128 dTHX;
e1caacb4 129 if (!*svp)
130 *svp = sv_2mortal(newSVpvn("",0));
131 SvGROW(*svp, datalen);
132 retval = XCERegQueryValueExA(handle, valuename, 0, NULL,
133 (PBYTE)SvPVX(*svp), &datalen);
134 if (retval == ERROR_SUCCESS) {
135 str = SvPVX(*svp);
136 SvCUR_set(*svp,datalen-1);
137 }
138 }
139 RegCloseKey(handle);
140 }
141 return str;
142}
143
144/* *svp (if non-NULL) is expected to be POK (valid allocated SvPVX(*svp)) */
145static char*
146get_regstr(const char *valuename, SV **svp)
147{
148 char *str = get_regstr_from(HKEY_CURRENT_USER, valuename, svp);
149 if (!str)
150 str = get_regstr_from(HKEY_LOCAL_MACHINE, valuename, svp);
151 return str;
152}
153
154/* *prev_pathp (if non-NULL) is expected to be POK (valid allocated SvPVX(sv)) */
155static char *
156get_emd_part(SV **prev_pathp, char *trailing_path, ...)
157{
158 char base[10];
159 va_list ap;
160 char mod_name[MAX_PATH+1];
161 char *ptr;
162 char *optr;
163 char *strip;
164 int oldsize, newsize;
165 STRLEN baselen;
166
167 va_start(ap, trailing_path);
168 strip = va_arg(ap, char *);
169
170 sprintf(base, "%d.%d", (int)PERL_REVISION, (int)PERL_VERSION);
171 baselen = strlen(base);
172
173 if (!*w32_module_name) {
174 set_w32_module_name();
175 }
176 strcpy(mod_name, w32_module_name);
177 ptr = strrchr(mod_name, '/');
178 while (ptr && strip) {
179 /* look for directories to skip back */
180 optr = ptr;
181 *ptr = '\0';
182 ptr = strrchr(mod_name, '/');
183 /* avoid stripping component if there is no slash,
184 * or it doesn't match ... */
185 if (!ptr || stricmp(ptr+1, strip) != 0) {
186 /* ... but not if component matches m|5\.$patchlevel.*| */
187 if (!ptr || !(*strip == '5' && *(ptr+1) == '5'
188 && strncmp(strip, base, baselen) == 0
189 && strncmp(ptr+1, base, baselen) == 0))
190 {
191 *optr = '/';
192 ptr = optr;
193 }
194 }
195 strip = va_arg(ap, char *);
196 }
197 if (!ptr) {
198 ptr = mod_name;
199 *ptr++ = '.';
200 *ptr = '/';
201 }
202 va_end(ap);
203 strcpy(++ptr, trailing_path);
204
205 /* only add directory if it exists */
206 if (XCEGetFileAttributesA(mod_name) != (DWORD) -1) {
207 /* directory exists */
acfe0abc 208 dTHX;
e1caacb4 209 if (!*prev_pathp)
210 *prev_pathp = sv_2mortal(newSVpvn("",0));
211 sv_catpvn(*prev_pathp, ";", 1);
212 sv_catpv(*prev_pathp, mod_name);
213 return SvPVX(*prev_pathp);
214 }
215
216 return Nullch;
217}
218
219char *
220win32_get_privlib(const char *pl)
221{
acfe0abc 222 dTHX;
e1caacb4 223 char *stdlib = "lib";
224 char buffer[MAX_PATH+1];
225 SV *sv = Nullsv;
226
227 /* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
228 sprintf(buffer, "%s-%s", stdlib, pl);
229 if (!get_regstr(buffer, &sv))
230 (void)get_regstr(stdlib, &sv);
231
232 /* $stdlib .= ";$EMD/../../lib" */
233 return get_emd_part(&sv, stdlib, ARCHNAME, "bin", Nullch);
234}
235
236static char *
237win32_get_xlib(const char *pl, const char *xlib, const char *libname)
238{
acfe0abc 239 dTHX;
e1caacb4 240 char regstr[40];
241 char pathstr[MAX_PATH+1];
242 DWORD datalen;
243 int len, newsize;
244 SV *sv1 = Nullsv;
245 SV *sv2 = Nullsv;
246
247 /* $HKCU{"$xlib-$]"} || $HKLM{"$xlib-$]"} . ---; */
248 sprintf(regstr, "%s-%s", xlib, pl);
249 (void)get_regstr(regstr, &sv1);
250
251 /* $xlib .=
252 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/$]/lib"; */
253 sprintf(pathstr, "%s/%s/lib", libname, pl);
254 (void)get_emd_part(&sv1, pathstr, ARCHNAME, "bin", pl, Nullch);
255
256 /* $HKCU{$xlib} || $HKLM{$xlib} . ---; */
257 (void)get_regstr(xlib, &sv2);
258
259 /* $xlib .=
260 * ";$EMD/" . ((-d $EMD/../../../$]) ? "../../.." : "../.."). "/$libname/lib"; */
261 sprintf(pathstr, "%s/lib", libname);
262 (void)get_emd_part(&sv2, pathstr, ARCHNAME, "bin", pl, Nullch);
263
264 if (!sv1 && !sv2)
265 return Nullch;
266 if (!sv1)
267 return SvPVX(sv2);
268 if (!sv2)
269 return SvPVX(sv1);
270
271 sv_catpvn(sv1, ";", 1);
272 sv_catsv(sv1, sv2);
273
274 return SvPVX(sv1);
275}
276
277char *
278win32_get_sitelib(const char *pl)
279{
280 return win32_get_xlib(pl, "sitelib", "site");
281}
282
283#ifndef PERL_VENDORLIB_NAME
284# define PERL_VENDORLIB_NAME "vendor"
285#endif
286
287char *
288win32_get_vendorlib(const char *pl)
289{
290 return win32_get_xlib(pl, "vendorlib", PERL_VENDORLIB_NAME);
291}
292
293#if !defined(PERL_IMPLICIT_SYS)
294/* since the current process environment is being updated in util.c
295 * the library functions will get the correct environment
296 */
297PerlIO *
298Perl_my_popen(pTHX_ char *cmd, char *mode)
299{
300 printf("popen(%s)\n", cmd);
301
302 Perl_croak(aTHX_ PL_no_func, "popen");
303 return NULL;
304}
305
306long
307Perl_my_pclose(pTHX_ PerlIO *fp)
308{
309 Perl_croak(aTHX_ PL_no_func, "pclose");
310 return -1;
311}
312#endif
313
314DllExport unsigned long
315win32_os_id(void)
316{
317 static OSVERSIONINFOA osver;
318
319 if (osver.dwPlatformId != w32_platform) {
320 memset(&osver, 0, sizeof(OSVERSIONINFOA));
321 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
322 XCEGetVersionExA(&osver);
323 w32_platform = osver.dwPlatformId;
324 }
325 return (unsigned long)w32_platform;
326}
327
328DllExport int
329win32_getpid(void)
330{
331 return xcegetpid();
332}
333
334bool
335Perl_do_exec(pTHX_ char *cmd)
336{
337 Perl_croak_nocontext("exec() unimplemented on this platform");
338 return FALSE;
339}
340
341DllExport int
342win32_pipe(int *pfd, unsigned int size, int mode)
343{
344 Perl_croak(aTHX_ PL_no_func, "pipe");
345 return -1;
346}
347
348DllExport int
349win32_times(struct tms *timebuf)
350{
351 Perl_croak(aTHX_ PL_no_func, "times");
352 return -1;
353}
354
42165d27 355/* TODO */
356bool
357win32_signal()
358{
359 Perl_croak_nocontext("signal() TBD on this platform");
360 return FALSE;
361}
362DllExport void
363win32_clearenv()
364{
365 return;
366}
367
368
e1caacb4 369DllExport char ***
370win32_environ(void)
371{
372 return (&(environ));
373}
374
375DllExport DIR *
376win32_opendir(char *filename)
377{
378 return opendir(filename);
379}
380
381DllExport struct direct *
382win32_readdir(DIR *dirp)
383{
384 return readdir(dirp);
385}
386
387DllExport long
388win32_telldir(DIR *dirp)
389{
390 Perl_croak(aTHX_ PL_no_func, "telldir");
391 return -1;
392}
393
394DllExport void
395win32_seekdir(DIR *dirp, long loc)
396{
397 Perl_croak(aTHX_ PL_no_func, "seekdir");
398}
399
400DllExport void
401win32_rewinddir(DIR *dirp)
402{
403 Perl_croak(aTHX_ PL_no_func, "rewinddir");
404}
405
406DllExport int
407win32_closedir(DIR *dirp)
408{
409 closedir(dirp);
410 return 0;
411}
412
413DllExport int
414win32_kill(int pid, int sig)
415{
416 Perl_croak(aTHX_ PL_no_func, "kill");
417 return -1;
418}
419
420DllExport unsigned int
421win32_sleep(unsigned int t)
422{
423 return xcesleep(t);
424}
425
426DllExport int
427win32_stat(const char *path, struct stat *sbuf)
428{
429 return xcestat(path, sbuf);
430}
431
432DllExport char *
433win32_longpath(char *path)
434{
435 return path;
436}
437
438#ifndef USE_WIN32_RTL_ENV
439
440DllExport char *
441win32_getenv(const char *name)
442{
443 return xcegetenv(name);
444}
445
446DllExport int
447win32_putenv(const char *name)
448{
449 return xceputenv(name);
450}
451
452#endif
453
454static long
455filetime_to_clock(PFILETIME ft)
456{
457 __int64 qw = ft->dwHighDateTime;
458 qw <<= 32;
459 qw |= ft->dwLowDateTime;
460 qw /= 10000; /* File time ticks at 0.1uS, clock at 1mS */
461 return (long) qw;
462}
463
464/* fix utime() so it works on directories in NT */
465static BOOL
466filetime_from_time(PFILETIME pFileTime, time_t Time)
467{
468 struct tm *pTM = localtime(&Time);
469 SYSTEMTIME SystemTime;
470 FILETIME LocalTime;
471
472 if (pTM == NULL)
473 return FALSE;
474
475 SystemTime.wYear = pTM->tm_year + 1900;
476 SystemTime.wMonth = pTM->tm_mon + 1;
477 SystemTime.wDay = pTM->tm_mday;
478 SystemTime.wHour = pTM->tm_hour;
479 SystemTime.wMinute = pTM->tm_min;
480 SystemTime.wSecond = pTM->tm_sec;
481 SystemTime.wMilliseconds = 0;
482
483 return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
484 LocalFileTimeToFileTime(&LocalTime, pFileTime);
485}
486
487DllExport int
488win32_unlink(const char *filename)
489{
490 return xceunlink(filename);
491}
492
493DllExport int
494win32_utime(const char *filename, struct utimbuf *times)
495{
496 return xceutime(filename, (struct _utimbuf *) times);
497}
498
499DllExport int
500win32_uname(struct utsname *name)
501{
502 struct hostent *hep;
503 STRLEN nodemax = sizeof(name->nodename)-1;
504 OSVERSIONINFOA osver;
505
506 memset(&osver, 0, sizeof(OSVERSIONINFOA));
507 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
508 if (XCEGetVersionExA(&osver)) {
509 /* sysname */
510 switch (osver.dwPlatformId) {
511 case VER_PLATFORM_WIN32_CE:
512 strcpy(name->sysname, "Windows CE");
513 break;
514 case VER_PLATFORM_WIN32_WINDOWS:
515 strcpy(name->sysname, "Windows");
516 break;
517 case VER_PLATFORM_WIN32_NT:
518 strcpy(name->sysname, "Windows NT");
519 break;
520 case VER_PLATFORM_WIN32s:
521 strcpy(name->sysname, "Win32s");
522 break;
523 default:
524 strcpy(name->sysname, "Win32 Unknown");
525 break;
526 }
527
528 /* release */
529 sprintf(name->release, "%d.%d",
530 osver.dwMajorVersion, osver.dwMinorVersion);
531
532 /* version */
533 sprintf(name->version, "Build %d",
534 osver.dwPlatformId == VER_PLATFORM_WIN32_NT
535 ? osver.dwBuildNumber : (osver.dwBuildNumber & 0xffff));
536 if (osver.szCSDVersion[0]) {
537 char *buf = name->version + strlen(name->version);
538 sprintf(buf, " (%s)", osver.szCSDVersion);
539 }
540 }
541 else {
542 *name->sysname = '\0';
543 *name->version = '\0';
544 *name->release = '\0';
545 }
546
547 /* nodename */
548 hep = win32_gethostbyname("localhost");
549 if (hep) {
550 STRLEN len = strlen(hep->h_name);
551 if (len <= nodemax) {
552 strcpy(name->nodename, hep->h_name);
553 }
554 else {
555 strncpy(name->nodename, hep->h_name, nodemax);
556 name->nodename[nodemax] = '\0';
557 }
558 }
559 else {
560 DWORD sz = nodemax;
561 if (!XCEGetComputerNameA(name->nodename, &sz))
562 *name->nodename = '\0';
563 }
564
565 /* machine (architecture) */
566 {
567 SYSTEM_INFO info;
568 char *arch;
569 GetSystemInfo(&info);
570
e1caacb4 571 switch (info.wProcessorArchitecture) {
e1caacb4 572 case PROCESSOR_ARCHITECTURE_INTEL:
573 arch = "x86"; break;
574 case PROCESSOR_ARCHITECTURE_MIPS:
575 arch = "mips"; break;
576 case PROCESSOR_ARCHITECTURE_ALPHA:
577 arch = "alpha"; break;
578 case PROCESSOR_ARCHITECTURE_PPC:
579 arch = "ppc"; break;
580 case PROCESSOR_ARCHITECTURE_ARM:
581 arch = "arm"; break;
582 case PROCESSOR_HITACHI_SH3:
583 arch = "sh3"; break;
584 case PROCESSOR_SHx_SH3:
585 arch = "sh3"; break;
586
587 default:
588 arch = "unknown"; break;
589 }
590 strcpy(name->machine, arch);
591 }
592 return 0;
593}
594
e1caacb4 595static UINT timerid = 0;
596
597static VOID CALLBACK TimerProc(HWND win, UINT msg, UINT id, DWORD time)
598{
acfe0abc 599 dTHX;
e1caacb4 600 KillTimer(NULL,timerid);
601 timerid=0;
602 sighandler(14);
603}
e1caacb4 604
605DllExport unsigned int
606win32_alarm(unsigned int sec)
607{
e1caacb4 608 /*
609 * the 'obvious' implentation is SetTimer() with a callback
610 * which does whatever receiving SIGALRM would do
611 * we cannot use SIGALRM even via raise() as it is not
612 * one of the supported codes in <signal.h>
613 *
614 * Snag is unless something is looking at the message queue
615 * nothing happens :-(
616 */
acfe0abc 617 dTHX;
e1caacb4 618 if (sec)
619 {
620 timerid = SetTimer(NULL,timerid,sec*1000,(TIMERPROC)TimerProc);
621 if (!timerid)
622 Perl_croak_nocontext("Cannot set timer");
623 }
624 else
625 {
626 if (timerid)
627 {
628 KillTimer(NULL,timerid);
629 timerid=0;
630 }
631 }
e1caacb4 632 return 0;
633}
634
635#ifdef HAVE_DES_FCRYPT
636extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
637#endif
638
639DllExport char *
640win32_crypt(const char *txt, const char *salt)
641{
acfe0abc 642 dTHX;
e1caacb4 643#ifdef HAVE_DES_FCRYPT
644 dTHR;
645 return des_fcrypt(txt, salt, w32_crypt_buffer);
646#else
647 Perl_croak(aTHX_ "The crypt() function is unimplemented due to excessive paranoia.");
648 return Nullch;
649#endif
650}
651
652/* C doesn't like repeat struct definitions */
653
654#if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX)
655
656#ifndef _CRTIMP
657#define _CRTIMP __declspec(dllimport)
658#endif
659
660/*
661 * Control structure for lowio file handles
662 */
663typedef struct {
664 long osfhnd; /* underlying OS file HANDLE */
665 char osfile; /* attributes of file (e.g., open in text mode?) */
666 char pipech; /* one char buffer for handles opened on pipes */
667 int lockinitflag;
668 CRITICAL_SECTION lock;
669} ioinfo;
670
671
672/*
673 * Array of arrays of control structures for lowio files.
674 */
675EXTERN_C _CRTIMP ioinfo* __pioinfo[];
676
677/*
678 * Definition of IOINFO_L2E, the log base 2 of the number of elements in each
679 * array of ioinfo structs.
680 */
681#define IOINFO_L2E 5
682
683/*
684 * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array
685 */
686#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
687
688/*
689 * Access macros for getting at an ioinfo struct and its fields from a
690 * file handle
691 */
692#define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)))
693#define _osfhnd(i) (_pioinfo(i)->osfhnd)
694#define _osfile(i) (_pioinfo(i)->osfile)
695#define _pipech(i) (_pioinfo(i)->pipech)
696
697#endif
698
699/*
700 * redirected io subsystem for all XS modules
701 *
702 */
703
704DllExport int *
705win32_errno(void)
706{
707 return (&errno);
708}
709
710/* the rest are the remapped stdio routines */
711DllExport FILE *
712win32_stderr(void)
713{
714 return (stderr);
715}
716
717DllExport FILE *
718win32_stdin(void)
719{
720 return (stdin);
721}
722
723DllExport FILE *
724win32_stdout()
725{
726 return (stdout);
727}
728
729DllExport int
730win32_ferror(FILE *fp)
731{
732 return (ferror(fp));
733}
734
735
736DllExport int
737win32_feof(FILE *fp)
738{
739 return (feof(fp));
740}
741
742/*
743 * Since the errors returned by the socket error function
744 * WSAGetLastError() are not known by the library routine strerror
745 * we have to roll our own.
746 */
747
748DllExport char *
749win32_strerror(int e)
750{
751 return xcestrerror(e);
752}
753
754DllExport void
755win32_str_os_error(void *sv, DWORD dwErr)
756{
acfe0abc 757 dTHX;
e1caacb4 758
759 sv_setpvn((SV*)sv, "Error", 5);
760}
761
762
763DllExport int
764win32_fprintf(FILE *fp, const char *format, ...)
765{
766 va_list marker;
767 va_start(marker, format); /* Initialize variable arguments. */
768
769 return (vfprintf(fp, format, marker));
770}
771
772DllExport int
773win32_printf(const char *format, ...)
774{
775 va_list marker;
776 va_start(marker, format); /* Initialize variable arguments. */
777
778 return (vprintf(format, marker));
779}
780
781DllExport int
782win32_vfprintf(FILE *fp, const char *format, va_list args)
783{
784 return (vfprintf(fp, format, args));
785}
786
787DllExport int
788win32_vprintf(const char *format, va_list args)
789{
790 return (vprintf(format, args));
791}
792
793DllExport size_t
794win32_fread(void *buf, size_t size, size_t count, FILE *fp)
795{
796 return fread(buf, size, count, fp);
797}
798
799DllExport size_t
800win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
801{
802 return fwrite(buf, size, count, fp);
803}
804
805DllExport FILE *
806win32_fopen(const char *filename, const char *mode)
807{
808 return xcefopen(filename, mode);
809}
810
811DllExport FILE *
812win32_fdopen(int handle, const char *mode)
813{
814 return palm_fdopen(handle, mode);
815}
816
817DllExport FILE *
818win32_freopen(const char *path, const char *mode, FILE *stream)
819{
820 return xcefreopen(path, mode, stream);
821}
822
823DllExport int
824win32_fclose(FILE *pf)
825{
826 return xcefclose(pf);
827}
828
829DllExport int
830win32_fputs(const char *s,FILE *pf)
831{
832 return fputs(s, pf);
833}
834
835DllExport int
836win32_fputc(int c,FILE *pf)
837{
838 return fputc(c,pf);
839}
840
841DllExport int
842win32_ungetc(int c,FILE *pf)
843{
844 return ungetc(c,pf);
845}
846
847DllExport int
848win32_getc(FILE *pf)
849{
850 return getc(pf);
851}
852
853DllExport int
854win32_fileno(FILE *pf)
855{
856 return palm_fileno(pf);
857}
858
859DllExport void
860win32_clearerr(FILE *pf)
861{
862 clearerr(pf);
863 return;
864}
865
866DllExport int
867win32_fflush(FILE *pf)
868{
869 return fflush(pf);
870}
871
872DllExport long
873win32_ftell(FILE *pf)
874{
875 return ftell(pf);
876}
877
878DllExport int
879win32_fseek(FILE *pf,long offset,int origin)
880{
881 return fseek(pf, offset, origin);
882}
883
cb69f87a 884/* fpos_t seems to be int64 on hpc pro! Really stupid. */
885/* But maybe someday there will be such large disks in a hpc... */
e1caacb4 886DllExport int
887win32_fgetpos(FILE *pf, fpos_t *p)
888{
889 return fgetpos(pf, p);
890}
891
892DllExport int
893win32_fsetpos(FILE *pf, const fpos_t *p)
894{
895 return fsetpos(pf, p);
896}
897
898DllExport void
899win32_rewind(FILE *pf)
900{
901 fseek(pf, 0, SEEK_SET);
902 return;
903}
904
905DllExport FILE*
906win32_tmpfile(void)
907{
908 Perl_croak(aTHX_ PL_no_func, "tmpfile");
909
910 return NULL;
911}
912
913DllExport void
914win32_abort(void)
915{
916 xceabort();
917
918 return;
919}
920
921DllExport int
922win32_fstat(int fd, struct stat *sbufptr)
923{
924 return xcefstat(fd, sbufptr);
925}
926
927DllExport int
928win32_link(const char *oldname, const char *newname)
929{
930 Perl_croak(aTHX_ PL_no_func, "link");
931
932 return -1;
933}
934
935DllExport int
936win32_rename(const char *oname, const char *newname)
937{
938 return xcerename(oname, newname);
939}
940
941DllExport int
942win32_setmode(int fd, int mode)
943{
944 if(mode != O_BINARY)
945 {
946 Perl_croak(aTHX_ PL_no_func, "setmode");
947 return -1;
948 }
949 return 0;
950}
951
952DllExport long
953win32_lseek(int fd, long offset, int origin)
954{
955 return xcelseek(fd, offset, origin);
956}
957
958DllExport long
959win32_tell(int fd)
960{
961 return xcelseek(fd, 0, SEEK_CUR);
962}
963
964DllExport int
965win32_open(const char *path, int flag, ...)
966{
967 int pmode;
968 va_list ap;
969
970 va_start(ap, flag);
971 pmode = va_arg(ap, int);
972 va_end(ap);
973
974 return xceopen(path, flag, pmode);
975}
976
977DllExport int
978win32_close(int fd)
979{
980 return xceclose(fd);
981}
982
983DllExport int
984win32_eof(int fd)
985{
986 Perl_croak(aTHX_ PL_no_func, "eof");
987 return -1;
988}
989
990DllExport int
991win32_dup(int fd)
992{
993 Perl_croak(aTHX_ PL_no_func, "dup");
994 return -1;
995}
996
997DllExport int
998win32_dup2(int fd1,int fd2)
999{
1000 Perl_croak(aTHX_ PL_no_func, "dup2");
1001 return -1;
1002}
1003
1004DllExport int
1005win32_read(int fd, void *buf, unsigned int cnt)
1006{
1007 return xceread(fd, buf, cnt);
1008}
1009
1010DllExport int
1011win32_write(int fd, const void *buf, unsigned int cnt)
1012{
1013 return xcewrite(fd, (void *) buf, cnt);
1014}
1015
1016DllExport int
1017win32_mkdir(const char *dir, int mode)
1018{
1019 return xcemkdir(dir);
1020}
1021
1022DllExport int
1023win32_rmdir(const char *dir)
1024{
1025 return xcermdir(dir);
1026}
1027
1028DllExport int
1029win32_chdir(const char *dir)
1030{
1031 return xcechdir(dir);
1032}
1033
1034DllExport int
1035win32_access(const char *path, int mode)
1036{
1037 return xceaccess(path, mode);
1038}
1039
1040DllExport int
1041win32_chmod(const char *path, int mode)
1042{
1043 return xcechmod(path, mode);
1044}
1045
1046DllExport void
1047win32_perror(const char *str)
1048{
1049 xceperror(str);
1050}
1051
1052DllExport void
1053win32_setbuf(FILE *pf, char *buf)
1054{
1055 Perl_croak(aTHX_ PL_no_func, "setbuf");
1056}
1057
1058DllExport int
1059win32_setvbuf(FILE *pf, char *buf, int type, size_t size)
1060{
1061 return setvbuf(pf, buf, type, size);
1062}
1063
1064DllExport int
1065win32_flushall(void)
1066{
1067 return flushall();
1068}
1069
1070DllExport int
1071win32_fcloseall(void)
1072{
1073 return fcloseall();
1074}
1075
1076DllExport char*
1077win32_fgets(char *s, int n, FILE *pf)
1078{
1079 return fgets(s, n, pf);
1080}
1081
1082DllExport char*
1083win32_gets(char *s)
1084{
1085 return gets(s);
1086}
1087
1088DllExport int
1089win32_fgetc(FILE *pf)
1090{
1091 return fgetc(pf);
1092}
1093
1094DllExport int
1095win32_putc(int c, FILE *pf)
1096{
1097 return putc(c,pf);
1098}
1099
1100DllExport int
1101win32_puts(const char *s)
1102{
1103 return puts(s);
1104}
1105
1106DllExport int
1107win32_getchar(void)
1108{
1109 return getchar();
1110}
1111
1112DllExport int
1113win32_putchar(int c)
1114{
1115 return putchar(c);
1116}
1117
1118#ifdef MYMALLOC
1119
1120#ifndef USE_PERL_SBRK
1121
1122static char *committed = NULL;
1123static char *base = NULL;
1124static char *reserved = NULL;
1125static char *brk = NULL;
1126static DWORD pagesize = 0;
1127static DWORD allocsize = 0;
1128
1129void *
1130sbrk(int need)
1131{
1132 void *result;
1133 if (!pagesize)
1134 {SYSTEM_INFO info;
1135 GetSystemInfo(&info);
1136 /* Pretend page size is larger so we don't perpetually
1137 * call the OS to commit just one page ...
1138 */
1139 pagesize = info.dwPageSize << 3;
1140 allocsize = info.dwAllocationGranularity;
1141 }
1142 /* This scheme fails eventually if request for contiguous
1143 * block is denied so reserve big blocks - this is only
1144 * address space not memory ...
1145 */
1146 if (brk+need >= reserved)
1147 {
1148 DWORD size = 64*1024*1024;
1149 char *addr;
1150 if (committed && reserved && committed < reserved)
1151 {
1152 /* Commit last of previous chunk cannot span allocations */
1153 addr = (char *) VirtualAlloc(committed,reserved-committed,MEM_COMMIT,PAGE_READWRITE);
1154 if (addr)
1155 committed = reserved;
1156 }
1157 /* Reserve some (more) space
1158 * Note this is a little sneaky, 1st call passes NULL as reserved
1159 * so lets system choose where we start, subsequent calls pass
1160 * the old end address so ask for a contiguous block
1161 */
1162 addr = (char *) VirtualAlloc(reserved,size,MEM_RESERVE,PAGE_NOACCESS);
1163 if (addr)
1164 {
1165 reserved = addr+size;
1166 if (!base)
1167 base = addr;
1168 if (!committed)
1169 committed = base;
1170 if (!brk)
1171 brk = committed;
1172 }
1173 else
1174 {
1175 return (void *) -1;
1176 }
1177 }
1178 result = brk;
1179 brk += need;
1180 if (brk > committed)
1181 {
1182 DWORD size = ((brk-committed + pagesize -1)/pagesize) * pagesize;
1183 char *addr = (char *) VirtualAlloc(committed,size,MEM_COMMIT,PAGE_READWRITE);
1184 if (addr)
1185 {
1186 committed += size;
1187 }
1188 else
1189 return (void *) -1;
1190 }
1191 return result;
1192}
1193
1194#endif
1195#endif
1196
1197DllExport void*
1198win32_malloc(size_t size)
1199{
1200 return malloc(size);
1201}
1202
1203DllExport void*
1204win32_calloc(size_t numitems, size_t size)
1205{
1206 return calloc(numitems,size);
1207}
1208
1209DllExport void*
1210win32_realloc(void *block, size_t size)
1211{
1212 return realloc(block,size);
1213}
1214
1215DllExport void
1216win32_free(void *block)
1217{
1218 free(block);
1219}
1220
1221DllExport int
1222win32_execv(const char *cmdname, const char *const *argv)
1223{
1224 Perl_croak(aTHX_ PL_no_func, "execv");
1225 return -1;
1226}
1227
1228DllExport int
1229win32_execvp(const char *cmdname, const char *const *argv)
1230{
1231 Perl_croak(aTHX_ PL_no_func, "execvp");
1232 return -1;
1233}
1234
1235DllExport void*
1236win32_dynaload(const char* filename)
1237{
acfe0abc 1238 dTHX;
e1caacb4 1239 HMODULE hModule;
1240
1241 hModule = XCELoadLibraryA(filename);
1242
1243 return hModule;
1244}
1245
cb69f87a 1246/* this is needed by Cwd.pm... */
e1caacb4 1247
1248static
1249XS(w32_GetCwd)
1250{
1251 dXSARGS;
1252 char buf[MAX_PATH];
1253 SV *sv = sv_newmortal();
1254
1255 xcegetcwd(buf, sizeof(buf));
1256
1257 sv_setpv(sv, xcestrdup(buf));
1258 EXTEND(SP,1);
1259 SvPOK_on(sv);
1260 ST(0) = sv;
ebdd4fa0 1261#ifndef INCOMPLETE_TAINTS
1262 SvTAINTED_on(ST(0));
1263#endif
e1caacb4 1264 XSRETURN(1);
1265}
1266
1267static
1268XS(w32_SetCwd)
1269{
1270 dXSARGS;
1271
1272 if (items != 1)
1273 Perl_croak(aTHX_ "usage: Win32::SetCwd($cwd)");
1274
1275 if (!xcechdir(SvPV_nolen(ST(0))))
1276 XSRETURN_YES;
1277
1278 XSRETURN_NO;
1279}
1280
1281static
1282XS(w32_GetTickCount)
1283{
1284 dXSARGS;
1285 DWORD msec = GetTickCount();
1286 EXTEND(SP,1);
1287 if ((IV)msec > 0)
1288 XSRETURN_IV(msec);
1289 XSRETURN_NV(msec);
1290}
1291
1292static
1293XS(w32_GetOSVersion)
1294{
1295 dXSARGS;
1296 OSVERSIONINFOA osver;
1297
1298 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1299 if (!XCEGetVersionExA(&osver)) {
1300 XSRETURN_EMPTY;
1301 }
1302 XPUSHs(newSVpvn(osver.szCSDVersion, strlen(osver.szCSDVersion)));
1303 XPUSHs(newSViv(osver.dwMajorVersion));
1304 XPUSHs(newSViv(osver.dwMinorVersion));
1305 XPUSHs(newSViv(osver.dwBuildNumber));
cb69f87a 1306 /* WINCE = 3 */
e1caacb4 1307 XPUSHs(newSViv(osver.dwPlatformId));
1308 PUTBACK;
1309}
1310
1311static
1312XS(w32_IsWinNT)
1313{
1314 dXSARGS;
1315 EXTEND(SP,1);
1316 XSRETURN_IV(IsWinNT());
1317}
1318
1319static
1320XS(w32_IsWin95)
1321{
1322 dXSARGS;
1323 EXTEND(SP,1);
1324 XSRETURN_IV(IsWin95());
1325}
1326
1327static
1328XS(w32_IsWinCE)
1329{
1330 dXSARGS;
1331 EXTEND(SP,1);
1332 XSRETURN_IV(IsWinCE());
1333}
1334
1335static
1336XS(w32_GetOemInfo)
1337{
1338 dXSARGS;
1339 wchar_t wbuf[126];
1340 char buf[126];
1341
1342 if(SystemParametersInfoW(SPI_GETOEMINFO, sizeof(wbuf), wbuf, FALSE))
1343 WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buf, sizeof(buf), 0, 0);
1344 else
1345 sprintf(buf, "SystemParametersInfo failed: %d", GetLastError());
1346
1347 EXTEND(SP,1);
1348 XSRETURN_PV(buf);
1349}
1350
1351static
1352XS(w32_Sleep)
1353{
1354 dXSARGS;
1355 if (items != 1)
1356 Perl_croak(aTHX_ "usage: Win32::Sleep($milliseconds)");
1357 Sleep(SvIV(ST(0)));
1358 XSRETURN_YES;
1359}
1360
1361static
1362XS(w32_CopyFile)
1363{
1364 dXSARGS;
1365 BOOL bResult;
1366 if (items != 3)
1367 Perl_croak(aTHX_ "usage: Win32::CopyFile($from, $to, $overwrite)");
1368
1369 {
1370 char szSourceFile[MAX_PATH+1];
1371 strcpy(szSourceFile, PerlDir_mapA(SvPV_nolen(ST(0))));
1372 bResult = XCECopyFileA(szSourceFile, SvPV_nolen(ST(1)),
1373 !SvTRUE(ST(2)));
1374 }
1375
1376 if (bResult)
1377 XSRETURN_YES;
1378
1379 XSRETURN_NO;
1380}
1381
1382static
1383XS(w32_MessageBox)
1384{
1385 dXSARGS;
1386
1387 char *txt;
1388 unsigned int res;
1389 unsigned int flags = MB_OK;
1390
1391 txt = SvPV_nolen(ST(0));
1392
1393 if (items < 1 || items > 2)
1394 Perl_croak(aTHX_ "usage: Win32::MessageBox($txt, [$flags])");
1395
1396 if(items == 2)
1397 flags = SvIV(ST(1));
1398
1399 res = XCEMessageBoxA(NULL, txt, "Perl", flags);
1400
1401 XSRETURN_IV(res);
1402}
1403
1404static
1405XS(w32_GetPowerStatus)
1406{
1407 dXSARGS;
1408
1409 SYSTEM_POWER_STATUS_EX sps;
1410
1411 if(GetSystemPowerStatusEx(&sps, TRUE) == FALSE)
1412 {
1413 XSRETURN_EMPTY;
1414 }
1415
1416 XPUSHs(newSViv(sps.ACLineStatus));
1417 XPUSHs(newSViv(sps.BatteryFlag));
1418 XPUSHs(newSViv(sps.BatteryLifePercent));
1419 XPUSHs(newSViv(sps.BatteryLifeTime));
1420 XPUSHs(newSViv(sps.BatteryFullLifeTime));
1421 XPUSHs(newSViv(sps.BackupBatteryFlag));
1422 XPUSHs(newSViv(sps.BackupBatteryLifePercent));
1423 XPUSHs(newSViv(sps.BackupBatteryLifeTime));
1424 XPUSHs(newSViv(sps.BackupBatteryFullLifeTime));
1425
1426 PUTBACK;
1427}
1428
1429#if UNDER_CE > 200
1430static
1431XS(w32_ShellEx)
1432{
1433 dXSARGS;
1434
1435 char buf[126];
1436 SHELLEXECUTEINFO si;
1437 char *file, *verb;
1438 wchar_t wfile[MAX_PATH];
1439 wchar_t wverb[20];
1440
1441 if (items != 2)
1442 Perl_croak(aTHX_ "usage: Win32::ShellEx($file, $verb)");
1443
1444 file = SvPV_nolen(ST(0));
1445 verb = SvPV_nolen(ST(1));
1446
1447 memset(&si, 0, sizeof(si));
1448 si.cbSize = sizeof(si);
1449 si.fMask = SEE_MASK_FLAG_NO_UI;
1450
1451 MultiByteToWideChar(CP_ACP, 0, verb, -1,
1452 wverb, sizeof(wverb)/2);
1453 si.lpVerb = (TCHAR *)wverb;
1454
1455 MultiByteToWideChar(CP_ACP, 0, file, -1,
1456 wfile, sizeof(wfile)/2);
1457 si.lpFile = (TCHAR *)wfile;
1458
1459 if(ShellExecuteEx(&si) == FALSE)
1460 {
1461 XSRETURN_NO;
1462 }
1463 XSRETURN_YES;
1464}
1465#endif
1466
1467void
1468Perl_init_os_extras(void)
1469{
acfe0abc 1470 dTHX;
e1caacb4 1471 char *file = __FILE__;
1472 dXSUB_SYS;
1473
1474 w32_perlshell_tokens = Nullch;
1475 w32_perlshell_items = -1;
1476 w32_fdpid = newAV(); /* XX needs to be in Perl_win32_init()? */
1477 New(1313, w32_children, 1, child_tab);
1478 w32_num_children = 0;
1479
1480 newXS("Win32::GetCwd", w32_GetCwd, file);
1481 newXS("Win32::SetCwd", w32_SetCwd, file);
1482 newXS("Win32::GetTickCount", w32_GetTickCount, file);
1483 newXS("Win32::GetOSVersion", w32_GetOSVersion, file);
1484#if UNDER_CE > 200
1485 newXS("Win32::ShellEx", w32_ShellEx, file);
1486#endif
1487 newXS("Win32::IsWinNT", w32_IsWinNT, file);
1488 newXS("Win32::IsWin95", w32_IsWin95, file);
1489 newXS("Win32::IsWinCE", w32_IsWinCE, file);
1490 newXS("Win32::CopyFile", w32_CopyFile, file);
1491 newXS("Win32::Sleep", w32_Sleep, file);
1492 newXS("Win32::MessageBox", w32_MessageBox, file);
1493 newXS("Win32::GetPowerStatus", w32_GetPowerStatus, file);
1494 newXS("Win32::GetOemInfo", w32_GetOemInfo, file);
1495}
1496
1497void
1498myexit(void)
1499{
1500 char buf[126];
1501
1502 puts("Hit return");
1503 fgets(buf, sizeof(buf), stdin);
1504}
1505
1506void
1507Perl_win32_init(int *argcp, char ***argvp)
1508{
1509#ifdef UNDER_CE
1510 char *p;
1511
1512 if((p = xcegetenv("PERLDEBUG")) && (p[0] == 'y' || p[0] == 'Y'))
1513 atexit(myexit);
1514#endif
1515
1516 MALLOC_INIT;
1517}
1518
1519DllExport int
1520win32_flock(int fd, int oper)
1521{
1522 Perl_croak(aTHX_ PL_no_func, "flock");
1523 return -1;
1524}
1525
1526DllExport int
1527win32_waitpid(int pid, int *status, int flags)
1528{
1529 Perl_croak(aTHX_ PL_no_func, "waitpid");
1530 return -1;
1531}
1532
1533DllExport int
1534win32_wait(int *status)
1535{
1536 Perl_croak(aTHX_ PL_no_func, "wait");
1537 return -1;
1538}
1539
1540int
1541do_spawn(char *cmd)
1542{
1543 return xcesystem(cmd);
1544}
1545
1546int
1547do_aspawn(void *vreally, void **vmark, void **vsp)
1548{
1549 Perl_croak(aTHX_ PL_no_func, "aspawn");
1550 return -1;
1551}
1552
1553int
1554wce_reopen_stdout(char *fname)
1555{
1556 if(xcefreopen(fname, "w", stdout) == NULL)
1557 return -1;
1558
1559 return 0;
1560}
1561
1562void
1563wce_hitreturn()
1564{
1565 char buf[126];
1566
1567 printf("Hit RETURN");
1568 fflush(stdout);
1569 fgets(buf, sizeof(buf), stdin);
1570 return;
1571}
1572
cb69f87a 1573/* //////////////////////////////////////////////////////////////////// */
e1caacb4 1574
e1caacb4 1575void
1576win32_argv2utf8(int argc, char** argv)
1577{
cb69f87a 1578 /* do nothing... */
e1caacb4 1579}
1580
1581void
1582Perl_sys_intern_init(pTHX)
1583{
1584 w32_perlshell_tokens = Nullch;
1585 w32_perlshell_vec = (char**)NULL;
1586 w32_perlshell_items = 0;
1587 w32_fdpid = newAV();
1588 New(1313, w32_children, 1, child_tab);
1589 w32_num_children = 0;
1590# ifdef USE_ITHREADS
1591 w32_pseudo_id = 0;
1592 New(1313, w32_pseudo_children, 1, child_tab);
1593 w32_num_pseudo_children = 0;
1594# endif
1595
1596#ifndef UNDER_CE
1597 w32_init_socktype = 0;
1598#endif
1599}
1600
1601void
1602Perl_sys_intern_clear(pTHX)
1603{
1604 Safefree(w32_perlshell_tokens);
1605 Safefree(w32_perlshell_vec);
1606 /* NOTE: w32_fdpid is freed by sv_clean_all() */
1607 Safefree(w32_children);
1608# ifdef USE_ITHREADS
1609 Safefree(w32_pseudo_children);
1610# endif
1611}
1612
cb69f87a 1613/* //////////////////////////////////////////////////////////////////// */
ca6c63e1 1614
1615#undef getcwd
1616
1617char *
1618getcwd(char *buf, size_t size)
1619{
1620 return xcegetcwd(buf, size);
1621}
1622
1623int
1624isnan(double d)
1625{
1626 return _isnan(d);
1627}
1628
42165d27 1629int
1630win32_open_osfhandle(intptr_t osfhandle, int flags)
1631{
1632 int fh;
1633 char fileflags=0; /* _osfile flags */
1634
18f68570 1635 XCEMessageBoxA(NULL, "NEED TO IMPLEMENT in wince/wince.c(win32_open_osfhandle)", "error", 0);
42165d27 1636 Perl_croak_nocontext("win32_open_osfhandle() TBD on this platform");
1637 return 0;
1638}
18f68570 1639
1640int
1641win32_get_osfhandle(intptr_t osfhandle, int flags)
1642{
1643 int fh;
1644 char fileflags=0; /* _osfile flags */
1645
1646 XCEMessageBoxA(NULL, "NEED TO IMPLEMENT in wince/wince.c(win32_get_osfhandle)", "error", 0);
1647 Perl_croak_nocontext("win32_get_osfhandle() TBD on this platform");
1648 return 0;
1649}
1650
1651/*
1652 * a popen() clone that respects PERL5SHELL
1653 *
1654 * changed to return PerlIO* rather than FILE * by BKS, 11-11-2000
1655 */
1656
1657DllExport PerlIO*
1658win32_popen(const char *command, const char *mode)
1659{
1660 XCEMessageBoxA(NULL, "NEED TO IMPLEMENT in wince/wince.c(win32_popen)", "error", 0);
1661 Perl_croak_nocontext("win32_popen() TBD on this platform");
1662}
1663
1664/*
1665 * pclose() clone
1666 */
1667
1668DllExport int
1669win32_pclose(PerlIO *pf)
1670{
1671#ifdef USE_RTL_POPEN
1672 return _pclose(pf);
1673#else
1674 dTHX;
1675 int childpid, status;
1676 SV *sv;
1677
1678 LOCK_FDPID_MUTEX;
1679 sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
1680
1681 if (SvIOK(sv))
1682 childpid = SvIVX(sv);
1683 else
1684 childpid = 0;
1685
1686 if (!childpid) {
1687 errno = EBADF;
1688 return -1;
1689 }
1690
1691#ifdef USE_PERLIO
1692 PerlIO_close(pf);
1693#else
1694 fclose(pf);
1695#endif
1696 SvIVX(sv) = 0;
1697 UNLOCK_FDPID_MUTEX;
1698
1699 if (win32_waitpid(childpid, &status, 0) == -1)
1700 return -1;
1701
1702 return status;
1703
1704#endif /* USE_RTL_POPEN */
1705}
1706
1707FILE *
1708win32_fdupopen(FILE *pf)
1709{
1710 FILE* pfdup;
1711 fpos_t pos;
1712 char mode[3];
1713 int fileno = win32_dup(win32_fileno(pf));
1714
1715 XCEMessageBoxA(NULL, "NEED TO IMPLEMENT a place in .../wince/wince.c(win32_fdupopen)", "Perl(developer)", 0);
1716 Perl_croak_nocontext("win32_fdupopen() TBD on this platform");
1717
1718#if 0
1719 /* open the file in the same mode */
1720 if((pf)->_flag & _IOREAD) {
1721 mode[0] = 'r';
1722 mode[1] = 0;
1723 }
1724 else if((pf)->_flag & _IOWRT) {
1725 mode[0] = 'a';
1726 mode[1] = 0;
1727 }
1728 else if((pf)->_flag & _IORW) {
1729 mode[0] = 'r';
1730 mode[1] = '+';
1731 mode[2] = 0;
1732 }
1733
1734 /* it appears that the binmode is attached to the
1735 * file descriptor so binmode files will be handled
1736 * correctly
1737 */
1738 pfdup = win32_fdopen(fileno, mode);
1739
1740 /* move the file pointer to the same position */
1741 if (!fgetpos(pf, &pos)) {
1742 fsetpos(pfdup, &pos);
1743 }
1744#endif
1745 return pfdup;
1746}