| OLD | NEW |
| (Empty) |
| 1 // Windows/FileIO.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 #include "FileIO.h" | |
| 6 #include "Defs.h" | |
| 7 #ifdef WIN_LONG_PATH | |
| 8 #include "../Common/MyString.h" | |
| 9 #endif | |
| 10 #ifndef _UNICODE | |
| 11 #include "../Common/StringConvert.h" | |
| 12 #endif | |
| 13 | |
| 14 #ifndef _UNICODE | |
| 15 extern bool g_IsNT; | |
| 16 #endif | |
| 17 | |
| 18 namespace NWindows { | |
| 19 namespace NFile { | |
| 20 | |
| 21 #if defined(WIN_LONG_PATH) && defined(_UNICODE) | |
| 22 #define WIN_LONG_PATH2 | |
| 23 #endif | |
| 24 | |
| 25 #ifdef WIN_LONG_PATH | |
| 26 bool GetLongPathBase(LPCWSTR s, UString &res) | |
| 27 { | |
| 28 res.Empty(); | |
| 29 int len = MyStringLen(s); | |
| 30 wchar_t c = s[0]; | |
| 31 if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.
')) | |
| 32 return true; | |
| 33 UString curDir; | |
| 34 bool isAbs = false; | |
| 35 if (len > 3) | |
| 36 isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'
A' && c <= L'Z')); | |
| 37 | |
| 38 if (!isAbs) | |
| 39 { | |
| 40 DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(M
AX_PATH + 1)); | |
| 41 curDir.ReleaseBuffer(); | |
| 42 if (needLength == 0 || needLength > MAX_PATH) | |
| 43 return false; | |
| 44 if (curDir[curDir.Length() - 1] != L'\\') | |
| 45 curDir += L'\\'; | |
| 46 } | |
| 47 res = UString(L"\\\\?\\") + curDir + s; | |
| 48 return true; | |
| 49 } | |
| 50 | |
| 51 bool GetLongPath(LPCWSTR path, UString &longPath) | |
| 52 { | |
| 53 if (GetLongPathBase(path, longPath)) | |
| 54 return !longPath.IsEmpty(); | |
| 55 return false; | |
| 56 } | |
| 57 #endif | |
| 58 | |
| 59 namespace NIO { | |
| 60 | |
| 61 CFileBase::~CFileBase() { Close(); } | |
| 62 | |
| 63 bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, | |
| 64 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
| 65 { | |
| 66 if (!Close()) | |
| 67 return false; | |
| 68 _handle = ::CreateFile(fileName, desiredAccess, shareMode, | |
| 69 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
| 70 flagsAndAttributes, (HANDLE)NULL); | |
| 71 #ifdef WIN_LONG_PATH2 | |
| 72 if (_handle == INVALID_HANDLE_VALUE) | |
| 73 { | |
| 74 UString longPath; | |
| 75 if (GetLongPath(fileName, longPath)) | |
| 76 _handle = ::CreateFileW(longPath, desiredAccess, shareMode, | |
| 77 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
| 78 flagsAndAttributes, (HANDLE)NULL); | |
| 79 } | |
| 80 #endif | |
| 81 return (_handle != INVALID_HANDLE_VALUE); | |
| 82 } | |
| 83 | |
| 84 #ifndef _UNICODE | |
| 85 bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, | |
| 86 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
| 87 { | |
| 88 if (!g_IsNT) | |
| 89 return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_AC
P : CP_OEMCP), | |
| 90 desiredAccess, shareMode, creationDisposition, flagsAndAttributes); | |
| 91 if (!Close()) | |
| 92 return false; | |
| 93 _handle = ::CreateFileW(fileName, desiredAccess, shareMode, | |
| 94 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
| 95 flagsAndAttributes, (HANDLE)NULL); | |
| 96 #ifdef WIN_LONG_PATH | |
| 97 if (_handle == INVALID_HANDLE_VALUE) | |
| 98 { | |
| 99 UString longPath; | |
| 100 if (GetLongPath(fileName, longPath)) | |
| 101 _handle = ::CreateFileW(longPath, desiredAccess, shareMode, | |
| 102 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
| 103 flagsAndAttributes, (HANDLE)NULL); | |
| 104 } | |
| 105 #endif | |
| 106 return (_handle != INVALID_HANDLE_VALUE); | |
| 107 } | |
| 108 #endif | |
| 109 | |
| 110 bool CFileBase::Close() | |
| 111 { | |
| 112 if (_handle == INVALID_HANDLE_VALUE) | |
| 113 return true; | |
| 114 if (!::CloseHandle(_handle)) | |
| 115 return false; | |
| 116 _handle = INVALID_HANDLE_VALUE; | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 bool CFileBase::GetPosition(UInt64 &position) const | |
| 121 { | |
| 122 return Seek(0, FILE_CURRENT, position); | |
| 123 } | |
| 124 | |
| 125 bool CFileBase::GetLength(UInt64 &length) const | |
| 126 { | |
| 127 DWORD sizeHigh; | |
| 128 DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); | |
| 129 if (sizeLow == 0xFFFFFFFF) | |
| 130 if (::GetLastError() != NO_ERROR) | |
| 131 return false; | |
| 132 length = (((UInt64)sizeHigh) << 32) + sizeLow; | |
| 133 return true; | |
| 134 } | |
| 135 | |
| 136 bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition
) const | |
| 137 { | |
| 138 LARGE_INTEGER value; | |
| 139 value.QuadPart = distanceToMove; | |
| 140 value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, move
Method); | |
| 141 if (value.LowPart == 0xFFFFFFFF) | |
| 142 if (::GetLastError() != NO_ERROR) | |
| 143 return false; | |
| 144 newPosition = value.QuadPart; | |
| 145 return true; | |
| 146 } | |
| 147 | |
| 148 bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) | |
| 149 { | |
| 150 return Seek(position, FILE_BEGIN, newPosition); | |
| 151 } | |
| 152 | |
| 153 bool CFileBase::SeekToBegin() | |
| 154 { | |
| 155 UInt64 newPosition; | |
| 156 return Seek(0, newPosition); | |
| 157 } | |
| 158 | |
| 159 bool CFileBase::SeekToEnd(UInt64 &newPosition) | |
| 160 { | |
| 161 return Seek(0, FILE_END, newPosition); | |
| 162 } | |
| 163 | |
| 164 bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const | |
| 165 { | |
| 166 BY_HANDLE_FILE_INFORMATION winFileInfo; | |
| 167 if (!::GetFileInformationByHandle(_handle, &winFileInfo)) | |
| 168 return false; | |
| 169 fileInfo.Attributes = winFileInfo.dwFileAttributes; | |
| 170 fileInfo.CTime = winFileInfo.ftCreationTime; | |
| 171 fileInfo.ATime = winFileInfo.ftLastAccessTime; | |
| 172 fileInfo.MTime = winFileInfo.ftLastWriteTime; | |
| 173 fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; | |
| 174 fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFi
leSizeLow; | |
| 175 fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; | |
| 176 fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInf
o.nFileIndexLow; | |
| 177 return true; | |
| 178 } | |
| 179 | |
| 180 ///////////////////////// | |
| 181 // CInFile | |
| 182 | |
| 183 bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition,
DWORD flagsAndAttributes) | |
| 184 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsA
ndAttributes); } | |
| 185 | |
| 186 bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) | |
| 187 { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0)
, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } | |
| 188 | |
| 189 bool CInFile::Open(LPCTSTR fileName) | |
| 190 { return OpenShared(fileName, false); } | |
| 191 | |
| 192 #ifndef _UNICODE | |
| 193 bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition,
DWORD flagsAndAttributes) | |
| 194 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsA
ndAttributes); } | |
| 195 | |
| 196 bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) | |
| 197 { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0)
, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } | |
| 198 | |
| 199 bool CInFile::Open(LPCWSTR fileName) | |
| 200 { return OpenShared(fileName, false); } | |
| 201 #endif | |
| 202 | |
| 203 // ReadFile and WriteFile functions in Windows have BUG: | |
| 204 // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB +
1) | |
| 205 // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES | |
| 206 // (Insufficient system resources exist to complete the requested service). | |
| 207 | |
| 208 // Probably in some version of Windows there are problems with other sizes: | |
| 209 // for 32 MB (maybe also for 16 MB). | |
| 210 // And message can be "Network connection was lost" | |
| 211 | |
| 212 static UInt32 kChunkSizeMax = (1 << 22); | |
| 213 | |
| 214 bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) | |
| 215 { | |
| 216 if (size > kChunkSizeMax) | |
| 217 size = kChunkSizeMax; | |
| 218 DWORD processedLoc = 0; | |
| 219 bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); | |
| 220 processedSize = (UInt32)processedLoc; | |
| 221 return res; | |
| 222 } | |
| 223 | |
| 224 bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) | |
| 225 { | |
| 226 processedSize = 0; | |
| 227 do | |
| 228 { | |
| 229 UInt32 processedLoc = 0; | |
| 230 bool res = ReadPart(data, size, processedLoc); | |
| 231 processedSize += processedLoc; | |
| 232 if (!res) | |
| 233 return false; | |
| 234 if (processedLoc == 0) | |
| 235 return true; | |
| 236 data = (void *)((unsigned char *)data + processedLoc); | |
| 237 size -= processedLoc; | |
| 238 } | |
| 239 while (size > 0); | |
| 240 return true; | |
| 241 } | |
| 242 | |
| 243 ///////////////////////// | |
| 244 // COutFile | |
| 245 | |
| 246 bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition
, DWORD flagsAndAttributes) | |
| 247 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposi
tion, flagsAndAttributes); } | |
| 248 | |
| 249 static inline DWORD GetCreationDisposition(bool createAlways) | |
| 250 { return createAlways? CREATE_ALWAYS: CREATE_NEW; } | |
| 251 | |
| 252 bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) | |
| 253 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_N
ORMAL); } | |
| 254 | |
| 255 bool COutFile::Create(LPCTSTR fileName, bool createAlways) | |
| 256 { return Open(fileName, GetCreationDisposition(createAlways)); } | |
| 257 | |
| 258 #ifndef _UNICODE | |
| 259 | |
| 260 bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition
, DWORD flagsAndAttributes) | |
| 261 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDi
sposition, flagsAndAttributes); } | |
| 262 | |
| 263 bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) | |
| 264 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_
NORMAL); } | |
| 265 | |
| 266 bool COutFile::Create(LPCWSTR fileName, bool createAlways) | |
| 267 { return Open(fileName, GetCreationDisposition(createAlways)); } | |
| 268 | |
| 269 #endif | |
| 270 | |
| 271 bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILET
IME *mTime) | |
| 272 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } | |
| 273 | |
| 274 bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTi
me); } | |
| 275 | |
| 276 bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) | |
| 277 { | |
| 278 if (size > kChunkSizeMax) | |
| 279 size = kChunkSizeMax; | |
| 280 DWORD processedLoc = 0; | |
| 281 bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); | |
| 282 processedSize = (UInt32)processedLoc; | |
| 283 return res; | |
| 284 } | |
| 285 | |
| 286 bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) | |
| 287 { | |
| 288 processedSize = 0; | |
| 289 do | |
| 290 { | |
| 291 UInt32 processedLoc = 0; | |
| 292 bool res = WritePart(data, size, processedLoc); | |
| 293 processedSize += processedLoc; | |
| 294 if (!res) | |
| 295 return false; | |
| 296 if (processedLoc == 0) | |
| 297 return true; | |
| 298 data = (const void *)((const unsigned char *)data + processedLoc); | |
| 299 size -= processedLoc; | |
| 300 } | |
| 301 while (size > 0); | |
| 302 return true; | |
| 303 } | |
| 304 | |
| 305 bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } | |
| 306 | |
| 307 bool COutFile::SetLength(UInt64 length) | |
| 308 { | |
| 309 UInt64 newPosition; | |
| 310 if (!Seek(length, newPosition)) | |
| 311 return false; | |
| 312 if (newPosition != length) | |
| 313 return false; | |
| 314 return SetEndOfFile(); | |
| 315 } | |
| 316 | |
| 317 }}} | |
| OLD | NEW |