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

523 lines
17 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: util.h
//
//--------------------------------------------------------------------------
#ifndef _UTIL_H_
#define _UTIL_H_
#ifndef _INC_CSCVIEW_CONFIG_H
# include "config.h"
#endif
#include "debug.h"
HRESULT GetRemotePath(LPCTSTR szInName, LPTSTR *pszOutName);
LPTSTR ULongToString(ULONG i, LPTSTR psz, ULONG cchMax);
VOID LocalFreeString(LPTSTR *ppsz);
BOOL LocalAllocString(LPTSTR *ppszDest, LPCTSTR pszSrc);
UINT SizeofStringResource(HINSTANCE hInstance, UINT idStr);
int LoadStringAlloc(LPTSTR *ppszResult, HINSTANCE hInstance, UINT idStr);
void ShellChangeNotify(LPCTSTR pszPath, WIN32_FIND_DATA *pfd, BOOL bFlush, LONG nEvent = 0);
inline void ShellChangeNotify(LPCTSTR pszPath, BOOL bFlush = FALSE, LONG nEvent = 0) {ShellChangeNotify(pszPath, NULL, bFlush, nEvent);}
HRESULT GetLinkTarget(LPCTSTR pszShortcut, LPTSTR *ppszTarget, DWORD *pdwAttr = NULL);
void CenterWindow(HWND hwnd, HWND hwndParent);
DWORD CSCUIRebootSystem(void);
HRESULT SHSimpleIDListFromFindData(LPCTSTR pszPath, const WIN32_FIND_DATA *pfd, LPITEMIDLIST *ppidl);
DWORD CscDelete(LPCTSTR pszPath);
HRESULT IsOpenConnectionShare(LPCTSTR pszShare);
HRESULT IsOpenConnectionPathUNC(LPCTSTR pszPathUNC);
BOOL IsCSCEnabled(void);
BOOL IsCacheEncrypted(BOOL *pbPartial);
BOOL IsSyncInProgress(void);
BOOL IsPurgeInProgress(void);
BOOL IsEncryptionInProgress(void);
HANDLE RequestPermissionToEncryptCache(void);
bool CscVolumeSupportsEncryption(LPCTSTR pszPath = NULL);
BOOL IsWindowsTerminalServer(void);
HRESULT SHCreateFileSysBindCtx(const WIN32_FIND_DATA *pfd, IBindCtx **ppbc);
BOOL DeleteOfflineFilesFolderLink(HWND hwndParent = NULL);
BOOL DeleteOfflineFilesFolderLink_PerfSensitive(HWND hwndParent = NULL);
BOOL ShowHidden(void);
BOOL ShowSuperHidden(void);
BOOL IsSyncMgrInitialized(void);
void SetSyncMgrInitialized(void);
HWND GetProgressDialogWindow(IProgressDialog *ppd);
HRESULT ExpandStringInPlace(LPTSTR psz, DWORD cch);
//
// Info returned through CSCFindFirst[Next]File APIs.
//
struct CscFindData
{
WIN32_FIND_DATA fd;
DWORD dwStatus;
DWORD dwPinCount;
DWORD dwHintFlags;
FILETIME ft;
};
HANDLE CacheFindFirst(LPCTSTR pszPath, PSID psid, WIN32_FIND_DATA *pfd, DWORD *pdwStatus, DWORD *pdwPinCount, DWORD *pdwHintFlags, FILETIME *pft);
inline
HANDLE CacheFindFirst(LPCTSTR pszPath, WIN32_FIND_DATA *pfd, DWORD *pdwStatus, DWORD *pdwPinCount, DWORD *pdwHintFlags, FILETIME *pft)
{ return CacheFindFirst(pszPath, (PSID)NULL, pfd, pdwStatus, pdwPinCount, pdwHintFlags, pft); }
inline
HANDLE CacheFindFirst(LPCTSTR pszPath, CscFindData *p)
{ return CacheFindFirst(pszPath, &p->fd, &p->dwStatus, &p->dwPinCount, &p->dwHintFlags, &p->ft); }
inline
HANDLE CacheFindFirst(LPCTSTR pszPath, PSID psid, CscFindData *p)
{ return CacheFindFirst(pszPath, psid, &p->fd, &p->dwStatus, &p->dwPinCount, &p->dwHintFlags, &p->ft); }
BOOL CacheFindNext(HANDLE hFind, WIN32_FIND_DATA *pfd, DWORD *pdwStatus, DWORD *pdwPinCount, DWORD *pdwHintFlags, FILETIME *pft);
inline
BOOL CacheFindNext(HANDLE hFind, CscFindData *p)
{ return CacheFindNext(hFind, &p->fd, &p->dwStatus, &p->dwPinCount, &p->dwHintFlags, &p->ft); }
inline bool IsHiddenSystem(DWORD dwAttr)
{
return ((dwAttr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM));
}
inline BOOL _PathIsSlow(DWORD dwSpeed) { return (dwSpeed && dwSpeed <= DWORD(CConfig::GetSingleton().SlowLinkSpeed())); }
typedef struct
{
TCHAR szVolume[80]; // Volume where CSC cache is stored.
LONGLONG llBytesOnVolume; // Disk size (bytes)
LONGLONG llBytesTotalInCache; // Size of cache (bytes)
LONGLONG llBytesUsedInCache; // Amount of cache used (bytes)
DWORD dwNumFilesInCache; // Files in cache
DWORD dwNumDirsInCache; // Directories in cache
} CSCSPACEUSAGEINFO;
void GetCscSpaceUsageInfo(CSCSPACEUSAGEINFO *psui);
typedef enum _enum_reason
{
ENUM_REASON_FILE = 0,
ENUM_REASON_FOLDER_BEGIN,
ENUM_REASON_FOLDER_END
} ENUM_REASON;
typedef DWORD (WINAPI *PFN_CSCENUMPROC)(LPCTSTR, ENUM_REASON, DWORD, DWORD, DWORD, PWIN32_FIND_DATA, LPARAM);
DWORD _CSCEnumDatabase(LPCTSTR pszFolder, BOOL bRecurse, PFN_CSCENUMPROC pfnCB, LPARAM lpContext);
typedef DWORD (WINAPI *PFN_WIN32ENUMPROC)(LPCTSTR, ENUM_REASON, PWIN32_FIND_DATA, LPARAM);
DWORD _Win32EnumFolder(LPCTSTR pszFolder, BOOL bRecurse, PFN_WIN32ENUMPROC pfnCB, LPARAM lpContext);
//
// Statistical information about a particular network share in the CSC database.
//
typedef struct _CSCSHARESTATS
{
int cTotal;
int cPinned;
int cModified;
int cSparse;
int cDirs;
int cAccessUser;
int cAccessGuest;
int cAccessOther;
bool bOffline;
bool bOpenFiles;
} CSCSHARESTATS, *PCSCSHARESTATS;
typedef struct
{
int cShares;
int cTotal;
int cPinned;
int cModified;
int cSparse;
int cDirs;
int cAccessUser;
int cAccessGuest;
int cAccessOther;
int cSharesOffline;
int cSharesWithOpenFiles;
} CSCCACHESTATS, *PCSCCACHESTATS;
//
// These flags indicate if the enumeration should stop when one or more associated
// value's exceed 1. This is useful when you're interested in 0 vs. !0 as opposed
// to an actual count.
// If multiple flags are set, the statistics enumeration continues until the
// values corresponding to ALL set unity flags are non-zero.
//
enum SHARE_STATS_UNITY_FLAGS { SSUF_NONE = 0x00000000, // This is the default.
SSUF_TOTAL = 0x00000001,
SSUF_PINNED = 0x00000002,
SSUF_MODIFIED = 0x00000004,
SSUF_SPARSE = 0x00000008,
SSUF_DIRS = 0x00000010,
SSUF_ACCUSER = 0x00000020,
SSUF_ACCGUEST = 0x00000040,
SSUF_ACCOTHER = 0x00000080,
SSUF_ACCAND = 0x00000100, // Must match all set access mask flags.
SSUF_ACCOR = 0x00000200, // Match at least one access mask flag.
SSUF_ALL = 0x000000FF };
//
// These flags indicate if any cache items should be excluded from the enumeration.
// By default, the value is 0 (everything included). For perf reasons, we use the
// same flags defined in cscapi.h.
//
enum SHARE_STATS_EXCLUDE_FLAGS {
SSEF_NONE = 0x00000000, // Default. Include everything.
SSEF_LOCAL_MOD_DATA = FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED,
SSEF_LOCAL_MOD_ATTRIB = FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED,
SSEF_LOCAL_MOD_TIME = FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED,
SSEF_LOCAL_DELETED = FLAG_CSC_COPY_STATUS_LOCALLY_DELETED,
SSEF_LOCAL_CREATED = FLAG_CSC_COPY_STATUS_LOCALLY_CREATED,
SSEF_STALE = FLAG_CSC_COPY_STATUS_STALE,
SSEF_SPARSE = FLAG_CSC_COPY_STATUS_SPARSE,
SSEF_ORPHAN = FLAG_CSC_COPY_STATUS_ORPHAN,
SSEF_SUSPECT = FLAG_CSC_COPY_STATUS_SUSPECT,
SSEF_CSCMASK = FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED |
FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED |
FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED |
FLAG_CSC_COPY_STATUS_LOCALLY_DELETED |
FLAG_CSC_COPY_STATUS_LOCALLY_CREATED |
FLAG_CSC_COPY_STATUS_STALE |
FLAG_CSC_COPY_STATUS_SPARSE |
FLAG_CSC_COPY_STATUS_ORPHAN |
FLAG_CSC_COPY_STATUS_SUSPECT,
SSEF_DIRECTORY = 0x01000000,
SSEF_FILE = 0x02000000,
SSEF_NOACCUSER = 0x04000000, // Exclude if no USER access.
SSEF_NOACCGUEST = 0x08000000, // Exclude if no GUEST access.
SSEF_NOACCOTHER = 0x10000000, // Exclude if no OTHER access.
SSEF_NOACCAND = 0x20000000 // Treat previous 3 flags as single mask.
};
typedef struct
{
DWORD dwExcludeFlags; // [in] SSEF_XXXXX flags.
DWORD dwUnityFlags; // [in] SSUF_XXXXX flags.
bool bAccessInfo; // [in] Implied 'T' if unity or exclude access bits are set.
bool bEnumAborted; // [out]
} CSCGETSTATSINFO, *PCSCGETSTATSINFO;
BOOL _GetShareStatistics(LPCTSTR pszShare, PCSCGETSTATSINFO pi, PCSCSHARESTATS pss);
BOOL _GetCacheStatistics(PCSCGETSTATSINFO pi, PCSCCACHESTATS pcs);
BOOL _GetShareStatisticsForUser(LPCTSTR pszShare, PCSCGETSTATSINFO pi, PCSCSHARESTATS pss);
BOOL _GetCacheStatisticsForUser(PCSCGETSTATSINFO pi, PCSCCACHESTATS pcs);
// Higher level wrapper for IDA stuff
class CIDArray
{
private:
STGMEDIUM m_Medium;
LPIDA m_pIDA;
IShellFolder *m_psf;
public:
CIDArray() : m_pIDA(NULL), m_psf(NULL)
{
ZeroMemory(&m_Medium, sizeof(m_Medium));
}
~CIDArray();
HRESULT Initialize(IDataObject *pdobj);
HRESULT GetFolderPath(LPTSTR pszPath, UINT cch);
HRESULT GetItemPath(UINT iItem, LPTSTR pszPath, UINT cch, DWORD *pdwAttribs);
UINT Count() { return m_pIDA ? m_pIDA->cidl : 0; }
};
//
// Trivial class to ensure cleanup of FindFirst/FindNext handles.
// Perf should be as close as possible to a simple handle so most
// operations are defined inline.
// Implementation is in enum.cpp
//
class CCscFindHandle
{
public:
CCscFindHandle(HANDLE handle = INVALID_HANDLE_VALUE)
: m_handle(handle), m_bOwns(INVALID_HANDLE_VALUE != handle) { }
CCscFindHandle(const CCscFindHandle& rhs)
: m_handle(INVALID_HANDLE_VALUE), m_bOwns(false)
{ *this = rhs; }
~CCscFindHandle(void)
{ Close(); }
void Close(void);
HANDLE Detach(void) const
{ m_bOwns = false; return m_handle; }
void Attach(HANDLE handle)
{ Close(); m_handle = handle; m_bOwns = true; }
operator HANDLE() const
{ return m_handle; }
bool IsValid(void) const
{ return INVALID_HANDLE_VALUE != m_handle; }
CCscFindHandle& operator = (HANDLE handle)
{ Attach(handle); return *this; }
CCscFindHandle& operator = (const CCscFindHandle& rhs);
private:
mutable HANDLE m_handle;
mutable bool m_bOwns;
};
class CMutexAutoRelease
{
public:
explicit CMutexAutoRelease(HANDLE hmutex)
: m_hmutex(hmutex) { }
~CMutexAutoRelease(void)
{
if (m_hmutex)
{
ReleaseMutex(m_hmutex);
CloseHandle(m_hmutex);
}
}
private:
HANDLE m_hmutex;
CMutexAutoRelease(const CMutexAutoRelease& rhs);
CMutexAutoRelease& operator = (const CMutexAutoRelease& rhs);
};
//
// Ensures CoInitialize/CoUninitialize is exception-safe.
//
class CCoInit
{
public:
CCoInit(void)
: m_hr(CoInitialize(NULL)) { }
~CCoInit(void)
{ if (SUCCEEDED(m_hr)) CoUninitialize(); }
HRESULT Result(void) const
{ return m_hr; }
private:
HRESULT m_hr;
};
// String formatting functions - *ppszResult must be LocalFree'd
DWORD FormatStringID(LPTSTR *ppszResult, HINSTANCE hInstance, UINT idStr, ...);
DWORD FormatString(LPTSTR *ppszResult, LPCTSTR pszFormat, ...);
DWORD FormatSystemError(LPTSTR *ppszResult, DWORD dwSysError);
DWORD vFormatStringID(LPTSTR *ppszResult, HINSTANCE hInstance, UINT idStr, va_list *pargs);
DWORD vFormatString(LPTSTR *ppszResult, LPCTSTR pszFormat, va_list *pargs);
void EnableDlgItems(HWND hwndDlg, const UINT* pCtlIds, int cCtls, bool bEnable);
void ShowDlgItems(HWND hwndDlg, const UINT* pCtlIds, int cCtls, bool bShow);
//
// We commonly use groups of CSC status flags together.
// Define them here so we're consistent throughout the project.
//
#define FLAG_CSCUI_COPY_STATUS_LOCALLY_DIRTY (FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED | \
FLAG_CSC_COPY_STATUS_LOCALLY_DELETED | \
FLAG_CSC_COPY_STATUS_LOCALLY_CREATED)
#define FLAG_CSCUI_COPY_STATUS_ALL_DIRTY (FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED | \
FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED | \
FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED | \
FLAG_CSC_COPY_STATUS_LOCALLY_DELETED | \
FLAG_CSC_COPY_STATUS_LOCALLY_CREATED)
//
// Some helper inlines for querying cache item access information.
//
inline bool CscCheckAccess(DWORD dwShareStatus, DWORD dwShift, DWORD dwAccessType)
{
return 0 != ((dwShareStatus >> dwShift) & dwAccessType);
}
inline bool CscAccessUserRead(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_USER_ACCESS_SHIFT_COUNT, FLAG_CSC_READ_ACCESS);
}
inline bool CscAccessUserWrite(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_USER_ACCESS_SHIFT_COUNT, FLAG_CSC_WRITE_ACCESS);
}
inline bool CscAccessUser(DWORD dwShareStatus)
{
return 0 != (dwShareStatus & FLAG_CSC_USER_ACCESS_MASK);
}
inline bool CscAccessGuestRead(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_GUEST_ACCESS_SHIFT_COUNT, FLAG_CSC_READ_ACCESS);
}
inline bool CscAccessGuestWrite(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_GUEST_ACCESS_SHIFT_COUNT, FLAG_CSC_WRITE_ACCESS);
}
inline bool CscAccessGuest(DWORD dwShareStatus)
{
return 0 != (dwShareStatus & FLAG_CSC_GUEST_ACCESS_MASK);
}
inline bool CscAccessOtherRead(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_OTHER_ACCESS_SHIFT_COUNT, FLAG_CSC_READ_ACCESS);
}
inline bool CscAccessOtherWrite(DWORD dwShareStatus)
{
return CscCheckAccess(dwShareStatus, FLAG_CSC_OTHER_ACCESS_SHIFT_COUNT, FLAG_CSC_WRITE_ACCESS);
}
inline bool CscAccessOther(DWORD dwShareStatus)
{
return 0 != (dwShareStatus & FLAG_CSC_OTHER_ACCESS_MASK);
}
inline bool CscCanUserMergeFile(DWORD dwStatus)
{
return (CscAccessUserWrite(dwStatus) || CscAccessGuestWrite(dwStatus));
}
//
// template inlines avoid the side-effects of min/max macros.
//
template <class T>
inline const T&
MAX(const T& a, const T& b)
{
return a > b ? a : b;
}
template <class T>
inline const T&
MIN(const T& a, const T& b)
{
return a < b ? a : b;
}
class CWin32Handle
{
public:
CWin32Handle(HANDLE handle)
: m_handle(handle) { }
CWin32Handle(void)
: m_handle(NULL) { }
~CWin32Handle(void)
{ Close(); }
void Close(void)
{ if (m_handle) CloseHandle(m_handle); m_handle = NULL; }
operator HANDLE() const
{ return m_handle; }
HANDLE *HandlePtr(void)
{ TraceAssert((NULL == m_handle)); return &m_handle; }
private:
HANDLE m_handle;
//
// Prevent copy.
// This class is only intended for automatic handle cleanup.
//
CWin32Handle(const CWin32Handle& rhs);
CWin32Handle& operator = (const CWin32Handle& rhs);
};
HRESULT DataObject_SetGlobal(IDataObject *pdtobj, CLIPFORMAT cf, HGLOBAL hGlobal);
HRESULT DataObject_SetDWORD(IDataObject *pdtobj, CLIPFORMAT cf, DWORD dw);
HRESULT DataObject_GetDWORD(IDataObject *pdtobj, CLIPFORMAT cf, DWORD *pdwOut);
HRESULT SetPreferredDropEffect(IDataObject *pdtobj, DWORD dwEffect);
DWORD GetPreferredDropEffect(IDataObject *pdtobj);
HRESULT SetLogicalPerformedDropEffect(IDataObject *pdtobj, DWORD dwEffect);
DWORD GetLogicalPerformedDropEffect(IDataObject *pdtobj);
//
// Simple class for automating the display and resetting of a wait cursor.
//
class CAutoWaitCursor
{
public:
CAutoWaitCursor(void)
: m_hCursor(SetCursor(LoadCursor(NULL, IDC_WAIT)))
{ ShowCursor(TRUE); }
~CAutoWaitCursor(void)
{ Reset(); }
void Reset(void);
private:
HCURSOR m_hCursor;
};
class CAutoSetRedraw
{
public:
CAutoSetRedraw(HWND hwnd)
: m_hwnd(hwnd) { }
CAutoSetRedraw(HWND hwnd, bool bSet)
: m_hwnd(hwnd) { Set(bSet); }
~CAutoSetRedraw(void)
{ Set(true); }
void Set(bool bSet)
{ SendMessage(m_hwnd, WM_SETREDRAW, (WPARAM)bSet, 0); }
private:
HWND m_hwnd;
};
#endif // _UTIL_H_