1 /* Win32API/File.xs */
2 
3 #include "EXTERN.h"
4 #include "perl.h"
5 #include "XSUB.h"
6 /*#include "patchlevel.h"*/
7 
8 /* Uncomment the next line unless set "WRITE_PERL=>1" in Makefile.PL: */
9 #define NEED_newCONSTSUB
10 #include "ppport.h"
11 
12 #ifdef WORD
13 # undef WORD
14 #endif
15 
16 #define  WIN32_LEAN_AND_MEAN	/* Tell windows.h to skip much */
17 #include <wchar.h>
18 #include <windows.h>
19 #include <winioctl.h>
20 
21 /*CONSTS_DEFINED*/
22 
23 #ifndef INVALID_SET_FILE_POINTER
24 #   define INVALID_SET_FILE_POINTER	((DWORD)-1)
25 #endif
26 
27 #define oDWORD DWORD
28 
29 #if (PERL_REVISION <= 5 && PERL_VERSION < 5) || defined(__CYGWIN__)
30 # define win32_get_osfhandle _get_osfhandle
31 # ifdef __CYGWIN__
32 #  define win32_open_osfhandle(handle,mode) \
33 	(Perl_croak(aTHX_ "_open_osfhandle not implemented on Cygwin!"), -1)
34 # else
35 #  define win32_open_osfhandle _open_osfhandle
36 # endif
37 # ifdef _get_osfhandle
38 #  undef _get_osfhandle	/* stolen_get_osfhandle() isn't available here */
39 # endif
40 # ifdef _open_osfhandle
41 #  undef _open_osfhandle /* stolen_open_osfhandle() isn't available here */
42 # endif
43 #endif
44 
45 #ifndef XST_mUV
46 # define XST_mUV(i,v)  (ST(i) = sv_2mortal(newSVuv(v))  )
47 #endif
48 
49 #ifndef XSRETURN_UV
50 # define XSRETURN_UV(v) STMT_START { XST_mUV(0,v);  XSRETURN(1); } STMT_END
51 #endif
52 
53 #ifndef DEBUGGING
54 # define	Debug(list)	/*Nothing*/
55 #else
56 # define	Debug(list)	ErrPrintf list
57 # include <stdarg.h>
58     static void
ErrPrintf(const char * sFmt,...)59     ErrPrintf( const char *sFmt, ... )
60     {
61       va_list pAList;
62       static char *sEnv= NULL;
63       DWORD uErr= GetLastError();
64 	if(  NULL == sEnv  ) {
65 	    if(  NULL == ( sEnv= getenv("DEBUG_WIN32API_FILE") )  )
66 		sEnv= "";
67 	}
68 	if(  '\0' == *sEnv  )
69 	    return;
70 	va_start( pAList, sFmt );
71 	vfprintf( stderr, sFmt, pAList );
72 	va_end( pAList );
73 	SetLastError( uErr );
74     }
75 #endif /* DEBUGGING */
76 
77 
78 #include "buffers.h"	/* Include this after DEBUGGING setup finished */
79 
80 static LONG uLastFileErr= 0;
81 
82 static void
SaveErr(BOOL bFailed)83 SaveErr( BOOL bFailed )
84 {
85     if(  bFailed  ) {
86 	uLastFileErr= GetLastError();
87     }
88 }
89 
90 MODULE = Win32API::File		PACKAGE = Win32API::File
91 
92 PROTOTYPES: DISABLE
93 
94 
95 LONG
96 _fileLastError( uError=0 )
97 	DWORD	uError
98     CODE:
99 	if(  1 <= items  ) {
100 	    uLastFileErr= uError;
101 	}
102 	RETVAL= uLastFileErr;
103     OUTPUT:
104 	RETVAL
105 
106 
107 BOOL
108 CloseHandle( hObject )
109 	HANDLE	hObject
110     CODE:
111         RETVAL = CloseHandle( hObject );
112 	SaveErr( !RETVAL );
113     OUTPUT:
114 	RETVAL
115 
116 
117 BOOL
118 CopyFileA( sOldFileName, sNewFileName, bFailIfExists )
119 	char *	sOldFileName
120 	char *	sNewFileName
121 	BOOL	bFailIfExists
122     CODE:
123         RETVAL = CopyFileA( sOldFileName, sNewFileName, bFailIfExists );
124 	SaveErr( !RETVAL );
125     OUTPUT:
126 	RETVAL
127 
128 
129 BOOL
130 CopyFileW( swOldFileName, swNewFileName, bFailIfExists )
131 	WCHAR *	swOldFileName
132 	WCHAR *	swNewFileName
133 	BOOL	bFailIfExists
134     CODE:
135         RETVAL = CopyFileW( swOldFileName, swNewFileName, bFailIfExists );
136 	SaveErr( !RETVAL );
137     OUTPUT:
138 	RETVAL
139 
140 
141 HANDLE
142 CreateFileA( sPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel )
143 	char *	sPath
144 	DWORD	uAccess
145 	DWORD	uShare
146 	void *	pSecAttr
147 	DWORD	uCreate
148 	DWORD	uFlags
149 	HANDLE	hModel
150     CODE:
151 	RETVAL= CreateFileA( sPath, uAccess, uShare,
152 	  (LPSECURITY_ATTRIBUTES)pSecAttr, uCreate, uFlags, hModel );
153 	if(  INVALID_HANDLE_VALUE == RETVAL  ) {
154 	    SaveErr( 1 );
155 	    XSRETURN_NO;
156 	} else if(  0 == RETVAL  ) {
157 	    XSRETURN_PV( "0 but true" );
158 	} else {
159 	    XSRETURN_UV( PTR2UV(RETVAL) );
160 	}
161 
162 
163 HANDLE
164 CreateFileW( swPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel )
165 	WCHAR *	swPath
166 	DWORD	uAccess
167 	DWORD	uShare
168 	void *	pSecAttr
169 	DWORD	uCreate
170 	DWORD	uFlags
171 	HANDLE	hModel
172     CODE:
173 	RETVAL= CreateFileW( swPath, uAccess, uShare,
174 	  (LPSECURITY_ATTRIBUTES)pSecAttr, uCreate, uFlags, hModel );
175 	if(  INVALID_HANDLE_VALUE == RETVAL  ) {
176 	    SaveErr( 1 );
177 	    XSRETURN_NO;
178 	} else if(  0 == RETVAL  ) {
179 	    XSRETURN_PV( "0 but true" );
180 	} else {
181 	    XSRETURN_UV( PTR2UV(RETVAL) );
182 	}
183 
184 
185 BOOL
186 DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath )
187 	DWORD	uFlags
188 	char *	sDosDeviceName
189 	char *	sTargetPath
190     CODE:
191         RETVAL = DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath );
192 	SaveErr( !RETVAL );
193     OUTPUT:
194 	RETVAL
195 
196 
197 BOOL
198 DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath )
199 	DWORD	uFlags
200 	WCHAR *	swDosDeviceName
201 	WCHAR *	swTargetPath
202     CODE:
203         RETVAL = DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath );
204 	SaveErr( !RETVAL );
205     OUTPUT:
206 	RETVAL
207 
208 
209 BOOL
210 DeleteFileA( sFileName )
211 	char *	sFileName
212     CODE:
213         RETVAL = DeleteFileA( sFileName );
214 	SaveErr( !RETVAL );
215     OUTPUT:
216 	RETVAL
217 
218 
219 BOOL
220 DeleteFileW( swFileName )
221 	WCHAR *	swFileName
222     CODE:
223         RETVAL = DeleteFileW( swFileName );
224 	SaveErr( !RETVAL );
225     OUTPUT:
226 	RETVAL
227 
228 
229 BOOL
230 DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf, opOutBuf, lOutBuf, olRetBytes, pOverlapped )
231 	HANDLE	hDevice
232 	DWORD	uIoControlCode
233 	char *	pInBuf
234 	DWORD	lInBuf		= init_buf_l($arg);
235 	char *	opOutBuf	= NO_INIT
236 	DWORD	lOutBuf		= init_buf_l($arg);
237 	oDWORD	&olRetBytes
238 	void *	pOverlapped
239     CODE:
240 	if(  NULL != pInBuf  ) {
241 	    if(  0 == lInBuf  ) {
242 		lInBuf= SvCUR(ST(2));
243 	    } else if(  SvCUR(ST(2)) < lInBuf  ) {
244 		croak( "%s: pInBuf shorter than specified (%d < %d)",
245 		  "Win32API::File::DeviceIoControl", SvCUR(ST(2)), lInBuf );
246 	    }
247 	}
248 	grow_buf_l( opOutBuf,ST(4),char *, lOutBuf,ST(5) );
249 	RETVAL= DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf,
250 		  opOutBuf, lOutBuf, &olRetBytes, (LPOVERLAPPED)pOverlapped );
251 	SaveErr( !RETVAL );
252     OUTPUT:
253 	RETVAL
254 	opOutBuf	trunc_buf_l( RETVAL, opOutBuf,ST(4), olRetBytes );
255 	olRetBytes
256 
257 
258 HANDLE
259 FdGetOsFHandle( ivFd )
260 	int	ivFd
261     CODE:
262 	RETVAL= (HANDLE) win32_get_osfhandle( ivFd );
263 	SaveErr( INVALID_HANDLE_VALUE == RETVAL );
264     OUTPUT:
265 	RETVAL
266 
267 
268 DWORD
269 GetDriveTypeA( sRootPath )
270 	char *	sRootPath
271     CODE:
272         RETVAL = GetDriveTypeA( sRootPath );
273 	SaveErr( !RETVAL );
274     OUTPUT:
275 	RETVAL
276 
277 
278 DWORD
279 GetDriveTypeW( swRootPath )
280 	WCHAR *	swRootPath
281     CODE:
282         RETVAL = GetDriveTypeW( swRootPath );
283 	SaveErr( !RETVAL );
284     OUTPUT:
285 	RETVAL
286 
287 
288 DWORD
289 GetFileAttributesA( sPath )
290 	char *	sPath
291     CODE:
292         RETVAL = GetFileAttributesA( sPath );
293 	SaveErr( !RETVAL );
294     OUTPUT:
295 	RETVAL
296 
297 
298 DWORD
299 GetFileAttributesW( swPath )
300 	WCHAR *	swPath
301     CODE:
302         RETVAL = GetFileAttributesW( swPath );
303 	SaveErr( !RETVAL );
304     OUTPUT:
305 	RETVAL
306 
307 
308 DWORD
309 GetFileType( hFile )
310 	HANDLE	hFile
311     CODE:
312         RETVAL = GetFileType( hFile );
313 	SaveErr( !RETVAL );
314     OUTPUT:
315 	RETVAL
316 
317 
318 BOOL
319 GetHandleInformation( hObject, ouFlags )
320 	HANDLE		hObject
321 	oDWORD *	ouFlags
322     CODE:
323         RETVAL = GetHandleInformation( hObject, ouFlags );
324 	SaveErr( !RETVAL );
325     OUTPUT:
326 	RETVAL
327 	ouFlags
328 
329 
330 DWORD
331 GetLogicalDrives()
332     CODE:
333         RETVAL = GetLogicalDrives();
334 	SaveErr( !RETVAL );
335     OUTPUT:
336 	RETVAL
337 
338 
339 DWORD
340 GetLogicalDriveStringsA( lBufSize, osBuffer )
341 	DWORD	lBufSize	= init_buf_l($arg);
342 	char *	osBuffer	= NO_INIT
343     CODE:
344 	grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) );
345 	RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer );
346 	if(  lBufSize < RETVAL  &&  autosize(ST(0))  ) {
347 	    lBufSize= RETVAL;
348 	    grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) );
349 	    RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer );
350 	}
351 	if(  0 == RETVAL  ||  lBufSize < RETVAL  ) {
352 	    SaveErr( 1 );
353 	} else {
354 	    trunc_buf_l( 1, osBuffer,ST(1), RETVAL );
355 	}
356     OUTPUT:
357 	RETVAL
358 	osBuffer	;/* The code for this appears above. */
359 
360 
361 DWORD
362 GetLogicalDriveStringsW( lwBufSize, oswBuffer )
363 	DWORD	lwBufSize	= init_buf_lw($arg);
364 	WCHAR *	oswBuffer	= NO_INIT
365     CODE:
366 	grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) );
367 	RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer );
368 	if(  lwBufSize < RETVAL  &&  autosize(ST(0))  ) {
369 	    lwBufSize= RETVAL;
370 	    grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) );
371 	    RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer );
372 	}
373 	if(  0 == RETVAL  ||  lwBufSize < RETVAL  ) {
374 	    SaveErr( 1 );
375 	} else {
376 	    trunc_buf_lw( 1, oswBuffer,ST(1), RETVAL );
377 	}
378     OUTPUT:
379 	RETVAL
380 	oswBuffer	;/* The code for this appears above. */
381 
382 
383 BOOL
384 GetVolumeInformationA( sRootPath, osVolName, lVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, osFsType, lFsType )
385 	char *	sRootPath
386 	char *	osVolName	= NO_INIT
387 	DWORD	lVolName	= init_buf_l($arg);
388 	oDWORD	&ouSerialNum	= optUV($arg);
389 	oDWORD	&ouMaxNameLen	= optUV($arg);
390 	oDWORD	&ouFsFlags	= optUV($arg);
391 	char *	osFsType	= NO_INIT
392 	DWORD	lFsType		= init_buf_l($arg);
393     CODE:
394 	grow_buf_l( osVolName,ST(1),char *, lVolName,ST(2) );
395 	grow_buf_l( osFsType,ST(6),char *, lFsType,ST(7) );
396 	RETVAL= GetVolumeInformationA( sRootPath, osVolName, lVolName,
397 		  &ouSerialNum, &ouMaxNameLen, &ouFsFlags, osFsType, lFsType );
398 	SaveErr( !RETVAL );
399     OUTPUT:
400 	RETVAL
401 	osVolName	trunc_buf_z( RETVAL, osVolName,ST(1) );
402 	osFsType	trunc_buf_z( RETVAL, osFsType,ST(6) );
403 	ouSerialNum
404 	ouMaxNameLen
405 	ouFsFlags
406 
407 
408 BOOL
409 GetVolumeInformationW( swRootPath, oswVolName, lwVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, oswFsType, lwFsType )
410 	WCHAR *	swRootPath
411 	WCHAR *	oswVolName	= NO_INIT
412 	DWORD	lwVolName	= init_buf_lw($arg);
413 	oDWORD	&ouSerialNum	= optUV($arg);
414 	oDWORD	&ouMaxNameLen	= optUV($arg);
415 	oDWORD	&ouFsFlags	= optUV($arg);
416 	WCHAR *	oswFsType	= NO_INIT
417 	DWORD	lwFsType	= init_buf_lw($arg);
418     CODE:
419 	grow_buf_lw( oswVolName,ST(1), lwVolName,ST(2) );
420 	grow_buf_lw( oswFsType,ST(6), lwFsType,ST(7) );
421 	RETVAL= GetVolumeInformationW( swRootPath, oswVolName, lwVolName,
422 	  &ouSerialNum, &ouMaxNameLen, &ouFsFlags, oswFsType, lwFsType );
423 	SaveErr( !RETVAL );
424     OUTPUT:
425 	RETVAL
426 	oswVolName	trunc_buf_zw( RETVAL, oswVolName,ST(1) );
427 	oswFsType	trunc_buf_zw( RETVAL, oswFsType,ST(6) );
428 	ouSerialNum
429 	ouMaxNameLen
430 	ouFsFlags
431 
432 
433 BOOL
434 IsRecognizedPartition( ivPartitionType )
435 	int	ivPartitionType
436     CODE:
437         RETVAL = IsRecognizedPartition( ivPartitionType );
438 	SaveErr( !RETVAL );
439     OUTPUT:
440 	RETVAL
441 
442 
443 BOOL
444 IsContainerPartition( ivPartitionType )
445 	int	ivPartitionType
446     CODE:
447         RETVAL = IsContainerPartition( ivPartitionType );
448 	SaveErr( !RETVAL );
449     OUTPUT:
450 	RETVAL
451 
452 
453 BOOL
454 MoveFileA( sOldName, sNewName )
455 	char *	sOldName
456 	char *	sNewName
457     CODE:
458         RETVAL = MoveFileA( sOldName, sNewName );
459 	SaveErr( !RETVAL );
460     OUTPUT:
461 	RETVAL
462 
463 
464 BOOL
465 MoveFileW( swOldName, swNewName )
466 	WCHAR *	swOldName
467 	WCHAR *	swNewName
468     CODE:
469         RETVAL = MoveFileW( swOldName, swNewName );
470 	SaveErr( !RETVAL );
471     OUTPUT:
472 	RETVAL
473 
474 
475 BOOL
476 MoveFileExA( sOldName, sNewName, uFlags )
477 	char *	sOldName
478 	char *	sNewName
479 	DWORD	uFlags
480     CODE:
481         RETVAL = MoveFileExA( sOldName, sNewName, uFlags );
482 	SaveErr( !RETVAL );
483     OUTPUT:
484 	RETVAL
485 
486 
487 BOOL
488 MoveFileExW( swOldName, swNewName, uFlags )
489 	WCHAR *	swOldName
490 	WCHAR *	swNewName
491 	DWORD	uFlags
492     CODE:
493         RETVAL = MoveFileExW( swOldName, swNewName, uFlags );
494 	SaveErr( !RETVAL );
495     OUTPUT:
496 	RETVAL
497 
498 
499 long
500 OsFHandleOpenFd( hOsFHandle, uMode )
501 	long	hOsFHandle
502 	DWORD	uMode
503     CODE:
504 	RETVAL= win32_open_osfhandle( hOsFHandle, uMode );
505 	if(  RETVAL < 0  ) {
506 	    SaveErr( 1 );
507 	    XSRETURN_NO;
508 	} else if(  0 == RETVAL  ) {
509 	    XSRETURN_PV( "0 but true" );
510 	} else {
511 	    XSRETURN_IV( (IV) RETVAL );
512 	}
513 
514 
515 DWORD
516 QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf )
517 	char *	sDeviceName
518 	char *	osTargetPath	= NO_INIT
519 	DWORD	lTargetBuf	= init_buf_l($arg);
520     CODE:
521 	grow_buf_l( osTargetPath,ST(1),char *, lTargetBuf,ST(2) );
522 	RETVAL= QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf );
523 	SaveErr( 0 == RETVAL );
524     OUTPUT:
525 	RETVAL
526 	osTargetPath	trunc_buf_l( 1, osTargetPath,ST(1), RETVAL );
527 
528 
529 DWORD
530 QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf )
531 	WCHAR *	swDeviceName
532 	WCHAR *	oswTargetPath	= NO_INIT
533 	DWORD	lwTargetBuf	= init_buf_lw($arg);
534     CODE:
535 	grow_buf_lw( oswTargetPath,ST(1), lwTargetBuf,ST(2) );
536 	RETVAL= QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf );
537 	SaveErr( 0 == RETVAL );
538     OUTPUT:
539 	RETVAL
540 	oswTargetPath	trunc_buf_lw( 1, oswTargetPath,ST(1), RETVAL );
541 
542 
543 BOOL
544 ReadFile( hFile, opBuffer, lBytes, olBytesRead, pOverlapped )
545 	HANDLE	hFile
546 	BYTE *	opBuffer	= NO_INIT
547 	DWORD	lBytes		= init_buf_l($arg);
548 	oDWORD	&olBytesRead
549 	void *	pOverlapped
550     CODE:
551 	grow_buf_l( opBuffer,ST(1),BYTE *, lBytes,ST(2) );
552 	/* Don't read more bytes than asked for if buffer is already big: */
553 	lBytes= init_buf_l(ST(2));
554 	if(  0 == lBytes  &&  autosize(ST(2))  ) {
555 	    lBytes= SvLEN( ST(1) ) - 1;
556 	}
557 	RETVAL= ReadFile( hFile, opBuffer, lBytes, &olBytesRead,
558 		  (LPOVERLAPPED)pOverlapped );
559 	SaveErr( !RETVAL );
560     OUTPUT:
561 	RETVAL
562 	opBuffer	trunc_buf_l( RETVAL, opBuffer,ST(1), olBytesRead );
563 	olBytesRead
564 
565 
566 BOOL
567 GetOverlappedResult( hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait)
568 	HANDLE hFile
569 	LPOVERLAPPED lpOverlapped
570 	LPDWORD lpNumberOfBytesTransferred
571 	BOOL bWait
572     CODE:
573     	RETVAL= GetOverlappedResult( hFile, lpOverlapped,
574 	 lpNumberOfBytesTransferred, bWait);
575 	SaveErr( !RETVAL );
576     OUTPUT:
577     	RETVAL
578 	lpOverlapped
579 	lpNumberOfBytesTransferred
580 
581 DWORD
582 GetFileSize( hFile, lpFileSizeHigh )
583 	HANDLE hFile
584 	LPDWORD lpFileSizeHigh
585     CODE:
586     	RETVAL= GetFileSize( hFile, lpFileSizeHigh );
587 	SaveErr( NO_ERROR != GetLastError() );
588     OUTPUT:
589     	RETVAL
590 	lpFileSizeHigh
591 
592 UINT
593 SetErrorMode( uNewMode )
594 	UINT	uNewMode
595 
596 
597 LONG
598 SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere )
599 	HANDLE	hFile
600 	LONG	ivOffset
601 	LONG *	ioivOffsetHigh
602 	DWORD	uFromWhere
603     CODE:
604 	RETVAL= SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere );
605 	if(  RETVAL == INVALID_SET_FILE_POINTER && (GetLastError() != NO_ERROR)  ) {
606 	    SaveErr( 1 );
607 	    XST_mNO(0);
608 	} else if(  0 == RETVAL  ) {
609 	    XST_mPV(0,"0 but true");
610 	} else {
611 	    XST_mIV(0,RETVAL);
612 	}
613     OUTPUT:
614 	ioivOffsetHigh
615 
616 
617 BOOL
618 SetHandleInformation( hObject, uMask, uFlags )
619 	HANDLE	hObject
620 	DWORD	uMask
621 	DWORD	uFlags
622     CODE:
623         RETVAL = SetHandleInformation( hObject, uMask, uFlags );
624 	SaveErr( !RETVAL );
625     OUTPUT:
626 	RETVAL
627 
628 
629 BOOL
630 WriteFile( hFile, pBuffer, lBytes, ouBytesWritten, pOverlapped )
631 	HANDLE		hFile
632 	BYTE *		pBuffer
633 	DWORD		lBytes		= init_buf_l($arg);
634 	oDWORD	&ouBytesWritten
635 	void *		pOverlapped
636     CODE:
637 	/* SvCUR(ST(1)) might "panic" if pBuffer isn't valid */
638 	if(  0 == lBytes  ) {
639 	    lBytes= SvCUR(ST(1));
640 	} else if(  SvCUR(ST(1)) < lBytes  ) {
641 	    croak( "%s: pBuffer value too short (%d < %d)",
642 	      "Win32API::File::WriteFile", SvCUR(ST(1)), lBytes );
643 	}
644 	RETVAL= WriteFile( hFile, pBuffer, lBytes,
645 		  &ouBytesWritten, (LPOVERLAPPED)pOverlapped );
646 	SaveErr( !RETVAL );
647     OUTPUT:
648 	RETVAL
649 	ouBytesWritten
650 
651 void
652 GetStdHandle(fd)
653     DWORD fd
654 PPCODE:
655 #ifdef _WIN64
656     XSRETURN_IV((DWORD_PTR)GetStdHandle(fd));
657 #else
658     XSRETURN_IV((DWORD)GetStdHandle(fd));
659 #endif
660 
661 void
662 SetStdHandle(fd,handle)
663     DWORD fd
664     HANDLE handle
665 PPCODE:
666     if (SetStdHandle(fd, handle))
667 	XSRETURN_YES;
668     else
669 	XSRETURN_NO;
670