📄 cpath.cpp
字号:
{
CPath tempDir;
if (!HasPlainLocalRoot() && !IsUNCPath())
{
tempDir.AssignCurrentDirectory();
if (IsSlashChar(GetAt(0)))
tempDir.DontEndInSlash();
else
tempDir.EndInSlash();
tempDir.Append(Get());
if (tempDir.IsValidDirectory())
tempDir.EndInSlash();
}
else
{
tempDir = Get();
}
tempDir.GetDirPart(dir);
}
void
CPath::GetExtensionPart(CPath& extension) const
{
extension.Empty();
PGPUInt32 length = Length();
for (PGPInt32 i = length; i > 0; i--)
{
char c = GetAt(i);
if (IsSlashChar(c))
break;
extension.Prepend(c);
if (c == '.')
break;
}
}
void
CPath::GetFileNamePart(CPath& fileName) const
{
fileName.Empty();
PGPUInt32 length = Length();
for (PGPInt32 i = length; i > 0; i--)
{
char c = GetAt(i);
if (IsSlashChar(c))
break;
fileName.Prepend(c);
}
}
void
CPath::GetServerPart(CPath& server) const
{
pgpAssert(IsUNCPath());
Mid(2, Find(kBackSlash, 3) - 1, server);
}
void
CPath::GetSharePart(CPath& share) const
{
pgpAssert(IsUNCPath());
PGPUInt32 firstChar = Find(kBackSlash, 3) + 1;
PGPUInt32 lastChar = Find(kBackSlash, 4);
if (lastChar == -1)
lastChar = Length();
else
lastChar--;
Mid(firstChar, lastChar, share);
}
PGPUInt32
CPath::GetFreeDrives(PGPBoolean ignoreAB)
{
PGPUInt8 i;
PGPUInt32 drives = GetLogicalDrives();
PGPUInt32 freeDrives = 0;
// Return array of drives we can actually use.
PGPUInt32 startDrive = (ignoreAB ? 2 : 0);
for (i = startDrive; i < kMaxDrives; i++)
{
if (!(drives & (1 << i)))
{
CPath root;
root.MakePlainLocalRoot(i);
if (!root.IsDriveNetworkMapped())
freeDrives |= (1 << i);
}
}
return freeDrives;
}
void
CPath::AddExtension(const char *ext)
{
pgpAssertStrValid(ext);
if (!IsEmpty() && !EndsInExtension())
Append(ext);
}
void
CPath::RemoveExtension()
{
for (PGPInt32 i = Length(); i > 0; i--)
{
char c = GetAt(i);
if (IsSlashChar(c))
{
break;
}
else if (c == '.')
{
Resize(i);
break;
}
}
}
void
CPath::GetDisplayFileName(CPath& displayName) const
{
GetFileTitle(Get(), displayName.GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength);
displayName.ReleaseBuffer();
}
void
CPath::ConvertPathToLong()
{
CPath prefix;
GetRootPart(prefix);
CPath postfix;
Right(Length() - prefix.Length(), postfix);
postfix.DontEndInSlash();
Empty();
while (!postfix.IsEmpty())
{
CPath fullPath = prefix;
fullPath.Append(postfix);
CPath fileName;
if (!fullPath.FindFirstFile(fileName))
THROW_ERRORS(kPGPError_FileOpFailed, GetLastError());
fullPath.FindClose();
int lastSlash = postfix.ReverseFind(kBackSlash);
if (lastSlash == -1)
postfix.Empty();
else
postfix.Resize(lastSlash);
if (!IsEmpty())
Prepend(kBackSlash);
Prepend(fileName);
}
Prepend(prefix);
if (IsValidDirectory())
EndInSlash();
else
DontEndInSlash();
}
void
CPath::ConvertPathToShort()
{
CPath temp;
GetShortPathName(Get(), temp.GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength);
Assign(temp);
}
void
CPath::EndInSlash()
{
if (!EndsInSlash())
Append(kBackSlash);
}
void
CPath::DontEndInSlash()
{
if (EndsInSlash())
Resize(Length() - 1);
}
void
CPath::FixSlashes()
{
for (PGPUInt16 i = 0; i < Length(); i++)
{
if (GetAt(i) == kForwardSlash)
SetAt(i, kBackSlash);
}
}
void
CPath::ResolveLocalToUNC()
{
using namespace UDynLink;
if (UWinVersion::IsWin95Compatible())
{
CPath tempPath = Get();
PGPBoolean result = Win95_WNetGetUniversalName(tempPath,
GetBuffer(PFLConstants::kMaxPathLength));
ReleaseBuffer();
if (!result)
THROW_ERRORS(kPGPError_NetworkOpFailed, GetLastError());
}
else if (UWinVersion::IsWinNT4Compatible())
{
unsigned long bufSize = sizeof(UNIVERSAL_NAME_INFO) +
PFLConstants::kMaxPathLength * sizeof(WCHAR);
CArray<PGPByte> uniInfoBuf(bufSize);
UNIVERSAL_NAME_INFO *pUNI =
reinterpret_cast<UNIVERSAL_NAME_INFO *>(uniInfoBuf.Get());
PGPUInt32 result = WinNT_WNetGetUniversalName(Get(),
UNIVERSAL_NAME_INFO_LEVEL, pUNI, &bufSize);
if (result != NO_ERROR)
THROW_ERRORS(kPGPError_NetworkOpFailed, result);
Assign(pUNI->lpUniversalName);
}
else
{
pgpAssert(FALSE);
}
}
void
CPath::ResolveUNCToLocal()
{
using namespace UDynLink;
// extract strings we will use
CPath root;
GetRootPart(root);
CPath notRoot;
Right(Length() - root.Length(), notRoot);
CPath server;
GetServerPart(server);
CPath share;
GetSharePart(share);
CPath newRoot;
// check equality of computer name manually, NetShareGetInfo is flaky
CString computerName;
DWORD maxCNSize = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(computerName.GetBuffer(maxCNSize), &maxCNSize);
if (!server.CompareNoCase(computerName))
return;
if (UWinVersion::IsWin95Compatible())
{
share.Uppercase(); // must be uppercase
PGPUInt32 bufSize = sizeof(share_info_50) + MAX_PATH +
MAXCOMMENTSZ + 2;
CArray<PGPByte> shareInfoBuf(bufSize);
share_info_50 *pSI50 = reinterpret_cast<share_info_50 *>(
shareInfoBuf.Get());
unsigned short cbTotalAvail;
PGPUInt32 result = Win95_NetShareGetInfo(NULL, share, 50,
reinterpret_cast<char *>(pSI50), bufSize, &cbTotalAvail);
if (result != NERR_Success)
THROW_ERRORS(kPGPError_NetworkOpFailed, result);
newRoot = pSI50->shi50_path;
}
else if (UWinVersion::IsWinNT4Compatible())
{
CArray<WCHAR> uniServer;
UUnicode::AsciiToUni(server, uniServer);
CArray<WCHAR> uniSharePath;
UUnicode::AsciiToUni(share, uniSharePath);
SHARE_INFO_2 *pSI2;
PGPUInt32 result = WinNT_NetShareGetInfo(uniServer.Get(),
uniSharePath.Get(), 2, reinterpret_cast<LPBYTE *>(&pSI2));
if (result != NERR_Success)
THROW_ERRORS(kPGPError_NetworkOpFailed, result);
UUnicode::UniToAscii(pSI2->shi2_path, newRoot);
WinNT_NetApiBufferFree(pSI2);
}
Assign(newRoot);
EndInSlash();
Append(notRoot);
}
void
CPath::ResolveLoopBackPath()
{
try
{
if (IsNetworkedPath())
{
if (!IsUNCPath())
ResolveLocalToUNC();
ResolveUNCToLocal();
}
}
catch (CComboError&) { }
}
void
CPath::ResolveShortCut()
{
pgpAssert(IsShortCut());
PGPUInt32 result;
// Load COM.
CComLibrary comLibrary;
// Get a pointer to the IShellLink interface.
CComObject<IShellLink> pShellLink(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink);
// Get a pointer to the IPersistFile interface.
CComObject<IPersistFile> pIPF(static_cast<IPersistFile *>(
pShellLink.QueryInterface(IID_IPersistFile)));
// Ensure that the string is Unicode.
CArray<WCHAR> uniSCPath;
UUnicode::AsciiToUni(Get(), uniSCPath);
// Load the shortcut.
result = pIPF->Load(uniSCPath.Get(), STGM_READ);
if (result != S_OK)
THROW_ERRORS(kPGPError_Win32COMOpFailed, result);
// Resolve the link.
result = pShellLink->Resolve(GetDesktopWindow(), SLR_ANY_MATCH);
if (result != NOERROR)
THROW_ERRORS(kPGPError_Win32COMOpFailed, result);
// Get the path to the link target.
WIN32_FIND_DATA WFD;
result = pShellLink->GetPath(GetBuffer(PFLConstants::kMaxPathLength),
PFLConstants::kMaxPathLength, &WFD, SLGP_SHORTPATH);
ReleaseBuffer();
if (result != NOERROR)
THROW_ERRORS(kPGPError_Win32COMOpFailed, result);
}
void
CPath::Canonicalize(const char *extension)
{
FixSlashes();
if (IsShortCut())
ResolveShortCut();
if (IsValidDirectory())
EndInSlash();
// If looped back, resolve it a to local path. This check WILL fail
// under non-Admin accounts under NT, we take care of that later.
ResolveLoopBackPath();
// Fill out filename if this is a file.
if (!IsValidDirectory())
{
CPath dir;
GetDirPartSmart(dir);
CPath bareName;
GetFileNamePart(bareName);
char *pFilePart;
if (!::SearchPath(dir, bareName, extension,
PFLConstants::kMaxPathLength,
GetBuffer(PFLConstants::kMaxPathLength), &pFilePart))
{
ReleaseBuffer();
THROW_PGPERROR(kPGPError_FileNotFound);
}
ReleaseBuffer();
}
// Convert to long pathname form.
ConvertPathToLong();
}
PGPBoolean
CPath::FindFirstFile(CPath& fileName)
{
pgpAssert(!FindInProgress());
WIN32_FIND_DATA findData;
mFindHandle = ::FindFirstFile(Get(), &findData);
if (mFindHandle == INVALID_HANDLE_VALUE)
return FALSE;
fileName = findData.cFileName;
return TRUE;
}
PGPBoolean
CPath::FindNextFile(CPath& fileName)
{
pgpAssert(FindInProgress());
WIN32_FIND_DATA findData;
if (!::FindNextFile(mFindHandle, &findData))
return FALSE;
fileName = findData.cFileName;
return TRUE;
}
void
CPath::FindClose()
{
pgpAssert(FindInProgress());
::FindClose(mFindHandle);
mFindHandle = INVALID_HANDLE_VALUE;
}
void
CPath::AssignCurrentDirectory()
{
PGPUInt32 result = GetCurrentDirectory(PFLConstants::kMaxPathLength,
GetBuffer(PFLConstants::kMaxPathLength));
ReleaseBuffer();
if (result == 0)
THROW_ERRORS(kPGPError_FileOpFailed, result);
}
void
CPath::BroadcastDriveMessage(WPARAM msg) const
{
pgpAssert(HasPlainLocalRoot());
DEV_BROADCAST_VOLUME DBV;
PGPInt32 result;
DBV.dbcv_size = sizeof(DBV);
DBV.dbcv_devicetype = DBT_DEVTYP_VOLUME;
DBV.dbcv_reserved = 0;
DBV.dbcv_unitmask = 1 << GetDriveNum();
DBV.dbcv_flags = 0; // MS says this should be zero instead of DBTF_MEDIA; wjb
result = UDynLink::BroadcastSystemMessage(
BSF_IGNORECURRENTTASK | BSF_POSTMESSAGE, NULL, WM_DEVICECHANGE, msg,
reinterpret_cast<LPARAM>(&DBV));
if (result < 1)
THROW_PGPERROR(kPGPError_Win32WindowOpFailed);
}
void
CPath::MakePlainLocalRoot(PGPUInt8 drive)
{
Format("%c:\\", UString::NumberToLetter(drive));
}
void
CPath::RecurseCreateDir()
{
CPath prefix;
GetRootPart(prefix);
CPath postfix;
Right(Length() - prefix.Length(), postfix);
postfix.EndInSlash();
CPath fullDir = prefix;
while (!postfix.IsEmpty())
{
PGPInt32 nextSlash = postfix.Find(kBackSlash);
CPath curDir;
postfix.Left(nextSlash + 1, curDir);
fullDir += curDir;
if (!fullDir.IsValidDirectory() && !CreateDirectory(fullDir, NULL))
THROW_ERRORS(kPGPError_FileOpFailed, GetLastError());
CPath temp;
postfix.Right(postfix.Length() - nextSlash - 1, temp);
postfix = temp;
}
}
void
CPath::Browse() const
{
SHELLEXECUTEINFO sei;
pgpClearMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.lpVerb = "explore";
sei.lpFile = Get();
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
PGPBoolean
CPath::AreShowingExtensions()
{
CPath appPath;
// Get the pathname of the application.
PGPUInt32 result = GetModuleFileName(NULL, appPath.GetBuffer(
PFLConstants::kMaxPathLength), PFLConstants::kMaxPathLength);
appPath.ReleaseBuffer();
// Get the display name.
CPath displayName;
appPath.GetDisplayFileName(displayName);
// Return whether it has an extension.
return displayName.EndsInExtension();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -