Add Win32API::File to the core
Steve Hay [Fri, 30 Jun 2006 13:46:06 +0000 (13:46 +0000)]
For discussions, see the thread starting here:
http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2006-06/msg00710.html

p4raw-id: //depot/perl@28460

21 files changed:
MANIFEST
Porting/Maintainers.pl
t/TEST
t/harness
win32/Makefile
win32/config_sh.PL
win32/ext/Win32API/File/Changes [new file with mode: 0644]
win32/ext/Win32API/File/ExtUtils/Myconst2perl.pm [new file with mode: 0644]
win32/ext/Win32API/File/File.pm [new file with mode: 0644]
win32/ext/Win32API/File/File.xs [new file with mode: 0644]
win32/ext/Win32API/File/Makefile.PL [new file with mode: 0644]
win32/ext/Win32API/File/README [new file with mode: 0644]
win32/ext/Win32API/File/buffers.h [new file with mode: 0644]
win32/ext/Win32API/File/cFile.h [new file with mode: 0644]
win32/ext/Win32API/File/cFile.pc [new file with mode: 0644]
win32/ext/Win32API/File/const2perl.h [new file with mode: 0644]
win32/ext/Win32API/File/ppport.h [new file with mode: 0644]
win32/ext/Win32API/File/t/file.t [new file with mode: 0644]
win32/ext/Win32API/File/t/tie.t [new file with mode: 0644]
win32/ext/Win32API/File/typemap [new file with mode: 0644]
win32/makefile.mk

index eeab56e..e87cb13 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -3702,6 +3702,20 @@ win32/dl_win32.xs                Win32 port
 win32/ext/Win32/Makefile.PL    Win32 extension makefile writer
 win32/ext/Win32/Win32.pm       Win32 extension Perl module
 win32/ext/Win32/Win32.xs       Win32 extension external subroutines
+win32/ext/Win32API/File/buffers.h                      Win32API::File extension
+win32/ext/Win32API/File/cFile.h                                Win32API::File extension
+win32/ext/Win32API/File/cFile.pc                       Win32API::File extension
+win32/ext/Win32API/File/Changes                                Win32API::File extension changes
+win32/ext/Win32API/File/const2perl.h                   Win32API::File extension
+win32/ext/Win32API/File/ExtUtils/Myconst2perl.pm       Win32API::File extension
+win32/ext/Win32API/File/File.pm                                Win32API::File extension
+win32/ext/Win32API/File/File.xs                                Win32API::File extension
+win32/ext/Win32API/File/Makefile.PL                    Win32API::File extension makefile write
+win32/ext/Win32API/File/ppport.h                       Win32API::File extension
+win32/ext/Win32API/File/README                         Win32API::File extension Readme
+win32/ext/Win32API/File/t/file.t                       See if Win32API::File extension works
+win32/ext/Win32API/File/t/tie.t                                See if Win32API::File extension works
+win32/ext/Win32API/File/typemap                                Win32API::File extension interface types
 win32/fcrypt.c                 crypt() implementation
 win32/FindExt.pm               Scan for extensions
 win32/genmk95.pl               Perl code to generate command.com-usable makefile.95
index dd8640d..427fdef 100644 (file)
@@ -62,6 +62,7 @@ package Maintainers;
        'tels'          => 'perl_dummy a-t bloodgate.com',
        'tomhughes'     => 'Tom Hughes <tomhughes@cpan.org>',
        'tjenness'      => 'Tim Jenness <tjenness@cpan.org>',
+       'tyemq'         => 'Tye McQueen <tyemq@cpan.org>',
        'yves'          => 'Yves Orton <yves@cpan.org>',
        );
 
@@ -695,6 +696,13 @@ package Maintainers;
                'CPAN'          => 0,
                },
 
