#ifndef _MTPT_H #define _MTPT_H #include "regsprtb.h" #include "hwcmmn.h" #include "dpa.h" #include #define REGSTR_MTPT_ROOTKEY2 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2") ///////////////////////////////////////////////////////////////////////////// // Assumptions ///////////////////////////////////////////////////////////////////////////// // 1- Floppies (3.5" and 5.25") are always FAT // 2- FAT does not support compression // 3- DRIVE_CDROM == CDFS or UDF for File system // 4- CDFS or UDF does not support compression // ///////////////////////////////////////////////////////////////////////////// #define DT_FIXEDDISK 0x00000001 #define DT_FLOPPY35 0x00000004 #define DT_FLOPPY525 0x00000008 #define DT_CDROM 0x00000020 #define DT_CDR 0x00000040 #define DT_CDRW 0x00000080 #define DT_DVDROM 0x00000100 #define DT_DVDRAM 0x00000200 #define DT_DVDR 0x00000400 #define DT_DVDRW 0x00000800 #define DT_REMOVABLEDISK 0x00001000 #define DT_REMOTE 0x00002000 #define DT_ANYTYPE 0x0000FFFF #define DT_ANYFLOPPYDRIVES ( DT_FLOPPY35 | \ DT_FLOPPY525 ) #define DT_ANYCDDRIVES ( DT_CDROM | \ DT_CDR | \ DT_CDRW | \ DT_DVDROM | \ DT_DVDRAM | \ DT_DVDR | \ DT_DVDRW ) #define DT_ANYDVDDRIVES ( DT_DVDROM | \ DT_DVDRAM | \ DT_DVDR | \ DT_DVDRW ) #define DT_ANYWRITABLECDDRIVES ( DT_CDR | \ DT_CDRW ) #define DT_ANYWRITABLEDVDDRIVES ( DT_DVDR | \ DT_DVDRW ) #define DT_ANYREMOVABLEMEDIADRIVES ( DT_ANYCDDRIVES | \ DT_ANYFLOPPYDRIVES | \ DT_REMOVABLEDISK ) #define DT_ANYLOCALDRIVES ( DT_ANYREMOVABLEMEDIADRIVES | \ DT_FIXEDDISK ) #define AUTORUNFLAG_MEDIAARRIVAL 0x00000001 #define AUTORUNFLAG_MTPTARRIVAL 0x00000002 #define AUTORUNFLAG_MENUINVOKED 0x00000004 // put in shell32\shellprv.h #define TF_MOUNTPOINT 0x08000000 #define MAX_DISPLAYNAME MAX_PATH #define MAX_MTPTCOMMENT MAX_PATH #define OFFSET_GUIDWITHINVOLUMEGUID (sizeof("\\\\?\\Volume") - 1) class CMountPoint; class CMtPtLocal; class CMtPtRemote; class CCriticalSection : CRITICAL_SECTION { public: BOOL Init() { // need to use InitializeCriticalSectionAndSpinCount since we are called during process attach if (InitializeCriticalSectionAndSpinCount(this, 0)) { _fInited = TRUE; } #ifdef DEBUG _dwThreadIDThatShouldNotTryToEnter = 0; _fFakeEntered = FALSE; #endif return _fInited; } void Enter() { #ifdef DEBUG if (_dwThreadIDThatShouldNotTryToEnter) { ASSERT(_dwThreadIDThatShouldNotTryToEnter != GetCurrentThreadId()); } #endif if (!_fShuttingDown) { if (_fInited) { EnterCriticalSection(this); } } } void Leave() { if (!_fShuttingDown) { if (_fInited) { LeaveCriticalSection(this); } } } void Delete() { if (_fInited) { _fInited = FALSE; DeleteCriticalSection(this); } } BOOL IsInitialized() { return _fInited; } BOOL _fInited; BOOL _fShuttingDown; #ifdef DEBUG BOOL IsInside() { ASSERT(_fInited); return _fFakeEntered || (OwningThread == UlongToHandle(GetCurrentThreadId())); } void FakeEnter() { ASSERT(_fInited); // See the comment in CMountPoint::_InitLocalDriveHelper where we use this fct. // Basically the cirtiical section should already be entered. This will not // verify that it's entered by the thread that launched us, but it will verify // that at least one thread entered it. ASSERT(OwningThread); _fFakeEntered = TRUE; } void FakeLeave() { ASSERT(_fInited); ASSERT(OwningThread); _fFakeEntered = FALSE; } void SetThreadIDToCheckForEntrance(DWORD dwThreadID) { _dwThreadIDThatShouldNotTryToEnter = dwThreadID; } DWORD _dwThreadIDThatShouldNotTryToEnter; BOOL _fFakeEntered; #endif }; typedef enum { APS_RESET = 0, APS_DID_SNIFF = 0x0001, // APS_ } APSTATEF; typedef enum { CTI_PIX = 0, CTI_MUSIC, CTI_VIDEO, CTI_MIXCONTENT, _CTI_TOTAL_COUNT_ } CONTENTTYPE_INDEX; class CAutoPlayParams { public: CAutoPlayParams(LPCWSTR pszDrive, CMountPoint* pMtPt, DWORD dwAutorunFlags); ~CAutoPlayParams() { ATOMICRELEASE(_pdo); } PCWSTR Drive() { return _pszDrive; } CMountPoint *MountPoint() { return _pmtpt; } CMtPtLocal *MountPointLocal() { return _pmtptl; } DWORD DriveType() { return _dwDriveType; } HRESULT DataObject(IDataObject **ppdo) { HRESULT hr = _InitObjects(NULL); *ppdo = _pdo; if (SUCCEEDED(hr)) _pdo->AddRef(); return hr; } BOOL IsContentTypePresent(DWORD dwContentType); DWORD ContentType(); void ForceSniff(); protected: // methods BOOL _ShouldSniffDrive(BOOL fCheckHandlerDefaults); void _TrySniff(); HRESULT _Sniff(DWORD *pdwFound); HRESULT _AddWalkToDataObject(INamespaceWalk* pnsw); HRESULT _InitObjects(IShellFolder **ppsf); protected: // members DWORD _state; // APSTATEF DWORD _dwDriveType; DWORD _dwContentType; DWORD _dwAutorunFlags; PCWSTR _pszDrive; CMountPoint *_pmtpt; CMtPtLocal* _pmtptl; IDataObject *_pdo; public: BOOL _fCheckAlwaysDoThisCheckBox; }; #define AUTORUN_CONDITION_FCT(a) static BOOL (a)(HWND hwndForeground, CAutoPlayParams *papp); class CMountPoint : public CRegSupport { /////////////////////////////////////////////////////////////////////////////// // Management (mtptmgmt.cpp) /////////////////////////////////////////////////////////////////////////////// public: static CMountPoint* GetMountPoint(LPCTSTR pszMountPoint, BOOL fCreateNew = TRUE); static CMountPoint* GetSimulatedMountPointFromVolumeGuid( LPCTSTR pszVolumeGuid ); static CMountPoint* GetMountPoint(int iDrive, BOOL fCreateNew = TRUE, BOOL fOKToHitNet = TRUE); static DWORD GetDrivesMask(); static void HandleMountPointNetEvent(LPCWSTR pszDrive, BOOL fArrival); static DWORD WINAPI HandleMountPointLocalEventThreadProc(void* pv); static void HandleMountPointLocalEvent(LPCWSTR pszDrive, BOOL fArrival, BOOL fMediaEvent); static void OnNetShareArrival(LPCWSTR pszDrive); static void OnNetShareRemoval(LPCWSTR pszDrive); static void OnMediaArrival(LPCWSTR pszDrive); static void OnMountPointArrival(LPCWSTR pszDrive); static void OnMediaRemoval(LPCWSTR pszDrive); static void OnMountPointRemoval(LPCWSTR pszDrive); static void FinalCleanUp(); static BOOL Initialize(); static void NotifyUnavailableNetDriveGone(LPCWSTR pszMountPoint); static void NotifyReconnectedNetDrive(LPCWSTR pszMountPoint); /////////////////////////////////////////////////////////////////////////////// // Public methods /////////////////////////////////////////////////////////////////////////////// public: HRESULT GetDisplayName(LPTSTR pszName, DWORD cchName); HRESULT GetComment(LPTSTR pszComment, DWORD cchComment); virtual HRESULT GetLabel(LPTSTR pszLabel, DWORD cchLabel) = 0; virtual HRESULT GetLabelNoFancy(LPTSTR pszLabel, DWORD cchLabel) = 0; virtual HRESULT SetLabel(HWND hwnd, LPCTSTR pszLabel) = 0; virtual HRESULT SetDriveLabel(HWND hwnd, LPCTSTR pszLabel) { return SetLabel(hwnd, pszLabel); } virtual HRESULT GetRemotePath(LPWSTR pszPath, DWORD cchPath) = 0; BOOL GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName); virtual void GetTypeString(LPTSTR pszType, DWORD cchType) = 0; DWORD GetAttributes(); DWORD GetClusterSize(); virtual int GetDriveFlags() = 0; int GetVolumeFlags(); virtual UINT GetIcon(LPTSTR pszModule, DWORD cchModule) = 0; virtual HRESULT GetAssocSystemElement(IAssociationElement **ppae) = 0; virtual DWORD GetShellDescriptionID() = 0; virtual HKEY GetRegKey() = 0; BOOL IsStrictRemovable(); BOOL IsFixedDisk(); BOOL IsRemote(); BOOL IsCDROM(); BOOL IsAudioCD(); BOOL IsAudioCDNoData(); BOOL IsDVD(); BOOL IsDVDRAMMedia(); BOOL IsFormattable(); BOOL IsNTFS(); BOOL IsCompressible(); BOOL IsCompressed(); BOOL IsSupportingSparseFile(); BOOL IsContentIndexed(); BOOL IsSlow(); BOOL IsFloppy(); BOOL IsRemovableDevice(); // Don't call this on net drive for nothing virtual BOOL IsMounted() { return TRUE; } virtual BOOL IsFormatted() = 0; virtual BOOL IsAutoRunDrive() { return FALSE; } virtual BOOL IsEjectable() { return FALSE; } virtual BOOL HasMedia() { return TRUE; } void SetAutorunStatus(BYTE* rgb, DWORD cbSize); // Returns E_FAIL if not applicable // Returns S_FALSE if cannot determine capabilities for drive virtual HRESULT GetCDInfo(DWORD* pdwDriveCapabilities, DWORD* pdwMediaCapabilities) { return E_FAIL; } // remote only virtual BOOL IsUnavailableNetDrive() { return FALSE; } virtual BOOL IsDisconnectedNetDrive() { return FALSE; } // local only virtual HRESULT Eject(HWND hwnd) { return E_FAIL; } virtual HRESULT ChangeNotifyRegisterAlias(void) = 0; virtual void StoreIconForUpdateImage(int iImage) { } static void HandleWMDeviceChange(ULONG_PTR code, DEV_BROADCAST_HDR *pbh); static void GetTypeString(int iDrive, LPTSTR pszType, DWORD cchType); static void DoAutorunPrompt(WPARAM iDrive); static void DoAutorun(LPCWSTR pszDrive, DWORD dwAutorunFlags); static void _DoAutorunHelper(CAutoPlayParams *papp); static HRESULT _Sniff(LPCWSTR pszDeviceIDVolume, LPCWSTR pszDrive, DWORD *pdwFound); static void WantAutorunUI(LPCWSTR pszDrive); static BOOL _AppAllowsAutoRun(HWND hwndApp, CMountPoint* pmtpt); static HRESULT _QueryRunningObject(CMountPoint* pmtpt, DWORD dwAutorunContentType, BOOL* pfAllow); AUTORUN_CONDITION_FCT(_acShiftKeyDown); AUTORUN_CONDITION_FCT(_acCurrentDesktopIsActiveConsole); AUTORUN_CONDITION_FCT(_acDriveIsMountedOnDriveLetter); AUTORUN_CONDITION_FCT(_acDriveIsRestricted); AUTORUN_CONDITION_FCT(_acHasAutorunCommand); AUTORUN_CONDITION_FCT(_acHasUseAutoPLAY); AUTORUN_CONDITION_FCT(_acForegroundAppAllowsAutorun); AUTORUN_CONDITION_FCT(_acQueryCancelAutoplayAllowsAutorun); AUTORUN_CONDITION_FCT(_acUserHasSelectedApplication); AUTORUN_CONDITION_FCT(_acShellIsForegroundApp); AUTORUN_CONDITION_FCT(_acOSIsServer); AUTORUN_CONDITION_FCT(_acIsDockedLaptop); AUTORUN_CONDITION_FCT(_acDriveIsFormatted); AUTORUN_CONDITION_FCT(_acShellExecuteDriveAutorunINF); AUTORUN_CONDITION_FCT(_acAlwaysReturnsTRUE); AUTORUN_CONDITION_FCT(_acPromptUser); AUTORUN_CONDITION_FCT(_acIsMixedContent); AUTORUN_CONDITION_FCT(_acExecuteAutoplayDefault); AUTORUN_CONDITION_FCT(_acWasjustDocked); AUTORUN_CONDITION_FCT(_acShouldSniff); AUTORUN_CONDITION_FCT(_acAddAutoplayVerb); AUTORUN_CONDITION_FCT(_acDirectXAppRunningFullScreen); static BOOL _ExecuteHelper(LPCWSTR pszHandler, LPCWSTR pszContentTypeHandler, CAutoPlayParams *papp, DWORD dwMtPtContentType); static UINT GetSuperPlainDriveIcon(LPCWSTR pszDrive, UINT uDriveType); static BOOL _CanRegister(); // returns DT_* defined above virtual DWORD _GetMTPTDriveType() = 0; // returns CT_* defined above virtual DWORD _GetMTPTContentType() = 0; /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// protected: virtual BOOL _IsFloppy() { return FALSE; } virtual BOOL _IsFloppy35() { return FALSE; } virtual BOOL _IsFloppy525() { return FALSE; } virtual BOOL _IsCDROM() { return FALSE; } virtual BOOL _IsStrictRemovable() { return FALSE; } virtual BOOL _IsAutorun() = 0; virtual BOOL _IsFormattable() { return FALSE; } virtual BOOL _IsAudioCD() { return FALSE; } virtual BOOL _IsAudioCDNoData() { return FALSE; } virtual BOOL _IsDVD() { return FALSE; } virtual BOOL _IsFixedDisk() { return FALSE; } virtual BOOL _IsDVDRAMMedia() { return FALSE; } virtual BOOL _IsRemovableDevice() { return FALSE; } BOOL _IsAutoRunDrive(); BOOL _ProcessAutoRunFile(); HRESULT _CopyInvokeVerbKey(LPCWSTR pszProgID, LPCWSTR pszVerb); HRESULT _AddAutoplayVerb(); static BOOL _IsDriveLetter(LPCWSTR pszDrive); // Helpers void _QualifyCommandToDrive(LPTSTR pszCommand, DWORD cchCommand); virtual BOOL _NeedToRefresh() { return FALSE; } public: // Should be accessed only by CMtPt_... fcts BOOL _IsLFN(); BOOL _IsSecure(); virtual BOOL _IsSlow() { return FALSE; } private: /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// protected: virtual BOOL _IsAudioDisc() { return FALSE; } virtual BOOL _IsRemote() { return FALSE; } BOOL _GetLegacyRegLabel(LPTSTR pszLabel, DWORD cchLabel); void _UpdateCommentFromDesktopINI(); void _InitLegacyRegIconAndLabel(BOOL fUseAutorunIcon, BOOL fUseAutorunLabel); virtual BOOL _IsMountedOnDriveLetter() = 0; /////////////////////////////////////////////////////////////////////////////// // Management (mtptmgmt.cpp) /////////////////////////////////////////////////////////////////////////////// public: // Drive Letter (DL) static CMountPoint* _GetMountPointDL(int iDrive, BOOL fCreateNew); // Mounted On Folder (MOF) static CMtPtLocal* _GetStoredMtPtMOF(LPTSTR pszPathWithBackslash); static BOOL _StoreMtPtMOF(CMtPtLocal* pMtPt); static CMtPtLocal* _GetStoredMtPtMOFFromHDPA(LPTSTR pszPathWithBackslash); protected: // Helpers static BOOL _IsNetDriveLazyLoadNetDLLs(int iDrive); static HRESULT _InitLocalDrives(); static HRESULT _InitNetDrives(); static HRESULT _InitNetDrivesHelper(DWORD dwScope); static HRESULT _ReInitNetDrives(); static HRESULT _EnumVolumes(IHardwareDevices* pihwdevs); static HRESULT _EnumMountPoints(IHardwareDevices* pihwdevs); static HRESULT _DeleteVolumeInfo(); static HRESULT _DeleteLocalMtPts(); static HRESULT _GetMountPointsForVolume(LPCWSTR pszDeviceIDVolume, HDPA hdpaMtPts); static HRESULT _MediaArrivalRemovalHelper(LPCWSTR pszDeviceIDVolume, BOOL fArrived); static HRESULT _RemoveLocalMountPoint(LPCWSTR pszMountPoint); static HRESULT _RemoveNetMountPoint(LPCWSTR pszMountPoint); static BOOL _LocalDriveIsCoveredByNetDrive(LPCWSTR pszDriveLetter); static BOOL _CheckLocalMtPtsMOF(LPCWSTR pszMountPoint); public: static BOOL _StripToClosestMountPoint(LPCTSTR pszSource, LPTSTR pszDest, DWORD cchDest); public: static HRESULT _InitLocalDriveHelper(); /////////////////////////////////////////////////////////////////////////////// // Miscellaneous helpers /////////////////////////////////////////////////////////////////////////////// protected: virtual LPCTSTR _GetNameForFctCall(); virtual BOOL _GetFileAttributes(DWORD* pdwAttrib) = 0; virtual BOOL _GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName) = 0; virtual BOOL _GetGVILabelOrMixedCaseFromReg(LPTSTR pszLabel, DWORD cchLabel) = 0; virtual BOOL _GetGVILabel(LPTSTR pszLabel, DWORD cchLabel) = 0; virtual BOOL _GetSerialNumber(DWORD* pdwSerialNumber) = 0; virtual BOOL _GetFileSystemFlags(DWORD* pdwFlags) = 0; virtual int _GetGVIDriveFlags() = 0; virtual int _GetDriveType() = 0; virtual DWORD _GetAutorunContentType() = 0; TCHAR _GetNameFirstCharUCase(); LPTSTR _GetNameFirstXChar(LPTSTR pszBuffer, int c); LPCTSTR _GetName(); LPCTSTR _GetNameDebug(); BOOL _GetLabelFromReg(LPWSTR psz, DWORD cch); BOOL _GetLabelFromDesktopINI(LPWSTR psz, DWORD cch); CMountPoint(); public: ULONG AddRef(); ULONG Release(); /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// static HRESULT _VolumeAddedOrUpdated(BOOL fAdded, VOLUMEINFO2* pvolinfo2); static HRESULT _VolumeRemoved(LPCWSTR pszDeviceIDVolume); static HRESULT _VolumeMountingEvent(LPCWSTR pszDeviceIDVolume, DWORD dwEvent); static HRESULT _MountPointAdded(LPCWSTR pszMountPoint, LPCWSTR pszDeviceIDVolume); static HRESULT _MountPointRemoved(LPCWSTR pszMountPoint); static HRESULT RegisterForHardwareNotifications(); static HRESULT HandleDeviceQueryRemove(); static DWORD WINAPI _RegisterThreadProc(void* pv); static void CALLBACK _EventAPCProc(ULONG_PTR ulpParam); static DWORD CALLBACK _EventProc(void* pv); /////////////////////////////////////////////////////////////////////////////// // Data /////////////////////////////////////////////////////////////////////////////// protected: // Only mtpt, volume, drive real data shared by derived objs WCHAR _szName[MAX_PATH]; LPWSTR _pszLegacyRegIcon; LPWSTR _pszLegacyRegLabel; BOOL _fAutorunFileProcessed; // Static, non-mtpt related stuff LONG _cRef; static CCriticalSection _csLocalMtPtHDPA; static CCriticalSection _csDL; static HDPA _hdpaMountPoints; static HDPA _hdpaVolumes; static HDPA _hdpaShares; static DWORD _dwAdviseToken; // optimization we have an array for the volumes mounted on drive letters static CMtPtLocal* _rgMtPtDriveLetterLocal[]; static CMtPtRemote* _rgMtPtDriveLetterNet[]; static BOOL _fNetDrivesInited; static BOOL _fLocalDrivesInited; static BOOL _fNoVolLocalDrivesInited; static DWORD _dwTickCountTriedAndFailed; // Constructor/destructor of _hwdevcb will NOT get called static BOOL _fShuttingDown; // Watch out! No constructor nor destructor called on the next members static CRegSupport _rsMtPtsLocalDL; static CRegSupport _rsMtPtsLocalMOF; static CRegSupport _rsMtPtsRemote; static DWORD _dwRemoteDriveAutorun; static HANDLE _hThreadSCN; static DWORD _dwRememberedNetDrivesMask; public: static BOOL _fCanRegisterWithShellService; }; STDAPI MountPoint_RegisterChangeNotifyAlias(int iDrive); BOOL _Shell32LoadedInDesktop(); struct TWODWORDS { DWORD dwLeft; DWORD dwRight; }; DWORD _DoDWORDMapping(DWORD dwLeft, const TWODWORDS* rgtwodword, DWORD ctwodword, BOOL fORed); class PNPNOTIFENTRY : public CRefCounted { public: HDEVNOTIFY hdevnotify; BOOL fStopSniffing; HANDLE hThread; }; // everything is only the things we care about #define DRIVEHAS_EVERYTHING (CT_AUTOPLAYMUSIC | CT_AUTOPLAYPIX | CT_AUTOPLAYMOVIE) class CSniffDrive : public INamespaceWalkCB { public: CSniffDrive(); ~CSniffDrive(); // IUnknown methods STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef() { // stack created return 3; } STDMETHODIMP_(ULONG) Release() { // stack created return 2; } // INamespaceWalkCB STDMETHODIMP FoundItem(IShellFolder *psf, LPCITEMIDLIST pidl); STDMETHODIMP EnterFolder(IShellFolder *psf, LPCITEMIDLIST pidl); STDMETHODIMP LeaveFolder(IShellFolder *psf, LPCITEMIDLIST pidl); STDMETHODIMP InitializeProgressDialog(LPWSTR *ppszTitle, LPWSTR *ppszCancel); DWORD Found() {return _dwFound;} // CSniffDrive static HRESULT Init(HANDLE hThreadSCN); static HRESULT InitNotifyWindow(HWND hwnd); static HRESULT CleanUp(); static HRESULT HandleNotif(HDEVNOTIFY hdevnotify); static void CALLBACK _RegisterForNotifsHelper(ULONG_PTR ul); static void CALLBACK _UnregisterForNotifsHelper(ULONG_PTR ul); HRESULT RegisterForNotifs(LPCWSTR pszDeviceIDVolume); HRESULT UnregisterForNotifs(); private: // methods BOOL _FoundEverything(); private: // members DWORD _dwFound; PNPNOTIFENTRY* _pne; public: static HANDLE _hThreadSCN; static CDPA _dpaNotifs; static HWND _hwndNotify; }; #endif //_MTPT_H