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