+       'Win32API::File' =>
+               {
+               'MAINTAINER'    => 'tyemq',
+               'FILES'         => q[win32/ext/Win32API/File],
+               'CPAN'          => 1,
+               },
+
        'XSLoader' =>
                {
                'MAINTAINER'    => 'saper',
diff --git a/t/TEST b/t/TEST
index 08530ff..8e02299 100755 (executable)
--- a/t/TEST
+++ b/t/TEST
@@ -142,8 +142,9 @@ unless (@ARGV) {
     }
     my $mani = File::Spec->catfile($updir, "MANIFEST");
     if (open(MANI, $mani)) {
+       my $ext_pat = $^O eq 'MSWin32' ? '(?:win32/)?ext' : 'ext';
        while (<MANI>) { # similar code in t/harness
-           if (m!^(ext/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) {
+           if (m!^($ext_pat/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) {
                my $t = $1;
                my $extension = $2;
                if (!$::core || $t =~ m!^lib/[a-z]!)
index f52c441..b58bbb5 100644 (file)
--- a/t/harness
+++ b/t/harness
@@ -97,8 +97,9 @@ if (@ARGV) {
        my $mani  = File::Spec->catfile(File::Spec->updir, "MANIFEST");
        if (open(MANI, $mani)) {
            my @manitests = ();
+           my $ext_pat = $^O eq 'MSWin32' ? '(?:win32/)?ext' : 'ext';
            while (<MANI>) { # similar code in t/TEST
-               if (m!^(ext/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) {
+               if (m!^($ext_pat/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) {
                    my ($test, $extension) = ($1, $2);
                    if (defined $extension) {
                        $extension =~ s!/t$!!;
index 77b233c..6c342c1 100644 (file)
@@ -773,6 +773,7 @@ UNICODENORMALIZE    = $(EXTDIR)\Unicode\Normalize\Normalize
 MATHBIGINTFASTCALC     = $(EXTDIR)\Math\BigInt\FastCalc\FastCalc
 COMPRESSZLIB           = $(EXTDIR)\Compress\Zlib\Zlib
 WIN32_DIR              = ext\Win32
+WIN32APIFILE           = ext\Win32API\File\File
 
 SOCKET_DLL             = $(AUTODIR)\Socket\Socket.dll
 FCNTL_DLL              = $(AUTODIR)\Fcntl\Fcntl.dll
@@ -808,6 +809,7 @@ UNICODENORMALIZE_DLL        = $(AUTODIR)\Unicode\Normalize\Normalize.dll
 MATHBIGINTFASTCALC_DLL = $(AUTODIR)\Math\BigInt\FastCalc\FastCalc.dll
 COMPRESSZLIB_DLL       = $(AUTODIR)\Compress\Zlib\Zlib.dll
 WIN32_DLL              = $(AUTODIR)\Win32\Win32.dll
+WIN32APIFILE_DLL       = $(AUTODIR)\Win32API\File\File.dll
 
 EXTENSION_C    =               \
                $(SOCKET).c     \
@@ -843,7 +845,8 @@ EXTENSION_C =               \
                $(UNICODENORMALIZE).c   \
                $(MATHBIGINTFASTCALC).c \
                $(COMPRESSZLIB).c       \
-               $(WIN32_DIR).c
+               $(WIN32_DIR).c  \
+               $(WIN32APIFILE).c
 
 EXTENSION_DLL  =               \
                $(SOCKET_DLL)   \
@@ -879,7 +882,8 @@ EXTENSION_DLL       =               \
                $(UNICODENORMALIZE_DLL) \
                $(MATHBIGINTFASTCALC_DLL)       \
                $(COMPRESSZLIB_DLL)     \
-               $(WIN32_DLL)
+               $(WIN32_DLL)    \
+               $(WIN32APIFILE_DLL)
 
 CFG_VARS       =                                       \
                "INST_DRV=$(INST_DRV)"                  \
@@ -1194,6 +1198,8 @@ distclean: realclean
        -del /f $(LIBDIR)\Unicode\Normalize.pm
        -del /f $(LIBDIR)\Math\BigInt\FastCalc.pm
        -del /f $(LIBDIR)\Win32.pm
+       -del /f $(LIBDIR)\Win32API\File.pm
+       -del /f $(LIBDIR)\Win32API\File\cFile.pc
        -if exist $(LIBDIR)\B rmdir /s /q $(LIBDIR)\B
        -if exist $(LIBDIR)\Compress rmdir /s /q $(LIBDIR)\Compress
        -if exist $(LIBDIR)\Data rmdir /s /q $(LIBDIR)\Data
@@ -1209,6 +1215,7 @@ distclean: realclean
        -if exist $(LIBDIR)\Sys rmdir /s /q $(LIBDIR)\Sys
        -if exist $(LIBDIR)\threads rmdir /s /q $(LIBDIR)\threads
        -if exist $(LIBDIR)\XS rmdir /s /q $(LIBDIR)\XS
+       -if exist $(LIBDIR)\Win32API rmdir /s /q $(LIBDIR)\Win32API
        -cd $(PODDIR) && del /f *.html *.bat checkpods \
            perlaix.pod perlamiga.pod perlapollo.pod perlbeos.pod \
            perlbs2000.pod perlce.pod perlcn.pod perlcygwin.pod \
index db4eb56..1d9a831 100644 (file)
@@ -43,6 +43,7 @@ while (@{$optref} && $optref->[0] =~ /^([\w_]+)=(.*)$/) {
 }
 
 FindExt::scan_ext("../ext");
+FindExt::scan_ext("ext");
 FindExt::set_static_extensions(split ' ', $opt{'static_ext'});
 
 my @dynamic_ext = grep(!/Thread/,FindExt::dynamic_ext());
diff --git a/win32/ext/Win32API/File/Changes b/win32/ext/Win32API/File/Changes
new file mode 100644 (file)
index 0000000..147b694
--- /dev/null
@@ -0,0 +1,99 @@
+Revision history for Perl extension Win32API::File.
+
+0.10 2005-09-09
+       - Added GetFileAttributes() function and corresponding constants.
+         (Patches from Kenneth Olwing from 2004-11-12).
+       - cygwin patches from Rafael Kitover and Reini Urban.
+         This includes the addition of the GetFileSize(), getFileSize()
+         setFilePointer() and GetOverlappedResult() methods and the
+         experimental new object oriented interface.  All file position
+         operations use either Math::BigInt objects or 8 byte integers
+         (cygwin) for file offsets.
+
+0.0901 2005-08-30
+       - increased version number to show difference to standalone
+         CPAN release of Win32API-File-0.09.zip
+
+0.09 2005-02-18
+        - Support 5.007+
+
+0.09 [libwin32 version only]
+       - Add AUTHOR and ABSTRACT_FROM to Makefile.PL.
+       - Trivial speed improvements.
+       - Fixed F<test.pl> if Z: is a valid drive letter.
+
+0.08 2000-04-07
+       - C<GetOsFHandle> now returns false for failure.
+       - New F<buffers.h> supports C++ compilers.
+       - Read-only output-only parameters now generate an error.
+       - Added fileLastError() since C<$^E> is often quickly overwritten.
+       - Complete rewrite of how C constants are made available in Perl.
+       - Added fileConstant(), a nice way to look-up constants at run time.
+       - Added Get/SetHandleInformation and HANDLE_FLAG_* constants.
+       - Added IOCTL_DISK_GET_MEDIA_TYPES since *_STORAGE_* fails for floppy.
+       - Added several example scripts.
+
+0.07 1999-08-17
+       - Added DeleteFile().
+       - Removed prototypes from OsFHandleOpen() and GetOsFHandle() since
+         the C<*> doesn't prevent warnings about bareword file handles and
+         prevents the useful usage message if no arguments given.
+       - Fixed bug due to failed C<(/k/i,/t/i)> in list context returning
+         C<()> not C<(undef,undef)> in modern versions of Perl.
+       - Change order of C<#include>s so can build with Perl5.005 and later.
+       - Fixed C<test.pl> to ignore Perl bug where C<$^E> is truncated.
+       - Turned on C<CAPI> in C<Makefile.PL> for certain versions of Perl.
+       - Updated C<README>.
+
+0.06 1999-08-10
+       - Switch to new buffers.h and "Hungarian" notation!
+       - Added full documentation!
+       - ReadFile() no longer tries to read more bytes than asked for
+         just because the scalar buffer can hold more bytes!
+       - createFile() does better DWIM for share mode.
+       - Return SV_NO rather than C<0> for Boolean false.
+       - For boolean args, non-empty strings are C<1>, don't convert to int.
+       - Added ":MEDIA_TYPE" export class.
+       - Added C<GENERIC_ALL> and C<GENERIC_EXECUTE> to ":GENERIC_" exports.
+       - Added C<FdGetOsFHandle()> and C<GetOsFHandle()>!
+       - Added C<OsFHandleOpenFd()> and C<OsFHandleOpen()>!
+       - Support calling C<constant()> without the useless integer argument.
+       - Auto-load/export constants with C<()> prototype so can be in-lined.
+       - Added C<IsRecognizedPartition()> and C<IsContainerPartition()>.
+       - Added C<getLogicalDrives()>.
+       - Added ":FILE_" export class for specific types of access to files.
+       - Added C<SECURITY_SQOS_PRESENT> to ":SECURITY_" export class.
+       - Added ":PARTITION_" export class for partition types.
+       - Seriously bulked up the test suite.
+
+0.05 1998-08-21
+       - "-w" no longer warns that a buffer size of "=99" "isn't numeric".
+         nor if pass undef var for buffer size or output-only parameter.
+       - Added SetErrorMode() and :SEM_.
+       - createFile() sharing now defaults to "rw" to match C RTL.
+       - createFile() was ignoring "r" and "w" in access masks.
+
+0.04 1998-08-13
+       - Added GetLogicalDrives and GetLogicalDriveStrings.
+       - Added GetDriveType and GetVolumeInformation.
+       - Added DRIVE_* for GetDriveType().
+       - Added FS_* for GetVolumeInformation().
+       - Added createFile(), getLogicalDrives(), and attrLetsToBits() helpers.
+       - CreateFile() returns:  INVALID_HANDLE_VALUE->false, 0->"0 but true".
+       - More standardized "Hungarian" notation and uses buffers.h.
+       - Large unsigned values no longer made negative.
+
+0.03 1998-04-25
+       - Added DDD_* constants to File.pm and moved codes mistakenly
+         exported for :DDD_ to be exported for :Misc.
+       - Split large group of constants to increase efficiency.
+       - Minor cosmetic fixes.
+
+0.02 1998-03-03
+       - Added DeviceIoControl().
+       - Added some IOCTL_STORAGE_* and IOCTL_DISK_* constants
+       - Taught test.pl to verify all exported functions and constants.
+
+0.01 1997-12-08
+       - original version; based on Win32API::Registry.
+       - release to partner
diff --git a/win32/ext/Win32API/File/ExtUtils/Myconst2perl.pm b/win32/ext/Win32API/File/ExtUtils/Myconst2perl.pm
new file mode 100644 (file)
index 0000000..d4f936e
--- /dev/null
@@ -0,0 +1,361 @@
+# This should eventually become part of MakeMaker as ExtUtils::Mkconst2perl.
+# Documentation for this is very skimpy at this point.  Full documentation
+# will be added to ExtUtils::Mkconst2perl when it is created.
+package ExtUtils::Myconst2perl;
+
+use strict;
+use Config;
+
+use vars qw( @ISA @EXPORT @EXPORT_OK $VERSION );
+BEGIN {
+    require Exporter;
+    push @ISA, 'Exporter';
+    @EXPORT= qw( &Myconst2perl );
+    @EXPORT_OK= qw( &ParseAttribs );
+    $VERSION= 1.00;
+}
+
+use Carp;
+use File::Basename;
+use ExtUtils::MakeMaker qw( neatvalue );
+
+# Return the extension to use for a file of C++ source code:
+sub _cc
+{
+    # Some day, $Config{_cc} might be defined for us:
+    return $Config{_cc}   if  $Config{_cc};
+    return ".cxx";     # Seems to be the most widely accepted extension.
+}
+
+=item ParseAttribs
+
+Parses user-firendly options into coder-firendly specifics.
+
+=cut
+
+sub ParseAttribs
+{
+    # Usage:  ParseAttribs( "Package::Name", \%opts, {opt=>\$var} );
+    my( $pkg, $hvAttr, $hvRequests )= @_;
+    my( $outfile, @perlfiles, %perlfilecodes, @cfiles, %cfilecodes );
+    my @importlist= @{$hvAttr->{IMPORT_LIST}};
+    my $perlcode= $hvAttr->{PERL_PE_CODE} ||
+       'last if /^\s*(bootstrap|XSLoader::load)\b/';
+    my $ccode= $hvAttr->{C_PE_CODE} ||
+       'last if m#/[/*]\s*CONSTS_DEFINED\b|^\s*MODULE\b#';
+    my $ifdef= $hvAttr->{IFDEF} || 0;
+    my $writeperl= !! $hvAttr->{WRITE_PERL};
+    my $export= !! $hvAttr->{DO_EXPORT};
+    my $importto= $hvAttr->{IMPORT_TO} || "_constants";
+    my $cplusplus= $hvAttr->{CPLUSPLUS};
+    $cplusplus= ""   if  ! defined $cplusplus;
+    my $object= "";
+    my $binary= "";
+    my $final= "";
+    my $norebuild= "";
+    my $subroutine= "";
+    my $base;
+    my %params= (
+       PERL_PE_CODE => \$perlcode,
+       PERL_FILE_LIST => \@perlfiles,
+       PERL_FILE_CODES => \%perlfilecodes,
+       PERL_FILES => sub { map {($_,$perlfilecodes{$_})} @perlfiles },
+       C_PE_CODE => \$ccode,
+       C_FILE_LIST => \@cfiles,
+       C_FILE_CODES => \%cfilecodes,
+       C_FILES => sub { map {($_,$cfilecodes{$_})} @cfiles },
+       DO_EXPORT => \$export,
+       IMPORT_TO => \$importto,
+       IMPORT_LIST => \@importlist,
+       SUBROUTINE => \$subroutine,
+       IFDEF => \$ifdef,
+       WRITE_PERL => \$writeperl,
+       CPLUSPLUS => \$cplusplus,
+       BASEFILENAME => \$base,
+       OUTFILE => \$outfile,
+       OBJECT => \$object,
+       BINARY => \$binary,
+       FINAL_PERL => \$final,
+       NO_REBUILD => \$norebuild,
+    );
+    {   my @err= grep {! defined $params{$_}} keys %$hvAttr;
+       carp "ExtUtils::Myconst2perl::ParseAttribs:  ",
+         "Unsupported option(s) (@err).\n"
+         if  @err;
+    }
+    $norebuild= $hvAttr->{NO_REBUILD}   if  exists $hvAttr->{NO_REBUILD};
+    my $module= ( split /::/, $pkg )[-1];
+    $base= "c".$module;
+    $base= $hvAttr->{BASEFILENAME}   if  exists $hvAttr->{BASEFILENAME};
+    my $ext=  ! $cplusplus  ?  ($Config{_c}||".c")
+      :  $cplusplus =~ /^[.]/  ?  $cplusplus  :  _cc();
+    if(  $writeperl  ) {
+       $outfile= $base . "_pc" . $ext;
+       $object= $base . "_pc" . ($Config{_o}||$Config{obj_ext});
+       $object= $hvAttr->{OBJECT}   if  $hvAttr->{OBJECT};
+       $binary= $base . "_pc" . ($Config{_exe}||$Config{exe_ext});
+       $binary= $hvAttr->{BINARY}   if  $hvAttr->{BINARY};
+       $final= $base . ".pc";
+       $final= $hvAttr->{FINAL_PERL}   if  $hvAttr->{FINAL_PERL};
+       $subroutine= "main";
+    } elsif(  $cplusplus  ) {
+       $outfile= $base . $ext;
+       $object= $base . ($Config{_o}||$Config{obj_ext});
+       $object= $hvAttr->{OBJECT}   if  $hvAttr->{OBJECT};
+       $subroutine= "const2perl_" . $pkg;
+       $subroutine =~ s/\W/_/g;
+    } else {
+       $outfile= $base . ".h";
+    }
+    $outfile= $hvAttr->{OUTFILE}   if  $hvAttr->{OUTFILE};
+    if(  $hvAttr->{PERL_FILES}  ) {
+       carp "ExtUtils::Myconst2perl:  PERL_FILES option not allowed ",
+         "with PERL_FILE_LIST nor PERL_FILE_CODES.\n"
+         if  $hvAttr->{PERL_FILE_LIST}  ||  $hvAttr->{PERL_FILE_CODES};
+       %perlfilecodes= @{$hvAttr->{PERL_FILES}};
+       my $odd= 0;
+       @perlfiles= grep {$odd= !$odd} @{$hvAttr->{PERL_FILES}};
+    } else {
+       if(  $hvAttr->{PERL_FILE_LIST}  ) {
+           @perlfiles= @{$hvAttr->{PERL_FILE_LIST}};
+       } elsif(  $hvAttr->{PERL_FILE_CODES}  ) {
+           @perlfiles= keys %{$hvAttr->{PERL_FILE_CODES}};
+       } else {
+           @perlfiles= ( "$module.pm" );
+       }
+       %perlfilecodes= %{$hvAttr->{PERL_FILE_CODES}}
+         if  $hvAttr->{PERL_FILE_CODES};
+    }
+    for my $file (  @perlfiles  ) {
+       $perlfilecodes{$file}= $perlcode  if  ! $perlfilecodes{$file};
+    }
+    if(  ! $subroutine  ) {
+       ; # Don't process any C source code files.
+    } elsif(  $hvAttr->{C_FILES}  ) {
+       carp "ExtUtils::Myconst2perl:  C_FILES option not allowed ",
+         "with C_FILE_LIST nor C_FILE_CODES.\n"
+         if  $hvAttr->{C_FILE_LIST}  ||  $hvAttr->{C_FILE_CODES};
+       %cfilecodes= @{$hvAttr->{C_FILES}};
+       my $odd= 0;
+       @cfiles= grep {$odd= !$odd} @{$hvAttr->{C_FILES}};
+    } else {
+       if(  $hvAttr->{C_FILE_LIST}  ) {
+           @cfiles= @{$hvAttr->{C_FILE_LIST}};
+       } elsif(  $hvAttr->{C_FILE_CODES}  ) {
+           @cfiles= keys %{$hvAttr->{C_FILE_CODES}};
+       } elsif(  $writeperl  ||  $cplusplus  ) {
+           @cfiles= ( "$module.xs" );
+       }
+       %cfilecodes= %{$hvAttr->{C_FILE_CODES}}   if  $hvAttr->{C_FILE_CODES};
+    }
+    for my $file (  @cfiles  ) {
+       $cfilecodes{$file}= $ccode  if  ! $cfilecodes{$file};
+    }
+    for my $key (  keys %$hvRequests  ) {
+       if(  ! $params{$key}  ) {
+           carp "ExtUtils::Myconst2perl::ParseAttribs:  ",
+             "Unsupported output ($key).\n";
+       } elsif(  "SCALAR" eq ref( $params{$key} )  ) {
+           ${$hvRequests->{$key}}= ${$params{$key}};
+       } elsif(  "ARRAY" eq ref( $params{$key} )  ) {
+           @{$hvRequests->{$key}}= @{$params{$key}};
+       } elsif(  "HASH" eq ref( $params{$key} )  ) {
+           %{$hvRequests->{$key}}= %{$params{$key}};
+       } elsif(  "CODE" eq ref( $params{$key} )  ) {
+           @{$hvRequests->{$key}}=  &{$params{$key}};
+       } else {
+           die "Impossible value in \$params{$key}";
+       }
+    }
+}
+
+=item Myconst2perl
+
+Generates a file used to implement C constants as "constant subroutines" in
+a Perl module.
+
+Extracts a list of constants from a module's export list by C<eval>ing the
+first part of the Module's F<*.pm> file and then requesting some groups of
+symbols be exported/imported into a dummy package.  Then writes C or C++
+code that can convert each C constant into a Perl "constant subroutine"
+whose name is the constant's name and whose value is the constant's value.
+
+=cut
+
+sub Myconst2perl
+{
+    my( $pkg, %spec )= @_;
+    my( $outfile, $writeperl, $ifdef, $export, $importto, @importlist,
+        @perlfile, %perlcode, @cfile, %ccode, $routine );
+    ParseAttribs( $pkg, \%spec, {
+       DO_EXPORT => \$export,
+       IMPORT_TO => \$importto,
+       IMPORT_LIST => \@importlist,
+       IFDEF => \$ifdef,
+       WRITE_PERL => \$writeperl,
+       OUTFILE => \$outfile,
+       PERL_FILE_LIST => \@perlfile,
+       PERL_FILE_CODES => \%perlcode,
+       C_FILE_LIST => \@cfile,
+       C_FILE_CODES => \%ccode,
+       SUBROUTINE => \$routine,
+    } );
+    my $module= ( split /::/, $pkg )[-1];
+
+    warn "Writing $outfile...\n";
+    open( STDOUT, ">$outfile" )  or  die "Can't create $outfile: $!\n";
+
+    my $code= "";
+    my $file;
+    foreach $file (  @perlfile  ) {
+       warn "Reading Perl file, $file:  $perlcode{$file}\n";
+       open( MODULE, "<$file" )  or  die "Can't read Perl file, $file: $!\n";
+       eval qq[
+           while(  <MODULE>  ) {
+               $perlcode{$file};
+               \$code .= \$_;
+           }
+           1;
+       ]  or  die "$file eval: $@\n";
+       close( MODULE );
+    }
+
+    print
+      "/* $outfile - Generated by ExtUtils::Myconst2perl::Myconst2perl */\n";
+    if(  $routine  ) {
+       print "/* See start of $routine() for generation parameters used */\n";
+       #print "#define main _main_proto"
+       #  " /* Ignore Perl's main() prototype */\n\n";
+       if(  $writeperl  ) {
+           # Here are more reasons why the WRITE_PERL option is discouraged.
+           if(  $Config{useperlio}  ) {
+               print "#define PERLIO_IS_STDIO 1\n";
+           }
+           print "#define WIN32IO_IS_STDIO 1\n";       # May cause a warning
+           print "#define NO_XSLOCKS 1\n";     # What a hack!
+       }
+       foreach $file (  @cfile  ) {
+           warn "Reading C file, $file:  $ccode{$file}\n";
+           open( XS, "<$file" )  or  die "Can't read C file, $file: $!\n";
+           my $code= $ccode{$file};
+           $code =~ s#\\#\\\\#g;
+           $code =~ s#([^\s -~])#"\\x".sprintf "%02X",unpack "C",$1#ge;
+           $code =~ s#[*]/#*\\/#g;
+           print qq[\n/* Include $file:  $code */\n];
+           print qq[\n#line 1 "$file"\n];
+           eval qq[
+               while(  <XS>  ) {
+                   $ccode{$file};
+                   print;
+               }
+               1;
+           ]  or  die "$file eval: $@\n";
+           close( XS );
+       }
+       #print qq[\n#undef main\n];
+       print qq[\n#define CONST2WRITE_PERL\n];
+       print qq[\n#include "const2perl.h"\n\n];
+       if(  $writeperl  ) {
+           print "int\nmain( int argc, char *argv[], char *envp[] )\n";
+       } else {
+           print "void\n$routine( void )\n";
+       }
+    }
+    print "{\n";
+
+    {
+       @ExtUtils::Myconst2perl::importlist= @importlist;
+       my $var= '@ExtUtils::Myconst2perl::importlist';
+       my $port= $export ? "export" : "import";
+       my $arg2= $export ? "q[$importto]," : "";
+       local( $^W )= 0;
+       eval $code . "{\n"
+         . "    {    package $importto;\n"
+         . "        warn qq[\u${port}ing to $importto: $var\\n];\n"
+         . "        \$pkg->$port( $arg2 $var );\n"
+         . "    }\n"
+         . "    {   no strict 'refs';\n"
+         . "        $var=  sort keys %{'_constants::'};   }\n"
+         . "    warn 0 + $var, qq[ symbols ${port}ed.\\n];\n"
+         . "}\n1;\n"
+         or  die "eval: $@\n";
+    }
+    my @syms= @ExtUtils::Myconst2perl::importlist;
+
+    my $if;
+    my $const;
+    print qq[    START_CONSTS( "$pkg" )        /* No ";" */\n];
+    {
+       my( $head, $tail )= ( "/*", "\n" );
+       if(  $writeperl  ) {
+           $head= '    printf( "#';
+           $tail= '\\n" );' . "\n";
+           print $head, " Generated by $outfile.", $tail;
+       }
+       print $head, " Package $pkg with options:", $tail;
+       $head= " *"   if  ! $writeperl;
+       my $key;
+       foreach $key (  sort keys %spec  ) {
+           my $val= neatvalue($spec{$key});
+           $val =~ s/\\/\\\\/g   if  $writeperl;
+           print $head, "    $key => ", $val, $tail;
+       }
+       print $head, " Perl files eval'd:", $tail;
+       foreach $key (  @perlfile  ) {
+           my $code= $perlcode{$key};
+           $code =~ s#\\#\\\\#g;
+           $code =~ s#([^ -~])#"\\".sprintf "%03o",unpack "C",$1#ge;
+           $code =~ s#"#\\"#g   if  $writeperl;
+           print $head, "    $key => ", $code, $tail;
+       }
+       if(  $writeperl  ) {
+           print $head, " C files included:", $tail;
+           foreach $key (  @cfile  ) {
+               my $code= $ccode{$key};
+               $code =~ s#\\#\\\\#g;
+               $code =~ s#([^ -~])#"\\".sprintf "%03o",unpack "C",$1#ge;
+               $code =~ s#"#\\"#g;
+               print $head, "    $key => ", $code, $tail;
+           }
+       } else {
+           print " */\n";
+       }
+    }
+    if(  ! ref($ifdef)  &&  $ifdef =~ /[^\s\w]/  ) {
+       my $sub= $ifdef;
+       $sub= 'sub { local($_)= @_; ' . $sub . ' }'
+         unless  $sub =~ /^\s*sub\b/;
+       $ifdef= eval $sub;
+       die "$@:  $sub\n"   if  $@;
+       if(  "CODE" ne ref($ifdef)  ) {
+           die "IFDEF didn't create subroutine reference:  eval $sub\n";
+       }
+    }
+    foreach $const (  @syms  ) {
+       $if=  "CODE" eq ref($ifdef)  ?  $ifdef->($const)  :  $ifdef;
+       if(  ! $if  ) {
+           $if= "";
+       } elsif(  "1" eq $if  ) {
+           $if= "#ifdef $const\n";
+       } elsif(  $if !~ /^#/  ) {
+           $if= "#ifdef $if\n";
+       } else {
+           $if= "$if\n";
+       }
+       print $if
+         . qq[    const2perl( $const );\n];
+       if(  $if  ) {
+           print "#else\n"
+             . qq[    noconst( $const );\n]
+             . "#endif\n";
+       }
+    }
+    if(  $writeperl  ) {
+       print
+         qq[    printf( "1;\\n" );\n],
+         qq[    return( 0 );\n];
+    }
+    print "}\n";
+}
+
+1;
diff --git a/win32/ext/Win32API/File/File.pm b/win32/ext/Win32API/File/File.pm
new file mode 100644 (file)
index 0000000..b597fcf
--- /dev/null
@@ -0,0 +1,3035 @@
+# File.pm -- Low-level access to Win32 file/dir functions/constants.
+
+package Win32API::File;
+
+use strict;
+use integer;
+use Carp;
+use Config qw( %Config );
+use Fcntl qw( O_RDONLY O_RDWR O_WRONLY O_APPEND O_BINARY O_TEXT );
+use vars qw( $VERSION @ISA );
+use vars qw( @EXPORT @EXPORT_OK @EXPORT_FAIL %EXPORT_TAGS );
+
+$VERSION= '0.10';
+
+use base qw( Exporter DynaLoader Tie::Handle IO::File );
+
+# Math::BigInt optimizations courtesy of Tels
+BEGIN {
+       require Math::BigInt;
+       if (defined($Math::BigInt::VERSION) && $Math::BigInt::VERSION >= 1.60) {
+           Math::BigInt->import(lib => 'GMP');
+       }
+}
+
+my $_64BITINT  = defined $Config{use64bitint} &&
+                $Config{use64bitint} eq 'define';
+
+my $THIRTY_TWO = $_64BITINT ? 32 : new Math::BigInt 32;
+
+my $FFFFFFFF   = $_64BITINT ? 0xFFFFFFFF : new Math::BigInt 0xFFFFFFFF;
+
+@EXPORT= qw();
+%EXPORT_TAGS= (
+    Func =>    [qw(            attrLetsToBits          createFile
+       fileConstant            fileLastError           getLogicalDrives
+       CloseHandle             CopyFile                CreateFile
+       DefineDosDevice         DeleteFile              DeviceIoControl
+       FdGetOsFHandle          GetDriveType            GetFileAttributes               GetFileType
+       GetHandleInformation    GetLogicalDrives        GetLogicalDriveStrings
+       GetOsFHandle            GetVolumeInformation    IsRecognizedPartition
+       IsContainerPartition    MoveFile                MoveFileEx
+       OsFHandleOpen           OsFHandleOpenFd         QueryDosDevice
+       ReadFile                SetErrorMode            SetFilePointer
+       SetHandleInformation    WriteFile               GetFileSize
+       getFileSize             setFilePointer          GetOverlappedResult)],
+    FuncA =>   [qw(
+       CopyFileA               CreateFileA             DefineDosDeviceA
+       DeleteFileA             GetDriveTypeA           GetFileAttributesA              GetLogicalDriveStringsA
+       GetVolumeInformationA   MoveFileA               MoveFileExA
+       QueryDosDeviceA )],
+    FuncW =>   [qw(
+       CopyFileW               CreateFileW             DefineDosDeviceW
+       DeleteFileW             GetDriveTypeW           GetFileAttributesW              GetLogicalDriveStringsW
+       GetVolumeInformationW   MoveFileW               MoveFileExW
+       QueryDosDeviceW )],
+    Misc =>            [qw(
+       CREATE_ALWAYS           CREATE_NEW              FILE_BEGIN
+       FILE_CURRENT            FILE_END                INVALID_HANDLE_VALUE
+       OPEN_ALWAYS             OPEN_EXISTING           TRUNCATE_EXISTING )],
+    DDD_ =>    [qw(
+       DDD_EXACT_MATCH_ON_REMOVE                       DDD_RAW_TARGET_PATH
+       DDD_REMOVE_DEFINITION )],
+    DRIVE_ =>  [qw(
+       DRIVE_UNKNOWN           DRIVE_NO_ROOT_DIR       DRIVE_REMOVABLE
+       DRIVE_FIXED             DRIVE_REMOTE            DRIVE_CDROM
+       DRIVE_RAMDISK )],
+    FILE_ =>   [qw(
+       FILE_READ_DATA                  FILE_LIST_DIRECTORY
+       FILE_WRITE_DATA                 FILE_ADD_FILE
+       FILE_APPEND_DATA                FILE_ADD_SUBDIRECTORY
+       FILE_CREATE_PIPE_INSTANCE       FILE_READ_EA
+       FILE_WRITE_EA                   FILE_EXECUTE
+       FILE_TRAVERSE                   FILE_DELETE_CHILD
+       FILE_READ_ATTRIBUTES            FILE_WRITE_ATTRIBUTES
+       FILE_ALL_ACCESS                 FILE_GENERIC_READ
+       FILE_GENERIC_WRITE              FILE_GENERIC_EXECUTE )],
+    FILE_ATTRIBUTE_ => [qw(
+    INVALID_FILE_ATTRIBUTES
+    FILE_ATTRIBUTE_DEVICE        FILE_ATTRIBUTE_DIRECTORY
+    FILE_ATTRIBUTE_ENCRYPTED     FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
+    FILE_ATTRIBUTE_REPARSE_POINT FILE_ATTRIBUTE_SPARSE_FILE
+       FILE_ATTRIBUTE_ARCHIVE           FILE_ATTRIBUTE_COMPRESSED
+       FILE_ATTRIBUTE_HIDDEN            FILE_ATTRIBUTE_NORMAL
+       FILE_ATTRIBUTE_OFFLINE           FILE_ATTRIBUTE_READONLY
+       FILE_ATTRIBUTE_SYSTEM            FILE_ATTRIBUTE_TEMPORARY )],
+    FILE_FLAG_ =>      [qw(
+       FILE_FLAG_BACKUP_SEMANTICS      FILE_FLAG_DELETE_ON_CLOSE
+       FILE_FLAG_NO_BUFFERING          FILE_FLAG_OVERLAPPED
+       FILE_FLAG_POSIX_SEMANTICS       FILE_FLAG_RANDOM_ACCESS
+       FILE_FLAG_SEQUENTIAL_SCAN       FILE_FLAG_WRITE_THROUGH
+       FILE_FLAG_OPEN_REPARSE_POINT )],
+    FILE_SHARE_ =>     [qw(
+       FILE_SHARE_DELETE       FILE_SHARE_READ         FILE_SHARE_WRITE )],
+    FILE_TYPE_ =>      [qw(
+       FILE_TYPE_CHAR          FILE_TYPE_DISK          FILE_TYPE_PIPE
+       FILE_TYPE_UNKNOWN )],
+    FS_ =>     [qw(
+       FS_CASE_IS_PRESERVED            FS_CASE_SENSITIVE
+       FS_UNICODE_STORED_ON_DISK       FS_PERSISTENT_ACLS 
+       FS_FILE_COMPRESSION             FS_VOL_IS_COMPRESSED )],
+       FSCTL_ => [qw(
+       FSCTL_SET_REPARSE_POINT         FSCTL_GET_REPARSE_POINT
+       FSCTL_DELETE_REPARSE_POINT )],
+    HANDLE_FLAG_ =>    [qw(
+       HANDLE_FLAG_INHERIT             HANDLE_FLAG_PROTECT_FROM_CLOSE )],
+    IOCTL_STORAGE_ =>  [qw(
+       IOCTL_STORAGE_CHECK_VERIFY      IOCTL_STORAGE_MEDIA_REMOVAL
+       IOCTL_STORAGE_EJECT_MEDIA       IOCTL_STORAGE_LOAD_MEDIA
+       IOCTL_STORAGE_RESERVE           IOCTL_STORAGE_RELEASE
+       IOCTL_STORAGE_FIND_NEW_DEVICES  IOCTL_STORAGE_GET_MEDIA_TYPES
+       )],
+    IOCTL_DISK_ =>     [qw(
+       IOCTL_DISK_FORMAT_TRACKS        IOCTL_DISK_FORMAT_TRACKS_EX
+       IOCTL_DISK_GET_DRIVE_GEOMETRY   IOCTL_DISK_GET_DRIVE_LAYOUT
+       IOCTL_DISK_GET_MEDIA_TYPES      IOCTL_DISK_GET_PARTITION_INFO
+       IOCTL_DISK_HISTOGRAM_DATA       IOCTL_DISK_HISTOGRAM_RESET
+       IOCTL_DISK_HISTOGRAM_STRUCTURE  IOCTL_DISK_IS_WRITABLE
+       IOCTL_DISK_LOGGING              IOCTL_DISK_PERFORMANCE
+       IOCTL_DISK_REASSIGN_BLOCKS      IOCTL_DISK_REQUEST_DATA
+       IOCTL_DISK_REQUEST_STRUCTURE    IOCTL_DISK_SET_DRIVE_LAYOUT
+       IOCTL_DISK_SET_PARTITION_INFO   IOCTL_DISK_VERIFY )],
+    GENERIC_ =>                [qw(
+       GENERIC_ALL                     GENERIC_EXECUTE
+       GENERIC_READ                    GENERIC_WRITE )],
+    MEDIA_TYPE =>      [qw(
+       Unknown                 F5_1Pt2_512             F3_1Pt44_512
+       F3_2Pt88_512            F3_20Pt8_512            F3_720_512
+       F5_360_512              F5_320_512              F5_320_1024
+       F5_180_512              F5_160_512              RemovableMedia
+       FixedMedia              F3_120M_512 )],
+    MOVEFILE_ =>       [qw(
+       MOVEFILE_COPY_ALLOWED           MOVEFILE_DELAY_UNTIL_REBOOT
+       MOVEFILE_REPLACE_EXISTING       MOVEFILE_WRITE_THROUGH )],
+    SECURITY_ =>       [qw(
+       SECURITY_ANONYMOUS              SECURITY_CONTEXT_TRACKING
+       SECURITY_DELEGATION             SECURITY_EFFECTIVE_ONLY
+       SECURITY_IDENTIFICATION         SECURITY_IMPERSONATION
+       SECURITY_SQOS_PRESENT )],
+    SEM_ =>            [qw(
+       SEM_FAILCRITICALERRORS          SEM_NOGPFAULTERRORBOX
+       SEM_NOALIGNMENTFAULTEXCEPT      SEM_NOOPENFILEERRORBOX )],
+    PARTITION_ =>      [qw(
+       PARTITION_ENTRY_UNUSED          PARTITION_FAT_12
+       PARTITION_XENIX_1               PARTITION_XENIX_2
+       PARTITION_FAT_16                PARTITION_EXTENDED
+       PARTITION_HUGE                  PARTITION_IFS
+       PARTITION_FAT32                 PARTITION_FAT32_XINT13
+       PARTITION_XINT13                PARTITION_XINT13_EXTENDED
+       PARTITION_PREP                  PARTITION_UNIX
+       VALID_NTFT                      PARTITION_NTFT )],
+);
+@EXPORT_OK= ();
+{
+    my $key;
+    foreach $key (  keys(%EXPORT_TAGS)  ) {
+       push( @EXPORT_OK, @{$EXPORT_TAGS{$key}} );
+       #push( @EXPORT_FAIL, @{$EXPORT_TAGS{$key}} )   unless  $key =~ /^Func/;
+    }
+}
+$EXPORT_TAGS{ALL}= \@EXPORT_OK;
+
+bootstrap Win32API::File $VERSION;
+
+# Preloaded methods go here.
+
+# To convert C constants to Perl code in cFile.pc
+# [instead of C or C++ code in cFile.h]:
+#    * Modify F<Makefile.PL> to add WriteMakeFile() =>
+#      CONST2PERL/postamble => [[ "Win32API::File" => ]] WRITE_PERL => 1.
+#    * Either comment out C<#include "cFile.h"> from F<File.xs>
+#      or make F<cFile.h> an empty file.
+#    * Make sure the following C<if> block is not commented out.
+#    * "nmake clean", "perl Makefile.PL", "nmake"
+
+if(  ! defined &GENERIC_READ  ) {
+    require "Win32API/File/cFile.pc";
+}
+
+sub fileConstant
+{
+    my( $name )= @_;
+    if(  1 != @_  ||  ! $name  ||  $name =~ /\W/  ) {
+       require Carp;
+       Carp::croak( 'Usage: ',__PACKAGE__,'::fileConstant("CONST_NAME")' );
+    }
+    my $proto= prototype $name;
+    if(  defined \&$name
+     &&  defined $proto
+     &&  "" eq $proto  ) {
+       no strict 'refs';
+       return &$name;
+    }
+    return undef;
+}
+
+# We provide this for backwards compatibility:
+sub constant
+{
+    my( $name )= @_;
+    my $value= fileConstant( $name );
+    if(  defined $value  ) {
+       $!= 0;
+       return $value;
+    }
+    $!= 11; # EINVAL
+    return 0;
+}
+
+# BEGIN {
+#     my $code= 'return _fileLastError(@_)';
+#     local( $!, $^E )= ( 1, 1 );
+#     if(  $! ne $^E  ) {
+#      $code= '
+#          local( $^E )= _fileLastError(@_);
+#          my $ret= $^E;
+#          return $ret;
+#      ';
+#     }
+#     eval "sub fileLastError { $code }";
+#     die "$@"   if  $@;
+# }
+
+package Win32API::File::_error;
+
+use overload
+    '""' => sub {
+       require Win32 unless defined &Win32::FormatMessage;
+       $_ = Win32::FormatMessage(Win32API::File::_fileLastError());
+       tr/\r\n//d;
+       return $_;
+    },
+    '0+' => sub { Win32API::File::_fileLastError() },
+    'fallback' => 1;
+
+sub new { return bless {}, shift }
+sub set { Win32API::File::_fileLastError($_[1]); return $_[0] }
+
+package Win32API::File;
+
+my $_error = new Win32API::File::_error;
+
+sub fileLastError {
+    croak 'Usage: ',__PACKAGE__,'::fileLastError( [$setWin32ErrCode] )'        if @_ > 1;
+    $_error->set($_[0]) if defined $_[0];
+    return $_error;
+}
+
+# Since we ISA DynaLoader which ISA AutoLoader, we ISA AutoLoader so we
+# need this next chunk to prevent Win32API::File->nonesuch() from
+# looking for "nonesuch.al" and producing confusing error messages:
+use vars qw($AUTOLOAD);
+sub AUTOLOAD {
+    require Carp;
+    Carp::croak(
+      "Can't locate method $AUTOLOAD via package Win32API::File" );
+}
+
+# Replace "&rout;" with "goto &rout;" when that is supported on Win32.
+
+# Aliases for non-Unicode functions:
+sub CopyFile                   { &CopyFileA; }
+sub CreateFile                 { &CreateFileA; }
+sub DefineDosDevice            { &DefineDosDeviceA; }
+sub DeleteFile                 { &DeleteFileA; }
+sub GetDriveType               { &GetDriveTypeA; }
+sub GetFileAttributes  { &GetFileAttributesA; }
+sub GetLogicalDriveStrings     { &GetLogicalDriveStringsA; }
+sub GetVolumeInformation       { &GetVolumeInformationA; }
+sub MoveFile                   { &MoveFileA; }
+sub MoveFileEx                 { &MoveFileExA; }
+sub QueryDosDevice             { &QueryDosDeviceA; }
+
+sub OsFHandleOpen {
+    if(  3 != @_  ) {
+       croak 'Win32API::File Usage:  ',
+             'OsFHandleOpen(FILE,$hNativeHandle,"rwatb")';
+    }
+    my( $fh, $osfh, $access )= @_;
+    if(  ! ref($fh)  ) {
+       if(  $fh !~ /('|::)/  ) {
+           $fh= caller() . "::" . $fh;
+       }
+       no strict "refs";
+       $fh= \*{$fh};
+    }
+    my( $mode, $pref );
+    if(  $access =~ /r/i  ) {
+       if(  $access =~ /w/i  ) {
+           $mode= O_RDWR;
+           $pref= "+<";
+       } else {
+           $mode= O_RDONLY;
+           $pref= "<";
+       }
+    } else {
+       if(  $access =~ /w/i  ) {
+           $mode= O_WRONLY;
+           $pref= ">";
+       } else {
+       #   croak qq<Win32API::File::OsFHandleOpen():  >,
+       #         qq<Access ($access) missing both "r" and "w">;
+           $mode= O_RDONLY;
+           $pref= "<";
+       }
+    }
+    $mode |= O_APPEND   if  $access =~ /a/i;
+    #$mode |= O_TEXT   if  $access =~ /t/i;
+    # Some versions of the Fcntl module are broken and won't autoload O_TEXT:
+    if(  $access =~ /t/i  ) {
+       my $o_text= eval "O_TEXT";
+       $o_text= 0x4000   if  $@;
+       $mode |= $o_text;
+    }
+    $mode |= O_BINARY   if  $access =~ /b/i;
+    my $fd = eval { OsFHandleOpenFd( $osfh, $mode ) };
+    if ($@) {
+       return tie *{$fh}, __PACKAGE__, $osfh;
+    }
+    return  undef if  $fd < 0;
+    return  open( $fh, $pref."&=".$fd );
+}
+
+sub GetOsFHandle {
+    if(  1 != @_  ) {
+       croak 'Win32API::File Usage:  $OsFHandle= GetOsFHandle(FILE)';
+    }
+    my( $file )= @_;
+    if(  ! ref($file)  ) {
+       if(  $file !~ /('|::)/  ) {
+           $file= caller() . "::" . $file;
+       }
+       no strict "refs";
+       # The eval "" is necessary in Perl 5.6, avoid it otherwise.
+       my $tied = !defined($^]) || $^] < 5.008
+                       ? eval "tied *{$file}"
+                       : tied *{$file};
+
+       if (UNIVERSAL::isa($tied => __PACKAGE__)) {
+               return $tied->win32_handle;
+       }
+
+       $file= *{$file};
+    }
+    my( $fd )= fileno($file);
+    if(  ! defined( $fd )  ) {
+       if(  $file =~ /^\d+\Z/  ) {
+           $fd= $file;
+       } else {
+           return ();  # $! should be set by fileno().
+       }
+    }
+    my $h= FdGetOsFHandle( $fd );
+    if(  INVALID_HANDLE_VALUE() == $h  ) {
+       $h= "";
+    } elsif(  "0" eq $h  ) {
+       $h= "0 but true";
+    }
+    return $h;
+}
+
+sub getFileSize {
+    croak 'Win32API::File Usage:  $size= getFileSize($hNativeHandle)'
+       if @_ != 1;
+
+    my $handle    = shift;
+    my $high_size = 0;
+
+    my $low_size = GetFileSize($handle, $high_size);
+
+    my $retval = $_64BITINT ? $high_size : new Math::BigInt $high_size;
+
+    $retval <<= $THIRTY_TWO;
+    $retval +=  $low_size;
+
+    return $retval;
+}
+
+sub setFilePointer {
+    croak 'Win32API::File Usage:  $pos= setFilePointer($hNativeHandle, $posl, $from_where)'
+       if @_ != 3;
+
+    my ($handle, $pos, $from_where) = @_;
+
+    my ($pos_low, $pos_high) = ($pos, 0);
+
+    if ($_64BITINT) {
+       $pos_low  = ($pos & $FFFFFFFF);
+       $pos_high = (($pos >> $THIRTY_TWO) & $FFFFFFFF);
+    }
+    elsif (UNIVERSAL::isa($pos => 'Math::BigInt')) {
+       $pos_low  = ($pos & $FFFFFFFF)->numify();
+       $pos_high = (($pos >> $THIRTY_TWO) & $FFFFFFFF)->numify();
+    }
+
+    my $retval = SetFilePointer($handle, $pos_low, $pos_high, $from_where);
+
+    if (defined $pos_high && $pos_high != 0) {
+       $retval   = new Math::BigInt $retval   unless $_64BITINT;
+       $pos_high = new Math::BigInt $pos_high unless $_64BITINT;
+
+       $retval += $pos_high << $THIRTY_TWO;
+    }
+
+    return $retval;
+}
+
+sub attrLetsToBits
+{
+    my( $lets )= @_;
+    my( %a )= (
+      "a"=>FILE_ATTRIBUTE_ARCHIVE(),   "c"=>FILE_ATTRIBUTE_COMPRESSED(),
+      "h"=>FILE_ATTRIBUTE_HIDDEN(),    "o"=>FILE_ATTRIBUTE_OFFLINE(),
+      "r"=>FILE_ATTRIBUTE_READONLY(),  "s"=>FILE_ATTRIBUTE_SYSTEM(),
+      "t"=>FILE_ATTRIBUTE_TEMPORARY() );
+    my( $bits )= 0;
+    foreach(  split(//,$lets)  ) {
+       croak "Win32API::File::attrLetsToBits: Unknown attribute letter ($_)"
+         unless  exists $a{$_};
+       $bits |= $a{$_};
+    }
+    return $bits;
+}
+
+use vars qw( @_createFile_Opts %_createFile_Opts );
+@_createFile_Opts= qw( Access Create Share Attributes
+                      Flags Security Model );
+@_createFile_Opts{@_createFile_Opts}= (1) x @_createFile_Opts;
+
+sub createFile
+{
+    my $opts= "";
+    if(  2 <= @_  &&  "HASH" eq ref($_[$#_])  ) {
+       $opts= pop( @_ );
+    }
+    my( $sPath, $svAccess, $svShare )= @_;
+    if(  @_ < 1  ||  3 < @_  ) {
+       croak "Win32API::File::createFile() usage:  \$hObject= createFile(\n",
+             "  \$sPath, [\$svAccess_qrw_ktn_ce,[\$svShare_rwd,]]",
+             " [{Option=>\$Value}] )\n",
+             "    options: @_createFile_Opts\nCalled";
+    }
+    my( $create, $flags, $sec, $model )= ( "", 0, [], 0 );
+    if(  ref($opts)  ) {
+        my @err= grep( ! $_createFile_Opts{$_}, keys(%$opts) );
+       @err  and  croak "_createFile:  Invalid options (@err)";
+       $flags= $opts->{Flags}          if  exists( $opts->{Flags} );
+       $flags |= attrLetsToBits( $opts->{Attributes} )
+                                       if  exists( $opts->{Attributes} );
+       $sec= $opts->{Security}         if  exists( $opts->{Security} );
+       $model= $opts->{Model}          if  exists( $opts->{Model} );
+       $svAccess= $opts->{Access}      if  exists( $opts->{Access} );
+       $create= $opts->{Create}        if  exists( $opts->{Create} );
+       $svShare= $opts->{Share}        if  exists( $opts->{Share} );
+    }
+    $svAccess= "r"             unless  defined($svAccess);
+    $svShare= "rw"             unless  defined($svShare);
+    if(  $svAccess =~ /^[qrw ktn ce]*$/i  ) {
+       ( my $c= $svAccess ) =~ tr/qrw QRW//d;
+       $create= $c   if  "" ne $c  &&  "" eq $create;
+       local( $_ )= $svAccess;
+       $svAccess= 0;
+       $svAccess |= GENERIC_READ()   if  /r/i;
+       $svAccess |= GENERIC_WRITE()   if  /w/i;
+    } elsif(  "?" eq $svAccess  ) {
+       croak
+         "Win32API::File::createFile:  \$svAccess can use the following:\n",
+             "    One or more of the following:\n",
+             "\tq -- Query access (same as 0)\n",
+             "\tr -- Read access (GENERIC_READ)\n",
+             "\tw -- Write access (GENERIC_WRITE)\n",
+             "    At most one of the following:\n",
+             "\tk -- Keep if exists\n",
+             "\tt -- Truncate if exists\n",
+             "\tn -- New file only (fail if file already exists)\n",
+             "    At most one of the following:\n",
+             "\tc -- Create if doesn't exist\n",
+             "\te -- Existing file only (fail if doesn't exist)\n",
+             "  ''   is the same as 'q  k e'\n",
+             "  'r'  is the same as 'r  k e'\n",
+             "  'w'  is the same as 'w  t c'\n",
+             "  'rw' is the same as 'rw k c'\n",
+             "  'rt' or 'rn' implies 'c'.\n",
+             "  Or \$svAccess can be numeric.\n", "Called from";
+    } elsif(  $svAccess == 0  &&  $svAccess !~ /^[-+.]*0/  ) {
+       croak "Win32API::File::createFile:  Invalid \$svAccess ($svAccess)";
+    }
+    if(  $create =~ /^[ktn ce]*$/  ) {
+        local( $_ )= $create;
+        my( $k, $t, $n, $c, $e )= ( scalar(/k/i), scalar(/t/i),
+         scalar(/n/i), scalar(/c/i), scalar(/e/i) );
+       if(  1 < $k + $t + $n  ) {
+           croak "Win32API::File::createFile: \$create must not use ",
+             qq<more than one of "k", "t", and "n" ($create)>;
+       }
+       if(  $c  &&  $e  ) {
+           croak "Win32API::File::createFile: \$create must not use ",
+             qq<both "c" and "e" ($create)>;
+       }
+       my $r= ( $svAccess & GENERIC_READ() ) == GENERIC_READ();
+       my $w= ( $svAccess & GENERIC_WRITE() ) == GENERIC_WRITE();
+       if(  ! $k  &&  ! $t  &&  ! $n  ) {
+           if(  $w  &&  ! $r  ) {              $t= 1;
+           } else {                            $k= 1; }
+       }
+       if(  $k  ) {
+           if(  $c  ||  $w && ! $e  ) {        $create= OPEN_ALWAYS();
+           } else {                            $create= OPEN_EXISTING(); }
+       } elsif(  $t  ) {
+           if(  $e  ) {                        $create= TRUNCATE_EXISTING();
+           } else {                            $create= CREATE_ALWAYS(); }
+       } else { # $n
+           if(  ! $e  ) {                      $create= CREATE_NEW();
+           } else {
+               croak "Win32API::File::createFile: \$create must not use ",
+                 qq<both "n" and "e" ($create)>;
+           }
+       }
+    } elsif(  "?" eq $create  ) {
+       croak 'Win32API::File::createFile: $create !~ /^[ktn ce]*$/;',
+             ' pass $svAccess as "?" for more information.';
+    } elsif(  $create == 0  &&  $create ne "0"  ) {
+       croak "Win32API::File::createFile: Invalid \$create ($create)";
+    }
+    if(  $svShare =~ /^[drw]*$/  ) {
+        my %s= ( "d"=>FILE_SHARE_DELETE(), "r"=>FILE_SHARE_READ(),
+                "w"=>FILE_SHARE_WRITE() );
+        my @s= split(//,$svShare);
+       $svShare= 0;
+       foreach( @s ) {
+           $svShare |= $s{$_};
+       }
+    } elsif(  $svShare == 0  &&  $svShare !~ /^[-+.]*0/  ) {
+       croak "Win32API::File::createFile: Invalid \$svShare ($svShare)";
+    }
+    return  CreateFileA(
+             $sPath, $svAccess, $svShare, $sec, $create, $flags, $model );
+}
+
+
+sub getLogicalDrives
+{
+    my( $ref )= @_;
+    my $s= "";
+    if(  ! GetLogicalDriveStringsA( 256, $s )  ) {
+       return undef;
+    }
+    if(  ! defined($ref)  ) {
+       return  split( /\0/, $s );
+    } elsif(  "ARRAY" ne ref($ref)  ) {
+       croak 'Usage:  C<@arr= getLogicalDrives()> ',
+             'or C<getLogicalDrives(\\@arr)>', "\n";
+    }
+    @$ref= split( /\0/, $s );
+    return $ref;
+}
+
+###############################################################################
+#   Experimental Tied Handle and Object Oriented interface.                   #
+###############################################################################
+
+sub new {
+       my $class = shift;
+       $class = ref $class || $class;
+
+       my $self = IO::File::new($class);
+       tie *$self, __PACKAGE__;
+
+       $self->open(@_) if @_;
+
+       return $self;
+}
+
+sub TIEHANDLE {
+       my ($class, $win32_handle) = @_;
+       $class = ref $class || $class;
+
+       return bless {
+               _win32_handle => $win32_handle,
+               _binmode      => 0,
+               _buffered     => 0,
+               _buffer       => '',
+               _eof          => 0,
+               _fileno       => undef,
+               _access       => 'r',
+               _append       => 0,
+       }, $class;
+}
+
+# This is called for getting the tied object from hard refs to glob refs in
+# some cases, for reasons I don't quite grok.
+
+sub FETCH { return $_[0] }
+
+# Public accessors
+
+sub win32_handle{ $_[0]->{_win32_handle}||= $_[1] }
+
+# Protected accessors
+
+sub _buffer    { $_[0]->{_buffer}      ||= $_[1] }
+sub _binmode   { $_[0]->{_binmode}     ||= $_[1] }
+sub _fileno    { $_[0]->{_fileno}      ||= $_[1] }
+sub _access    { $_[0]->{_access}      ||= $_[1] }
+sub _append    { $_[0]->{_append}      ||= $_[1] }
+
+# Tie interface
+
+sub OPEN {
+       my $self  = shift;
+       my $expr  = shift;
+       croak "Only the two argument form of open is supported at this time" if @_;
+# FIXME: this needs to parse the full Perl open syntax in $expr
+
+       my ($mixed, $mode, $path) =
+               ($expr =~ /^\s* (\+)? \s* (<|>|>>)? \s* (.*?) \s*$/x);
+
+       croak "Unsupported open mode" if not $path;
+
+       my $access = 'r';
+       my $append = $mode eq '>>' ? 1 : 0;
+
+       if ($mixed) {
+               $access = 'rw';
+       } elsif($mode eq '>') {
+               $access = 'w';
+       }
+
+       my $w32_handle = createFile($path, $access);
+
+       $self->win32_handle($w32_handle);
+
+       $self->seek(1,2) if $append;
+
+       $self->_access($access);
+       $self->_append($append);
+
+       return 1;
+}
+
+sub BINMODE {
+       $_[0]->_binmode(1);
+}
+
+sub WRITE {
+       my ($self, $buf, $len, $offset, $overlap) = @_;
+
+       if ($offset) {
+               $buf = substr($buf, $offset);
+               $len = length($buf);
+       }
+
+       $len       = length($buf) if not defined $len;
+
+       $overlap   = [] if not defined $overlap;;
+
+       my $bytes_written = 0;
+
+       WriteFile (
+               $self->win32_handle, $buf, $len,
+               $bytes_written, $overlap
+       );
+
+       return $bytes_written;
+}
+
+sub PRINT {
+       my $self = shift;
+
+       my $buf = join defined $, ? $, : "" => @_;
+
+       $buf =~ s/\012/\015\012/sg unless $self->_binmode();
+
+       $buf .= $\ if defined $\;
+
+       $self->WRITE($buf, length($buf), 0);
+}
+
+sub READ {
+       my $self = shift;
+       my $into = \$_[0]; shift;
+       my ($len, $offset, $overlap) = @_;
+
+       my $buffer     = defined $self->_buffer ? $self->_buffer : "";
+       my $buf_length = length($buffer);
+       my $bytes_read = 0;
+       my $data;
+       $offset        = 0 if not defined $offset;
+
+       if ($buf_length >= $len) {
+               $data       = substr($buffer, 0, $len => "");
+               $bytes_read = $len;
+               $self->_buffer($buffer);
+       } else {
+               if ($buf_length > 0) {
+                       $len -= $buf_length;
+                       substr($$into, $offset) = $buffer;
+                       $offset += $buf_length;
+               }
+
+               $overlap ||= [];
+
+               ReadFile (
+                       $self->win32_handle, $data, $len,
+                       $bytes_read, $overlap
+               );
+       }
+
+       $$into = "" if not defined $$into;
+
+       substr($$into, $offset) = $data;
+
+       return $bytes_read;
+}
+
+sub READLINE {
+       my $self = shift;
+       my $line = "";
+
+       while ((index $line, $/) == $[-1) { # read until end of line marker
+               my $char = $self->GETC();
+
+               last if !defined $char || $char eq '';
+
+               $line .= $char;
+       }
+
+       return undef if $line eq '';
+
+       return $line;
+}
+
+
+sub FILENO {
+       my $self = shift;
+
+       return $self->_fileno() if defined $self->_fileno();
+
+       return -1 if $^O eq 'cygwin';
+
+# FIXME: We don't always open the handle, better to query the handle or to set
+# the right access info at TIEHANDLE time.
+
+       my $access = $self->_access();
+       my $mode   = $access eq 'rw' ? O_RDWR :
+               $access eq 'w' ? O_WRONLY : O_RDONLY;
+
+       $mode |= O_APPEND if $self->_append();
+
+       $mode |= O_TEXT   if not $self->_binmode();
+
+       return $self->_fileno ( OsfHandleOpenFd (
+               $self->win32_handle, $mode
+       ));
+}
+
+sub SEEK {
+       my ($self, $pos, $whence) = @_;
+
+       $whence = 0 if not defined $whence;
+       my @file_consts = map {
+               fileConstant($_)
+       } qw(FILE_BEGIN FILE_CURRENT FILE_END);
+
+       my $from_where = $file_consts[$whence];
+
+       return setFilePointer($self->win32_handle, $pos, $from_where);
+}
+
+sub TELL {
+# SetFilePointer with position 0 at FILE_CURRENT will return position.
+       return $_[0]->SEEK(0, 1);
+}
+
+sub EOF {
+       my $self = shift;
+
+       my $current = $self->TELL() + 0;
+       my $end     = getFileSize($self->win32_handle) + 0;
+
+       return $current == $end;
+}
+
+sub CLOSE {
+       my $self = shift;
+
+       my $retval = 1;
+       
+       if (defined $self->win32_handle) {
+               $retval = CloseHandle($self->win32_handle);
+
+               $self->win32_handle(undef);
+       }
+
+       return $retval;
+}
+
+# Only close the handle on explicit close, too many problems otherwise.
+sub UNTIE {}
+
+sub DESTROY {}
+
+# End of Tie/OO Interface
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+
+=head1 NAME
+
+Win32API::File - Low-level access to Win32 system API calls for files/dirs.
+
+=head1 SYNOPSIS
+
+  use Win32API::File 0.08 qw( :ALL );
+
+  MoveFile( $Source, $Destination )
+    or  die "Can't move $Source to $Destination: ",fileLastError(),"\n";
+  MoveFileEx( $Source, $Destination, MOVEFILE_REPLACE_EXISTING() )
+    or  die "Can't move $Source to $Destination: ",fileLastError(),"\n";
+  [...]
+
+=head1 DESCRIPTION
+
+This provides fairly low-level access to the Win32 System API
+calls dealing with files and directories.
+
+To pass in C<NULL> as the pointer to an optional buffer, pass in
+an empty list reference, C<[]>.
+
+Beyond raw access to the API calls and related constants, this module
+handles smart buffer allocation and translation of return codes.
+
+All functions, unless otherwise noted, return a true value for success
+and a false value for failure and set C<$^E> on failure.
+
+=head2 Object Oriented/Tied Handle Interface
+
+WARNING: this is new code, use at your own risk.
+
+This version of C<Win32API::File> can be used like an C<IO::File> object:
+
+  my $file = new Win32API::File "+> foo";
+  binmode $file;
+  print $file "hello there\n";
+  seek $file, 0, 0;
+  my $line = <$file>;
+  $file->close;
+
+It also supports tying via a win32 handle (for example, from C<createFile()>):
+
+  tie FILE, 'Win32API::File', $win32_handle;
+  print FILE "...";
+
+It has not been extensively tested yet and buffered I/O is not yet implemented.
+
+=head2 Exports
+
+Nothing is exported by default.  The following tags can be used to
+have large sets of symbols exported:  C<":Func">, C<":FuncA">,
+C<":FuncW">, C<":Misc">, C<":DDD_">, C<":DRIVE_">, C<":FILE_">,
+C<":FILE_ATTRIBUTE_">, C<":FILE_FLAG_">, C<":FILE_SHARE_">,
+C<":FILE_TYPE_">, C<":FS_">, C<":FSCTL_">, C<":HANDLE_FLAG_">,
+C<":IOCTL_STORAGE_">, C<":IOCTL_DISK_">, C<":GENERIC_">,
+C<":MEDIA_TYPE">, C<":MOVEFILE_">, C<":SECURITY_">, C<":SEM_">,
+and C<":PARTITION_">.
+
+=over
+
+=item C<":Func">
+
+The basic function names:  C<attrLetsToBits>,         C<createFile>,
+C<fileConstant>,           C<fileLastError>,          C<getLogicalDrives>,
+C<setFilePointer>,         C<getFileSize>,
+C<CloseHandle>,            C<CopyFile>,               C<CreateFile>,
+C<DefineDosDevice>,        C<DeleteFile>,             C<DeviceIoControl>,
+C<FdGetOsFHandle>,         C<GetDriveType>,           C<GetFileAttributes>,
+C<GetFileSize>,            C<GetFileType>,            C<GetHandleInformation>,
+C<GetLogicalDrives>,       C<GetLogicalDriveStrings>, C<GetOsFHandle>,
+C<GetOverlappedResult>,    C<GetVolumeInformation>,   C<IsContainerPartition>,
+C<IsRecognizedPartition>,  C<MoveFile>,               C<MoveFileEx>,
+C<OsFHandleOpen>,          C<OsFHandleOpenFd>,        C<QueryDosDevice>,
+C<ReadFile>,               C<SetErrorMode>,           C<SetFilePointer>,
+C<SetHandleInformation>,   and C<WriteFile>.
+
+=over
+
+=item attrLetsToBits
+
+=item C<$uBits= attrLetsToBits( $sAttributeLetters )>
+
+Converts a string of file attribute letters into an unsigned value with
+the corresponding bits set.  C<$sAttributeLetters> should contain zero
+or more letters from C<"achorst">:
+
+=over
+
+=item C<"a">
+
+C<FILE_ATTRIBUTE_ARCHIVE>
+
+=item C<"c">
+
+C<FILE_ATTRIBUTE_COMPRESSED>
+
+=item C<"h">
+
+C<FILE_ATTRIBUTE_HIDDEN>
+
+=item C<"o">
+
+C<FILE_ATTRIBUTE_OFFLINE>
+
+=item C<"r">
+
+C<FILE_ATTRIBUTE_READONLY>
+
+=item C<"s">
+
+C<FILE_ATTRIBUTE_SYSTEM>
+
+=item C<"t">
+
+C<FILE_ATTRIBUTE_TEMPORARY>
+
+=back
+
+=item createFile
+
+=item C<$hObject= createFile( $sPath )>
+
+=item C<$hObject= createFile( $sPath, $rvhvOptions )>
+
+=item C<$hObject= createFile( $sPath, $svAccess )>
+
+=item C<$hObject= createFile( $sPath, $svAccess, $rvhvOptions )>
+
+=item C<$hObject= createFile( $sPath, $svAccess, $svShare )>
+
+=item C<$hObject= createFile( $sPath, $svAccess, $svShare, $rvhvOptions )>
+
+This is a Perl-friendly wrapper around C<CreateFile>.
+
+On failure, C<$hObject> gets set to a false value and C<regLastError()>
+and C<$^E> are set to the reason for the failure.  Otherwise,
+C<$hObject> gets set to a Win32 native file handle which is alwasy
+a true value [returns C<"0 but true"> in the impossible(?) case of
+the handle having a value of C<0>].
+
+C<$sPath> is the path to the file [or device, etc.] to be opened.  See
+C<CreateFile> for more information on possible special values for
+C<$sPath>.  
+
+C<$svAccess> can be a number containing the bit mask representing
+the specific type(s) of access to the file that you desire.  See the
+C<$uAccess> parameter to C<CreateFile> for more information on these
+values.
+
+More likely, C<$svAccess> is a string describing the generic type of
+access you desire and possibly the file creation options to use.  In
+this case, C<$svAccess> should contain zero or more characters from
+C<"qrw"> [access desired], zero or one character each from C<"ktn">
+and C<"ce">, and optional white space.  These letters stand for,
+respectively, "Query access", "Read access", "Write access", "Keep if
+exists", "Truncate if exists", "New file only", "Create if none", and
+"Existing file only".  Case is ignored.
+
+You can pass in C<"?"> for C<$svAccess> to have an error message
+displayed summarizing its possible values.  This is very handy when
+doing on-the-fly programming using the Perl debugger:
+
+    Win32API::File::createFile:  $svAccess can use the following:
+       One or more of the following:
+           q -- Query access (same as 0)
+           r -- Read access (GENERIC_READ)
+           w -- Write access (GENERIC_WRITE)
+       At most one of the following:
+           k -- Keep if exists
+           t -- Truncate if exists
+           n -- New file only (fail if file already exists)
+       At most one of the following:
+           c -- Create if doesn't exist
+           e -- Existing file only (fail if doesn't exist)
+      ''   is the same as 'q  k e'
+      'r'  is the same as 'r  k e'
+      'w'  is the same as 'w  t c'
+      'rw' is the same as 'rw k c'
+      'rt' or 'rn' implies 'c'.
+      Or $access can be numeric.
+
+C<$svAccess> is designed to be "do what I mean", so you can skip
+the rest of its explanation unless you are interested in the complex
+details.  Note that, if you want write access to a device, you need
+to specify C<"k"> [and perhaps C<"e">, as in C<"w ke"> or C<"rw ke">]
+since Win32 suggests C<OPEN_EXISTING> be used when opening a device.
+
+=over
+
+=item C<"q"> 
+
+Stands for "Query access".  This is really a no-op since you always have
+query access when you open a file.  You can specify C<"q"> to document
+that you plan to query the file [or device, etc.].  This is especially
+helpful when you don't want read nor write access since something like
+C<"q"> or C<"q ke"> may be easier to understand than just C<""> or C<"ke">.
+
+=item C<"r">
+
+Stands for "Read access".  Sets the C<GENERIC_READ> bit(s) in the
+C<$uAccess> that is passed to C<CreateFile>.  This is the default
+access if the C<$svAccess> parameter is missing [or if it is C<undef>
+and C<$rvhvOptions> doesn't specify an C<"Access"> option].
+
+=item C<"w">
+
+Stands for "Write access".  Sets the C<GENERIC_WRITE> bit(s) in the
+C<$uAccess> that is passed to C<CreateFile>.
+
+=item C<"k">
+
+Stands for "Keep if exists".  If the requested file exists, then it is
+opened.  This is the default unless C<GENERIC_WRITE> access has been
+requested but C<GENERIC_READ> access has not been requested.   Contrast
+with C<"t"> and C<"n">.
+
+=item C<"t">
+
+Stands for "Truncate if exists".  If the requested file exists, then
+it is truncated to zero length and then opened.  This is the default if
+C<GENERIC_WRITE> access has been requested and C<GENERIC_READ> access
+has not been requested.  Contrast with C<"k"> and C<"n">.
+
+=item C<"n">
+
+Stands for "New file only".  If the requested file exists, then it is
+not opened and the C<createFile> call fails.  Contrast with C<"k"> and
+C<"t">.  Can't be used with C<"e">.
+
+=item C<"c">
+
+Stands for "Create if none".  If the requested file does not
+exist, then it is created and then opened.  This is the default
+if C<GENERIC_WRITE> access has been requested or if C<"t"> or
+C<"n"> was specified.  Contrast with C<"e">.
+
+=item C<"e">
+
+Stands for "Existing file only".  If the requested file does not
+exist, then nothing is opened and the C<createFile> call fails.  This
+is the default unless C<GENERIC_WRITE> access has been requested or
+C<"t"> or C<"n"> was specified.   Contrast with C<"c">.   Can't be
+used with C<"n">.
+
+=back
+
+The characters from C<"ktn"> and C<"ce"> are combined to determine the
+what value for C<$uCreate> to pass to C<CreateFile> [unless overridden
+by C<$rvhvOptions>]:
+
+=over
+
+=item C<"kc">
+
+C<OPEN_ALWAYS>
+
+=item C<"ke">
+
+C<OPEN_EXISTING>
+
+=item C<"tc">
+
+C<TRUNCATE_EXISTING>
+
+=item C<"te">
+
+C<CREATE_ALWAYS>
+
+=item C<"nc">
+
+C<CREATE_NEW>
+
+=item C<"ne">
+
+Illegal.
+
+=back
+
+C<$svShare> controls how the file is shared, that is, whether other
+processes can have read, write, and/or delete access to the file while
+we have it opened.  C<$svShare> will usually be a string containing zero
+or more characters from C<"rwd"> but can also be a numeric bit mask.
+
+C<"r"> sets the C<FILE_SHARE_READ> bit which allows other processes to have
+read access to the file.  C<"w"> sets the C<FILE_SHARE_WRITE> bit which
+allows other processes to have write access to the file.  C<"d"> sets the
+C<FILE_SHARE_DELETE> bit which allows other processes to have delete access
+to the file [ignored under Windows 95].
+
+The default for C<$svShare> is C<"rw"> which provides the same sharing as
+using regular perl C<open()>.
+
+If another process currently has read, write, and/or delete access to
+the file and you don't allow that level of sharing, then your call to
+C<createFile> will fail.  If you requested read, write, and/or delete
+access and another process already has the file open but doesn't allow
+that level of sharing, then your call to C<createFile> will fail.  Once
+you have the file open, if another process tries to open it with read,
+write, and/or delete access and you don't allow that level of sharing,
+then that process won't be allowed to open the file.
+
+C<$rvhvOptions> is a reference to a hash where any keys must be from
+the list C<qw( Access Create Share Attributes Flags Security Model )>.
+The meaning of the value depends on the key name, as described below.
+Any option values in C<$rvhvOptions> override the settings from
+C<$svAccess> and C<$svShare> if they conflict.
+
+=over
+
+=item Flags => $uFlags
+
+C<$uFlags> is an unsigned value having any of the C<FILE_FLAG_*> or
+C<FILE_ATTRIBUTE_*> bits set.  Any C<FILE_ATTRIBUTE_*> bits set via the
+C<Attributes> option are logically C<or>ed with these bits.  Defaults
+to C<0>.
+
+If opening the client side of a named pipe, then you can also specify
+C<SECURITY_SQOS_PRESENT> along with one of the other C<SECURITY_*>
+constants to specify the security quality of service to be used.
+
+=item Attributes => $sAttributes
+
+A string of zero or more characters from C<"achorst"> [see C<attrLetsToBits>
+for more information] which are converted to C<FILE_ATTRIBUTE_*> bits to
+be set in the C<$uFlags> argument passed to C<CreateFile>.
+
+=item Security => $pSecurityAttributes
+
+C<$pSecurityAttributes> should contain a C<SECURITY_ATTRIBUTES> structure
+packed into a string or C<[]> [the default].
+
+=item Model => $hModelFile
+
+C<$hModelFile> should contain a handle opened with C<GENERIC_READ>
+access to a model file from which file attributes and extended attributes
+are to be copied.  Or C<$hModelFile> can be C<0> [the default].
+
+=item Access => $sAccess
+
+=item Access => $uAccess
+
+C<$sAccess> should be a string of zero or more characters from
+C<"qrw"> specifying the type of access desired:  "query" or C<0>,
+"read" or C<GENERIC_READ> [the default], or "write" or
+C<GENERIC_WRITE>.
+
+C<$uAccess> should be an unsigned value containing bits set to
+indicate the type of access desired.  C<GENERIC_READ> is the default.
+
+=item Create => $sCreate
+
+=item Create => $uCreate
+
+C<$sCreate> should be a string constaing zero or one character from
+C<"ktn"> and zero or one character from C<"ce">.  These stand for
+"Keep if exists", "Truncate if exists", "New file only", "Create if
+none", and "Existing file only".  These are translated into a
+C<$uCreate> value.
+
+C<$uCreate> should be one of C<OPEN_ALWAYS>, C<OPEN_EXISTING>,
+C<TRUNCATE_EXISTING>, C<CREATE_ALWAYS>, or C<CREATE_NEW>.
+
+=item Share => $sShare
+
+=item Share => $uShare
+
+C<$sShare> should be a string with zero or more characters from
+C<"rwd"> that is translated into a C<$uShare> value.  C<"rw"> is
+the default.
+
+C<$uShare> should be an unsigned value having zero or more of the
+following bits set:  C<FILE_SHARE_READ>, C<FILE_SHARE_WRITE>, and
+C<FILE_SHARE_DELETE>.  C<FILE_SHARE_READ|FILE_SHARE_WRITE> is the
+default.
+
+=back
+
+Examples:
+
+    $hFlop= createFile( "//./A:", "r", "r" )
+      or  die "Can't prevent others from writing to floppy: $^E\n";
+    $hDisk= createFile( "//./C:", "rw ke", "" )
+      or  die "Can't get exclusive access to C: $^E\n";
+    $hDisk= createFile( $sFilePath, "ke",
+      { Access=>FILE_READ_ATTRIBUTES } )
+      or  die "Can't read attributes of $sFilePath: $^E\n";
+    $hTemp= createFile( "$ENV{Temp}/temp.$$", "wn", "",
+      { Attributes=>"hst", Flags=>FILE_FLAG_DELETE_ON_CLOSE() } )
+      or  die "Can't create temporary file, temp.$$: $^E\n";
+
+=item getLogicalDrives
+
+=item C<@roots= getLogicalDrives()>
+
+Returns the paths to the root directories of all logical drives
+currently defined.  This includes all types of drive lettters, such
+as floppies, CD-ROMs, hard disks, and network shares.  A typical
+return value on a poorly equipped computer would be C<("A:\\","C:\\")>.
+
+=item CloseHandle
+
+=item C<CloseHandle( $hObject )>
+
+Closes a Win32 native handle, such as one opened via C<CreateFile>. 
+Like most routines, returns a true value if successful and a false
+value [and sets C<$^E> and C<regLastError()>] on failure.
+
+=item CopyFile
+
+=item C<CopyFile( $sOldFileName, $sNewFileName, $bFailIfExists )>
+
+C<$sOldFileName> is the path to the file to be copied. 
+C<$sNewFileName> is the path to where the file should be copied. 
+Note that you can B<NOT> just specify a path to a directory in
+C<$sNewFileName> to copy the file to that directory using the
+same file name.
+
+If C<$bFailIfExists> is true and C<$sNewFileName> is the path to
+a file that already exists, then C<CopyFile> will fail.  If
+C<$bFailIfExists> is falsea, then the copy of the C<$sOldFileNmae>
+file will overwrite the C<$sNewFileName> file if it already exists.
+
+Like most routines, returns a true value if successful and a false
+value [and sets C<$^E> and C<regLastError()>] on failure.
+
+=item CreateFile
+
+=item C<$hObject= CreateFile( $sPath, $uAccess, $uShare, $pSecAttr, $uCreate, $uFlags, $hModel )>
+
+On failure, C<$hObject> gets set to a false value and C<$^E> and
+C<fileLastError()> are set to the reason for the failure.  Otherwise,
+C<$hObject> gets set to a Win32 native file handle which is always a
+true value [returns C<"0 but true"> in the impossible(?) case of the
+handle having a value of C<0>].
+
+C<$sPath> is the path to the file [or device, etc.] to be opened.
+
+C<$sPath> can use C<"/"> or C<"\\"> as path delimiters and can even
+mix the two.  We will usually only use C<"/"> in our examples since
+using C<"\\"> is usually harder to read.
+
+Under Windows NT, C<$sPath> can start with C<"//?/"> to allow the use
+of paths longer than C<MAX_PATH> [for UNC paths, replace the leading
+C<"//"> with C<"//?/UNC/">, as in C<"//?/UNC/Server/Share/Dir/File.Ext">].
+
+C<$sPath> can start with C<"//./"> to indicate that the rest of the
+path is the name of a "DOS device."  You can use C<QueryDosDevice>
+to list all current DOS devices and can add or delete them with
+C<DefineDosDevice>.  If you get the source-code distribution of this
+module from CPAN, then it includes an example script, F<ex/ListDevs.plx>
+that will list all current DOS devices and their "native" definition.
+Again, note that this doesn't work under Win95 nor Win98.
+
+The most common such DOS devices include:
+
+=over
+
+=item C<"//./PhysicalDrive0">
+
+Your entire first hard disk.  Doesn't work under Windows 95.  This
+allows you to read or write raw sectors of your hard disk and to use
+C<DeviceIoControl> to perform miscellaneous queries and operations
+to the hard disk.   Writing raw sectors and certain other operations
+can seriously damage your files or the function of your computer.
+
+Locking this for exclusive access [by specifying C<0> for C<$uShare>]
+doesn't prevent access to the partitions on the disk nor their file
+systems.  So other processes can still access any raw sectors within
+a partition and can use the file system on the disk as usual.
+
+=item C<"//./C:">
+
+Your F<C:> partition.  Doesn't work under Windows 95.  This allows
+you to read or write raw sectors of that partition and to use
+C<DeviceIoControl> to perform miscellaneous queries and operations
+to the partition.  Writing raw sectors and certain other operations
+can seriously damage your files or the function of your computer.
+
+Locking this for exclusive access doesn't prevent access to the
+physical drive that the partition is on so other processes can
+still access the raw sectors that way.  Locking this for exclusive
+access B<does> prevent other processes from opening the same raw
+partition and B<does> prevent access to the file system on it.  It
+even prevents the current process from accessing the file system
+on that partition.
+
+=item C<"//./A:">
+
+The raw floppy disk.  Doesn't work under Windows 95.  This allows
+you to read or write raw sectors of the floppy disk and to use
+C<DeviceIoControl> to perform miscellaneous queries and operations
+to the floopy disk or drive.
+
+Locking this for exclusive access prevents all access to the floppy.
+
+=item C<"//./PIPE/PipeName">
+
+A named pipe, created via C<CreateNamedPipe>.
+
+=back
+
+C<$uAccess> is an unsigned value with bits set indicating the
+type of access desired.  Usually either C<0> ["query" access],
+C<GENERIC_READ>, C<GENERIC_WRITE>, C<GENERIC_READ|GENERIC_WRITE>,
+or C<GENERIC_ALL>.  More specific types of access can be specified,
+such as C<FILE_APPEND_DATA> or C<FILE_READ_EA>.
+
+C<$uShare> controls how the file is shared, that is, whether other
+processes can have read, write, and/or delete access to the file while
+we have it opened.  C<$uShare> is an unsigned value with zero or more
+of these bits set:  C<FILE_SHARE_READ>, C<FILE_SHARE_WRITE>, and
+C<FILE_SHARE_DELETE>.
+
+If another process currently has read, write, and/or delete access to
+the file and you don't allow that level of sharing, then your call to
+C<CreateFile> will fail.  If you requested read, write, and/or delete
+access and another process already has the file open but doesn't allow
+that level of sharing, thenn your call to C<createFile> will fail.  Once
+you have the file open, if another process tries to open it with read,
+write, and/or delete access and you don't allow that level of sharing,
+then that process won't be allowed to open the file.
+
+C<$pSecAttr> should either be C<[]> [for C<NULL>] or a
+C<SECURITY_ATTRIBUTES> data structure packed into a string.
+For example, if C<$pSecDesc> contains a C<SECURITY_DESCRIPTOR>
+structure packed into a string, perhaps via:
+
+    RegGetKeySecurity( $key, 4, $pSecDesc, 1024 );
+
+then you can set C<$pSecAttr> via:
+
+    $pSecAttr= pack( "L P i", 12, $pSecDesc, $bInheritHandle );
+
+C<$uCreate> is one of the following values:  C<OPEN_ALWAYS>,
+C<OPEN_EXISTING>, C<TRUNCATE_EXISTING>, C<CREATE_ALWAYS>, and
+C<CREATE_NEW>.
+
+C<$uFlags> is an unsigned value with zero or more bits set indicating
+attributes to associate with the file [C<FILE_ATTRIBUTE_*> values] or
+special options [C<FILE_FLAG_*> values].
+
+If opening the client side of a named pipe, then you can also set
+C<$uFlags> to include C<SECURITY_SQOS_PRESENT> along with one of the
+other C<SECURITY_*> constants to specify the security quality of
+service to be used.
+
+C<$hModel> is C<0> [or C<[]>, both of which mean C<NULL>] or a Win32
+native handle opened with C<GENERIC_READ> access to a model file from
+which file attributes and extended attributes are to be copied if a
+new file gets created.
+
+Examples:
+
+    $hFlop= CreateFile( "//./A:", GENERIC_READ(),
+      FILE_SHARE_READ(), [], OPEN_EXISTING(), 0, [] )
+      or  die "Can't prevent others from writing to floppy: $^E\n";
+    $hDisk= createFile( $sFilePath, FILE_READ_ATTRIBUTES(),
+      FILE_SHARE_READ()|FILE_SHARE_WRITE(), [], OPEN_EXISTING(), 0, [] )
+      or  die "Can't read attributes of $sFilePath: $^E\n";
+    $hTemp= createFile( "$ENV{Temp}/temp.$$", GENERIC_WRITE(), 0,
+      CREATE_NEW(), FILE_FLAG_DELETE_ON_CLOSE()|attrLetsToBits("hst"), [] )
+      or  die "Can't create temporary file, temp.$$: $^E\n";
+
+=item DefineDosDevice
+
+=item C<DefineDosDevice( $uFlags, $sDosDeviceName, $sTargetPath )>
+
+Defines a new DOS device, overrides the current definition of a DOS
+device, or deletes a definition of a DOS device.  Like most routines,
+returns a true value if successful and a false value [and sets C<$^E>
+and C<regLastError()>] on failure.
+
+C<$sDosDeviceName> is the name of a DOS device for which we'd like
+to add or delete a definition.
+
+C<$uFlags> is an unsigned value with zero or more of the following
+bits set:
+
+=over
+
+=item C<DDD_RAW_TARGET_PATH>
+
+Indicates that C<$sTargetPath> will be a raw Windows NT object name. 
+This usually means that C<$sTargetPath> starts with C<"\\Device\\">. 
+Note that you cannot use C<"/"> in place of C<"\\"> in raw target path
+names.
+
+=item C<DDD_REMOVE_DEFINITION>
+
+Requests that a definition be deleted.  If C<$sTargetPath> is
+C<[]> [for C<NULL>], then the most recently added definition for
+C<$sDosDeviceName> is removed.  Otherwise the most recently added
+definition matching C<$sTargetPath> is removed.
+
+If the last definition is removed, then the DOS device name is
+also deleted.
+
+=item C<DDD_EXACT_MATCH_ON_REMOVE>
+
+When deleting a definition, this bit causes each C<$sTargetPath> to
+be compared to the full-length definition when searching for the most
+recently added match.  If this bit is not set, then C<$sTargetPath>
+only needs to match a prefix of the definition.
+
+=back
+
+C<$sTargetPath> is the DOS device's specific definition that you
+wish to add or delete.  For C<DDD_RAW_TARGET_PATH>, these usually
+start with C<"\\Device\\">.  If the C<DDD_RAW_TARGET_PATH> bit is
+not set, then C<$sTargetPath> is just an ordinary path to some file
+or directory, providing the functionality of the B<subst> command.
+
+=item DeleteFile
+
+=item C<DeleteFile( $sFileName )>
+
+Deletes the named file.  Compared to Perl's C<unlink>, C<DeleteFile>
+has the advantage of not deleting read-only files.  For B<some>
+versions of Perl, C<unlink> silently calls C<chmod> whether it needs
+to or not before deleting the file so that files that you have
+protected by marking them as read-only are not always protected from
+Perl's C<unlink>.
+
+Like most routines, returns a true value if successful and a false
+value [and sets C<$^E> and C<regLastError()>] on failure.
+
+=item DeviceIoControl
+
+=item C<DeviceIoControl( $hDevice, $uIoControlCode, $pInBuf, $lInBuf, $opOutBuf, $lOutBuf, $olRetBytes, $pOverlapped )>
+
+Requests a special operation on an I/O [input/output] device, such
+as ejecting a tape or formatting a disk.  Like most routines, returns
+a true value if successful and a false value [and sets C<$^E> and
+C<regLastError()>] on failure.
+
+C<$hDevice> is a Win32 native file handle to a device [return value
+from C<CreateFile>].
+
+C<$uIoControlCode> is an unsigned value [a C<IOCTL_*> or C<FSCTL_*>
+constant] indicating the type query or other operation to be performed.
+
+C<$pInBuf> is C<[]> [for C<NULL>] or a data structure packed into a
+string.  The type of data structure depends on the C<$uIoControlCode>
+value.  C<$lInBuf> is C<0> or the length of the structure in
+C<$pInBuf>.  If C<$pInBuf> is not C<[]> and C<$lInBuf> is C<0>, then
+C<$lInBuf> will automatically be set to C<length($pInBuf)> for you.
+
+C<$opOutBuf> is C<[]> [for C<NULL>] or will be set to contain a
+returned data structure packed into a string.  C<$lOutBuf> indicates
+how much space to allocate in C<$opOutBuf> for C<DeviceIoControl> to
+store the data structure.  If C<$lOutBuf> is a number and C<$opOutBuf>
+already has a buffer allocated for it that is larger than C<$lOutBuf>
+bytes, then this larger buffer size will be passed to C<DeviceIoControl>.
+However, you can force a specific buffer size to be passed to
+C<DeviceIoControl> by prepending a C<"="> to the front of C<$lOutBuf>.
+
+C<$olRetBytes> is C<[]> or is a scalar to receive the number of bytes
+written to C<$opOutBuf>.  Even when C<$olRetBytes> is C<[]>, a valid
+pointer to a C<DWORD> [and not C<NULL>] is passed to C<DeviceIoControl>.
+In this case, C<[]> just means that you don't care about the value
+that might be written to C<$olRetBytes>, which is usually the case
+since you can usually use C<length($opOutBuf)> instead.
+
+C<$pOverlapped> is C<[]> or is a C<OVERLAPPED> structure packed into
+a string.  This is only useful if C<$hDevice> was opened with the
+C<FILE_FLAG_OVERLAPPED> flag set.
+
+=item FdGetOsFHandle
+
+=item C<$hNativeHandle= FdGetOsFHandle( $ivFd )>
+
+C<FdGetOsFHandle> simply calls C<_get_osfhandle()>.  It was renamed
+to better fit in with the rest the function names of this module,
+in particular to distinguish it from C<GetOsFHandle>.  It takes an
+integer file descriptor [as from Perl's C<fileno>] and returns the
+Win32 native file handle associated with that file descriptor or
+C<INVALID_HANDLE_VALUE> if C<$ivFd> is not an open file descriptor.
+
+When you call Perl's C<open> to set a Perl file handle [like C<STDOUT>],
+Perl calls C's C<fopen> to set a stdio C<FILE *>.  C's C<fopen> calls
+something like Unix's C<open>, that is, Win32's C<_sopen>, to get an
+integer file descriptor [where 0 is for C<STDIN>, 1 for C<STDOUT>, etc.].
+Win32's C<_sopen> calls C<CreateFile> to set a C<HANDLE>, a Win32 native
+file handle.  So every Perl file handle [like C<STDOUT>] has an integer
+file descriptor associated with it that you can get via C<fileno>.  And,
+under Win32, every file descriptor has a Win32 native file handle
+associated with it.  C<FdGetOsFHandle> lets you get access to that.
+
+C<$hNativeHandle> is set to C<INVALID_HANDLE_VALUE> [and
+C<lastFileError()> and C<$^E> are set] if C<FdGetOsFHandle> fails. 
+See also C<GetOsFHandle> which provides a friendlier interface.
+
+=item fileConstant
+
+=item C<$value= fileConstant( $sConstantName )>
+
+Fetch the value of a constant.  Returns C<undef> if C<$sConstantName>
+is not the name of a constant supported by this module.  Never sets
+C<$!> nor C<$^E>.
+
+This function is rarely used since you will usually get the value of a
+constant by having that constant imported into your package by listing
+the constant name in the C<use Win32API::File> statement and then
+simply using the constant name in your code [perhaps followed by
+C<()>].  This function is useful for verifying constant names not in
+Perl code, for example, after prompting a user to type in a constant
+name.
+
+=item fileLastError
+
+=item C<$svError= fileLastError();>
+
+=item C<fileLastError( $uError );>
+
+Returns the last error encountered by a routine from this module. 
+It is just like C<$^E> except it isn't changed by anything except
+routines from this module.  Ideally you could just use C<$^E>, but
+current versions of Perl often overwrite C<$^E> before you get a
+chance to check it and really old versions of Perl don't really
+support C<$^E> under Win32.
+
+Just like C<$^E>, in a numeric context C<fileLastError()> returns
+the numeric error value while in a string context it returns a
+text description of the error [actually it returns a Perl scalar
+that contains both values so C<$x= fileLastError()> causes C<$x>
+to give different values in string vs. numeric contexts].
+
+The last form sets the error returned by future calls to
+C<fileLastError()> and should not be used often.  C<$uError> must
+be a numeric error code.  Also returns the dual-valued version
+of C<$uError>.
+
+=item GetDriveType
+
+=item C<$uDriveType= GetDriveType( $sRootPath )>
+
+Takes a string giving the path to the root directory of a file system
+[called a "drive" because every file system is assigned a "drive letter"]
+and returns an unsigned value indicating the type of drive the file
+system is on.  The return value should be one of:
+
+=over
+
+=item C<DRIVE_UNKNOWN>
+
+None of the following.
+
+=item C<DRIVE_NO_ROOT_DIR>
+
+A "drive" that does not have a file system.  This can be a drive letter
+that hasn't been defined or a drive letter assigned to a partition
+that hasn't been formatted yet.
+
+=item C<DRIVE_REMOVABLE>
+
+A floppy diskette drive or other removable media drive, but not a CD-ROM
+drive.
+
+=item C<DRIVE_FIXED>
+
+An ordinary hard disk partition.
+
+=item C<DRIVE_REMOTE>
+
+A network share.
+
+=item C<DRIVE_CDROM>
+
+A CD-ROM drive.
+
+=item C<DRIVE_RAMDISK>
+
+A "ram disk" or memory-resident virtual file system used for high-speed
+access to small amounts of temporary file space.
+
+=back
+
+=item GetFileAttributes
+
+=item C<$uAttrs = GetFileAttributes( $sPath )>
+
+Takes a path string and returns an unsigned value with attribute flags.
+If it fails, it returns INVALID_FILE_ATTRIBUTES, otherwise it can be
+one or more of the following values:
+
+=over
+
+=item C<FILE_ATTRIBUTE_ARCHIVE>
+
+The file or directory is an archive file or directory. Applications use
+this attribute to mark files for backup or removal.
+
+=item C<FILE_ATTRIBUTE_COMPRESSED>
+
+The file or directory is compressed. For a file, this means that all of
+the data in the file is compressed. For a directory, this means that
+compression is the default for newly created files and subdirectories. 
+
+=item C<FILE_ATTRIBUTE_DEVICE>
+
+Reserved; do not use. 
+
+=item C<FILE_ATTRIBUTE_DIRECTORY>
+
+The handle identifies a directory. 
+
+=item C<FILE_ATTRIBUTE_ENCRYPTED>
+
+The file or directory is encrypted. For a file, this means that all data
+streams in the file are encrypted. For a directory, this means that
+encryption is the default for newly created files and subdirectories. 
+
+=item C<FILE_ATTRIBUTE_HIDDEN>
+
+The file or directory is hidden. It is not included in an ordinary directory
+listing. 
+
+=item C<FILE_ATTRIBUTE_NORMAL>
+
+The file or directory has no other attributes set. This attribute is valid
+only if used alone. 
+
+=item C<FILE_ATTRIBUTE_NOT_CONTENT_INDEXED>
+
+The file will not be indexed by the content indexing service. 
+
+=item C<FILE_ATTRIBUTE_OFFLINE>
+
+The data of the file is not immediately available. This attribute indicates
+that the file data has been physically moved to offline storage. This
+attribute is used by Remote Storage, the hierarchical storage management
+software. Applications should not arbitrarily change this attribute. 
+
+=item C<FILE_ATTRIBUTE_READONLY>
+
+The file or directory is read-only. Applications can read the file but cannot
+write to it or delete it. In the case of a directory, applications cannot
+delete it. 
+
+=item C<FILE_ATTRIBUTE_REPARSE_POINT>
+
+The file or directory has an associated reparse point. 
+
+=item C<FILE_ATTRIBUTE_SPARSE_FILE>
+
+The file is a sparse file. 
+
+=item C<FILE_ATTRIBUTE_SYSTEM>
+
+The file or directory is part of, or is used exclusively by, the operating
+system. 
+
+=item C<FILE_ATTRIBUTE_TEMPORARY>
+
+The file is being used for temporary storage. File systems avoid writing
+data back to mass storage if sufficient cache memory is available, because
+often the application deletes the temporary file shortly after the handle is
+closed. In that case, the system can entirely avoid writing the data.
+Otherwise, the data will be written after the handle is closed. 
+
+=back
+
+=item GetFileType
+
+=item C<$uFileType= GetFileType( $hFile )>
+
+Takes a Win32 native file handle and returns a C<FILE_TYPE_*> constant
+indicating the type of the file opened on that handle:
+
+=over
+
+=item C<FILE_TYPE_UNKNOWN>
+
+None of the below.  Often a special device.
+
+=item C<FILE_TYPE_DISK>
+
+An ordinary disk file.
+
+=item C<FILE_TYPE_CHAR>
+
+What Unix would call a "character special file", that is, a device that
+works on character streams such as a printer port or a console.
+
+=item C<FILE_TYPE_PIPE>
+
+Either a named or anonymous pipe.
+
+=back
+
+=item getFileSize
+
+=item C<$size= getFileSize( $hFile )>
+
+This is a Perl-friendly wrapper for the C<GetFileSize> (below) API call.
+
+It takes a Win32 native file handle and returns the size in bytes. Since the
+size can be a 64 bit value, on non 64 bit integer Perls the value returned will
+be an object of type C<Math::BigInt>.
+
+=item GetFileSize
+
+=item C<$iSizeLow= GetFileSize($win32Handle, $iSizeHigh)>
+
+Returns the size of a file pointed to by C<$win32Handle>, optionally storing
+the high order 32 bits into C<$iSizeHigh> if it is not C<[]>. If $iSizeHigh is
+C<[]>, a non-zero value indicates success. Otherwise, on failure the return
+value will be C<0xffffffff> and C<fileLastError()> will not be C<NO_ERROR>.
+
+=item GetOverlappedResult
+
+=item C<$bRetval= GetOverlappedResult( $win32Handle, $pOverlapped,
+ $numBytesTransferred, $bWait )>
+
+Used for asynchronous IO in Win32 to get the result of a pending IO operation,
+such as when a file operation returns C<ERROR_IO_PENDING>. Returns a false
+value on failure. The C<$overlapped> structure and C<$numBytesTransferred>
+will be modified with the results of the operation.
+
+As far as creating the C<$pOverlapped> structure, you are currently on your own.
+
+See L<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getoverlappedresult.asp> for more information.
+
+=item GetLogicalDrives
+
+=item C<$uDriveBits= GetLogicalDrives()>
+
+Returns an unsigned value with one bit set for each drive letter currently
+defined.  If "A:" is currently a valid drive letter, then the C<1> bit
+will be set in C<$uDriveBits>.  If "B:" is valid, then the C<2> bit will
+be set.  If "Z:" is valid, then the C<2**26> [C<0x4000000>] bit will be
+set.
+
+=item GetLogicalDriveStrings
+
+=item C<$olOutLength= GetLogicalDriveStrings( $lBufSize, $osBuffer )>
+
+For each currently defined drive letter, a C<'\0'>-terminated string
+of the path to the root of its file system is constructed.  All of
+these strings are concatenated into a single larger string and an
+extra terminating C<'\0'> is added.  This larger string is returned
+in C<$osBuffer>.  Note that this includes drive letters that have
+been defined but that have no file system, such as drive letters
+assigned to unformatted partitions.
+
+C<$lBufSize> is the size of the buffer to allocate to store this
+list of strings.  C<26*4+1> is always sufficient and should usually
+be used.
+
+C<$osBuffer> is a scalar to be set to contain the constructed string.
+
+C<$olOutLength> is the number of bytes actually written to C<$osBuffer>
+but C<length($osBuffer)> can also be used to determine this.
+
+For example, on a poorly equipped computer,
+
+    GetLogicalDriveStrings( 4*26+1, $osBuffer );
+
+might set C<$osBuffer> to the 9-character string, C<"A:\\\0C:\\\0\0">.
+
+=item GetHandleInformation
+
+=item C<GetHandleInformation( $hObject, $ouFlags )>
+
+Retrieves the flags associated with a Win32 native file handle or object
+handle.
+
+C<$hObject> is an open Win32 native file handle or an open Win32 native
+handle to some other type of object.
+
+C<$ouFlags> will be set to an unsigned value having zero or more of
+the bits C<HANDLE_FLAG_INHERIT> and C<HANDLE_FLAG_PROTECT_FROM_CLOSE>
+set.  See the C<":HANDLE_FLAG_"> export class for the meanings of these
+bits.
+
+=item GetOsFHandle
+
+=item C<$hNativeHandle= GetOsFHandle( FILE )>
+
+Takes a Perl file handle [like C<STDIN>] and returns the Win32 native
+file handle associated with it.  See C<FdGetOsFHandle> for more
+information about Win32 native file handles.
+
+C<$hNativeHandle> is set to a false value [and C<lastFileError()> and
+C<$^E> are set] if C<GetOsFHandle> fails.    C<GetOsFHandle> returns
+C<"0 but true"> in the impossible(?) case of the handle having a value
+of C<0>.
+
+=item GetVolumeInformation
+
+=item C<GetVolumeInformation( $sRootPath, $osVolName, $lVolName, $ouSerialNum, $ouMaxNameLen, $ouFsFlags, $osFsType, $lFsType )>
+
+Gets information about a file system volume, returning a true
+value if successful.  On failure, returns a false value and sets
+C<fileLastError()> and C<$^E>.
+
+C<$sRootPath> is a string specifying the path to the root of the file system,
+for example, C<"C:/">.
+
+C<$osVolName> is a scalar to be set to the string representing the
+volume name, also called the file system label.  C<$lVolName> is the
+number of bytes to allocate for the C<$osVolName> buffer [see
+L<Buffer Sizes> for more information].
+
+C<$ouSerialNum> is C<[]> [for C<NULL>] or will be set to the numeric
+value of the volume's serial number.
+
+C<$ouMaxNameLen> is C<[]> [for C<NULL>] or will be set to the maximum
+length allowed for a file name or directory name within the file system.
+
+C<$osFsType> is a scalar to be set to the string representing the
+file system type, such as C<"FAT"> or C<"NTFS">.  C<$lFsType> is the
+number of bytes to allocate for the C<$osFsType> buffer [see
+L<Buffer Sizes> for more information].
+
+C<$ouFsFlags> is C<[]> [for C<NULL>] or will be set to an unsigned integer
+with bits set indicating properties of the file system:
+
+=over
+
+=item C<FS_CASE_IS_PRESERVED>
+
+The file system preserves the case of file names [usually true].
+That is, it doesn't change the case of file names such as forcing
+them to upper- or lower-case.
+
+=item C<FS_CASE_SENSITIVE>
+
+The file system supports the ability to not ignore the case of file
+names [but might ignore case the way you are using it].  That is, the
+file system has the ability to force you to get the letter case of a
+file's name exactly right to be able to open it.  This is true for
+"NTFS" file systems, even though case in file names is usually still
+ignored.
+
+=item C<FS_UNICODE_STORED_ON_DISK>
+
+The file system preserves Unicode in file names [true for "NTFS"].
+
+=item C<FS_PERSISTENT_ACLS>
+
+The file system supports setting Access Control Lists on files [true
+for "NTFS"].
+
+=item C<FS_FILE_COMPRESSION>
+
+The file system supports compression on a per-file basis [true for
+"NTFS"].
+
+=item C<FS_VOL_IS_COMPRESSED>
+
+The entire file system is compressed such as via "DoubleSpace".
+
+=back
+
+=item IsRecognizedPartition
+
+=item C<IsRecognizedPartition( $ivPartitionType )>
+
+Takes a partition type and returns whether that partition type is
+supported under Win32.  C<$ivPartitonType> is an integer value as from
+the operating system byte of a hard disk's DOS-compatible partition
+table [that is, a partition table for x86-based Win32, not, for
+example, one used with Windows NT for Alpha processors].  For example,
+the C<PartitionType> member of the C<PARTITION_INFORMATION> structure.
+
+Common values for C<$ivPartitionType> include C<PARTITION_FAT_12==1>,
+C<PARTITION_FAT_16==4>, C<PARTITION_EXTENDED==5>, C<PARTITION_FAT32==0xB>.
+
+=item IsContainerPartition
+
+=item C<IsContainerPartition( $ivPartitionType )>
+
+Takes a partition type and returns whether that partition is a
+"container" partition that is supported under Win32, that is, whether
+it is an "extended" partition that can contain "logical" partitions. 
+C<$ivPartitonType> is as for C<IsRecognizedPartition>.
+
+=item MoveFile
+
+=item C<MoveFile( $sOldName, $sNewName )>
+
+Renames a file or directory.  C<$sOldName> is the name of the existing
+file or directory that is to be renamed.  C<$sNewName> is the new name
+to give the file or directory.  Returns a true value if the move
+succeeds.  For failure, returns a false value and sets
+C<fileLastErorr()> and C<$^E> to the reason for the failure.
+
+Files can be "renamed" between file systems and the file contents and
+some attributes will be moved.  Directories can only be renamed within
+one file system.  If there is already a file or directory named
+C<$sNewName>, then C<MoveFile> will fail.
+
+=item MoveFileEx
+
+=item C<MoveFileEx( $sOldName, $sNewName, $uFlags )>
+
+Renames a file or directory.  C<$sOldName> is the name of the existing
+file or directory that is to be renamed.  C<$sNewName> is the new name
+to give the file or directory.  Returns a true value if the move
+succeeds.  For failure, returns a false value and sets
+C<fileLastErorr()> and C<$^E> to the reason for the failure.
+
+C<$uFlags> is an unsigned value with zero or more of the following bits set:
+
+=over
+
+=item C<MOVEFILE_REPLACE_EXISTING>
+
+If this bit is set and a file [but not a directory] named C<$sNewName>
+already exists, then it will be replaced by C<$sOldName>.  If this bit
+is not set then C<MoveFileEx> will fail rather than replace an existing
+C<$sNewName>.
+
+=item C<MOVEFILE_COPY_ALLOWED>
+
+Allows files [but not directories] to be moved between file systems
+by copying the C<$sOldName> file data and some attributes to
+C<$sNewName> and then deleting C<$sOldName>.  If this bit is not set
+[or if C<$sOldName> denotes a directory] and C<$sNewName> refers to a
+different file system than C<$sOldName>, then C<MoveFileEx> will fail.
+
+=item C<MOVEFILE_DELAY_UNTIL_REBOOT>
+
+Preliminary verifications are made and then an entry is added to the
+Registry to cause the rename [or delete] operation to be done the
+next time this copy of the operating system is booted [right after
+any automatic file system checks have completed].  This is not
+supported under Windows 95.
+
+When this bit is set, C<$sNewName> can be C<[]> [for C<NULL>] to
+indicate that C<$sOldName> should be deleted during the next boot
+rather than renamed.
+
+Setting both the C<MOVEFILE_COPY_ALLOWED> and
+C<MOVEFILE_DELAY_UNTIL_REBOOT> bits will cause C<MoveFileEx> to fail.
+
+=item C<MOVEFILE_WRITE_THROUGH>
+
+Ensures that C<MoveFileEx> won't return until the operation has
+finished and been flushed to disk.   This is not supported under
+Windows 95.  Only affects file renames to another file system,
+forcing a buffer flush at the end of the copy operation.
+
+=back
+
+=item OsFHandleOpen
+
+=item C<OsFHandleOpen( FILE, $hNativeHandle, $sMode )>
+
+Opens a Perl file handle based on an already open Win32 native
+file handle [much like C's C<fdopen()> does with a file descriptor].
+Returns a true value if the open operation succeeded.  For failure,
+returns a false value and sets C<$!> [and possibly C<fileLastError()>
+and C<$^E>] to the reason for the failure.
+
+C<FILE> is a Perl file handle [in any of the supported forms, a
+bareword, a string, a typeglob, or a reference to a typeglob] that
+will be opened.  If C<FILE> is already open, it will automatically
+be closed before it is reopened.
+
+C<$hNativeHandle> is an open Win32 native file handle, probably the
+return value from C<CreateFile> or C<createFile>.
+
+C<$sMode> is string of zero or more letters from C<"rwatb">.  These
+are translated into a combination C<O_RDONLY> [C<"r">], C<O_WRONLY>
+[C<"w">], C<O_RDWR> [C<"rw">], C<O_APPEND> [C<"a">], C<O_TEXT>
+[C<"t">], and C<O_BINARY> [C<"b">] flags [see the L<Fcntl> module]
+that is passed to C<OsFHandleOpenFd>.   Currently only C<O_APPEND>
+and C<O_TEXT> have any significance.
+
+Also, a C<"r"> and/or C<"w"> in C<$sMode> is used to decide how the
+file descriptor is converted into a Perl file handle, even though this
+doesn't appear to make a difference.  One of the following is used:
+
+    open( FILE, "<&=".$ivFd )  # "r" w/o "w"
+    open( FILE, ">&=".$ivFd )  # "w" w/o "r"
+    open( FILE, "+<&=".$ivFd ) # both "r" and "w"
+
+C<OsFHandleOpen> eventually calls the Win32-specific C routine
+C<_open_osfhandle()> or Perl's "improved" version called
+C<win32_open_osfhandle()>.  Prior to Perl5.005, C's
+C<_open_osfhandle()> is called which will fail if
+C<GetFileType($hNativeHandle)> would return C<FILE_TYPE_UNKNOWN>.  For
+Perl5.005 and later, C<OsFHandleOpen> calls C<win32_open_osfhandle()>
+from the Perl DLL which doesn't have this restriction.
+
+=item OsFHandleOpenFd
+
+=item C<$ivFD= OsFHandleOpenFd( $hNativeHandle, $uMode )>
+
+Opens a file descriptor [C<$ivFD>] based on an already open Win32
+native file handle, C<$hNativeHandle>.  This just calls the
+Win32-specific C routine C<_open_osfhandle()> or Perl's "improved"
+version called C<win32_open_osfhandle()>.  Prior to Perl5.005 and in Cygwin
+Perl, C's C<_open_osfhandle()> is called which will fail if
+C<GetFileType($hNativeHandle)> would return C<FILE_TYPE_UNKNOWN>.  For
+Perl5.005 and later, C<OsFHandleOpenFd> calls C<win32_open_osfhandle()> from
+the Perl DLL which doesn't have this restriction.
+
+C<$uMode> the logical combination of zero or more C<O_*> constants
+exported by the C<Fcntl> module.  Currently only C<O_APPEND> and
+C<O_TEXT> have any significance.
+
+C<$ivFD> will be non-negative if the open operation was successful. 
+For failure, C<-1> is returned and C<$!> [and possibly
+C<fileLastError()> and C<$^E>] is set to the reason for the failure.
+
+=item QueryDosDevice
+
+=item C<$olTargetLen= QueryDosDevice( $sDosDeviceName, $osTargetPath, $lTargetBuf )>
+
+Looks up the definition of a given "DOS" device name, yielding the
+active Windows NT native device name along with any currently dormant
+definitions.
+
+C<$sDosDeviceName> is the name of the "DOS" device whose definitions
+we want.  For example, C<"C:">, C<"COM1">, or C<"PhysicalDrive0">.
+If C<$sDosDeviceName> is C<[]> [for C<NULL>], the list of all DOS
+device names is returned instead.
+
+C<$osTargetPath> will be assigned a string containing the list of
+definitions.  The definitions are each C<'\0'>-terminate and are
+concatenated into the string, most recent first, with an extra C<'\0'>
+at the end of the whole string [see C<GetLogicalDriveStrings> for
+a sample of this format].
+
+C<$lTargetBuf> is the size [in bytes] of the buffer to allocate for
+C<$osTargetPath>.  See L<Buffer Sizes> for more information.
+
+C<$olTargetLen> is set to the number of bytes written to
+C<$osTargetPath> but you can also use C<length($osTargetPath)>
+to determine this.
+
+For failure, C<0> is returned and C<fileLastError()> and C<$^E> are
+set to the reason for the failure.
+
+=item ReadFile
+
+=item C<ReadFile( $hFile, $opBuffer, $lBytes, $olBytesRead, $pOverlapped )>
+
+Reads bytes from a file or file-like device.  Returns a true value if
+the read operation was successful.  For failure, returns a false value
+and sets C<fileLastError()> and C<$^E> for the reason for the failure.
+
+C<$hFile> is a Win32 native file handle that is already open to the
+file or device to read from.
+
+C<$opBuffer> will be set to a string containing the bytes read.
+
+C<$lBytes> is the number of bytes you would like to read. 
+C<$opBuffer> is automatically initialized to have a buffer large
+enough to hold that many bytes.  Unlike other buffer sizes, C<$lBytes>
+does not need to have a C<"="> prepended to it to prevent a larger
+value to be passed to the underlying Win32 C<ReadFile> API.  However,
+a leading C<"="> will be silently ignored, even if Perl warnings are
+enabled.
+
+If C<$olBytesRead> is not C<[]>, it will be set to the actual number
+of bytes read, though C<length($opBuffer)> can also be used to
+determine this.
+
+C<$pOverlapped> is C<[]> or is a C<OVERLAPPED> structure packed
+into a string.  This is only useful if C<$hFile> was opened with
+the C<FILE_FLAG_OVERLAPPED> flag set.
+
+=item SetErrorMode
+
+=item C<$uOldMode= SetErrorMode( $uNewMode )>
+
+Sets the mode controlling system error handling B<and> returns the
+previous mode value.  Both C<$uOldMode> and C<$uNewMode> will have
+zero or more of the following bits set:
+
+=over
+
+=item C<SEM_FAILCRITICALERRORS>
+
+If set, indicates that when a critical error is encountered, the call
+that triggered the error fails immediately.  Normally this bit is not
+set, which means that a critical error causes a dialogue box to appear
+notifying the desktop user that some application has triggered a
+critical error.   The dialogue box allows the desktop user to decide
+whether the critical error is returned to the process, is ignored, or
+the offending operation is retried.
+
+This affects the C<CreateFile> and C<GetVolumeInformation> calls.
+
+Setting this bit is useful for allowing you to check whether a floppy
+diskette is in the floppy drive.
+
+=item C<SEM_NOALIGNMENTFAULTEXCEPT>
+
+If set, this causes memory access misalignment faults to be
+automatically fixed in a manner invisible to the process.  This flag
+is ignored on x86-based versions of Windows NT.  This flag is not
+supported on Windows 95.
+
+=item C<SEM_NOGPFAULTERRORBOX>
+
+If set, general protection faults do not generate a dialogue box but
+can instead be handled by the process via an exception handler.  This
+bit should not be set by programs that don't know how to handle such
+faults.
+
+=item C<SEM_NOOPENFILEERRORBOX>
+
+If set, then when an attempt to continue reading from or writing to
+an already open file [usually on a removable medium like a floppy
+diskette] finds the file no longer available, the call will
+immediately fail.  Normally this bit is not set, which means that
+instead a dialogue box will appear notifying the desktop user that
+some application has run into this problem.   The dialogue box allows
+the desktop user to decide whether the failure is returned to the
+process, is ignored, or the offending operation is retried.
+
+This affects the C<ReadFile> and C<WriteFile> calls.
+
+=back
+
+=item setFilePointer
+
+=item C<$uNewPos = setFilePointer( $hFile, $ivOffset, $uFromWhere )>
+
+This is a perl-friendly wrapper for the SetFilePointer API (below).
+C<$ivOffset> can be a 64 bit integer or C<Math::BigInt> object if your Perl
+doesn't have 64 bit integers. The return value is the new offset and will
+likewise be a 64 bit integer or a C<Math::BigInt> object.
+
+=item SetFilePointer
+
+=item C<$uNewPos = SetFilePointer( $hFile, $ivOffset, $ioivOffsetHigh, $uFromWhere )>
+
+The native Win32 version of C<seek()>.  C<SetFilePointer> sets the
+position within a file where the next read or write operation will
+start from.
+
+C<$hFile> is a Win32 native file handle.
+
+C<$uFromWhere> is either C<FILE_BEGIN>, C<FILE_CURRENT>, or
+C<FILE_END>, indicating that the new file position is being specified
+relative to the beginning of the file, the current file pointer, or
+the end of the file, respectively.
+
+C<$ivOffset> is [if C<$ioivOffsetHigh> is C<[]>] the offset [in bytes]
+to the new file position from the position specified via
+C<$uFromWhere>.  If C<$ioivOffsetHigh> is not C<[]>, then C<$ivOffset>
+is converted to an unsigned value to be used as the low-order 4 bytes
+of the offset.
+
+C<$ioivOffsetHigh> can be C<[]> [for C<NULL>] to indicate that you are
+only specifying a 4-byte offset and the resulting file position will
+be 0xFFFFFFFE or less [just under 4GB].  Otherwise C<$ioivOfffsetHigh>
+starts out with the high-order 4 bytes [signed] of the offset and gets
+set to the [unsigned] high-order 4 bytes of the resulting file position.
+
+The underlying C<SetFilePointer> returns C<0xFFFFFFFF> to indicate
+failure, but if C<$ioivOffsetHigh> is not C<[]>, you would also have
+to check C<$^E> to determine whether C<0xFFFFFFFF> indicates an error
+or not.  C<Win32API::File::SetFilePointer> does this checking for you
+and returns a false value if and only if the underlying
+C<SetFilePointer> failed.  For this reason, C<$uNewPos> is set to
+C<"0 but true"> if you set the file pointer to the beginning of the
+file [or any position with 0 for the low-order 4 bytes].
+
+So the return value will be true if the seek operation was successful.
+For failure, a false value is returned and C<fileLastError()> and
+C<$^E> are set to the reason for the failure.
+
+=item SetHandleInformation
+
+=item C<SetHandleInformation( $hObject, $uMask, $uFlags )>
+
+Sets the flags associated with a Win32 native file handle or object
+handle.  Returns a true value if the operation was successful.  For
+failure, returns a false value and sets C<fileLastError()> and C<$^E>
+for the reason for the failure.
+
+C<$hObject> is an open Win32 native file handle or an open Win32 native
+handle to some other type of object.
+
+C<$uMask> is an unsigned value having one or more of the bits
+C<HANDLE_FLAG_INHERIT> and C<HANDLE_FLAG_PROTECT_FROM_CLOSE> set.
+Only bits set in C<$uMask> will be modified by C<SetHandleInformation>.
+
+C<$uFlags> is an unsigned value having zero or more of the bits
+C<HANDLE_FLAG_INHERIT> and C<HANDLE_FLAG_PROTECT_FROM_CLOSE> set.
+For each bit set in C<$uMask>, the cooresponding bit in the handle's
+flags is set to the value of the cooresponding bit in C<$uFlags>.
+
+If C<$uOldFlags> were the value of the handle's flags before the
+call to C<SetHandleInformation>, then the value of the handle's
+flags afterward would be:
+
+    ( $uOldFlags & ~$uMask ) | ( $uFlags & $uMask )
+
+[at least as far as the C<HANDLE_FLAG_INHERIT> and
+C<HANDLE_FLAG_PROTECT_FROM_CLOSE> bits are concerned.]
+
+See the C<":HANDLE_FLAG_"> export class for the meanings of these bits.
+
+=item WriteFile
+
+=item C<WriteFile( $hFile, $pBuffer, $lBytes, $ouBytesWritten, $pOverlapped )>
+
+Write bytes to a file or file-like device.  Returns a true value if
+the operation was successful.  For failure, returns a false value and
+sets C<fileLastError()> and C<$^E> for the reason for the failure.
+
+C<$hFile> is a Win32 native file handle that is already open to the
+file or device to be written to.
+
+C<$pBuffer> is a string containing the bytes to be written.
+
+C<$lBytes> is the number of bytes you would like to write.  If
+C<$pBuffer> is not at least C<$lBytes> long, C<WriteFile> croaks.  You
+can specify C<0> for C<$lBytes> to write C<length($pBuffer)> bytes.
+A leading C<"="> on C<$lBytes> will be silently ignored, even if Perl
+warnings are enabled.
+
+C<$ouBytesWritten> will be set to the actual number of bytes written
+unless you specify it as C<[]>.
+
+C<$pOverlapped> is C<[]> or is an C<OVERLAPPED> structure packed
+into a string.  This is only useful if C<$hFile> was opened with
+the C<FILE_FLAG_OVERLAPPED> flag set.
+
+=back
+
+=item C<":FuncA">
+
+The ASCII-specific functions.  Each of these is just the same as the
+version without the trailing "A".
+
+       CopyFileA
+       CreateFileA
+       DefineDosDeviceA
+       DeleteFileA
+       GetDriveTypeA
+       GetFileAttributesA
+       GetLogicalDriveStringsA
+       GetVolumeInformationA
+       MoveFileA
+       MoveFileExA
+       QueryDosDeviceA
+
+=item C<":FuncW">
+
+The wide-character-specific (Unicode) functions.  Each of these is
+just the same as the version without the trailing "W" except that
+strings are expected in Unicode and some lengths are measured as
+number of C<WCHAR>s instead of number of bytes, as indicated below.
+
+=over
+
+=item CopyFileW
+
+=item C<CopyFileW( $swOldFileName, $swNewFileName, $bFailIfExists )>
+
+C<$swOldFileName> and C<$swNewFileName> are Unicode strings.
+
+=item CreateFileW
+
+=item C<$hObject= CreateFileW( $swPath, $uAccess, $uShare, $pSecAttr, $uCreate, $uFlags, $hModel )>
+
+C<$swPath> is Unicode.
+
+=item DefineDosDeviceW
+
+=item C<DefineDosDeviceW( $uFlags, $swDosDeviceName, $swTargetPath )>
+
+C<$swDosDeviceName> and C<$swTargetPath> are Unicode.
+
+=item DeleteFileW
+
+=item C<DeleteFileW( $swFileName )>
+
+C<$swFileName> is Unicode.
+
+=item GetDriveTypeW
+
+=item C<$uDriveType= GetDriveTypeW( $swRootPath )>
+
+C<$swRootPath> is Unicode.
+
+=item GetFileAttributesW
+
+=item C<$uAttrs= GetFileAttributesW( $swPath )>
+
+C<$swPath> is Unicode.
+
+=item GetLogicalDriveStringsW
+
+=item C<$olwOutLength= GetLogicalDriveStringsW( $lwBufSize, $oswBuffer )>
+
+Unicode is stored in C<$oswBuffer>.  C<$lwBufSize> and C<$olwOutLength>
+are measured as number of C<WCHAR>s.
+
+=item GetVolumeInformationW
+
+=item C<GetVolumeInformationW( $swRootPath, $oswVolName, $lwVolName, $ouSerialNum, $ouMaxNameLen, $ouFsFlags, $oswFsType, $lwFsType )>
+
+C<$swRootPath> is Unicode and Unicode is written to C<$oswVolName> and
+C<$oswFsType>.  C<$lwVolName> and C<$lwFsType> are measures as number
+of C<WCHAR>s.
+
+=item MoveFileW
+
+=item C<MoveFileW( $swOldName, $swNewName )>
+
+C<$swOldName> and C<$swNewName> are Unicode.
+
+=item MoveFileExW
+
+=item C<MoveFileExW( $swOldName, $swNewName, $uFlags )>
+
+C<$swOldName> and C<$swNewName> are Unicode.
+
+=item QueryDosDeviceW
+
+=item C<$olwTargetLen= QueryDosDeviceW( $swDeviceName, $oswTargetPath, $lwTargetBuf )>
+
+C<$swDeviceName> is Unicode and Unicode is written to
+C<$oswTargetPath>.  C<$lwTargetBuf> and C<$olwTargetLen> are measured
+as number of  C<WCHAR>s.
+
+=back
+
+=item C<":Misc">
+
+Miscellaneous constants.  Used for the C<$uCreate> argument of
+C<CreateFile> or the C<$uFromWhere> argument of C<SetFilePointer>.
+Plus C<INVALID_HANDLE_VALUE>, which you usually won't need to check
+for since most routines translate it into a false value.
+
+       CREATE_ALWAYS           CREATE_NEW              OPEN_ALWAYS
+       OPEN_EXISTING           TRUNCATE_EXISTING       INVALID_HANDLE_VALUE
+       FILE_BEGIN              FILE_CURRENT            FILE_END
+
+=item C<":DDD_">
+
+Constants for the C<$uFlags> argument of C<DefineDosDevice>.
+
+       DDD_EXACT_MATCH_ON_REMOVE
+       DDD_RAW_TARGET_PATH
+       DDD_REMOVE_DEFINITION
+
+=item C<":DRIVE_">
+
+Constants returned by C<GetDriveType>.
+
+       DRIVE_UNKNOWN           DRIVE_NO_ROOT_DIR       DRIVE_REMOVABLE
+       DRIVE_FIXED             DRIVE_REMOTE            DRIVE_CDROM
+       DRIVE_RAMDISK
+
+=item C<":FILE_">
+
+Specific types of access to files that can be requested via the
+C<$uAccess> argument to C<CreateFile>.
+
+       FILE_READ_DATA                  FILE_LIST_DIRECTORY
+       FILE_WRITE_DATA                 FILE_ADD_FILE
+       FILE_APPEND_DATA                FILE_ADD_SUBDIRECTORY
+       FILE_CREATE_PIPE_INSTANCE       FILE_READ_EA
+       FILE_WRITE_EA                   FILE_EXECUTE
+       FILE_TRAVERSE                   FILE_DELETE_CHILD
+       FILE_READ_ATTRIBUTES            FILE_WRITE_ATTRIBUTES
+       FILE_ALL_ACCESS                 FILE_GENERIC_READ
+       FILE_GENERIC_WRITE              FILE_GENERIC_EXECUTE )],
+
+=item C<":FILE_ATTRIBUTE_">
+
+File attribute constants.  Returned by C<attrLetsToBits> and used in
+the C<$uFlags> argument to C<CreateFile>.
+
+       FILE_ATTRIBUTE_ARCHIVE                  FILE_ATTRIBUTE_COMPRESSED
+       FILE_ATTRIBUTE_HIDDEN                   FILE_ATTRIBUTE_NORMAL
+       FILE_ATTRIBUTE_OFFLINE                  FILE_ATTRIBUTE_READONLY
+       FILE_ATTRIBUTE_SYSTEM                   FILE_ATTRIBUTE_TEMPORARY
+
+In addition, C<GetFileAttributes> can return these constants (or
+INVALID_FILE_ATTRIBUTES in case of an error).
+
+       FILE_ATTRIBUTE_DEVICE                   FILE_ATTRIBUTE_DIRECTORY
+       FILE_ATTRIBUTE_ENCRYPTED                FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
+       FILE_ATTRIBUTE_REPARSE_POINT    FILE_ATTRIBUTE_SPARSE_FILE
+
+=item C<":FILE_FLAG_">
+
+File option flag constants.  Used in the C<$uFlags> argument to
+C<CreateFile>.
+
+       FILE_FLAG_BACKUP_SEMANTICS      FILE_FLAG_DELETE_ON_CLOSE
+       FILE_FLAG_NO_BUFFERING          FILE_FLAG_OVERLAPPED
+       FILE_FLAG_POSIX_SEMANTICS       FILE_FLAG_RANDOM_ACCESS
+       FILE_FLAG_SEQUENTIAL_SCAN       FILE_FLAG_WRITE_THROUGH
+       FILE_FLAG_OPEN_REPARSE_POINT
+
+=item C<":FILE_SHARE_">
+
+File sharing constants.  Used in the C<$uShare> argument to
+C<CreateFile>.
+
+       FILE_SHARE_DELETE       FILE_SHARE_READ         FILE_SHARE_WRITE
+
+=item C<":FILE_TYPE_">
+
+File type constants.  Returned by C<GetFileType>.
+
+       FILE_TYPE_CHAR          FILE_TYPE_DISK
+       FILE_TYPE_PIPE          FILE_TYPE_UNKNOWN
+
+=item C<":FS_">
+
+File system characteristics constants.  Placed in the C<$ouFsFlags>
+argument to C<GetVolumeInformation>.
+
+       FS_CASE_IS_PRESERVED            FS_CASE_SENSITIVE
+       FS_UNICODE_STORED_ON_DISK       FS_PERSISTENT_ACLS 
+       FS_FILE_COMPRESSION             FS_VOL_IS_COMPRESSED
+
+=item C<":HANDLE_FLAG_">
+
+Flag bits modifying the behavior of an object handle and accessed via
+C<GetHandleInformation> and C<SetHandleInformation>.
+
+=over
+
+=item HANDLE_FLAG_INHERIT
+
+If this bit is set, then children of this process who inherit handles
+[that is, processes created by calls to the Win32 C<CreateProcess> API
+with the C<bInheritHandles> parameter specified as C<TRUE>], will inherit
+this particular object handle.
+
+=item HANDLE_FLAG_PROTECT_FROM_CLOSE
+
+If this bit is set, then calls to C<CloseHandle> against this handle
+will be ignored, leaving the handle open and usable.
+
+=back
+
+=item C<":IOCTL_STORAGE_">
+
+I/O control operations for generic storage devices.  Used in the
+C<$uIoControlCode> argument to C<DeviceIoControl>.  Includes
+C<IOCTL_STORAGE_CHECK_VERIFY>, C<IOCTL_STORAGE_MEDIA_REMOVAL>,
+C<IOCTL_STORAGE_EJECT_MEDIA>, C<IOCTL_STORAGE_LOAD_MEDIA>,
+C<IOCTL_STORAGE_RESERVE>, C<IOCTL_STORAGE_RELEASE>,
+C<IOCTL_STORAGE_FIND_NEW_DEVICES>, and
+C<IOCTL_STORAGE_GET_MEDIA_TYPES>.
+
+=over
+
+=item C<IOCTL_STORAGE_CHECK_VERIFY>
+
+Verify that a device's media is accessible.  C<$pInBuf> and C<$opOutBuf>
+should both be C<[]>.  If C<DeviceIoControl> returns a true value, then
+the media is currently accessible.
+
+=item C<IOCTL_STORAGE_MEDIA_REMOVAL>
+
+Allows the device's media to be locked or unlocked.  C<$opOutBuf> should
+be C<[]>.  C<$pInBuf> should be a C<PREVENT_MEDIA_REMOVAL> data structure,
+which is simply an interger containing a boolean value:
+
+    $pInBuf= pack( "i", $bPreventMediaRemoval );
+
+=item C<IOCTL_STORAGE_EJECT_MEDIA>
+
+Requests that the device eject the media.  C<$pInBuf> and C<$opOutBuf>
+should both be C<[]>.  
+
+=item C<IOCTL_STORAGE_LOAD_MEDIA>
+
+Requests that the device load the media.  C<$pInBuf> and C<$opOutBuf>
+should both be C<[]>.
+
+=item C<IOCTL_STORAGE_RESERVE>
+
+Requests that the device be reserved.  C<$pInBuf> and C<$opOutBuf>
+should both be C<[]>.
+
+=item C<IOCTL_STORAGE_RELEASE>
+
+Releases a previous device reservation.  C<$pInBuf> and C<$opOutBuf>
+should both be C<[]>.
+
+=item C<IOCTL_STORAGE_FIND_NEW_DEVICES>
+
+No documentation on this IOCTL operation was found.
+
+=item C<IOCTL_STORAGE_GET_MEDIA_TYPES>
+
+Requests information about the type of media supported by the device. 
+C<$pInBuf> should be C<[]>.  C<$opOutBuf> will be set to contain a
+vector of C<DISK_GEOMETRY> data structures, which can be decoded via:
+
+    # Calculate the number of DISK_GEOMETRY structures returned:
+    my $cStructs= length($opOutBuf)/(4+4+4+4+4+4);
+    my @fields= unpack( "L l I L L L" x $cStructs, $opOutBuf )
+    my( @ucCylsLow, @ivcCylsHigh, @uMediaType, @uTracksPerCyl,
+      @uSectsPerTrack, @uBytesPerSect )= ();
+    while(  @fields  ) {
+       push( @ucCylsLow, unshift @fields );
+       push( @ivcCylsHigh, unshift @fields );
+       push( @uMediaType, unshift @fields );
+       push( @uTracksPerCyl, unshift @fields );
+       push( @uSectsPerTrack, unshift @fields );
+       push( @uBytesPerSect, unshift @fields );
+    }
+
+For the C<$i>th type of supported media, the following variables will
+contain the following data.
+
+=over
+
+=item C<$ucCylsLow[$i]>
+
+The low-order 4 bytes of the total number of cylinders.
+
+=item C<$ivcCylsHigh[$i]> 
+
+The high-order 4 bytes of the total number of cylinders.
+
+=item C<$uMediaType[$i]>
+
+A code for the type of media.  See the C<":MEDIA_TYPE"> export class.
+
+=item C<$uTracksPerCyl[$i]>
+
+The number of tracks in each cylinder.
+
+=item C<$uSectsPerTrack[$i]>
+
+The number of sectors in each track.
+
+=item C<$uBytesPerSect[$i]>
+
+The number of bytes in each sector.
+
+=back
+
+=back
+
+=item C<":IOCTL_DISK_">
+
+I/O control operations for disk devices.  Used in the C<$uIoControlCode>
+argument to C<DeviceIoControl>.  Most of these are to be used on
+physical drive devices like C<"//./PhysicalDrive0">.  However,
+C<IOCTL_DISK_GET_PARTITION_INFO> and C<IOCTL_DISK_SET_PARTITION_INFO>
+should only be used on a single-partition device like C<"//./C:">.  Also,
+C<IOCTL_DISK_GET_MEDIA_TYPES> is documented as having been superceded but
+is still useful when used on a floppy device like C<"//./A:">.
+
+Includes C<IOCTL_DISK_FORMAT_TRACKS>, C<IOCTL_DISK_FORMAT_TRACKS_EX>,
+C<IOCTL_DISK_GET_DRIVE_GEOMETRY>, C<IOCTL_DISK_GET_DRIVE_LAYOUT>,
+C<IOCTL_DISK_GET_MEDIA_TYPES>, C<IOCTL_DISK_GET_PARTITION_INFO>,
+C<IOCTL_DISK_HISTOGRAM_DATA>, C<IOCTL_DISK_HISTOGRAM_RESET>,
+C<IOCTL_DISK_HISTOGRAM_STRUCTURE>, C<IOCTL_DISK_IS_WRITABLE>,
+C<IOCTL_DISK_LOGGING>, C<IOCTL_DISK_PERFORMANCE>,
+C<IOCTL_DISK_REASSIGN_BLOCKS>, C<IOCTL_DISK_REQUEST_DATA>,
+C<IOCTL_DISK_REQUEST_STRUCTURE>, C<IOCTL_DISK_SET_DRIVE_LAYOUT>,
+C<IOCTL_DISK_SET_PARTITION_INFO>, and C<IOCTL_DISK_VERIFY>.
+
+=over
+
+=item C<IOCTL_DISK_GET_DRIVE_GEOMETRY>
+
+Request information about the size and geometry of the disk.  C<$pInBuf>
+should be C<[]>.  C<$opOutBuf> will be set to a C<DISK_GEOMETRY> data
+structure which can be decode via:
+
+    ( $ucCylsLow, $ivcCylsHigh, $uMediaType, $uTracksPerCyl,
+      $uSectsPerTrack, $uBytesPerSect )= unpack( "L l I L L L", $opOutBuf );
+
+=over
+
+=item C<$ucCylsLow>
+
+The low-order 4 bytes of the total number of cylinders.
+
+=item C<$ivcCylsHigh> 
+
+The high-order 4 bytes of the total number of cylinders.
+
+=item C<$uMediaType>
+
+A code for the type of media.  See the C<":MEDIA_TYPE"> export class.
+
+=item C<$uTracksPerCyl>
+
+The number of tracks in each cylinder.
+
+=item C<$uSectsPerTrack>
+
+The number of sectors in each track.
+
+=item C<$uBytesPerSect>
+
+The number of bytes in each sector.
+
+=back
+
+=item C<IOCTL_DISK_GET_PARTITION_INFO>
+
+Request information about the size and geometry of the partition. 
+C<$pInBuf> should be C<[]>.  C<$opOutBuf> will be set to a
+C<PARTITION_INFORMATION> data structure which can be decode via:
+
+    ( $uStartLow, $ivStartHigh, $ucHiddenSects, $uPartitionSeqNumber,
+      $uPartitionType, $bActive, $bRecognized, $bToRewrite )=
+      unpack( "L l L L C c c c", $opOutBuf );
+
+=over
+
+=item C<$uStartLow> and C<$ivStartHigh>
+
+The low-order and high-order [respectively] 4 bytes of the starting
+offset of the partition, measured in bytes.
+
+=item C<$ucHiddenSects>
+
+The number of "hidden" sectors for this partition.  Actually this is
+the number of sectors found prior to this partiton, that is, the
+starting offset [as found in C<$uStartLow> and C<$ivStartHigh>]
+divided by the number of bytes per sector.
+
+=item C<$uPartitionSeqNumber>
+
+The sequence number of this partition.  Partitions are numbered
+starting as C<1> [with "partition 0" meaning the entire disk].  
+Sometimes this field may be C<0> and you'll have to infer the
+partition sequence number from how many partitions preceed it on
+the disk.
+
+=item C<$uPartitionType>
+
+The type of partition.  See the C<":PARTITION_"> export class for a
+list of known types.  See also C<IsRecognizedPartition> and
+C<IsContainerPartition>.
+
+=item C<$bActive>
+
+C<1> for the active [boot] partition, C<0> otherwise.
+
+=item C<$bRecognized>
+
+Whether this type of partition is support under Win32.
+
+=item C<$bToRewrite>
+
+Whether to update this partition information.  This field is not used
+by C<IOCTL_DISK_GET_PARTITION_INFO>.  For
+C<IOCTL_DISK_SET_DRIVE_LAYOUT>, you must set this field to a true
+value for any partitions you wish to have changed, added, or deleted.
+
+=back
+
+=item C<IOCTL_DISK_SET_PARTITION_INFO>
+
+Change the type of the partition.  C<$opOutBuf> should be C<[]>.
+C<$pInBuf> should be a C<SET_PARTITION_INFORMATION> data structure
+which is just a single byte containing the new parition type [see
+the C<":PARTITION_"> export class for a list of known types]:
+
+    $pInBuf= pack( "C", $uPartitionType );
+
+=item C<IOCTL_DISK_GET_DRIVE_LAYOUT>
+
+Request information about the disk layout.  C<$pInBuf> should be C<[]>.
+C<$opOutBuf> will be set to contain C<DRIVE_LAYOUT_INFORMATION>
+structure including several C<PARTITION_INFORMATION> structures:
+
+    my( $cPartitions, $uDiskSignature )= unpack( "L L", $opOutBuf );
+    my @fields= unpack( "x8" . ( "L l L L C c c c" x $cPartitions ),
+                       $opOutBuf );
+    my( @uStartLow, @ivStartHigh, @ucHiddenSects,
+      @uPartitionSeqNumber, @uPartitionType, @bActive,
+      @bRecognized, @bToRewrite )= ();
+    for(  1..$cPartition  ) {
+       push( @uStartLow, unshift @fields );
+       push( @ivStartHigh, unshift @fields );
+       push( @ucHiddenSects, unshift @fields );
+       push( @uPartitionSeqNumber, unshift @fields );
+       push( @uPartitionType, unshift @fields );
+       push( @bActive, unshift @fields );
+       push( @bRecognized, unshift @fields );
+       push( @bToRewrite, unshift @fields );
+    }
+
+=over
+
+=item C<$cPartitions>
+
+If the number of partitions on the disk.
+
+=item C<$uDiskSignature>
+
+Is the disk signature, a unique number assigned by Disk Administrator
+[F<WinDisk.exe>] and used to identify the disk.  This allows drive
+letters for partitions on that disk to remain constant even if the
+SCSI Target ID of the disk gets changed.
+
+=back
+
+See C<IOCTL_DISK_GET_PARTITION_INFORMATION> for information on the
+remaining these fields.
+
+=item C<IOCTL_DISK_GET_MEDIA_TYPES>
+
+Is supposed to be superseded by C<IOCTL_STORAGE_GET_MEDIA_TYPES> but
+is still useful for determining the types of floppy diskette formats
+that can be produced by a given floppy drive.  See
+F<ex/FormatFloppy.plx> for an example.
+
+=item C<IOCTL_DISK_SET_DRIVE_LAYOUT>
+
+Change the partition layout of the disk.  C<$pOutBuf> should be C<[]>.
+C<$pInBuf> should be a C<DISK_LAYOUT_INFORMATION> data structure
+including several C<PARTITION_INFORMATION> data structures.
+
+    # Already set:  $cPartitions, $uDiskSignature, @uStartLow, @ivStartHigh,
+    #   @ucHiddenSects, @uPartitionSeqNumber, @uPartitionType, @bActive,
+    #   @bRecognized, and @bToRewrite.
+    my( @fields, $prtn )= ();
+    for $prtn (  1..$cPartition  ) {
+       push( @fields, $uStartLow[$prtn-1], $ivStartHigh[$prtn-1],
+           $ucHiddenSects[$prtn-1], $uPartitionSeqNumber[$prtn-1],
+           $uPartitionType[$prtn-1], $bActive[$prtn-1],
+           $bRecognized[$prtn-1], $bToRewrite[$prtn-1] );
+    }
+    $pInBuf= pack( "L L" . ( "L l L L C c c c" x $cPartitions ),
+                  $cPartitions, $uDiskSignature, @fields );
+
+To delete a partition, zero out all fields except for C<$bToRewrite>
+which should be set to C<1>.  To add a partition, increment
+C<$cPartitions> and add the information for the new partition
+into the arrays, making sure that you insert C<1> into @bToRewrite.
+
+See C<IOCTL_DISK_GET_DRIVE_LAYOUT> and
+C<IOCTL_DISK_GET_PARITITON_INFORMATION> for descriptions of the
+fields.
+
+=item C<IOCTL_DISK_VERIFY>
+
+Performs a logical format of [part of] the disk.  C<$opOutBuf> should
+be C<[]>.  C<$pInBuf> should contain a C<VERIFY_INFORMATION> data
+structure:
+
+    $pInBuf= pack( "L l L",
+                  $uStartOffsetLow, $ivStartOffsetHigh, $uLength );
+
+=over
+
+=item C<$uStartOffsetLow> and C<$ivStartOffsetHigh>
+
+The low-order and high-order [respectively] 4 bytes of the offset [in
+bytes] where the formatting should begin.
+
+=item C<$uLength>
+
+The length [in bytes] of the section to be formatted.
+
+=back
+
+=item C<IOCTL_DISK_FORMAT_TRACKS>
+
+Format a range of tracks on the disk.  C<$opOutBuf> should be C<[]>. 
+C<$pInBuf> should contain a C<FORMAT_PARAMETERS> data structure:
+
+    $pInBuf= pack( "L L L L L", $uMediaType,
+                  $uStartCyl, $uEndCyl, $uStartHead, $uEndHead );
+
+C<$uMediaType> if the type of media to be formatted.  Mostly used to
+specify the density to use when formatting a floppy diskette.  See the
+C<":MEDIA_TYPE"> export class for more information.
+
+The remaining fields specify the starting and ending cylinder and
+head of the range of tracks to be formatted.
+
+=item C<IOCTL_DISK_REASSIGN_BLOCKS>
+
+Reassign a list of disk blocks to the disk's spare-block pool. 
+C<$opOutBuf> should be C<[]>.  C<$pInBuf> should be a
+C<REASSIGN_BLOCKS> data structure:
+
+    $pInBuf= pack( "S S L*", 0, $cBlocks, @uBlockNumbers );
+
+=item C<IOCTL_DISK_PERFORMANCE>
+
+Request information about disk performance.  C<$pInBuf> should be C<[]>.
+C<$opOutBuf> will be set to contain a C<DISK_PERFORMANCE> data structure:
+
+    my( $ucBytesReadLow, $ivcBytesReadHigh,
+       $ucBytesWrittenLow, $ivcBytesWrittenHigh,
+       $uReadTimeLow, $ivReadTimeHigh,
+       $uWriteTimeLow, $ivWriteTimeHigh,
+       $ucReads, $ucWrites, $uQueueDepth )=
+       unpack( "L l L l L l L l L L L", $opOutBuf );
+
+=item C<IOCTL_DISK_IS_WRITABLE>
+
+No documentation on this IOCTL operation was found.
+
+=item C<IOCTL_DISK_LOGGING>
+
+Control disk logging.  Little documentation for this IOCTL operation
+was found.  It makes use of a C<DISK_LOGGING> data structure:
+
+=over
+
+=item DISK_LOGGING_START
+
+Start logging each disk request in a buffer internal to the disk device
+driver of size C<$uLogBufferSize>:
+
+    $pInBuf= pack( "C L L", 0, 0, $uLogBufferSize );
+
+=item DISK_LOGGING_STOP
+
+Stop loggin each disk request:
+
+    $pInBuf= pack( "C L L", 1, 0, 0 );
+
+=item DISK_LOGGING_DUMP
+
+Copy the interal log into the supplied buffer:
+
+    $pLogBuffer= ' ' x $uLogBufferSize
+    $pInBuf= pack( "C P L", 2, $pLogBuffer, $uLogBufferSize );
+
+    ( $uByteOffsetLow[$i], $ivByteOffsetHigh[$i],
+      $uStartTimeLow[$i], $ivStartTimeHigh[$i],
+      $uEndTimeLog[$i], $ivEndTimeHigh[$i],
+      $hVirtualAddress[$i], $ucBytes[$i],
+      $uDeviceNumber[$i], $bWasReading[$i] )=
+      unpack( "x".(8+8+8+4+4+1+1+2)." L l L l L l L L C c x2", $pLogBuffer );
+
+=item DISK_LOGGING_BINNING
+
+Keep statics grouped into bins based on request sizes.
+
+    $pInBuf= pack( "C P L", 3, $pUnknown, $uUnknownSize );
+
+=back
+
+=item C<IOCTL_DISK_FORMAT_TRACKS_EX>
+
+No documentation on this IOCTL is included.
+
+=item C<IOCTL_DISK_HISTOGRAM_STRUCTURE>
+
+No documentation on this IOCTL is included.
+
+=item C<IOCTL_DISK_HISTOGRAM_DATA>
+
+No documentation on this IOCTL is included.
+
+=item C<IOCTL_DISK_HISTOGRAM_RESET>
+
+No documentation on this IOCTL is included.
+
+=item C<IOCTL_DISK_REQUEST_STRUCTURE>
+
+No documentation on this IOCTL operation was found.
+
+=item C<IOCTL_DISK_REQUEST_DATA>
+
+No documentation on this IOCTL operation was found.
+
+=back
+
+=item C<":FSCTL_">
+
+File system control operations.  Used in the C<$uIoControlCode>
+argument to C<DeviceIoControl>.
+
+Includes C<FSCTL_SET_REPARSE_POINT>, C<FSCTL_GET_REPARSE_POINT>,
+C<FSCTL_DELETE_REPARSE_POINT>.
+
+=over
+
+=item C<FSCTL_SET_REPARSE_POINT>
+
+Sets reparse point data to be associated with $hDevice.
+
+=item C<FSCTL_GET_REPARSE_POINT>
+
+Retrieves the reparse point data associated with $hDevice.
+
+=item C<FSCTL_DELETE_REPARSE_POINT>
+
+Deletes the reparse point data associated with $hDevice.
+
+=back
+
+=item C<":GENERIC_">
+
+Constants specifying generic access permissions that are not specific
+to one type of object.
+
+       GENERIC_ALL                     GENERIC_EXECUTE
+       GENERIC_READ            GENERIC_WRITE
+
+=item C<":MEDIA_TYPE">
+
+Different classes of media that a device can support.  Used in the
+C<$uMediaType> field of a C<DISK_GEOMETRY> structure.
+
+=over
+
+=item C<Unknown>
+
+Format is unknown.
+
+=item C<F5_1Pt2_512>
+
+5.25" floppy, 1.2MB [really 1,200KB] total space, 512 bytes/sector.
+
+=item C<F3_1Pt44_512>
+
+3.5" floppy, 1.44MB [really 1,440KB] total space, 512 bytes/sector.
+
+=item C<F3_2Pt88_512>
+
+3.5" floppy, 2.88MB [really 2,880KB] total space, 512 bytes/sector.
+
+=item C<F3_20Pt8_512>
+
+3.5" floppy, 20.8MB total space, 512 bytes/sector.
+
+=item C<F3_720_512>
+
+3.5" floppy, 720KB total space, 512 bytes/sector.
+
+=item C<F5_360_512>
+
+5.25" floppy, 360KB total space, 512 bytes/sector.
+
+=item C<F5_320_512>
+
+5.25" floppy, 320KB total space, 512 bytes/sector.
+
+=item C<F5_320_1024>
+
+5.25" floppy, 320KB total space, 1024 bytes/sector.
+
+=item C<F5_180_512>
+
+5.25" floppy, 180KB total space, 512 bytes/sector.
+
+=item C<F5_160_512>
+
+5.25" floppy, 160KB total space, 512 bytes/sector.
+
+=item C<RemovableMedia>
+
+Some type of removable media other than a floppy diskette.
+
+=item C<FixedMedia>
+
+A fixed hard disk.
+
+=item C<F3_120M_512>
+
+3.5" floppy, 120MB total space.
+
+=back
+
+=item C<":MOVEFILE_">
+
+Constants for use in C<$uFlags> arguments to C<MoveFileEx>.
+
+       MOVEFILE_COPY_ALLOWED           MOVEFILE_DELAY_UNTIL_REBOOT
+       MOVEFILE_REPLACE_EXISTING       MOVEFILE_WRITE_THROUGH
+
+=item C<":SECURITY_">
+
+Security quality of service values that can be used in the C<$uFlags>
+argument to C<CreateFile> if opening the client side of a named pipe.
+
+       SECURITY_ANONYMOUS              SECURITY_CONTEXT_TRACKING
+       SECURITY_DELEGATION             SECURITY_EFFECTIVE_ONLY
+       SECURITY_IDENTIFICATION         SECURITY_IMPERSONATION
+       SECURITY_SQOS_PRESENT
+
+=item C<":SEM_">
+
+Constants to be used with C<SetErrorMode>.
+
+       SEM_FAILCRITICALERRORS          SEM_NOGPFAULTERRORBOX
+       SEM_NOALIGNMENTFAULTEXCEPT      SEM_NOOPENFILEERRORBOX
+
+=item C<":PARTITION_">
+
+Constants describing partition types.
+
+       PARTITION_ENTRY_UNUSED          PARTITION_FAT_12
+       PARTITION_XENIX_1               PARTITION_XENIX_2
+       PARTITION_FAT_16                PARTITION_EXTENDED
+       PARTITION_HUGE                  PARTITION_IFS
+       PARTITION_FAT32                 PARTITION_FAT32_XINT13
+       PARTITION_XINT13                PARTITION_XINT13_EXTENDED
+       PARTITION_PREP                  PARTITION_UNIX
+       VALID_NTFT                      PARTITION_NTFT
+
+=item C<":ALL">
+
+All of the above.
+
+=back
+
+=head1 BUGS
+
+None known at this time.
+
+=head1 AUTHOR
+
+Tye McQueen, tye@metronet.com, http://www.metronet.com/~tye/.
+
+=head1 SEE ALSO
+
+The pyramids.
+
+=cut
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
diff --git a/win32/ext/Win32API/File/Makefile.PL b/win32/ext/Win32API/File/Makefile.PL
new file mode 100644 (file)
index 0000000..c84d1de
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/perl -w
+use ExtUtils::MakeMaker;
+use Config;
+use strict;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+    'NAME'     => 'Win32API::File',
+    'VERSION_FROM' => 'File.pm', # finds $VERSION
+    (  $Config{archname} =~ /-object\b/i  ?  ( 'CAPI' => 'TRUE' )  :  ()  ),
+    (  $] < 5.005  ?  ()  :
+       ( 'AUTHOR'              => 'Tye McQueen <tye@metronet.com>',
+         'ABSTRACT_FROM'       => 'File.pm' )
+    ),
+    'postamble' => { IMPORT_LIST => [qw(/._/ !/[a-z]/ :MEDIA_TYPE)],
+                    IFDEF => "!/[a-z\\d]/",
+                    CPLUSPLUS => 1,
+                    WRITE_PERL => 1,
+                    # Comment out next line to rebuild constants defs:
+                    NO_REBUILD => 1,
+                  },
+    (  ! $Config{libperl}  ?  ()  :  ( LIBPERL_A => $Config{libperl} )  ),
+);
+
+# Replacement for MakeMaker's "const2perl section" for versions
+# of MakeMaker prior to the addition of this functionality:
+sub MY::postamble
+{
+    my( $self, %attribs )= @_;
+
+    # Don't do anything if MakeMaker has const2perl
+    # that already took care of all of this:
+    return   unless  %attribs;
+
+    # Don't require these here if we just C<return> above:
+    eval "use ExtUtils::Myconst2perl qw(ParseAttribs); 1"   or  die "$@";
+    eval "use ExtUtils::MakeMaker qw(neatvalue); 1"   or  die "$@";
+
+    # If only one module, can skip one level of indirection:
+    my $hvAttr= \%attribs;
+    if(  $attribs{IMPORT_LIST}  ) {
+       $hvAttr= { $self->{NAME} => \%attribs };
+    }
+
+    my( $module, @m, $_final, @clean, @realclean );
+    foreach $module (  keys %$hvAttr  ) {
+       my( $outfile, @perlfiles, @cfiles, $bin, $obj, $final, $noreb );
+
+       # Translate user-friendly options into coder-friendly specifics:
+       ParseAttribs( $module, $hvAttr->{$module}, { OUTFILE => \$outfile,
+         C_FILE_LIST => \@perlfiles, PERL_FILE_LIST => \@cfiles,
+         OBJECT => \$obj, BINARY => \$bin, FINAL_PERL => \$final,
+         NO_REBUILD => \$noreb } );
+       die "IFDEF option in Makefile.PL must be string, not code ref.\n"
+         if  ref $hvAttr->{$module}->{IFDEF};
+       die qq{IFDEF option in Makefile.PL must not contain quotes (").\n}
+         if  ref $hvAttr->{$module}->{IFDEF};
+
+       # How to create F<$outfile> via ExtUtils::Myconst2perl::Myconst2perl:
+       push @m, "
+$outfile:      @perlfiles  @cfiles  Makefile" . '
+       $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Myconst2perl \\
+         -e "my %attribs;" \\
+         ';
+       $m[-1] =~ s/^/##/gm   if  $noreb;
+       my( $key, $value );
+       while(  ( $key, $value )= each %{$hvAttr->{$module}}  ) {
+           push @m, '-e "$$attribs{' . $key . '}= '
+             . neatvalue($value) . qq[;" \\\n\t  ];
+           $m[-1] =~ s/^/##/gm   if  $noreb;
+       }
+       push @m, '-e "Myconst2perl(' . neatvalue($module) . ",%attribs)\"\n";
+
+       # If requested extra work to generate Perl instead of XS code:
+       if(  $bin  ) {
+           my @path= split /::/, $module;
+           my $_final= $final;
+           $_final =~ s/\W/_/g;
+
+           # How to compile F<$outfile> and then run it to produce F<$final>:
+           push @m, "
+$bin:  $outfile" . '
+       $(CC) $(INC) $(CCFLAGS) $(OPTIMIZE) $(PERLTYPE) $(LARGE) \\
+         $(SPLIT) $(DEFINE_VERSION) $(XS_DEFINE_VERSION) -I$(PERL_INC) \\
+         $(DEFINE)' . $outfile . " "
+         .  $self->catfile(qw[ $(PERL_INC) $(LIBPERL_A) ]) . " -o $bin
+
+$final: $bin
+       " .  $self->catfile(".",$bin) . " >$final\n";
+           $m[-1] =~ s/^/##/gm   if  $noreb;
+
+           # Make sure the rarely-used $(INST_ARCHLIB) directory exists:
+           push @m, $self->dir_target('$(INST_ARCHLIB)');
+
+           ##warn qq{$path[-1].pm should C<require "},
+           ##  join("/",@path,$final), qq{">.\n};
+           # Install F<$final> whenever regular pm_to_blib target is built:
+           push @m, "
+pm_to_blib: ${_final}_to_blib
+
+${_final}_to_blib: $final
+       " . '@$(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" \\
+       "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Install \\
+        -e "pm_to_blib({ ',neatvalue($final),',',
+       neatvalue($self->catfile('$(INST_ARCHLIB)',@path,$final)), ' },',
+       neatvalue($self->catfile(qw[$(INST_LIB) auto])), ')"
+       @$(TOUCH) ', $_final, "_to_blib\n";
+
+           push( @clean, $outfile, $bin, $obj, $_final . "_to_blib" );
+           push( @realclean, $final )   unless  $noreb;
+       } else {
+
+           ##my $name= ( split /::/, $module )[-1];
+           ##warn qq{$name.xs should C<#include "$final"> },
+           ##  qq{in the C<BOOT:> section\n};
+           push( @realclean, $outfile )   unless  $noreb;
+       }
+    }
+
+    push @m, "
+clean ::
+       $self->{RM_F} @clean\n"   if  @clean;
+    push @m, "
+realclean ::
+       $self->{RM_F} @realclean\n"   if  @realclean;
+    return join('',@m);
+}
diff --git a/win32/ext/Win32API/File/README b/win32/ext/Win32API/File/README
new file mode 100644 (file)
index 0000000..ead08d5
--- /dev/null
@@ -0,0 +1,132 @@
+Win32API::File v0.08 -- Low-level access to Win32 API calls for files.
+
+New since v0.07:
+
+       GetHandleInformation    SetHandleInformation
+       HANDLE_FLAG_INHERIT     HANDLE_FLAG_PROTECT_FROM_CLOSE
+       fileConstant            fileLastError
+
+Low-level and full-power access to the following routines are provided:
+
+       CloseHandle             CopyFile                CreateFile
+       DefineDosDevice         DeleteFile              DeviceIoControl
+       GetDriveType            GetFileType             GetHandleInformation
+       GetLogicalDrives        GetLogicalDriveStrings  GetVolumeInformation
+       IsRecognizedPartition   IsContainerPartition    MoveFile
+       MoveFileEx              QueryDosDevice          ReadFile
+       SetFilePointer          SetErrorMode            SetHandleInformation
+       WriteFile
+
+Plus the Unicode versions:
+
+       CopyFileW               CreateFileW             DefineDosDeviceW
+       DeleteFileW             GetDriveTypeW           GetLogicalDriveStringsW
+       GetVolumeInformationW   MoveFileW               MoveFileExW
+       QueryDosDeviceW
+
+Full conversion between Win32-native file handles and Perl file handles is
+also supported.  Access to the following C run-time library routines [or at
+least the Perl run-time library wrappers for them] is provided:
+
+       _get_osfhandle or win32_get_osfhandle   as FdGetOsFHandle               
+       _open_osfhandle or win32_open_osfhandle as OsFHandleOpenFd              
+
+The following Perl-friendly wrappers and helper functions are also provided:
+
+       OsFHandleOpen           GetOsFHandle            attrLetsToBits
+       createFile              fileConstant            fileLastError
+       getLogicalDrives
+
+Plus the following constants:
+
+       CREATE_ALWAYS           CREATE_NEW              FILE_BEGIN
+       FILE_CURRENT            FILE_END                INVALID_HANDLE_VALUE
+       OPEN_ALWAYS             OPEN_EXISTING           TRUNCATE_EXISTING
+
+       DDD_EXACT_MATCH_ON_REMOVE                       DDD_RAW_TARGET_PATH
+       DDD_REMOVE_DEFINITION
+
+       DRIVE_UNKNOWN           DRIVE_NO_ROOT_DIR       DRIVE_REMOVABLE
+       DRIVE_FIXED             DRIVE_REMOTE            DRIVE_CDROM
+       DRIVE_RAMDISK
+
+       FILE_READ_DATA                  FILE_LIST_DIRECTORY
+       FILE_WRITE_DATA                 FILE_ADD_FILE
+       FILE_APPEND_DATA                FILE_ADD_SUBDIRECTORY
+       FILE_CREATE_PIPE_INSTANCE       FILE_READ_EA
+       FILE_WRITE_EA                   FILE_EXECUTE
+       FILE_TRAVERSE                   FILE_DELETE_CHILD
+       FILE_READ_ATTRIBUTES            FILE_WRITE_ATTRIBUTES
+       FILE_ALL_ACCESS                 FILE_GENERIC_READ
+       FILE_GENERIC_WRITE              FILE_GENERIC_EXECUTE
+
+       FILE_ATTRIBUTE_ARCHIVE          FILE_ATTRIBUTE_COMPRESSED
+       FILE_ATTRIBUTE_HIDDEN           FILE_ATTRIBUTE_NORMAL
+       FILE_ATTRIBUTE_OFFLINE          FILE_ATTRIBUTE_READONLY
+       FILE_ATTRIBUTE_SYSTEM           FILE_ATTRIBUTE_TEMPORARY
+
+       FILE_FLAG_BACKUP_SEMANTICS      FILE_FLAG_DELETE_ON_CLOSE
+       FILE_FLAG_NO_BUFFERING          FILE_FLAG_OVERLAPPED
+       FILE_FLAG_POSIX_SEMANTICS       FILE_FLAG_RANDOM_ACCESS
+       FILE_FLAG_SEQUENTIAL_SCAN       FILE_FLAG_WRITE_THROUGH
+
+       FILE_SHARE_DELETE       FILE_SHARE_READ         FILE_SHARE_WRITE
+
+       FILE_TYPE_CHAR          FILE_TYPE_DISK          FILE_TYPE_PIPE
+       FILE_TYPE_UNKNOWN
+
+       FS_CASE_IS_PRESERVED            FS_CASE_SENSITIVE
+       FS_UNICODE_STORED_ON_DISK       FS_PERSISTENT_ACLS 
+       FS_FILE_COMPRESSION             FS_VOL_IS_COMPRESSED
+
+       HANDLE_FLAG_INHERIT             HANDLE_FLAG_PROTECT_FROM_CLOSE
+
+       IOCTL_STORAGE_CHECK_VERIFY      IOCTL_STORAGE_MEDIA_REMOVAL
+       IOCTL_STORAGE_EJECT_MEDIA       IOCTL_STORAGE_LOAD_MEDIA
+       IOCTL_STORAGE_RESERVE           IOCTL_STORAGE_RELEASE
+       IOCTL_STORAGE_FIND_NEW_DEVICES  IOCTL_STORAGE_GET_MEDIA_TYPES
+
+       IOCTL_DISK_GET_DRIVE_GEOMETRY   IOCTL_DISK_GET_PARTITION_INFO
+       IOCTL_DISK_SET_PARTITION_INFO   IOCTL_DISK_GET_DRIVE_LAYOUT
+       IOCTL_DISK_SET_DRIVE_LAYOUT     IOCTL_DISK_VERIFY
+       IOCTL_DISK_FORMAT_TRACKS        IOCTL_DISK_REASSIGN_BLOCKS
+       IOCTL_DISK_PERFORMANCE          IOCTL_DISK_IS_WRITABLE
+       IOCTL_DISK_LOGGING              IOCTL_DISK_FORMAT_TRACKS_EX
+       IOCTL_DISK_HISTOGRAM_STRUCTURE  IOCTL_DISK_HISTOGRAM_DATA
+       IOCTL_DISK_HISTOGRAM_RESET      IOCTL_DISK_REQUEST_STRUCTURE
+       IOCTL_DISK_REQUEST_DATA
+
+       GENERIC_ALL                     GENERIC_EXECUTE
+       GENERIC_READ                    GENERIC_WRITE
+
+       Unknown                 F5_1Pt2_512             F3_1Pt44_512
+       F3_2Pt88_512            F3_20Pt8_512            F3_720_512
+       F5_360_512              F5_320_512              F5_320_1024
+       F5_180_512              F5_160_512              RemovableMedia
+       FixedMedia              F3_120M_512
+
+       MOVEFILE_COPY_ALLOWED           MOVEFILE_DELAY_UNTIL_REBOOT
+       MOVEFILE_REPLACE_EXISTING       MOVEFILE_WRITE_THROUGH
+
+       SECURITY_ANONYMOUS              SECURITY_CONTEXT_TRACKING
+       SECURITY_DELEGATION             SECURITY_EFFECTIVE_ONLY
+       SECURITY_IDENTIFICATION         SECURITY_IMPERSONATION
+       SECURITY_SQOS_PRESENT
+
+       SEM_FAILCRITICALERRORS          SEM_NOGPFAULTERRORBOX
+       SEM_NOALIGNMENTFAULTEXCEPT      SEM_NOOPENFILEERRORBOX
+
+       PARTITION_ENTRY_UNUSED          PARTITION_FAT_12
+       PARTITION_XENIX_1               PARTITION_XENIX_2
+       PARTITION_FAT_16                PARTITION_EXTENDED
+       PARTITION_HUGE                  PARTITION_IFS
+       PARTITION_FAT32                 PARTITION_FAT32_XINT13
+       PARTITION_XINT13                PARTITION_XINT13_EXTENDED
+       PARTITION_PREP                  PARTITION_UNIX
+       VALID_NTFT                      PARTITION_NTFT
+
+Comments, additions, and bug reports are welcomed.  Please address
+technical questions that are not full bug reports to one of the Usenet
+newsgroups comp.lang.perl.modules or comp.lang.perl.moderated.
+
+Tye McQueen, tye@metronet.com, http://www.metronet.com/~tye/.
diff --git a/win32/ext/Win32API/File/buffers.h b/win32/ext/Win32API/File/buffers.h
new file mode 100644 (file)
index 0000000..2ae74e6
--- /dev/null
@@ -0,0 +1,423 @@
+/* buffers.h -- Version 1.11 */
+
+/* The following abbreviations are used at start of parameter names
+ * to indicate the type of data:
+ *     s       string (char * or WCHAR *) [PV]
+ *     sw      wide string (WCHAR *) [PV]
+ *     p       pointer (usually to some structure) [PV]
+ *     a       array (packed array as in C) (usually of some structure) [PV]
+ *                 called a "vector" or "vect" in some places.
+ *     n       generic number [IV, UV, or NV]
+ *     iv      signed integral value [IV]
+ *     u       unsigned integral value [UV]
+ *     d       floating-point number (double) [NV]
+ *     b       boolean (bool) [IV]
+ *     c       count of items [UV]
+ *     l       length (in bytes) [UV]
+ *     lw      length in WCHARs [UV]
+ *     h       a handle [IV]
+ *     r       record (structure) [PV]
+ *     sv      Perl scalar (s, i, u, d, n, or rv) [SV]
+ *     rv      Perl reference (usually to scalar) [RV]
+ *     hv      reference to Perl hash [HV]
+ *     av      reference to Perl array [AV]
+ *     cv      Perl code reference [PVCV]
+ *
+ * Unusual combined types:
+ *     pp      single pointer (to non-Perl data) packed into string [PV]
+ *     pap     vector of pointers (to non-Perl data) packed into string [PV]
+ *
+ * Whether a parameter is for input data, output data, or both is usually
+ * not reflected by the data type prefix.  In cases where this is not
+ * obvious nor reflected in the variable name proper, you can use
+ * the following in front of the data type prefix:
+ *     i       an input parameter given to API (usually omitted)
+ *     o       an Output parameter taken from API
+ *     io      Input given to API then overwritten with Output taken from API
+ */
+
+/* Buffer arguments are usually followed by an argument (or two) specifying
+ * their size and/or returning the size of data written.  The size can be
+ * measured in bytes ["lSize"] or in characters [for (char *) buffers such as
+ * for *A() routines, these sizes are also called "lSize", but are called
+ * "lwSize" for (WCHAR *) buffers, UNICODE strings, such as for *W() routines].
+ *
+ * Before calling the actual C function, you must make sure the Perl variable
+ * actually has a big enough buffer allocated, and, if the user didn't want
+ * to specify a buffer size, set the buffer size to be correct.  This is what
+ * the grow_*() macros are for.  They also handle special meanings of the
+ * buffer size argument [described below].
+ *
+ * Once the actual C function returns, you must set the Perl variable to know
+ * the size of the written data.  This is what the trunc_*() macros are for.
+ *
+ * The size sometimes does and sometimes doesn't include the trailing '\0'
+ * [or L'\0'], so we always add or substract 1 in the appropriate places so
+ * we don't care about this detail.
+ *
+ * A call may  1) request a pointer to the buffer size which means that
+ * the buffer size will be overwritten with the size of the data written;
+ * 2) have an extra argument which is a pointer to the place to write the
+ * size of the written data;  3) provide the size of the written data in
+ * the function's return value;  4) format the data so that the length
+ * can be determined by examining the data [such as with '\0'-terminated
+ * strings];  or  5) write fixed-length data [usually sizeof(STRUCT)].
+ * This obviously determines what you should use in the trunc_*() macro
+ # to specify the size of the output value.
+ *
+ * The user can pass in an empty list reference, C<[]>, to indicate C<NULL>
+ * for the pointer to the buffer which means that they don't want that data.
+ *
+ * The user can pass in C<[]> or C<0> to indicate that they don't care about
+ * the buffer size [we aren't programming in C here, after all] and just try
+ * to get the data.  This will work if either the buffer already alloated for
+ * the SV [scalar value] is large enough to hold the data or the API provides
+ * an easy way to determine the required size [and the XS code uses it].
+ *
+ * If the user passes in a numeric value for a buffer size, then the XS
+ * code makes sure that the buffer is at least large enough to hold a value
+ * of that size and then passes in how large the buffer is.  So the buffer
+ * size passed to the API call is the larger of the size requested by the
+ * user and the size of the buffer aleady allocated to the SV.
+ *
+ * The user can also pass in a string consisting of a leading "=" followed
+ * by digits for a buffer size.  This means just use the size specified after
+ * the equals sign, even if the allocated buffer is larger.  The XS code will
+ * still allocate a large enough buffer before the first call.
+ *
+ * If the function is nice enough to tell us that a buffer was too small
+ * [usually via ERROR_MORE_DATA] _and_ how large the buffer needs to be,
+ * then the XS code should enlarge the buffer(s) and repeat the call [once].
+ * This resizing is _not_ done for buffers whose size was specified with a
+ * leading "=".
+ *
+ * Only grow_buf() and perhaps trunc_buf() can be used in a typemap file.
+ * The other macros would be used in the parameter declarations or INPUT:
+ * section [grow_*()], the INIT: section [init_*()], or the OUTPUT: section
+ * [trunc_*()].
+ *
+ * Buffer arguments should be initialied with C<= NO_INIT> [or C<= NULL;>].
+ *
+ * See also the F<typemap> file.  C<oDWORD>, for example, is for an output-
+ * only parameter of type C<DWORD> and you should simply C<#define> it to be
+ * C<DWORD>.  In F<typemap>, C<oDWORD> is treated differently than C<DWORD>
+ * in two ways.
+ *
+ * First, if C<undef> is passed in, a C<DWORD> could generate a warning
+ * when it gets converted to 0 while C<oDWORD> will never generate such a
+ * warning for C<undef>.  This first difference doesn't apply if specific
+ * initialization is specified for the variable, as in C<= init_buf_l($var);>.
+ * In particular, the init_*() macros also convert C<undef> to 0 without
+ * ever producing a warning.
+ *
+ * Second, passing in a read-only SV for a C<oDWORD> parameter will generate
+ * a fatal error on output when we try to update the SV.  For C<DWORD>, we
+ * won't update a read-only SV since passing in a literal constant for a
+ * buffer size is a useful thing to do even though it prevents us from
+ * returning the size of data written via that SV.  Since we should use a
+ * trunc_*() macro to output the actual data, the user should be able to
+ * determine the size of data written based on the size of the scalar we
+ * output anyway.
+ *
+ * This second difference doesn't apply unless the paremter is listed in
+ * the OUTPUT: section without specific output instructions.  We define
+ * no macros for outputing buffer length parameters so be careful to use
+ * C<oDWORD> [for example] for them if and only if they are output-only.
+ *
+ * Note that C<oDWORD> is the same as C<DWORD> in that, if a defined value
+ * is passed in, it is used [and can generate a warning if the value is
+ * "not numeric"].  So although C<oDWORD> is for output-only parameters,
+ * we still initialize the C variable before calling the API.  This is good
+ * in case the parameter isn't always strictly output-only due to upgrades,
+ * bugs, etc.
+ *
+ * Here is a made-up example that shows several cases:
+ *
+ * # Actual GetDataW() returns length of data written to ioswName, not bool.
+ * bool
+ * GetDataW( ioswName, ilwName, oswText, iolwText, opJunk, opRec, ilRec, olRec )
+ *     WCHAR * ioswName        = NO_INIT
+ *     DWORD   ilwName         = NO_INIT
+ *     WCHAR * oswText         = NO_INIT
+ *     DWORD   &iolwText       = init_buf_l($arg);
+ *     void *  opJunk          = NO_INIT
+ *     BYTE *  opRec           = NO_INIT
+ *     DWORD   ilRec           = init_buf_l($arg);
+ *     oDWORD  &olRec
+ * PREINIT:
+ *     DWORD   olwName;
+ * INIT:
+ *     grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );
+ *     grow_buf_lw( oswText,ST(2), iolwText,ST(3) );
+ *     grow_buf_typ( opJunk,ST(4),void *, LONG_STRUCT_TYPEDEF );
+ *     grow_buf_l( opRec,ST(5),BYTE *, ilRec,ST(6) );
+ * CODE:
+ *     olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,
+ *                        (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );
+ *     if(  0 == olwName  &&  ERROR_MORE_DATA == GetLastError()
+ *      &&  ( autosize(ST(1)) || autosize(ST(3)) || autosize(ST(6)) )  ) {
+ *         if(  autosize(ST(1))  )
+ *             grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );
+ *         if(  autosize(ST(3))  )
+ *             grow_buf_lw( oswText,ST(2), iolwText,ST(3) );
+ *         if(  autosize(ST(6))  )
+ *             grow_buf_l( opRec,ST(5),BYTE *, iolRec,ST(6) );
+ *         olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,
+ *                            (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );
+ *     }
+ *     RETVAL=  0 != olwName;
+ * OUTPUT:
+ *     RETVAL
+ *     ioswName        trunc_buf_lw( RETVAL, ioswName,ST(0), olwName );
+ *     oswText         trunc_buf_lw( RETVAL, oswText,ST(2), iolwText );
+ *     iolwText
+ *     opJunk          trunc_buf_typ(RETVAL,opJunk,ST(4),LONG_STRUCT_TYPEDEF);
+ *     opRec           trunc_buf_l( RETVAL, opRec,ST(5), olRec );
+ *     olRec
+ *
+ * The above example would be more complex and less efficient if we used
+ * C<DWORD * iolwText> in place of C<DWORD  &iolwText>.  The only possible
+ * advantage would be that C<NULL> would be passed in for C<iolwText> if
+ * _both_ C<$oswText> and C<$iolwText> were specified as C<[]>.  The *_pl*()
+ * macros are defined [and C<DWORD *> specified in F<typemap>] so we can
+ * handle those cases but it is usually better to use the *_l*() macros
+ * instead by specifying C<&> instead of C<*>.  Using C<&> instead of C<*>
+ * is usually better when dealing with scalars, even if they aren't buffer
+ * sizes.  But you must use C<*> if it is important for that parameter to
+ * be able to pass C<NULL> to the underlying API.
+ *
+ * In Win32API::, we try to use C<*> for buffer sizes of optional buffers
+ * and C<&> for buffer sizes of required buffers.
+ *
+ * For parameters that are pointers to things other than buffers or buffer
+ * sizes, we use C<*> for "important" parameters [so that using C<[]>
+ * generates an error rather than fetching the value and just throwing it
+ * away], and for optional parameters [in case specifying C<NULL> is or
+ * becomes important].  Otherwise we use C<&> [for "unimportant" but
+ * required parameters] so the user can specify C<[]> if they don't care
+ * about it.  The output handle of an "open" routine is "important".
+ */
+
+#ifndef Debug
+# define       Debug(list)     /*Nothing*/
+#endif
+
+/*#ifndef CAST
+ *# ifdef __cplusplus
+ *#  define   CAST(type,expr)  static_cast<type>(expr)
+ *# else*/
+#  define   CAST(type,expr)    (type)(expr)
+/*# endif
+ *#endif*/
+
+/* Is an argument C<[]>, meaning we should pass C<NULL>? */
+#define null_arg(sv)   (  SvROK(sv)  &&  SVt_PVAV == SvTYPE(SvRV(sv))  \
+                          &&  -1 == av_len((AV*)SvRV(sv))  )
+
+#define PV_or_null(sv) ( null_arg(sv) ? NULL : SvPV(sv,PL_na) )
+
+/* Minimum buffer size to use when no buffer existed: */
+#define MIN_GROW_SIZE  128
+
+#ifdef Debug
+/* Used in Debug() messages to show which macro call is involved: */
+#define string(arg) #arg
+#endif
+
+/* Simplify using SvGROW() for byte-sized buffers: */
+#define lSvGROW(sv,n)  SvGROW( sv, 0==(n) ? MIN_GROW_SIZE : (n)+1 )
+
+/* Simplify using SvGROW() for WCHAR-sized buffers: */
+#define lwSvGROW(sv,n) CAST( WCHAR *,          \
+       SvGROW( sv, sizeof(WCHAR)*( 0==(n) ? MIN_GROW_SIZE : (n)+1 ) ) )
+
+/* Whether the buffer size we got lets us change what buffer size we use: */
+#define autosize(sv)   (!(  SvOK(sv)  &&  ! SvROK(sv)          \
+                        &&  SvPV(sv,PL_na)  &&  '=' == *SvPV(sv,PL_na)  ))
+
+/* Get the IV/UV for a parameter that might be C<[]> or C<undef>: */
+#define optIV(sv)      ( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvIV(sv) )
+#define optUV(sv)      ( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvUV(sv) )
+
+/* Allocate temporary storage that will automatically be freed later: */
+#ifndef TempAlloc      /* Can be C<#define>d to be C<_alloca>, for example */
+# define TempAlloc( size )     sv_grow( sv_newmortal(), size )
+#endif
+
+/* Initialize a buffer size argument of type (DWORD *): */
+#define init_buf_pl( plSize, svSize, tpSize )          STMT_START {    \
+       if(  null_arg(svSize)  )                                        \
+           plSize= NULL;                                               \
+       else {                                                          \
+           STRLEN n_a;                                                 \
+           *( plSize= CAST( tpSize, TempAlloc(sizeof(*plSize)) ) )=    \
+             autosize(svSize) ? optUV(svSize)                          \
+               : strtoul( 1+SvPV(svSize,n_a), NULL, 10 );              \
+       } } STMT_END
+/* In INPUT section put ": init_buf_pl($var,$arg,$type);" after var name. */
+
+/* Initialize a buffer size argument of type DWORD: */
+#define init_buf_l( svSize )                                           \
+       (  null_arg(svSize) ? 0 : autosize(svSize) ? optUV(svSize)      \
+          : strtoul( 1+SvPV(svSize,PL_na), NULL, 10 )  )
+/* In INPUT section put "= init_buf_l($arg);" after variable name. */
+
+/* Lengths in WCHARs are initialized the same as lengths in bytes: */
+#define init_buf_plw   init_buf_pl
+#define init_buf_lw    init_buf_l
+
+/* grow_buf_pl() and grow_buf_plw() are included so you can define
+ * parameters of type C<DWORD *>, for example.  In practice, it is
+ * usually better to define such parameters as "DWORD &". */
+
+/* Grow a buffer where we have a pointer to its size in bytes: */
+#define        grow_buf_pl( sBuf,svBuf,tpBuf, plSize,svSize,tpSize ) STMT_START { \
+       Debug(("grow_buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\
+         string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)?     \
+         SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),  \
+         plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));        \
+       if(  null_arg(svBuf)  ) {                                       \
+           sBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  NULL == plSize  )                                      \
+               *( plSize= CAST(tpSize,TempAlloc(sizeof(*plSize))) )= 0;\
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           sBuf= CAST( tpBuf, lSvGROW( svBuf, *plSize ) );             \
+           if(  autosize(svSize)  )   *plSize= SvLEN(svBuf) - 1;       \
+           Debug(("more buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\
+             string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)? \
+             SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),\
+             plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));    \
+       } } STMT_END
+
+/* Grow a buffer where we have a pointer to its size in WCHARs: */
+#define        grow_buf_plw( sBuf,svBuf, plwSize,svSize,tpSize ) STMT_START {  \
+       if(  null_arg(svBuf)  ) {                                       \
+           sBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  NULL == plwSize  )                                     \
+               *( plwSize= CAST(tpSize,TempAlloc(sizeof(*plwSize))) )= 0;\
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           sBuf= lwSvGROW( svBuf, *plwSize );                          \
+           if(  autosize(svSize)  )                                    \
+               *plwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;               \
+       } } STMT_END
+
+/* Grow a buffer where we have its size in bytes: */
+#define        grow_buf_l( sBuf,svBuf,tpBuf, lSize,svSize )    STMT_START {    \
+       if(  null_arg(svBuf)  ) {                                       \
+           sBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           sBuf= CAST( tpBuf, lSvGROW( svBuf, lSize ) );               \
+           if(  autosize(svSize)  )   lSize= SvLEN(svBuf) - 1;         \
+       } } STMT_END
+
+/* Grow a buffer where we have its size in WCHARs: */
+#define        grow_buf_lw( swBuf,svBuf, lwSize,svSize )       STMT_START {    \
+       if(  null_arg(svBuf)  ) {                                       \
+           swBuf= NULL;                                                \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           swBuf= lwSvGROW( svBuf, lwSize );                           \
+           if(  autosize(svSize)  )                                    \
+               lwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;                 \
+       } } STMT_END
+
+/* Grow a buffer that contains the declared fixed data type: */
+#define        grow_buf( pBuf,svBuf, tpBuf )                   STMT_START {    \
+       if(  null_arg(svBuf)  ) {                                       \
+           pBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf) ) );        \
+       } } STMT_END
+
+/* Grow a buffer that contains a fixed data type other than that declared: */
+#define        grow_buf_typ( pBuf,svBuf,tpBuf, Type )          STMT_START {    \
+       if(  null_arg(svBuf)  ) {                                       \
+           pBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(Type) ) ); \
+       } } STMT_END
+
+/* Grow a buffer that contains a list of items of the declared data type: */
+#define        grow_vect( pBuf,svBuf,tpBuf, cItems )           STMT_START {    \
+       if(  null_arg(svBuf)  ) {                                       \
+           pBuf= NULL;                                                 \
+       } else {                                                        \
+           STRLEN n_a;                                                 \
+           if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);             \
+           (void) SvPV_force( svBuf, n_a );                            \
+           pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf)*cItems ) ); \
+       } } STMT_END
+
+/* If call succeeded, set data length to returned length (in bytes): */
+#define        trunc_buf_l( bOkay, sBuf,svBuf, lSize )         STMT_START {    \
+       if(  bOkay  &&  NULL != sBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, lSize );                                  \
+       } } STMT_END
+
+/* Same as above except we have a poitner to the returned length: */
+#define        trunc_buf_pl( bOkay, sBuf,svBuf, plSize )                       \
+       trunc_buf_l( bOkay, sBuf,svBuf, *plSize )
+
+/* If call succeeded, set data length to returned length (in WCHARs): */
+#define        trunc_buf_lw( bOkay, sBuf,svBuf, lwSize )       STMT_START {    \
+       if(  bOkay  &&  NULL != sBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, (lwSize)*sizeof(WCHAR) );                 \
+       } } STMT_END
+
+/* Same as above except we have a poitner to the returned length: */
+#define        trunc_buf_plw( bOkay, swBuf,svBuf, plwSize )                    \
+       trunc_buf_lw( bOkay, swBuf,svBuf, *plwSize )
+
+/* Set data length for a buffer that contains the declared fixed data type: */
+#define        trunc_buf( bOkay, pBuf,svBuf )                  STMT_START {    \
+       if(  bOkay  &&  NULL != pBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, sizeof(*pBuf) );                          \
+       } } STMT_END
+
+/* Set data length for a buffer that contains some other fixed data type: */
+#define        trunc_buf_typ( bOkay, pBuf,svBuf, Type )        STMT_START {    \
+       if(  bOkay  &&  NULL != pBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, sizeof(Type) );                           \
+       } } STMT_END
+
+/* Set length for buffer that contains list of items of the declared type: */
+#define        trunc_vect( bOkay, pBuf,svBuf, cItems )         STMT_START {    \
+       if(  bOkay  &&  NULL != pBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, sizeof(*pBuf)*cItems );                   \
+       } } STMT_END
+
+/* Set data length for a buffer where a '\0'-terminate string was stored: */
+#define        trunc_buf_z( bOkay, sBuf,svBuf )                STMT_START {    \
+       if(  bOkay  &&  NULL != sBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, strlen(sBuf) );                           \
+       } } STMT_END
+
+/* Set data length for a buffer where a L'\0'-terminate string was stored: */
+#define        trunc_buf_zw( bOkay, sBuf,svBuf )               STMT_START {    \
+       if(  bOkay  &&  NULL != sBuf  ) {                               \
+           SvPOK_only( svBuf );                                        \
+           SvCUR_set( svBuf, wcslen(sBuf)*sizeof(WCHAR) );             \
+       } } STMT_END
diff --git a/win32/ext/Win32API/File/cFile.h b/win32/ext/Win32API/File/cFile.h
new file mode 100644 (file)
index 0000000..23e7ed8
--- /dev/null
@@ -0,0 +1 @@
+/* Would contain C code to generate Perl constants if not using cFile.pc */
diff --git a/win32/ext/Win32API/File/cFile.pc b/win32/ext/Win32API/File/cFile.pc
new file mode 100644 (file)
index 0000000..da00f41
--- /dev/null
@@ -0,0 +1,165 @@
+# Generated by cFile_pc.cxx.
+# Package Win32API::File with options:
+#    CPLUSPLUS => q[1]
+#    IFDEF => q[!/[a-z\d]/]
+#    IMPORT_LIST => [q[/._/], q[!/[a-z]/], q[:MEDIA_TYPE]]
+#    WRITE_PERL => q[1]
+# Perl files eval'd:
+#    File.pm => last if /^\s*(bootstrap|XSLoader::load)\b/
+# C files included:
+#    File.xs => last if m#/[/*]\s*CONSTS_DEFINED\b|^\s*MODULE\b#
+sub CREATE_ALWAYS () { 2 }
+sub CREATE_NEW () { 1 }
+sub DDD_EXACT_MATCH_ON_REMOVE () { 4 }
+sub DDD_RAW_TARGET_PATH () { 1 }
+sub DDD_REMOVE_DEFINITION () { 2 }
+sub DRIVE_CDROM () { 5 }
+sub DRIVE_FIXED () { 3 }
+sub DRIVE_NO_ROOT_DIR () { 1 }
+sub DRIVE_RAMDISK () { 6 }
+sub DRIVE_REMOTE () { 4 }
+sub DRIVE_REMOVABLE () { 2 }
+sub DRIVE_UNKNOWN () { 0 }
+sub F3_120M_512 () { 13 }
+sub F3_1Pt44_512 () { 2 }
+sub F3_20Pt8_512 () { 4 }
+sub F3_2Pt88_512 () { 3 }
+sub F3_720_512 () { 5 }
+sub F5_160_512 () { 10 }
+sub F5_180_512 () { 9 }
+sub F5_1Pt2_512 () { 1 }
+sub F5_320_1024 () { 8 }
+sub F5_320_512 () { 7 }
+sub F5_360_512 () { 6 }
+sub FILE_ADD_FILE () { 2 }
+sub FILE_ADD_SUBDIRECTORY () { 4 }
+sub FILE_ALL_ACCESS () { 2032127 }
+sub FILE_APPEND_DATA () { 4 }
+sub FILE_ATTRIBUTE_ARCHIVE () { 32 }
+sub FILE_ATTRIBUTE_COMPRESSED () { 2048 }
+sub FILE_ATTRIBUTE_DEVICE () { 0x00000040 }
+sub FILE_ATTRIBUTE_DIRECTORY () { 0x00000010 }
+sub FILE_ATTRIBUTE_ENCRYPTED () { 0x00004000 }
+sub FILE_ATTRIBUTE_HIDDEN () { 2 }
+sub FILE_ATTRIBUTE_NORMAL () { 128 }
+sub FILE_ATTRIBUTE_NOT_CONTENT_INDEXED () { 0x00002000 }
+sub FILE_ATTRIBUTE_OFFLINE () { 4096 }
+sub FILE_ATTRIBUTE_READONLY () { 1 }
+sub FILE_ATTRIBUTE_REPARSE_POINT () { 0x00000400 }
+sub FILE_ATTRIBUTE_SPARSE_FILE () { 0x00000200 }
+sub FILE_ATTRIBUTE_SYSTEM () { 4 }
+sub FILE_ATTRIBUTE_TEMPORARY () { 256 }
+sub FILE_BEGIN () { 0 }
+sub FILE_CREATE_PIPE_INSTANCE () { 4 }
+sub FILE_CURRENT () { 1 }
+sub FILE_DELETE_CHILD () { 64 }
+sub FILE_END () { 2 }
+sub FILE_EXECUTE () { 32 }
+sub FILE_FLAG_BACKUP_SEMANTICS () { 33554432 }
+sub FILE_FLAG_DELETE_ON_CLOSE () { 67108864 }
+sub FILE_FLAG_NO_BUFFERING () { 536870912 }
+sub FILE_FLAG_OPEN_REPARSE_POINT () { 0x200000 }
+sub FILE_FLAG_OVERLAPPED () { 1073741824 }
+sub FILE_FLAG_POSIX_SEMANTICS () { 16777216 }
+sub FILE_FLAG_RANDOM_ACCESS () { 268435456 }
+sub FILE_FLAG_SEQUENTIAL_SCAN () { 134217728 }
+sub FILE_FLAG_WRITE_THROUGH () { 0x80000000 }
+sub FILE_GENERIC_EXECUTE () { 1179808 }
+sub FILE_GENERIC_READ () { 1179785 }
+sub FILE_GENERIC_WRITE () { 1179926 }
+sub FILE_LIST_DIRECTORY () { 1 }
+sub FILE_READ_ATTRIBUTES () { 128 }
+sub FILE_READ_DATA () { 1 }
+sub FILE_READ_EA () { 8 }
+sub FILE_SHARE_DELETE () { 4 }
+sub FILE_SHARE_READ () { 1 }
+sub FILE_SHARE_WRITE () { 2 }
+sub FILE_TRAVERSE () { 32 }
+sub FILE_TYPE_CHAR () { 2 }
+sub FILE_TYPE_DISK () { 1 }
+sub FILE_TYPE_PIPE () { 3 }
+sub FILE_TYPE_UNKNOWN () { 0 }
+sub FILE_WRITE_ATTRIBUTES () { 256 }
+sub FILE_WRITE_DATA () { 2 }
+sub FILE_WRITE_EA () { 16 }
+sub FS_CASE_IS_PRESERVED () { 2 }
+sub FS_CASE_SENSITIVE () { 1 }
+sub FS_FILE_COMPRESSION () { 16 }
+sub FS_PERSISTENT_ACLS () { 8 }
+sub FS_UNICODE_STORED_ON_DISK () { 4 }
+sub FS_VOL_IS_COMPRESSED () { 32768 }
+sub FSCTL_SET_REPARSE_POINT () { (9 << 16 | 0 << 14 | 41 << 2 | 0) }
+sub FSCTL_GET_REPARSE_POINT () { (9 << 16 | 0 << 14 | 42 << 2 | 0) }
+sub FSCTL_DELETE_REPARSE_POINT () { (9 << 16 | 0 << 14 | 43 << 2 | 0) }
+sub FixedMedia () { 12 }
+sub GENERIC_ALL () { 268435456 }
+sub GENERIC_EXECUTE () { 536870912 }
+sub GENERIC_READ () { 0x80000000 }
+sub GENERIC_WRITE () { 1073741824 }
+sub HANDLE_FLAG_INHERIT () { 1 }
+sub HANDLE_FLAG_PROTECT_FROM_CLOSE () { 2 }
+sub INVALID_FILE_ATTRIBUTES () { 0xFFFFFFFF }
+sub INVALID_HANDLE_VALUE () { 0xffffffff }
+sub IOCTL_DISK_FORMAT_TRACKS () { 507928 }
+sub IOCTL_DISK_FORMAT_TRACKS_EX () { 507948 }
+sub IOCTL_DISK_GET_DRIVE_GEOMETRY () { 458752 }
+sub IOCTL_DISK_GET_DRIVE_LAYOUT () { 475148 }
+sub IOCTL_DISK_GET_MEDIA_TYPES () { 461824 }
+sub IOCTL_DISK_GET_PARTITION_INFO () { 475140 }
+sub IOCTL_DISK_HISTOGRAM_DATA () { 458804 }
+sub IOCTL_DISK_HISTOGRAM_RESET () { 458808 }
+sub IOCTL_DISK_HISTOGRAM_STRUCTURE () { 458800 }
+sub IOCTL_DISK_IS_WRITABLE () { 458788 }
+sub IOCTL_DISK_LOGGING () { 458792 }
+sub IOCTL_DISK_PERFORMANCE () { 458784 }
+sub IOCTL_DISK_REASSIGN_BLOCKS () { 507932 }
+sub IOCTL_DISK_REQUEST_DATA () { 458816 }
+sub IOCTL_DISK_REQUEST_STRUCTURE () { 458812 }
+sub IOCTL_DISK_SET_DRIVE_LAYOUT () { 507920 }
+sub IOCTL_DISK_SET_PARTITION_INFO () { 507912 }
+sub IOCTL_DISK_VERIFY () { 458772 }
+sub IOCTL_STORAGE_CHECK_VERIFY () { 2967552 }
+sub IOCTL_STORAGE_EJECT_MEDIA () { 2967560 }
+sub IOCTL_STORAGE_FIND_NEW_DEVICES () { 2967576 }
+sub IOCTL_STORAGE_GET_MEDIA_TYPES () { 2952192 }
+sub IOCTL_STORAGE_LOAD_MEDIA () { 2967564 }
+sub IOCTL_STORAGE_MEDIA_REMOVAL () { 2967556 }
+sub IOCTL_STORAGE_RELEASE () { 2967572 }
+sub IOCTL_STORAGE_RESERVE () { 2967568 }
+sub MOVEFILE_COPY_ALLOWED () { 2 }
+sub MOVEFILE_DELAY_UNTIL_REBOOT () { 4 }
+sub MOVEFILE_REPLACE_EXISTING () { 1 }
+sub MOVEFILE_WRITE_THROUGH () { 8 }
+sub OPEN_ALWAYS () { 4 }
+sub OPEN_EXISTING () { 3 }
+sub PARTITION_ENTRY_UNUSED () { 0 }
+sub PARTITION_EXTENDED () { 5 }
+sub PARTITION_FAT32 () { 11 }
+sub PARTITION_FAT32_XINT13 () { 12 }
+sub PARTITION_FAT_12 () { 1 }
+sub PARTITION_FAT_16 () { 4 }
+sub PARTITION_HUGE () { 6 }
+sub PARTITION_IFS () { 7 }
+sub PARTITION_NTFT () { 128 }
+sub PARTITION_PREP () { 65 }
+sub PARTITION_UNIX () { 99 }
+sub PARTITION_XENIX_1 () { 2 }
+sub PARTITION_XENIX_2 () { 3 }
+sub PARTITION_XINT13 () { 14 }
+sub PARTITION_XINT13_EXTENDED () { 15 }
+sub RemovableMedia () { 11 }
+sub SECURITY_ANONYMOUS () { 0 }
+sub SECURITY_CONTEXT_TRACKING () { 262144 }
+sub SECURITY_DELEGATION () { 196608 }
+sub SECURITY_EFFECTIVE_ONLY () { 524288 }
+sub SECURITY_IDENTIFICATION () { 65536 }
+sub SECURITY_IMPERSONATION () { 131072 }
+sub SECURITY_SQOS_PRESENT () { 1048576 }
+sub SEM_FAILCRITICALERRORS () { 1 }
+sub SEM_NOALIGNMENTFAULTEXCEPT () { 4 }
+sub SEM_NOGPFAULTERRORBOX () { 2 }
+sub SEM_NOOPENFILEERRORBOX () { 32768 }
+sub TRUNCATE_EXISTING () { 5 }
+sub Unknown () { 0 }
+sub VALID_NTFT () { 192 }
+1;
diff --git a/win32/ext/Win32API/File/const2perl.h b/win32/ext/Win32API/File/const2perl.h
new file mode 100644 (file)
index 0000000..dbd94c1
--- /dev/null
@@ -0,0 +1,193 @@
+/* const2perl.h -- For converting C constants into Perl constant subs
+ *     (usually via XS code but can just write Perl code to stdout). */
+
+
+/* #ifndef _INCLUDE_CONST2PERL_H
+ * #define _INCLUDE_CONST2PERL_H 1 */
+
+#ifndef CONST2WRITE_PERL       /* Default is "const to .xs": */
+
+# define newconst( sName, sFmt, xValue, newSV )        \
+               newCONSTSUB( mHvStash, sName, newSV )
+
+# define noconst( const )      av_push( mAvExportFail, newSVpv(#const,0) )
+
+# define setuv(u)      do {                            \
+       mpSvNew= newSViv(0); sv_setuv(mpSvNew,u);       \
+    } while( 0 )
+
+#else
+
+/* #ifdef __cplusplus
+ * # undef printf
+ * # undef fprintf
+ * # undef stderr
+ * # define stderr (&_iob[2])
+ * # undef iobuf
+ * # undef malloc
+ * #endif */
+
+# include <stdio.h>    /* Probably already included, but shouldn't hurt */
+# include <errno.h>    /* Possibly already included, but shouldn't hurt */
+
+# define newconst( sName, sFmt, xValue, newSV )        \
+               printf( "sub %s () { " sFmt " }\n", sName, xValue )
+
+# define noconst( const )      printf( "push @EXPORT_FAIL, '%s';\n", #const )
+
+# define setuv(u)      /* Nothing */
+
+# ifndef IVdf
+#  define IVdf "ld"
+# endif
+# ifndef UVuf
+#  define UVuf "lu"
+# endif
+# ifndef UVxf
+#  define UVxf "lX"
+# endif
+# ifndef NV_DIG
+#  define NV_DIG 15
+# endif
+
+static char *
+escquote( const char *sValue )
+{
+    Size_t lLen= 1+2*strlen(sValue);
+    char *sEscaped= (char *) malloc( lLen );
+    char *sNext= sEscaped;
+    if(  NULL == sEscaped  ) {
+       fprintf( stderr, "Can't allocate %"UVuf"-byte buffer (errno=%d)\n",
+         U_V(lLen), _errno );
+       exit( 1 );
+    }
+    while(  '\0' != *sValue  ) {
+       switch(  *sValue  ) {
+        case '\'':
+        case '\\':
+           *(sNext++)= '\\';
+       }
+       *(sNext++)= *(sValue++);
+    }
+    *sNext= *sValue;
+    return( sEscaped );
+}
+
+#endif
+
+
+#ifdef __cplusplus
+
+class _const2perl {
+ public:
+    char msBuf[64];    /* Must fit sprintf of longest NV */
+#ifndef CONST2WRITE_PERL
+    HV *mHvStash;
+    AV *mAvExportFail;
+    SV *mpSvNew;
+    _const2perl::_const2perl( char *sModName ) {
+       mHvStash= gv_stashpv( sModName, TRUE );
+       SV **pSv= hv_fetch( mHvStash, "EXPORT_FAIL", 11, TRUE );
+       GV *gv;
+       char *sVarName= (char *) malloc( 15+strlen(sModName) );
+       strcpy( sVarName, sModName );
+       strcat( sVarName, "::EXPORT_FAIL" );
+       gv= gv_fetchpv( sVarName, 1, SVt_PVAV );
+       mAvExportFail= GvAVn( gv );
+    }
+#else
+    _const2perl::_const2perl( char *sModName ) {
+       ;       /* Nothing to do */
+    }
+#endif /* CONST2WRITE_PERL */
+    void mkconst( char *sName, unsigned long uValue ) {
+       setuv(uValue);
+       newconst( sName, "0x%"UVxf, uValue, mpSvNew );
+    }
+    void mkconst( char *sName, unsigned int uValue ) {
+       setuv(uValue);
+       newconst( sName, "0x%"UVxf, uValue, mpSvNew );
+    }
+    void mkconst( char *sName, unsigned short uValue ) {
+       setuv(uValue);
+       newconst( sName, "0x%"UVxf, uValue, mpSvNew );
+    }
+    void mkconst( char *sName, long iValue ) {
+       newconst( sName, "%"IVdf, iValue, newSViv(iValue) );
+    }
+    void mkconst( char *sName, int iValue ) {
+       newconst( sName, "%"IVdf, iValue, newSViv(iValue) );
+    }
+    void mkconst( char *sName, short iValue ) {
+       newconst( sName, "%"IVdf, iValue, newSViv(iValue) );
+    }
+    void mkconst( char *sName, double nValue ) {
+       newconst( sName, "%s",
+         Gconvert(nValue,NV_DIG,0,msBuf), newSVnv(nValue) );
+    }
+    void mkconst( char *sName, char *sValue ) {
+       newconst( sName, "'%s'", escquote(sValue), newSVpv(sValue,0) );
+    }
+    void mkconst( char *sName, const void *pValue ) {
+       setuv((UV)pValue);
+       newconst( sName, "0x%"UVxf, (UV)(pValue), mpSvNew );
+    }
+/*#ifdef HAS_QUAD
+ * HAS_QUAD only means pack/unpack deal with them, not that SVs can.
+ *    void mkconst( char *sName, Quad_t *qValue ) {
+ *     newconst( sName, "0x%"QVxf, qValue, newSVqv(qValue) );
+ *    }
+ *#endif / * HAS_QUAD */
+};
+
+#define START_CONSTS( sModName )       _const2perl const2( sModName );
+#define const2perl( const )            const2.mkconst( #const, const )
+
+#else  /* __cplusplus */
+
+# ifndef CONST2WRITE_PERL
+#  define START_CONSTS( sModName )                                     \
+           HV *mHvStash= gv_stashpv( sModName, TRUE );                 \
+           AV *mAvExportFail;                                          \
+           SV *mpSvNew;                                                \
+           { char *sVarName= malloc( 15+strlen(sModName) );            \
+             GV *gv;                                                   \
+               strcpy( sVarName, sModName );                           \
+               strcat( sVarName, "::EXPORT_FAIL" );                    \
+               gv= gv_fetchpv( sVarName, 1, SVt_PVAV );                \
+               mAvExportFail= GvAVn( gv );                             \
+           }
+# else
+#  define START_CONSTS( sModName )     /* Nothing */
+# endif
+
+#define const2perl( const )    do {                                    \
+       if(  const < 0  ) {                                             \
+           newconst( #const, "%"IVdf, const, newSViv((IV)const) );     \
+       } else {                                                        \
+           setuv( (UV)const );                                         \
+           newconst( #const, "0x%"UVxf, const, mpSvNew );              \
+       }                                                               \
+    } while( 0 )
+
+#endif /* __cplusplus */
+
+
+//Example use:
+//#include <const2perl.h>
+//  {
+//    START_CONSTS( "Package::Name" )  /* No ";" */
+//#ifdef $const
+//    const2perl( $const );
+//#else
+//    noconst( $const );
+//#endif
+//  }
+// sub ? { my( $sConstName )= @_;
+//    return $sConstName;      # "#ifdef $sConstName"
+//    return FALSE;            # Same as above
+//    return "HAS_QUAD";       # "#ifdef HAS_QUAD"
+//    return "#if 5.04 <= VERSION";
+//    return "#if 0";
+//    return 1;                # No #ifdef
+/* #endif / * _INCLUDE_CONST2PERL_H */
diff --git a/win32/ext/Win32API/File/ppport.h b/win32/ext/Win32API/File/ppport.h
new file mode 100644 (file)
index 0000000..6814757
--- /dev/null
@@ -0,0 +1,283 @@
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+/* Perl/Pollution/Portability Version 1.0007etm */
+
+/* Copyright (C) 1999, Kenneth Albanowski. This code may be used and
+   distributed under the same license as any version of Perl. */
+   
+/* For the latest version of this code, please retreive the Devel::PPPort
+   module from CPAN, contact the author at <kjahds@kjahds.com>, or check
+   with the Perl maintainers. */
+   
+/* If you needed to customize this file for your project, please mention
+   your changes, and visible alter the version number. */
+
+
+/*
+   In order for a Perl extension module to be as portable as possible
+   across differing versions of Perl itself, certain steps need to be taken.
+   Including this header is the first major one, then using dTHR is all the
+   appropriate places and using a PL_ prefix to refer to global Perl
+   variables is the second.
+*/
+
+
+/* If you use one of a few functions that were not present in earlier
+   versions of Perl, please add a define before the inclusion of ppport.h
+   for a static include, or use the GLOBAL request in a single module to
+   produce a global definition that can be referenced from the other
+   modules.
+   
+   Function:            Static define:           Extern define:
+   newCONSTSUB()        NEED_newCONSTSUB         NEED_newCONSTSUB_GLOBAL
+
+*/
+
+/* To verify whether ppport.h is needed for your module, and whether any
+   special defines should be used, ppport.h can be run through Perl to check
+   your source code. Simply say:
+   
+       perl -x ppport.h *.c *.h *.xs foo/*.c [etc]
+   
+   The result will be a list of patches suggesting changes that should at
+   least be acceptable, if not necessarily the most efficient solution, or a
+   fix for all possible problems. It won't catch where dTHR is needed, and
+   doesn't attempt to account for global macro or function definitions,
+   nested includes, typemaps, etc.
+   
+   In order to test for the need of dTHR, please try your module under a
+   recent version of Perl that has threading compiled-in.
+*/ 
+
+
+/*
+#!/usr/bin/perl
+@ARGV = ("*.xs") if !@ARGV;
+%badmacros = %funcs = %macros = (); $replace = 0;
+foreach (<DATA>) {
+       $funcs{$1} = 1 if /Provide:\s+(\S+)/;
+       $macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/;
+       $replace = $1 if /Replace:\s+(\d+)/;
+       $badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/;
+       $badmacros{$1}=$2 if /Replace (\S+) with (\S+)/;
+}
+foreach $filename (map(glob($_),@ARGV)) {
+       unless (open(IN, "<$filename")) {
+               warn "Unable to read from $file: $!\n";
+               next;
+       }
+       print "Scanning $filename...\n";
+       $c = ""; while (<IN>) { $c .= $_; } close(IN);
+       $need_include = 0; %add_func = (); $changes = 0;
+       $has_include = ($c =~ /#.*include.*ppport/m);
+
+       foreach $func (keys %funcs) {
+               if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) {
+                       if ($c !~ /\b$func\b/m) {
+                               print "If $func isn't needed, you don't need to request it.\n" if
+                               $changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m);
+                       } else {
+                               print "Uses $func\n";
+                               $need_include = 1;
+                       }
+               } else {
+                       if ($c =~ /\b$func\b/m) {
+                               $add_func{$func} =1 ;
+                               print "Uses $func\n";
+                               $need_include = 1;
+                       }
+               }
+       }
+
+       if (not $need_include) {
+               foreach $macro (keys %macros) {
+                       if ($c =~ /\b$macro\b/m) {
+                               print "Uses $macro\n";
+                               $need_include = 1;
+                       }
+               }
+       }
+
+       foreach $badmacro (keys %badmacros) {
+               if ($c =~ /\b$badmacro\b/m) {
+                       $changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm);
+                       print "Uses $badmacros{$badmacro} (instead of $badmacro)\n";
+                       $need_include = 1;
+               }
+       }
+       
+       if (scalar(keys %add_func) or $need_include != $has_include) {
+               if (!$has_include) {
+                       $inc = join('',map("#define NEED_$_\n", sort keys %add_func)).
+                              "#include \"ppport.h\"\n";
+                       $c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m;
+               } elsif (keys %add_func) {
+                       $inc = join('',map("#define NEED_$_\n", sort keys %add_func));
+                       $c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m;
+               }
+               if (!$need_include) {
+                       print "Doesn't seem to need ppport.h.\n";
+                       $c =~ s/^.*#.*include.*ppport.*\n//m;
+               }
+               $changes++;
+       }
+       
+       if ($changes) {
+               open(OUT,">/tmp/ppport.h.$$");
+               print OUT $c;
+               close(OUT);
+               open(DIFF, "diff -u $filename /tmp/ppport.h.$$|");
+               while (<DIFF>) { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; }
+               close(DIFF);
+               unlink("/tmp/ppport.h.$$");
+       } else {
+               print "Looks OK\n";
+       }
+}
+__DATA__
+*/
+
+#ifndef PERL_REVISION
+#   ifndef __PATCHLEVEL_H_INCLUDED__
+#       include "patchlevel.h"
+#   endif
+#   ifndef PERL_REVISION
+#      define PERL_REVISION    (5)
+        /* Replace: 1 */
+#       define PERL_VERSION    PATCHLEVEL
+#       define PERL_SUBVERSION SUBVERSION
+        /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+        /* Replace: 0 */
+#   endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+#ifndef ERRSV
+#      define ERRSV perl_get_sv("@",FALSE)
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+#      define PL_sv_undef      sv_undef
+#      define PL_sv_yes        sv_yes
+#      define PL_sv_no         sv_no
+#      define PL_na            na
+#      define PL_stdingv       stdingv
+#      define PL_hints         hints
+#      define PL_curcop        curcop
+#      define PL_curstash      curstash
+#      define PL_copline       copline
+#      define PL_Sv            Sv
+/* Replace: 0 */
+#endif
+
+#ifndef dTHR
+#  ifdef WIN32
+#      define dTHR extern int Perl___notused
+#  else
+#      define dTHR extern int errno
+#  endif
+#endif
+
+#ifndef boolSV
+#      define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+#ifndef gv_stashpvn
+#      define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
+#endif
+
+#ifndef newSVpvn
+#      define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
+#endif
+
+#ifndef newRV_inc
+/* Replace: 1 */
+#      define newRV_inc(sv) newRV(sv)
+/* Replace: 0 */
+#endif
+
+#ifndef newRV_noinc
+#  ifdef __GNUC__
+#    define newRV_noinc(sv)               \
+      ({                                  \
+          SV *nsv = (SV*)newRV(sv);       \
+          SvREFCNT_dec(sv);               \
+          nsv;                            \
+      })
+#  else
+#    if defined(CRIPPLED_CC) || defined(USE_THREADS)
+static SV * newRV_noinc (SV * sv)
+{
+          SV *nsv = (SV*)newRV(sv);       
+          SvREFCNT_dec(sv);               
+          return nsv;                     
+}
+#    else
+#      define newRV_noinc(sv)    \
+        ((PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
+#    endif
+#  endif
+#endif
+
+/* Provide: newCONSTSUB */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
+
+#if defined(NEED_newCONSTSUB)
+static
+#else
+extern void newCONSTSUB _((HV * stash, char * name, SV *sv));
+#endif
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+void
+newCONSTSUB( HV *stash, char *name, SV *sv )
+{
+       U32 oldhints = PL_hints;
+       HV *old_cop_stash = PL_curcop->cop_stash;
+       HV *old_curstash = PL_curstash;
+       line_t oldline = PL_curcop->cop_line;
+       PL_curcop->cop_line = PL_copline;
+
+       PL_hints &= ~HINT_BLOCK_SCOPE;
+       if (stash)
+               PL_curstash = PL_curcop->cop_stash = stash;
+
+       newSUB(
+
+#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
+     /* before 5.003_22 */
+               start_subparse(),
+#else
+#  if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
+     /* 5.003_22 */
+               start_subparse(0),
+#  else
+     /* 5.003_23  onwards */
+               start_subparse(FALSE, 0),
+#  endif
+#endif
+
+               newSVOP(OP_CONST, 0, newSVpv(name,0)),
+               newSVOP(OP_CONST, 0, &PL_sv_no),   /* SvPV(&PL_sv_no) == "" -- GMB */
+               newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+       );
+
+       PL_hints = oldhints;
+       PL_curcop->cop_stash = old_cop_stash;
+       PL_curstash = old_curstash;
+       PL_curcop->cop_line = oldline;
+}
+#endif
+
+#endif /* newCONSTSUB */
+
+
+#endif /* _P_P_PORTABILITY_H_ */
diff --git a/win32/ext/Win32API/File/t/file.t b/win32/ext/Win32API/File/t/file.t
new file mode 100644 (file)
index 0000000..739b773
--- /dev/null
@@ -0,0 +1,402 @@
+#!/usr/bin/perl -w
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+BEGIN { $|= 1; print "1..267\n"; }
+END {print "not ok 1\n" unless $loaded;}
+use Win32API::File qw(:ALL);
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+$test= 1;
+
+use strict qw(subs);
+
+$temp= $ENV{"TMP"};
+$temp= $ENV{"TEMP"}    unless -d $temp;
+$temp= "C:/Temp"       unless -d $temp;
+$temp= "."             unless -d $temp;
+$dir= "W32ApiF.tmp";
+
+$ENV{WINDIR} = $ENV{SYSTEMROOT} if not exists $ENV{WINDIR};
+
+chdir( $temp )
+  or  die "# Can't cd to temp directory, $temp: $!\n";
+
+if(  -d $dir  ) {
+    print "# deleting $temp\\$dir\\*\n" if glob "$dir/*";
+
+    for (glob "$dir/*") {
+       chmod 0777, $_;
+       unlink $_;
+    }
+    rmdir $dir or die "Could not rmdir $dir: $!";
+}
+mkdir( $dir, 0777 )
+  or  die "# Can't create temp dir, $temp/$dir: $!\n";
+print "# chdir $temp\\$dir\n";
+chdir( $dir )
+  or  die "# Can't cd to my dir, $temp/$dir: $!\n";
+
+$h1= createFile( "ReadOnly.txt", "r", { Attributes=>"r" } );
+$ok=  ! $h1  &&  fileLastError() =~ /not find the file?/i;
+$ok or print "# ","".fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 2
+if(  ! $ok  ) {   CloseHandle($h1);   unlink("ReadOnly.txt");   }
+
+$ok= $h1= createFile( "ReadOnly.txt", "wcn", { Attributes=>"r" } );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 3
+
+$ok= WriteFile( $h1, "Original text\n", 0, [], [] );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 4
+
+$h2= createFile( "ReadOnly.txt", "rcn" );
+$ok= ! $h2  &&  fileLastError() =~ /file exists?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 5
+if(  ! $ok  ) {   CloseHandle($h2);   }
+
+$h2= createFile( "ReadOnly.txt", "rwke" );
+$ok= ! $h2  &&  fileLastError() =~ /access is denied?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 6
+if(  ! $ok  ) {   CloseHandle($h2);   }
+
+$ok= $h2= createFile( "ReadOnly.txt", "r" );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 7
+
+$ok= SetFilePointer( $h1, length("Original"), [], FILE_BEGIN );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 8
+
+$ok= WriteFile( $h1, "ly was other text\n", 0, $len, [] )
+  &&  $len == length("ly was other text\n");
+$ok or print "# <$len> should be <",
+  length("ly was other text\n"),">: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 9
+
+$ok= ReadFile( $h2, $text, 80, $len, [] )
+ &&  $len == length($text);
+$ok or print "# <$len> should be <",length($text),
+  ">: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 10
+
+$ok= $text eq "Originally was other text\n";
+if( !$ok ) {
+    $text =~ s/\r/\\r/g;   $text =~ s/\n/\\n/g;
+    print "# <$text> should be <Originally was other text\\n>.\n";
+}
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 11
+
+$ok= CloseHandle($h2);
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 12
+
+$ok= ! ReadFile( $h2, $text, 80, $len, [] )
+ &&  fileLastError() =~ /handle is invalid?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 13
+
+CloseHandle($h1);
+
+$ok= $h1= createFile( "CanWrite.txt", "rw", FILE_SHARE_WRITE,
+             { Create=>CREATE_ALWAYS } );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 14
+
+$ok= WriteFile( $h1, "Just this and not this", 10, [], [] );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 15
+
+$ok= $h2= createFile( "CanWrite.txt", "wk", { Share=>"rw" } );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 16
+
+$ok= OsFHandleOpen( "APP", $h2, "wat" );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 17
+
+$ok=  $h2 == GetOsFHandle( "APP" );
+$ok or print "# $h2 != ",GetOsFHandle("APP"),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 18
+
+{   my $save= select(APP);   $|= 1;  select($save);   }
+$ok= print APP "is enough\n";
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 19
+
+SetFilePointer($h1, 0, [], FILE_BEGIN) if $^O eq 'cygwin';
+
+$ok= ReadFile( $h1, $text, 0, [], [] );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 20
+
+$ok=  $text eq "is enough\r\n";
+if( !$ok ) {
+    $text =~ s/\r/\\r/g;
+    $text =~ s/\n/\\n/g;
+    print "# <$text> should be <is enough\\r\\n>\n";
+}
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 21
+
+$skip = "";
+if ($^O eq 'cygwin') {
+    $ok = 1;
+    $skip = " # skip cygwin can delete open files";
+}
+else {
+    unlink("CanWrite.txt");
+    $ok= -e "CanWrite.txt" &&  $! =~ /permission denied/i;
+    $ok or print "# $!\n";
+}
+print $ok ? "" : "not ", "ok ", ++$test, "$skip\n"; # ok 22
+
+close(APP);            # Also does C<CloseHandle($h2)>
+## CloseHandle( $h2 );
+CloseHandle( $h1 );
+
+$ok= ! DeleteFile( "ReadOnly.txt" )
+ &&  fileLastError() =~ /access is denied?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 23
+
+$ok= ! CopyFile( "ReadOnly.txt", "CanWrite.txt", 1 )
+ &&  fileLastError() =~ /file exists?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 24
+
+$ok= ! CopyFile( "CanWrite.txt", "ReadOnly.txt", 0 )
+ &&  fileLastError() =~ /access is denied?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 25
+
+$ok= ! MoveFile( "NoSuchFile", "NoSuchDest" )
+ &&  fileLastError() =~ /not find the file/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 26
+
+$ok= ! MoveFileEx( "NoSuchFile", "NoSuchDest", 0 )
+ &&  fileLastError() =~ /not find the file/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 27
+
+$ok= ! MoveFile( "ReadOnly.txt", "CanWrite.txt" )
+ &&  fileLastError() =~ /file already exists?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 28
+
+$ok= ! MoveFileEx( "ReadOnly.txt", "CanWrite.txt", 0 )
+ &&  fileLastError() =~ /file already exists?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 29
+
+$ok= CopyFile( "ReadOnly.txt", "ReadOnly.cp", 1 )
+ &&  CopyFile( "CanWrite.txt", "CanWrite.cp", 1 );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 30
+
+$ok= ! MoveFileEx( "CanWrite.txt", "ReadOnly.cp", MOVEFILE_REPLACE_EXISTING )
+ &&  fileLastError() =~ /access is denied?|cannot create/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 31
+
+$ok= MoveFileEx( "ReadOnly.cp", "CanWrite.cp", MOVEFILE_REPLACE_EXISTING );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 32
+
+$ok= MoveFile( "CanWrite.cp", "Moved.cp" );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 33
+
+$ok= ! unlink( "ReadOnly.cp" )
+ &&  $! =~ /no such file/i
+ &&  ! unlink( "CanWrite.cp" )
+ &&  $! =~ /no such file/i;
+$ok or print "# $!\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 34
+
+$ok= ! DeleteFile( "Moved.cp" )
+ &&  fileLastError() =~ /access is denied?/i;
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 35
+
+system( "attrib -r Moved.cp" );
+
+$ok= DeleteFile( "Moved.cp" );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 36
+
+$new= SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX;
+$old= SetErrorMode( $new );
+$renew= SetErrorMode( $old );
+$reold= SetErrorMode( $old );
+
+$ok= $old == $reold;
+$ok or print "# $old != $reold: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 37
+
+$ok= ($renew&$new) == $new;
+$ok or print "# $new != $renew: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 38
+
+$ok= @drives= getLogicalDrives();
+$ok && print "# @drives\n";
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 39
+
+$ok=  $drives[0] !~ /^[ab]/  ||  DRIVE_REMOVABLE == GetDriveType($drives[0]);
+$ok or print "# ",DRIVE_REMOVABLE," != ",GetDriveType($drives[0]),
+  ": ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 40
+
+$drive= substr( $ENV{WINDIR}, 0, 3 );
+
+$ok= 1 == grep /^\Q$drive\E/i, @drives;
+$ok or print "# No $drive found in list of drives.\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 41
+
+$ok= DRIVE_FIXED == GetDriveType( $drive );
+$ok or print
+  "# ",DRIVE_FIXED," != ",GetDriveType($drive),": ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 42
+
+$ok=  GetVolumeInformation( $drive, $vol, 64, $ser, $max, $flag, $fs, 16 );
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 43
+$vol= $ser= $max= $flag= $fs= "";      # Prevent warnings.
+
+chop($drive);
+$ok= QueryDosDevice( $drive, $dev, 80 );
+$ok or print "# $drive: ",fileLastError(),"\n";
+if( $ok ) {
+    ( $text= $dev ) =~ s/\0/\\0/g;
+    print "# $drive => $text\n";
+}
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 44
+
+$bits= GetLogicalDrives();
+$let= 25;
+$bit= 1<<$let;
+while(  $bit & $bits  ) {
+    $let--;
+    $bit >>= 1;
+}
+$let= pack( "C", $let + unpack("C","A") ) . ":";
+print "# Querying undefined $let.\n";
+
+$ok= DefineDosDevice( 0, $let, $ENV{WINDIR} );
+$ok or print "# $let,$ENV{WINDIR}: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 45
+
+$ok=  -s $let."/Win.ini"  ==  -s $ENV{WINDIR}."/Win.ini";
+$ok or print "# ", -s $let."/Win.ini", " vs. ",
+  -s $ENV{WINDIR}."/Win.ini", ": ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 46
+
+$ok= DefineDosDevice( DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
+                     $let, $ENV{WINDIR} );
+$ok or print "# $let,$ENV{WINDIR}: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 47
+
+$ok= ! -f $let."/Win.ini"
+  &&  $! =~ /no such file/i;
+$ok or print "# $!\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 48
+
+$ok= DefineDosDevice( DDD_RAW_TARGET_PATH, $let, $dev );
+if( !$ok  ) {
+    ( $text= $dev ) =~ s/\0/\\0/g;
+    print "# $let,$text: ",fileLastError(),"\n";
+}
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 49
+
+$ok= -f $let.substr($ENV{WINDIR},3)."/win.ini";
+$ok or print "# ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 50
+
+$ok= DefineDosDevice( DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE
+                    |DDD_RAW_TARGET_PATH, $let, $dev );
+$ok or print "# $let,$dev: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 51
+
+my $path = $ENV{WINDIR};
+my $attrs = GetFileAttributes( $path );
+$ok= $attrs != INVALID_FILE_ATTRIBUTES;
+$ok or print "# $path gave invalid attribute value, attrs=$attrs: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 52
+
+$ok= ($attrs & FILE_ATTRIBUTE_DIRECTORY);
+$ok or print "# $path not a directory, attrs=$attrs: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 53
+
+$path .= "/win.ini";
+$attrs = GetFileAttributes( $path );
+$ok= $attrs != INVALID_FILE_ATTRIBUTES;
+$ok or print "# $path gave invalid attribute value, attrs=$attrs: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 54
+
+$ok= !($attrs & FILE_ATTRIBUTE_DIRECTORY);
+$ok or print "# $path is a directory, attrs=$attrs: ",fileLastError(),"\n";
+print $ok ? "" : "not ", "ok ", ++$test, "\n"; # ok 55
+
+#      DefineDosDevice
+#      GetFileType
+#      GetVolumeInformation
+#      QueryDosDevice
+#Add a drive letter that points to our temp directory
+#Add a drive letter that points to the drive our directory is in
+
+#winnt.t:
+# get first drive letters and use to test disk and storage IOCTLs
+# "//./PhysicalDrive0"
+#      DeviceIoControl
+
+my %consts;
+my @consts= @Win32API::File::EXPORT_OK;
+@consts{@consts}= @consts;
+
+my( @noargs, %noargs )= qw(
+  attrLetsToBits fileLastError getLogicalDrives GetLogicalDrives );
+@noargs{@noargs}= @noargs;
+
+foreach $func ( @{$Win32API::File::EXPORT_TAGS{Func}} ) {
+    delete $consts{$func};
+    if(  defined( $noargs{$func} )  ) {
+       $ok=  ! eval("$func(0,0)")  &&  $@ =~ /(::|\s)_?${func}A?[(:\s]/;
+    } else {
+       $ok=  ! eval("$func()")  &&  $@ =~ /(::|\s)_?${func}A?[(:\s]/;
+    }
+    $ok or print "# $func: $@\n";
+    print $ok ? "" : "not ", "ok ", ++$test, "\n";
+}
+
+foreach $func ( @{$Win32API::File::EXPORT_TAGS{FuncA}},
+                @{$Win32API::File::EXPORT_TAGS{FuncW}} ) {
+    $ok=  ! eval("$func()")  &&  $@ =~ /::_?${func}\(/;
+    delete $consts{$func};
+    $ok or print "# $func: $@\n";
+    print $ok ? "" : "not ", "ok ", ++$test, "\n";
+}
+
+foreach $const ( keys(%consts) ) {
+    $ok= eval("my \$x= $const(); 1");
+    $ok or print "# Constant $const: $@\n";
+    print $ok ? "" : "not ", "ok ", ++$test, "\n";
+}
+
+chdir( $temp );
+if (-e "$dir/ReadOnly.txt") {
+    chmod 0777, "$dir/ReadOnly.txt";
+    unlink "$dir/ReadOnly.txt";
+}
+unlink "$dir/CanWrite.txt" if -e "$dir/CanWrite.txt";
+rmdir $dir;
+
+__END__
diff --git a/win32/ext/Win32API/File/t/tie.t b/win32/ext/Win32API/File/t/tie.t
new file mode 100644 (file)
index 0000000..ec2f7c2
--- /dev/null
@@ -0,0 +1,79 @@
+#!perl
+# vim:syntax=perl:
+
+BEGIN { $|= 1; print "1..10\n"; }
+END   { print "not ok 1\n" unless $main::loaded; }
+
+use strict;
+use warnings;
+use Win32API::File qw(:ALL);
+use IO::File;
+
+$main::loaded = 1;
+
+print "ok 1\n";
+
+unlink "foo.txt";
+
+my $fh = new Win32API::File "+> foo.txt"
+       or die fileLastError();
+
+my $tell = tell $fh;
+print "# tell \$fh == '$tell'\n";
+print "not " unless
+       tell $fh == 0;
+print "ok 2\n";
+
+my $text = "some text\n";
+
+print "not " unless
+       print $fh $text;
+print "ok 3\n";
+
+$tell = tell $fh;
+print "# after printing 'some text\\n', tell is: '$tell'\n";
+print "not " unless
+       $tell == length($text) + 1;
+print "ok 4\n";
+
+print "not " unless
+       seek($fh, 0, 0) == 0;
+print "ok 5\n";
+
+print "not " unless
+       not eof $fh;
+print "ok 6\n";
+
+my $readline = <$fh>;
+
+my $pretty_readline = $readline;
+$pretty_readline =~ s/\r/\\r/g;  $pretty_readline =~ s/\n/\\n/g;  
+print "# read line is '$pretty_readline'\n";
+
+print "not " unless
+       $readline eq "some text\r\n";
+print "ok 7\n";
+
+print "not " unless
+       eof $fh;
+print "ok 8\n";
+
+print "not " unless
+       close $fh;
+print "ok 9\n";
+
+# Test out binmode (should be only LF with print, no CR).
+
+$fh = new Win32API::File "+> foo.txt"
+       or die fileLastError();
+binmode $fh;
+print $fh "hello there\n";
+seek $fh, 0, 0;
+
+print "not " unless
+       <$fh> eq "hello there\n";
+print "ok 10\n";
+
+close $fh;
+
+unlink "foo.txt";
diff --git a/win32/ext/Win32API/File/typemap b/win32/ext/Win32API/File/typemap
new file mode 100644 (file)
index 0000000..d595765
--- /dev/null
@@ -0,0 +1,140 @@
+BOOL                   T_BOOL
+LONG                   T_IV
+HKEY                   T_UV
+HANDLE                 T_UV
+DWORD                  T_UV
+oDWORD                 O_UV
+UINT                   T_UV
+REGSAM                 T_UV
+SECURITY_INFORMATION   T_UV
+char *                 T_BUF
+WCHAR *                        T_BUF
+BYTE *                 T_BUF
+void *                 T_BUF
+ValEntA *              T_BUF
+ValEntW *              T_BUF
+SECURITY_DESCRIPTOR *  T_BUF
+SECURITY_ATTRIBUTES *  T_BUF
+LPOVERLAPPED           T_BUF
+LONG *                 T_IVBUF
+DWORD *                        T_UVBUF
+LPDWORD                        T_UVBUF
+oDWORD *               O_UVBUF
+HKEY *                 T_UVBUFP
+oHKEY *                        O_UVBUFP
+FILETIME *             T_SBUF
+
+#############################################################################
+INPUT
+T_BOOL
+       $var= null_arg($arg)||!SvTRUE($arg) ? ($type)0 : looks_like_number($arg) ? ($type)SvIV($arg) : ($type)1
+T_BUF
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           $var= ($type) SvPV( $arg, PL_na )
+T_SBUF
+       grow_buf( $var,$arg, $type )
+T_IV
+       $var= null_arg($arg) ? ($type)0 : INT2PTR($type,SvIV($arg))
+T_UV
+       $var= null_arg($arg) ? ($type)0 : INT2PTR($type,SvUV($arg))
+O_IV
+       $var= optIV($arg)
+O_UV
+       $var= optUV($arg)
+T_IVBUF
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )= SvIV($arg)
+T_UVBUF
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )= SvUV($arg)
+O_IVBUF
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )=
+             SvOK($arg) ? SvIV($arg) : 0;
+O_UVBUF
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )=
+             SvOK($arg) ? SvUV($arg) : 0;
+T_IVBUFP
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )= (void *)SvIV($arg)
+T_UVBUFP
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )= (void *)SvUV($arg)
+O_IVBUFP
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )=
+             SvOK($arg) ? (void *)SvIV($arg) : 0;
+O_UVBUFP
+       if(  null_arg($arg)  )
+           $var= NULL;
+       else
+           *( $var= ($type) TempAlloc( sizeof(*($var)) ) )=
+             SvOK($arg) ? (void *)SvUV($arg) : 0;
+
+#############################################################################
+OUTPUT
+T_BOOL
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  ) {
+           if(  $var  ) {
+               sv_setiv( $arg, (IV)$var );
+           } else {
+               sv_setsv( $arg, &PL_sv_no );
+           }
+       }
+T_BUF
+       ;
+T_SBUF
+       trunc_buf( RETVAL, $var,$arg );
+T_IV
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setiv( $arg, PTR2IV($var) );
+T_UV
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setuv( $arg, PTR2UV($var) );
+O_IV
+       if(  ! null_arg($arg)  )
+           sv_setiv( $arg, PTR2IV($var) );
+O_UV
+       if(  ! null_arg($arg)  )
+           sv_setuv( $arg, PTR2UV($var) );
+T_IVBUF
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setiv( $arg, (IV)*($var) );
+T_UVBUF
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setuv( $arg, (UV)*($var) );
+O_IVBUF
+       if(  ! null_arg($arg)  )
+           sv_setiv( $arg, (IV)*($var) );
+O_UVBUF
+       if(  ! null_arg($arg)  )
+           sv_setuv( $arg, (UV)*($var) );
+T_IVBUFP
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setiv( $arg, (IV)*($var) );
+T_UVBUFP
+       if(  ! null_arg($arg)  &&  ! SvREADONLY($arg)  )
+           sv_setuv( $arg, (UV)*($var) );
+O_IVBUFP
+       if(  ! null_arg($arg)  )
+           sv_setiv( $arg, (IV)*($var) );
+O_UVBUFP
+       if(  ! null_arg($arg)  )
+           sv_setuv( $arg, (UV)*($var) );
index 39fcc28..556a8a0 100644 (file)
@@ -892,7 +892,8 @@ DYNAMIC_EXT = Socket IO Fcntl Opcode SDBM_File POSIX attrs Thread B re \
                Data/Dumper Devel/Peek ByteLoader Devel/DProf File/Glob \
                Sys/Hostname Storable Filter/Util/Call Encode \
                Digest/MD5 Digest/SHA PerlIO/scalar MIME/Base64 Time/HiRes \
