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 CReparseAttrCReparseAttr47 CReparseAttr(): Tag(0), Flags(0) {} 48 49 // Parse() 50 // returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK) 51 // returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK) 52 bool Parse(const Byte *p, size_t size, DWORD &errorCode); 53 IsMountPointCReparseAttr54 bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction IsSymLinkCReparseAttr55 bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } IsRelativeCReparseAttr56 bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } 57 // bool IsVolume() const; 58 59 bool IsOkNamePair() const; 60 UString GetPath() const; 61 }; 62 63 namespace NIO { 64 65 bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); 66 bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); 67 68 class CFileBase 69 { 70 protected: 71 HANDLE _handle; 72 73 bool Create(CFSTR path, DWORD desiredAccess, 74 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); 75 76 public: 77 78 bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, 79 LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const 80 { 81 return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, 82 outBuffer, outSize, bytesReturned, overlapped)); 83 } 84 DeviceIoControlOut(DWORD controlCode,LPVOID outBuffer,DWORD outSize,LPDWORD bytesReturned)85 bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const 86 { 87 return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); 88 } 89 DeviceIoControlOut(DWORD controlCode,LPVOID outBuffer,DWORD outSize)90 bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const 91 { 92 DWORD bytesReturned; 93 return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); 94 } 95 96 public: 97 #ifdef SUPPORT_DEVICE_FILE 98 bool IsDeviceFile; 99 bool SizeDefined; 100 UInt64 Size; // it can be larger than real available size 101 #endif 102 CFileBase()103 CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; ~CFileBase()104 ~CFileBase() { Close(); } 105 106 bool Close() throw(); 107 108 bool GetPosition(UInt64 &position) const throw(); 109 bool GetLength(UInt64 &length) const throw(); 110 111 bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); 112 bool Seek(UInt64 position, UInt64 &newPosition) const throw(); 113 bool SeekToBegin() const throw(); 114 bool SeekToEnd(UInt64 &newPosition) const throw(); 115 GetFileInformation(BY_HANDLE_FILE_INFORMATION * info)116 bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const 117 { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } 118 GetFileInformation(CFSTR path,BY_HANDLE_FILE_INFORMATION * info)119 static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) 120 { 121 NIO::CFileBase file; 122 if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) 123 return false; 124 return file.GetFileInformation(info); 125 } 126 }; 127 128 #ifndef UNDER_CE 129 #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM 130 #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) 131 // #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) 132 133 // IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP 134 #define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) 135 136 struct my_DISK_GEOMETRY_EX 137 { 138 DISK_GEOMETRY Geometry; 139 LARGE_INTEGER DiskSize; 140 BYTE Data[1]; 141 }; 142 #endif 143 144 class CInFile: public CFileBase 145 { 146 #ifdef SUPPORT_DEVICE_FILE 147 148 #ifndef UNDER_CE 149 GetGeometry(DISK_GEOMETRY * res)150 bool GetGeometry(DISK_GEOMETRY *res) const 151 { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } 152 GetGeometryEx(my_DISK_GEOMETRY_EX * res)153 bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const 154 { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } 155 GetCdRomGeometry(DISK_GEOMETRY * res)156 bool GetCdRomGeometry(DISK_GEOMETRY *res) const 157 { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } 158 GetPartitionInfo(PARTITION_INFORMATION * res)159 bool GetPartitionInfo(PARTITION_INFORMATION *res) 160 { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } 161 162 #endif 163 164 void CorrectDeviceSize(); 165 void CalcDeviceSize(CFSTR name); 166 167 #endif 168 169 public: 170 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); 171 bool OpenShared(CFSTR fileName, bool shareForWrite); 172 bool Open(CFSTR fileName); 173 174 #ifndef UNDER_CE 175 OpenReparse(CFSTR fileName)176 bool OpenReparse(CFSTR fileName) 177 { 178 // 17.02 fix: to support Windows XP compatibility junctions: 179 // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ 180 return 181 Create(fileName, 0, 182 // Open(fileName, 183 FILE_SHARE_READ, OPEN_EXISTING, 184 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); 185 } 186 187 #endif 188 189 bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); 190 bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); 191 bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); 192 }; 193 194 class COutFile: public CFileBase 195 { 196 public: 197 bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); 198 bool Open(CFSTR fileName, DWORD creationDisposition); 199 bool Create(CFSTR fileName, bool createAlways); 200 bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); 201 202 bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); 203 bool SetMTime(const FILETIME *mTime) throw(); 204 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); 205 bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); 206 bool SetEndOfFile() throw(); 207 bool SetLength(UInt64 length) throw(); 208 }; 209 210 }}} 211 212 #endif 213