//+------------------------------------------------------------------------- // // 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 inline const T& MAX(const T& a, const T& b) { return a > b ? a : b; } template 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_