This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add Win32API::File to the core
[perl5.git] / win32 / ext / Win32API / File / File.xs
diff --git a/win32/ext/Win32API/File/File.xs b/win32/ext/Win32API/File/File.xs
new file mode 100644 (file)
index 0000000..7dbe783
--- /dev/null
@@ -0,0 +1,647 @@
+/* Win32API/File.xs */
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+/*#include "patchlevel.h"*/
+
+/* Uncomment the next line unless set "WRITE_PERL=>1" in Makefile.PL: */
+#define NEED_newCONSTSUB
+#include "ppport.h"
+
+#ifdef WORD
+# undef WORD
+#endif
+
+#define  WIN32_LEAN_AND_MEAN   /* Tell windows.h to skip much */
+#include <windows.h>
+#include <winioctl.h>
+
+/*CONSTS_DEFINED*/
+
+#ifndef INVALID_SET_FILE_POINTER
+#   define INVALID_SET_FILE_POINTER    ((DWORD)-1)
+#endif
+
+#define oDWORD DWORD
+
+#if (PERL_REVISION <= 5 && PERL_VERSION < 5) || defined(__CYGWIN__)
+# define win32_get_osfhandle _get_osfhandle
+# ifdef __CYGWIN__
+#  define win32_open_osfhandle(handle,mode) \
+       (Perl_croak(aTHX_ "_open_osfhandle not implemented on Cygwin!"), -1)
+# else
+#  define win32_open_osfhandle _open_osfhandle
+# endif
+# ifdef _get_osfhandle
+#  undef _get_osfhandle        /* stolen_get_osfhandle() isn't available here */
+# endif
+# ifdef _open_osfhandle
+#  undef _open_osfhandle /* stolen_open_osfhandle() isn't available here */
+# endif
+#endif
+
+#ifndef XST_mUV
+# define XST_mUV(i,v)  (ST(i) = sv_2mortal(newSVuv(v))  )
+#endif
+
+#ifndef XSRETURN_UV
+# define XSRETURN_UV(v) STMT_START { XST_mUV(0,v);  XSRETURN(1); } STMT_END
+#endif
+
+#ifndef DEBUGGING
+# define       Debug(list)     /*Nothing*/
+#else
+# define       Debug(list)     ErrPrintf list
+# include <stdarg.h>
+    static void
+    ErrPrintf( const char *sFmt, ... )
+    {
+      va_list pAList;
+      static char *sEnv= NULL;
+      DWORD uErr= GetLastError();
+       if(  NULL == sEnv  ) {
+           if(  NULL == ( sEnv= getenv("DEBUG_WIN32API_FILE") )  )
+               sEnv= "";
+       }
+       if(  '\0' == *sEnv  )
+           return;
+       va_start( pAList, sFmt );
+       vfprintf( stderr, sFmt, pAList );
+       va_end( pAList );
+       SetLastError( uErr );
+    }
+#endif /* DEBUGGING */
+
+
+#include "buffers.h"   /* Include this after DEBUGGING setup finished */
+
+static LONG uLastFileErr= 0;
+
+static void
+SaveErr( BOOL bFailed )
+{
+    if(  bFailed  ) {
+       uLastFileErr= GetLastError();
+    }
+}
+
+MODULE = Win32API::File                PACKAGE = Win32API::File
+
+PROTOTYPES: DISABLE
+
+
+LONG
+_fileLastError( uError=0 )
+       DWORD   uError
+    CODE:
+       if(  1 <= items  ) {
+           uLastFileErr= uError;
+       }
+       RETVAL= uLastFileErr;
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+CloseHandle( hObject )
+       HANDLE  hObject
+    CODE:
+        RETVAL = CloseHandle( hObject );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+CopyFileA( sOldFileName, sNewFileName, bFailIfExists )
+       char *  sOldFileName
+       char *  sNewFileName
+       BOOL    bFailIfExists
+    CODE:
+        RETVAL = CopyFileA( sOldFileName, sNewFileName, bFailIfExists );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+CopyFileW( swOldFileName, swNewFileName, bFailIfExists )
+       WCHAR * swOldFileName
+       WCHAR * swNewFileName
+       BOOL    bFailIfExists
+    CODE:
+        RETVAL = CopyFileW( swOldFileName, swNewFileName, bFailIfExists );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+HANDLE
+CreateFileA( sPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel )
+       char *  sPath
+       DWORD   uAccess
+       DWORD   uShare
+       void *  pSecAttr
+       DWORD   uCreate
+       DWORD   uFlags
+       HANDLE  hModel
+    CODE:
+       RETVAL= CreateFileA( sPath, uAccess, uShare,
+         pSecAttr, uCreate, uFlags, hModel );
+       if(  INVALID_HANDLE_VALUE == RETVAL  ) {
+           SaveErr( 1 );
+           XSRETURN_NO;
+       } else if(  0 == RETVAL  ) {
+           XSRETURN_PV( "0 but true" );
+       } else {
+           XSRETURN_UV( PTR2UV(RETVAL) );
+       }
+
+
+HANDLE
+CreateFileW( swPath, uAccess, uShare, pSecAttr, uCreate, uFlags, hModel )
+       WCHAR * swPath
+       DWORD   uAccess
+       DWORD   uShare
+       void *  pSecAttr
+       DWORD   uCreate
+       DWORD   uFlags
+       HANDLE  hModel
+    CODE:
+       RETVAL= CreateFileW( swPath, uAccess, uShare,
+         pSecAttr, uCreate, uFlags, hModel );
+       if(  INVALID_HANDLE_VALUE == RETVAL  ) {
+           SaveErr( 1 );
+           XSRETURN_NO;
+       } else if(  0 == RETVAL  ) {
+           XSRETURN_PV( "0 but true" );
+       } else {
+           XSRETURN_UV( PTR2UV(RETVAL) );
+       }
+
+
+BOOL
+DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath )
+       DWORD   uFlags
+       char *  sDosDeviceName
+       char *  sTargetPath
+    CODE:
+        RETVAL = DefineDosDeviceA( uFlags, sDosDeviceName, sTargetPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath )
+       DWORD   uFlags
+       WCHAR * swDosDeviceName
+       WCHAR * swTargetPath
+    CODE:
+        RETVAL = DefineDosDeviceW( uFlags, swDosDeviceName, swTargetPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+DeleteFileA( sFileName )
+       char *  sFileName
+    CODE:
+        RETVAL = DeleteFileA( sFileName );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+DeleteFileW( swFileName )
+       WCHAR * swFileName
+    CODE:
+        RETVAL = DeleteFileW( swFileName );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf, opOutBuf, lOutBuf, olRetBytes, pOverlapped )
+       HANDLE  hDevice
+       DWORD   uIoControlCode
+       char *  pInBuf
+       DWORD   lInBuf          = init_buf_l($arg);
+       char *  opOutBuf        = NO_INIT
+       DWORD   lOutBuf         = init_buf_l($arg);
+       oDWORD  &olRetBytes
+       void *  pOverlapped
+    CODE:
+       if(  NULL != pInBuf  ) {
+           if(  0 == lInBuf  ) {
+               lInBuf= SvCUR(ST(2));
+           } else if(  SvCUR(ST(2)) < lInBuf  ) {
+               croak( "%s: pInBuf shorter than specified (%d < %d)",
+                 "Win32API::File::DeviceIoControl", SvCUR(ST(2)), lInBuf );
+           }
+       }
+       grow_buf_l( opOutBuf,ST(4),char *, lOutBuf,ST(5) );
+       RETVAL= DeviceIoControl( hDevice, uIoControlCode, pInBuf, lInBuf,
+                 opOutBuf, lOutBuf, &olRetBytes, pOverlapped );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       opOutBuf        trunc_buf_l( RETVAL, opOutBuf,ST(4), olRetBytes );
+       olRetBytes
+
+
+HANDLE
+FdGetOsFHandle( ivFd )
+       int     ivFd
+    CODE:
+       RETVAL= (HANDLE) win32_get_osfhandle( ivFd );
+       SaveErr( INVALID_HANDLE_VALUE == RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetDriveTypeA( sRootPath )
+       char *  sRootPath
+    CODE:
+        RETVAL = GetDriveTypeA( sRootPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetDriveTypeW( swRootPath )
+       WCHAR * swRootPath
+    CODE:
+        RETVAL = GetDriveTypeW( swRootPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetFileAttributesA( sPath )
+       char *  sPath
+    CODE:
+        RETVAL = GetFileAttributesA( sPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetFileAttributesW( swPath )
+       WCHAR * swPath
+    CODE:
+        RETVAL = GetFileAttributesW( swPath );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetFileType( hFile )
+       HANDLE  hFile
+    CODE:
+        RETVAL = GetFileType( hFile );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+GetHandleInformation( hObject, ouFlags )
+       HANDLE          hObject
+       oDWORD *        ouFlags
+    CODE:
+        RETVAL = GetHandleInformation( hObject, ouFlags );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       ouFlags
+
+
+DWORD
+GetLogicalDrives()
+    CODE:
+        RETVAL = GetLogicalDrives();
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+DWORD
+GetLogicalDriveStringsA( lBufSize, osBuffer )
+       DWORD   lBufSize        = init_buf_l($arg);
+       char *  osBuffer        = NO_INIT
+    CODE:
+       grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) );
+       RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer );
+       if(  lBufSize < RETVAL  &&  autosize(ST(0))  ) {
+           lBufSize= RETVAL;
+           grow_buf_l( osBuffer,ST(1),char *, lBufSize,ST(0) );
+           RETVAL= GetLogicalDriveStringsA( lBufSize, osBuffer );
+       }
+       if(  0 == RETVAL  ||  lBufSize < RETVAL  ) {
+           SaveErr( 1 );
+       } else {
+           trunc_buf_l( 1, osBuffer,ST(1), RETVAL );
+       }
+    OUTPUT:
+       RETVAL
+       osBuffer        ;/* The code for this appears above. */
+
+
+DWORD
+GetLogicalDriveStringsW( lwBufSize, oswBuffer )
+       DWORD   lwBufSize       = init_buf_lw($arg);
+       WCHAR * oswBuffer       = NO_INIT
+    CODE:
+       grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) );
+       RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer );
+       if(  lwBufSize < RETVAL  &&  autosize(ST(0))  ) {
+           lwBufSize= RETVAL;
+           grow_buf_lw( oswBuffer,ST(1), lwBufSize,ST(0) );
+           RETVAL= GetLogicalDriveStringsW( lwBufSize, oswBuffer );
+       }
+       if(  0 == RETVAL  ||  lwBufSize < RETVAL  ) {
+           SaveErr( 1 );
+       } else {
+           trunc_buf_lw( 1, oswBuffer,ST(1), RETVAL );
+       }
+    OUTPUT:
+       RETVAL
+       oswBuffer       ;/* The code for this appears above. */
+
+
+BOOL
+GetVolumeInformationA( sRootPath, osVolName, lVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, osFsType, lFsType )
+       char *  sRootPath
+       char *  osVolName       = NO_INIT
+       DWORD   lVolName        = init_buf_l($arg);
+       oDWORD  &ouSerialNum    = optUV($arg);
+       oDWORD  &ouMaxNameLen   = optUV($arg);
+       oDWORD  &ouFsFlags      = optUV($arg);
+       char *  osFsType        = NO_INIT
+       DWORD   lFsType         = init_buf_l($arg);
+    CODE:
+       grow_buf_l( osVolName,ST(1),char *, lVolName,ST(2) );
+       grow_buf_l( osFsType,ST(6),char *, lFsType,ST(7) );
+       RETVAL= GetVolumeInformationA( sRootPath, osVolName, lVolName,
+                 &ouSerialNum, &ouMaxNameLen, &ouFsFlags, osFsType, lFsType );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       osVolName       trunc_buf_z( RETVAL, osVolName,ST(1) );
+       osFsType        trunc_buf_z( RETVAL, osFsType,ST(6) );
+       ouSerialNum
+       ouMaxNameLen
+       ouFsFlags
+
+
+BOOL
+GetVolumeInformationW( swRootPath, oswVolName, lwVolName, ouSerialNum, ouMaxNameLen, ouFsFlags, oswFsType, lwFsType )
+       WCHAR * swRootPath
+       WCHAR * oswVolName      = NO_INIT
+       DWORD   lwVolName       = init_buf_lw($arg);
+       oDWORD  &ouSerialNum    = optUV($arg);
+       oDWORD  &ouMaxNameLen   = optUV($arg);
+       oDWORD  &ouFsFlags      = optUV($arg);
+       WCHAR * oswFsType       = NO_INIT
+       DWORD   lwFsType        = init_buf_lw($arg);
+    CODE:
+       grow_buf_lw( oswVolName,ST(1), lwVolName,ST(2) );
+       grow_buf_lw( oswFsType,ST(6), lwFsType,ST(7) );
+       RETVAL= GetVolumeInformationW( swRootPath, oswVolName, lwVolName,
+         &ouSerialNum, &ouMaxNameLen, &ouFsFlags, oswFsType, lwFsType );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       oswVolName      trunc_buf_zw( RETVAL, oswVolName,ST(1) );
+       oswFsType       trunc_buf_zw( RETVAL, oswFsType,ST(6) );
+       ouSerialNum
+       ouMaxNameLen
+       ouFsFlags
+
+
+BOOL
+IsRecognizedPartition( ivPartitionType )
+       int     ivPartitionType
+    CODE:
+        RETVAL = IsRecognizedPartition( ivPartitionType );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+IsContainerPartition( ivPartitionType )
+       int     ivPartitionType
+    CODE:
+        RETVAL = IsContainerPartition( ivPartitionType );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+MoveFileA( sOldName, sNewName )
+       char *  sOldName
+       char *  sNewName
+    CODE:
+        RETVAL = MoveFileA( sOldName, sNewName );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+MoveFileW( swOldName, swNewName )
+       WCHAR * swOldName
+       WCHAR * swNewName
+    CODE:
+        RETVAL = MoveFileW( swOldName, swNewName );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+MoveFileExA( sOldName, sNewName, uFlags )
+       char *  sOldName
+       char *  sNewName
+       DWORD   uFlags
+    CODE:
+        RETVAL = MoveFileExA( sOldName, sNewName, uFlags );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+MoveFileExW( swOldName, swNewName, uFlags )
+       WCHAR * swOldName
+       WCHAR * swNewName
+       DWORD   uFlags
+    CODE:
+        RETVAL = MoveFileExW( swOldName, swNewName, uFlags );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+long
+OsFHandleOpenFd( hOsFHandle, uMode )
+       long    hOsFHandle
+       DWORD   uMode
+    CODE:
+       RETVAL= win32_open_osfhandle( hOsFHandle, uMode );
+       if(  RETVAL < 0  ) {
+           SaveErr( 1 );
+           XSRETURN_NO;
+       } else if(  0 == RETVAL  ) {
+           XSRETURN_PV( "0 but true" );
+       } else {
+           XSRETURN_IV( (IV) RETVAL );
+       }
+
+
+DWORD
+QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf )
+       char *  sDeviceName
+       char *  osTargetPath    = NO_INIT
+       DWORD   lTargetBuf      = init_buf_l($arg);
+    CODE:
+       grow_buf_l( osTargetPath,ST(1),char *, lTargetBuf,ST(2) );
+       RETVAL= QueryDosDeviceA( sDeviceName, osTargetPath, lTargetBuf );
+       SaveErr( 0 == RETVAL );
+    OUTPUT:
+       RETVAL
+       osTargetPath    trunc_buf_l( 1, osTargetPath,ST(1), RETVAL );
+
+
+DWORD
+QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf )
+       WCHAR * swDeviceName
+       WCHAR * oswTargetPath   = NO_INIT
+       DWORD   lwTargetBuf     = init_buf_lw($arg);
+    CODE:
+       grow_buf_lw( oswTargetPath,ST(1), lwTargetBuf,ST(2) );
+       RETVAL= QueryDosDeviceW( swDeviceName, oswTargetPath, lwTargetBuf );
+       SaveErr( 0 == RETVAL );
+    OUTPUT:
+       RETVAL
+       oswTargetPath   trunc_buf_lw( 1, oswTargetPath,ST(1), RETVAL );
+
+
+BOOL
+ReadFile( hFile, opBuffer, lBytes, olBytesRead, pOverlapped )
+       HANDLE  hFile
+       BYTE *  opBuffer        = NO_INIT
+       DWORD   lBytes          = init_buf_l($arg);
+       oDWORD  &olBytesRead
+       void *  pOverlapped
+    CODE:
+       grow_buf_l( opBuffer,ST(1),BYTE *, lBytes,ST(2) );
+       /* Don't read more bytes than asked for if buffer is already big: */
+       lBytes= init_buf_l(ST(2));
+       if(  0 == lBytes  &&  autosize(ST(2))  ) {
+           lBytes= SvLEN( ST(1) ) - 1;
+       }
+       RETVAL= ReadFile( hFile, opBuffer, lBytes, &olBytesRead, pOverlapped );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       opBuffer        trunc_buf_l( RETVAL, opBuffer,ST(1), olBytesRead );
+       olBytesRead
+
+
+BOOL
+GetOverlappedResult( hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait)
+       HANDLE hFile
+       LPOVERLAPPED lpOverlapped
+       LPDWORD lpNumberOfBytesTransferred
+       BOOL bWait
+    CODE:
+       RETVAL= GetOverlappedResult( hFile, lpOverlapped,
+        lpNumberOfBytesTransferred, bWait);
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       lpOverlapped
+       lpNumberOfBytesTransferred
+
+DWORD
+GetFileSize( hFile, lpFileSizeHigh )
+       HANDLE hFile
+       LPDWORD lpFileSizeHigh
+    CODE:
+       RETVAL= GetFileSize( hFile, lpFileSizeHigh );
+       SaveErr( NO_ERROR != GetLastError() );
+    OUTPUT:
+       RETVAL
+       lpFileSizeHigh
+
+UINT
+SetErrorMode( uNewMode )
+       UINT    uNewMode
+
+
+LONG
+SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere )
+       HANDLE  hFile
+       LONG    ivOffset
+       LONG *  ioivOffsetHigh
+       DWORD   uFromWhere
+    CODE:
+       RETVAL= SetFilePointer( hFile, ivOffset, ioivOffsetHigh, uFromWhere );
+       if(  RETVAL == INVALID_SET_FILE_POINTER && (GetLastError() != NO_ERROR)  ) {
+           SaveErr( 1 );
+           XST_mNO(0);
+       } else if(  0 == RETVAL  ) {
+           XST_mPV(0,"0 but true");
+       } else {
+           XST_mIV(0,RETVAL);
+       }
+    OUTPUT:
+       ioivOffsetHigh
+
+
+BOOL
+SetHandleInformation( hObject, uMask, uFlags )
+       HANDLE  hObject
+       DWORD   uMask
+       DWORD   uFlags
+    CODE:
+        RETVAL = SetHandleInformation( hObject, uMask, uFlags );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+
+
+BOOL
+WriteFile( hFile, pBuffer, lBytes, ouBytesWritten, pOverlapped )
+       HANDLE          hFile
+       BYTE *          pBuffer
+       DWORD           lBytes          = init_buf_l($arg);
+       oDWORD  &ouBytesWritten
+       void *          pOverlapped
+    CODE:
+       /* SvCUR(ST(1)) might "panic" if pBuffer isn't valid */
+       if(  0 == lBytes  ) {
+           lBytes= SvCUR(ST(1));
+       } else if(  SvCUR(ST(1)) < lBytes  ) {
+           croak( "%s: pBuffer value too short (%d < %d)",
+             "Win32API::File::WriteFile", SvCUR(ST(1)), lBytes );
+       }
+       RETVAL= WriteFile( hFile, pBuffer, lBytes,
+                 &ouBytesWritten, pOverlapped );
+       SaveErr( !RETVAL );
+    OUTPUT:
+       RETVAL
+       ouBytesWritten