415 lines
10 KiB
C++
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;
|
|
}
|