📄 win32utils.cpp
字号:
// the file, without the path. It checks the Windows 'show extensions'
// preference and keeps or discards the extension as necessary.
DualErr
GetBareName(LPCSTR path, CString *bareName, BareNameExtFlag bneFlag)
{
DualErr derr;
pgpAssertStrValid(path);
pgpAssertAddrValid(bareName, CString);
try
{
CString displayName, tempString;
PGPBoolean stripExtension;
PGPInt32 lastSlash;
SHFILEINFO SHFI;
bareName->Empty();
if (strlen(path) < 3)
derr = DualErr(kPGDMinorError_InvalidPathNameFound);
// Will we show or hide the extension?
if (derr.IsntError())
{
switch (bneFlag)
{
case kBNE_Default:
// Ask the system how to display this pathname.
SHGetFileInfo(path, NULL, &SHFI, sizeof(SHFI),
SHGFI_DISPLAYNAME);
displayName = SHFI.szDisplayName;
stripExtension = (displayName.Right(4).CompareNoCase(
kPGPdiskFileExtension) != 0);
;
break;
case kBNE_HideExt:
stripExtension = TRUE;
break;
case kBNE_ShowExt:
stripExtension = FALSE;
break;
default:
pgpAssert(FALSE);
break;
}
tempString = path;
// Strip the path component.
lastSlash = tempString.ReverseFind('\\');
if (lastSlash != -1)
{
(* bareName) = tempString.Right(tempString.GetLength() -
lastSlash - 1);
}
else
{
(* bareName) = tempString;
}
// Strip extension if ordered to.
if (stripExtension)
{
PGPInt32 lastDot;
tempString = (* bareName);
lastDot = tempString.ReverseFind('.');
if (lastDot != -1)
(* bareName) = tempString.Left(lastDot);
}
}
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
return derr;
}
// CanonicalizeVolumeName turns the input string into a legal volume name.
DualErr
CanonicalizeVolumeName(LPCSTR inName, CString *outName)
{
DualErr derr;
pgpAssertStrValid(inName);
pgpAssertAddrValid(outName, CString);
try
{
PGPUInt32 i;
// Legalize the label.
(* outName) = inName;
(* outName) = outName->Left(kMaxVolumeLabelLength);
while ((i = outName->FindOneOf(kInvalidVolumeNameChars)) != -1)
{
outName->SetAt(i, kInvalidCharReplacement);
}
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
return derr;
}
// VerifyAndCanonicalizePath takes a pathname or a filename, and returns the
// full path to the closest file it can find.
DualErr
VerifyAndCanonicalizePath(LPCSTR inPath, CString *outPath)
{
DualErr derr;
try
{
CString bareName, csInPath, dir, localPath;
LPSTR pFilePart = NULL;
PGPBoolean isLoopedBack;
pgpAssertStrValid(inPath);
pgpAssertAddrValid(outPath, CString);
csInPath = inPath;
// If looped back, resolve it a to local path.
if (derr.IsntError())
{
if (IsNetworkedPath(csInPath))
{
if (!IsUNCPath(csInPath))
derr = TranslateDriveToUNC(csInPath, &csInPath);
if (derr.IsntError())
{
CheckIfLoopedBack(csInPath, &localPath,
&isLoopedBack);
if (derr.IsntError())
{
if (isLoopedBack)
csInPath = localPath;
}
// This check WILL fail on non-admin accounts; don't
// sweat it now, we will deal with it later.
derr = DualErr::NoError;
}
}
}
// Get the bare file name.
if (derr.IsntError())
{
derr = GetBareName(csInPath, &bareName, kBNE_ShowExt);
}
// Get the directory component.
if (derr.IsntError())
{
derr = GetDirectorySmart(csInPath, &dir);
}
// Get full pathname to the file.
if (derr.IsntError())
{
if (!::SearchPath(dir, bareName, kPGPdiskFileExtension,
kMaxStringSize, outPath->GetBuffer(kMaxStringSize),
&pFilePart))
{
derr = DualErr(kPGDMinorError_PGPdiskNotFound);
}
outPath->ReleaseBuffer();
}
// Convert to long pathname form.
if (derr.IsntError())
{
derr = ConvertPathToLong(outPath);
}
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
return derr;
}
// ResolveShortcut takes a path to a shortcut and returns a path to the actual
// file. Ripped from the SDK.
DualErr
ResolveShortcut(LPCSTR shortcutPath, CString *fullPath)
{
CString szGotPath;
DualErr derr;
HRESULT result;
IPersistFile *pIPF;
IShellLink *pShellLink;
PGPBoolean loadedCOM, loadedPersistFile, loadedShellLink;
WIN32_FIND_DATA WFD;
pgpAssertStrValid(shortcutPath);
pgpAssertAddrValid(fullPath, CString);
loadedCOM = loadedPersistFile = loadedShellLink = FALSE;
// Load COM.
result = CoInitialize(NULL);
if (result < 0)
derr = DualErr(kPGDMinorError_CoInitializeExFailed);
loadedCOM = derr.IsntError();
// Get a pointer to the IShellLink interface.
if (derr.IsntError())
{
result = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &pShellLink);
if (result < 0)
derr = DualErr(kPGDMinorError_CoCreateInstanceFailed);
loadedShellLink = derr.IsntError();
}
// Get a pointer to the IPersistFile interface.
if (derr.IsntError())
{
result = pShellLink->QueryInterface(IID_IPersistFile,
(void **) &pIPF);
if (result < 0)
derr = DualErr(kPGDMinorError_QueryInterfaceFailed);
loadedPersistFile = derr.IsntError();
}
if (derr.IsntError())
{
PGPUInt16 uniSCPath[kMaxStringSize];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, shortcutPath, -1, uniSCPath,
kMaxStringSize);
// Load the shortcut.
result = pIPF->Load(uniSCPath, STGM_READ);
if (result < 0)
derr = DualErr(kPGDMinorError_OLELoadCommandFailed);
}
// Resolve the link.
if (derr.IsntError())
{
result = pShellLink->Resolve(MessageBoxParent->GetSafeHwnd(),
SLR_ANY_MATCH);
if (result < 0)
derr = DualErr(kPGDMinorError_ResolveShortcutFailed);
}
// Get the path to the link target.
if (derr.IsntError())
{
try
{
result = pShellLink->GetPath(fullPath->GetBuffer(kMaxStringSize),
kMaxStringSize, (WIN32_FIND_DATA *) &WFD, SLGP_SHORTPATH);
fullPath->ReleaseBuffer();
if (result < 0)
derr = DualErr(kPGDMinorError_OLEGetPathFailed);
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
}
// Release the pointer to the IPersistFile interface.
if (loadedPersistFile)
pIPF->Release();
// Release the pointer to the IShellLink interface.
if (loadedShellLink)
pShellLink->Release();
if (loadedCOM)
CoUninitialize();
return derr;
}
/////////////////////////
// Drive/volume functions
/////////////////////////
// BroadcastDriveMessage broadcasts a system message concerning the volume.
DualErr
BroadcastDriveMessage(PGPUInt8 drive, WPARAM msg)
{
DEV_BROADCAST_VOLUME DBV;
DualErr derr;
PGPInt32 result;
pgpAssert(IsLegalDriveNumber(drive));
DBV.dbcv_size = sizeof(DBV);
DBV.dbcv_devicetype = DBT_DEVTYP_VOLUME;
DBV.dbcv_reserved = 0;
DBV.dbcv_unitmask = 1 << drive;
DBV.dbcv_flags = DBTF_MEDIA;
result = BroadcastSystemMessage(BSF_NOHANG | BSF_POSTMESSAGE, NULL,
WM_DEVICECHANGE, msg, (LPARAM) &DBV);
if (result < 1)
derr = DualErr(kPGDMinorError_BroadcastSystemMessageFailed);
return derr;
}
// GetLocalComputerName returns the name of the local computer.
DualErr
GetLocalComputerName(CString *compName)
{
DualErr derr;
try
{
PGPUInt32 result;
WKSTA_INFO_100 *pWI100;
USES_CONVERSION;
pgpAssertAddrValid(compName, CString);
pgpAssert(IsWinNT4CompatibleMachine());
result = WinNT_NetWkstaGetInfo(NULL, 100, (LPBYTE *) &pWI100);
if (result != NERR_Success)
{
derr = DualErr(kPGDMinorError_NetWkstaGetInfoFailed,
result);
}
if (derr.IsntError())
{
(* compName) = W2A((LPWSTR) pWI100->wki100_computername);
WinNT_NetApiBufferFree(pWI100);
}
}
catch (CMemoryException *ex)
{
ex->Delete();
derr = DualErr(kPGDMinorError_OutOfMemory);
}
return derr;
}
// Win95GetUniversalName implements a hack under Windows95 that simulates
// the non-working WNetGetUniversalName (from KB Article ID: Q131416).
static BOOL
Win95GetUniversalName( LPCTSTR szDrive, LPTSTR szUniv )
{
// get the local drive letter
char chLocal = toupper( szDrive[0] );
// cursory validation
if ( chLocal < 'A' || chLocal > 'Z' )
return FALSE;
if ( szDrive[1] != ':' || szDrive[2] != '\\' )
return FALSE;
HANDLE hEnum;
DWORD dwResult = WNetOpenEnum( RESOURCE_CONNECTED, RESOURCETYPE_DISK,
0, NULL, &hEnum );
if ( dwResult != NO_ERROR )
return FALSE;
// request all available entries
const int c_cEntries = 0xFFFFFFFF;
// start with a reasonable buffer size
DWORD cbBuffer = 50 * sizeof( NETRESOURCE );
NETRESOURCE *pNetResource = (NETRESOURCE*) malloc( cbBuffer );
BOOL fResult = FALSE;
while ( TRUE )
{
DWORD dwSize = cbBuffer,
cEntries = c_cEntries;
dwResult = WNetEnumResource( hEnum, &cEntries, pNetResource,
&dwSize );
if ( dwResult == ERROR_MORE_DATA )
{
// the buffer was too small, enlarge
cbBuffer = dwSize;
pNetResource = (NETRESOURCE*) realloc(pNetResource, cbBuffer);
continue;
}
if ( dwResult != NO_ERROR )
goto done;
// search for the specified drive letter
for ( int i = 0; i < (int) cEntries; i++ )
if ( pNetResource[i].lpLocalName &&
chLocal == toupper(pNetResource[i].lpLocalName[0]) )
{
// match
fResult = TRUE;
// build a UNC name
strcpy( szUniv, pNetResource[i].lpRemoteName );
strcat( szUniv, szDrive + 2 );
_strupr( szUniv );
goto done;
}
}
done:
// cleanup
WNetCloseEnum( hEnum );
free( pNetResource );
return fResult;
}
// TranslateDriveToUNC translates a mapped networked drive-based pathname to
// its UNC form.
DualErr
TranslateDriveToUNC(LPCSTR inPath, CString *outPath)
{
DualErr derr;
try
{
PGPUInt32 result;
pgpAssertStrValid(inPath);
pgpAssertAddrValid(outPath, CString);
if (IsWin95CompatibleMachine() && !IsWin98CompatibleMachine())
{
PGPBoolean resultWin95;
char tempOutPath[kMaxStringSize];
// Special hack function for Windows95.
resultWin95 = Win95GetUniversalName(inPath, tempOutPath);
if (!resultWin95)
{
derr = DualErr(kPGDMinorError_WNetGetUniNameFailed,
GetLastError());
}
else
{
(* outPath) = tempOutPath;
}
}
else
{
UNIVERSAL_NAME_INFO *pUNI;
unsigned long bufSize;
// Handle normally for Win98 and WinNT.
bufSize = sizeof(UNIVERSAL_NAME_INFO) +
kMaxStringSize * sizeof(WCHAR);
pUNI = (UNIVERSAL_NAME_INFO *) new PGPUInt8[bufSize];
if (derr.IsntError())
{
result = WNetGetUniversalName(inPath,
UNIVERSAL_NAME_INFO_LEVEL, pUNI, &bufSize);
if (result != NO_ERROR)
{
derr = DualErr(kPGDMinorError_WNetGetUniNameFailed,
result);
}
}
if (derr.IsntError())
{
(* outPath) = pUNI->lpUniversalName;
}
delete[] (PGPUInt8 *) pUNI;
}
}
catch (CMemoryException *ex)
{
ex->Delete();
derr = DualErr(kPGDMinorError_OutOfMemory);
}
return derr;
}
// TranslateUNCToLocal translates a 'looped-back' path to its local form.
DualErr
TranslateUNCToLocal(
LPCSTR inPath,
CString *outPath,
PGPBoolean *isLoopedBack)
{
DualErr derr;
pgpAssertStrValid(inPath);
pgpAssertAddrValid(outPath, CString);
pgpAssertAddrValid(isLoopedBack, PGPBoolean);
pgpAssert(IsWin95CompatibleMachine() || IsWinNT4CompatibleMachine());
try
{
CString newRoot, nonRoot, share;
derr = GetShare(inPath, &share);
if (derr.IsntError())
{
derr = StripRoot(inPath, &nonRoot);
}
if (derr.IsntError())
{
if (IsWin95CompatibleMachine())
{
PGPUInt32 bufSize, result;
share_info_50 *pSI50;
unsigned short cbTotalAvail;
bufSize = sizeof(share_info_50) + MAX_PATH + MAXCOMMENTSZ + 2;
pSI50 = (share_info_50 *) new PGPUInt8[bufSize];
result = Win95_NetShareGetInfo(NULL, share, 50,
(char *) pSI50, bufSize, &cbTotalAvail);
if (result != NERR_Success)
{
derr = DualErr(kPGDMinorError_NetShareGetInfoFailed,
result);
}
if (derr.IsntError())
{
newRoot = pSI50->shi50_path;
}
delete[] (PGPUInt8 *) pSI50;
}
else if (IsWinNT4CompatibleMachine())
{
PGPUInt32 result;
SHARE_INFO_2 *pSI2;
USES_CONVERSION;
result = WinNT_NetShareGetInfo(NULL, A2W(share), 2,
(LPBYTE *) &pSI2);
if (result != NERR_Success)
{
derr = DualErr(kPGDMinorError_NetShareGetInfoFailed,
result);
}
if (derr.IsntError())
{
newRoot = W2A((LPWSTR) pSI2->shi2_path);
WinNT_NetApiBufferFree(pSI2);
}
}
}
if (derr.IsntError())
{
(* outPath) = newRoot + "\\" + nonRoot;
}
}
catch (CMemoryException *ex)
{
ex->Delete();
derr = DualErr(kPGDMinorError_OutOfMemory);
}
(* isLoopedBack) = derr.IsntError();
return derr;
}
// CheckIfLoopedBack checks if the given networked path is looped back to a
// local drive.
DualErr
CheckIfLoopedBack(
LPCSTR inPath,
CString *outPath,
PGPBoolean *isLoopedBack)
{
DualErr derr;
pgpAssertStrValid(inPath);
pgpAssertAddrValid(outPath, CString);
pgpAssertAddrValid(isLoopedBack, PGPBoolean);
if (!IsNetworkedPath(inPath))
{
(* isLoopedBack) = FALSE;
}
else if (IsUNCPath(inPath))
{
derr = TranslateUNCToLocal(inPath, outPath, isLoopedBack);
}
else
{
CString uncPath, share;
derr = TranslateDriveToUNC(inPath, &uncPath);
if (derr.IsntError())
{
derr = TranslateUNCToLocal(uncPath, outPath, isLoopedBack);
}
}
return derr;
}
// IsDriveNetworkMapped checks if a given drive letter represents a currently
// mapped, or a mapped but non-working networked drive. (Needed because
// mapped but non-working drives are seen in the Explorer but not indicated
// by GetLogicalDrives).
PGPBoolean
IsDriveNetworkMapped(PGPUInt8 drive)
{
char keyName[2];
CString regPathToMapped;
HKEY regHandle;
PGPBoolean isMapped = FALSE;
PGPUInt32 result;
pgpAssert(IsLegalDriveNumber(drive));
keyName[0] = DriveNumToLet(drive);
keyName[1] = kNullChar;
if (IsWin95CompatibleMachine())
regPathToMapped = kRegistryMappedDrive98Section;
else
regPathToMapped = kRegistryMappedDriveNTSection;
regPathToMapped += "\\";
regPathToMapped += keyName;
result = RegOpenKeyEx(kRegistryMappedDriveRoot, regPathToMapped, NULL,
KEY_READ, ®Handle);
if (result == ERROR_SUCCESS)
{
isMapped = TRUE;
RegCloseKey(regHandle);
}
else
{
isMapped = FALSE;
}
return isMapped;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -