Mercurial > vba-clojure
diff src/win32/7zip/7z/CPP/Windows/FileIO.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/Windows/FileIO.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,317 @@ 1.4 +// Windows/FileIO.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "FileIO.h" 1.9 +#include "Defs.h" 1.10 +#ifdef WIN_LONG_PATH 1.11 +#include "../Common/MyString.h" 1.12 +#endif 1.13 +#ifndef _UNICODE 1.14 +#include "../Common/StringConvert.h" 1.15 +#endif 1.16 + 1.17 +#ifndef _UNICODE 1.18 +extern bool g_IsNT; 1.19 +#endif 1.20 + 1.21 +namespace NWindows { 1.22 +namespace NFile { 1.23 + 1.24 +#if defined(WIN_LONG_PATH) && defined(_UNICODE) 1.25 +#define WIN_LONG_PATH2 1.26 +#endif 1.27 + 1.28 +#ifdef WIN_LONG_PATH 1.29 +bool GetLongPathBase(LPCWSTR s, UString &res) 1.30 +{ 1.31 + res.Empty(); 1.32 + int len = MyStringLen(s); 1.33 + wchar_t c = s[0]; 1.34 + if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) 1.35 + return true; 1.36 + UString curDir; 1.37 + bool isAbs = false; 1.38 + if (len > 3) 1.39 + isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); 1.40 + 1.41 + if (!isAbs) 1.42 + { 1.43 + DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); 1.44 + curDir.ReleaseBuffer(); 1.45 + if (needLength == 0 || needLength > MAX_PATH) 1.46 + return false; 1.47 + if (curDir[curDir.Length() - 1] != L'\\') 1.48 + curDir += L'\\'; 1.49 + } 1.50 + res = UString(L"\\\\?\\") + curDir + s; 1.51 + return true; 1.52 +} 1.53 + 1.54 +bool GetLongPath(LPCWSTR path, UString &longPath) 1.55 +{ 1.56 + if (GetLongPathBase(path, longPath)) 1.57 + return !longPath.IsEmpty(); 1.58 + return false; 1.59 +} 1.60 +#endif 1.61 + 1.62 +namespace NIO { 1.63 + 1.64 +CFileBase::~CFileBase() { Close(); } 1.65 + 1.66 +bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, 1.67 + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.68 +{ 1.69 + if (!Close()) 1.70 + return false; 1.71 + _handle = ::CreateFile(fileName, desiredAccess, shareMode, 1.72 + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 1.73 + flagsAndAttributes, (HANDLE)NULL); 1.74 + #ifdef WIN_LONG_PATH2 1.75 + if (_handle == INVALID_HANDLE_VALUE) 1.76 + { 1.77 + UString longPath; 1.78 + if (GetLongPath(fileName, longPath)) 1.79 + _handle = ::CreateFileW(longPath, desiredAccess, shareMode, 1.80 + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 1.81 + flagsAndAttributes, (HANDLE)NULL); 1.82 + } 1.83 + #endif 1.84 + return (_handle != INVALID_HANDLE_VALUE); 1.85 +} 1.86 + 1.87 +#ifndef _UNICODE 1.88 +bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, 1.89 + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.90 +{ 1.91 + if (!g_IsNT) 1.92 + return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), 1.93 + desiredAccess, shareMode, creationDisposition, flagsAndAttributes); 1.94 + if (!Close()) 1.95 + return false; 1.96 + _handle = ::CreateFileW(fileName, desiredAccess, shareMode, 1.97 + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 1.98 + flagsAndAttributes, (HANDLE)NULL); 1.99 + #ifdef WIN_LONG_PATH 1.100 + if (_handle == INVALID_HANDLE_VALUE) 1.101 + { 1.102 + UString longPath; 1.103 + if (GetLongPath(fileName, longPath)) 1.104 + _handle = ::CreateFileW(longPath, desiredAccess, shareMode, 1.105 + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 1.106 + flagsAndAttributes, (HANDLE)NULL); 1.107 + } 1.108 + #endif 1.109 + return (_handle != INVALID_HANDLE_VALUE); 1.110 +} 1.111 +#endif 1.112 + 1.113 +bool CFileBase::Close() 1.114 +{ 1.115 + if (_handle == INVALID_HANDLE_VALUE) 1.116 + return true; 1.117 + if (!::CloseHandle(_handle)) 1.118 + return false; 1.119 + _handle = INVALID_HANDLE_VALUE; 1.120 + return true; 1.121 +} 1.122 + 1.123 +bool CFileBase::GetPosition(UInt64 &position) const 1.124 +{ 1.125 + return Seek(0, FILE_CURRENT, position); 1.126 +} 1.127 + 1.128 +bool CFileBase::GetLength(UInt64 &length) const 1.129 +{ 1.130 + DWORD sizeHigh; 1.131 + DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); 1.132 + if (sizeLow == 0xFFFFFFFF) 1.133 + if (::GetLastError() != NO_ERROR) 1.134 + return false; 1.135 + length = (((UInt64)sizeHigh) << 32) + sizeLow; 1.136 + return true; 1.137 +} 1.138 + 1.139 +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const 1.140 +{ 1.141 + LARGE_INTEGER value; 1.142 + value.QuadPart = distanceToMove; 1.143 + value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); 1.144 + if (value.LowPart == 0xFFFFFFFF) 1.145 + if (::GetLastError() != NO_ERROR) 1.146 + return false; 1.147 + newPosition = value.QuadPart; 1.148 + return true; 1.149 +} 1.150 + 1.151 +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) 1.152 +{ 1.153 + return Seek(position, FILE_BEGIN, newPosition); 1.154 +} 1.155 + 1.156 +bool CFileBase::SeekToBegin() 1.157 +{ 1.158 + UInt64 newPosition; 1.159 + return Seek(0, newPosition); 1.160 +} 1.161 + 1.162 +bool CFileBase::SeekToEnd(UInt64 &newPosition) 1.163 +{ 1.164 + return Seek(0, FILE_END, newPosition); 1.165 +} 1.166 + 1.167 +bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const 1.168 +{ 1.169 + BY_HANDLE_FILE_INFORMATION winFileInfo; 1.170 + if (!::GetFileInformationByHandle(_handle, &winFileInfo)) 1.171 + return false; 1.172 + fileInfo.Attributes = winFileInfo.dwFileAttributes; 1.173 + fileInfo.CTime = winFileInfo.ftCreationTime; 1.174 + fileInfo.ATime = winFileInfo.ftLastAccessTime; 1.175 + fileInfo.MTime = winFileInfo.ftLastWriteTime; 1.176 + fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; 1.177 + fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; 1.178 + fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; 1.179 + fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; 1.180 + return true; 1.181 +} 1.182 + 1.183 +///////////////////////// 1.184 +// CInFile 1.185 + 1.186 +bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.187 + { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } 1.188 + 1.189 +bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) 1.190 +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } 1.191 + 1.192 +bool CInFile::Open(LPCTSTR fileName) 1.193 + { return OpenShared(fileName, false); } 1.194 + 1.195 +#ifndef _UNICODE 1.196 +bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.197 + { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } 1.198 + 1.199 +bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) 1.200 +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } 1.201 + 1.202 +bool CInFile::Open(LPCWSTR fileName) 1.203 + { return OpenShared(fileName, false); } 1.204 +#endif 1.205 + 1.206 +// ReadFile and WriteFile functions in Windows have BUG: 1.207 +// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) 1.208 +// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES 1.209 +// (Insufficient system resources exist to complete the requested service). 1.210 + 1.211 +// Probably in some version of Windows there are problems with other sizes: 1.212 +// for 32 MB (maybe also for 16 MB). 1.213 +// And message can be "Network connection was lost" 1.214 + 1.215 +static UInt32 kChunkSizeMax = (1 << 22); 1.216 + 1.217 +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) 1.218 +{ 1.219 + if (size > kChunkSizeMax) 1.220 + size = kChunkSizeMax; 1.221 + DWORD processedLoc = 0; 1.222 + bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); 1.223 + processedSize = (UInt32)processedLoc; 1.224 + return res; 1.225 +} 1.226 + 1.227 +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) 1.228 +{ 1.229 + processedSize = 0; 1.230 + do 1.231 + { 1.232 + UInt32 processedLoc = 0; 1.233 + bool res = ReadPart(data, size, processedLoc); 1.234 + processedSize += processedLoc; 1.235 + if (!res) 1.236 + return false; 1.237 + if (processedLoc == 0) 1.238 + return true; 1.239 + data = (void *)((unsigned char *)data + processedLoc); 1.240 + size -= processedLoc; 1.241 + } 1.242 + while (size > 0); 1.243 + return true; 1.244 +} 1.245 + 1.246 +///////////////////////// 1.247 +// COutFile 1.248 + 1.249 +bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.250 + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } 1.251 + 1.252 +static inline DWORD GetCreationDisposition(bool createAlways) 1.253 + { return createAlways? CREATE_ALWAYS: CREATE_NEW; } 1.254 + 1.255 +bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) 1.256 + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } 1.257 + 1.258 +bool COutFile::Create(LPCTSTR fileName, bool createAlways) 1.259 + { return Open(fileName, GetCreationDisposition(createAlways)); } 1.260 + 1.261 +#ifndef _UNICODE 1.262 + 1.263 +bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) 1.264 + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } 1.265 + 1.266 +bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) 1.267 + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } 1.268 + 1.269 +bool COutFile::Create(LPCWSTR fileName, bool createAlways) 1.270 + { return Open(fileName, GetCreationDisposition(createAlways)); } 1.271 + 1.272 +#endif 1.273 + 1.274 +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) 1.275 + { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } 1.276 + 1.277 +bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } 1.278 + 1.279 +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) 1.280 +{ 1.281 + if (size > kChunkSizeMax) 1.282 + size = kChunkSizeMax; 1.283 + DWORD processedLoc = 0; 1.284 + bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); 1.285 + processedSize = (UInt32)processedLoc; 1.286 + return res; 1.287 +} 1.288 + 1.289 +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) 1.290 +{ 1.291 + processedSize = 0; 1.292 + do 1.293 + { 1.294 + UInt32 processedLoc = 0; 1.295 + bool res = WritePart(data, size, processedLoc); 1.296 + processedSize += processedLoc; 1.297 + if (!res) 1.298 + return false; 1.299 + if (processedLoc == 0) 1.300 + return true; 1.301 + data = (const void *)((const unsigned char *)data + processedLoc); 1.302 + size -= processedLoc; 1.303 + } 1.304 + while (size > 0); 1.305 + return true; 1.306 +} 1.307 + 1.308 +bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } 1.309 + 1.310 +bool COutFile::SetLength(UInt64 length) 1.311 +{ 1.312 + UInt64 newPosition; 1.313 + if (!Seek(length, newPosition)) 1.314 + return false; 1.315 + if (newPosition != length) 1.316 + return false; 1.317 + return SetEndOfFile(); 1.318 +} 1.319 + 1.320 +}}}