1287 lines
36 KiB
C++
1287 lines
36 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:
|
|
|
|
// ==========================================================================
|