|
1 // Windows/FileIO.cpp |
|
2 |
|
3 #include "StdAfx.h" |
|
4 |
|
5 #include "FileIO.h" |
|
6 #include "Defs.h" |
|
7 #ifndef _UNICODE |
|
8 #include "../Common/StringConvert.h" |
|
9 #endif |
|
10 |
|
11 #ifndef _UNICODE |
|
12 extern bool g_IsNT; |
|
13 #endif |
|
14 |
|
15 namespace NWindows { |
|
16 namespace NFile { |
|
17 namespace NIO { |
|
18 |
|
19 CFileBase::~CFileBase() { Close(); } |
|
20 |
|
21 bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, |
|
22 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
23 { |
|
24 Close(); |
|
25 _handle = ::CreateFile(fileName, desiredAccess, shareMode, |
|
26 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, |
|
27 flagsAndAttributes, (HANDLE) NULL); |
|
28 return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); |
|
29 } |
|
30 |
|
31 #ifndef _UNICODE |
|
32 bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, |
|
33 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
34 { |
|
35 if (g_IsNT) |
|
36 { |
|
37 Close(); |
|
38 _handle = ::CreateFileW(fileName, desiredAccess, shareMode, |
|
39 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, |
|
40 flagsAndAttributes, (HANDLE) NULL); |
|
41 return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); |
|
42 } |
|
43 return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), |
|
44 desiredAccess, shareMode, creationDisposition, flagsAndAttributes); |
|
45 } |
|
46 #endif |
|
47 |
|
48 bool CFileBase::Close() |
|
49 { |
|
50 if(!_fileIsOpen) |
|
51 return true; |
|
52 bool result = BOOLToBool(::CloseHandle(_handle)); |
|
53 _fileIsOpen = !result; |
|
54 return result; |
|
55 } |
|
56 |
|
57 bool CFileBase::GetPosition(UInt64 &position) const |
|
58 { |
|
59 return Seek(0, FILE_CURRENT, position); |
|
60 } |
|
61 |
|
62 bool CFileBase::GetLength(UInt64 &length) const |
|
63 { |
|
64 DWORD sizeHigh; |
|
65 DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); |
|
66 if(sizeLow == 0xFFFFFFFF) |
|
67 if(::GetLastError() != NO_ERROR) |
|
68 return false; |
|
69 length = (((UInt64)sizeHigh) << 32) + sizeLow; |
|
70 return true; |
|
71 } |
|
72 |
|
73 bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const |
|
74 { |
|
75 LARGE_INTEGER value; |
|
76 value.QuadPart = distanceToMove; |
|
77 value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); |
|
78 if (value.LowPart == 0xFFFFFFFF) |
|
79 if(::GetLastError() != NO_ERROR) |
|
80 return false; |
|
81 newPosition = value.QuadPart; |
|
82 return true; |
|
83 } |
|
84 |
|
85 bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) |
|
86 { |
|
87 return Seek(position, FILE_BEGIN, newPosition); |
|
88 } |
|
89 |
|
90 bool CFileBase::SeekToBegin() |
|
91 { |
|
92 UInt64 newPosition; |
|
93 return Seek(0, newPosition); |
|
94 } |
|
95 |
|
96 bool CFileBase::SeekToEnd(UInt64 &newPosition) |
|
97 { |
|
98 return Seek(0, FILE_END, newPosition); |
|
99 } |
|
100 |
|
101 bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const |
|
102 { |
|
103 BY_HANDLE_FILE_INFORMATION winFileInfo; |
|
104 if(!::GetFileInformationByHandle(_handle, &winFileInfo)) |
|
105 return false; |
|
106 fileInfo.Attributes = winFileInfo.dwFileAttributes; |
|
107 fileInfo.CreationTime = winFileInfo.ftCreationTime; |
|
108 fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; |
|
109 fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; |
|
110 fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; |
|
111 fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; |
|
112 fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; |
|
113 fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; |
|
114 return true; |
|
115 } |
|
116 |
|
117 ///////////////////////// |
|
118 // CInFile |
|
119 |
|
120 bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
121 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } |
|
122 |
|
123 bool CInFile::Open(LPCTSTR fileName) |
|
124 { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } |
|
125 |
|
126 #ifndef _UNICODE |
|
127 bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
128 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } |
|
129 |
|
130 bool CInFile::Open(LPCWSTR fileName) |
|
131 { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } |
|
132 #endif |
|
133 |
|
134 // ReadFile and WriteFile functions in Windows have BUG: |
|
135 // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) |
|
136 // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES |
|
137 // (Insufficient system resources exist to complete the requested service). |
|
138 |
|
139 static UInt32 kChunkSizeMax = (1 << 24); |
|
140 |
|
141 bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) |
|
142 { |
|
143 if (size > kChunkSizeMax) |
|
144 size = kChunkSizeMax; |
|
145 DWORD processedLoc = 0; |
|
146 bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); |
|
147 processedSize = (UInt32)processedLoc; |
|
148 return res; |
|
149 } |
|
150 |
|
151 bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) |
|
152 { |
|
153 processedSize = 0; |
|
154 do |
|
155 { |
|
156 UInt32 processedLoc = 0; |
|
157 bool res = ReadPart(data, size, processedLoc); |
|
158 processedSize += processedLoc; |
|
159 if (!res) |
|
160 return false; |
|
161 if (processedLoc == 0) |
|
162 return true; |
|
163 data = (void *)((unsigned char *)data + processedLoc); |
|
164 size -= processedLoc; |
|
165 } |
|
166 while (size > 0); |
|
167 return true; |
|
168 } |
|
169 |
|
170 ///////////////////////// |
|
171 // COutFile |
|
172 |
|
173 bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
174 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } |
|
175 |
|
176 static inline DWORD GetCreationDisposition(bool createAlways) |
|
177 { return createAlways? CREATE_ALWAYS: CREATE_NEW; } |
|
178 |
|
179 bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) |
|
180 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } |
|
181 |
|
182 bool COutFile::Create(LPCTSTR fileName, bool createAlways) |
|
183 { return Open(fileName, GetCreationDisposition(createAlways)); } |
|
184 |
|
185 #ifndef _UNICODE |
|
186 |
|
187 bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) |
|
188 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } |
|
189 |
|
190 bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) |
|
191 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } |
|
192 |
|
193 bool COutFile::Create(LPCWSTR fileName, bool createAlways) |
|
194 { return Open(fileName, GetCreationDisposition(createAlways)); } |
|
195 |
|
196 #endif |
|
197 |
|
198 bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) |
|
199 { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } |
|
200 |
|
201 bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) |
|
202 { return SetTime(NULL, NULL, lastWriteTime); } |
|
203 |
|
204 bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) |
|
205 { |
|
206 if (size > kChunkSizeMax) |
|
207 size = kChunkSizeMax; |
|
208 DWORD processedLoc = 0; |
|
209 bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); |
|
210 processedSize = (UInt32)processedLoc; |
|
211 return res; |
|
212 } |
|
213 |
|
214 bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) |
|
215 { |
|
216 processedSize = 0; |
|
217 do |
|
218 { |
|
219 UInt32 processedLoc = 0; |
|
220 bool res = WritePart(data, size, processedLoc); |
|
221 processedSize += processedLoc; |
|
222 if (!res) |
|
223 return false; |
|
224 if (processedLoc == 0) |
|
225 return true; |
|
226 data = (const void *)((const unsigned char *)data + processedLoc); |
|
227 size -= processedLoc; |
|
228 } |
|
229 while (size > 0); |
|
230 return true; |
|
231 } |
|
232 |
|
233 bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } |
|
234 |
|
235 bool COutFile::SetLength(UInt64 length) |
|
236 { |
|
237 UInt64 newPosition; |
|
238 if(!Seek(length, newPosition)) |
|
239 return false; |
|
240 if(newPosition != length) |
|
241 return false; |
|
242 return SetEndOfFile(); |
|
243 } |
|
244 |
|
245 }}} |