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