Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
update.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 139k
Category:
Windows Kernel
Development Platform:
Visual C++
- //+-------------------------------------------------------------------------
- //
- // Microsoft Windows
- //
- // Copyright (C) Microsoft Corporation, 1997 - 1999
- //
- // File: update.cpp
- //
- // Authors;
- // Jeff Saathoff (jeffreys)
- //
- // Notes;
- // SyncMgr integration
- //--------------------------------------------------------------------------
- #include "pch.h"
- #include "msgbox.h" // CscWin32Message
- #include "folder.h"
- #include <openfile.h> // OpenOfflineFile
- #include "cscst.h" // PostToSystray
- #include "uihooks.h" // Self-host notifications
- #include "fopendlg.h" // OpenFilesWarningDialog
- #include "statdlg.h" // ReconnectServers
- #include "security.h"
- #define RAS_CONNECT_DELAY (10 * 1000)
- // Maximum length of username
- #define MAX_USERNAME_CHARS 64
- // SYNCTHREADDATA.dwSyncStatus flags
- #define SDS_SYNC_OUT 0x00000001 // CSCMergeShare
- #define SDS_SYNC_IN_QUICK 0x00000002 // CSCFillSparseFiles(FALSE)
- #define SDS_SYNC_IN_FULL 0x00000004 // CSCFillSparseFiles(TRUE)
- #define SDS_SYNC_FORCE_INWARD 0x00000008
- #define SDS_SYNC_RAS_CONNECTED 0x00000010
- #define SDS_SYNC_RESTART_MERGE 0x00000020
- #define SDS_SYNC_DELETE_DELETE 0x00000040
- #define SDS_SYNC_DELETE_RESTORE 0x00000080
- #define SDS_SYNC_AUTOCACHE 0x00000100
- #define SDS_SYNC_CONFLICT_KEEPLOCAL 0x00000200
- #define SDS_SYNC_CONFLICT_KEEPNET 0x00000400
- #define SDS_SYNC_CONFLICT_KEEPBOTH 0x00000800
- #define SDS_SYNC_STARTED 0x00010000
- #define SDS_SYNC_ERROR 0x00020000
- #define SDS_SYNC_CANCELLED 0x00040000
- #define SDS_SYNC_FILE_SKIPPED 0x00080000
- #define SDS_SYNC_DELETE_CONFLICT_MASK (SDS_SYNC_DELETE_DELETE | SDS_SYNC_DELETE_RESTORE)
- #define SDS_SYNC_FILE_CONFLICT_MASK (SDS_SYNC_CONFLICT_KEEPLOCAL | SDS_SYNC_CONFLICT_KEEPNET | SDS_SYNC_CONFLICT_KEEPBOTH)
- // Sync Flags used internally by CCscUpdate
- #define CSC_SYNC_OUT 0x00000001L
- #define CSC_SYNC_IN_QUICK 0x00000002L
- #define CSC_SYNC_IN_FULL 0x00000004L
- #define CSC_SYNC_SETTINGS 0x00000008L
- #define CSC_SYNC_MAYBOTHERUSER 0x00000010L
- #define CSC_SYNC_NOTIFY_SYSTRAY 0x00000020L
- #define CSC_SYNC_LOGOFF 0x00000040L
- #define CSC_SYNC_LOGON 0x00000080L
- #define CSC_SYNC_IDLE 0x00000100L
- #define CSC_SYNC_NONET 0x00000200L
- #define CSC_SYNC_PINFILES 0x00000400L
- #define CSC_SYNC_PIN_RECURSE 0x00000800L
- #define CSC_SYNC_OFWARNINGDONE 0x00001000L
- #define CSC_SYNC_CANCELLED 0x00002000L
- #define CSC_SYNC_SHOWUI_ALWAYS 0x00004000L
- #define CSC_SYNC_IGNORE_ACCESS 0x00008000L
- #define CSC_SYNC_SKIP_EFS 0x00010000L
- #define CSC_SYNC_EFS_WARNING_SHOWN 0x00020000L
- #define CSC_SYNC_RECONNECT 0x00040000L
- #define CSC_LOCALLY_MODIFIED (FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED
- | FLAG_CSC_COPY_STATUS_LOCALLY_DELETED
- | FLAG_CSC_COPY_STATUS_LOCALLY_CREATED)
- HICON g_hCscIcon = NULL;
- // Used for marshalling data into the SyncMgr process
- typedef struct _CSC_UPDATE_DATA
- {
- DWORD dwUpdateFlags;
- DWORD dwFileBufferOffset;
- } CSC_UPDATE_DATA, *PCSC_UPDATE_DATA;
- LPTSTR GetErrorText(DWORD dwErr)
- {
- UINT idString = (UINT)-1;
- LPTSTR pszError = NULL;
- switch (dwErr)
- {
- case ERROR_INVALID_NAME:
- // "Files of this type cannot be made available offline."
- idString = IDS_CACHING_DISALLOWED;
- break;
- }
- if ((UINT)-1 != idString)
- {
- LoadStringAlloc(&pszError, g_hInstance, idString);
- }
- else if (NOERROR != dwErr)
- {
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dwErr,
- 0,
- (LPTSTR)&pszError,
- 1,
- NULL);
- }
- return pszError;
- }
- //*************************************************************
- //
- // CscRegisterHandler
- //
- // Purpose: Register/unregister CSC Update handler with SyncMgr
- //
- // Parameters: bRegister - TRUE to register, FALSE to unregister
- // punkSyncMgr - (optional) instance of SyncMgr to use
- //
- // Return: HRESULT
- //
- //*************************************************************
- HRESULT
- CscRegisterHandler(BOOL bRegister, LPUNKNOWN punkSyncMgr)
- {
- HRESULT hr;
- HRESULT hrComInit = E_FAIL;
- ISyncMgrRegister *pSyncRegister = NULL;
- const DWORD dwRegFlags = SYNCMGRREGISTERFLAG_CONNECT | SYNCMGRREGISTERFLAG_PENDINGDISCONNECT;
- static BOOL s_bSyncHandlerRegistered = FALSE;
- TraceEnter(TRACE_UPDATE, "CscRegisterHandler");
- if (bRegister && s_bSyncHandlerRegistered)
- TraceLeaveResult(S_OK); // already registered
- // Note: if bRegister and s_bSyncHandlerRegistered are both FALSE, unregister anyway.
- if (punkSyncMgr)
- {
- hr = punkSyncMgr->QueryInterface(IID_ISyncMgrRegister, (LPVOID*)&pSyncRegister);
- }
- else
- {
- hrComInit = CoInitialize(NULL);
- hr = CoCreateInstance(CLSID_SyncMgr,
- NULL,
- CLSCTX_SERVER,
- IID_ISyncMgrRegister,
- (LPVOID*)&pSyncRegister);
- }
- FailGracefully(hr, "Unable to get ISyncMgrRegister interface");
- if (bRegister)
- hr = pSyncRegister->RegisterSyncMgrHandler(CLSID_CscUpdateHandler, NULL, dwRegFlags);
- else
- hr = pSyncRegister->UnregisterSyncMgrHandler(CLSID_CscUpdateHandler, dwRegFlags);
- if (SUCCEEDED(hr))
- s_bSyncHandlerRegistered = bRegister;
- exit_gracefully:
- DoRelease(pSyncRegister);
- if (SUCCEEDED(hrComInit))
- CoUninitialize();
- TraceLeaveResult(hr);
- }
- //*************************************************************
- //
- // CscUpdateCache
- //
- // Purpose: Invoke SyncMgr to update the CSC cache
- //
- // Parameters: pNamelist - list of files passed to the CSC SyncMgr handler
- //
- //
- // Return: HRESULT
- //
- //*************************************************************
- HRESULT
- CscUpdateCache(DWORD dwUpdateFlags, CscFilenameList *pfnl)
- {
- HRESULT hr;
- HRESULT hrComInit = E_FAIL;
- ISyncMgrSynchronizeInvoke *pSyncInvoke = NULL;
- DWORD dwSyncMgrFlags = 0;
- ULONG cbDataLength = sizeof(CSC_UPDATE_DATA);
- PCSC_UPDATE_DATA pUpdateData = NULL;
- PCSC_NAMELIST_HDR pNamelist = NULL;
- TraceEnter(TRACE_UPDATE, "CscUpdateCache");
- hrComInit = CoInitialize(NULL);
- hr = CoCreateInstance(CLSID_SyncMgr,
- NULL,
- CLSCTX_SERVER,
- IID_ISyncMgrSynchronizeInvoke,
- (LPVOID*)&pSyncInvoke);
- FailGracefully(hr, "Unable to create SyncMgr object");
- if (dwUpdateFlags & CSC_UPDATE_SELECTION)
- {
- if (NULL == pfnl || (0 == (CSC_UPDATE_SHOWUI_ALWAYS & dwUpdateFlags) && 0 == pfnl->GetShareCount()))
- ExitGracefully(hr, E_INVALIDARG, "CSC_UPDATE_SELECTION with no selection");
- pNamelist = pfnl->CreateListBuffer();
- if (!pNamelist)
- ExitGracefully(hr, E_OUTOFMEMORY, "Unable to create namelist buffer");
- cbDataLength += pNamelist->cbSize;
- }
- //
- // Alloc a buffer for the cookie data
- //
- pUpdateData = (PCSC_UPDATE_DATA)LocalAlloc(LPTR, cbDataLength);
- if (!pUpdateData)
- ExitGracefully(hr, E_OUTOFMEMORY, "LocalAlloc failed");
- pUpdateData->dwUpdateFlags = dwUpdateFlags;
- if (pNamelist)
- {
- pUpdateData->dwFileBufferOffset = sizeof(CSC_UPDATE_DATA);
- CopyMemory(ByteOffset(pUpdateData, pUpdateData->dwFileBufferOffset),
- pNamelist,
- pNamelist->cbSize);
- }
- if (dwUpdateFlags & CSC_UPDATE_STARTNOW)
- dwSyncMgrFlags |= SYNCMGRINVOKE_STARTSYNC;
- //
- // Start SyncMgr
- //
- hr = pSyncInvoke->UpdateItems(dwSyncMgrFlags,
- CLSID_CscUpdateHandler,
- cbDataLength,
- (LPBYTE)pUpdateData);
- exit_gracefully:
- if (pNamelist)
- CscFilenameList::FreeListBuffer(pNamelist);
- if (pUpdateData)
- LocalFree(pUpdateData);
- DoRelease(pSyncInvoke);
- if (SUCCEEDED(hrComInit))
- CoUninitialize();
- TraceLeaveResult(hr);
- }
- //*************************************************************
- //
- // GetNewVersionName
- //
- // Purpose: Create unique names for copies of a file
- //
- // Parameters: LPTSTR pszUNCPath - fully qualified UNC name of file
- // LPTSTR pszShare - \servershare that file lives on
- // LPTSTR pszDrive - drive mapping to use for net operations
- // LPTSTR *ppszNewName - filename for new version returned here (must free)
- //
- // Return: Win32 error code
- //
- //*************************************************************
- DWORD
- GetNewVersionName(LPCTSTR pszUNCPath,
- LPCTSTR pszShare,
- LPCTSTR pszDrive,
- LPTSTR *ppszNewName)
- {
- DWORD dwErr = NOERROR;
- LPTSTR pszDriveLetterPath = NULL;
- LPTSTR pszPath = NULL;
- LPTSTR pszFile = NULL;
- LPTSTR pszExt = NULL;
- LPTSTR pszWildCardName = NULL;
- TCHAR szUserName[MAX_USERNAME_CHARS];
- ULONG nLength;
- ULONG nMaxVersion = 0;
- ULONG cOlderVersions = 0;
- HANDLE hFind = INVALID_HANDLE_VALUE;
- WIN32_FIND_DATA fd;
- LPTSTR pszT;
- TraceEnter(TRACE_UPDATE, "GetNewVersionName");
- TraceAssert(pszUNCPath != NULL);
- TraceAssert(ppszNewName != NULL);
- *ppszNewName = NULL;
- // 1. Split the path into components.
- // 2. Build wildcard name "X:dirfoo (johndoe v*).txt"
- // 3. Do a findfirst/findnext loop to get the min & max version #
- // and count the number of old versions.
- // 4. Increment the max version # and build the new filename as:
- // "foo (johndoe v<max+1>).txt"
- // Assume that the UNC name contains more than the share
- TraceAssert(!StrCmpNI(pszUNCPath, pszShare, lstrlen(pszShare)));
- TraceAssert(lstrlen(pszUNCPath) > lstrlen(pszShare));
- // Copy the path (without \servershare)
- if (!LocalAllocString(&pszPath, pszUNCPath + lstrlen(pszShare)))
- ExitGracefully(dwErr, ERROR_OUTOFMEMORY, "LocalAllocString failed");
- // Find the file part of the name
- pszT = PathFindFileName(pszPath);
- if (!pszT)
- ExitGracefully(dwErr, ERROR_INVALID_PARAMETER, "Incomplete path");
- // Copy the filename
- if (!LocalAllocString(&pszFile, pszT))
- ExitGracefully(dwErr, ERROR_OUTOFMEMORY, "LocalAllocString failed");
- // Look for the file extension
- pszT = PathFindExtension(pszFile);
- if (pszT)
- {
- // Copy the extension and truncate the file root at this point
- LocalAllocString(&pszExt, pszT);
- *pszT = TEXT('');
- }
- // Truncate the path
- PathRemoveFileSpec(pszPath);
- // Get the user name
- nLength = ARRAYSIZE(szUserName);
- if (!GetUserName(szUserName, &nLength))
- LoadString(g_hInstance, IDS_UNKNOWN_USER, szUserName, ARRAYSIZE(szUserName));
- // Build the wildcard path "X:dirfoo (johndoe v*).txt"
- nLength = FormatStringID(&pszWildCardName, g_hInstance, IDS_VERSION_FORMAT, pszFile, szUserName, c_szStar, pszExt);
- if (!nLength)
- ExitGracefully(dwErr, GetLastError(), "Unable to format string");
- nLength += lstrlen(pszUNCPath) + lstrlen(szUserName);
- pszDriveLetterPath = (LPTSTR)LocalAlloc(LPTR, MAX(nLength, ULONG(MAX_PATH)) * sizeof(TCHAR));
- if (!pszDriveLetterPath)
- ExitGracefully(dwErr, ERROR_OUTOFMEMORY, "LocalAlloc failed");
- PathCombine(pszDriveLetterPath, pszDrive, pszPath);
- PathAppend(pszDriveLetterPath, pszWildCardName);
- nLength = (ULONG)(StrStr(pszWildCardName, c_szStar) - pszWildCardName); // remember where the '*' is
- // Search for existing versions of the file with this username
- hFind = FindFirstFile(pszDriveLetterPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE)
- {
- ULONG nVersion;
- do
- {
- nVersion = StrToLong(&fd.cFileName[nLength]);
- if (nVersion > nMaxVersion)
- {
- nMaxVersion = nVersion;
- }
- cOlderVersions++;
- }
- while (FindNextFile(hFind, &fd));
- FindClose(hFind);
- }
- // Build the new file name to return to the caller.
- // This one is version nMaxVersion+1.
- ULongToString(nMaxVersion+1, pszDriveLetterPath, lstrlen(pszDriveLetterPath));
- nLength = FormatStringID(ppszNewName, g_hInstance, IDS_VERSION_FORMAT, pszFile, szUserName, pszDriveLetterPath, pszExt);
- if (!nLength)
- ExitGracefully(dwErr, GetLastError(), "Unable to format string");
- exit_gracefully:
- LocalFreeString(&pszDriveLetterPath);
- LocalFreeString(&pszPath);
- LocalFreeString(&pszFile);
- LocalFreeString(&pszExt);
- LocalFreeString(&pszWildCardName);
- if (NOERROR != dwErr)
- {
- LocalFreeString(ppszNewName);
- }
- TraceLeaveValue(dwErr);
- }
- //*************************************************************
- //
- // ConflictDlgCallback
- //
- // Purpose: Display local or remote file from conflict dialog
- //
- // Parameters: hWnd - conflict dialog handle (used as parent for UI)
- // uMsg - one of RFCCM_*
- // wParam - depends on uMsg (unused)
- // lParam - pointer to context data (RFCDLGPARAM)
- //
- //
- // Return: TRUE on success, FALSE otherwise
- //
- //*************************************************************
- typedef struct _CONFLICT_DATA
- {
- LPCTSTR pszShare;
- LPCTSTR pszDrive;
- } CONFLICT_DATA;
- BOOL
- ConflictDlgCallback(HWND hWnd, UINT uMsg, WPARAM /*wParam*/, LPARAM lParam)
- {
- RFCDLGPARAM *pdlgParam = (RFCDLGPARAM*)lParam;
- CONFLICT_DATA cd = {0};
- LPTSTR pszTmpName = NULL;
- ULONG cchShare = 0;
- LPTSTR szFile;
- DWORD dwErr = NOERROR;
- TraceEnter(TRACE_UPDATE, "ConflictDlgCallback");
- if (NULL == pdlgParam)
- {
- TraceAssert(FALSE);
- TraceLeaveValue(FALSE);
- }
- szFile = (LPTSTR)LocalAlloc(LMEM_FIXED,
- MAX(StringByteSize(pdlgParam->pszLocation)
- + StringByteSize(pdlgParam->pszFilename), MAX_PATH_BYTES));
- if (!szFile)
- TraceLeaveValue(FALSE);
- if (pdlgParam->lCallerData)
- cd = *(CONFLICT_DATA*)pdlgParam->lCallerData;
- if (cd.pszShare)
- cchShare = lstrlen(cd.pszShare);
- switch (uMsg)
- {
- case RFCCM_VIEWLOCAL:
- // Build UNC path and view what's in the cache
- PathCombine(szFile, pdlgParam->pszLocation, pdlgParam->pszFilename);
- dwErr = OpenOfflineFile(szFile);
- break;
- case RFCCM_VIEWNETWORK:
- // Build drive letter (non-UNC) path and ShellExecute it
- PathCombine(szFile, cd.pszDrive, pdlgParam->pszLocation + cchShare);
- PathAppend(szFile, pdlgParam->pszFilename);
- {
- SHELLEXECUTEINFO si = {0};
- si.cbSize = sizeof(si);
- si.fMask = SEE_MASK_FLAG_NO_UI;
- si.hwnd = hWnd;
- si.lpFile = szFile;
- si.nShow = SW_NORMAL;
- Trace((TEXT("ShellExecuting "%s""), szFile));
- if (!ShellExecuteEx(&si))
- dwErr = GetLastError();
- }
- break;
- }
- if (NOERROR != dwErr)
- CscWin32Message(hWnd, dwErr, CSCUI::SEV_ERROR);
- LocalFree(szFile);
- TraceLeaveValue(TRUE);
- }
- //*************************************************************
- //
- // ShowConflictDialog
- //
- // Purpose: Invoke the conflict resolution dialog
- //
- // Parameters: hWndParent - dialog parent window
- // pszUNCPath - full UNC of file that conflicts
- // pszNewName - filespec to use for new copy of file (e.g. "foo (johndoe v1).txt"
- // pszShare - "\servershare"
- // pszDrive - "X:" drive mapping of remote connection
- // pfdLocal - Information about local file
- // pfdRemote - Information about remote file
- //
- //
- // Return: HRESULT
- //
- //*************************************************************
- typedef int (WINAPI *PFNSYNCMGRRESOLVECONFLICT)(HWND hWndParent, RFCDLGPARAM *pdlgParam);
- TCHAR const c_szSyncMgrDll[] = TEXT("mobsync.dll");
- #ifdef UNICODE
- CHAR const c_szResolveConflict[] = "SyncMgrResolveConflictW";
- #else
- CHAR const c_szResolveConflict[] = "SyncMgrResolveConflictA";
- #endif
- BOOL FileHasAssociation(LPCTSTR pszFile)
- {
- HRESULT hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
- if (pszFile)
- {
- pszFile = PathFindExtension(pszFile);
- if (pszFile && *pszFile)
- {
- IQueryAssociations *pAssoc = NULL;
- hr = AssocCreate(CLSID_QueryAssociations,
- IID_IQueryAssociations,
- (LPVOID*)&pAssoc);
- if (SUCCEEDED(hr))
- {
- hr = pAssoc->Init(ASSOCF_IGNOREBASECLASS, pszFile, NULL, NULL);
- pAssoc->Release();
- }
- }
- }
- return SUCCEEDED(hr);
- }
- int
- ShowConflictDialog(HWND hWndParent,
- LPCTSTR pszUNCPath,
- LPCTSTR pszNewName,
- LPCTSTR pszShare,
- LPCTSTR pszDrive,
- LPWIN32_FIND_DATA pfdLocal,
- LPWIN32_FIND_DATA pfdRemote)
- {
- int nResult = 0;
- TCHAR szUser[MAX_USERNAME_CHARS];
- LPTSTR pszPath = NULL;
- LPTSTR pszFile = NULL;
- TCHAR szRemoteDate[MAX_PATH];
- TCHAR szLocalDate[MAX_PATH];
- ULONG nLength;
- SYSTEMTIME st;
- RFCDLGPARAM dp = {0};
- CONFLICT_DATA cd;
- BOOL bLocalIsDir = FALSE;
- BOOL bRemoteIsDir = FALSE;
- static PFNSYNCMGRRESOLVECONFLICT pfnResolveConflict = NULL;
- TraceEnter(TRACE_UPDATE, "ShowConflictDialog");
- TraceAssert(pszUNCPath);
- if (NULL == pfnResolveConflict)
- {
- // The CSC Update handler is loaded by SyncMgr, so assume the SyncMgr
- // dll is already loaded. We don't want to link to the LIB to keep
- // SyncMgr from loading every time our context menu or icon overlay
- // handler is loaded (for example).
- HMODULE hSyncMgrDll = GetModuleHandle(c_szSyncMgrDll);
- if (NULL != hSyncMgrDll)
- pfnResolveConflict = (PFNSYNCMGRRESOLVECONFLICT)GetProcAddress(hSyncMgrDll,
- c_szResolveConflict);
- if (NULL == pfnResolveConflict)
- return 0;
- }
- TraceAssert(NULL != pfnResolveConflict);
- szUser[0] = TEXT('');
- nLength = ARRAYSIZE(szUser);
- GetUserName(szUser, &nLength);
- szRemoteDate[0] = TEXT('');
- if (NULL != pfdRemote)
- {
- DWORD dwFlags = FDTF_DEFAULT;
- SHFormatDateTime(&pfdRemote->ftLastWriteTime, &dwFlags, szRemoteDate, ARRAYSIZE(szRemoteDate));
- if (pfdRemote->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- bRemoteIsDir = TRUE;
- }
- szLocalDate[0] = TEXT('');
- if (NULL != pfdLocal)
- {
- DWORD dwFlags = FDTF_DEFAULT;
- SHFormatDateTime(&pfdLocal->ftLastWriteTime, &dwFlags, szLocalDate, ARRAYSIZE(szLocalDate));
- if (pfdLocal->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- bLocalIsDir = TRUE;
- }
- if (!LocalAllocString(&pszPath, pszUNCPath))
- ExitGracefully(nResult, 0, "LocalAllocString failed");
- pszFile = PathFindFileName(pszUNCPath);
- PathRemoveFileSpec(pszPath);
- dp.dwFlags = RFCF_APPLY_ALL;
- dp.pszFilename = pszFile;
- dp.pszLocation = pszPath;
- dp.pszNewName = pszNewName;
- dp.pszNetworkModifiedBy = NULL;
- dp.pszLocalModifiedBy = szUser;
- dp.pszNetworkModifiedOn = szRemoteDate;
- dp.pszLocalModifiedOn = szLocalDate;
- dp.pfnCallBack = NULL;
- dp.lCallerData = 0;
- // Only turn on the View buttons (set a callback) if we're
- // dealing with files that have associations.
- if (!(bLocalIsDir || bRemoteIsDir) && FileHasAssociation(pszFile))
- {
- // Save both the share name and drive letter for building paths to view files
- cd.pszShare = pszShare;
- cd.pszDrive = pszDrive;
- dp.pfnCallBack = ConflictDlgCallback;
- dp.lCallerData = (LPARAM)&cd;
- }
- nResult = (*pfnResolveConflict)(hWndParent, &dp);
- exit_gracefully:
- LocalFreeString(&pszPath);
- // No need to free pszFile
- TraceLeaveValue(nResult);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // SyncMgr integration implementation //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- CCscUpdate::CCscUpdate() : m_cRef(1), m_ShareLog(HKEY_CURRENT_USER, c_szCSCShareKey),
- m_pSyncMgrCB(NULL), m_hSyncThreads(NULL),
- m_pFileList(NULL), m_hSyncItems(NULL), m_hwndDlgParent(NULL),
- m_hSyncInProgMutex(NULL), m_pConflictPinList(NULL),
- m_pSilentFolderList(NULL), m_pSpecialFolderList(NULL)
- {
- DllAddRef();
- InitializeCriticalSection(&m_csThreadList);
- if (!g_hCscIcon)
- g_hCscIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_CSCUI_ICON));
- m_hSyncMutex = CreateMutex(NULL, FALSE, c_szSyncMutex);
- }
- CCscUpdate::~CCscUpdate()
- {
- TraceEnter(TRACE_UPDATE, "CCscUpdate::~CCscUpdate");
- SyncCompleted();
- TraceAssert(NULL == m_hSyncInProgMutex);
- // We should never get here while a sync thread is still running
- TraceAssert(NULL == m_hSyncThreads || 0 == DPA_GetPtrCount(m_hSyncThreads));
- if (NULL != m_hSyncThreads)
- DPA_Destroy(m_hSyncThreads);
- DeleteCriticalSection(&m_csThreadList);
- if (NULL != m_hSyncItems)
- DSA_Destroy(m_hSyncItems);
- DoRelease(m_pSyncMgrCB);
- delete m_pFileList;
- delete m_pConflictPinList;
- delete m_pSilentFolderList;
- delete m_pSpecialFolderList;
- if (NULL != m_hSyncMutex)
- CloseHandle(m_hSyncMutex);
- DllRelease();
- TraceLeaveVoid();
- }
- HRESULT WINAPI
- CCscUpdate::CreateInstance(REFIID riid, LPVOID *ppv)
- {
- HRESULT hr;
- CCscUpdate *pThis;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::CreateInstance");
- TraceAssert(IsCSCEnabled());
- pThis = new CCscUpdate;
- if (pThis)
- {
- hr = pThis->QueryInterface(riid, ppv);
- pThis->Release();
- }
- else
- hr = E_OUTOFMEMORY;
- TraceLeaveResult(hr);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // SyncMgr integration implementation (IUnknown) //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP CCscUpdate::QueryInterface(REFIID riid, void **ppv)
- {
- static const QITAB qit[] =
- {
- QITABENT(CCscUpdate, ISyncMgrSynchronize),
- { 0 },
- };
- return QISearch(this, qit, riid, ppv);
- }
- STDMETHODIMP_(ULONG) CCscUpdate::AddRef()
- {
- return InterlockedIncrement(&m_cRef);
- }
- STDMETHODIMP_(ULONG) CCscUpdate::Release()
- {
- if (InterlockedDecrement(&m_cRef))
- return m_cRef;
- delete this;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // Sync Manager integration implementation (ISyncMgrSynchronize) //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP
- CCscUpdate::Initialize(DWORD /*dwReserved*/,
- DWORD dwSyncFlags,
- DWORD cbCookie,
- const BYTE *pCookie)
- {
- HRESULT hr = S_OK;
- HKEY hkCSC;
- BOOL bNoNet = TRUE;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::Initialize");
- TraceAssert(IsCSCEnabled());
- if (!(SYNCMGRFLAG_SETTINGS & dwSyncFlags) && ::IsSyncInProgress())
- {
- //
- // We need to guard against running multiple syncs at the
- // same time. User notification in the UI is handled where
- // the UI code calls CscUpdate(). This is so that the UI
- // message contains the proper context with respect to what
- // the user is doing.
- //
- TraceLeaveResult(E_FAIL);
- }
- m_dwSyncFlags = 0;
- delete m_pFileList;
- m_pFileList = NULL;
- delete m_pConflictPinList;
- m_pConflictPinList = NULL;
- // We used to get the tray status to check for NoNet, but
- // there's a timing problem at logon (the tray window may not
- // be created yet). So ask RDR instead. If this call fails,
- // then RDR must be dead, so bNoNet defaults to TRUE.
- CSCIsServerOffline(NULL, &bNoNet);
- switch (dwSyncFlags & SYNCMGRFLAG_EVENTMASK)
- {
- case SYNCMGRFLAG_CONNECT: // Logon
- if (bNoNet)
- ExitGracefully(hr, E_FAIL, "No Logon sync when no net");
- m_dwSyncFlags = CSC_SYNC_OUT | CSC_SYNC_LOGON | CSC_SYNC_NOTIFY_SYSTRAY; // | CSC_SYNC_RECONNECT;
- break;
- case SYNCMGRFLAG_PENDINGDISCONNECT: // Logoff
- if (bNoNet)
- ExitGracefully(hr, E_FAIL, "No Logoff sync when no net");
- m_dwSyncFlags = CSC_SYNC_LOGOFF;
- if (CConfig::eSyncFull == CConfig::GetSingleton().SyncAtLogoff())
- m_dwSyncFlags |= CSC_SYNC_OUT | CSC_SYNC_IN_FULL;
- else
- m_dwSyncFlags |= CSC_SYNC_IN_QUICK;
- break;
- case SYNCMGRFLAG_INVOKE: // CscUpdateCache
- if (pCookie != NULL && cbCookie > 0)
- {
- PCSC_UPDATE_DATA pUpdateData = (PCSC_UPDATE_DATA)pCookie;
- TraceAssert(cbCookie >= sizeof(CSC_UPDATE_DATA));
- DWORD dwUpdateFlags = pUpdateData->dwUpdateFlags;
- if (dwUpdateFlags & CSC_UPDATE_SELECTION)
- {
- TraceAssert(cbCookie > sizeof(CSC_UPDATE_DATA));
- // Create the filelist from the selection provided
- m_pFileList = new CscFilenameList((PCSC_NAMELIST_HDR)ByteOffset(pUpdateData, pUpdateData->dwFileBufferOffset),
- true);
- if (!m_pFileList)
- ExitGracefully(hr, E_OUTOFMEMORY, "Unable to create CscFilenameList object");
- if (!m_pFileList->IsValid())
- ExitGracefully(hr, E_FAIL, "Unable to initialize CscFilenameList object");
- if (CSC_UPDATE_SHOWUI_ALWAYS & dwUpdateFlags)
- {
- m_dwSyncFlags |= CSC_SYNC_SHOWUI_ALWAYS;
- }
- else if (0 == m_pFileList->GetShareCount())
- ExitGracefully(hr, E_UNEXPECTED, "CSC_UPDATE_SELECTION with no selection");
- }
- if (dwUpdateFlags & CSC_UPDATE_RECONNECT)
- {
- m_dwSyncFlags |= CSC_SYNC_RECONNECT;
- }
- if (dwUpdateFlags & CSC_UPDATE_NOTIFY_DONE)
- {
- //
- // Caller of CscUpdateCache want's systray notification
- // when sync is complete.
- //
- m_dwSyncFlags |= CSC_SYNC_NOTIFY_SYSTRAY;
- }
- if (dwUpdateFlags & CSC_UPDATE_FILL_ALL)
- m_dwSyncFlags |= CSC_SYNC_IN_FULL;
- else if (dwUpdateFlags & CSC_UPDATE_FILL_QUICK)
- m_dwSyncFlags |= CSC_SYNC_IN_QUICK;
- if (dwUpdateFlags & CSC_UPDATE_REINT)
- m_dwSyncFlags |= CSC_SYNC_OUT;
- if (dwUpdateFlags & CSC_UPDATE_PIN_RECURSE)
- m_dwSyncFlags |= CSC_SYNC_PINFILES | CSC_SYNC_PIN_RECURSE | CSC_SYNC_IN_QUICK;
- else if (dwUpdateFlags & CSC_UPDATE_PINFILES)
- m_dwSyncFlags |= CSC_SYNC_PINFILES | CSC_SYNC_IN_QUICK;
- if (dwUpdateFlags & CSC_UPDATE_IGNORE_ACCESS)
- m_dwSyncFlags |= CSC_SYNC_IGNORE_ACCESS;
- }
- break;
- case SYNCMGRFLAG_IDLE: // Auto-sync at idle time
- if (bNoNet)
- ExitGracefully(hr, E_FAIL, "No idle sync when no net");
- m_dwSyncFlags = CSC_SYNC_OUT | CSC_SYNC_IN_QUICK | CSC_SYNC_IDLE | CSC_SYNC_NOTIFY_SYSTRAY;
- break;
- case SYNCMGRFLAG_MANUAL: // Run "mobsync.exe"
- m_dwSyncFlags = CSC_SYNC_OUT | CSC_SYNC_IN_FULL | CSC_SYNC_NOTIFY_SYSTRAY | CSC_SYNC_RECONNECT;
- break;
- case SYNCMGRFLAG_SCHEDULED: // User scheduled sync
- m_dwSyncFlags = CSC_SYNC_OUT | CSC_SYNC_IN_FULL | CSC_SYNC_NOTIFY_SYSTRAY;
- break;
- }
- if (!(m_dwSyncFlags & CSC_SYNC_PINFILES))
- m_dwSyncFlags |= CSC_SYNC_SKIP_EFS; // skip EFS if not pinning
- if (dwSyncFlags & SYNCMGRFLAG_SETTINGS)
- m_dwSyncFlags |= CSC_SYNC_SETTINGS;
- if (!m_dwSyncFlags)
- ExitGracefully(hr, E_UNEXPECTED, "Nothing to do");
- if (dwSyncFlags & SYNCMGRFLAG_MAYBOTHERUSER)
- m_dwSyncFlags |= CSC_SYNC_MAYBOTHERUSER;
- if (bNoNet)
- m_dwSyncFlags |= CSC_SYNC_NONET;
- GetSilentFolderList();
- exit_gracefully:
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
- {
- HRESULT hr = S_OK;
- LPSYNCMGRHANDLERINFO pHandlerInfo;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::GetHandlerInfo");
- if (NULL == ppSyncMgrHandlerInfo)
- TraceLeaveResult(E_INVALIDARG);
- *ppSyncMgrHandlerInfo = NULL;
- pHandlerInfo = (LPSYNCMGRHANDLERINFO)CoTaskMemAlloc(sizeof(SYNCMGRHANDLERINFO));
- if (NULL == pHandlerInfo)
- ExitGracefully(hr, E_OUTOFMEMORY, "LocalAlloc failed");
- pHandlerInfo->cbSize = sizeof(SYNCMGRHANDLERINFO);
- pHandlerInfo->hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_CSCUI_ICON));
- pHandlerInfo->SyncMgrHandlerFlags = SYNCMGRHANDLER_HASPROPERTIES | SYNCMGRHANDLER_MAYESTABLISHCONNECTION;
- LoadStringW(g_hInstance,
- IDS_APPLICATION,
- pHandlerInfo->wszHandlerName,
- ARRAYSIZE(pHandlerInfo->wszHandlerName));
- *ppSyncMgrHandlerInfo = pHandlerInfo;
- exit_gracefully:
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::EnumSyncMgrItems(LPSYNCMGRENUMITEMS *ppenum)
- {
- HRESULT hr;
- PUPDATEENUM pNewEnum;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::EnumSyncMgrItems");
- *ppenum = NULL;
- pNewEnum = new CUpdateEnumerator(this);
- if (pNewEnum)
- {
- hr = pNewEnum->QueryInterface(IID_ISyncMgrEnumItems, (LPVOID*)ppenum);
- pNewEnum->Release();
- }
- else
- hr = E_OUTOFMEMORY;
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::GetItemObject(REFSYNCMGRITEMID /*rItemID*/, REFIID /*riid*/, LPVOID * /*ppv*/)
- {
- return E_NOTIMPL;
- }
- STDMETHODIMP
- CCscUpdate::ShowProperties(HWND hWndParent, REFSYNCMGRITEMID rItemID)
- {
- CSCEntry *pShareEntry;
- LPCTSTR pszShareName = TEXT("");
- pShareEntry = m_ShareLog.Get(rItemID);
- // We don't enumerate shares to SyncMgr unless a share entry
- // exists in the registry, so m_ShareLog.Get should never fail here.
- if (pShareEntry)
- pszShareName = pShareEntry->Name();
- COfflineFilesFolder::Open();
- // Notify SyncMgr that the ShowProperties is done.
- if (NULL != m_pSyncMgrCB)
- m_pSyncMgrCB->ShowPropertiesCompleted(S_OK);
- return S_OK;
- }
- STDMETHODIMP
- CCscUpdate::SetProgressCallback(LPSYNCMGRSYNCHRONIZECALLBACK pCallback)
- {
- TraceEnter(TRACE_UPDATE, "CCscUpdate::SetProgressCallback");
- DoRelease(m_pSyncMgrCB);
- m_pSyncMgrCB = pCallback;
- if (m_pSyncMgrCB)
- m_pSyncMgrCB->AddRef();
- TraceLeaveResult(S_OK);
- }
- STDMETHODIMP
- CCscUpdate::PrepareForSync(ULONG cNumItems,
- SYNCMGRITEMID *pItemID,
- HWND /*hWndParent*/,
- DWORD /*dwReserved*/)
- {
- HRESULT hr = S_OK;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::PrepareForSync");
- TraceAssert(0 != cNumItems);
- TraceAssert(NULL != pItemID);
- //
- // Copy the list of item ID's
- //
- if (NULL == m_hSyncItems)
- {
- m_hSyncItems = DSA_Create(sizeof(SYNCMGRITEMID), 4);
- if (NULL == m_hSyncItems)
- ExitGracefully(hr, E_OUTOFMEMORY, "Unable to create DSA for SYNCMGRITEMID list");
- }
- else
- DSA_DeleteAllItems(m_hSyncItems);
- while (cNumItems--)
- DSA_AppendItem(m_hSyncItems, pItemID++);
- exit_gracefully:
- // ISyncMgrSynchronize::PrepareForSync is now an asynchronous call
- // so we could create another thread to do the work and return from
- // this call immediately. However, since all we do is copy the list
- // of Item IDs, let's do it here and call
- // m_pSyncMgrCB->PrepareForSyncCompleted before returning.
- if (NULL != m_pSyncMgrCB)
- m_pSyncMgrCB->PrepareForSyncCompleted(hr);
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::Synchronize(HWND hWndParent)
- {
- HRESULT hr = E_FAIL;
- ULONG cItems = 0;
- BOOL bConnectionEstablished = FALSE;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::Synchronize");
- if (NULL != m_hSyncItems)
- cItems = DSA_GetItemCount(m_hSyncItems);
- //
- // Don't want systray UI updates while syncing.
- // Whenever the systray UI is updated, the code checks first
- // for this global mutex object. If it's non-signaled, the
- // systray knows there's a sync in progress and the UI isn't
- // updated.
- //
- TraceAssert(NULL == m_hSyncInProgMutex);
- m_hSyncInProgMutex = CreateMutex(NULL, TRUE, c_szSyncInProgMutex);
- if (0 == cItems)
- {
- ExitGracefully(hr, E_UNEXPECTED, "Nothing to synchronize");
- }
- else if (1 == cItems)
- {
- SYNCMGRITEMID *pItemID = (SYNCMGRITEMID*)DSA_GetItemPtr(m_hSyncItems, 0);
- if (NULL != pItemID && IsEqualGUID(GUID_CscNullSyncItem, *pItemID))
- {
- //
- // A single item in the DSA and it's our "null sync" GUID.
- // This means we really have nothing to sync but the invoker
- // of the sync wants to see some SyncMgr progress UI. In
- // this scenario the update item enumerator already enumerated
- // the "null sync" item. Here we set this single item's progress
- // UI info to 100% complete and skip any sync activity.
- //
- SYNCMGRPROGRESSITEM spi = {0};
- spi.mask = SYNCMGRPROGRESSITEM_STATUSTYPE |
- SYNCMGRPROGRESSITEM_STATUSTEXT |
- SYNCMGRPROGRESSITEM_PROGVALUE |
- SYNCMGRPROGRESSITEM_MAXVALUE;
- spi.cbSize = sizeof(spi);
- spi.dwStatusType = SYNCMGRSTATUS_SUCCEEDED;
- spi.lpcStatusText = L" ";
- spi.iProgValue = 1;
- spi.iMaxValue = 1;
- m_pSyncMgrCB->Progress(GUID_CscNullSyncItem, &spi);
- m_pSyncMgrCB->SynchronizeCompleted(S_OK);
- ExitGracefully(hr, NOERROR, "Nothing to sync. Progress UI displayed");
- }
- }
- m_hwndDlgParent = hWndParent;
- // We can pin autocached files without a net (no sync required);
- // otherwise we need to establish a RAS connection to do anything.
- if ((m_dwSyncFlags & CSC_SYNC_NONET) && !(m_dwSyncFlags & CSC_SYNC_PINFILES))
- {
- hr = m_pSyncMgrCB->EstablishConnection(NULL, 0);
- FailGracefully(hr, "Unable to establish RAS connection");
- bConnectionEstablished = TRUE;
- }
- // For each share, kick off a thread to do the work
- while (cItems > 0)
- {
- SYNCMGRITEMID *pItemID;
- CSCEntry *pShareEntry;
- --cItems;
- pItemID = (SYNCMGRITEMID*)DSA_GetItemPtr(m_hSyncItems, cItems);
- pShareEntry = m_ShareLog.Get(*pItemID);
- // We don't enumerate shares to SyncMgr unless a share entry
- // exists in the registry, so m_ShareLog.Get should never fail here.
- if (NULL == pShareEntry)
- ExitGracefully(hr, E_UNEXPECTED, "No share entry");
- hr = SynchronizeShare(pItemID, pShareEntry->Name(), bConnectionEstablished);
- DSA_DeleteItem(m_hSyncItems, cItems);
- FailGracefully(hr, "Unable to create sync thread");
- }
- TraceAssert(0 == DSA_GetItemCount(m_hSyncItems));
- exit_gracefully:
- if (FAILED(hr))
- SetItemStatus(GUID_NULL, SYNCMGRSTATUS_STOPPED);
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::SetItemStatus(REFSYNCMGRITEMID rItemID,
- DWORD dwSyncMgrStatus)
- {
- HRESULT hr = E_FAIL;
- ULONG cItems;
- BOOL bAllItems;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::SetItemStatus");
- if (SYNCMGRSTATUS_SKIPPED != dwSyncMgrStatus && SYNCMGRSTATUS_STOPPED != dwSyncMgrStatus)
- TraceLeaveResult(E_NOTIMPL);
- bAllItems = FALSE;
- if (SYNCMGRSTATUS_STOPPED == dwSyncMgrStatus)
- {
- bAllItems = TRUE;
- m_dwSyncFlags |= CSC_SYNC_CANCELLED;
- }
- // SetItemStatus can be called between PrepareForSync and Synchronize, in
- // in which case the correct thing to do is remove the item from m_hSyncItems.
- if (NULL != m_hSyncItems)
- {
- cItems = DSA_GetItemCount(m_hSyncItems);
- while (cItems > 0)
- {
- SYNCMGRITEMID *pItemID;
- --cItems;
- pItemID = (SYNCMGRITEMID*)DSA_GetItemPtr(m_hSyncItems, cItems);
- if (bAllItems || IsEqualGUID(rItemID, *pItemID))
- {
- // Remove the item from the list of items to sync
- DSA_DeleteItem(m_hSyncItems, cItems);
- if (!bAllItems)
- ExitGracefully(hr, S_OK, "Skipping item");
- }
- }
- }
- // Lookup the thread for the item ID and set its status
- // to cause it to terminate.
- hr = SetSyncThreadStatus(SyncStop, bAllItems ? GUID_NULL : rItemID);
- exit_gracefully:
- TraceLeaveResult(hr);
- }
- STDMETHODIMP
- CCscUpdate::ShowError(HWND /*hWndParent*/ , REFSYNCMGRERRORID /*ErrorID*/)
- {
- return E_NOTIMPL;
- }
- HRESULT
- CCscUpdate::SynchronizeShare(SYNCMGRITEMID *pItemID, LPCTSTR pszShareName, BOOL bRasConnected)
- {
- HRESULT hr = S_OK;
- DWORD dwThreadID;
- PSYNCTHREADDATA pThreadData;
- ULONG cbShareName = 0;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::SynchronizeShare");
- TraceAssert(NULL != pItemID);
- TraceAssert(NULL != pszShareName);
- TraceAssert(*pszShareName);
- EnterCriticalSection(&m_csThreadList);
- if (NULL == m_hSyncThreads)
- m_hSyncThreads = DPA_Create(4);
- LeaveCriticalSection(&m_csThreadList);
- if (NULL == m_hSyncThreads)
- ExitGracefully(hr, E_OUTOFMEMORY, "Unable to create DPA for threads");
- cbShareName = StringByteSize(pszShareName);
- pThreadData = (PSYNCTHREADDATA)LocalAlloc(LPTR, sizeof(SYNCTHREADDATA) + cbShareName);
- if (!pThreadData)
- ExitGracefully(hr, E_OUTOFMEMORY, "LocalAlloc failed");
- pThreadData->pThis = this;
- pThreadData->ItemID = *pItemID;
- pThreadData->pszShareName = (LPTSTR)(pThreadData + 1);
- CopyMemory(pThreadData->pszShareName, pszShareName, cbShareName);
- //
- // If we established a RAS connection, then it will go away
- // right after the sync completes, so there's no point trying
- // to reconnect. That is, only check CSC_SYNC_RECONNECT and
- // add the share to the reconnect list if we aren't doing RAS.
- //
- if (bRasConnected)
- {
- pThreadData->dwSyncStatus |= SDS_SYNC_RAS_CONNECTED;
- }
- else if (m_dwSyncFlags & CSC_SYNC_RECONNECT)
- {
- CscFilenameList::HSHARE hShare;
- m_ReconnectList.AddShare(pszShareName, &hShare);
- }
- pThreadData->hThread = CreateThread(NULL,
- 0,
- _SyncThread,
- pThreadData,
- CREATE_SUSPENDED,
- &dwThreadID);
- if (NULL != pThreadData->hThread)
- {
- EnterCriticalSection(&m_csThreadList);
- DPA_AppendPtr(m_hSyncThreads, pThreadData);
- LeaveCriticalSection(&m_csThreadList);
- ResumeThread(pThreadData->hThread);
- }
- else
- {
- DWORD dwErr = GetLastError();
- LocalFree(pThreadData);
- LPTSTR pszErr = GetErrorText(GetLastError());
- LogError(*pItemID,
- SYNCMGRLOGLEVEL_ERROR,
- IDS_FILL_SPARSE_FILES_ERROR,
- pszShareName,
- pszErr);
- LocalFreeString(&pszErr);
- hr = HRESULT_FROM_WIN32(dwErr);
- }
- exit_gracefully:
- TraceLeaveResult(hr);
- }
- void
- CCscUpdate::SetLastSyncTime(LPCTSTR pszShareName)
- {
- HKEY hKey = NULL;
- hKey = m_ShareLog.OpenKey(pszShareName, KEY_SET_VALUE);
- if (hKey)
- {
- FILETIME ft = {0};
- GetSystemTimeAsFileTime(&ft);
- RegSetValueEx(hKey, c_szLastSync, 0, REG_BINARY, (LPBYTE)&ft, sizeof(ft));
- RegCloseKey(hKey);
- }
- }
- DWORD
- CCscUpdate::GetLastSyncTime(LPCTSTR pszShareName, LPFILETIME pft)
- {
- DWORD dwResult = ERROR_PATH_NOT_FOUND;
- HKEY hKey = NULL;
- hKey = m_ShareLog.OpenKey(pszShareName, KEY_QUERY_VALUE);
- if (hKey)
- {
- DWORD dwSize = sizeof(*pft);
- dwResult = RegQueryValueEx(hKey, c_szLastSync, NULL, NULL, (LPBYTE)pft, &dwSize);
- RegCloseKey(hKey);
- }
- return dwResult;
- }
- void
- CCscUpdate::SyncThreadCompleted(PSYNCTHREADDATA pSyncData)
- {
- int iThread;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::SyncThreadCompleted");
- TraceAssert(NULL != pSyncData);
- TraceAssert(NULL != m_hSyncThreads);
- EnterCriticalSection(&m_csThreadList);
- iThread = DPA_GetPtrIndex(m_hSyncThreads, pSyncData);
- TraceAssert(-1 != iThread);
- DPA_DeletePtr(m_hSyncThreads, iThread);
- CloseHandle(pSyncData->hThread);
- pSyncData->hThread = NULL;
- iThread = DPA_GetPtrCount(m_hSyncThreads);
- LeaveCriticalSection(&m_csThreadList);
- if (0 == iThread)
- {
- SyncCompleted();
- }
- TraceLeaveVoid();
- }
- void
- CCscUpdate::SyncCompleted(void)
- {
- if ((m_dwSyncFlags & CSC_SYNC_RECONNECT) &&
- !(m_dwSyncFlags & CSC_SYNC_CANCELLED))
- {
- m_dwSyncFlags &= ~CSC_SYNC_RECONNECT;
- ReconnectServers(&m_ReconnectList, FALSE, FALSE);
- }
- if (NULL != m_hSyncInProgMutex)
- {
- // We're not syncing so reset the global event
- ReleaseMutex(m_hSyncInProgMutex);
- CloseHandle(m_hSyncInProgMutex);
- m_hSyncInProgMutex = NULL;
- }
- if (m_dwSyncFlags & CSC_SYNC_NOTIFY_SYSTRAY)
- {
- // Notify systray that we're done
- PostToSystray(CSCWM_DONESYNCING, 0, 0);
- m_dwSyncFlags &= ~CSC_SYNC_NOTIFY_SYSTRAY;
- }
- // Notify SyncMgr that the sync is done
- if (NULL != m_pSyncMgrCB)
- {
- m_pSyncMgrCB->SynchronizeCompleted(S_OK);
- }
- }
- UINT
- GetErrorFormat(DWORD dwErr, BOOL bMerging = FALSE)
- {
- UINT idString = 0;
- // BUGBUG these are all just initial guesses. Not sure
- // which error codes we'll get from CSC.
- switch (dwErr)
- {
- case ERROR_DISK_FULL:
- // "The server disk is full."
- // "The local disk is full."
- idString = bMerging ? IDS_SERVER_FULL_ERROR : IDS_LOCAL_DISK_FULL_ERROR;
- break;
- case ERROR_LOCK_VIOLATION:
- case ERROR_SHARING_VIOLATION:
- case ERROR_OPEN_FILES:
- case ERROR_ACTIVE_CONNECTIONS:
- case ERROR_DEVICE_IN_USE:
- // "'%1' is in use on %2"
- idString = IDS_FILE_OPEN_ERROR;
- break;
- case ERROR_BAD_NETPATH:
- case ERROR_DEV_NOT_EXIST:
- case ERROR_NETNAME_DELETED:
- case ERROR_BAD_NET_NAME:
- case ERROR_SHARING_PAUSED:
- case ERROR_REQ_NOT_ACCEP:
- case ERROR_REDIR_PAUSED:
- case ERROR_BAD_DEVICE:
- case ERROR_CONNECTION_UNAVAIL:
- case ERROR_NO_NET_OR_BAD_PATH:
- case ERROR_NO_NETWORK:
- case ERROR_CONNECTION_REFUSED:
- case ERROR_GRACEFUL_DISCONNECT:
- case ERROR_NETWORK_UNREACHABLE:
- case ERROR_HOST_UNREACHABLE:
- case ERROR_PROTOCOL_UNREACHABLE:
- case ERROR_PORT_UNREACHABLE:
- case ERROR_LOGON_FAILURE:
- // "Unable to connect to '%1.' %2"
- idString = IDS_SHARE_CONNECT_ERROR;
- break;
- case ERROR_OPEN_FAILED:
- case ERROR_UNEXP_NET_ERR:
- case ERROR_NETWORK_BUSY:
- case ERROR_BAD_NET_RESP:
- // "Unable to access '%1' on %2. %3"
- idString = IDS_NET_ERROR;
- break;
- case ERROR_ACCESS_DENIED:
- case ERROR_NETWORK_ACCESS_DENIED:
- // "Access to '%1' is denied on %2"
- idString = IDS_ACCESS_ERROR;
- break;
- case ERROR_BAD_FORMAT:
- // "The Offline Files cache is corrupt. Restart the computer to correct the cache."
- idString = IDS_CACHE_CORRUPT;
- break;
- default:
- // "Error accessing '%1' on %2. %3"
- idString = IDS_UNKNOWN_SYNC_ERROR;
- break;
- }
- return idString;
- }
- HRESULT
- CCscUpdate::LogError(REFSYNCMGRITEMID rItemID,
- LPCTSTR pszText,
- DWORD dwLogLevel,
- REFSYNCMGRERRORID ErrorID)
- {
- HRESULT hr;
- SYNCMGRLOGERRORINFO slei;
- USES_CONVERSION;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::LogError");
- if (NULL == m_pSyncMgrCB)
- TraceLeaveResult(E_UNEXPECTED);
- slei.cbSize = sizeof(slei);
- slei.mask = SYNCMGRLOGERROR_ITEMID | SYNCMGRLOGERROR_ERRORID;
- slei.ItemID = rItemID;
- slei.ErrorID = ErrorID;
- // if we have a jumptext associated with this item then
- // set the enable jumptext flag
- if (ErrorID != GUID_NULL)
- {
- slei.mask |= SYNCMGRLOGERROR_ERRORFLAGS;
- slei.dwSyncMgrErrorFlags = SYNCMGRERRORFLAG_ENABLEJUMPTEXT;
- }
- Trace((pszText));
- hr = m_pSyncMgrCB->LogError(dwLogLevel, T2CW(pszText), &slei);
- TraceLeaveResult(hr);
- }
- DWORD
- CCscUpdate::LogError(REFSYNCMGRITEMID rItemID,
- DWORD dwLogLevel,
- UINT nFormatID,
- ...)
- {
- LPTSTR pszError = NULL;
- va_list args;
- va_start(args, nFormatID);
- if (vFormatStringID(&pszError, g_hInstance, nFormatID, &args))
- {
- LogError(rItemID, pszError, dwLogLevel);
- LocalFree(pszError);
- }
- va_end(args);
- return 0;
- }
- DWORD
- CCscUpdate::LogError(REFSYNCMGRITEMID rItemID,
- UINT nFormatID,
- LPCTSTR pszName,
- DWORD dwErr,
- DWORD dwLogLevel)
- {
- //
- // Break the filename into "file" and "path" components
- //
- TCHAR szPath[MAX_PATH] = TEXT("\");
- LPCTSTR pszFile = NULL;
- if (pszName)
- {
- pszFile = PathFindFileName(pszName);
- lstrcpyn(szPath, pszName, min(ARRAYSIZE(szPath),(int)(pszFile-pszName)));
- }
- //
- // Get the system error text and format the error
- //
- LPTSTR pszErr = GetErrorText(dwErr);
- LogError(rItemID,
- dwLogLevel,
- nFormatID,
- pszFile,
- szPath,
- pszErr);
- LocalFreeString(&pszErr);
- return 0;
- }
- BOOL
- MakeDriveLetterPath(LPCTSTR pszUNC,
- LPCTSTR pszShare,
- LPCTSTR pszDrive,
- LPTSTR *ppszResult)
- {
- BOOL bResult = FALSE;
- ULONG cchShare;
- if (!pszUNC || !pszShare || !ppszResult)
- return FALSE;
- *ppszResult = NULL;
- cchShare = lstrlen(pszShare);
- // If the path is on the share, use the drive letter instead
- if (pszDrive && *pszDrive &&
- CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT,
- NORM_IGNORECASE,
- pszUNC,
- cchShare,
- pszShare,
- cchShare))
- {
- *ppszResult = (LPTSTR)LocalAlloc(LPTR, MAX(StringByteSize(pszUNC), MAX_PATH_BYTES));
- if (*ppszResult)
- {
- PathCombine(*ppszResult, pszDrive, pszUNC + cchShare);
- bResult = TRUE;
- }
- }
- return bResult;
- }
- DWORD
- CCscUpdate::CopyLocalFileWithDriveMapping(LPCTSTR pszSrc,
- LPCTSTR pszDst,
- LPCTSTR pszShare,
- LPCTSTR pszDrive,
- BOOL bDirectory)
- {
- DWORD dwErr = NOERROR;
- LPTSTR szDst = NULL;
- if (!pszSrc || !pszDst || !pszShare)
- return ERROR_INVALID_PARAMETER;
- // If the destination is on the share, use the drive letter instead
- if (MakeDriveLetterPath(pszDst, pszShare, pszDrive, &szDst))
- pszDst = szDst;
- if (bDirectory)
- {
- // We don't need to copy the directory contents here, just create
- // the tree structure on the server.
- if (!CreateDirectory(pszDst, NULL))
- {
- dwErr = GetLastError();
- if (ERROR_ALREADY_EXISTS == dwErr)
- dwErr = NOERROR;
- }
- }
- else
- {
- LPTSTR pszTmpName = NULL;
- if (!CSCCopyReplica(pszSrc, &pszTmpName) ||
- !MoveFileEx(pszTmpName,
- pszDst,
- MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
- {
- dwErr = GetLastError();
- }
- if (NULL != pszTmpName)
- {
- DeleteFile(pszTmpName);
- LocalFree(pszTmpName);
- }
- }
- if (ERROR_PATH_NOT_FOUND == dwErr)
- {
- // The parent directory doesn't exist, create it now.
- TCHAR szParent[MAX_PATH];
- lstrcpyn(szParent, pszDst, ARRAYSIZE(szParent));
- PathRemoveFileSpec(szParent);
- dwErr = CopyLocalFileWithDriveMapping(pszSrc, szParent, pszShare, NULL, TRUE);
- // If that worked, retry the original operation.
- if (NOERROR == dwErr)
- dwErr = CopyLocalFileWithDriveMapping(pszSrc, pszDst, pszShare, NULL, bDirectory);
- }
- LocalFreeString(&szDst);
- return dwErr;
- }
- BOOL
- HandleConflictLocally(PSYNCTHREADDATA pSyncData,
- LPCTSTR pszPath,
- DWORD dwCscStatus,
- DWORD dwLocalAttr,
- DWORD dwRemoteAttr = 0)
- {
- BOOL bResult = FALSE;
- LPTSTR szParent = NULL;
- // If it's super-hidden or not modified locally, we can always
- // handle the conflict locally.
- if (!(dwCscStatus & CSC_LOCALLY_MODIFIED) || IsHiddenSystem(dwLocalAttr) || IsHiddenSystem(dwRemoteAttr))
- return TRUE;
- // If we're dealing with 2 folders, the worst that happens is that the
- // underlying files/folders get merged.
- if ((FILE_ATTRIBUTE_DIRECTORY & dwLocalAttr) && (FILE_ATTRIBUTE_DIRECTORY & dwRemoteAttr))
- return TRUE;
- //
- // Next, check whether the parent path is super-hidden.
- //
- // For example, recycle bin makes super-hidden folders and puts
- // metadata files in them.
- //
- // Do this on the server, since CSC has exclusive access to the database
- // while merging, causing GetFileAttributes to fail with Access Denied.
- //
- if (MakeDriveLetterPath(pszPath, pSyncData->pszShareName, pSyncData->szDrive, &szParent))
- {
- do
- {
- PathRemoveFileSpec(szParent);
- dwRemoteAttr = GetFileAttributes(szParent);
- if ((DWORD)-1 == dwRemoteAttr)
- {
- // Path doesn't exist, access denied, etc.
- break;
- }
- if (IsHiddenSystem(dwRemoteAttr))
- {
- bResult = TRUE;
- break;
- }
- }
- while (!PathIsRoot(szParent));
- }
- LocalFreeString(&szParent);
- return bResult;
- }
- DWORD
- CCscUpdate::HandleFileConflict(PSYNCTHREADDATA pSyncData,
- LPCTSTR pszName,
- DWORD dwStatus,
- DWORD dwHintFlags,
- LPWIN32_FIND_DATA pFind32)
- {
- DWORD dwResult = CSCPROC_RETURN_CONTINUE;
- DWORD dwErr = NOERROR;
- int nErrorResolution = RFC_KEEPBOTH;
- LPTSTR pszNewName = NULL;
- LPTSTR szFullPath = NULL;
- BOOL bApplyToAll = FALSE;
- TraceEnter(TRACE_UPDATE, "CCscUpdate::HandleFileConflict");
- Trace((TEXT("File conflict: %s"), pszName));
- TraceAssert(pSyncData->dwSyncStatus & SDS_SYNC_OUT);
- szFullPath = (LPTSTR)LocalAlloc(LPTR, StringByteSize(pszName) + MAX_PATH*sizeof(TCHAR));
- if (!szFullPath)
- {
- dwErr = ERROR_OUTOFMEMORY;
- ExitGracefully(dwResult, CSCPROC_RETURN_SKIP, "LocalAlloc failed");
- }
- HANDLE hFind;
- WIN32_FIND_DATA fdRemote;
- PathCombine(szFullPath, pSyncData->szDrive, pszName + lstrlen(pSyncData->pszShareName));
- hFind = FindFirstFile(szFullPath, &fdRemote);
- // Does the net version still exist?
- if (hFind == INVALID_HANDLE_VALUE)
- ExitGracefully(dwResult, HandleDeleteConflict(pSyncData, pszName, dwStatus, dwHintFlags, pFind32), "Net file deleted");
- // Still exists, continue
- FindClose(hFind);
- // If only the attributes or file times were modified locally,
- // or if the file is hidden+system, keep the server copy and
- // don't bother the user. (e.g. desktop.ini)
- if (HandleConflictLocally(pSyncData, pszName, dwStatus, pFind32->dwFileAttributes, fdRemote.dwFileAttributes))
- {
- ExitGracefully(dwResult, CSCPROC_RETURN_FORCE_INWARD, "Ignoring conflict");
- }
- else if (IsSilentFolder(pszName))
- {
- // It's in a per-user shell special folder. Last writer wins.
- if (CompareFileTime(&pFind32->ftLastWriteTime, &fdRemote.ftLastWriteTime) < 0)
- {
- ExitGracefully(dwResult, CSCPROC_RETURN_FORCE_INWARD, "Handling special folder conflict - server copy wins");
- }
- else
- {
- ExitGracefully(dwResult, CSCPROC_RETURN_FORCE_OUTWARD, "Handling special folder conflict - local copy wins");
- }
- }
- dwErr = GetNewVersionName(pszName,
- pSyncData->pszShareName,
- pSyncData->szDrive,
- &pszNewName);
- if (NOERROR != dwErr)
- {
- ExitGracefully(dwResult, CSCPROC_RETURN_SKIP, "GetNewVersionName failed");
- }
- switch (SDS_SYNC_FILE_CONFLICT_MASK & pSyncData->dwSyncStatus)
- {
- case 0:
- if (CSC_SYNC_MAYBOTHERUSER & m_dwSyncFlags)
- {
- nErrorResolution = ShowConflictDialog(m_hwndDlgParent,
- pszName,
- pszNewName,
- pSyncData->pszShareName,
- pSyncData->szDrive,
- pFind32,
- &fdRemote);
- if (RFC_APPLY_TO_ALL & nErrorResolution)
- {
- bApplyToAll = TRUE;
- nErrorResolution &= ~RFC_APPLY_TO_ALL;
- }
- }
- break;
- case SDS_SYNC_CONFLICT_KEEPLOCAL:
- nErrorResolution = RFC_KEEPLOCAL;
- break;
- case SDS_SYNC_CONFLICT_KEEPNET:
- nErrorResolution = RFC_KEEPNETWORK;
- break;
- case SDS_SYNC_CONFLICT_KEEPBOTH:
- nErrorResolution = RFC_KEEPBOTH;
- break;
- }
- // Self-host notification callback
- CSCUI_NOTIFYHOOK((CSCH_UpdateConflict, TEXT("Update conflict: %1, resolution %2!d!"), pszName, nErrorResolution));
- switch (nErrorResolution)
- {
- default:
- case RFC_KEEPBOTH:
- if (bApplyToAll)
- pSyncData->dwSyncStatus |= SDS_SYNC_CONFLICT_KEEPBOTH;
- lstrcpy(szFullPath, pszName);
- PathRemoveFileSpec(szFullPath);
- if (FILE_ATTRIBUTE_DIRECTORY & pFind32->dwFileAttributes)
- {
- // Rename the local version in the cache and merge again.
- lstrcpyn(pFind32->cFileName, pszNewName, ARRAYSIZE(pFind32->cFileName));
- if (!CSCDoLocalRenameEx(pszName, szFullPath, pFind32, TRUE, TRUE))
- {
- dwErr = GetLastError();
- ExitGracefully(dwResult, CSCPROC_RETURN_SKIP, "CSCDoLocalRenameEx failed");
- }
- // Because CSCDoLocalRenameEx and CSCMergeShare are separate operations,
- // we have to abort the current merge operation and start over.
- // Otherwise, the current merge operation fails due to the "left
- // hand not knowing what the right hande is doing".
- Trace((TEXT("Restarting merge on: %s"), pSyncData->pszShareName));
- pSyncData->dwSyncStatus |= SDS_SYNC_RESTART_MERGE;
- dwResult = CSCPROC_RETURN_ABORT;
- }
- else
- {
- // Note that CSCDoLocalRenameEx would work for files also, but we
- // prefer to avoid restarting CSCMergeShare so do these ourselves.
- PathAppend(szFullPath, pszNewName);
- dwErr = CopyLocalFileWithDriveMapping(pszName,
- szFullPath,
- pSyncData->pszShareName,
- pSyncData->szDrive);
- if (NOERROR != dwErr)
- ExitGracefully(dwResult, CSCPROC_RETURN_SKIP, "CopyLocalFileWithDriveMapping failed");
- // If the original file was pinned, we want to pin the copy also.
- // Unfortunately, we can't reliably pin during a merge, so we have
- // to remember these in a list and pin them later.
- if (dwHintFlags & FLAG_CSC_HINT_PIN_USER)
- {
- if (!m_pConflictPinList)
- m_pConflictPinList = new CscFilenameList;
- if (m_pConflictPinList)
- {
- m_pConflictPinList->AddFile(szFullPath,
- !!(pFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
- }
- }
- // Tell CSCMergeShare to copy the server copy to the cache
- // (with the old name). This clears the dirty cache.
- dwResult = CSCPROC_RETURN_FORCE_INWARD;
- }
- break;
- case RFC_KEEPNETWORK:
- // Tell CSCMergeShare to copy the server copy to the cache
- dwResult = CSCPROC_RETURN_FORCE_INWARD;
- if (bApplyToAll)
- pSyncData->dwSyncStatus |= SDS_SYNC_CONFLICT_KEEPNET;
- break;
- case RFC_KEEPLOCAL:
- // Tell CSCMergeShare to push the local copy to the server
- dwResult = CSCPROC_RETURN_FORCE_OUTWARD;
- if (bApplyToAll)
- pSyncData->dwSyncStatus |= SDS_SYNC_CONFLICT_KEEPLOCAL;
- break;
- case RFC_CANCEL:
- TraceMsg("HandleFileConflict: Cancelling sync - user bailed");
- SetItemStatus(GUID_NULL, SYNCMGRSTATUS_STOPPED);
- dwResult = CSCPROC_RETURN_ABORT;
- break;
- }
- exit_gracefully:
- if (CSCPROC_RETURN_FORCE_INWARD == dwResult)
- {
- // CSCMergeShare truncates (makes sparse) the
- // file if we return this. We'd like to fill
- // it during this sync.
- pSyncData->cFilesToSync++;
- pSyncData->dwSyncStatus |= SDS_SYNC_FORCE_INWARD;
- }
- if (NOERROR != dwErr)
- {
- pszName += lstrlen(pSyncData->pszShareName);
- if (*pszName == TEXT('\'))
- pszName++;
- LogError(pSyncData->ItemID,
- IDS_NAME_CONFLICT_ERROR,
- pszName,
- dwErr);
- pSyncData->dwSyncStatus |= SDS_SYNC_ERROR;
- }
- LocalFreeString(&szFullPath);
- LocalFreeString(&pszNewName);
- TraceLeaveResult(dwResult);
- }
- // Returns values for the Resolve Delete Conflict dialog
- #define RDC_CANCEL 0x00
- #define RDC_DELETE 0x01
- #define RDC_RESTORE 0x02
- #define RDC_APPLY_ALL 0x04
- #define RDC_DELETE_ALL (RDC_APPLY_ALL | RDC_DELETE)
- #define RDC_RESTORE_ALL (RDC_APPLY_ALL | RDC_RESTORE)
- TCHAR const c_szDeleteSelection[] = TEXT("DeleteConflictSelection");
- INT_PTR CALLBACK
- DeleteConflictProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- int nResult;
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- TCHAR szShare[MAX_PATH];
- LPCTSTR pszPath = (LPCTSTR)lParam;
- LPTSTR pszT = NULL;
- szShare[0] = TEXT('');
- lstrcpyn(szShare, pszPath, ARRAYSIZE(szShare));
- PathStripToRoot(szShare);
- // Format the file name
- PathSetDlgItemPath(hDlg, IDC_FILENAME, pszPath);
- // Build the "Do this for all on <this share>" string
- FormatStringID(&pszT, g_hInstance, IDS_FMT_DELETE_APPLY_ALL, szShare);
- if (pszT)
- {
- SetDlgItemText(hDlg, IDC_APPLY_TO_ALL, pszT);
- LocalFreeString(&pszT);
- }
- // else default text is OK (no share name)
- // Select whatever the user chose last time, default is "restore"
- DWORD dwPrevSelection = RDC_RESTORE;
- DWORD dwType;
- DWORD cbData = sizeof(dwPrevSelection);
- SHGetValue(HKEY_CURRENT_USER,
- c_szCSCKey,
- c_szDeleteSelection,
- &dwType,
- &dwPrevSelection,
- &cbData);
- dwPrevSelection = (RDC_DELETE == dwPrevSelection ? IDC_DELETE_LOCAL : IDC_KEEP_LOCAL);
- CheckRadioButton(hDlg, IDC_KEEP_LOCAL, IDC_DELETE_LOCAL, dwPrevSelection);
- // Get the file-type icon
- pszT = PathFindExtension(pszPath);
- if (pszT)
- {
- SHFILEINFO sfi = {0};
- SHGetFileInfo(pszT, 0, &sfi, sizeof(sfi), SHGFI_ICON);
- if (sfi.hIcon)
- {
- SendDlgItemMessage(hDlg,
- IDC_DLGTYPEICON,
- STM_SETICON,
- (WPARAM)sfi.hIcon,
- 0L);
- }
- }
- }
- return TRUE;
- case WM_COMMAND:
- nResult = -1;
- switch (LOWORD(wParam))
- {
- case IDCANCEL:
- nResult = RDC_CANCEL;
- break;
- case IDOK:
- if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_DELETE_LOCAL))
- nResult = RDC_DELETE;
- else
- nResult = RDC_RESTORE;
- // Remember the selection for next time
- SHSetValue(HKEY_CURRENT_USER,
- c_szCSCKey,
- c_szDeleteSelection,
- REG_DWORD,
- &nResult,
- sizeof(nResult));
- if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_APPLY_TO_ALL))
- nResult |= RDC_APPLY_ALL;
- break;
- }
- if (-1 != nResult)
- {
- EndDialog(hDlg, nResult);
- return TRUE;
- }
- break;
- }
- return FALSE;
- }
- BOOL CALLBACK
- ConflictPurgeCallback(LPCWSTR /*pszFile*/, LPARAM lParam)
- {
- PSYNCTHREADDATA pSyncData = (PSYNCTHREADDATA)lParam;
- return !(SDS_SYNC_CANCELLED & pSyncData->dwSyncStatus);
- }
- DWORD
- CCscUpdate::HandleDeleteConflict(PSYNCTHREADDATA pSyncData,
- LPCTSTR pszName,
- DWORD dwStatus,
- DWORD dwHintFlags,
- LPWIN32_FIND_DATA pFind32)
- {
- DWORD dwResult = CSCPROC_RETURN_CONTINUE;
- int nErrorResolution = RDC_DELETE; // default action
- BOOL bDirectory = (FILE_ATTRIBUTE_DIRECTORY & pFind32->dwFileAttributes);
- TraceEnter(TRACE_UPDATE, "CCscUpdate::HandleDeleteConflict");
- Trace((TEXT("Net file deleted: %s"), pszName));
- //
- // We already know that the net file was deleted, or HandleDeleteConflict
- // wouldn't be called. If the local copy was also deleted, then there
- // isn't really a conflict and we can continue without prompting.
- //
- // If the file isn't pinned, handle the conflict silently if
- // only attributes changed or it's super-hidden.
- //
- // Finally, if the file lives in certain special folder locations,
- // such as AppData, handle the conflict silently.
- //
- // If we get past all that, ask the user what to do, but only bother
- // the user as a last resort.
- //
- if ( !(dwStatus & FLAG_CSC_COPY_STATUS_LOCALLY_DELETED)
- && ((dwHintFlags & (FLAG_CSC_HINT_PIN_USER | FLAG_CSC_HINT_PIN_ADMIN)) ||
- !HandleConflictLocally(pSyncData, pszName, dwStatus, pFind32->dwFileAttributes))
- && !IsSilentFolder(pszName)
- )
- {
- // The file is either pinned or modified locally, so
- // default action is now "restore".
- nErrorResolution = RDC_RESTORE;