1286 lines
74 KiB
C++
1286 lines
74 KiB
C++
// ==========================================================================
|
||
// Class Implementation : COXUNCStandardActor
|
||
// ==========================================================================
|
||
|
||
// Version: 9.3
|
||
|
||
// Source file : OXUNCStandardActor.cpp
|
||
|
||
// This software along with its related components, documentation and files ("The Libraries")
|
||
// is ?1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
||
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
||
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
||
// to obtain this file, or directly from our office. For a copy of the license governing
|
||
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
||
|
||
// //////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "stdafx.h"
|
||
#include "OXUNCStandardActor.h"
|
||
#include "OXMainRes.h"
|
||
|
||
#pragma warning(disable : 4201)
|
||
|
||
#include <IO.h> // for _access
|
||
#include <WinIOCtl.h> // for FSCTL_GET_COMPRESSION and FSCTL_SET_COMPRESSION
|
||
|
||
#include "UTBStrOp.h"
|
||
|
||
#ifdef _DEBUG
|
||
#undef THIS_FILE
|
||
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
IMPLEMENT_DYNAMIC(COXUNCStandardActor, CObject)
|
||
|
||
#define new DEBUG_NEW
|
||
|
||
#ifdef _DEBUG
|
||
// Trace a message when the RESULT specifies failure
|
||
#define CONDITIONAL_TRACE_RESULT(TEXT, RESULT) \
|
||
{ if (FAILED(RESULT)) { \
|
||
TRACE(_T("%s : Failed (%u == 0x%X, Code : %u) :\n\t%s\n"), \
|
||
_T(TEXT), RESULT, RESULT, HRESULT_CODE(RESULT), GetResultMessage(RESULT)); \
|
||
} }
|
||
#else
|
||
// Do not trace in Release build
|
||
#define CONDITIONAL_TRACE_RESULT(TEXT, RESULT)
|
||
#endif // _DEBUG
|
||
|
||
// Assign the LastError of Win32 as HRESULT code to RESULT
|
||
#define GET_LAST_HRESULT(RESULT) RESULT = (RESULT = ::GetLastError(), HRESULT_FROM_WIN32(RESULT))
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Definition of static members
|
||
COXUNCStandardActor COXUNCStandardActor::m_theOneAndOnly;
|
||
|
||
// Data members -------------------------------------------------------------
|
||
// protected:
|
||
|
||
// private:
|
||
|
||
// Member functions ---------------------------------------------------------
|
||
// public:
|
||
|
||
COXUNCStandardActor::COXUNCStandardActor()
|
||
{
|
||
ASSERT_VALID(this);
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::MakeAbsolute(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
LPCTSTR pszPathName = UNC.m_sUNC;
|
||
if (*pszPathName == COXUNC::m_cNull)
|
||
// ... Empty path spec stays empty
|
||
return hResult;
|
||
|
||
CString sAbsolutePath;
|
||
DWORD nMaxAbsolutePathLength = 0;
|
||
DWORD nPathLength = 0;
|
||
LPTSTR pszAbsolutePath = NULL;
|
||
LPTSTR pszFilePart = NULL;
|
||
|
||
// ... First get the necessary length for the result string
|
||
nMaxAbsolutePathLength = ::GetFullPathName(pszPathName, nMaxAbsolutePathLength, pszAbsolutePath, &pszFilePart);
|
||
if (nMaxAbsolutePathLength != 0)
|
||
{
|
||
nMaxAbsolutePathLength++;
|
||
// ... The alloc a buffer and get the absolute path
|
||
pszAbsolutePath = sAbsolutePath.GetBuffer(nMaxAbsolutePathLength);
|
||
nPathLength = ::GetFullPathName(pszPathName, nMaxAbsolutePathLength, pszAbsolutePath, &pszFilePart);
|
||
// ... Check for failure
|
||
if ((nPathLength == 0) || (nMaxAbsolutePathLength < nPathLength))
|
||
GET_LAST_HRESULT(hResult);
|
||
sAbsolutePath.ReleaseBuffer();
|
||
}
|
||
else
|
||
{
|
||
// ... First call to GetFullPathName already failed
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... We should have created a buffer that is large enough
|
||
ASSERT(nPathLength <= nMaxAbsolutePathLength);
|
||
UNC = sAbsolutePath;
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::MakeAbsolute", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::Exists(COXUNC UNC, BOOL& bExists)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
bExists = FALSE;
|
||
|
||
if (UNC.File().IsEmpty())
|
||
{
|
||
// Search for device or directory
|
||
int nAccess = _taccess(UNC, 0);
|
||
bExists = (nAccess == 0);
|
||
if (!bExists)
|
||
hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||
}
|
||
else
|
||
{
|
||
// Search for file
|
||
WIN32_FIND_DATA findFileData;
|
||
HANDLE hFind = ::FindFirstFile(UNC, &findFileData);
|
||
bExists = (hFind != INVALID_HANDLE_VALUE);
|
||
if (!bExists)
|
||
GET_LAST_HRESULT(hResult);
|
||
else
|
||
{
|
||
VERIFY(::FindClose(hFind));
|
||
// Check that we have not found a directory, because we are searching for a file
|
||
if ((findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
// ... Searching for file but found dir
|
||
bExists = FALSE;
|
||
hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||
}
|
||
}
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::Exists", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::Create(COXUNC UNC)
|
||
{
|
||
// ... We will change the parameter UNC in this function
|
||
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// First create all the directories specified (some may not yet exist)
|
||
CString sOriginalDir = UNC.Directory();
|
||
CString sOriginalFile = UNC.File();
|
||
LPCTSTR pszDirBegin = sOriginalDir;
|
||
LPCTSTR pszDirEnd = NULL;
|
||
|
||
// ... Get a pointer to the end of the first subdirectory
|
||
if (*pszDirBegin != COXUNC::m_cNull)
|
||
pszDirEnd = _tcspbrk(pszDirBegin + 1, COXUNC::m_pszSlashes);
|
||
else
|
||
pszDirEnd = NULL;
|
||
|
||
// ... Remove the file part from the URL
|
||
UNC.File().Empty();
|
||
|
||
// Iterate all the subdirectories and create them one by one
|
||
CString sDir;
|
||
int nDirLength = 0;
|
||
while (pszDirEnd != NULL)
|
||
{
|
||
nDirLength = (int)(pszDirEnd - pszDirBegin);
|
||
UTBStr::tcsncpy(sDir.GetBufferSetLength(nDirLength), nDirLength, pszDirBegin, nDirLength);
|
||
UNC.Directory() = sDir;
|
||
if (!::CreateDirectory(UNC, NULL))
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
if (hResult == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
|
||
// ... Dirctory already exists : OK, continue
|
||
hResult = ERROR_SUCCESS;
|
||
else
|
||
// ... Failed to create the directory
|
||
break;
|
||
}
|
||
|
||
// ... Get pointer to the end of the next subdirectory
|
||
pszDirEnd = _tcspbrk(pszDirEnd + 1, COXUNC::m_pszSlashes);
|
||
}
|
||
UNC.Directory() = sOriginalDir;
|
||
|
||
// Then create the file (if one was specified)
|
||
if (!sOriginalFile.IsEmpty())
|
||
{
|
||
UNC.File() = sOriginalFile;
|
||
HANDLE hFile = ::CreateFile(UNC, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
VERIFY(::CloseHandle(hFile));
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::Create", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::CreateTemporaryFile(COXUNC tempDir, LPCTSTR pszPrefix, COXUNC& file)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
file.Empty();
|
||
|
||
CString sPrefix(pszPrefix);
|
||
CString sTempFile;
|
||
|
||
if (!::GetTempFileName(tempDir.FileForm(), sPrefix, 0, sTempFile.GetBuffer(_MAX_PATH)))
|
||
GET_LAST_HRESULT(hResult);
|
||
sTempFile.ReleaseBuffer();
|
||
|
||
if (SUCCEEDED(hResult))
|
||
file = sTempFile;
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::CreateTemporaryFile", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::Copy(COXUNC sourceUNC, COXUNC destinationUNC, BOOL bReplaceExisting)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
if (!destinationUNC.IsEmpty())
|
||
{
|
||
// ... Use the parts of the source that are not filled out in the destination
|
||
if (destinationUNC.Server().IsEmpty() && destinationUNC.Share().IsEmpty())
|
||
{
|
||
destinationUNC.Server() = sourceUNC.Server();
|
||
destinationUNC.Share() = sourceUNC.Share();
|
||
}
|
||
if (destinationUNC.Directory().IsEmpty())
|
||
destinationUNC.Directory() = sourceUNC.Directory();
|
||
if (destinationUNC.File().IsEmpty())
|
||
destinationUNC.File() = sourceUNC.File();
|
||
}
|
||
|
||
if (!::CopyFile(sourceUNC.FileForm(), destinationUNC.FileForm(), !bReplaceExisting))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::Copy", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::MoveRename(COXUNC sourceUNC, COXUNC destinationUNC, DWORD dwFlags)
|
||
{
|
||
// ... We will change the parameters sourceUNC and destinationUNC in this function
|
||
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
if (!destinationUNC.IsEmpty())
|
||
{
|
||
// ... Use the parts of the source that are not filled out in the destination
|
||
if (destinationUNC.Server().IsEmpty() && destinationUNC.Share().IsEmpty())
|
||
{
|
||
destinationUNC.Server() = sourceUNC.Server();
|
||
destinationUNC.Share() = sourceUNC.Share();
|
||
}
|
||
if (destinationUNC.Directory().IsEmpty())
|
||
destinationUNC.Directory() = sourceUNC.Directory();
|
||
if (destinationUNC.File().IsEmpty())
|
||
destinationUNC.File() = sourceUNC.File();
|
||
}
|
||
|
||
// ... When destination is NULL, we are deleting the file
|
||
CString sFileForm = destinationUNC.FileForm();
|
||
LPCTSTR pszDestUNC = sFileForm;
|
||
if (sFileForm.GetLength() == 0)
|
||
pszDestUNC = NULL;
|
||
|
||
if (!::MoveFileEx(sourceUNC.FileForm(), pszDestUNC, dwFlags))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (hResult == HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED))
|
||
{
|
||
// Function call failed because it is not supported on this platform
|
||
// (probably Win95)
|
||
|
||
// We will try to emulate this function through other function calls
|
||
|
||
// Comapre absolute paths of source and destination
|
||
sourceUNC.MakeAbsolute();
|
||
destinationUNC.MakeAbsolute();
|
||
// ... If source and destination are equal we do not have to copy it
|
||
if (sourceUNC.StandardForm() == destinationUNC.StandardForm())
|
||
hResult = ERROR_SUCCESS;
|
||
else
|
||
{
|
||
switch(dwFlags)
|
||
{
|
||
case 0:
|
||
// Use plain ::MoveFile()
|
||
hResult = ERROR_SUCCESS;
|
||
if (!::MoveFile(sourceUNC.FileForm(), pszDestUNC))
|
||
GET_LAST_HRESULT(hResult);
|
||
break;
|
||
case MOVEFILE_COPY_ALLOWED:
|
||
// COPY the file and delete the original (do not allow overwrite)
|
||
hResult = ERROR_SUCCESS;
|
||
if (!::CopyFile(sourceUNC.FileForm(), pszDestUNC, TRUE))
|
||
GET_LAST_HRESULT(hResult);
|
||
if (SUCCEEDED(hResult) && !::DeleteFile(sourceUNC.FileForm()))
|
||
GET_LAST_HRESULT(hResult);
|
||
break;
|
||
case MOVEFILE_REPLACE_EXISTING:
|
||
// We cannot disallow moves accross disks, so specifying MOVEFILE_REPLACE_EXISTING
|
||
// also implies MOVEFILE_COPY_ALLOWED, even when not specified.
|
||
// ... Fall through
|
||
case MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED:
|
||
// First delete destination and then move the file
|
||
// ... Delete may fail if it does not exist, so we discard the result
|
||
hResult = ERROR_SUCCESS;
|
||
if (pszDestUNC != NULL)
|
||
::DeleteFile(pszDestUNC);
|
||
if (!::MoveFile(sourceUNC.FileForm(), pszDestUNC))
|
||
GET_LAST_HRESULT(hResult);
|
||
break;
|
||
default:
|
||
// Other combinations (e.g. MOVEFILE_DELAY_UNTIL_REBOOT or
|
||
// MOVEFILE_WRITE_THROUGH) cannot be emulated and will fail)
|
||
ASSERT(FAILED(hResult));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::MoveRename", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::Delete(COXUNC UNC, BOOL bRemoveReadOnly)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
if (!UNC.File().IsEmpty())
|
||
{
|
||
// Delete file
|
||
if (!::DeleteFile(UNC))
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
if ((hResult == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) && bRemoveReadOnly)
|
||
{
|
||
// File may be read/only : Remove this attribute
|
||
if (::SetFileAttributes(UNC, FILE_ATTRIBUTE_NORMAL) && ::DeleteFile(UNC))
|
||
hResult = ERROR_SUCCESS;
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Delete directory
|
||
if (!::RemoveDirectory(UNC))
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::Delete", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetCurrentDirectory(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
UNC.Empty();
|
||
|
||
CString sDir;
|
||
int nMaxDirLength = 0;
|
||
nMaxDirLength = ::GetCurrentDirectory(nMaxDirLength, NULL);
|
||
if (nMaxDirLength != 0)
|
||
{
|
||
nMaxDirLength = ::GetCurrentDirectory(nMaxDirLength, sDir.GetBuffer(nMaxDirLength));
|
||
if (nMaxDirLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sDir.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... Add terminating slash if necessary
|
||
TCHAR cLastChar = *(sDir.Right(1));
|
||
if (_tcschr(COXUNC::m_pszSlashes, cLastChar) == NULL)
|
||
sDir += COXUNC::m_cBackslash;
|
||
UNC = sDir;
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetCurrentDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetCurrentDirectory(COXUNC UNC)
|
||
{
|
||
// ... We will change the parameter UNC in this function
|
||
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Remove file spacification
|
||
UNC.File().Empty();
|
||
|
||
if (!::SetCurrentDirectory(UNC))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetCurrentDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetWindowsDirectory(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
UNC.Empty();
|
||
|
||
CString sDir;
|
||
int nMaxDirLength = 0;
|
||
nMaxDirLength = ::GetWindowsDirectory(NULL, nMaxDirLength);
|
||
if (nMaxDirLength != 0)
|
||
{
|
||
nMaxDirLength = ::GetWindowsDirectory(sDir.GetBuffer(nMaxDirLength), nMaxDirLength);
|
||
if (nMaxDirLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sDir.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... Add terminating slash if necessary
|
||
TCHAR cLastChar = *(sDir.Right(1));
|
||
if (_tcschr(COXUNC::m_pszSlashes, cLastChar) == NULL)
|
||
sDir += COXUNC::m_cBackslash;
|
||
UNC = sDir;
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetWindowsDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetSystemDirectory(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
UNC.Empty();
|
||
|
||
CString sDir;
|
||
int nMaxDirLength = 0;
|
||
nMaxDirLength = ::GetSystemDirectory(NULL, nMaxDirLength);
|
||
if (nMaxDirLength != 0)
|
||
{
|
||
nMaxDirLength = ::GetSystemDirectory(sDir.GetBuffer(nMaxDirLength), nMaxDirLength);
|
||
if (nMaxDirLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sDir.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... Add terminating slash if necessary
|
||
TCHAR cLastChar = *(sDir.Right(1));
|
||
if (_tcschr(COXUNC::m_pszSlashes, cLastChar) == NULL)
|
||
sDir += COXUNC::m_cBackslash;
|
||
UNC = sDir;
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetSystemDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetApplicationDirectory(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
UNC.Empty();
|
||
|
||
CString sAppPath;
|
||
int nMaxPathLength = _MAX_PATH;
|
||
nMaxPathLength = ::GetModuleFileName(NULL, sAppPath.GetBuffer(nMaxPathLength), nMaxPathLength);
|
||
if (nMaxPathLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sAppPath.ReleaseBuffer();
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... Use path, but remove the file name
|
||
UNC = sAppPath;
|
||
UNC.File().Empty();
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetApplicationDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetTemporaryDirectory(COXUNC& UNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
UNC.Empty();
|
||
|
||
CString sDir;
|
||
int nMaxDirLength = 0;
|
||
nMaxDirLength = ::GetTempPath(nMaxDirLength, NULL);
|
||
if (nMaxDirLength != 0)
|
||
{
|
||
nMaxDirLength = ::GetTempPath(nMaxDirLength, sDir.GetBuffer(nMaxDirLength));
|
||
if (nMaxDirLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sDir.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
{
|
||
// ... Add terminating slash if necessary
|
||
TCHAR cLastChar = *(sDir.Right(1));
|
||
if (_tcschr(COXUNC::m_pszSlashes, cLastChar) == NULL)
|
||
sDir += COXUNC::m_cBackslash;
|
||
UNC = sDir;
|
||
}
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetTemporaryDirectory", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetSize(COXUNC UNC, DWORDLONG& nSize)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
nSize = 0;
|
||
|
||
ULARGE_INTEGER nFileSize;
|
||
nFileSize.LowPart = 0;
|
||
nFileSize.HighPart = 0;
|
||
HANDLE hFile = NULL;
|
||
|
||
// ... Open the (existing) file
|
||
hFile = ::CreateFile(UNC, 0 /* Query */, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
// ... Get the file size
|
||
nFileSize.LowPart = ::GetFileSize(hFile, &nFileSize.HighPart);
|
||
if (nFileSize.LowPart == MAXDWORD)
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
// If (nFileSize.LowPart == MAXDWORD) AND (GetLastError != NO_ERROR))
|
||
// Then an error has occurred
|
||
}
|
||
VERIFY(::CloseHandle(hFile));
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
nSize = nFileSize.QuadPart;
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetSize", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetCompressedSize(COXUNC UNC, DWORDLONG& nSize)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
nSize = 0;
|
||
|
||
ULARGE_INTEGER nFileSize;
|
||
nFileSize.LowPart = 0;
|
||
nFileSize.HighPart = 0;
|
||
|
||
// ... Get the compressed file size
|
||
nFileSize.LowPart = ::GetCompressedFileSize(UNC, &nFileSize.HighPart);
|
||
if (nFileSize.LowPart == MAXDWORD)
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
// If (nFileSize.LowPart == MAXDWORD) AND (GetLastError != NO_ERROR))
|
||
// Then an error has occurred
|
||
}
|
||
|
||
if (SUCCEEDED(hResult))
|
||
nSize = nFileSize.QuadPart;
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetCompressedSize", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetSize(COXUNC UNC, DWORDLONG nSize)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
ULARGE_INTEGER nWantedFileSize;
|
||
nWantedFileSize.QuadPart = nSize;
|
||
|
||
// ... Convert from unsigned to signed (needed for SetFilePointer)
|
||
LONG nWantedFileSizeLow = 0;
|
||
LONG nWantedFileSizeHigh = 0;
|
||
if (nWantedFileSize.LowPart < MAXLONG)
|
||
{
|
||
// ... High order bit of low part is not used
|
||
nWantedFileSizeLow = (LONG)nWantedFileSize.LowPart;
|
||
nWantedFileSizeHigh = (LONG)(nWantedFileSize.HighPart << 1);
|
||
}
|
||
else
|
||
{
|
||
// ... Transfer high order bit from low part to high
|
||
nWantedFileSizeLow = (LONG)(nWantedFileSize.LowPart & MAXLONG);
|
||
nWantedFileSizeHigh = (LONG)((nWantedFileSize.HighPart << 1 ) + 1);
|
||
}
|
||
|
||
|
||
DWORD nNewLowSize;
|
||
HANDLE hFile = NULL;
|
||
|
||
// ... Open the (existing) file
|
||
hFile = ::CreateFile(UNC, GENERIC_WRITE, FILE_SHARE_READ,
|
||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
// ... Set the file size
|
||
nNewLowSize = ::SetFilePointer(hFile, nWantedFileSizeLow, &nWantedFileSizeHigh, FILE_BEGIN);
|
||
if (nNewLowSize == MAXDWORD)
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
// If (nNewLowSize == MAXDWORD) AND (GetLastError != NO_ERROR))
|
||
// Then an error has occurred
|
||
}
|
||
|
||
if (SUCCEEDED(hResult))
|
||
if (!::SetEndOfFile(hFile))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
VERIFY(::CloseHandle(hFile));
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetSize", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetShortName(COXUNC UNC, COXUNC& shortUNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
shortUNC.Empty();
|
||
|
||
CString sShortPath;
|
||
int nMaxPathLength = 0;
|
||
nMaxPathLength = ::GetShortPathName(UNC, NULL, nMaxPathLength);
|
||
if (nMaxPathLength != 0)
|
||
{
|
||
nMaxPathLength = ::GetShortPathName(UNC, sShortPath.GetBuffer(nMaxPathLength), nMaxPathLength);
|
||
if (nMaxPathLength == 0)
|
||
GET_LAST_HRESULT(hResult);
|
||
sShortPath.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
shortUNC = sShortPath;
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetShortName", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetLongName(COXUNC UNC, COXUNC& longUNC)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
longUNC.Empty();
|
||
|
||
// Change every subdirectory and file name into its long name
|
||
WIN32_FIND_DATA findFileData;
|
||
HANDLE hFind = NULL;
|
||
longUNC = UNC;
|
||
|
||
// First change all the subdirectories
|
||
longUNC.File().Empty();
|
||
CString sShortDir = longUNC.Directory();
|
||
|
||
// ... Copy leading slash to result (if present)
|
||
CString sLongDir = sShortDir.Left(1);
|
||
if (_tcschr(COXUNC::m_pszSlashes, *LPCTSTR(sShortDir)) != NULL)
|
||
sLongDir = sShortDir.Left(1);
|
||
|
||
CString sDirPart;
|
||
LPCTSTR pszDirPartEnd = NULL;
|
||
if (0 < sShortDir.GetLength())
|
||
pszDirPartEnd = _tcspbrk((LPCTSTR)sShortDir + 1, COXUNC::m_pszSlashes);
|
||
int nDirLength = 0;
|
||
|
||
while(SUCCEEDED(hResult) && (pszDirPartEnd != NULL))
|
||
{
|
||
nDirLength = (int)(pszDirPartEnd - (LPCTSTR)sShortDir + 1);
|
||
UTBStr::tcsncpy(sDirPart.GetBufferSetLength(nDirLength), nDirLength, sShortDir, nDirLength);
|
||
|
||
// ... Get the long directory name
|
||
longUNC.Directory() = sDirPart;
|
||
hFind = ::FindFirstFile(longUNC.FileForm(), &findFileData);
|
||
if (hFind != INVALID_HANDLE_VALUE)
|
||
{
|
||
VERIFY(::FindClose(hFind));
|
||
sLongDir += findFileData.cFileName + CString(UNC.PreferedSlash());
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
// ... Get next subirectory
|
||
pszDirPartEnd = _tcspbrk(pszDirPartEnd + 1, COXUNC::m_pszSlashes);
|
||
}
|
||
longUNC.Directory() = sLongDir;
|
||
|
||
// Then change the file name itself
|
||
longUNC.File() = UNC.File();
|
||
hFind = ::FindFirstFile(UNC, &findFileData);
|
||
if (hFind != INVALID_HANDLE_VALUE)
|
||
{
|
||
VERIFY(::FindClose(hFind));
|
||
longUNC.File() = findFileData.cFileName;
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (FAILED(hResult))
|
||
longUNC.Empty();
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetLongName", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetLogicalDrives(CString& sDrives)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
sDrives.Empty();
|
||
|
||
int nMaxDrivesLength = 0;
|
||
nMaxDrivesLength = ::GetLogicalDriveStrings(nMaxDrivesLength, NULL);
|
||
if (nMaxDrivesLength != 0)
|
||
{
|
||
LPTSTR pszDrives = sDrives.GetBuffer(nMaxDrivesLength);
|
||
nMaxDrivesLength = ::GetLogicalDriveStrings(nMaxDrivesLength, pszDrives);
|
||
if (nMaxDrivesLength != 0)
|
||
{
|
||
// Change all NULL-characters to a '|' which is easier to use in a CString
|
||
// ... Stop when we find two NULLs after each other
|
||
pszDrives += _tcslen(pszDrives);
|
||
while (*(pszDrives + 1) != _T('\0'))
|
||
{
|
||
*pszDrives = _T('|');
|
||
pszDrives += _tcslen(pszDrives);
|
||
}
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
sDrives.ReleaseBuffer();
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
if (SUCCEEDED(hResult))
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetLogicalDrives", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetTotalDiskSpace(COXUNC UNC, DWORDLONG& nTotalSpace)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
nTotalSpace = 0;
|
||
|
||
DWORDLONG nFreeSpace = 0;
|
||
if (!GetDiskSpace(UNC.GetRoot(), nTotalSpace, nFreeSpace))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetTotalDiskSpace", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetFreeDiskSpace(COXUNC UNC, DWORDLONG& nFreeSpace)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
nFreeSpace = 0;
|
||
|
||
DWORDLONG nTotalSpace = 0;
|
||
if (!GetDiskSpace(UNC.GetRoot(), nTotalSpace, nFreeSpace))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetFreeDiskSpace", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetDriveType(COXUNC UNC, UINT& nDriveType)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
nDriveType = ::GetDriveType(UNC.GetRoot());
|
||
|
||
// ... GetDriveType does not use GetLastError so we substitute
|
||
// the result for more appropriate error codes
|
||
if (nDriveType == 0)
|
||
hResult = HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE);
|
||
else if (nDriveType == 1)
|
||
hResult = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetDriveType", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetDiskInformation(COXUNC UNC, CString& sName, DWORD& nSerialNumber,
|
||
DWORD& nMaximumComponentLength, DWORD& nFileSystemFlags, CString& sFileSystemName)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
sName.Empty();
|
||
nSerialNumber = 0;
|
||
nMaximumComponentLength = 0;
|
||
nFileSystemFlags = 0;
|
||
sFileSystemName.Empty();
|
||
|
||
const int nMaxVolumneNameLength = 256;
|
||
const int nMaxFileSystemNameLength = 256;
|
||
|
||
if (!::GetVolumeInformation(UNC.GetRoot(), sName.GetBuffer(nMaxVolumneNameLength), nMaxVolumneNameLength,
|
||
&nSerialNumber, &nMaximumComponentLength, &nFileSystemFlags,
|
||
sFileSystemName.GetBuffer(nMaxFileSystemNameLength), nMaxFileSystemNameLength))
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
|
||
sName.ReleaseBuffer();
|
||
sFileSystemName.ReleaseBuffer();
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetDiskInformation", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetDiskName(COXUNC UNC, LPCTSTR pszDiskName)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
if (!::SetVolumeLabel(UNC.GetRoot(), pszDiskName))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetDiskName", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetAttributes(COXUNC UNC, DWORD& nAttributes)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
nAttributes = ::GetFileAttributes(UNC.FileForm());
|
||
if (nAttributes == MAXDWORD)
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetAttributes", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetAttributes(COXUNC UNC, DWORD nAttributes)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
if (!::SetFileAttributes(UNC.FileForm(), nAttributes))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetAttributes", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetCompression(COXUNC UNC, USHORT nCompressionState)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
DWORD nBytesReturned = 0;
|
||
HANDLE hFile = NULL;
|
||
|
||
// Get handle to file or directory
|
||
BOOL bDirectory = UNC.File().IsEmpty();
|
||
hFile = ::CreateFile(UNC.FileForm(), GENERIC_READ,
|
||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||
bDirectory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
if (!DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &nCompressionState,
|
||
sizeof(nCompressionState), NULL, 0, &nBytesReturned, NULL))
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
VERIFY(::CloseHandle(hFile));
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetAttributes", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetCompression(COXUNC UNC, USHORT& nCompressionState)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
nCompressionState = 0;
|
||
|
||
DWORD nBytesReturned = 0;
|
||
HANDLE hFile;
|
||
|
||
// Get handle to file or directory
|
||
BOOL bDirectory = UNC.File().IsEmpty();
|
||
hFile = ::CreateFile(UNC.FileForm(), GENERIC_READ,
|
||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||
bDirectory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
if (!DeviceIoControl(hFile, FSCTL_GET_COMPRESSION, NULL, 0, &nCompressionState,
|
||
sizeof(nCompressionState), &nBytesReturned, NULL))
|
||
{
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
VERIFY(::CloseHandle(hFile));
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetCompression", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::GetTime(COXUNC UNC, CTime& creationTime,
|
||
CTime& lastAccessTime, CTime& lastWriteTime)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// ... Initialize result
|
||
creationTime = 0;
|
||
lastAccessTime = 0;
|
||
lastWriteTime = 0;
|
||
|
||
WIN32_FIND_DATA findFileData;
|
||
HANDLE hFind = ::FindFirstFile(UNC.FileForm(), &findFileData);
|
||
if (hFind != INVALID_HANDLE_VALUE)
|
||
{
|
||
VERIFY(::FindClose(hFind));
|
||
|
||
// Convert FILETIME to CTime (UTC -> local -> system)
|
||
creationTime = CTime(findFileData.ftCreationTime);
|
||
lastAccessTime = CTime(findFileData.ftLastAccessTime);
|
||
lastWriteTime = CTime(findFileData.ftLastWriteTime);
|
||
|
||
// When creation and last access is not supported, use last write time
|
||
if (creationTime.GetTime() == 0)
|
||
creationTime = lastWriteTime;
|
||
if (lastAccessTime.GetTime() == 0)
|
||
lastAccessTime = lastWriteTime;
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::GetTime", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::SetTime(COXUNC UNC, CTime creationTime, CTime lastAccessTime,
|
||
CTime lastWriteTime)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
BOOL bDirectory = UNC.File().IsEmpty();
|
||
HANDLE hFile = ::CreateFile(UNC.FileForm(), GENERIC_READ|GENERIC_WRITE,
|
||
FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||
bDirectory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
FILETIME newCreationTime;
|
||
FILETIME newLastAccessTime;
|
||
FILETIME newLastWriteTime;
|
||
|
||
LPFILETIME pNewCreationTime = NULL;
|
||
LPFILETIME pNewLastAccessTime = NULL;
|
||
LPFILETIME pNewLastWriteTime = NULL;
|
||
|
||
// Convert CTime to FILETIME (sytem -> local -> UTC)
|
||
if ((creationTime.GetTime() != 0) && TimeToFileTime(creationTime, &newCreationTime))
|
||
pNewCreationTime = &newCreationTime;
|
||
if ((lastAccessTime.GetTime() != 0) && TimeToFileTime(lastAccessTime, &newLastAccessTime))
|
||
pNewLastAccessTime = &newLastAccessTime;
|
||
if ((lastWriteTime.GetTime() != 0) && TimeToFileTime(lastWriteTime, &newLastWriteTime))
|
||
pNewLastWriteTime = &newLastWriteTime;
|
||
|
||
// Set the new times
|
||
if (!::SetFileTime(hFile, pNewCreationTime, pNewLastAccessTime, pNewLastWriteTime))
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
VERIFY(::CloseHandle(hFile));
|
||
}
|
||
else
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::SetTime", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::FindFirstFile(COXUNC UNC, HANDLE &hFindFile, WIN32_FIND_DATA &findFileData,
|
||
BOOL /* bOnlyDirectories */ /* = FALSE */)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
|
||
// bOnlyDirectories is ignored for now
|
||
hFindFile = ::FindFirstFile(UNC.FileForm(), &findFileData);
|
||
if (hFindFile == INVALID_HANDLE_VALUE)
|
||
{
|
||
// ... Use a NULL handle instead of INVALID_HANDLE_VALUE
|
||
hFindFile = NULL;
|
||
GET_LAST_HRESULT(hResult);
|
||
}
|
||
|
||
#ifdef _DEBUG
|
||
// The ERROR_FILE_NOT_FOUND condition is a situation that is likely to occur
|
||
// (viz. at the end of each iteration)
|
||
// We do not trace a message then
|
||
if (HRESULT_CODE(hResult) != ERROR_FILE_NOT_FOUND)
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::FindFirstFile", hResult);
|
||
#endif
|
||
|
||
return hResult;
|
||
}
|
||
|
||
|
||
HRESULT COXUNCStandardActor::FindNextFile(HANDLE hFindFile, WIN32_FIND_DATA &findFileData)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
BOOL bSuccess = TRUE;
|
||
|
||
bSuccess = ::FindNextFile(hFindFile, &findFileData);
|
||
if (!bSuccess)
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
#ifdef _DEBUG
|
||
// The ERROR_NO_MORE_FILES condition is a situation that is likely to occur
|
||
// (viz. at the end of each iteration)
|
||
// We do not trace a message then
|
||
if (HRESULT_CODE(hResult) != ERROR_NO_MORE_FILES)
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::FindNextFile", hResult);
|
||
#endif
|
||
|
||
return hResult;
|
||
}
|
||
|
||
HRESULT COXUNCStandardActor::FindClose(HANDLE hFindFile)
|
||
{
|
||
HRESULT hResult = ERROR_SUCCESS;
|
||
BOOL bSuccess = TRUE;
|
||
|
||
bSuccess = ::FindClose(hFindFile);
|
||
if (!bSuccess)
|
||
GET_LAST_HRESULT(hResult);
|
||
|
||
CONDITIONAL_TRACE_RESULT("COXUNCStandardActor::FindClose", hResult);
|
||
return hResult;
|
||
}
|
||
|
||
|
||
#ifdef _DEBUG
|
||
void COXUNCStandardActor::AssertValid() const
|
||
{
|
||
CObject::AssertValid();
|
||
}
|
||
|
||
void COXUNCStandardActor::Dump(CDumpContext& dc) const
|
||
{
|
||
CObject::Dump(dc);
|
||
}
|
||
#endif //_DEBUG
|
||
|
||
COXUNCStandardActor::~COXUNCStandardActor()
|
||
{
|
||
}
|
||
|
||
// protected:
|
||
#ifdef _DEBUG
|
||
|
||
static TCHAR szUnknownError[] = _T("*** Unknown Error ***");
|
||
static DWORD dwLangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
|
||
|
||
CString COXUNCStandardActor::GetResultMessage(HRESULT hResult)
|
||
// --- In : hResult : The result code
|
||
// --- Out :
|
||
// --- Returns : A string containg a message of the specified code
|
||
// --- Effect :
|
||
{
|
||
CString sResultMessage;
|
||
LPTSTR pszMsgBuf = NULL;
|
||
BOOL bUnknown = FALSE;
|
||
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
|
||
|
||
// ... Remove the facility part if FACILITY_WIN32
|
||
if (HRESULT_FACILITY(hResult) == FACILITY_WIN32)
|
||
hResult = HRESULT_CODE(hResult);
|
||
|
||
// ... Get the actual message
|
||
if (::FormatMessage(dwFlags, NULL, hResult, dwLangID,
|
||
(LPTSTR)&pszMsgBuf, 0, NULL) == 0)
|
||
{
|
||
TRACE2("COXUNCStandardActor::GetResultMessage : No message was found for result code %i == 0x%8.8X\n",
|
||
hResult, hResult);
|
||
//pszMsgBuf = szUnknownError;
|
||
VERIFY(sResultMessage.LoadString(IDS_OX_UNCUNKNOWNERROR));
|
||
bUnknown = TRUE;
|
||
}
|
||
else
|
||
sResultMessage = pszMsgBuf;
|
||
|
||
// ... Clean up
|
||
if (!bUnknown)
|
||
LocalFree(pszMsgBuf);
|
||
|
||
return sResultMessage;
|
||
}
|
||
#endif //_DEBUG
|
||
|
||
BOOL COXUNCStandardActor::GetDiskSpace(LPCTSTR pszRoot, DWORDLONG& nTotalSpace, DWORDLONG& nFreeSpace)
|
||
// --- In : pszRoot : The root of wich info is requested
|
||
// --- Out : nTotalSpace : The total space in bytes
|
||
// nFreeSpace : The free space in bytes
|
||
// --- Returns : Whether it was successful or not
|
||
// --- Effect : Computes the total and free space of a disk
|
||
{
|
||
BOOL bSuccess = TRUE;
|
||
|
||
// Check whether we can use the GetDiskFreeSpaceEx function
|
||
// This is available on Windows 95 systems beginning with OEM Service Release 2 (OSR 2).
|
||
|
||
// ... Can we use GetDiskFreeSpaceEx
|
||
BOOL bExFunctionAvailable = FALSE;
|
||
|
||
// Check the OS Version number
|
||
OSVERSIONINFO OSVersionInfo;
|
||
::ZeroMemory(&OSVersionInfo, sizeof(OSVersionInfo));
|
||
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
|
||
VERIFY(::GetVersionEx(&OSVersionInfo));
|
||
if ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
|
||
(1000 < LOWORD(OSVersionInfo.dwBuildNumber)) )
|
||
bExFunctionAvailable = TRUE;
|
||
|
||
if (bExFunctionAvailable)
|
||
{
|
||
// GetDiskFreeSpaceEx function is available
|
||
ULARGE_INTEGER nFreeBytesAvailableToCaller;
|
||
ULARGE_INTEGER nTotalNumberOfBytes;
|
||
ULARGE_INTEGER nTotalNumberOfFreeBytes;
|
||
nFreeBytesAvailableToCaller.QuadPart = 0;
|
||
nTotalNumberOfBytes.QuadPart = 0;
|
||
nTotalNumberOfFreeBytes.QuadPart = 0;
|
||
|
||
HINSTANCE hKernelInstance = NULL;
|
||
BOOL (*pfnGetDiskFreeSpaceEx)(LPCTSTR lpDirectoryName,
|
||
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
|
||
PULARGE_INTEGER lpTotalNumberOfBytes,
|
||
PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
|
||
|
||
hKernelInstance = ::LoadLibrary(_T("KERNEL32.DLL"));
|
||
if (hKernelInstance != NULL)
|
||
(FARPROC&)pfnGetDiskFreeSpaceEx = ::GetProcAddress(hKernelInstance, "GetDiskFreeSpaceEx");
|
||
if (pfnGetDiskFreeSpaceEx == NULL)
|
||
{
|
||
TRACE0("COXUNCStandardActor::GetDiskSpace : Dynamic load of GetDiskFreeSpaceEx function failed\n");
|
||
// ... Try GetDiskFreeSpace function
|
||
bExFunctionAvailable = FALSE;
|
||
}
|
||
|
||
bSuccess = bExFunctionAvailable && (*pfnGetDiskFreeSpaceEx)(pszRoot, &nFreeBytesAvailableToCaller, &nTotalNumberOfBytes, &nTotalNumberOfFreeBytes);
|
||
if (bSuccess)
|
||
{
|
||
nTotalSpace = nTotalNumberOfBytes.QuadPart;
|
||
nFreeSpace = nTotalNumberOfFreeBytes.QuadPart;
|
||
}
|
||
|
||
// ... No need to call FreeLibrary because KERNEL32 will stay loaded anyway
|
||
}
|
||
|
||
if (!bExFunctionAvailable)
|
||
{
|
||
// GetDiskFreeSpaceEx function is not available, use GetDiskFreeSpace
|
||
DWORD nSectorsPerCluster = 0;
|
||
DWORD nBytesPerSector = 0;
|
||
DWORD nNumberOfFreeClusters = 0;
|
||
DWORD nTotalNumberOfClusters = 0;
|
||
|
||
bSuccess = ::GetDiskFreeSpace(pszRoot, &nSectorsPerCluster, &nBytesPerSector,
|
||
&nNumberOfFreeClusters, &nTotalNumberOfClusters);
|
||
if (bSuccess)
|
||
{
|
||
nTotalSpace = UInt32x32To64(nTotalNumberOfClusters, nSectorsPerCluster) * (DWORDLONG)nBytesPerSector;
|
||
nFreeSpace = UInt32x32To64(nNumberOfFreeClusters, nSectorsPerCluster) * (DWORDLONG)nBytesPerSector;
|
||
}
|
||
}
|
||
|
||
return bSuccess;
|
||
}
|
||
|
||
BOOL COXUNCStandardActor::TimeToFileTime(const CTime& time, LPFILETIME pFileTime)
|
||
// --- In : time
|
||
// pFileTime : Points to a FILETIME object
|
||
// --- Out : pFileTime : The filled out object
|
||
// --- Returns : Whether it was successful or not
|
||
// --- Effect : Converts a CTime object to a FILETIME object
|
||
{
|
||
SYSTEMTIME sysTime;
|
||
sysTime.wYear = (WORD)time.GetYear();
|
||
sysTime.wMonth = (WORD)time.GetMonth();
|
||
sysTime.wDay = (WORD)time.GetDay();
|
||
sysTime.wHour = (WORD)time.GetHour();
|
||
sysTime.wMinute = (WORD)time.GetMinute();
|
||
sysTime.wSecond = (WORD)time.GetSecond();
|
||
sysTime.wMilliseconds = 0;
|
||
|
||
// Convert system time to local file time
|
||
FILETIME localTime;
|
||
if (!::SystemTimeToFileTime((LPSYSTEMTIME)&sysTime, &localTime))
|
||
{
|
||
TRACE0("COXUNCStandardActor::TimeToFileTime : Illegal system time encountered, ignoring\n");
|
||
return FALSE;
|
||
}
|
||
|
||
// Convert local file time to UTC file time
|
||
if (!::LocalFileTimeToFileTime(&localTime, pFileTime))
|
||
{
|
||
TRACE0("COXUNCStandardActor::TimeToFileTime : Illegal logal file time encountered, ignoring\n");
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// private:
|
||
|
||
// ==========================================================================
|