windows-nt/Source/XPSP1/NT/shell/shell32/mtpt2.cpp
2020-09-26 16:20:57 +08:00

415 lines
10 KiB
C++

#include "shellprv.h"
#pragma hdrstop
#include "mtpt.h"
#include "ids.h"
#include "shitemid.h"
#include "filetbl.h"
#include "shpriv.h"
#include "hwcmmn.h"
#include "apithk.h"
#include <ntddcdrm.h>
///////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////
// get the friendly name for a given drive thing
// for example:
// Floppy (A:)
// Volume Name (D:)
// User on 'Pyrex' (V:)
// Dist on Strike\sys\public (Netware case)
HRESULT CMountPoint::GetDisplayName(LPTSTR pszName, DWORD cchName)
{
HRESULT hres = E_FAIL;
TCHAR szDriveLabel[MAX_DISPLAYNAME];
static BOOL s_fAllDriveLetterFirst = -1;
static BOOL s_fRemoteDriveLetterFirst = -1;
static BOOL s_fNoDriveLetter = -1;
ASSERT(cchName > 0);
*pszName = 0; // handle failure case
// for s_fDriveLetterFirst, see bug 250899, that's a long story.
if (-1 == s_fRemoteDriveLetterFirst)
{
DWORD dw;
DWORD cb = sizeof(dw);
s_fRemoteDriveLetterFirst = FALSE;
s_fAllDriveLetterFirst = FALSE;
s_fNoDriveLetter = FALSE;
if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
TEXT("ShowDriveLettersFirst"), NULL, &dw, &cb))
{
if (1 == dw)
{
s_fRemoteDriveLetterFirst = TRUE;
}
else
{
if (2 == dw)
{
s_fNoDriveLetter = TRUE;
}
else
{
if (4 == dw)
{
s_fAllDriveLetterFirst = TRUE;
}
}
}
}
}
hres = GetLabel(szDriveLabel, ARRAYSIZE(szDriveLabel));
if (SUCCEEDED(hres))
{
if (s_fNoDriveLetter)
{
StrCpyN(pszName, szDriveLabel, cchName);
}
else
{
BOOL fDriveLetterFirst = ((_IsRemote()) && s_fRemoteDriveLetterFirst) ||
s_fAllDriveLetterFirst;
// To return something like: "My Drive (c:)", we need a drive letter.
// Fortunately for us this fct is only called for a drive mounted on a
// letter (from drive implementation of IShellFolder), for volumes mounted
// on folders, the folder impl is called rather than the drive one.
LPTSTR psz = ShellConstructMessageString(HINST_THISDLL,
MAKEINTRESOURCE(fDriveLetterFirst ? IDS_VOL_FORMAT_LETTER_1ST : IDS_VOL_FORMAT),
szDriveLabel, _GetNameFirstCharUCase());
if (psz)
{
StrCpyN(pszName, psz, cchName);
LocalFree(psz);
}
else
{
hres = E_OUTOFMEMORY;
}
}
}
return hres;
}
// { DRIVE_ISCOMPRESSIBLE | DRIVE_COMPRESSED | DRIVE_LFN | DRIVE_SECURITY }
int CMountPoint::GetVolumeFlags()
{
int iFlags = _GetGVIDriveFlags();
// Try to avoid getting the attributes
if (iFlags & DRIVE_ISCOMPRESSIBLE)
{
DWORD dwAttrib = -1;
if (_GetFileAttributes(&dwAttrib))
{
if (dwAttrib & FILE_ATTRIBUTE_COMPRESSED)
{
iFlags |= DRIVE_COMPRESSED;
}
}
}
return iFlags;
}
DWORD CMountPoint::GetClusterSize()
{
DWORD dwSecPerClus, dwBytesPerSec, dwClusters, dwTemp;
// assume this, avoid div by zero
DWORD dwRet = 512;
if (GetDiskFreeSpace(_GetNameForFctCall(), &dwSecPerClus, &dwBytesPerSec, &dwTemp, &dwClusters))
{
dwRet = dwSecPerClus * dwBytesPerSec;
}
return dwRet;
}
//static
void CMountPoint::GetTypeString(int iDrive, LPTSTR pszType, DWORD cchType)
{
*pszType = 0;
CMountPoint* pmtpt = GetMountPoint(iDrive);
if (pmtpt)
{
pmtpt->GetTypeString(pszType, cchType);
pmtpt->Release();
}
}
// static
UINT CMountPoint::GetSuperPlainDriveIcon(LPCWSTR pszDrive, UINT uDriveType)
{
int iIcon;
switch (uDriveType)
{
case DRIVE_REMOVABLE:
{
iIcon = II_DRIVEREMOVE;
if (pszDrive)
{
if ((TEXT('a') == *pszDrive) || (TEXT('A') == *pszDrive))
{
iIcon = II_DRIVE35;
}
else
{
if ((TEXT('b') == *pszDrive) || (TEXT('B') == *pszDrive))
{
iIcon = II_DRIVE35;
}
}
}
break;
}
case DRIVE_FIXED:
{
iIcon = II_DRIVEFIXED;
break;
}
case DRIVE_REMOTE:
{
iIcon = II_DRIVENET;
break;
}
case DRIVE_CDROM:
{
iIcon = II_DRIVECD;
break;
}
case DRIVE_RAMDISK:
{
iIcon = II_DRIVERAM;
break;
}
case DRIVE_UNKNOWN:
case DRIVE_NO_ROOT_DIR:
default:
{
iIcon = -IDI_DRIVEUNKNOWN;
break;
}
}
return iIcon;
}
///////////////////////////////////////////////////////////////////////////////
// Call Backs
///////////////////////////////////////////////////////////////////////////////
void CMountPoint::_UpdateCommentFromDesktopINI()
{
WCHAR szCommentFromDesktopINI[MAX_MTPTCOMMENT];
GetShellClassInfoInfoTip(_GetName(), szCommentFromDesktopINI, ARRAYSIZE(szCommentFromDesktopINI));
RSSetTextValue(NULL, TEXT("_CommentFromDesktopINI"),
szCommentFromDesktopINI, REG_OPTION_NON_VOLATILE);
}
///////////////////////////////////////////////////////////////////////////////
// Default Icon/Label
///////////////////////////////////////////////////////////////////////////////
void CMountPoint::_InitLegacyRegIconAndLabel(BOOL fUseAutorunIcon,
BOOL fUseAutorunLabel)
{
// No Autorun icon, load the legacy reg icon if any
if (!fUseAutorunIcon && _IsMountedOnDriveLetter())
{
WCHAR szSubKey[MAX_PATH];
WCHAR szIconLocation[MAX_PATH + 12];
wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultIcon"),
_GetNameFirstCharUCase());
szIconLocation[0] = 0;
if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szIconLocation,
ARRAYSIZE(szIconLocation) * sizeof(TCHAR)))
{
// Let's try second location
wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultIcon"),
_GetNameFirstCharUCase());
RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szIconLocation,
ARRAYSIZE(szIconLocation) * sizeof(TCHAR));
}
if (szIconLocation[0])
{
AssertMsg(!_pszLegacyRegIcon, TEXT("_InitLegacyRegIconAndLabel: called twice"));
_pszLegacyRegIcon = StrDup(szIconLocation);
}
}
if (!fUseAutorunLabel && _IsMountedOnDriveLetter())
{
WCHAR szSubKey[MAX_PATH];
WCHAR szLabel[MAX_LABEL];
wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultLabel"),
_GetNameFirstCharUCase());
szLabel[0] = 0;
if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szLabel,
ARRAYSIZE(szLabel) * sizeof(TCHAR)))
{
// Let's try second location
wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultLabel"),
_GetNameFirstCharUCase());
RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szLabel,
ARRAYSIZE(szLabel) * sizeof(TCHAR));
}
if (szLabel[0])
{
AssertMsg(!_pszLegacyRegLabel, TEXT("_InitLegacyRegIconAndLabel: called twice"));
_pszLegacyRegLabel = StrDup(szLabel);
}
}
}
BOOL CMountPoint::_GetLegacyRegLabel(LPTSTR pszLabel, DWORD cchLabel)
{
BOOL fRet;
if (_pszLegacyRegLabel)
{
StrCpyN(pszLabel, _pszLegacyRegLabel, cchLabel);
fRet = TRUE;
}
else
{
*pszLabel = 0;
fRet = FALSE;
}
return fRet;
}
LPCTSTR CMountPoint::_GetNameForFctCall()
{
return _szName;
}
// the first character in the name, and convert it to upper case
// the first character is generally the drive letter
TCHAR CMountPoint::_GetNameFirstCharUCase()
{
return (TCHAR) CharUpper((LPTSTR) _szName[0]);
}
LPTSTR CMountPoint::_GetNameFirstXChar(LPTSTR pszBuffer, int c)
{
StrCpyN(pszBuffer, _szName, c);
return pszBuffer;
}
LPCTSTR CMountPoint::_GetNameDebug()
{
return _szName;
}
LPCTSTR CMountPoint::_GetName()
{
return _szName;
}
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
//
// External API for use by non-CPP modules.
//
HRESULT MountPoint_RegisterChangeNotifyAlias(int iDrive)
{
HRESULT hr = E_FAIL;
CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
if (pMtPt)
{
pMtPt->ChangeNotifyRegisterAlias();
pMtPt->Release();
hr = NOERROR;
}
return hr;
}
HRESULT CMountPoint::GetComment(LPTSTR pszComment, DWORD cchComment)
{
RSGetTextValue(NULL, TEXT("_CommentFromDesktopINI"), pszComment, &cchComment);
return *pszComment ? S_OK : E_FAIL;
}
BOOL CMountPoint::GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName)
{
return _GetFileSystemName(pszFileSysName, cchFileSysName);
}
BOOL CMountPoint::_GetLabelFromReg(LPWSTR psz, DWORD cch)
{
*psz = 0;
return (RSGetTextValue(NULL, TEXT("_LabelFromReg"), psz, &cch) && *psz);
}
BOOL CMountPoint::_GetLabelFromDesktopINI(LPWSTR psz, DWORD cch)
{
*psz = 0;
return (RSGetTextValue(NULL, TEXT("_LabelFromDesktopINI"), psz, &cch) && *psz);
}
DWORD CMountPoint::GetAttributes()
{
DWORD dwAttrib;
_GetFileAttributes(&dwAttrib);
return dwAttrib;
}
CMountPoint::CMountPoint() : _cRef(1)
{
}
ULONG CMountPoint::AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG CMountPoint::Release()
{
if (InterlockedDecrement(&_cRef) > 0)
return _cRef;
delete this;
return 0;
}