-               Unicode/Normalize Math/BigInt/FastCalc Compress/Zlib Win32
+               Unicode/Normalize Math/BigInt/FastCalc Compress/Zlib Win32 \
+               Win32API/File
 STATIC_EXT     = 
 NONXS_EXT      = Errno
 
@@ -1332,6 +1333,8 @@ distclean: realclean
        -del /f $(LIBDIR)\Unicode\Normalize.pm
        -del /f $(LIBDIR)\Math\BigInt\FastCalc.pm
        -del /f $(LIBDIR)\Win32.pm
+       -del /f $(LIBDIR)\Win32API\File.pm
+       -del /f $(LIBDIR)\Win32API\File\cFile.pc
        -if exist $(LIBDIR)\B rmdir /s /q $(LIBDIR)\B
        -if exist $(LIBDIR)\Compress rmdir /s /q $(LIBDIR)\Compress
        -if exist $(LIBDIR)\Data rmdir /s /q $(LIBDIR)\Data
@@ -1347,6 +1350,7 @@ distclean: realclean
        -if exist $(LIBDIR)\Sys rmdir /s /q $(LIBDIR)\Sys
        -if exist $(LIBDIR)\threads rmdir /s /q $(LIBDIR)\threads
        -if exist $(LIBDIR)\XS rmdir /s /q $(LIBDIR)\XS
+       -if exist $(LIBDIR)\Win32API rmdir /s /q $(LIBDIR)\Win32API
        -cd $(PODDIR) && del /f *.html *.bat checkpods \
            perlaix.pod perlamiga.pod perlapollo.pod perlbeos.pod \
            perlbs2000.pod perlce.pod perlcn.pod perlcygwin.pod \