Home | History | Annotate | Download | only in Windows
      1 // Windows/FileIO.h
      2 
      3 #ifndef __WINDOWS_FILE_IO_H
      4 #define __WINDOWS_FILE_IO_H
      5 
      6 #if defined(_WIN32) && !defined(UNDER_CE)
      7 #include <winioctl.h>
      8 #endif
      9 
     10 #include "../Common/MyString.h"
     11 #include "../Common/MyBuffer.h"
     12 
     13 #include "Defs.h"
     14 
     15 #define _my_IO_REPARSE_TAG_MOUNT_POINT  (0xA0000003L)
     16 #define _my_IO_REPARSE_TAG_SYMLINK      (0xA000000CL)
     17 
     18 #define _my_SYMLINK_FLAG_RELATIVE 1
     19 
     20 #define my_FSCTL_SET_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER
     21 #define my_FSCTL_GET_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)     // REPARSE_DATA_BUFFER
     22 
     23 namespace NWindows {
     24 namespace NFile {
     25 
     26 #if defined(_WIN32) && !defined(UNDER_CE)
     27 bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink);
     28 #endif
     29 
     30 struct CReparseShortInfo
     31 {
     32   unsigned Offset;
     33   unsigned Size;
     34 
     35   bool Parse(const Byte *p, size_t size);
     36 };
     37 
     38 struct CReparseAttr
     39 {
     40   UInt32 Tag;
     41   UInt32 Flags;
     42   UString SubsName;
     43   UString PrintName;
     44 
     45   CReparseAttr(): Tag(0), Flags(0) {}
     46   bool Parse(const Byte *p, size_t size);
     47 
     48   bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
     49   bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
     50   bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }
     51   // bool IsVolume() const;
     52 
     53   bool IsOkNamePair() const;
     54   UString GetPath() const;
     55 };
     56 
     57 namespace NIO {
     58 
     59 bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);
     60 bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
     61 
     62 class CFileBase
     63 {
     64 protected:
     65   HANDLE _handle;
     66 
     67   bool Create(CFSTR path, DWORD desiredAccess,
     68       DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
     69 
     70 public:
     71 
     72   bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,
     73       LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const
     74   {
     75     return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,
     76         outBuffer, outSize, bytesReturned, overlapped));
     77   }
     78 
     79   bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const
     80   {
     81     return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned);
     82   }
     83 
     84   bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const
     85   {
     86     DWORD bytesReturned;
     87     return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned);
     88   }
     89 
     90 public:
     91   #ifdef SUPPORT_DEVICE_FILE
     92   bool IsDeviceFile;
     93   bool SizeDefined;
     94   UInt64 Size; // it can be larger than real available size
     95   #endif
     96 
     97   CFileBase(): _handle(INVALID_HANDLE_VALUE) {};
     98   ~CFileBase() { Close(); }
     99 
    100   bool Close() throw();
    101 
    102   bool GetPosition(UInt64 &position) const throw();
    103   bool GetLength(UInt64 &length) const throw();
    104 
    105   bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw();
    106   bool Seek(UInt64 position, UInt64 &newPosition) const throw();
    107   bool SeekToBegin() const throw();
    108   bool SeekToEnd(UInt64 &newPosition) const throw();
    109 
    110   bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const
    111     { return BOOLToBool(GetFileInformationByHandle(_handle, info)); }
    112 
    113   static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info)
    114   {
    115     NIO::CFileBase file;
    116     if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS))
    117       return false;
    118     return file.GetFileInformation(info);
    119   }
    120 };
    121 
    122 #ifndef UNDER_CE
    123 #define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM
    124 #define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
    125 // #define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
    126 
    127 // IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP
    128 #define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX  CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)
    129 
    130 struct my_DISK_GEOMETRY_EX
    131 {
    132   DISK_GEOMETRY Geometry;
    133   LARGE_INTEGER DiskSize;
    134   BYTE Data[1];
    135 };
    136 #endif
    137 
    138 class CInFile: public CFileBase
    139 {
    140   #ifdef SUPPORT_DEVICE_FILE
    141 
    142   #ifndef UNDER_CE
    143 
    144   bool GetGeometry(DISK_GEOMETRY *res) const
    145     { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
    146 
    147   bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const
    148     { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); }
    149 
    150   bool GetCdRomGeometry(DISK_GEOMETRY *res) const
    151     { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
    152 
    153   bool GetPartitionInfo(PARTITION_INFORMATION *res)
    154     { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }
    155 
    156   #endif
    157 
    158   void CorrectDeviceSize();
    159   void CalcDeviceSize(CFSTR name);
    160 
    161   #endif
    162 
    163 public:
    164   bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
    165   bool OpenShared(CFSTR fileName, bool shareForWrite);
    166   bool Open(CFSTR fileName);
    167 
    168   #ifndef UNDER_CE
    169 
    170   bool OpenReparse(CFSTR fileName)
    171   {
    172     return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING,
    173         FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);
    174   }
    175 
    176   #endif
    177 
    178   bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw();
    179   bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw();
    180   bool Read(void *data, UInt32 size, UInt32 &processedSize) throw();
    181 };
    182 
    183 class COutFile: public CFileBase
    184 {
    185 public:
    186   bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
    187   bool Open(CFSTR fileName, DWORD creationDisposition);
    188   bool Create(CFSTR fileName, bool createAlways);
    189   bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes);
    190 
    191   bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
    192   bool SetMTime(const FILETIME *mTime) throw();
    193   bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();
    194   bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();
    195   bool SetEndOfFile() throw();
    196   bool SetLength(UInt64 length) throw();
    197 };
    198 
    199 }}}
    200 
    201 #endif
    202