📄 cpath.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CPath.cpp,v 1.14 2002/08/06 20:10:46 dallen Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include <commdlg.h>
#include <dbt.h>
#include <shellapi.h>
#include <shlobj.h>
#include "CFile.h"
#include "CComLibrary.h"
#include "CComObject.h"
#include "CPath.h"
#include "CRegistryKey.h"
#include "UDynLink.h"
#include "UUnicode.h"
#include "UWinVersion.h"
_USING_PGP
_UNNAMED_BEGIN
// Constants
const HKEY kRegistryMappedDriveRoot = HKEY_CURRENT_USER;
const char *kRegistryMappedDrive98Section = "Network\\Persistent";
const char *kRegistryMappedDriveNTSection = "Network";
const char *kInvalidPathChars = "<>:\"|";
const char *k83InvalidPathChars = "<>:\"|,;*? ";
const char *kShortCutExtension = ".lnk";
_UNNAMED_END
// Class CPath member functions
CPath::CPath() : mFindHandle(INVALID_HANDLE_VALUE)
{
}
CPath::CPath(const char *str) :
CString(str), mFindHandle(INVALID_HANDLE_VALUE)
{
}
CPath::CPath(const CPath& path) :
CString(path.Get()), mFindHandle(INVALID_HANDLE_VALUE)
{
}
CPath&
CPath::operator=(const char *str)
{
CString::operator=(str);
return *this;
}
CPath::~CPath()
{
try
{
if (FindInProgress())
FindClose();
}
catch (CComboError&) { }
}
CPath&
CPath::operator=(const CPath& path)
{
return operator=(path.Get());
}
PGPBoolean
CPath::HasPlainLocalRoot() const
{
return ((Length() >= 3) &&
(UString::LetterToNumber(GetAt(0)) < kMaxDrives) &&
(GetAt(1) == ':') && (IsSlashChar(GetAt(2))));
}
PGPBoolean
CPath::IsPlainLocalRoot() const
{
return ((Length() == 3) && HasPlainLocalRoot());
}
PGPBoolean
CPath::IsNetworkedPath() const
{
if (IsUNCPath())
return TRUE;
CPath root;
GetRootPart(root);
return (GetDriveType(root) == DRIVE_REMOTE);
}
PGPBoolean
CPath::IsShortCut() const
{
if (Length() < 4)
return FALSE;
CPath ext;
GetExtensionPart(ext);
return ext.CompareNoCase(kShortCutExtension);
}
PGPBoolean
CPath::IsUNCPath() const
{
if (!IsSlashChar(GetAt(0)) || !IsSlashChar(GetAt(1)))
return FALSE;
PGPUInt32 length = Length();
PGPUInt32 numSlashes = 0;
for (PGPUInt32 i = 0; i < length; i++)
{
if (IsSlashChar(GetAt(i)))
numSlashes++;
if (numSlashes >= 3)
return TRUE;
}
return FALSE;
}
PGPBoolean
CPath::EndsInExtension() const
{
for (PGPInt32 i = Length(); i > 0; i--)
{
char c = GetAt(i);
if (IsSlashChar(c))
return FALSE;
else if (c == '.')
return TRUE;
}
return FALSE;
}
PGPBoolean
CPath::IsLegalPath() const
{
if (IsEmpty())
return FALSE;
PGPBoolean supportsLong = SupportsLongFilenames();
PGPUInt32 i, startChar;
if (HasPlainLocalRoot())
startChar = 3;
else if (IsUNCPath())
startChar = 0;
else
return FALSE;
PGPUInt32 lengthPath = Length();
if (supportsLong)
{
PGPUInt32 lengthInv = strlen(kInvalidPathChars);
for (i = startChar; i < lengthPath; i++)
{
for (PGPUInt32 j = 0; j < lengthInv; j++)
{
if (GetAt(i) == kInvalidPathChars[j])
return FALSE;
}
}
}
else
{
PGPUInt32 lengthInv = strlen(k83InvalidPathChars);
for (i = startChar; i < lengthPath; i++)
{
for (PGPUInt32 j = 0; j < lengthInv; j++)
{
if (GetAt(i) == k83InvalidPathChars[j])
return FALSE;
}
}
}
if (!supportsLong)
{
PGPInt32 chunkSize = 0;
for (i = lengthPath - 1; i >= 0; i--)
{
char c = GetAt(i);
if (c == '.')
{
if (chunkSize > 3)
return FALSE;
chunkSize = 0;
}
if (IsSlashChar(c))
break;
chunkSize++;
}
if (chunkSize > 8)
return FALSE;
}
return TRUE;
}
PGPBoolean
CPath::IsValidDirectory() const
{
PGPUInt32 attribs = GetFileAttributes(Get());
if (attribs == 0xFFFFFFFF)
return FALSE;
else
return (attribs & FILE_ATTRIBUTE_DIRECTORY ? TRUE : FALSE);
}
PGPBoolean
CPath::IsValidFile() const
{
PGPUInt32 attribs = GetFileAttributes(Get());
if (attribs == 0xFFFFFFFF)
return FALSE;
else
return (attribs & FILE_ATTRIBUTE_DIRECTORY ? FALSE : TRUE);
}
PGPBoolean
CPath::IsCompressed() const
{
return (GetFileAttributes(Get()) & FILE_ATTRIBUTE_COMPRESSED ? TRUE :
FALSE);
}
PGPBoolean
CPath::IsDriveNetworkMapped() const
{
pgpAssert(HasPlainLocalRoot());
CString keyName;
keyName.Format("%c", GetAt(0));
CString regPathToMapped;
if (UWinVersion::IsWin95Compatible())
regPathToMapped = kRegistryMappedDrive98Section;
else
regPathToMapped = kRegistryMappedDriveNTSection;
regPathToMapped.Append(kBackSlash);
regPathToMapped.Append(keyName);
// If key exists, drive is claimed.
PGPBoolean isMapped = FALSE;
try
{
CRegistryKey mappedDriveKey;
mappedDriveKey.Open(kRegistryMappedDriveRoot, regPathToMapped,
KEY_READ);
isMapped = TRUE;
}
catch (CComboError&) { }
return isMapped;
}
PGPBoolean
CPath::IsReadOnly() const
{
PGPBoolean isReadOnly;
try
{
if (IsValidDirectory())
{
// Attempt to create a temporary file in the directory.
CFile theFile;
CPath tempName;
if (!GetTempFileName(Get(), "pgp", 0,
tempName.GetBuffer(PFLConstants::kMaxPathLength)))
{
THROW_PGPERROR(kPGPError_FileOpFailed);
}
tempName.ReleaseBuffer();
theFile.Delete(tempName);
isReadOnly = FALSE;
}
else
{
// Try to write a byte to the file.
CFile theFile;
PGPByte firstByte;
theFile.Open(Get());
PGPUInt64 length = theFile.GetLength();
if (length > 0)
theFile.Read(&firstByte, 0, 1);
theFile.Write(&firstByte, 0, 1);
if (length == 0)
theFile.SetLength(0);
isReadOnly = FALSE;
}
}
catch (CComboError&)
{
isReadOnly = TRUE;
}
return isReadOnly;
}
PGPBoolean
CPath::IsDirectoryEmpty() const
{
CPath allFiles(*this);
allFiles.EndInSlash();
allFiles.Append("*");
CPath curFile;
if (!allFiles.FindFirstFile(curFile))
THROW_ERRORS(kPGPError_FileOpFailed, GetLastError());
PGPBoolean foundFiles = FALSE;
do
{
if ((curFile == ".") || (curFile == ".."))
continue;
foundFiles = TRUE;
}
while (allFiles.FindNextFile(curFile));
allFiles.FindClose();
return !foundFiles;
}
PGPUInt64
CPath::GetFreeVolumeSpace() const
{
// We must pass the root, not the path, to the system.
CPath root;
GetRootPart(root);
ULARGE_INTEGER freeAvail;
// There are two different functions - for OSR1 and for everything else.
if (UWinVersion::IsWin95OSR2Compatible() ||
UWinVersion::IsWinNT4Compatible())
{
PGPUInt32 result;
ULARGE_INTEGER totalBytes, totalFreeBytes;
result = UDynLink::GetDiskFreeSpaceEx(root, &freeAvail,
&totalBytes, &totalFreeBytes);
if (!result)
THROW_ERRORS(kPGPError_FileOpFailed, GetLastError());
}
else
{
unsigned long spc, bps, freeClust, totalClust;
if (!GetDiskFreeSpace(root, &spc, &bps, &freeClust, &totalClust))
THROW_ERRORS(kPGPError_FileOpFailed, GetLastError());
freeAvail.QuadPart = bps * spc * freeClust;
}
return freeAvail.QuadPart;
}
PGPBoolean
CPath::TestFreeVolumeSpace(PGPUInt64 bytes) const
{
CPath dir;
GetDirPart(dir);
// Open a temporary file in the directory.
CPath tempPath;
try
{
GetTempFileName(dir, "pgp", 0,
tempPath.GetBuffer(PFLConstants::kMaxPathLength));
tempPath.ReleaseBuffer();
CFile tempFile;
tempFile.Open(tempPath, CFile::kCreateIfFlag);
// Set the file to the desired length.
tempFile.SetLength(bytes);
// Make absolutely sure by closing and re-opening file.
tempFile.Close();
tempFile.Open(tempPath);
if (tempFile.GetLength() != bytes)
return FALSE;
tempFile.Close();
tempFile.Delete(tempPath);
return TRUE;
}
catch (CComboError&)
{
return FALSE;
}
}
PGPBoolean
CPath::SupportsLongFilenames() const
{
try
{
CPath volRoot;
GetVolumeRoot(volRoot);
if (UWinVersion::IsWin2000Compatible())
{
CPath realRoot;
PGPBoolean succeeded =
UDynLink::Win2k_GetVolumeNameForVolumeMountPoint(volRoot,
realRoot.GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength);
realRoot.ReleaseBuffer();
if (succeeded)
{
volRoot = realRoot;
volRoot.EndInSlash();
}
}
DWORD maxLength;
if (!GetVolumeInformation(volRoot, NULL, 0, NULL, &maxLength, NULL,
NULL, 0))
{
THROW_ERRORS(kPGPError_VolumeOpFailed, GetLastError());
}
return (maxLength >= 255);
}
catch (CComboError&)
{
return TRUE;
}
}
void
CPath::GetVolumeFileSys(CString& fileSys) const
{
CPath volRoot;
GetVolumeRoot(volRoot);
if (UWinVersion::IsWin2000Compatible())
{
CPath realRoot;
PGPBoolean succeeded =
UDynLink::Win2k_GetVolumeNameForVolumeMountPoint(volRoot,
realRoot.GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength);
realRoot.ReleaseBuffer();
if (succeeded)
{
volRoot = realRoot;
volRoot.EndInSlash();
}
}
if (!GetVolumeInformation(volRoot, NULL, 0, NULL, NULL, NULL,
fileSys.GetBuffer(32), 32))
{
fileSys.ReleaseBuffer();
THROW_ERRORS(kPGPError_VolumeOpFailed, GetLastError());
}
fileSys.ReleaseBuffer();
}
void
CPath::GetVolumeRoot(CPath& volRoot) const
{
if (UWinVersion::IsWin2000Compatible())
{
PGPBoolean succeeded =
UDynLink::Win2k_GetVolumePathName(Get(),
volRoot.GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength);
volRoot.ReleaseBuffer();
if (succeeded)
{
volRoot.EndInSlash();
return;
}
}
GetRootPart(volRoot);
}
void
CPath::GetRootPart(CPath& root) const
{
if (HasPlainLocalRoot())
{
Left(3, root);
}
else if (IsUNCPath())
{
PGPUInt32 length = Length();
PGPUInt32 numSlashes = 0;
for (PGPUInt32 i = 0; i < length; i++)
{
if (IsSlashChar(GetAt(i)))
numSlashes++;
root.Append(GetAt(i));
if (numSlashes == 4)
break;
}
}
}
void
CPath::GetDirPart(CPath& dir) const
{
CPath fileName;
GetFileNamePart(fileName);
Left(Length() - fileName.Length(), dir);
if (!dir.IsEmpty())
dir.EndInSlash();
}
// GetDirPartSmart is like GetDirPart except it tacks on a working
// directory path to incomplete directories.
void
CPath::GetDirPartSmart(CPath& dir) const
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -