Mercurial > vba-clojure
view 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 source
1 // Windows/FileIO.cpp3 #include "StdAfx.h"5 #include "FileIO.h"6 #include "Defs.h"7 #ifdef WIN_LONG_PATH8 #include "../Common/MyString.h"9 #endif10 #ifndef _UNICODE11 #include "../Common/StringConvert.h"12 #endif14 #ifndef _UNICODE15 extern bool g_IsNT;16 #endif18 namespace NWindows {19 namespace NFile {21 #if defined(WIN_LONG_PATH) && defined(_UNICODE)22 #define WIN_LONG_PATH223 #endif25 #ifdef WIN_LONG_PATH26 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'));38 if (!isAbs)39 {40 DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_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 }51 bool GetLongPath(LPCWSTR path, UString &longPath)52 {53 if (GetLongPathBase(path, longPath))54 return !longPath.IsEmpty();55 return false;56 }57 #endif59 namespace NIO {61 CFileBase::~CFileBase() { Close(); }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_PATH272 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 #endif81 return (_handle != INVALID_HANDLE_VALUE);82 }84 #ifndef _UNICODE85 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_ACP : 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_PATH97 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 #endif106 return (_handle != INVALID_HANDLE_VALUE);107 }108 #endif110 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 }120 bool CFileBase::GetPosition(UInt64 &position) const121 {122 return Seek(0, FILE_CURRENT, position);123 }125 bool CFileBase::GetLength(UInt64 &length) const126 {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 }136 bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const137 {138 LARGE_INTEGER value;139 value.QuadPart = distanceToMove;140 value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);141 if (value.LowPart == 0xFFFFFFFF)142 if (::GetLastError() != NO_ERROR)143 return false;144 newPosition = value.QuadPart;145 return true;146 }148 bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)149 {150 return Seek(position, FILE_BEGIN, newPosition);151 }153 bool CFileBase::SeekToBegin()154 {155 UInt64 newPosition;156 return Seek(0, newPosition);157 }159 bool CFileBase::SeekToEnd(UInt64 &newPosition)160 {161 return Seek(0, FILE_END, newPosition);162 }164 bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const165 {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.nFileSizeLow;175 fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;176 fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;177 return true;178 }180 /////////////////////////181 // CInFile183 bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)184 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }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); }189 bool CInFile::Open(LPCTSTR fileName)190 { return OpenShared(fileName, false); }192 #ifndef _UNICODE193 bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)194 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }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); }199 bool CInFile::Open(LPCWSTR fileName)200 { return OpenShared(fileName, false); }201 #endif203 // 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_RESOURCES206 // (Insufficient system resources exist to complete the requested service).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"212 static UInt32 kChunkSizeMax = (1 << 22);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 }224 bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)225 {226 processedSize = 0;227 do228 {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 }243 /////////////////////////244 // COutFile246 bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)247 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }249 static inline DWORD GetCreationDisposition(bool createAlways)250 { return createAlways? CREATE_ALWAYS: CREATE_NEW; }252 bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)253 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }255 bool COutFile::Create(LPCTSTR fileName, bool createAlways)256 { return Open(fileName, GetCreationDisposition(createAlways)); }258 #ifndef _UNICODE260 bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)261 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }263 bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)264 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }266 bool COutFile::Create(LPCWSTR fileName, bool createAlways)267 { return Open(fileName, GetCreationDisposition(createAlways)); }269 #endif271 bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)272 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }274 bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); }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 }286 bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)287 {288 processedSize = 0;289 do290 {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 }305 bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }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 }317 }}}