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
23namespace NWindows {
24namespace NFile {
25
26#if defined(_WIN32) && !defined(UNDER_CE)
27bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink);
28#endif
29
30struct CReparseShortInfo
31{
32  unsigned Offset;
33  unsigned Size;
34
35  bool Parse(const Byte *p, size_t size);
36};
37
38struct CReparseAttr
39{
40  UInt32 Tag;
41  UInt32 Flags;
42  UString SubsName;
43  UString PrintName;
44
45  CReparseAttr(): Tag(0), Flags(0) {}
46  bool Parse(const Byte *p, size_t size);
47
48  bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction
49  bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; }
50  bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; }
51  // bool IsVolume() const;
52
53  bool IsOkNamePair() const;
54  UString GetPath() const;
55};
56
57namespace NIO {
58
59bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);
60bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
61
62class CFileBase
63{
64protected:
65  HANDLE _handle;
66
67  bool Create(CFSTR path, DWORD desiredAccess,
68      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
69
70public:
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
79  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const
80  {
81    return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned);
82  }
83
84  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const
85  {
86    DWORD bytesReturned;
87    return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned);
88  }
89
90public:
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
97  CFileBase(): _handle(INVALID_HANDLE_VALUE) {};
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
110  bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const
111    { return BOOLToBool(GetFileInformationByHandle(_handle, info)); }
112
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
130struct my_DISK_GEOMETRY_EX
131{
132  DISK_GEOMETRY Geometry;
133  LARGE_INTEGER DiskSize;
134  BYTE Data[1];
135};
136#endif
137
138class CInFile: public CFileBase
139{
140  #ifdef SUPPORT_DEVICE_FILE
141
142  #ifndef UNDER_CE
143
144  bool GetGeometry(DISK_GEOMETRY *res) const
145    { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
146
147  bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const
148    { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); }
149
150  bool GetCdRomGeometry(DISK_GEOMETRY *res) const
151    { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }
152
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
163public:
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
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
183class COutFile: public CFileBase
184{
185public:
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