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