windows-nt/Source/XPSP1/NT/shell/ext/cscui/folder.h
2020-09-26 16:20:57 +08:00

409 lines
14 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: folder.h
//
//--------------------------------------------------------------------------
#ifndef _INC_CSCUI_FOLDER_H
#define _INC_CSCUI_FOLDER_H
#include <shellp.h> // IShellDetails
#include <shlguidp.h> // IShellFolderViewCb
#include <shlwapip.h> // QITAB, QISearch
#include <shsemip.h> // ILFree(), etc
#include <sfview.h>
#include <comctrlp.h>
#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]; // path<nul>name<nul> (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 LPCTSTR OLID_GetPath(LPCOLID polid, LPTSTR pszPath, UINT cchPath);
static LPCTSTR 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 void OLID_CombinePathAndName(LPOLID polid);
static void OLID_SplitPathAndName(LPOLID polid);
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