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 CReparseAttrCReparseAttr45 CReparseAttr(): Tag(0), Flags(0) {} 46 bool Parse(const Byte *p, size_t size); 47 IsMountPointCReparseAttr48 bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction IsSymLinkCReparseAttr49 bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } IsRelativeCReparseAttr50 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 DeviceIoControlOut(DWORD controlCode,LPVOID outBuffer,DWORD outSize,LPDWORD bytesReturned)79 bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const 80 { 81 return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); 82 } 83 DeviceIoControlOut(DWORD controlCode,LPVOID outBuffer,DWORD outSize)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 CFileBase()97 CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; ~CFileBase()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 GetFileInformation(BY_HANDLE_FILE_INFORMATION * info)110 bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const 111 { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } 112 GetFileInformation(CFSTR path,BY_HANDLE_FILE_INFORMATION * info)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 GetGeometry(DISK_GEOMETRY * res)144 bool GetGeometry(DISK_GEOMETRY *res) const 145 { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } 146 GetGeometryEx(my_DISK_GEOMETRY_EX * res)147 bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const 148 { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } 149 GetCdRomGeometry(DISK_GEOMETRY * res)150 bool GetCdRomGeometry(DISK_GEOMETRY *res) const 151 { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } 152 GetPartitionInfo(PARTITION_INFORMATION * res)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 OpenReparse(CFSTR fileName)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