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