This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add missing wchar.h include to Win32API::File
[perl5.git] / cpan / Win32API-File / File.xs
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
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
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;