#include "shellprv.h" #pragma hdrstop #include "shitemid.h" #include "ids.h" #include #include "shpriv.h" #include "hwcmmn.h" #include "mtptl.h" #include "cdburn.h" #ifdef DEBUG DWORD CMtPtLocal::_cMtPtLocal = 0; DWORD CVolume::_cVolume = 0; #endif const static WCHAR g_szCrossProcessCacheVolumeKey[] = TEXT("CPC\\Volume"); CRegSupport CMtPtLocal::_rsVolumes; HRESULT CMtPtLocal::SetLabel(HWND hwnd, LPCTSTR pszLabel) { HRESULT hr = E_FAIL; TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::SetLabel: for '%s'", _GetNameDebug()); if (SetVolumeLabel(_GetNameForFctCall(), pszLabel)) { TraceMsg(TF_MOUNTPOINT, " 'SetVolumeLabel' succeeded"); if ( !_fVolumePoint ) { RSSetTextValue(NULL, TEXT("_LabelFromReg"), pszLabel, REG_OPTION_NON_VOLATILE); } if (!_CanUseVolume()) { // we notify for only the current drive (no folder mounted drive) SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATH, _GetName(), _GetName()); } hr = S_OK; } else { DWORD dwErr = GetLastError(); switch (dwErr) { case ERROR_SUCCESS: break; case ERROR_ACCESS_DENIED: hr = S_FALSE; // don't have permission, shouldn't put them back into editing mode ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ACCESSDENIED ), MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND); break; case ERROR_WRITE_PROTECT: hr = S_FALSE; // can't write, shouldn't put them back into editing mode ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_WRITEPROTECTED ), MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND); break; case ERROR_LABEL_TOO_LONG: ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ERR_VOLUMELABELBAD ), MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND); break; case ERROR_UNRECOGNIZED_VOLUME: hr = S_FALSE; // can't write, shouldn't put them back into editing mode ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ERR_VOLUMEUNFORMATTED ), MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND); break; default: ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_BADLABEL ), MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND); break; } TraceMsg(TF_MOUNTPOINT, " 'SetVolumeLabel' failed"); } return hr; } HRESULT CMtPtLocal::SetDriveLabel(HWND hwnd, LPCTSTR pszLabel) { HRESULT hr = E_FAIL; if ((_IsFloppy() || !_IsMediaPresent()) && _IsMountedOnDriveLetter()) { // we rename the drive not the media TCHAR szSubKey[MAX_PATH]; hr = StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultLabel"), _GetNameFirstCharUCase()); if (SUCCEEDED(hr)) { hr = RegSetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, pszLabel) ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { LocalFree(_pszLegacyRegLabel); // may be NULL _pszLegacyRegLabel = *pszLabel ? StrDup(pszLabel) : NULL; // empty string resets SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATH, _GetName(), _GetName()); } } } else { hr = SetLabel(hwnd, pszLabel); } return hr; } HRESULT CMtPtLocal::GetLabelNoFancy(LPTSTR pszLabel, DWORD cchLabel) { HRESULT hr = S_OK; if (!_GetGVILabelOrMixedCaseFromReg(pszLabel, cchLabel)) { *pszLabel = 0; // Propagate failure code out for caller hr = E_FAIL; } return hr; } BOOL _ShowUglyDriveNames() { static BOOL s_fShowUglyDriveNames = (BOOL)42; // Preload some value to say lets calculate... if (s_fShowUglyDriveNames == (BOOL)42) { int iACP; TCHAR szTemp[MAX_PATH]; // Nice large buffer if (GetLocaleInfo(GetUserDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, szTemp, ARRAYSIZE(szTemp))) { iACP = StrToInt(szTemp); // per Samer Arafeh, show ugly name for 1256 (Arabic ACP) if (iACP == 1252 || iACP == 1254 || iACP == 1255 || iACP == 1257 || iACP == 1258) goto TryLoadString; else s_fShowUglyDriveNames = TRUE; } else { TryLoadString: // All indications are that we can use pretty drive names. // Double-check that the localizers didn't corrupt the chars. LoadString(HINST_THISDLL, IDS_DRIVES_UGLY_TEST, szTemp, ARRAYSIZE(szTemp)); // If the characters did not come through properly set ugly mode... s_fShowUglyDriveNames = (szTemp[0] != 0x00BC || szTemp[1] != 0x00BD); } } return s_fShowUglyDriveNames; } BOOL CMtPtLocal::_HasAutorunLabel() { BOOL fRet = FALSE; if (_CanUseVolume()) { fRet = BOOLFROMPTR(_pvol->pszAutorunLabel) && *(_pvol->pszAutorunLabel); } return fRet; } BOOL CMtPtLocal::_HasAutorunIcon() { BOOL fRet = FALSE; if (_CanUseVolume()) { fRet = BOOLFROMPTR(_pvol->pszAutorunIconLocation) && *(_pvol->pszAutorunIconLocation); } return fRet; } void CMtPtLocal::_GetAutorunLabel(LPWSTR pszLabel, DWORD cchLabel) { ASSERT(_CanUseVolume()); StringCchCopy(pszLabel, cchLabel, _pvol->pszAutorunLabel); } HRESULT CMtPtLocal::GetLabel(LPTSTR pszLabel, DWORD cchLabel) { HRESULT hr = S_OK; BOOL fFoundIt = FALSE; // Autorun first // Fancy icon (Autoplay) second // True label from drive for non-removable // Legacy drive icons third // Regular last if (_HasAutorunLabel()) { _GetAutorunLabel(pszLabel, cchLabel); fFoundIt = TRUE; } if (!fFoundIt) { if (!_IsFloppy()) { if (!_GetGVILabelOrMixedCaseFromReg(pszLabel, cchLabel)) { *pszLabel = 0; } else { if (*pszLabel) { fFoundIt = TRUE; } } } } if (!fFoundIt) { fFoundIt = _GetLegacyRegLabel(pszLabel, cchLabel); } if (!fFoundIt) { if (!_IsFloppy()) { if (_CanUseVolume()) { if (_pvol->pszLabelFromService) { if (SUCCEEDED(SHLoadIndirectString(_pvol->pszLabelFromService, pszLabel, cchLabel, NULL))) { fFoundIt = TRUE; } else { *pszLabel = 0; } } } } } if (!fFoundIt) { if (_CanUseVolume() && (HWDTS_CDROM == _pvol->dwDriveType)) { fFoundIt = _GetCDROMName(pszLabel, cchLabel); } } if (!fFoundIt) { if (_IsFloppy()) { // For some weird reason we have wo sets of "ugly" name for floppies, // the other is in GetTypeString UINT id; if (_IsFloppy35()) { id = _ShowUglyDriveNames() ? IDS_35_FLOPPY_DRIVE_UGLY : IDS_35_FLOPPY_DRIVE; } else { id = _ShowUglyDriveNames() ? IDS_525_FLOPPY_DRIVE_UGLY : IDS_525_FLOPPY_DRIVE; } LoadString(HINST_THISDLL, id, pszLabel, cchLabel); } else { // Cook up a default name GetTypeString(pszLabel, cchLabel); } } return hr; } HRESULT CMtPtLocal::Eject(HWND hwnd) { TCHAR szNameForError[MAX_DISPLAYNAME]; GetDisplayName(szNameForError, ARRAYSIZE(szNameForError)); return _Eject(hwnd, szNameForError); } BOOL CMtPtLocal::HasMedia() { return _IsMediaPresent(); } BOOL CMtPtLocal::IsFormatted() { return _IsFormatted(); } BOOL CMtPtLocal::IsMounted() { BOOL fRet; if (_pvol) { if (_pvol->dwVolumeFlags & HWDVF_STATE_DISMOUNTED) { fRet = FALSE; } else { fRet = TRUE; } } else { // Assume true. Code that will call this will do so mainly to go // around the caching done in _pvol. fRet = TRUE; } return fRet; } BOOL CMtPtLocal::IsEjectable() { BOOL fIsEjectable = FALSE; if (_IsCDROM()) { fIsEjectable = TRUE; } else { // Floppies are not Software ejectable if (_IsStrictRemovable()) { fIsEjectable = TRUE; } else { if (_IsFloppy()) { if (_CanUseVolume() && (HWDDC_FLOPPYSOFTEJECT & _pvol->dwDriveCapability)) { if (_IsMediaPresent()) { fIsEjectable = TRUE; } } } } } if (fIsEjectable) { if (_CanUseVolume()) { if (HWDDC_NOSOFTEJECT & _pvol->dwDriveCapability) { fIsEjectable = FALSE; } } } return fIsEjectable; } HRESULT CMtPtLocal::GetCDInfo(DWORD* pdwDriveCapabilities, DWORD* pdwMediaCapabilities) { HRESULT hr; *pdwDriveCapabilities = 0; *pdwMediaCapabilities = 0; if (_IsCDROM()) { if (_CanUseVolume()) { if (HWDDC_CAPABILITY_SUPPORTDETECTION & _pvol->dwDriveCapability) { *pdwDriveCapabilities = (_pvol->dwDriveCapability & HWDDC_CDTYPEMASK); if (HWDMC_WRITECAPABILITY_SUPPORTDETECTION & _pvol->dwMediaCap) { *pdwMediaCapabilities = (_pvol->dwMediaCap & HWDMC_CDTYPEMASK); } hr = S_OK; } else { // in the case where we really dont know, see if the IMAPI info cached in the // registry has what we want. hr = CDBurn_GetCDInfo(_pvol->pszVolumeGUID, pdwDriveCapabilities, pdwMediaCapabilities); } } else { hr = S_FALSE; } } else { hr = E_FAIL; } return hr; } // Put all these together BOOL CMtPtLocal::_IsDVDDisc() { BOOL fRet = FALSE; if (_CanUseVolume()) { if (HWDMC_HASDVDMOVIE & _pvol->dwMediaCap) { fRet = TRUE; } } // else In safe boot we don't care about Audio Disc return fRet; } BOOL CMtPtLocal::_IsRemovableDevice() { BOOL fRet = FALSE; if (_CanUseVolume()) { if (HWDDC_REMOVABLEDEVICE & _pvol->dwDriveCapability) { fRet = TRUE; } } return fRet; } // We keep the functionality we had before: a drive is Autorun only if it has // a Autorun.inf in the root when inserted. If it acquires one after, too bad. BOOL CMtPtLocal::_IsAutorun() { BOOL fRet = FALSE; if (_CanUseVolume()) { if ((HWDMC_HASAUTORUNINF & _pvol->dwMediaCap) && (HWDMC_HASAUTORUNCOMMAND & _pvol->dwMediaCap) && !(HWDMC_HASUSEAUTOPLAY & _pvol->dwMediaCap)) { fRet = TRUE; } } else { WCHAR szAutorun[MAX_PATH]; DWORD dwErrMode = SetErrorMode(SEM_FAILCRITICALERRORS); if (SUCCEEDED(StringCchCopy(szAutorun, ARRAYSIZE(szAutorun), _GetNameForFctCall()))) { if (SUCCEEDED(StringCchCat(szAutorun, ARRAYSIZE(szAutorun), TEXT("autorun.inf")))) { if (-1 != GetFileAttributes(szAutorun)) { fRet = TRUE; } } } SetErrorMode(dwErrMode); } return fRet; } // try to rename it BOOL CMtPtLocal::_IsAudioDisc() { BOOL fRet = FALSE; if (_CanUseVolume()) { if (HWDMC_HASAUDIOTRACKS & _pvol->dwMediaCap) { fRet = TRUE; } } // else In safe boot we don't care about Audio Disc return fRet; } LPCTSTR CMtPtLocal::_GetNameForFctCall() { LPCTSTR psz; if (_CanUseVolume()) { psz = _pvol->pszVolumeGUID; } else { psz = _szName; } return psz; } HRESULT CMtPtLocal::_Eject(HWND hwnd, LPTSTR pszMountPointNameForError) { HRESULT hr = E_FAIL; #ifndef _WIN64 // NTRAID#NTBUG9-093957-2000/09/08-StephStm Code temporarily disabled for Win64 // MCI is not 64bit ready. It crashes. // We do this check to see if the CD will accept an IOCTL to eject it. // Old CD drives do not. On W2K ssince the IOCTL was not implemented they use // to all say 'no'. I assumne that on ia64 machine they will have recent CD // drives. I call the IOCTL for them. It works now, and it's certainly better // than the crash we get using MCI, worst come to worst it will silently fail. if (IsEjectable()) { #endif //_WIN64 // it is a protect mode drive that we can tell directly... if (_IsCDROM()) { HANDLE h = _GetHandleReadRead(); if (INVALID_HANDLE_VALUE != h) { DWORD dwReturned; DeviceIoControl(h, IOCTL_DISK_EJECT_MEDIA, NULL, 0, NULL, 0, &dwReturned, NULL); CloseHandle(h); } hr = S_OK; } else { // For removable drives, we want to do all the calls on a single // handle, thus we can't do lots of calls to DeviceIoControl. // Instead, use the helper routines to do our work... // Don't bring up any error message if the user already chose to abort. BOOL fAborted = FALSE; BOOL fFailed = TRUE; HANDLE h = _GetHandleWithAccessAndShareMode(GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE); if (INVALID_HANDLE_VALUE != h) { DWORD dwReturned; _RETRY_LOCK_VOLUME_: // Now try to lock the drive... // // In theory, if no filesystem was mounted, the IOCtl command could go // to the device, which would fail with ERROR_INVALID_FUNCTION. If that // occured, we would still want to proceed, since the device might still // be able to handle the IOCTL_DISK_EJECT_MEDIA command below. // if (!DeviceIoControl(h, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwReturned, NULL) && (GetLastError() != ERROR_INVALID_FUNCTION)) { // So we can't lock the drive, bring up a message box to see if user // wants to // 1. Abort. // 2. Retry to lock the drive. // 3. Dismount anyway. WCHAR szLabelForMessage[MAX_LABEL]; szLabelForMessage[0] = 0; if (_CanUseVolume() && (_pvol->pszLabelFromService)) { StringCchCopy(szLabelForMessage, ARRAYSIZE(szLabelForMessage), _pvol->pszLabelFromService); } if (!(szLabelForMessage[0])) { GetTypeString(szLabelForMessage, ARRAYSIZE(szLabelForMessage)); LPTSTR psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_VOL_FORMAT), szLabelForMessage, _GetNameFirstCharUCase()); if (psz) { StringCchCopy(szLabelForMessage, ARRAYSIZE(szLabelForMessage), psz); LocalFree(psz); } else { StringCchCopy(szLabelForMessage, ARRAYSIZE(szLabelForMessage), pszMountPointNameForError); } } int iRet = ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_UNMOUNT_TEXT ), pszMountPointNameForError, MB_CANCELTRYCONTINUE | MB_ICONWARNING | MB_SETFOREGROUND, szLabelForMessage); switch (iRet) { case IDCANCEL: // we did not fail, we aborted the format fFailed = FALSE; fAborted = TRUE; break; case IDCONTINUE: // send FSCTL_DISMOUNT_VOLUME if (!DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwReturned, NULL)) { TraceMsg(TF_WARNING, "FSCTL_DISMOUNT_VOLUME failed with error %d.", GetLastError()); fFailed = TRUE; break; } // We sucessfully dismounted the volume, so the h we have is not valid anymore. We // therefore close it and start the process all over again, hoping to lock the volume before // anyone re-opens a handle to it // // (fall through) case IDTRYAGAIN: goto _RETRY_LOCK_VOLUME_; } } else { ASSERT(!fAborted); // should not have aborted if we got this far... fFailed = FALSE; } if (!fFailed && !fAborted) { PREVENT_MEDIA_REMOVAL pmr; pmr.PreventMediaRemoval = FALSE; // tell the drive to allow removal, then eject if (!DeviceIoControl(h, IOCTL_STORAGE_MEDIA_REMOVAL, &pmr, sizeof(pmr), NULL, 0, &dwReturned, NULL) || !DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwReturned, NULL)) { ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_EJECT_TEXT ), MAKEINTRESOURCE( IDS_EJECT_TITLE ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND, pszMountPointNameForError); } else { hr = S_OK; } } CloseHandle(h); } if (fFailed) { ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_UNMOUNT_TEXT ), MAKEINTRESOURCE( IDS_UNMOUNT_TITLE ), MB_OK | MB_ICONSTOP | MB_SETFOREGROUND, pszMountPointNameForError); } } #ifndef _WIN64 } else { // Is this needed anymore? // See comment above for why this is ifdef'ed out on Win64 // (stephstm) only works for drive mounted on letter TCHAR szMCI[128]; hr = StringCchPrintf(szMCI, ARRAYSIZE(szMCI), TEXT("Open %c: type cdaudio alias foo shareable"), _GetNameFirstCharUCase()); if (SUCCEEDED(hr)) { if (mciSendString(szMCI, NULL, 0, 0L) == MMSYSERR_NOERROR) { mciSendString(TEXT("set foo door open"), NULL, 0, 0L); mciSendString(TEXT("close foo"), NULL, 0, 0L); hr = S_OK; } } } #endif //_WIN64 return hr; } /////////////////////////////////////////////////////////////////////////////// // New ////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// BOOL CMtPtLocal::_GetFileAttributes(DWORD* pdwAttrib) { BOOL fRet = FALSE; BOOL fDoRead = FALSE; *pdwAttrib = -1; if (_CanUseVolume() && !_IsFloppy()) { if (_IsMediaPresent() && _IsFormatted()) { if (_IsReadOnly()) { // The file attrib we received at the begginning should be // valid, do not touch the drive for nothing *pdwAttrib = _pvol->dwRootAttributes; fRet = TRUE; } else { fDoRead = TRUE; } } } else { fDoRead = TRUE; } if (fDoRead) { DWORD dw = GetFileAttributes(_GetNameForFctCall()); if (-1 != dw) { *pdwAttrib = dw; fRet = TRUE; } } return fRet; } // { DRIVE_ISCOMPRESSIBLE | DRIVE_LFN | DRIVE_SECURITY } int CMtPtLocal::_GetGVIDriveFlags() { int iFlags = 0; DWORD dwFileSystemFlags = 0; DWORD dwMaxFileNameLen = 13; if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { if (_IsMediaPresent() && _IsFormatted()) { // No check for _IsReadOnly, we'll be notified if there's a format dwFileSystemFlags = _pvol->dwFileSystemFlags; dwMaxFileNameLen = _pvol->dwMaxFileNameLen; } } else { if (!GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL, &dwMaxFileNameLen, &dwFileSystemFlags, NULL, NULL)) { // Just make sure dwMaxFileNameLen = 13; } } // The file attrib we received at the begginning should be // valid, do not touch the drive for nothing if (dwFileSystemFlags & FS_FILE_COMPRESSION) { iFlags |= DRIVE_ISCOMPRESSIBLE; } // Volume supports long filename (greater than 8.3)? if (dwMaxFileNameLen > 12) { iFlags |= DRIVE_LFN; } // Volume supports security? if (dwFileSystemFlags & FS_PERSISTENT_ACLS) { iFlags |= DRIVE_SECURITY; } return iFlags; } BOOL CMtPtLocal::_GetGVILabel(LPTSTR pszLabel, DWORD cchLabel) { BOOL fRet = FALSE; *pszLabel = 0; if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { if (_IsMediaPresent() && _IsFormatted()) { // No check for _IsReadOnly, we'll be notified if there's a change // of label fRet = SUCCEEDED(StringCchCopy(pszLabel, cchLabel, _pvol->pszLabel)); } } else { fRet = GetVolumeInformation(_GetNameForFctCall(), pszLabel, cchLabel, NULL, NULL, NULL, NULL, NULL); } return fRet; } BOOL CMtPtLocal::_GetSerialNumber(DWORD* pdwSerialNumber) { BOOL fRet = FALSE; if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { if (_IsMediaPresent() && _IsFormatted()) { *pdwSerialNumber = _pvol->dwSerialNumber; fRet = TRUE; } } else { fRet = GetVolumeInformation(_GetNameForFctCall(), NULL, 0, pdwSerialNumber, NULL, NULL, NULL, NULL); } return fRet; } BOOL CMtPtLocal::_GetGVILabelOrMixedCaseFromReg(LPTSTR pszLabel, DWORD cchLabel) { BOOL fRet = FALSE; *pszLabel = 0; fRet = _GetGVILabel(pszLabel, cchLabel); if (fRet) { WCHAR szLabelFromReg[MAX_LABEL]; // Do we already have a label from the registry for this volume? // (the user may have renamed this drive) if (_GetLabelFromReg(szLabelFromReg, ARRAYSIZE(szLabelFromReg)) && szLabelFromReg[0]) { // Yes // Do they match (only diff in case) if (lstrcmpi(szLabelFromReg, pszLabel) == 0) { // Yes StringCchCopy(pszLabel, cchLabel, szLabelFromReg); } } } return fRet; } BOOL CMtPtLocal::_GetFileSystemFlags(DWORD* pdwFlags) { BOOL fRet = FALSE; DWORD dwFileSystemFlags = 0; *pdwFlags = 0; if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { if (_IsMediaPresent() && _IsFormatted()) { // No check for _IsReadOnly, we'll be notified if there's a // format oper. *pdwFlags = _pvol->dwFileSystemFlags; fRet = TRUE; } } else { if (GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL, NULL, pdwFlags, NULL, NULL)) { fRet = TRUE; } } return fRet; } BOOL CMtPtLocal::_GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName) { BOOL fRet = FALSE; *pszFileSysName = 0; if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { if (_IsMediaPresent() && _IsFormatted()) { fRet = SUCCEEDED(StringCchCopy(pszFileSysName, cchFileSysName, _pvol->pszFileSystem)); } } else { if (GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL, NULL, NULL, pszFileSysName, cchFileSysName)) { fRet = TRUE; } } return fRet; } struct CDROMICONS { DWORD dwCap; UINT iIcon; UINT iName; }; // Go from most wonderful caps to less wonderful (according to stepshtm) // Keep in order, it is verrrrry important const CDROMICONS rgMediaPresent[] = { // Specfic content { HWDMC_HASDVDMOVIE, -IDI_AP_VIDEO, 0}, // we display the DVD media icon, // since it will most likely be // replaced by an icon from the DVD itself { HWDMC_HASAUDIOTRACKS | HWDMC_HASDATATRACKS, -IDI_MEDIACDAUDIOPLUS, 0}, { HWDMC_HASAUDIOTRACKS, -IDI_CDAUDIO, 0 }, { HWDMC_HASAUTORUNINF, -IDI_DRIVECD, 0 }, // Specific media { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDRAM, -IDI_MEDIADVDRAM, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDRECORDABLE, -IDI_MEDIADVDR, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDREWRITABLE, -IDI_MEDIADVDRW, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDROM, -IDI_MEDIADVDROM, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDREWRITABLE, -IDI_MEDIACDRW, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDRECORDABLE, -IDI_MEDIACDR, 0 }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDROM, -IDI_MEDIACDROM, 0 }, }; // Keep in order, it is verrrrry important const CDROMICONS rgNoMedia[] = { { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDRAM, -IDI_DRIVECD, IDS_DRIVES_DVDRAM }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_DVDR }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_DVDRW }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM | HWDDC_CDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_DVDCDRW }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM | HWDDC_CDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_DVDCDR }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM, -IDI_DVDDRIVE, IDS_DRIVES_DVD }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_CDRW }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_CDR }, { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDROM, -IDI_DRIVECD, IDS_DRIVES_CDROM }, }; UINT _GetCDROMIconFromArray(DWORD dwCap, const CDROMICONS* prgcdromicons, DWORD ccdromicons) { UINT iIcon = 0; for (DWORD dw = 0; dw < ccdromicons; ++dw) { if ((prgcdromicons[dw].dwCap & dwCap) == prgcdromicons[dw].dwCap) { iIcon = prgcdromicons[dw].iIcon; break; } } return iIcon; } UINT _GetCDROMNameFromArray(DWORD dwCap) { UINT iName = 0; for (DWORD dw = 0; dw < ARRAYSIZE(rgNoMedia); ++dw) { if ((rgNoMedia[dw].dwCap & dwCap) == rgNoMedia[dw].dwCap) { iName = rgNoMedia[dw].iName; break; } } return iName; } UINT CMtPtLocal::_GetCDROMIcon() { int iIcon; if (_IsMediaPresent()) { ASSERT(_CanUseVolume()); iIcon = _GetCDROMIconFromArray(_pvol->dwMediaCap, rgMediaPresent, ARRAYSIZE(rgMediaPresent)); if (!iIcon) { iIcon = -IDI_DRIVECD; } } else { ASSERT(_CanUseVolume()); iIcon = _GetCDROMIconFromArray(_pvol->dwDriveCapability, rgNoMedia, ARRAYSIZE(rgNoMedia)); if (!iIcon) { // No media generic CD icon iIcon = -IDI_DRIVECD; } } return iIcon; } BOOL CMtPtLocal::_GetCDROMName(LPWSTR pszName, DWORD cchName) { BOOL fRet = FALSE; *pszName = 0; if (!_IsMediaPresent()) { ASSERT(_CanUseVolume()); UINT iName = _GetCDROMNameFromArray(_pvol->dwDriveCapability); if (iName) { fRet = LoadString(HINST_THISDLL, iName, pszName, cchName); } } return fRet; } UINT CMtPtLocal::_GetAutorunIcon(LPTSTR pszModule, DWORD cchModule) { int iIcon = -1; ASSERT(_CanUseVolume()); if (_pvol->pszAutorunIconLocation) { if (SUCCEEDED(StringCchCopy(pszModule, cchModule, _GetName()))) { if (SUCCEEDED(StringCchCat(pszModule, cchModule, _pvol->pszAutorunIconLocation))) { iIcon = PathParseIconLocation(pszModule); } } } return iIcon; } UINT CMtPtLocal::GetIcon(LPTSTR pszModule, DWORD cchModule) { UINT iIcon = -IDI_DRIVEUNKNOWN; *pszModule = 0; if (_CanUseVolume()) { // Autorun first // Fancy icon (Autoplay) second // Legacy drive icons last if (_HasAutorunIcon()) { iIcon = _GetAutorunIcon(pszModule, cchModule); } if (-IDI_DRIVEUNKNOWN == iIcon) { // Try fancy icon if (!_IsFloppy()) { if (_IsMediaPresent()) { if (_pvol->pszIconFromService) { if (FAILED(StringCchCopy(pszModule, cchModule, _pvol->pszIconFromService))) { *pszModule = 0; } } } else { if (_pvol->pszNoMediaIconFromService) { if (FAILED(StringCchCopy(pszModule, cchModule, _pvol->pszNoMediaIconFromService))) { *pszModule = 0; } } else { if (_pvol->pszIconFromService) { if (FAILED(StringCchCopy(pszModule, cchModule, _pvol->pszIconFromService))) { *pszModule = 0; } } } } if (*pszModule) { iIcon = PathParseIconLocation(pszModule); } } if (-IDI_DRIVEUNKNOWN == iIcon) { if (_pszLegacyRegIcon) { if (*_pszLegacyRegIcon) { if (SUCCEEDED(StringCchCopy(pszModule, cchModule, _pszLegacyRegIcon))) { iIcon = PathParseIconLocation(pszModule); } } else { *pszModule = 0; } } else { if (_CanUseVolume() && (HWDTS_CDROM == _pvol->dwDriveType)) { iIcon = _GetCDROMIcon(); *pszModule = 0; } } } if (-IDI_DRIVEUNKNOWN == iIcon) { switch (_pvol->dwDriveType) { case HWDTS_FLOPPY35: { iIcon = II_DRIVE35; break; } case HWDTS_FIXEDDISK: { iIcon = II_DRIVEFIXED; break; } case HWDTS_CDROM: { iIcon = II_DRIVECD; break; } case HWDTS_REMOVABLEDISK: { iIcon = II_DRIVEREMOVE; break; } case HWDTS_FLOPPY525: { iIcon = II_DRIVE525; break; } default: { iIcon = -IDI_DRIVEUNKNOWN; break; } } } } } else { iIcon = CMountPoint::GetSuperPlainDriveIcon(_szName, GetDriveType(_GetName())); } if (*pszModule) TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetIcon: for '%s', chose '%s', '%d'", _GetNameDebug(), pszModule, iIcon); else TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetIcon: for '%s', chose '%d'", _GetNameDebug(), iIcon); return iIcon; } HRESULT CMtPtLocal::GetAssocSystemElement(IAssociationElement **ppae) { PCWSTR psz = NULL; if (_IsFixedDisk()) psz = L"Drive.Fixed"; else if (_IsFloppy()) psz = L"Drive.Floppy"; else if (_IsCDROM()) psz = L"Drive.CDROM"; else if (_IsStrictRemovable()) psz = L"Drive.Removable"; if (psz) return AssocElemCreateForClass(&CLSID_AssocSystemElement, psz, ppae); return E_FAIL; } int CMtPtLocal::GetDriveFlags() { UINT uDriveFlags = 0; // Is this a CD/DVD of some sort? if (_IsCDROM()) { // Yes LPCTSTR pszSubKey = NULL; if (_IsAudioDisc()) { uDriveFlags |= DRIVE_AUDIOCD; pszSubKey = TEXT("AudioCD\\shell"); } else if (_IsDVDDisc()) { uDriveFlags |= DRIVE_DVD; pszSubKey = TEXT("DVD\\shell"); } // Set the AutoOpen stuff, if applicable if (pszSubKey) { TCHAR ach[80]; DWORD cb = sizeof(ach); ach[0] = 0; // get the default verb for Audio CD/DVD if (ERROR_SUCCESS == SHRegGetValue(HKEY_CLASSES_ROOT, pszSubKey, NULL, SRRF_RT_REG_SZ, NULL, ach, &cb)) { // we should only set AUTOOPEN if there is a default verb on Audio CD/DVD if (ach[0]) uDriveFlags |= DRIVE_AUTOOPEN; } } } else { // No, by default every drive type is ShellOpen, except CD-ROMs uDriveFlags |= DRIVE_SHELLOPEN; } if (_IsAutorun()) { uDriveFlags |= DRIVE_AUTORUN; //FEATURE should we set AUTOOPEN based on a flag in the AutoRun.inf??? uDriveFlags |= DRIVE_AUTOOPEN; } return uDriveFlags; } void CMtPtLocal::GetTypeString(LPTSTR pszType, DWORD cchType) { int iID; *pszType = 0; if (_CanUseVolume()) { switch (_pvol->dwDriveType) { case HWDTS_FLOPPY35: if (_ShowUglyDriveNames()) { iID = IDS_DRIVES_DRIVE35_UGLY; } else { iID = IDS_DRIVES_DRIVE35; } break; case HWDTS_FLOPPY525: if (_ShowUglyDriveNames()) { iID = IDS_DRIVES_DRIVE525_UGLY; } else { iID = IDS_DRIVES_DRIVE525; } break; case HWDTS_REMOVABLEDISK: iID = IDS_DRIVES_REMOVABLE; break; case HWDTS_FIXEDDISK: iID = IDS_DRIVES_FIXED; break; case HWDTS_CDROM: iID = IDS_DRIVES_CDROM; break; } } else { UINT uDriveType = GetDriveType(_GetNameForFctCall()); switch (uDriveType) { case DRIVE_REMOVABLE: iID = IDS_DRIVES_REMOVABLE; break; case DRIVE_REMOTE: iID = IDS_DRIVES_NETDRIVE; break; case DRIVE_CDROM: iID = IDS_DRIVES_CDROM; break; case DRIVE_RAMDISK: iID = IDS_DRIVES_RAMDISK; break; case DRIVE_FIXED: default: iID = IDS_DRIVES_FIXED; break; } } LoadString(HINST_THISDLL, iID, pszType, cchType); } DWORD CMtPtLocal::GetShellDescriptionID() { DWORD dwShellDescrID; if (_CanUseVolume()) { switch (_pvol->dwDriveType) { case HWDTS_FLOPPY35: dwShellDescrID = SHDID_COMPUTER_DRIVE35; break; case HWDTS_FLOPPY525: dwShellDescrID = SHDID_COMPUTER_DRIVE525; break; case HWDTS_REMOVABLEDISK: dwShellDescrID = SHDID_COMPUTER_REMOVABLE; break; case HWDTS_FIXEDDISK: dwShellDescrID = SHDID_COMPUTER_FIXED; break; case HWDTS_CDROM: dwShellDescrID = SHDID_COMPUTER_CDROM; break; default: dwShellDescrID = SHDID_COMPUTER_OTHER; break; } } else { UINT uDriveType = GetDriveType(_GetNameForFctCall()); switch (uDriveType) { case DRIVE_REMOVABLE: dwShellDescrID = SHDID_COMPUTER_REMOVABLE; break; case DRIVE_CDROM: dwShellDescrID = SHDID_COMPUTER_CDROM; break; case DRIVE_FIXED: dwShellDescrID = SHDID_COMPUTER_FIXED; break; case DRIVE_RAMDISK: dwShellDescrID = SHDID_COMPUTER_RAMDISK; break; case DRIVE_NO_ROOT_DIR: case DRIVE_UNKNOWN: default: dwShellDescrID = SHDID_COMPUTER_OTHER; break; } } return dwShellDescrID; } /////////////////////////////////////////////////////////////////////////////// // DeviceIoControl stuff /////////////////////////////////////////////////////////////////////////////// HANDLE CMtPtLocal::_GetHandleWithAccessAndShareMode(DWORD dwDesiredAccess, DWORD dwShareMode) { HANDLE handle = INVALID_HANDLE_VALUE; WCHAR szVolumeGUIDWOSlash[50]; DWORD dwFileAttributes = 0; if (_CanUseVolume()) { StringCchCopy(szVolumeGUIDWOSlash, ARRAYSIZE(szVolumeGUIDWOSlash), _pvol->pszVolumeGUID); PathRemoveBackslash(szVolumeGUIDWOSlash); } else { // Go for VolumeGUID first if (GetVolumeNameForVolumeMountPoint(_GetName(), szVolumeGUIDWOSlash, ARRAYSIZE(szVolumeGUIDWOSlash))) { PathRemoveBackslash(szVolumeGUIDWOSlash); } else { // Probably a floppy, which cannot be mounted on a folder StringCchCopy(szVolumeGUIDWOSlash, ARRAYSIZE(szVolumeGUIDWOSlash), TEXT("\\\\.\\A:")); szVolumeGUIDWOSlash[4] = _GetNameFirstCharUCase(); } } return CreateFile(szVolumeGUIDWOSlash, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, dwFileAttributes, NULL); } // On NT, when use GENERIC_READ (as opposed to 0) in the CreateFile call, we // get a handle to the filesystem (CDFS), not the device itself. But we can't // change DriveIOCTL to do this, since that causes the floppy disks to spin // up, and we don't want to do that. HANDLE CMtPtLocal::_GetHandleReadRead() { return _GetHandleWithAccessAndShareMode(GENERIC_READ, FILE_SHARE_READ); } BOOL CMtPtLocal::_CanUseVolume() { // This is used in ASSERTs, do not add code that would introduce a side // effect in debug only (stephstm) // For Dismounted volumes, we want the code to take the alternate code // path. The volume, when ready to be re-mounted, will be remounted // until some code tries to access it. So using the alternate code path // will try to remount it, if it's ready it will get remounted, the Shell // Service will get an event, and we'll remove the DISMOUNTED bit. return (_pvol && !(_pvol->dwVolumeFlags & HWDVF_STATE_ACCESSDENIED) && !(_pvol->dwVolumeFlags & HWDVF_STATE_DISMOUNTED)); } HRESULT CMtPtLocal::_InitWithVolume(LPCWSTR pszMtPt, CVolume* pvol) { HRESULT hr = StringCchCopy(_szName, ARRAYSIZE(_szName), pszMtPt); if (SUCCEEDED(hr)) { pvol->AddRef(); _pvol = pvol; PathAddBackslash(_szName); _fMountedOnDriveLetter = _IsDriveLetter(pszMtPt); RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, _pvol->pszKeyName, REG_OPTION_NON_VOLATILE); RSSetTextValue(NULL, TEXT("BaseClass"), TEXT("Drive")); _InitAutorunInfo(); if (_CanUseVolume()) { if (HWDMC_HASDESKTOPINI & _pvol->dwMediaCap) { // we need to listen to change notify to know when this guys will change _UpdateCommentFromDesktopINI(); } } _InitLegacyRegIconAndLabelHelper(); } return hr; } // These can only be mounted on drive letter HRESULT CMtPtLocal::_Init(LPCWSTR pszMtPt) { HRESULT hr; ASSERT(_IsDriveLetter(pszMtPt)); if (GetLogicalDrives() & (1 << DRIVEID(pszMtPt))) { _fMountedOnDriveLetter = TRUE; hr = StringCchCopy(_szName, ARRAYSIZE(_szName), pszMtPt); if (SUCCEEDED(hr)) { PathAddBackslash(_szName); _GetNameFirstXChar(_szNameNoVolume, ARRAYSIZE(_szNameNoVolume)); RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, _szNameNoVolume, REG_OPTION_NON_VOLATILE); RSSetTextValue(NULL, TEXT("BaseClass"), TEXT("Drive")); _InitAutorunInfo(); } } else { hr = E_FAIL; } return hr; } void CMtPtLocal::_InitLegacyRegIconAndLabelHelper() { CMountPoint::_InitLegacyRegIconAndLabel(_HasAutorunIcon(), _HasAutorunLabel()); } void CMtPtLocal::StoreIconForUpdateImage(int iImage) { if (_CanUseVolume()) { _pvol->iShellImageForUpdateImage = iImage; } } void CMtPtLocal::_InitAutorunInfo() { if (_Shell32LoadedInDesktop()) { BOOL fAutorun = FALSE; if (!_CanUseVolume()) { if (_IsAutorun()) { fAutorun = TRUE; } } if (!fAutorun && !_fVolumePoint) { // Make sure to delete the shell key RSDeleteSubKey(TEXT("Shell")); } } } // Equivalent of GetDriveType API int CMtPtLocal::_GetDriveType() { int iDriveType = DRIVE_NO_ROOT_DIR; if (_CanUseVolume()) { switch (_pvol->dwDriveType) { case HWDTS_FLOPPY35: case HWDTS_FLOPPY525: case HWDTS_REMOVABLEDISK: iDriveType = DRIVE_REMOVABLE; break; case HWDTS_FIXEDDISK: iDriveType = DRIVE_FIXED; break; case HWDTS_CDROM: iDriveType = DRIVE_CDROM; break; } } else { iDriveType = GetDriveType(_GetNameForFctCall()); } return iDriveType; } #define VALID_VOLUME_PREFIX TEXT("\\\\?\\Volume") // static HRESULT CMtPtLocal::_CreateVolume(VOLUMEINFO* pvolinfo, CVolume** ppvolNew) { ASSERT(_csDL.IsInside()); HRESULT hr; if (!StrCmpN(pvolinfo->pszVolumeGUID, VALID_VOLUME_PREFIX, ARRAYSIZE(VALID_VOLUME_PREFIX) - 1)) { CVolume* pvol = new CVolume(); *ppvolNew = NULL; if (pvol) { // The next four strings shouyld always be set to something pvol->pszDeviceIDVolume = StrDup(pvolinfo->pszDeviceIDVolume); pvol->pszVolumeGUID = StrDup(pvolinfo->pszVolumeGUID); pvol->pszLabel = StrDup(pvolinfo->pszLabel); pvol->pszFileSystem = StrDup(pvolinfo->pszFileSystem); // The following five strings are optional if (pvolinfo->pszAutorunIconLocation) { pvol->pszAutorunIconLocation = StrDup(pvolinfo->pszAutorunIconLocation); } if (pvolinfo->pszAutorunLabel) { pvol->pszAutorunLabel = StrDup(pvolinfo->pszAutorunLabel); } if (pvolinfo->pszIconLocationFromService) { pvol->pszIconFromService = StrDup(pvolinfo->pszIconLocationFromService); } if (pvolinfo->pszNoMediaIconLocationFromService) { pvol->pszNoMediaIconFromService = StrDup(pvolinfo->pszNoMediaIconLocationFromService); } if (pvolinfo->pszLabelFromService) { pvol->pszLabelFromService = StrDup(pvolinfo->pszLabelFromService); } if (pvol->pszDeviceIDVolume && pvol->pszVolumeGUID && pvol->pszLabel && pvol->pszFileSystem) { pvol->dwState = pvolinfo->dwState; pvol->dwVolumeFlags = pvolinfo->dwVolumeFlags; pvol->dwDriveType = pvolinfo->dwDriveType; pvol->dwDriveCapability = pvolinfo->dwDriveCapability; pvol->dwFileSystemFlags = pvolinfo->dwFileSystemFlags; pvol->dwMaxFileNameLen = pvolinfo->dwMaxFileNameLen; pvol->dwRootAttributes = pvolinfo->dwRootAttributes; pvol->dwSerialNumber = pvolinfo->dwSerialNumber; pvol->dwDriveState = pvolinfo->dwDriveState; pvol->dwMediaState = pvolinfo->dwMediaState; pvol->dwMediaCap = pvolinfo->dwMediaCap; if (_hdpaVolumes && (-1 != DPA_AppendPtr(_hdpaVolumes, pvol))) { pvol->pszKeyName = pvol->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID; pvol->AddRef(); *ppvolNew = pvol; hr = S_OK; } else { hr = E_OUTOFMEMORY; } } else { hr = E_OUTOFMEMORY; } if (FAILED(hr)) { delete pvol; } } else { hr = E_OUTOFMEMORY; } } else { hr = E_FAIL; } return hr; } // this helper function will hit the drive to see if media is present. // should only be used for drives that don't support the HWDVF_STATE_SUPPORTNOTIFICATION BOOL CMtPtLocal::_ForceCheckMediaPresent() { BOOL bRet = FALSE; // assume no media present HANDLE hDevice = _GetHandleWithAccessAndShareMode(GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE); if (hDevice != INVALID_HANDLE_VALUE) { DWORD dwDummy; // call the ioctl to verify media presence if (DeviceIoControl(hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &dwDummy, NULL)) { bRet = TRUE; } CloseHandle(hDevice); } return bRet; } BOOL CMtPtLocal::_IsMediaPresent() { BOOL bRet; if (!_CanUseVolume() || !(_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { // if the drive dosen't support notification, we need to ping it now bRet = _ForceCheckMediaPresent(); } else { bRet = (HWDMS_PRESENT & _pvol->dwMediaState); } return bRet; } BOOL CMtPtLocal::_IsFormatted() { BOOL bRet = FALSE; if (!_CanUseVolume() || !(_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION)) { // if the drive dosen't support notification, we need to ping it now bRet = GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL, NULL, NULL, NULL, NULL); } else { bRet = (_IsMediaPresent() && (HWDMS_FORMATTED & _pvol->dwMediaState)); } return bRet; } BOOL CMtPtLocal::_IsReadOnly() { ASSERT(_CanUseVolume()); ASSERT(_IsMediaPresent()); // does not make sense otherwise BOOL fRet = FALSE; if (_IsCDROM() && ( (HWDMC_WRITECAPABILITY_SUPPORTDETECTION & _pvol->dwMediaState) && ( (HWDMC_CDROM & _pvol->dwMediaCap) || (HWDMC_DVDROM & _pvol->dwMediaCap) ) ) ) { fRet = TRUE; } else { // We could optimize by checking if the floppy is write protected. But // it might not be worth it. fRet = FALSE; } return fRet; } BOOL CMtPtLocal::_IsMountedOnDriveLetter() { return _fMountedOnDriveLetter; } CMtPtLocal::CMtPtLocal() { #ifdef DEBUG ++_cMtPtLocal; #endif } CMtPtLocal::~CMtPtLocal() { if (_pvol) { _pvol->Release(); } #ifdef DEBUG --_cMtPtLocal; #endif } // static HRESULT CMtPtLocal::_CreateMtPtLocal(LPCWSTR pszMountPoint) { ASSERT(_csDL.IsInside()); HRESULT hr; CMtPtLocal* pmtptl = new CMtPtLocal(); if (pmtptl) { int iDrive = DRIVEID(pszMountPoint); if (_rgMtPtDriveLetterLocal[iDrive]) { _rgMtPtDriveLetterLocal[iDrive]->Release(); _rgMtPtDriveLetterLocal[iDrive] = NULL; } hr = pmtptl->_Init(pszMountPoint); if (SUCCEEDED(hr)) { // Yes _rgMtPtDriveLetterLocal[iDrive] = pmtptl; } else { delete pmtptl; } } else { hr = E_OUTOFMEMORY; } return hr; } HRESULT CMtPtLocal::GetMountPointName(LPWSTR pszMountPoint, DWORD cchMountPoint) { return StringCchCopy(pszMountPoint, cchMountPoint, _GetName()); } // static HRESULT CMtPtLocal::_CreateMtPtLocalWithVolume(LPCWSTR pszMountPoint, CVolume* pvol) { ASSERT(_csDL.IsInside()); HRESULT hr; CMtPtLocal* pmtptlNew = new CMtPtLocal(); if (pmtptlNew) { // Is it a drive letter only? if (_IsDriveLetter(pszMountPoint)) { // Yes int iDrive = DRIVEID(pszMountPoint); if (_rgMtPtDriveLetterLocal[iDrive]) { _rgMtPtDriveLetterLocal[iDrive]->Release(); _rgMtPtDriveLetterLocal[iDrive] = NULL; } } else { _RemoveLocalMountPoint(pszMountPoint); } hr = pmtptlNew->_InitWithVolume(pszMountPoint, pvol); if (SUCCEEDED(hr)) { // Is it a drive letter only? if (_IsDriveLetter(pszMountPoint)) { // Yes int iDrive = DRIVEID(pszMountPoint); _rgMtPtDriveLetterLocal[iDrive] = pmtptlNew; } else { hr = _StoreMtPtMOF(pmtptlNew); } } if (FAILED(hr)) { delete pmtptlNew; } } else { hr = E_OUTOFMEMORY; } return hr; } // static HRESULT CMtPtLocal::_CreateMtPtLocalFromVolumeGuid(LPCWSTR pszVolumeGuid, CMountPoint ** ppmtpt ) { ASSERT(_csDL.IsInside()); HRESULT hr; CMtPtLocal* pmtptlNew = new CMtPtLocal(); Assert(NULL != ppmtpt); *ppmtpt = (CMountPoint*)pmtptlNew; if (pmtptlNew) { ASSERT(NULL == pmtptlNew->_pvol); hr = StringCchCopy(pmtptlNew->_szName, ARRAYSIZE(pmtptlNew->_szName), pszVolumeGuid); if (SUCCEEDED(hr)) { pmtptlNew->RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, pmtptlNew->_szName, REG_OPTION_NON_VOLATILE); PathAddBackslash(pmtptlNew->_szName); pmtptlNew->_fMountedOnDriveLetter = FALSE; pmtptlNew->_fVolumePoint = TRUE; pmtptlNew->_InitAutorunInfo(); } } else { hr = E_OUTOFMEMORY; } return hr; } // static CVolume* CMtPtLocal::_GetVolumeByMtPt(LPCWSTR pszMountPoint) { ASSERT(_csDL.IsInside()); CVolume* pvol = NULL; WCHAR szVolumeGUID[50]; if (_fLocalDrivesInited) { if (GetVolumeNameForVolumeMountPoint(pszMountPoint, szVolumeGUID, ARRAYSIZE(szVolumeGUID))) { DWORD c = DPA_GetPtrCount(_hdpaVolumes); for (DWORD dw = 0; dw < c; ++dw) { pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, dw); if (pvol) { if (!lstrcmpi(pvol->pszVolumeGUID, szVolumeGUID)) { pvol->AddRef(); break; } else { pvol = NULL; } } } } } return pvol; } // static CVolume* CMtPtLocal::_GetVolumeByID(LPCWSTR pszDeviceIDVolume) { ASSERT(_csDL.IsInside()); CVolume* pvol = NULL; if (_hdpaVolumes) { DWORD c = DPA_GetPtrCount(_hdpaVolumes); for (DWORD dw = 0; dw < c; ++dw) { pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, dw); if (pvol) { if (!lstrcmpi(pvol->pszDeviceIDVolume, pszDeviceIDVolume)) { pvol->AddRef(); break; } else { pvol = NULL; } } } } return pvol; } // static CVolume* CMtPtLocal::_GetAndRemoveVolumeByID(LPCWSTR pszDeviceIDVolume) { CVolume* pvol = NULL; _csDL.Enter(); if (_hdpaVolumes) { DWORD c = DPA_GetPtrCount(_hdpaVolumes); for (int i = c - 1; i >= 0; --i) { pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i); if (pvol) { if (!lstrcmpi(pvol->pszDeviceIDVolume, pszDeviceIDVolume)) { // Do not AddRef DPA_DeletePtr(_hdpaVolumes, i); break; } else { pvol = NULL; } } } } _csDL.Leave(); return pvol; } // static HRESULT CMtPtLocal::_GetAndRemoveVolumeAndItsMtPts(LPCWSTR pszDeviceIDVolume, CVolume** ppvol, HDPA hdpaMtPts) { _csDL.Enter(); CVolume* pvol = _GetAndRemoveVolumeByID(pszDeviceIDVolume); if (pvol) { for (DWORD dw = 0; dw < 26; ++dw) { CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw]; if (pmtptl && pmtptl->_pvol) { if (pmtptl->_pvol == pvol) { _rgMtPtDriveLetterLocal[dw] = 0; DPA_AppendPtr(hdpaMtPts, pmtptl); break; } } } _csLocalMtPtHDPA.Enter(); if (_hdpaMountPoints) { DWORD c = DPA_GetPtrCount(_hdpaMountPoints); for (int i = c - 1; i >= 0; --i) { CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i); if (pmtptl && pmtptl->_pvol) { if (pmtptl->_pvol == pvol) { DPA_DeletePtr(_hdpaMountPoints, i); DPA_AppendPtr(hdpaMtPts, pmtptl); } } } } _csLocalMtPtHDPA.Leave(); } *ppvol = pvol; _csDL.Leave(); return S_OK; } BOOL CMtPtLocal::_IsMiniMtPt() { return !_CanUseVolume(); } HKEY CMtPtLocal::GetRegKey() { TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetRegKey: for '%s'", _GetNameDebug()); if (_IsAutoRunDrive()) { _ProcessAutoRunFile(); } return RSDuplicateRootKey(); } DWORD CMtPtLocal::_GetRegVolumeGen() { ASSERT(_CanUseVolume()); DWORD dwGen; if (!_rsVolumes.RSGetDWORDValue(_pvol->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), &dwGen)) { dwGen = 0; } return dwGen; } BOOL CMtPtLocal::_NeedToRefresh() { ASSERT(_csDL.IsInside()); ASSERT(!_Shell32LoadedInDesktop()); BOOL fNeedToRefresh = FALSE; if (_CanUseVolume()) { DWORD dwRegVolumeGeneration = _GetRegVolumeGen(); if (dwRegVolumeGeneration != _pvol->dwGeneration) { // Remove it so that new mtpts do not get it. CVolume* pvolnew; CVolume* pvol = _GetAndRemoveVolumeByID(_pvol->pszDeviceIDVolume); if (pvol) { // Release our cache ref count pvol->Release(); } // Replace the volume if (SUCCEEDED(CMtPtLocal::_CreateVolumeFromReg(_pvol->pszDeviceIDVolume, &pvolnew))) { pvolnew->Release(); } fNeedToRefresh = TRUE; } } return fNeedToRefresh; } // static HRESULT CMtPtLocal::_CreateVolumeFromVOLUMEINFO2(VOLUMEINFO2* pvolinfo2, CVolume** ppvolNew) { VOLUMEINFO volinfo = {0}; volinfo.pszDeviceIDVolume = pvolinfo2->szDeviceIDVolume; volinfo.pszVolumeGUID = pvolinfo2->szVolumeGUID; volinfo.pszLabel = pvolinfo2->szLabel; volinfo.pszFileSystem = pvolinfo2->szFileSystem; volinfo.dwState = pvolinfo2->dwState; volinfo.dwVolumeFlags = pvolinfo2->dwVolumeFlags; volinfo.dwDriveType = pvolinfo2->dwDriveType; volinfo.dwDriveCapability = pvolinfo2->dwDriveCapability; volinfo.dwFileSystemFlags = pvolinfo2->dwFileSystemFlags; volinfo.dwMaxFileNameLen = pvolinfo2->dwMaxFileNameLen; volinfo.dwRootAttributes = pvolinfo2->dwRootAttributes; volinfo.dwSerialNumber = pvolinfo2->dwSerialNumber; volinfo.dwDriveState = pvolinfo2->dwDriveState; volinfo.dwMediaState = pvolinfo2->dwMediaState; volinfo.dwMediaCap = pvolinfo2->dwMediaCap; if (-1 != pvolinfo2->oAutorunIconLocation) { volinfo.pszAutorunIconLocation = pvolinfo2->szOptionalStrings + pvolinfo2->oAutorunIconLocation; } if (-1 != pvolinfo2->oAutorunLabel) { volinfo.pszAutorunLabel = pvolinfo2->szOptionalStrings + pvolinfo2->oAutorunLabel; } if (-1 != pvolinfo2->oIconLocationFromService) { volinfo.pszIconLocationFromService = pvolinfo2->szOptionalStrings + pvolinfo2->oIconLocationFromService; } if (-1 != pvolinfo2->oNoMediaIconLocationFromService) { volinfo.pszNoMediaIconLocationFromService = pvolinfo2->szOptionalStrings + pvolinfo2->oNoMediaIconLocationFromService; } if (-1 != pvolinfo2->oLabelFromService) { volinfo.pszLabelFromService = pvolinfo2->szOptionalStrings + pvolinfo2->oLabelFromService; } return _CreateVolume(&volinfo, ppvolNew); } // static HRESULT CMtPtLocal::_CreateVolumeFromRegHelper(LPCWSTR pszGUID, CVolume** ppvolNew) { ASSERT(!_Shell32LoadedInDesktop()); ASSERT(_csDL.IsInside()); HRESULT hr; DWORD cbSize = MAX_VOLUMEINFO2; PBYTE pb = (PBYTE)LocalAlloc(LPTR, cbSize); if (pb) { if (_rsVolumes.RSGetBinaryValue(pszGUID, TEXT("Data"), pb, &cbSize)) { DWORD dwGen; if (_rsVolumes.RSGetDWORDValue(pszGUID, TEXT("Generation"), &dwGen)) { VOLUMEINFO2* pvolinfo2 = (VOLUMEINFO2*)pb; hr = _CreateVolumeFromVOLUMEINFO2(pvolinfo2, ppvolNew); if (SUCCEEDED(hr)) { (*ppvolNew)->dwGeneration = dwGen; } } else { hr = E_FAIL; } } else { hr = E_FAIL; } LocalFree(pb); } else { hr = E_OUTOFMEMORY; } return hr; } // static HRESULT CMtPtLocal::_CreateVolumeFromReg(LPCWSTR pszDeviceIDVolume, CVolume** ppvolNew) { ASSERT(!_Shell32LoadedInDesktop()); ASSERT(_csDL.IsInside()); HRESULT hr; WCHAR szDeviceIDWithSlash[MAX_PATH]; WCHAR szVolumeGUID[50]; hr = StringCchCopy(szDeviceIDWithSlash, ARRAYSIZE(szDeviceIDWithSlash), pszDeviceIDVolume); if (SUCCEEDED(hr)) { if (PathAddBackslash(szDeviceIDWithSlash)) { if (GetVolumeNameForVolumeMountPoint(szDeviceIDWithSlash, szVolumeGUID, ARRAYSIZE(szVolumeGUID))) { LPWSTR pszGUID = &(szVolumeGUID[OFFSET_GUIDWITHINVOLUMEGUID]); hr = _CreateVolumeFromRegHelper(pszGUID, ppvolNew); } else { hr = E_FAIL; } } else { hr = E_FAIL; } } return hr; } // static HRESULT CMtPtLocal::_UpdateVolumeRegInfo(VOLUMEINFO* pvolinfo) { ASSERT(_Shell32LoadedInDesktop()); ASSERT(_csDL.IsInside()); HRESULT hr; DWORD cbSize = MAX_VOLUMEINFO2; PBYTE pb = (PBYTE)LocalAlloc(LPTR, cbSize); if (pb) { DWORD dwGen; VOLUMEINFO2* pvolinfo2 = (VOLUMEINFO2*)pb; // Get the Generation if (!_rsVolumes.RSGetDWORDValue( pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), &dwGen)) { dwGen = 0; } ++dwGen; ASSERT(pvolinfo->pszDeviceIDVolume); ASSERT(pvolinfo->pszVolumeGUID); ASSERT(pvolinfo->pszLabel); ASSERT(pvolinfo->pszFileSystem); hr = StringCchCopy(pvolinfo2->szDeviceIDVolume, ARRAYSIZE(pvolinfo2->szDeviceIDVolume), pvolinfo->pszDeviceIDVolume); if (SUCCEEDED(hr)) { hr = StringCchCopy(pvolinfo2->szVolumeGUID, ARRAYSIZE(pvolinfo2->szVolumeGUID), pvolinfo->pszVolumeGUID); } if (SUCCEEDED(hr)) { StringCchCopy(pvolinfo2->szLabel, ARRAYSIZE(pvolinfo2->szLabel), pvolinfo->pszLabel); StringCchCopy(pvolinfo2->szFileSystem, ARRAYSIZE(pvolinfo2->szFileSystem), pvolinfo->pszFileSystem); pvolinfo2->dwState = pvolinfo->dwState; pvolinfo2->dwVolumeFlags = pvolinfo->dwVolumeFlags; pvolinfo2->dwDriveType = pvolinfo->dwDriveType; pvolinfo2->dwDriveCapability = pvolinfo->dwDriveCapability; pvolinfo2->dwFileSystemFlags = pvolinfo->dwFileSystemFlags; pvolinfo2->dwMaxFileNameLen = pvolinfo->dwMaxFileNameLen; pvolinfo2->dwRootAttributes = pvolinfo->dwRootAttributes; pvolinfo2->dwSerialNumber = pvolinfo->dwSerialNumber; pvolinfo2->dwDriveState = pvolinfo->dwDriveState; pvolinfo2->dwMediaState = pvolinfo->dwMediaState; pvolinfo2->dwMediaCap = pvolinfo->dwMediaCap; pvolinfo2->oAutorunIconLocation = -1; pvolinfo2->oAutorunLabel = -1; pvolinfo2->oIconLocationFromService = -1; pvolinfo2->oNoMediaIconLocationFromService = -1; pvolinfo2->oLabelFromService = -1; LPWSTR pszNext = pvolinfo2->szOptionalStrings; size_t cchLeft = (cbSize - sizeof(*pvolinfo2) + sizeof(pvolinfo2->szOptionalStrings)) / sizeof(WCHAR); size_t cchLeftBeginWith = cchLeft; // The following five strings are optional if (pvolinfo->pszAutorunIconLocation) { pvolinfo2->oAutorunIconLocation = (DWORD)(cchLeftBeginWith - cchLeft); hr = StringCchCopyEx(pszNext, cchLeft, pvolinfo->pszAutorunIconLocation, &pszNext, &cchLeft, 0); ++pszNext; --cchLeft; } if (SUCCEEDED(hr) && pvolinfo->pszAutorunLabel) { pvolinfo2->oAutorunLabel = (DWORD)(cchLeftBeginWith - cchLeft); hr = StringCchCopyEx(pszNext, cchLeft, pvolinfo->pszAutorunLabel, &pszNext, &cchLeft, 0); ++pszNext; --cchLeft; } if (SUCCEEDED(hr) && pvolinfo->pszIconLocationFromService) { pvolinfo2->oIconLocationFromService = (DWORD)(cchLeftBeginWith - cchLeft); hr = StringCchCopyEx(pszNext, cchLeft, pvolinfo->pszIconLocationFromService, &pszNext, &cchLeft, 0); ++pszNext; --cchLeft; } if (SUCCEEDED(hr) && pvolinfo->pszNoMediaIconLocationFromService) { pvolinfo2->oNoMediaIconLocationFromService = (DWORD)(cchLeftBeginWith - cchLeft); hr = StringCchCopyEx(pszNext, cchLeft, pvolinfo->pszNoMediaIconLocationFromService, &pszNext, &cchLeft, 0); ++pszNext; --cchLeft; } if (SUCCEEDED(hr) && pvolinfo->pszLabelFromService) { pvolinfo2->oLabelFromService = (DWORD)(cchLeftBeginWith - cchLeft); hr = StringCchCopyEx(pszNext, cchLeft, pvolinfo->pszLabelFromService, &pszNext, &cchLeft, 0); // Remove one for the null terminator --cchLeft; } if (SUCCEEDED(hr)) { if (_rsVolumes.RSSetBinaryValue(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Data"), pb, cbSize - (cchLeft * sizeof(WCHAR)), REG_OPTION_VOLATILE)) { if (_rsVolumes.RSSetDWORDValue(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), dwGen)) { hr = S_OK; } else { hr = E_FAIL; } } else { hr = E_FAIL; } } if (FAILED(hr)) { _rsVolumes.RSDeleteSubKey(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID); } } LocalFree(pb); } else { hr = E_OUTOFMEMORY; } return hr; } // static HRESULT CMtPtLocal::_UpdateVolumeRegInfo2(VOLUMEINFO2* pvolinfo2) { ASSERT(_Shell32LoadedInDesktop()); ASSERT(_csDL.IsInside()); HRESULT hr; DWORD dwGen; // Get the Generation if (!_rsVolumes.RSGetDWORDValue( pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), &dwGen)) { dwGen = 0; } ++dwGen; if (_rsVolumes.RSSetBinaryValue(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Data"), (PBYTE)pvolinfo2, pvolinfo2->cbSize, REG_OPTION_VOLATILE)) { if (_rsVolumes.RSSetDWORDValue(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), dwGen)) { hr = S_OK; } else { hr = E_FAIL; } } else { hr = E_FAIL; } if (FAILED(hr)) { _rsVolumes.RSDeleteSubKey(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID); } return hr; } //static BOOL CMtPtLocal::Initialize() { _rsVolumes.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, g_szCrossProcessCacheVolumeKey, REG_OPTION_VOLATILE); return TRUE; } void CMtPtLocal::FinalCleanUp() { if (_Shell32LoadedInDesktop()) { _rsVolumes.RSDeleteKey(); } } static const TWODWORDS arcontenttypemappings[] = { { HWDMC_HASAUTORUNINF, ARCONTENT_AUTORUNINF }, { HWDMC_HASAUDIOTRACKS, ARCONTENT_AUDIOCD }, { HWDMC_HASDVDMOVIE, ARCONTENT_DVDMOVIE }, }; static const TWODWORDS arblankmediamappings[] = { { HWDMC_CDRECORDABLE, ARCONTENT_BLANKCD }, { HWDMC_CDREWRITABLE, ARCONTENT_BLANKCD }, { HWDMC_DVDRECORDABLE, ARCONTENT_BLANKDVD }, { HWDMC_DVDREWRITABLE, ARCONTENT_BLANKDVD }, }; DWORD CMtPtLocal::_GetAutorunContentType() { DWORD dwRet = 0; if (_CanUseVolume()) { dwRet = _DoDWORDMapping(_pvol->dwMediaCap, arcontenttypemappings, ARRAYSIZE(arcontenttypemappings), TRUE); if (_pvol->dwMediaState & HWDMS_FORMATTED) { dwRet |= ARCONTENT_UNKNOWNCONTENT; } else { ASSERT(!dwRet); DWORD dwDriveCapabilities; DWORD dwMediaCapabilities; if (_IsCDROM()) { if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities))) { dwRet = _DoDWORDMapping(dwMediaCapabilities, arblankmediamappings, ARRAYSIZE(arblankmediamappings), TRUE); } } } } else { // If there's no _pvol, we care only about autorun.inf if (_IsAutorun()) { dwRet = ARCONTENT_AUTORUNINF; } if (_IsFormatted()) { dwRet |= ARCONTENT_UNKNOWNCONTENT; } } return dwRet; } // static BOOL CMtPtLocal::IsVolume(LPCWSTR pszDeviceID) { BOOL fRet = FALSE; _csDL.Enter(); CVolume* pvol = _GetVolumeByID(pszDeviceID); if (pvol) { fRet = TRUE; pvol->Release(); } _csDL.Leave(); return fRet; } static const TWODWORDS drivetypemappings[] = { { HWDTS_FLOPPY35 , DT_FLOPPY35 }, { HWDTS_FLOPPY525 , DT_FLOPPY525 }, { HWDTS_REMOVABLEDISK, DT_REMOVABLEDISK }, { HWDTS_FIXEDDISK , DT_FIXEDDISK }, { HWDTS_CDROM , DT_CDROM }, }; static const TWODWORDS drivetypemappingusingGDT[] = { { DRIVE_REMOVABLE , DT_REMOVABLEDISK }, { DRIVE_FIXED , DT_FIXEDDISK }, { DRIVE_RAMDISK , DT_FIXEDDISK }, { DRIVE_CDROM , DT_CDROM }, }; static const TWODWORDS cdtypemappings[] = { { HWDDC_CDROM , DT_CDROM }, { HWDDC_CDRECORDABLE , DT_CDR }, { HWDDC_CDREWRITABLE , DT_CDRW }, { HWDDC_DVDROM , DT_DVDROM }, { HWDDC_DVDRECORDABLE, DT_DVDR }, { HWDDC_DVDREWRITABLE, DT_DVDRW }, { HWDDC_DVDRAM , DT_DVDRAM }, }; DWORD CMtPtLocal::_GetMTPTDriveType() { DWORD dwRet = 0; if (_CanUseVolume()) { dwRet = _DoDWORDMapping(_pvol->dwDriveType, drivetypemappings, ARRAYSIZE(drivetypemappings), TRUE); if (DT_CDROM == dwRet) { DWORD dwDriveCapabilities; DWORD dwMediaCapabilities; if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities))) { dwRet |= _DoDWORDMapping(dwDriveCapabilities, cdtypemappings, ARRAYSIZE(cdtypemappings), TRUE); } } } else { dwRet = _DoDWORDMapping(GetDriveType(_GetNameForFctCall()), drivetypemappingusingGDT, ARRAYSIZE(drivetypemappingusingGDT), FALSE); } return dwRet; } /* TBD CT_UNKNOWNCONTENT 0x00000008 CT_AUTOPLAYMUSIC 0x00000100 CT_AUTOPLAYPIX 0x00000200 CT_AUTOPLAYMOVIE 0x00000400*/ static const TWODWORDS contenttypemappings[] = { { HWDMC_HASAUTORUNINF, CT_AUTORUNINF }, { HWDMC_HASAUDIOTRACKS, CT_CDAUDIO }, { HWDMC_HASDVDMOVIE, CT_DVDMOVIE }, }; static const TWODWORDS blankmediamappings[] = { { HWDMC_CDRECORDABLE, CT_BLANKCDR }, { HWDMC_CDREWRITABLE, CT_BLANKCDRW }, { HWDMC_DVDRECORDABLE, CT_BLANKDVDR }, { HWDMC_DVDREWRITABLE, CT_BLANKDVDRW }, }; DWORD CMtPtLocal::_GetMTPTContentType() { DWORD dwRet = 0; if (_CanUseVolume()) { dwRet = _DoDWORDMapping(_pvol->dwMediaCap, contenttypemappings, ARRAYSIZE(contenttypemappings), TRUE); if (!(_pvol->dwMediaState & HWDMS_FORMATTED)) { ASSERT(!dwRet); DWORD dwDriveCapabilities; DWORD dwMediaCapabilities; if (_IsCDROM()) { if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities))) { dwRet = _DoDWORDMapping(dwMediaCapabilities, blankmediamappings, ARRAYSIZE(blankmediamappings), TRUE); } } } else { dwRet |= CT_UNKNOWNCONTENT; } } else { // If there's no _pvol, we care only about autorun.inf if (_IsAutorun()) { dwRet = CT_AUTORUNINF; } if (_IsFormatted()) { dwRet |= CT_UNKNOWNCONTENT; } } return dwRet; }