//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: folder.h // //-------------------------------------------------------------------------- #ifndef _INC_CSCUI_FOLDER_H #define _INC_CSCUI_FOLDER_H #include // IShellDetails #include // IShellFolderViewCb #include // QITAB, QISearch #include // ILFree(), etc #include #include #include "util.h" STDAPI_(void) DllAddRef(void); STDAPI_(void) DllRelease(void); #define OLID_SIG 0x4444 #pragma pack(1) // PIDL format for CSC cache non leaf items... typedef struct { USHORT cb; // Total size of IDList. USHORT uSig; // IDList signature. DWORD cbFixed; // Fixed size of IDList. DWORD dwFileAttributes; // Win32 file attributes. DWORD dwStatus; // CSC file/folder status flags. DWORD dwServerStatus; // CSC server status flags. DWORD dwPinCount; // CSC pin count. DWORD dwHintFlags; // CSC "hint" flags. DWORD dwFileSizeHigh; // Win32 file size. DWORD dwFileSizeLow; FILETIME ft; // Last write time (from CSC). DWORD cchNameOfs; // Offset of name part from szPath[0]. TCHAR szPath[0]; // pathname (variable length). } OLID; typedef UNALIGNED OLID *LPOLID; typedef const UNALIGNED OLID *LPCOLID; #pragma pack() class COfflineFilesEnum; // forward class COfflineFilesViewCallback; class COfflineDetails; class COfflineItemsData; class COfflineItems; class CFolderCache; //---------------------------------------------------------------------------- // CFileTypeCache //---------------------------------------------------------------------------- class CFileTypeCache { public: explicit CFileTypeCache(int cBuckets); ~CFileTypeCache(void); HRESULT GetTypeName( LPCTSTR pszPath, DWORD dwFileAttributes, LPTSTR pszDest, int cchDest); private: class CEntry { public: CEntry(LPCTSTR pszExt, LPCTSTR pszTypeName); ~CEntry(void); void SetNext(CEntry *pNext) { m_pNext = pNext; } CEntry *Next(void) const { return m_pNext; } int CompareExt(LPCTSTR pszExt) const { return lstrcmpi(m_pszExt, pszExt); } LPCTSTR TypeName(void) const { return m_pszTypeName; } bool IsValid(void) const { return (NULL != m_pszExt) && (NULL != m_pszTypeName); } private: LPTSTR m_pszExt; LPTSTR m_pszTypeName; CEntry *m_pNext; // Next in hash bucket. // // Prevent copy. // CEntry(const CEntry& rhs); CEntry& operator = (const CEntry& rhs); }; int m_cBuckets; CEntry **m_prgBuckets; CRITICAL_SECTION m_cs; int Hash(LPCTSTR pszExt); CEntry *Lookup(LPCTSTR pszExt); HRESULT Add(LPCTSTR pszExt, LPCTSTR pszTypeName); void Lock(void) { EnterCriticalSection(&m_cs); } void Unlock(void) { LeaveCriticalSection(&m_cs); } // // Prevent copy. // CFileTypeCache(const CFileTypeCache& rhs); CFileTypeCache& operator = (const CFileTypeCache& rhs); }; STDAPI COfflineFilesFolder_CreateInstance(REFIID riid, void **ppv); class COfflineFilesFolder : public IPersistFolder2, IShellFolder, IShellIcon, IShellIconOverlay { public: static HRESULT WINAPI CreateInstance(REFIID riid, void **ppv); static INT Open(void); static HRESULT CreateIDList(LPITEMIDLIST *ppidl); static HRESULT IdentifyIDList(LPCITEMIDLIST pidl); static HRESULT CreateLinkOnDesktop(HWND hwndParent); static HRESULT IsLinkOnDesktop(HWND hwndParent, LPTSTR pszPathOut, UINT cchPathOut); static HRESULT GetFolder(IShellFolder **ppsf); // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IShellFolder STDMETHOD(ParseDisplayName)(HWND hwnd, LPBC pbc, LPOLESTR pDisplayName, ULONG *pchEaten, LPITEMIDLIST *ppidl, ULONG *pdwAttributes); STDMETHOD(EnumObjects)(HWND hwnd, DWORD grfFlags, IEnumIDList **ppEnumIDList); STDMETHOD(BindToObject)(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppvOut); STDMETHOD(BindToStorage)(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void **ppvObj); STDMETHOD(CompareIDs)(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); STDMETHOD(CreateViewObject)(HWND hwnd, REFIID riid, void **ppvOut); STDMETHOD(GetAttributesOf)(UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfInOut); STDMETHOD(GetUIObjectOf)(HWND hwnd, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, void **ppvOut); STDMETHOD(GetDisplayNameOf)(LPCITEMIDLIST pidl, DWORD uFlags, STRRET *pName); STDMETHOD(SetNameOf)(HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR pszName, DWORD uFlags, LPITEMIDLIST* ppidlOut); // IPersist STDMETHOD(GetClassID)(LPCLSID pClassID); // IPersistFolder STDMETHOD(Initialize)(LPCITEMIDLIST pidl); // IPersistFolder2 STDMETHOD(GetCurFolder)(LPITEMIDLIST *pidl); // IShellIcon STDMETHOD(GetIconOf)(LPCITEMIDLIST pidl, UINT gil, int *pnIcon); // IShellIconOverlay STDMETHOD(GetOverlayIndex)(LPCITEMIDLIST pidl, int * pIndex); STDMETHOD(GetOverlayIconIndex)(LPCITEMIDLIST pidl, int * pIconIndex); static bool ValidateIDList(LPCITEMIDLIST pidl); private: friend COfflineFilesEnum; friend COfflineFilesViewCallback; friend COfflineDetails; friend COfflineItemsData; friend COfflineItems; friend CFolderCache; friend HRESULT COfflineFilesFolder_CreateInstance(REFIID riid, void **ppv); COfflineFilesFolder(); ~COfflineFilesFolder(); void _GetSyncStatusString(LPCOLID polid, LPTSTR pszStatus, UINT cchStatus); void _GetPinStatusString(LPCOLID polid, LPTSTR pszStatus, UINT cchStatus); void _GetServerStatusString(LPCOLID polid, LPTSTR pszStatus, UINT cchStatus); void _GetTypeString(LPCOLID polid, LPTSTR pszType, UINT cchType); void _GetAccessString(LPCOLID polid, LPTSTR pszAccess, UINT cchAccess); HRESULT GetAssociations(LPCOLID polid, void **ppvQueryAssociations); BOOL GetClassKey(LPCOLID polid, HKEY *phkeyProgID, HKEY *phkeyBaseID); static LPCOLID _Validate(LPCITEMIDLIST pidl); static HRESULT IsOurLink(LPCTSTR pszFile); static HRESULT _BindToObject(IShellFolder *psf, REFIID riid, LPCITEMIDLIST pidl, void **ppvOut); static HRESULT ContextMenuCB(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam); static HRESULT OLID_GetFullPath(LPCOLID polid, LPTSTR pszPath, UINT cchPath); static LPCTSTR OLID_GetFileName(LPCOLID polid, LPTSTR pszName, UINT cchName); static HRESULT OLID_CreateFromUNCPath(LPCTSTR pszPath, const WIN32_FIND_DATA *pfd, DWORD dwStatus, DWORD dwPinCount, DWORD dwHintFlags, DWORD dwServerStatus, LPOLID *ppolid); static void OLID_GetWin32FindData(LPCOLID polid, WIN32_FIND_DATA *pfd); static HRESULT OLID_Bind(LPCOLID polid, REFIID riid, void **ppv, LPITEMIDLIST *ppidlFull, LPCITEMIDLIST *ppidlItem); static HRESULT OLID_CreateSimpleIDList(LPCOLID polid, LPITEMIDLIST *ppidlOut); LONG _cRef; LPITEMIDLIST _pidl; IShellFolderViewCB *_psfvcb; CFileTypeCache m_FileTypeCache; }; // // This class represents a simple cache of CSC status bits for each // server in the CSC cache. The reason we need this is sort of bogus // but we have no control over it. When enumerating shares in the CSC // database, shares on the same server might not return the same online-offline // status depending on if the share really has a connection or not. The // problem is that in the network redirector an entire server is either // online or offline. We display "server" status in the UI so we need to // merge the status information from each share in the database so that // we have status information for each server. Clear as mud? This cache // implements that merging of information so that all a client (i.e. the // enum code) has to do is call GetServerStatus() with a given UNC path and // they'll get the status we should be reporting for that path's server. // class CServerStatusCache { public: CServerStatusCache(void) : m_hdpa(NULL) { } ~CServerStatusCache(void); // // This is the only public API for this class. When it's // called for the first time, the cache is populated. Therefore, // you can create a cache object but you're not charged much // until you need to use it. // DWORD GetServerStatus(LPCTSTR pszUNC); private: // // A single entry in the cache. // class CEntry { public: CEntry(LPCTSTR pszServer, DWORD dwStatus); ~CEntry(void); void AddStatus(DWORD dwStatus) { m_dwStatus |= dwStatus; } DWORD GetStatus(void) const { return m_dwStatus; } LPCTSTR GetServer(void) const { return m_pszServer; } bool IsValid(void) const { return NULL != m_pszServer; } private: LPTSTR m_pszServer; DWORD m_dwStatus; // // Prevent copy. // CEntry(const CEntry& rhs); CEntry& operator = (const CEntry& rhs); }; HDPA m_hdpa; // The DPA for holding entries. bool AddShareStatus(LPCTSTR pszShare, DWORD dwShareStatus); CEntry *FindEntry(LPCTSTR pszShare); LPTSTR ServerFromUNC(LPCTSTR pszShare, LPTSTR pszServer, UINT cchServer); // // Prevent copy. // CServerStatusCache(const CServerStatusCache& rhs); CServerStatusCache& operator = (const CServerStatusCache& rhs); }; class COfflineFilesEnum : public IEnumIDList { public: COfflineFilesEnum(DWORD grfFlags, COfflineFilesFolder *pfolder); bool IsValid(void) const; // IUnknown Methods STDMETHODIMP QueryInterface(REFIID,void **); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IEnumIDList Methods STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched); STDMETHODIMP Skip(ULONG celt); STDMETHODIMP Reset(); STDMETHODIMP Clone(IEnumIDList **ppenum); protected: // // Element of the folder path stack. (_hdsaFolderPaths). // Includes length to reduce length calculations. // struct FolderPathInfo { DWORD cchPath; // Chars in path including nul term. LPTSTR pszPath; // Folder path string. }; ~COfflineFilesEnum(); LONG _cRef; // ref count COfflineFilesFolder *_pfolder; // this is what we enumerate UINT _grfFlags; // enumeration flags CCscFindHandle _hEnumShares; CCscFindHandle _hEnum; HDSA _hdsaFolderPathInfo; // A stack of FolderPathInfo. LPTSTR _pszPath; // Dynamic scratch buffer for paths. INT _cchPathBuf; // Current length of _pszPath buffer. DWORD _dwServerStatus; // dwStatus flags for current server. CServerStatusCache _ServerStatusCache; bool _bShowSuperHiddenFiles; bool _bShowHiddenFiles; bool _bUserIsAdmin; private: bool PopFolderPathInfo(FolderPathInfo *pfpi); bool PushFolderPathInfo(const FolderPathInfo& fpi) { return (-1 != DSA_AppendItem(_hdsaFolderPathInfo, (LPVOID)&fpi)); } bool SaveFolderPath(LPCTSTR pszRoot, LPCTSTR pszFolder); bool Exclude(const CscFindData& cscfd); bool OkToEnumFolder(const CscFindData& cscfd); bool UserHasAccess(const CscFindData& cscfd); HRESULT GrowPathBuffer(INT cchRequired, INT cchExtra); }; //---------------------------------------------------------------------------- // Delete handler // // This class packages up the operation of deleting a selection of files // from the folder view. These methods could easily be made members of // the COfflineFilesFolder class. I think the separation is reasonable. //---------------------------------------------------------------------------- class CFolderDeleteHandler { public: CFolderDeleteHandler(HWND hwndParent, IDataObject *pdtobj, IShellFolderViewCB *psfvcb); ~CFolderDeleteHandler(void); HRESULT DeleteFiles(void); private: HWND m_hwndParent;// Parent for any UI. IDataObject *m_pdtobj; // Data object containing IDArray. IShellFolderViewCB *m_psfvcb; // View callback for view notifications. static INT_PTR ConfirmDeleteFilesDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static INT_PTR ConfirmDeleteModifiedFileDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); bool ConfirmDeleteFiles(HWND hwndParent); bool ConfirmDeleteModifiedFile(HWND hwndParent, LPCTSTR pszFile, bool *pbNoToAll, bool *pbCancel); bool FileModifiedOffline(LPCTSTR pszFile); bool OthersHaveAccess(LPCTSTR pszFile); }; HRESULT CreateOfflineFilesContextMenu( IDataObject *pdtobj, REFIID riid, void **ppv); #endif // _INC_CSCUI_FOLDER_H