Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2884 lines
78 KiB

  1. //==========================================================================
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright 1998 - 1999 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "precomp.h"
  12. extern UINT g_cRefThisDll; // Reference count of this DLL.
  13. extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
  14. extern CSettings *g_pSettings; // ptr to global settings class.
  15. //+---------------------------------------------------------------------------
  16. //
  17. // Member: CSyncMgrHandler::CSyncMgrHandler, public
  18. //
  19. // Synopsis: Constructor
  20. //
  21. // Arguments:
  22. //
  23. // Returns:
  24. //
  25. // Modifies:
  26. //
  27. //----------------------------------------------------------------------------
  28. CSyncMgrHandler::CSyncMgrHandler()
  29. {
  30. g_cRefThisDll++;
  31. m_cRef = 1;
  32. m_phThread = NULL;
  33. m_pSyncMgrSynchronizeCallback = NULL;
  34. m_pItemsToSyncList = NULL;
  35. m_dwSyncFlags = 0;
  36. m_hwndWorker = FALSE;
  37. m_hwndHandler = FALSE;
  38. m_fSynchronizing = FALSE;
  39. m_fPrepareForSync = FALSE;
  40. m_fStopped = FALSE;
  41. }
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Member: CSyncMgrHandler::~CSyncMgrHandler, public
  45. //
  46. // Synopsis: Destructor
  47. //
  48. // Arguments:
  49. //
  50. // Returns:
  51. //
  52. // Modifies:
  53. //
  54. //----------------------------------------------------------------------------
  55. CSyncMgrHandler::~CSyncMgrHandler()
  56. {
  57. Assert(NULL == m_pSyncMgrSynchronizeCallback);
  58. Assert(NULL == m_pItemsToSyncList);
  59. if (m_phThread)
  60. {
  61. HANDLE hThread = m_phThread;
  62. m_phThread = NULL;
  63. PostMessage(m_hwndWorker,WM_WORKERMSG_RELEASE,0,0);
  64. WaitForSingleObject(hThread,INFINITE); // wait for thread to go away
  65. CloseHandle(hThread);
  66. }
  67. if (m_hwndHandler)
  68. {
  69. DestroyWindow(m_hwndHandler);
  70. m_hwndHandler = NULL;
  71. }
  72. g_cRefThisDll--;
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Member: CSyncMgrHandler::QueryInteface, public
  77. //
  78. // Synopsis:
  79. //
  80. // Arguments:
  81. //
  82. // Returns:
  83. //
  84. // Modifies:
  85. //
  86. //----------------------------------------------------------------------------
  87. STDMETHODIMP CSyncMgrHandler::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  88. {
  89. *ppv = NULL;
  90. if (IsEqualIID(riid, IID_IUnknown))
  91. {
  92. *ppv = (LPUNKNOWN)this;
  93. }
  94. else if (IsEqualIID(riid, IID_ISyncMgrSynchronize))
  95. {
  96. *ppv = (LPSYNCMGRSYNCHRONIZE)this;
  97. }
  98. if (*ppv)
  99. {
  100. AddRef();
  101. return NOERROR;
  102. }
  103. return E_NOINTERFACE;
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Member: CSyncMgrHandler::AddRef, public
  108. //
  109. // Synopsis:
  110. //
  111. // Arguments:
  112. //
  113. // Returns:
  114. //
  115. // Modifies:
  116. //
  117. //----------------------------------------------------------------------------
  118. STDMETHODIMP_(ULONG) CSyncMgrHandler::AddRef()
  119. {
  120. return ++m_cRef;
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Member: CSyncMgrHandler::Release, public
  125. //
  126. // Synopsis:
  127. //
  128. // Arguments:
  129. //
  130. // Returns:
  131. //
  132. // Modifies:
  133. //
  134. //----------------------------------------------------------------------------
  135. STDMETHODIMP_(ULONG) CSyncMgrHandler::Release()
  136. {
  137. if (--m_cRef)
  138. return m_cRef;
  139. delete this;
  140. return 0L;
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Member: CSyncMgrHandler::Initialize, public
  145. //
  146. // Synopsis:
  147. //
  148. // Arguments:
  149. //
  150. // Returns:
  151. //
  152. // Modifies:
  153. //
  154. //----------------------------------------------------------------------------
  155. STDMETHODIMP CSyncMgrHandler::Initialize(DWORD dwReserved,DWORD dwSyncFlags,
  156. DWORD cbCookie,const BYTE *lpCooke)
  157. {
  158. HRESULT hr = NOERROR;
  159. m_dwSyncFlags = dwSyncFlags;
  160. RegisterHandlerWndClasses();
  161. // create hwnd for main class.
  162. m_hwndHandler = CreateWindowEx(0,
  163. SZ_SAMPLESYNCMGRHANDLERWNDCLASS,
  164. TEXT(""),
  165. // must use WS_POPUP so the window does not get
  166. // assigned a hot key by user.
  167. (WS_DISABLED | WS_POPUP),
  168. CW_USEDEFAULT,
  169. CW_USEDEFAULT,
  170. CW_USEDEFAULT,
  171. CW_USEDEFAULT,
  172. NULL,
  173. NULL,
  174. g_hmodThisDll,
  175. this);
  176. if (NULL == m_hwndHandler)
  177. {
  178. hr = E_UNEXPECTED;
  179. }
  180. if (NOERROR == hr)
  181. {
  182. hr = CreateWorkerThread();
  183. }
  184. // if hr is not NOERROR then clean up.
  185. if (NOERROR != hr)
  186. {
  187. if (m_phThread)
  188. {
  189. HANDLE hThread = m_phThread;
  190. m_phThread = NULL;
  191. PostMessage(m_hwndWorker,WM_WORKERMSG_RELEASE,0,0);
  192. WaitForSingleObject(hThread,INFINITE); // wait for thread to go away
  193. CloseHandle(hThread);
  194. }
  195. if (m_hwndHandler)
  196. {
  197. DestroyWindow(m_hwndHandler);
  198. m_hwndHandler = NULL;
  199. }
  200. }
  201. return hr;
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Member: CSyncMgrHandler::CreateWorkerThread, private
  206. //
  207. // Synopsis:
  208. //
  209. // Arguments:
  210. //
  211. // Returns:
  212. //
  213. // Modifies:
  214. //
  215. //----------------------------------------------------------------------------
  216. HRESULT CSyncMgrHandler::CreateWorkerThread()
  217. {
  218. HRESULT hr = E_FAIL;
  219. HANDLE hNewThread = NULL;
  220. DWORD dwThreadID;
  221. WorkerThreadArgs ThreadArgs;
  222. ThreadArgs.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  223. ThreadArgs.pThis = this;
  224. if (ThreadArgs.hEvent)
  225. {
  226. hNewThread = CreateThread(NULL,0,WorkerThread,&ThreadArgs,0,&dwThreadID);
  227. if (hNewThread)
  228. {
  229. WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
  230. if (NOERROR == ThreadArgs.hr)
  231. {
  232. m_hwndWorker = ThreadArgs.hwnd;
  233. m_phThread = hNewThread;
  234. hr = NOERROR;
  235. }
  236. else
  237. {
  238. CloseHandle(hNewThread);
  239. hr = ThreadArgs.hr;
  240. }
  241. }
  242. else
  243. {
  244. hr = GetLastError();
  245. }
  246. CloseHandle(ThreadArgs.hEvent);
  247. }
  248. return hr;
  249. }
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Member: CSyncMgrHandler::GetHandlerInfo, public
  253. //
  254. // Synopsis:
  255. //
  256. // Arguments:
  257. //
  258. // Returns:
  259. //
  260. // Modifies:
  261. //
  262. //----------------------------------------------------------------------------
  263. STDMETHODIMP CSyncMgrHandler::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
  264. {
  265. LPSYNCMGRHANDLERINFO pSyncInfo;
  266. if (!ppSyncMgrHandlerInfo)
  267. {
  268. Assert(ppSyncMgrHandlerInfo)
  269. return E_INVALIDARG;
  270. }
  271. pSyncInfo = (LPSYNCMGRHANDLERINFO) CoTaskMemAlloc(sizeof(SYNCMGRHANDLERINFO));
  272. if (pSyncInfo)
  273. {
  274. pSyncInfo->cbSize = sizeof(SYNCMGRHANDLERINFO);
  275. pSyncInfo->hIcon = LoadIcon(g_hmodThisDll,MAKEINTRESOURCE(IDI_SAMPLEHANDLERICON));
  276. pSyncInfo->SyncMgrHandlerFlags = SYNCMGRHANDLER_HASPROPERTIES;
  277. pSyncInfo->SyncMgrHandlerFlags |= SYNCMGRHANDLER_ALWAYSLISTHANDLER;
  278. lstrcpyW(pSyncInfo->wszHandlerName,L"Sample Handler");
  279. }
  280. *ppSyncMgrHandlerInfo = pSyncInfo;
  281. return *ppSyncMgrHandlerInfo ? NOERROR : E_OUTOFMEMORY;
  282. }
  283. //+---------------------------------------------------------------------------
  284. //
  285. // Member: CSyncMgrHandler::GetItemObject, public
  286. //
  287. // Synopsis:
  288. //
  289. // Arguments:
  290. //
  291. // Returns:
  292. //
  293. // Modifies:
  294. //
  295. //----------------------------------------------------------------------------
  296. STDMETHODIMP CSyncMgrHandler::GetItemObject(REFSYNCMGRITEMID ItemID,REFIID riid,void** ppv)
  297. {
  298. return E_NOTIMPL;
  299. }
  300. //+---------------------------------------------------------------------------
  301. //
  302. // Member: CSyncMgrHandler::EnumSyncMgrItems, public
  303. //
  304. // Synopsis:
  305. //
  306. // Arguments:
  307. //
  308. // Returns:
  309. //
  310. // Modifies:
  311. //
  312. //----------------------------------------------------------------------------
  313. STDMETHODIMP CSyncMgrHandler::EnumSyncMgrItems(ISyncMgrEnumItems** ppenumOffineItems)
  314. {
  315. Assert(g_pSettings);
  316. if (g_pSettings)
  317. {
  318. return g_pSettings->EnumSyncMgrItems(ppenumOffineItems);
  319. }
  320. return E_UNEXPECTED;
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Member: CSyncMgrHandler::ShowProperties, public
  325. //
  326. // Synopsis:
  327. //
  328. // Arguments:
  329. //
  330. // Returns:
  331. //
  332. // Modifies:
  333. //
  334. //----------------------------------------------------------------------------
  335. STDMETHODIMP CSyncMgrHandler::ShowProperties(HWND hWndParent,REFSYNCMGRITEMID ItemID)
  336. {
  337. METHODARGS *pMethodArgs;
  338. pMethodArgs = (METHODARGS*) ALLOC(sizeof(METHODARGS));
  339. if (NULL == pMethodArgs)
  340. {
  341. Assert(pMethodArgs);
  342. return E_OUTOFMEMORY;
  343. }
  344. pMethodArgs->fAsync = TRUE;
  345. pMethodArgs->dwWorkerMsg = WM_WORKERMSG_SHOWPROPERTIES;
  346. pMethodArgs->ShowPropertiesMsg.hWndParent = hWndParent;
  347. pMethodArgs->ShowPropertiesMsg.ItemID = ItemID;
  348. PostMessage(m_hwndWorker,WM_WORKERMSG_SHOWPROPERTIES,0,(LPARAM) pMethodArgs);
  349. return NOERROR;
  350. }
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Member: CSyncMgrHandler::ShowPropertiesCall, private
  354. //
  355. // Synopsis: Called on WorkerThread
  356. //
  357. // Arguments:
  358. //
  359. // Returns:
  360. //
  361. // Modifies:
  362. //
  363. //----------------------------------------------------------------------------
  364. void CSyncMgrHandler::ShowPropertiesCall(HWND hWndParent,REFSYNCMGRITEMID ItemID)
  365. {
  366. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  367. HRESULT hr = NOERROR;
  368. Assert(g_pSettings);
  369. if (g_pSettings)
  370. {
  371. hr = g_pSettings->ShowProperties(hWndParent,ItemID);
  372. }
  373. if (pCallback)
  374. {
  375. pCallback->ShowPropertiesCompleted(hr);
  376. pCallback->Release();
  377. }
  378. return;
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // Member: CSyncMgrHandler::SetProgressCallback, public
  383. //
  384. // Synopsis:
  385. //
  386. // Arguments:
  387. //
  388. // Returns:
  389. //
  390. // Modifies:
  391. //
  392. //----------------------------------------------------------------------------
  393. STDMETHODIMP CSyncMgrHandler::SetProgressCallback(ISyncMgrSynchronizeCallback *lpCallBack)
  394. {
  395. LPSYNCMGRSYNCHRONIZECALLBACK pCallbackCurrent;
  396. CLock clock(this);
  397. clock.Enter();
  398. pCallbackCurrent = m_pSyncMgrSynchronizeCallback;
  399. m_pSyncMgrSynchronizeCallback = lpCallBack;
  400. if (m_pSyncMgrSynchronizeCallback)
  401. m_pSyncMgrSynchronizeCallback->AddRef();
  402. if (pCallbackCurrent)
  403. pCallbackCurrent->Release();
  404. clock.Leave();
  405. return NOERROR;
  406. }
  407. //+---------------------------------------------------------------------------
  408. //
  409. // Member: CSyncMgrHandler::GetProgressCallback, private
  410. //
  411. // Synopsis:
  412. //
  413. // Arguments:
  414. //
  415. // Returns:
  416. //
  417. // Modifies:
  418. //
  419. //----------------------------------------------------------------------------
  420. LPSYNCMGRSYNCHRONIZECALLBACK CSyncMgrHandler::GetProgressCallback()
  421. {
  422. #ifdef _USECURRENTTHREADFORCALLBACK
  423. LPSYNCMGRSYNCHRONIZECALLBACK pCallback;
  424. CLock clock(this);
  425. clock.Enter();
  426. pCallback = m_pSyncMgrSynchronizeCallback;
  427. if (pCallback)
  428. {
  429. pCallback->AddRef();
  430. }
  431. clock.Leave();
  432. return pCallback;
  433. #else
  434. return new CCallbackWrapper(m_hwndHandler);
  435. #endif
  436. }
  437. //+---------------------------------------------------------------------------
  438. //
  439. // Member: CSyncMgrHandler::PrepareForSync, public
  440. //
  441. // Synopsis:
  442. //
  443. // Arguments:
  444. //
  445. // Returns:
  446. //
  447. // Modifies:
  448. //
  449. //----------------------------------------------------------------------------
  450. STDMETHODIMP CSyncMgrHandler::PrepareForSync(ULONG cbNumItems,SYNCMGRITEMID *pItemIDs,
  451. HWND hWndParent,DWORD dwReserved)
  452. {
  453. METHODARGS *pMethodArgs;
  454. SYNCMGRITEMID *pItemIdCopy;
  455. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  456. CLock clock(this);
  457. if (!pCallback)
  458. {
  459. Assert(pCallback);
  460. return E_UNEXPECTED;
  461. }
  462. pMethodArgs = (METHODARGS*) ALLOC(sizeof(METHODARGS));
  463. pItemIdCopy = (SYNCMGRITEMID *) ALLOC(sizeof(SYNCMGRITEMID) * cbNumItems);
  464. // create items list before kicking off async call so can handle case
  465. // skip and stop come in before PrepareForSyncCall is handled.
  466. clock.Enter();
  467. m_fStopped = FALSE; // always reset stop on a new PrepareForSync, (for example retry came in)
  468. m_fPrepareForSync = TRUE;
  469. Assert(NULL == m_pItemsToSyncList);
  470. m_pItemsToSyncList = CreateItemList();
  471. // lookup and request a lock on the items to synchronize
  472. // we then place the ones that we found and have permission into our
  473. // own private sync queue.
  474. if (g_pSettings && m_pItemsToSyncList)
  475. {
  476. ULONG ulIndex;
  477. SYNCMGRITEMID *pCurItemID;
  478. pCurItemID = pItemIDs;
  479. for (ulIndex = 0 ; ulIndex < cbNumItems; ++ulIndex)
  480. {
  481. BOOL fAdded = FALSE;;
  482. if (g_pSettings->RequestItemLock(this,*pCurItemID))
  483. {
  484. LPHANDLERITEM_SYNCSTATUS pNewItem;
  485. pNewItem = (LPHANDLERITEM_SYNCSTATUS) AddNewItemToList(m_pItemsToSyncList,sizeof(HANDLERITEM_SYNCSTATUS));
  486. if (pNewItem)
  487. {
  488. pNewItem->ItemID = *pCurItemID;
  489. fAdded = TRUE;
  490. }
  491. else
  492. {
  493. // not enough memory to allocate itemList,
  494. LogError(pCallback,(*pCurItemID),SYNCMGRLOGLEVEL_ERROR,
  495. TEXT("Not Enough Memory to Synchronize"));
  496. // update progress for this item
  497. ProgressSetItemStatusType(pCallback,(*pCurItemID),SYNCMGRSTATUS_FAILED);
  498. }
  499. }
  500. if (!fAdded)
  501. {
  502. // if another instance already syncing set progress
  503. // to complete since done but don't update statustext
  504. // so we dont' stomp the running instance.
  505. Progress(pCallback,(*pCurItemID),
  506. SYNCMGRPROGRESSITEM_PROGVALUE | SYNCMGRPROGRESSITEM_MAXVALUE,
  507. NULL,0,100,100);
  508. }
  509. ++pCurItemID;
  510. }
  511. }
  512. if (NULL == pMethodArgs || NULL == pItemIdCopy || NULL == m_pItemsToSyncList)
  513. {
  514. Assert(pMethodArgs);
  515. Assert(pItemIdCopy);
  516. if (pMethodArgs)
  517. {
  518. FREE(pMethodArgs);
  519. }
  520. if (pItemIdCopy)
  521. {
  522. FREE(pItemIdCopy);
  523. }
  524. if (m_pItemsToSyncList)
  525. {
  526. if (0 == Release_ItemList(m_pItemsToSyncList))
  527. {
  528. m_pItemsToSyncList = NULL;
  529. }
  530. }
  531. clock.Leave();
  532. pCallback->Release();
  533. m_fPrepareForSync = FALSE;
  534. return E_OUTOFMEMORY;
  535. }
  536. clock.Leave();
  537. // now make the async call
  538. pMethodArgs->fAsync = TRUE;
  539. pMethodArgs->dwWorkerMsg = WM_WORKERMSG_PREPFORSYNC;
  540. pMethodArgs->PrepareForSyncMsg.cbNumItems = cbNumItems;
  541. pMethodArgs->PrepareForSyncMsg.hWndParent = hWndParent;
  542. pMethodArgs->PrepareForSyncMsg.dwReserved = dwReserved;
  543. memcpy(pItemIdCopy,pItemIDs,sizeof(SYNCMGRITEMID) * cbNumItems);
  544. pMethodArgs->PrepareForSyncMsg.pItemIDs = pItemIdCopy;
  545. pCallback->Release();
  546. PostMessage(m_hwndWorker,WM_WORKERMSG_PREPFORSYNC,0,(LPARAM) pMethodArgs);
  547. return NOERROR;
  548. }
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Member: CSyncMgrHandler::PrepareForSyncCall, private
  552. //
  553. // Synopsis: Called on WorkerThread
  554. //
  555. // Arguments:
  556. //
  557. // Returns:
  558. //
  559. // Modifies:
  560. //
  561. //----------------------------------------------------------------------------
  562. void CSyncMgrHandler::PrepareForSyncCall(ULONG cbNumItems,SYNCMGRITEMID* pItemIDs,HWND hWndParent,
  563. DWORD dwReserved)
  564. {
  565. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  566. CLock clock(this);
  567. if (!pCallback)
  568. {
  569. Assert(pCallback);
  570. return;
  571. }
  572. clock.Enter();
  573. // if a stop came in then release the sync list if any
  574. if (m_fStopped && m_pItemsToSyncList)
  575. {
  576. if (0 == Release_ItemList(m_pItemsToSyncList))
  577. {
  578. m_pItemsToSyncList = NULL;
  579. }
  580. }
  581. m_fPrepareForSync = FALSE;
  582. clock.Leave();
  583. // currently all PrepareForSync is handled before the async call since we
  584. // just create a list and store it.
  585. pCallback->PrepareForSyncCompleted(NOERROR);
  586. pCallback->Release();
  587. return;
  588. }
  589. //+---------------------------------------------------------------------------
  590. //
  591. // Member: CSyncMgrHandler::Synchronize, public
  592. //
  593. // Synopsis:
  594. //
  595. // Arguments:
  596. //
  597. // Returns:
  598. //
  599. // Modifies:
  600. //
  601. //----------------------------------------------------------------------------
  602. STDMETHODIMP CSyncMgrHandler::Synchronize(HWND hWndParent)
  603. {
  604. METHODARGS *pMethodArgs;
  605. CLock clock(this);
  606. clock.Enter();
  607. m_fSynchronizing = TRUE;
  608. clock.Leave();
  609. pMethodArgs = (METHODARGS*) ALLOC(sizeof(METHODARGS));
  610. if (NULL == pMethodArgs)
  611. {
  612. Assert(pMethodArgs);
  613. return E_OUTOFMEMORY;
  614. }
  615. pMethodArgs->fAsync = TRUE;
  616. pMethodArgs->dwWorkerMsg = WM_WORKERMSG_SYNCHRONIZE;
  617. pMethodArgs->SynchronizeMsg.hWndParent = hWndParent;
  618. PostMessage(m_hwndWorker,WM_WORKERMSG_SYNCHRONIZE,0,(LPARAM) pMethodArgs);
  619. return NOERROR;
  620. }
  621. //+---------------------------------------------------------------------------
  622. //
  623. // Member: CSyncMgrHandler::SynchronizeCall, private
  624. //
  625. // Synopsis: Called on WorkerThread
  626. //
  627. // Arguments:
  628. //
  629. // Returns:
  630. //
  631. // Modifies:
  632. //
  633. //----------------------------------------------------------------------------
  634. void CSyncMgrHandler::SynchronizeCall(HWND hWndParent)
  635. {
  636. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  637. CLock clock(this);
  638. if (!pCallback)
  639. {
  640. Assert(pCallback);
  641. clock.Enter();
  642. m_fSynchronizing = FALSE;
  643. clock.Leave();
  644. return;
  645. }
  646. clock.Enter();
  647. // should either have a syncList or receive a Stop Item request.
  648. Assert(m_pItemsToSyncList || m_fStopped);
  649. if (m_pItemsToSyncList)
  650. {
  651. LPHANDLERITEM_SYNCSTATUS pCurItem;
  652. if (g_pSettings)
  653. {
  654. // get first item in the list, sync, remove, repeat
  655. // until no more items in the list.
  656. while (pCurItem = (LPHANDLERITEM_SYNCSTATUS)
  657. m_pItemsToSyncList->pFirstGenericItem)
  658. {
  659. FILETIME ft;
  660. SYSTEMTIME sysTime;
  661. HANDLERITEMSETTINGS HANDLERITEMSETTINGS;
  662. // if already cancelled such as setItemstatus came in while not synchronizing
  663. // then just skip over
  664. if (!pCurItem->fSynchronizeComplete)
  665. {
  666. Assert(sizeof(HANDLERITEM_SYNCSTATUS) == pCurItem->genericItem.cbSize);
  667. Assert(FALSE == pCurItem->fSynchronizing);
  668. if (g_pSettings->CopyHandlerSyncInfo(pCurItem->ItemID,&HANDLERITEMSETTINGS))
  669. {
  670. pCurItem->fSynchronizing = TRUE; // set synchronizing before releasing lock.
  671. // release lock and call call helper to do the real sync work.
  672. clock.Leave();
  673. SyncDirs(hWndParent,pCurItem,&HANDLERITEMSETTINGS);
  674. clock.Enter();
  675. // assert that noboday changed the state on us while
  676. // the sync was in progress.
  677. Assert(TRUE == pCurItem->fSynchronizing);
  678. Assert(FALSE == pCurItem->fSynchronizeComplete);
  679. pCurItem->fSynchronizing = FALSE;
  680. pCurItem->fSynchronizeComplete = TRUE;
  681. }
  682. // only update file time if item wasn't cancelled,
  683. // no failures occured and no
  684. // unresolved conflicts.
  685. if (!pCurItem->fUnresolvedConflicts && !pCurItem->fCancelled
  686. && (SYNCMGRSTATUS_SUCCEEDED == pCurItem->dwSyncMgrResultStatus) )
  687. {
  688. GetSystemTime(&sysTime);
  689. SystemTimeToFileTime(&sysTime,&ft);
  690. }
  691. else
  692. {
  693. ft = HANDLERITEMSETTINGS.ft;
  694. }
  695. // tell settings class we are done syncing.
  696. g_pSettings->ReleaseItemLock(this,pCurItem->ItemID,&ft);
  697. DeleteItemFromList(m_pItemsToSyncList, (LPGENERICITEM) pCurItem);
  698. }
  699. }
  700. }
  701. // release the item list if this is the last ref then null out
  702. // the member var
  703. if (0 == Release_ItemList(m_pItemsToSyncList))
  704. {
  705. m_pItemsToSyncList = NULL;
  706. }
  707. }
  708. m_fSynchronizing = FALSE;
  709. clock.Leave();
  710. if (pCallback)
  711. {
  712. pCallback->SynchronizeCompleted(NOERROR);
  713. pCallback->Release();
  714. }
  715. return;
  716. }
  717. //+---------------------------------------------------------------------------
  718. //
  719. // Member: CSyncMgrHandler::SetItemStatus, public
  720. //
  721. // Synopsis:
  722. //
  723. // Arguments:
  724. //
  725. // Returns:
  726. //
  727. // Modifies:
  728. //
  729. //----------------------------------------------------------------------------
  730. STDMETHODIMP CSyncMgrHandler::SetItemStatus(REFSYNCMGRITEMID ItemID,DWORD dwSyncMgrStatus)
  731. {
  732. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  733. CLock clock(this);
  734. if (!pCallback)
  735. {
  736. Assert(pCallback);
  737. return E_UNEXPECTED;
  738. }
  739. clock.Enter();
  740. if (m_pItemsToSyncList)
  741. {
  742. LPHANDLERITEM_SYNCSTATUS pCurItem = (LPHANDLERITEM_SYNCSTATUS) m_pItemsToSyncList->pFirstGenericItem;
  743. while (pCurItem)
  744. {
  745. LPHANDLERITEM_SYNCSTATUS pCurItemNext;
  746. pCurItemNext = (LPHANDLERITEM_SYNCSTATUS) pCurItem->genericItem.pNextGenericItem;
  747. Assert(sizeof(HANDLERITEM_SYNCSTATUS) == pCurItem->genericItem.cbSize);
  748. if ((SYNCMGRSTATUS_SKIPPED == dwSyncMgrStatus &&
  749. ItemID == pCurItem->ItemID)
  750. || SYNCMGRSTATUS_STOPPED == dwSyncMgrStatus)
  751. {
  752. pCurItem->fCancelled = TRUE;
  753. if (!pCurItem->fSynchronizeComplete)
  754. {
  755. pCurItem->dwSyncMgrResultStatus = dwSyncMgrStatus;
  756. }
  757. // if not currently synchronizing and synchronization is
  758. // not already done on this item set the progress accordingly
  759. if (!pCurItem->fSynchronizing && !pCurItem->fSynchronizeComplete)
  760. {
  761. ProgressSetItemStatusType(pCallback,pCurItem->ItemID,dwSyncMgrStatus);
  762. ProgressSetItemProgMaxValue(pCallback,pCurItem->ItemID,10);
  763. ProgressSetItemProgValue(pCallback,pCurItem->ItemID,10);
  764. pCurItem->fSynchronizeComplete = TRUE;
  765. // if we have a syncList
  766. // then delete the items from the list
  767. // and relesae the lock
  768. // Note: this code relies on PrepareForSync
  769. // not yielding while setting up item table.
  770. g_pSettings->ReleaseItemLock(this,pCurItem->ItemID);
  771. DeleteItemFromList(m_pItemsToSyncList, (LPGENERICITEM) pCurItem);
  772. }
  773. if (SYNCMGRSTATUS_SKIPPED == dwSyncMgrStatus)
  774. {
  775. break; // if skipped done when found a match.
  776. }
  777. }
  778. pCurItem = pCurItemNext;
  779. }
  780. }
  781. // if not in a synchronize or prepareForSync call when stop is
  782. // pressed release the itemList.
  783. if ((SYNCMGRSTATUS_STOPPED == dwSyncMgrStatus)
  784. && !m_fSynchronizing && !m_fPrepareForSync)
  785. {
  786. m_fStopped = TRUE;
  787. if (m_pItemsToSyncList)
  788. {
  789. if (0 == Release_ItemList(m_pItemsToSyncList))
  790. {
  791. m_pItemsToSyncList = NULL;
  792. }
  793. }
  794. }
  795. clock.Leave();
  796. pCallback->Release();
  797. return NOERROR;
  798. }
  799. //+---------------------------------------------------------------------------
  800. //
  801. // Member: CSyncMgrHandler::ShowError, public
  802. //
  803. // Synopsis:
  804. //
  805. // Arguments:
  806. //
  807. // Returns:
  808. //
  809. // Modifies:
  810. //
  811. //----------------------------------------------------------------------------
  812. STDMETHODIMP CSyncMgrHandler::ShowError(HWND hWndParent,REFSYNCMGRERRORID ErrorID)
  813. {
  814. METHODARGS *pMethodArgs;
  815. pMethodArgs = (METHODARGS*) ALLOC(sizeof(METHODARGS));
  816. if (NULL == pMethodArgs)
  817. {
  818. Assert(pMethodArgs);
  819. return E_OUTOFMEMORY;
  820. }
  821. pMethodArgs->fAsync = TRUE;
  822. pMethodArgs->dwWorkerMsg = WM_WORKERMSG_SHOWERROR;
  823. pMethodArgs->ShowErrorMsg.hWndParent = hWndParent;
  824. pMethodArgs->ShowErrorMsg.ErrorID = ErrorID;
  825. PostMessage(m_hwndWorker,WM_WORKERMSG_SHOWERROR,0,(LPARAM) pMethodArgs);
  826. return NOERROR;
  827. }
  828. //+---------------------------------------------------------------------------
  829. //
  830. // Member: CSyncMgrHandler::ShowErrorCall, private
  831. //
  832. // Synopsis: Called on Worker Thread
  833. //
  834. // Arguments:
  835. //
  836. // Returns:
  837. //
  838. // Modifies:
  839. //
  840. //----------------------------------------------------------------------------
  841. void CSyncMgrHandler::ShowErrorCall(HWND hWndParent,REFSYNCMGRERRORID ErrorID)
  842. {
  843. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  844. if (pCallback)
  845. {
  846. pCallback->ShowErrorCompleted(NOERROR,0,NULL);
  847. pCallback->Release();
  848. }
  849. return;
  850. }
  851. //+---------------------------------------------------------------------------
  852. //
  853. // Member: CSyncMgrHandler::Progress, private
  854. //
  855. // Synopsis: Helper method for sending progress information.
  856. //
  857. // Arguments:
  858. //
  859. // Returns:
  860. //
  861. // Modifies:
  862. //
  863. //----------------------------------------------------------------------------
  864. void CSyncMgrHandler::Progress(ISyncMgrSynchronizeCallback *lpCallBack,REFSYNCMGRITEMID pItemID,
  865. UINT mask,TCHAR *pStatusText,DWORD dwStatusType,
  866. int iProgValue,int iMaxValue)
  867. {
  868. SYNCMGRPROGRESSITEM syncProg;
  869. Assert(lpCallBack);
  870. syncProg.cbSize = sizeof(SYNCMGRPROGRESSITEM);
  871. syncProg.mask = mask;
  872. if (SYNCMGRPROGRESSITEM_STATUSTEXT & mask)
  873. {
  874. #ifdef _UNICODE
  875. syncProg.lpcStatusText = pStatusText;
  876. #else
  877. WCHAR wszStatusText[MAX_PATH];
  878. MultiByteToWideChar(CP_ACP, 0,
  879. pStatusText,
  880. -1, wszStatusText,MAX_PATH);
  881. syncProg.lpcStatusText = wszStatusText;
  882. #endif // _UNICODE
  883. }
  884. syncProg.dwStatusType = dwStatusType;
  885. syncProg.iProgValue = iProgValue;
  886. syncProg.iMaxValue = iMaxValue;
  887. lpCallBack->Progress(pItemID,&syncProg);
  888. }
  889. //+---------------------------------------------------------------------------
  890. //
  891. // Member: CSyncMgrHandler::ProgressSetItemStatusType, private
  892. //
  893. // Synopsis: Helper method for sending progress information.
  894. //
  895. // Arguments:
  896. //
  897. // Returns:
  898. //
  899. // Modifies:
  900. //
  901. //----------------------------------------------------------------------------
  902. void CSyncMgrHandler::ProgressSetItemStatusType(ISyncMgrSynchronizeCallback *lpCallBack,
  903. REFSYNCMGRITEMID pItemID,DWORD dwSyncMgrStatus)
  904. {
  905. Progress(lpCallBack,pItemID,SYNCMGRPROGRESSITEM_STATUSTYPE,
  906. NULL,dwSyncMgrStatus,0,0);
  907. }
  908. //+---------------------------------------------------------------------------
  909. //
  910. // Member: CSyncMgrHandler::ProgressSetItemStatusText, private
  911. //
  912. // Synopsis: Helper method for sending progress information.
  913. //
  914. // Arguments:
  915. //
  916. // Returns:
  917. //
  918. // Modifies:
  919. //
  920. //----------------------------------------------------------------------------
  921. void CSyncMgrHandler::ProgressSetItemStatusText(ISyncMgrSynchronizeCallback *lpCallBack,
  922. REFSYNCMGRITEMID pItemID,TCHAR *pStatusText)
  923. {
  924. Progress(lpCallBack,pItemID,SYNCMGRPROGRESSITEM_STATUSTEXT,
  925. pStatusText,0,0,0);
  926. }
  927. //+---------------------------------------------------------------------------
  928. //
  929. // Member: CSyncMgrHandler::ProgressSetItemProgValue, private
  930. //
  931. // Synopsis: Helper method for sending progress information.
  932. //
  933. // Arguments:
  934. //
  935. // Returns:
  936. //
  937. // Modifies:
  938. //
  939. //----------------------------------------------------------------------------
  940. void CSyncMgrHandler::ProgressSetItemProgValue(ISyncMgrSynchronizeCallback *lpCallBack,
  941. REFSYNCMGRITEMID pItemID,int iProgValue)
  942. {
  943. Progress(lpCallBack,pItemID,SYNCMGRPROGRESSITEM_PROGVALUE,
  944. NULL,0,iProgValue,0);
  945. }
  946. //+---------------------------------------------------------------------------
  947. //
  948. // Member: CSyncMgrHandler::ProgressSetItemMaxValue, private
  949. //
  950. // Synopsis: Helper method for sending progress information.
  951. //
  952. // Arguments:
  953. //
  954. // Returns:
  955. //
  956. // Modifies:
  957. //
  958. //----------------------------------------------------------------------------
  959. void CSyncMgrHandler::ProgressSetItemProgMaxValue(ISyncMgrSynchronizeCallback *lpCallBack,
  960. REFSYNCMGRITEMID pItemID,int iProgMaxValue)
  961. {
  962. Progress(lpCallBack,pItemID,SYNCMGRPROGRESSITEM_MAXVALUE,
  963. NULL,0,0,iProgMaxValue);
  964. }
  965. //+---------------------------------------------------------------------------
  966. //
  967. // Member: CSyncMgrHandler::LogError, private
  968. //
  969. // Synopsis: Helper method for logging Error information.
  970. //
  971. // Arguments:
  972. //
  973. // Returns:
  974. //
  975. // Modifies:
  976. //
  977. //----------------------------------------------------------------------------
  978. void CSyncMgrHandler::LogError(ISyncMgrSynchronizeCallback *lpCallBack,REFSYNCMGRITEMID pItemID,
  979. DWORD dwErrorLevel,TCHAR *lpErrorText,DWORD mask,DWORD dwSyncMgrErrorFlags,
  980. SYNCMGRERRORID ErrorID)
  981. {
  982. SYNCMGRLOGERRORINFO logError;
  983. WCHAR *pwszErrorText;
  984. Assert(lpCallBack);
  985. logError.cbSize = sizeof(SYNCMGRLOGERRORINFO);
  986. logError.mask = mask | SYNCMGRLOGERROR_ERRORID | SYNCMGRLOGERROR_ERRORFLAGS;
  987. logError.dwSyncMgrErrorFlags = dwSyncMgrErrorFlags | SYNCMGRERRORFLAG_ENABLEJUMPTEXT;
  988. logError.ErrorID = ErrorID;
  989. logError.ItemID = pItemID;
  990. #ifdef _UNICODE
  991. pwszErrorText = lpErrorText;
  992. #else
  993. WCHAR wszErrorText[MAX_PATH];
  994. MultiByteToWideChar(CP_ACP, 0,
  995. lpErrorText,
  996. -1, wszErrorText,MAX_PATH);
  997. pwszErrorText = wszErrorText;
  998. #endif // _UNICODE
  999. lpCallBack->LogError(dwErrorLevel,pwszErrorText,&logError);
  1000. }
  1001. //+---------------------------------------------------------------------------
  1002. //
  1003. // Member: CSyncMgrHandler::LogError, private
  1004. //
  1005. // Synopsis: Helper method for logging Error information.
  1006. //
  1007. // Arguments:
  1008. //
  1009. // Returns:
  1010. //
  1011. // Modifies:
  1012. //
  1013. //----------------------------------------------------------------------------
  1014. void CSyncMgrHandler::LogError(ISyncMgrSynchronizeCallback *lpCallBack,REFSYNCMGRITEMID pItemID,
  1015. DWORD dwErrorLevel,TCHAR *lpErrorText)
  1016. {
  1017. LogError(lpCallBack,pItemID,dwErrorLevel,lpErrorText,SYNCMGRLOGERROR_ITEMID,0,GUID_NULL);
  1018. }
  1019. //+---------------------------------------------------------------------------
  1020. //
  1021. // Member: CSyncMgrHandler::LogError, private
  1022. //
  1023. // Synopsis: Helper method for logging Error information.
  1024. //
  1025. // Arguments:
  1026. //
  1027. // Returns:
  1028. //
  1029. // Modifies:
  1030. //
  1031. //----------------------------------------------------------------------------
  1032. void CSyncMgrHandler::LogError(ISyncMgrSynchronizeCallback *lpCallBack,
  1033. DWORD dwErrorLevel,TCHAR *lpErrorText)
  1034. {
  1035. LogError(lpCallBack,GUID_NULL,dwErrorLevel,lpErrorText,0,0,GUID_NULL);
  1036. }
  1037. ////******
  1038. ///
  1039. // methods specific to this implementation to sync up file directories
  1040. //
  1041. ///*******
  1042. //+---------------------------------------------------------------------------
  1043. //
  1044. // Member: CSyncMgrHandler::GetFilesForDir, private
  1045. //
  1046. // Synopsis: creates a list of files for the given directory.
  1047. //
  1048. // Arguments:
  1049. //
  1050. // Returns:
  1051. //
  1052. // Modifies:
  1053. //
  1054. //----------------------------------------------------------------------------
  1055. LPFILEOBJECTLIST CSyncMgrHandler::GetFilesForDir(TCHAR *pDirName,BOOL fRecursive)
  1056. {
  1057. LPFILEOBJECTLIST pDirList;
  1058. HANDLE hFind;
  1059. BOOL bMore;
  1060. WIN32_FIND_DATA finddata;
  1061. TCHAR szSearch[MAX_PATH];
  1062. pDirList = CreateItemList();
  1063. if (!pDirList)
  1064. {
  1065. return NULL;
  1066. }
  1067. wsprintf(szSearch,TEXT("%s\\*.*"),pDirName);
  1068. hFind = FindFirstFile(szSearch, &finddata);
  1069. bMore = (hFind != (HANDLE) -1);
  1070. while (bMore) {
  1071. if ( (lstrcmp(finddata.cFileName, TEXT(".")) != 0) &&
  1072. ( lstrcmp(finddata.cFileName, TEXT("..")) != 0) )
  1073. {
  1074. LPFILEOBJECT pFileObject = (LPFILEOBJECT) AddNewItemToList(pDirList,sizeof(FILEOBJECT));
  1075. BOOL bIsDir;
  1076. if (!pFileObject) // if alloc ever fails just bail.
  1077. {
  1078. break;
  1079. }
  1080. // init the data.
  1081. lstrcpy(pFileObject->fName,finddata.cFileName);
  1082. bIsDir = (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TRUE : FALSE;
  1083. pFileObject->fDirectory = bIsDir;
  1084. if (!bIsDir)
  1085. {
  1086. HANDLE hFile;
  1087. FILETIME ftCreate;
  1088. FILETIME ftLastAccess;
  1089. // Review - need to check failure
  1090. // and if way to get modified with openning file.
  1091. wsprintf(szSearch,TEXT("%s\\%s"),pDirName,pFileObject->fName);
  1092. hFile = CreateFile(szSearch, GENERIC_READ, 0, NULL,
  1093. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1094. if (GetFileTime(hFile, &ftCreate,
  1095. &ftLastAccess,&(pFileObject->ftLastUpdate)) )
  1096. {
  1097. pFileObject->fLastUpdateValid = TRUE;
  1098. }
  1099. CloseHandle(hFile);
  1100. }
  1101. else
  1102. {
  1103. // if this is a directory and recursive, get children
  1104. if (fRecursive)
  1105. {
  1106. TCHAR szFullPath[MAX_PATH];
  1107. // fullpath is current dir name + \ + this dir name.
  1108. wsprintf(szFullPath,TEXT("%s\\%s"),pDirName,pFileObject->fName);
  1109. pFileObject->pChildList =
  1110. GetFilesForDir(szFullPath,fRecursive);
  1111. }
  1112. }
  1113. }
  1114. bMore = FindNextFile(hFind, &finddata);
  1115. }
  1116. FindClose(hFind);
  1117. return pDirList;
  1118. }
  1119. //+---------------------------------------------------------------------------
  1120. //
  1121. // Member: CSyncMgrHandler::CreateDirFileListFromPath, private
  1122. //
  1123. // Synopsis: creates a new FileObjectList for the given Directory
  1124. //
  1125. // Arguments:
  1126. //
  1127. // Returns:
  1128. //
  1129. // Modifies:
  1130. //
  1131. //----------------------------------------------------------------------------
  1132. LPFILEOBJECTLIST CSyncMgrHandler::CreateDirFileListFromPath(TCHAR *pDirName,BOOL fRecursive)
  1133. {
  1134. LPFILEOBJECTLIST pDirObj;
  1135. BOOL fValidDir = FALSE;
  1136. if (!IsValidDir(pDirName))
  1137. {
  1138. return NULL;
  1139. }
  1140. pDirObj = CreateItemList();
  1141. if (pDirObj)
  1142. {
  1143. LPFILEOBJECT pFileObject;
  1144. // go ahead and add this as the toplevel dir
  1145. pFileObject = (LPFILEOBJECT) AddNewItemToList(pDirObj,sizeof(FILEOBJECT));
  1146. if (pFileObject)
  1147. {
  1148. pFileObject->fDirectory = TRUE;
  1149. lstrcpy(pFileObject->fName,pDirName);
  1150. pFileObject->pChildList = GetFilesForDir(pFileObject->fName,fRecursive);
  1151. }
  1152. }
  1153. return pDirObj;
  1154. }
  1155. //+---------------------------------------------------------------------------
  1156. //
  1157. // Member: CSyncMgrHandler::ReleaseFileObjectList, private
  1158. //
  1159. // Synopsis: releases the fileobject list.
  1160. //
  1161. // Arguments:
  1162. //
  1163. // Returns:
  1164. //
  1165. // Modifies:
  1166. //
  1167. //----------------------------------------------------------------------------
  1168. void CSyncMgrHandler::ReleaseFileObjectList(LPFILEOBJECTLIST pfObjList,BOOL fRecursive)
  1169. {
  1170. LPFILEOBJECT pCurItem;
  1171. if (!pfObjList)
  1172. {
  1173. Assert(pfObjList)
  1174. return;
  1175. }
  1176. // see if object has any childs and free them if they do.
  1177. pCurItem= (LPFILEOBJECT) pfObjList->pFirstGenericItem;
  1178. while(pCurItem)
  1179. {
  1180. Assert(sizeof(FILEOBJECT ) == pCurItem->genericItem.cbSize);
  1181. if (pCurItem->fDirectory)
  1182. {
  1183. Assert(pCurItem->pChildList || (!fRecursive));
  1184. if (pCurItem->pChildList)
  1185. {
  1186. ReleaseFileObjectList(pCurItem->pChildList,fRecursive);
  1187. }
  1188. }
  1189. pCurItem = (LPFILEOBJECT) pCurItem->genericItem.pNextGenericItem;
  1190. }
  1191. Release_ItemList(pfObjList);
  1192. }
  1193. //+---------------------------------------------------------------------------
  1194. //
  1195. // Member: CSyncMgrHandler::CountNumberofFilesInList, private
  1196. //
  1197. // Synopsis: returns a total count of the number of items in the list.
  1198. //
  1199. // Arguments:
  1200. //
  1201. // Returns:
  1202. //
  1203. // Modifies:
  1204. //
  1205. //----------------------------------------------------------------------------
  1206. ULONG CSyncMgrHandler::CountNumberOfFilesInList(LPFILEOBJECTLIST pfObjList,BOOL fRecursive)
  1207. {
  1208. LPFILEOBJECT pCurItem;
  1209. ULONG ulTotalCount = 0;
  1210. if (!pfObjList)
  1211. {
  1212. Assert(pfObjList)
  1213. return 0;
  1214. }
  1215. // see if object has any childs and free them if they do.
  1216. pCurItem= (LPFILEOBJECT) pfObjList->pFirstGenericItem;
  1217. while(pCurItem)
  1218. {
  1219. Assert(sizeof(FILEOBJECT ) == pCurItem->genericItem.cbSize);
  1220. if (pCurItem->fDirectory)
  1221. {
  1222. Assert(pCurItem->pChildList || (!fRecursive));
  1223. if (pCurItem->pChildList)
  1224. {
  1225. ulTotalCount += CountNumberOfFilesInList(pCurItem->pChildList,fRecursive);
  1226. }
  1227. }
  1228. else
  1229. {
  1230. ++ulTotalCount;
  1231. }
  1232. pCurItem = (LPFILEOBJECT) pCurItem->genericItem.pNextGenericItem;
  1233. }
  1234. return ulTotalCount;
  1235. }
  1236. //+---------------------------------------------------------------------------
  1237. //
  1238. // Member: CSyncMgrHandler::FindFileItemWithName, private
  1239. //
  1240. // Synopsis: trys to find the items with with the specified filename in
  1241. // the fileobject list.
  1242. //
  1243. // Arguments:
  1244. //
  1245. // Returns:
  1246. //
  1247. // Modifies:
  1248. //
  1249. //----------------------------------------------------------------------------
  1250. LPFILEOBJECT CSyncMgrHandler::FindFileItemWithName(LPFILEOBJECTLIST pDir,TCHAR *pfName)
  1251. {
  1252. LPFILEOBJECT pCurItem = NULL;
  1253. if (!pDir)
  1254. {
  1255. Assert(pDir)
  1256. return NULL;
  1257. }
  1258. // see if object has any childs and free them if they do.
  1259. pCurItem= (LPFILEOBJECT) pDir->pFirstGenericItem;
  1260. while(pCurItem)
  1261. {
  1262. Assert(sizeof(FILEOBJECT ) == pCurItem->genericItem.cbSize);
  1263. if (0 == lstrcmp(pfName,pCurItem->fName))
  1264. {
  1265. break;
  1266. }
  1267. pCurItem = (LPFILEOBJECT) pCurItem->genericItem.pNextGenericItem;
  1268. }
  1269. return pCurItem;
  1270. }
  1271. //+---------------------------------------------------------------------------
  1272. //
  1273. // Member: CSyncMgrHandler::CopyfileFullPath, private
  1274. //
  1275. // Synopsis: copies file1 to file2 along with attribs.
  1276. //
  1277. // Arguments:
  1278. //
  1279. // Returns:
  1280. //
  1281. // Modifies:
  1282. //
  1283. //----------------------------------------------------------------------------
  1284. BOOL CSyncMgrHandler::CopyFileFullPath(TCHAR *pszFile1,TCHAR *pszFile2)
  1285. {
  1286. HANDLE hfile;
  1287. DWORD dwAttribs;
  1288. FILETIME ftCreate,ftLastAccess,ftLastWrite;
  1289. BOOL fOk;
  1290. fOk = CopyFile(pszFile1, pszFile2, FALSE);
  1291. if (fOk)
  1292. {
  1293. BOOL fFileTime = FALSE;
  1294. // having copied the file, now copy the times, attributes
  1295. // if fail to get go ahead and say copy succeeded.
  1296. hfile = CreateFile(pszFile1, GENERIC_READ, 0, NULL,
  1297. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1298. if (INVALID_HANDLE_VALUE != hfile)
  1299. {
  1300. fFileTime = GetFileTime(hfile, &ftCreate,
  1301. &ftLastAccess, &ftLastWrite);
  1302. CloseHandle(hfile);
  1303. }
  1304. if (fFileTime)
  1305. {
  1306. hfile = CreateFile(pszFile2, GENERIC_WRITE, 0, NULL,
  1307. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1308. if (INVALID_HANDLE_VALUE != hfile)
  1309. {
  1310. SetFileTime(hfile, &ftCreate,
  1311. &ftLastAccess,
  1312. &ftLastWrite);
  1313. CloseHandle(hfile);
  1314. }
  1315. }
  1316. // update attributes
  1317. dwAttribs = GetFileAttributes(pszFile1);
  1318. if (-1 != dwAttribs)
  1319. {
  1320. SetFileAttributes(pszFile2,dwAttribs);
  1321. }
  1322. }
  1323. return fOk;
  1324. }
  1325. //+---------------------------------------------------------------------------
  1326. //
  1327. // Member: CSyncMgrHandler::CopyFiles, private
  1328. //
  1329. // Synopsis: copies all files from dir1 to dir2
  1330. //
  1331. // Arguments:
  1332. //
  1333. // Returns:
  1334. //
  1335. // Modifies:
  1336. //
  1337. //----------------------------------------------------------------------------
  1338. void CSyncMgrHandler::CopyFiles( LPHANDLERITEM_SYNCSTATUS pHandlerItemID,
  1339. LPHANDLERITEMSETTINGS pHANDLERITEMSETTINGS,
  1340. LPSYNCMGRSYNCHRONIZECALLBACK pCallback,
  1341. DWORD *pdwCurProgValue,
  1342. TCHAR *pszDir1,
  1343. LPFILEOBJECTLIST pDir1,
  1344. TCHAR *pszDir2)
  1345. {
  1346. LPFILEOBJECT pCurDir1Item;
  1347. LPFILEOBJECT pNextDir1Item;
  1348. // anything left is list when done is unique and needs to be copied
  1349. // walk through each list moving the items.
  1350. pNextDir1Item = (LPFILEOBJECT) pDir1->pFirstGenericItem;
  1351. while(pNextDir1Item)
  1352. {
  1353. // each time through the loop check for if item is cancelled
  1354. // and if so return;
  1355. if (pHandlerItemID->fCancelled)
  1356. return;
  1357. Assert(sizeof(FILEOBJECT ) == pNextDir1Item->genericItem.cbSize);
  1358. pCurDir1Item = pNextDir1Item;
  1359. pNextDir1Item = (LPFILEOBJECT) pNextDir1Item->genericItem.pNextGenericItem;
  1360. if (pCurDir1Item->fDirectory)
  1361. {
  1362. if (pCurDir1Item->pChildList)
  1363. {
  1364. TCHAR szDir1[MAX_PATH];
  1365. TCHAR szDir2[MAX_PATH];
  1366. wsprintf(szDir1,TEXT("%s\\%s"),pszDir1,pCurDir1Item->fName);
  1367. wsprintf(szDir2,TEXT("%s\\%s"),pszDir2,pCurDir1Item->fName);
  1368. // create destination dir if necessary.
  1369. CreateDirectory(szDir2,NULL);
  1370. CopyFiles(pHandlerItemID,pHANDLERITEMSETTINGS,pCallback,pdwCurProgValue,
  1371. szDir1,pCurDir1Item->pChildList,szDir2);
  1372. }
  1373. }
  1374. else
  1375. {
  1376. TCHAR szFullPath1[MAX_PATH];
  1377. TCHAR szFullPath2[MAX_PATH];
  1378. TCHAR szProgress[MAX_PATH];
  1379. wsprintf(szProgress,TEXT("Copying %s"),pCurDir1Item->fName);
  1380. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,szProgress);
  1381. wsprintf(szFullPath1,TEXT("%s\\%s"),pszDir1,pCurDir1Item->fName);
  1382. wsprintf(szFullPath2,TEXT("%s\\%s"),pszDir2,pCurDir1Item->fName);
  1383. // copy the file over
  1384. if (FALSE == CopyFileFullPath(szFullPath1,szFullPath2))
  1385. {
  1386. wsprintf(szProgress,TEXT("Error Copying %s"),pCurDir1Item->fName);
  1387. LogError(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRLOGLEVEL_ERROR,
  1388. szProgress);
  1389. }
  1390. // update the progress bar value.
  1391. *pdwCurProgValue += 1;
  1392. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,*pdwCurProgValue);
  1393. // always release, even on
  1394. DeleteItemFromList(pDir1,(LPGENERICITEM) pCurDir1Item);
  1395. }
  1396. }
  1397. }
  1398. //+---------------------------------------------------------------------------
  1399. //
  1400. // Member: CSyncMgrHandler::reconcileDir, private
  1401. //
  1402. // Synopsis: does main job of reconciling dir1 and dir2
  1403. //
  1404. // Arguments:
  1405. //
  1406. // Returns:
  1407. //
  1408. // Modifies:
  1409. //
  1410. //----------------------------------------------------------------------------
  1411. void CSyncMgrHandler::ReconcileDir(HWND hWndParent,
  1412. LPHANDLERITEM_SYNCSTATUS pHandlerItemID,
  1413. LPHANDLERITEMSETTINGS pHANDLERITEMSETTINGS,
  1414. LPSYNCMGRSYNCHRONIZECALLBACK pCallback,
  1415. DWORD *pdwCurProgValue,
  1416. TCHAR *pszDir1,LPFILEOBJECTLIST pDir1,
  1417. TCHAR *pszDir2,LPFILEOBJECTLIST pDir2)
  1418. {
  1419. LPFILEOBJECT pCurDir1Item;
  1420. LPFILEOBJECT pCurDir1NextItem;
  1421. LPFILEOBJECT pCurDir2Item;
  1422. if (!pDir1 || !pDir2 || !pCallback)
  1423. {
  1424. Assert(pCallback);
  1425. Assert(pDir1);
  1426. Assert(pDir1);
  1427. return;
  1428. }
  1429. // loop through dir finding and comparing matches,
  1430. // if find matching dirs call ReconcileDir
  1431. pCurDir1NextItem= (LPFILEOBJECT) pDir1->pFirstGenericItem;
  1432. while(pCurDir1NextItem)
  1433. {
  1434. Assert(sizeof(FILEOBJECT ) == pCurDir1NextItem->genericItem.cbSize);
  1435. // each time through the loop check for if item is cancelled
  1436. // and if so return;
  1437. if (pHandlerItemID->fCancelled)
  1438. return;
  1439. pCurDir1Item = pCurDir1NextItem;
  1440. pCurDir1NextItem = (LPFILEOBJECT) pCurDir1Item->genericItem.pNextGenericItem;
  1441. pCurDir2Item = FindFileItemWithName(pDir2,pCurDir1Item->fName);
  1442. // if found match, deal with it, else leave in list and
  1443. // catch on the copy pass.
  1444. if (pCurDir2Item)
  1445. {
  1446. // if both directies
  1447. if (pCurDir1Item->fDirectory && pCurDir2Item->fDirectory)
  1448. {
  1449. if (pCurDir1Item->pChildList && pCurDir2Item->pChildList)
  1450. {
  1451. TCHAR szDir1[MAX_PATH];
  1452. TCHAR szDir2[MAX_PATH];
  1453. wsprintf(szDir1,TEXT("%s\\%s"),pszDir1,pCurDir1Item->fName);
  1454. wsprintf(szDir2,TEXT("%s\\%s"),pszDir2,pCurDir2Item->fName);
  1455. ReconcileDir(hWndParent,pHandlerItemID,pHANDLERITEMSETTINGS,
  1456. pCallback,
  1457. pdwCurProgValue,
  1458. szDir1,pCurDir1Item->pChildList,
  1459. szDir2,pCurDir2Item->pChildList);
  1460. }
  1461. else
  1462. {
  1463. // one of the directories didn't have a child list and
  1464. // one did.
  1465. if (pCurDir1Item->pChildList)
  1466. {
  1467. *pdwCurProgValue += CountNumberOfFilesInList(pCurDir1Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1468. ReleaseFileObjectList(pCurDir1Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1469. pCurDir1Item->pChildList = NULL;
  1470. }
  1471. *pdwCurProgValue += 1;
  1472. DeleteItemFromList(pDir1,(LPGENERICITEM) pCurDir1Item);
  1473. if (pCurDir2Item->pChildList)
  1474. {
  1475. *pdwCurProgValue += CountNumberOfFilesInList(pCurDir2Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1476. ReleaseFileObjectList(pCurDir2Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1477. pCurDir2Item->pChildList = NULL;
  1478. }
  1479. *pdwCurProgValue += 1;
  1480. DeleteItemFromList(pDir2,(LPGENERICITEM) pCurDir2Item);
  1481. // update the progress value.
  1482. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,*pdwCurProgValue);
  1483. }
  1484. }
  1485. else if (!pCurDir1Item->fDirectory && !pCurDir2Item->fDirectory)
  1486. {
  1487. FILETIME *pftLastUpdate = &(pHANDLERITEMSETTINGS->ft);
  1488. int iFileCompare;
  1489. BOOL fCopy = FALSE;
  1490. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,pCurDir1Item->fName);
  1491. // if filestimes are the same do nothing
  1492. // both filetimes are greater than < last sync time, conflict,
  1493. // else copy newer file over.
  1494. if (0 != (iFileCompare = CompareFileTime(&(pCurDir1Item->ftLastUpdate),&(pCurDir2Item->ftLastUpdate)) ))
  1495. {
  1496. int iFile1UpdateTimeCompare = CompareFileTime(&(pCurDir1Item->ftLastUpdate),pftLastUpdate);
  1497. int iFile2UpdateTimeCompare = CompareFileTime(&(pCurDir2Item->ftLastUpdate),pftLastUpdate);
  1498. if (iFile1UpdateTimeCompare == iFile2UpdateTimeCompare)
  1499. {
  1500. RFCDLGPARAM rfcParam;
  1501. int iResolution;
  1502. TCHAR szNetModifiedOnBuf[MAX_PATH];
  1503. TCHAR szLocalModifiedOnBuf[MAX_PATH];
  1504. // !!! Conflict
  1505. memset(&rfcParam,0,sizeof(RFCDLGPARAM));
  1506. rfcParam.dwFlags = 0;
  1507. rfcParam.pszFilename = pCurDir1Item->fName;
  1508. rfcParam.pszLocation = pszDir1;
  1509. rfcParam.pszNewName = pCurDir2Item->fName;
  1510. rfcParam.pszNetworkModifiedOn
  1511. = FormatDateTime(&(pCurDir1Item->ftLastUpdate),szNetModifiedOnBuf,sizeof(szNetModifiedOnBuf)/sizeof(TCHAR));
  1512. rfcParam.pszLocalModifiedOn
  1513. = FormatDateTime(&(pCurDir2Item->ftLastUpdate),szLocalModifiedOnBuf,sizeof(szLocalModifiedOnBuf)/sizeof(TCHAR));
  1514. // if can show UI call enable modeless, and show
  1515. // conflict dialog, else log and error and treat
  1516. // as if use chose to keep both.
  1517. if ( (m_dwSyncFlags & SYNCMGRFLAG_MAYBOTHERUSER)
  1518. && (S_OK == pCallback->EnableModeless(TRUE)) )
  1519. {
  1520. iResolution = SyncMgrResolveConflict(hWndParent,&rfcParam);
  1521. pCallback->EnableModeless(FALSE);
  1522. }
  1523. else
  1524. {
  1525. TCHAR szLogText[MAX_PATH];
  1526. iResolution = RFC_KEEPBOTH;
  1527. wsprintf(szLogText,TEXT("Conflict occured - %s"),pCurDir1Item->fName);
  1528. LogError(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRLOGLEVEL_WARNING,
  1529. szLogText);
  1530. }
  1531. switch (iResolution)
  1532. {
  1533. case RFC_KEEPNETWORK: // treat dir1 as network copy
  1534. iFileCompare = 1;
  1535. fCopy = TRUE;
  1536. break;
  1537. case RFC_KEEPLOCAL: // treat dir2 as local copy.
  1538. iFileCompare = - 1;
  1539. fCopy = TRUE;
  1540. break;
  1541. case RFC_KEEPBOTH: // if keep both wait until next sync.
  1542. default:
  1543. fCopy = FALSE;
  1544. pHandlerItemID->fUnresolvedConflicts = TRUE;
  1545. break;
  1546. }
  1547. }
  1548. else
  1549. {
  1550. fCopy = TRUE;
  1551. }
  1552. if (fCopy)
  1553. {
  1554. TCHAR szProgressText[MAX_PATH];
  1555. TCHAR szFile1FullPath[MAX_PATH],szFile2FullPath[MAX_PATH];
  1556. BOOL fOk;
  1557. wsprintf(szProgressText,TEXT("Updating %s"),pCurDir1Item->fName);
  1558. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,szProgressText);
  1559. wsprintf(szFile1FullPath,TEXT("%s\\%s"),pszDir1,pCurDir1Item->fName);
  1560. wsprintf(szFile2FullPath,TEXT("%s\\%s"),pszDir2,pCurDir2Item->fName);
  1561. // copy newer file.
  1562. if (0 < iFileCompare)
  1563. {
  1564. // 1 > 2.
  1565. fOk = CopyFileFullPath(szFile1FullPath,szFile2FullPath);
  1566. }
  1567. else
  1568. {
  1569. fOk = CopyFileFullPath(szFile2FullPath,szFile1FullPath);
  1570. }
  1571. }
  1572. }
  1573. // when done incmrement the progress value and release the items.
  1574. *pdwCurProgValue += 2; // incrent progress by 2 since we handled both files.
  1575. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,*pdwCurProgValue);
  1576. // always release, even on error since don't want copy to kick in.
  1577. DeleteItemFromList(pDir1,(LPGENERICITEM) pCurDir1Item);
  1578. DeleteItemFromList(pDir2,(LPGENERICITEM) pCurDir2Item);
  1579. }
  1580. else
  1581. {
  1582. TCHAR szLogError[MAX_PATH];
  1583. wsprintf(szLogError,TEXT("%s is a Directory in one location and file in another.")
  1584. ,pCurDir1Item->fName);
  1585. LogError(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRLOGLEVEL_ERROR,szLogError);
  1586. // release both dir and file.
  1587. if (pCurDir1Item->fDirectory && pCurDir1Item->pChildList)
  1588. {
  1589. *pdwCurProgValue += CountNumberOfFilesInList(pCurDir1Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1590. ReleaseFileObjectList(pCurDir1Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1591. pCurDir1Item->pChildList = NULL;
  1592. }
  1593. *pdwCurProgValue += 1;
  1594. DeleteItemFromList(pDir1,(LPGENERICITEM) pCurDir1Item);
  1595. if (pCurDir2Item->fDirectory && pCurDir2Item->pChildList)
  1596. {
  1597. *pdwCurProgValue += CountNumberOfFilesInList(pCurDir2Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1598. ReleaseFileObjectList(pCurDir2Item->pChildList,pHANDLERITEMSETTINGS->fRecursive);
  1599. pCurDir2Item->pChildList = NULL;
  1600. }
  1601. *pdwCurProgValue += 1;
  1602. DeleteItemFromList(pDir2, (LPGENERICITEM) pCurDir2Item);
  1603. // update the progress value.
  1604. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,*pdwCurProgValue);
  1605. }
  1606. }
  1607. }
  1608. // Anything left is a copy
  1609. // This sample doesn't properly handle the following cases
  1610. // 1) file has been deleted in one folder and not the other - next sync file will be
  1611. // copied back to folder it was delted from
  1612. // 2) File has been renamed in one folder and not the other - next sync both files will
  1613. // appear.
  1614. CopyFiles(pHandlerItemID,pHANDLERITEMSETTINGS,pCallback,pdwCurProgValue,pszDir1,pDir1,pszDir2);
  1615. CopyFiles(pHandlerItemID,pHANDLERITEMSETTINGS,pCallback,pdwCurProgValue,pszDir2,pDir2,pszDir1);
  1616. }
  1617. //+---------------------------------------------------------------------------
  1618. //
  1619. // Member: CSyncMgrHandler::SyncDirs, private
  1620. //
  1621. // Synopsis: Called by SynchronizeCall(). Sets up dirlists
  1622. // for synchronization and then calls the ReconcileDir function.
  1623. //
  1624. // Arguments:
  1625. //
  1626. // Returns:
  1627. //
  1628. // Modifies:
  1629. //
  1630. //----------------------------------------------------------------------------
  1631. void CSyncMgrHandler::SyncDirs(HWND hWndParent,LPHANDLERITEM_SYNCSTATUS pHandlerItemID,
  1632. LPHANDLERITEMSETTINGS pHANDLERITEMSETTINGS)
  1633. {
  1634. LPSYNCMGRSYNCHRONIZECALLBACK pCallback = GetProgressCallback();
  1635. LPFILEOBJECTLIST pfObjDir1 = NULL,pfObjDir2 = NULL;
  1636. ULONG ulProgressMaxValue = 0;
  1637. ULONG ulProgressCurValue = 0;
  1638. TCHAR szStatusText[MAX_PATH];
  1639. // if already cancelled go on.
  1640. if (pHandlerItemID->fCancelled)
  1641. goto synccomplete;
  1642. // synchronizing flag should be TRUE so SetItemStatus knows this is
  1643. Assert(TRUE == pHandlerItemID->fSynchronizing);
  1644. pHandlerItemID->dwSyncMgrResultStatus = SYNCMGRSTATUS_SUCCEEDED;
  1645. ProgressSetItemStatusType(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRSTATUS_UPDATING);
  1646. wsprintf(szStatusText,TEXT("Scanning %s"),pHANDLERITEMSETTINGS->dir1);
  1647. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,szStatusText);
  1648. pfObjDir1 = CreateDirFileListFromPath(pHANDLERITEMSETTINGS->dir1,
  1649. pHANDLERITEMSETTINGS->fRecursive);
  1650. if (pHandlerItemID->fCancelled)
  1651. goto synccomplete;
  1652. if (!pfObjDir1)
  1653. {
  1654. wsprintf(szStatusText,TEXT("Error Scanning %s"),pHANDLERITEMSETTINGS->dir1);
  1655. LogError(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRLOGLEVEL_ERROR,szStatusText);
  1656. pHandlerItemID->dwSyncMgrResultStatus = SYNCMGRSTATUS_FAILED;
  1657. }
  1658. else
  1659. {
  1660. wsprintf(szStatusText,TEXT("Scanning %s"),pHANDLERITEMSETTINGS->dir2);
  1661. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,szStatusText);
  1662. pfObjDir2 = CreateDirFileListFromPath(pHANDLERITEMSETTINGS->dir2,
  1663. pHANDLERITEMSETTINGS->fRecursive);
  1664. if (!pfObjDir2)
  1665. {
  1666. wsprintf(szStatusText,TEXT("Error Scanning %s"),pHANDLERITEMSETTINGS->dir2);
  1667. LogError(pCallback,pHANDLERITEMSETTINGS->ItemID,SYNCMGRLOGLEVEL_ERROR,szStatusText);
  1668. pHandlerItemID->dwSyncMgrResultStatus = SYNCMGRSTATUS_FAILED;
  1669. }
  1670. }
  1671. if (pHandlerItemID->fCancelled)
  1672. goto synccomplete;
  1673. if (pfObjDir1 && pfObjDir2)
  1674. {
  1675. // Calc the progress Item MaxValue which is the total
  1676. // number of items to sync.
  1677. ulProgressMaxValue += CountNumberOfFilesInList(pfObjDir1,pHANDLERITEMSETTINGS->fRecursive);
  1678. ulProgressMaxValue += CountNumberOfFilesInList(pfObjDir2,pHANDLERITEMSETTINGS->fRecursive);
  1679. ProgressSetItemProgMaxValue(pCallback,pHANDLERITEMSETTINGS->ItemID,ulProgressMaxValue);
  1680. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,0);
  1681. // want to kick Reconcil off pointing to childlist of each toplevel dir
  1682. if (pfObjDir1->pFirstGenericItem && pfObjDir2->pFirstGenericItem)
  1683. {
  1684. LPFILEOBJECTLIST pfObjStartDir1,pfObjStartDir2;
  1685. TCHAR *pszDir1Name,*pszDir2Name;
  1686. pfObjStartDir1 = ((LPFILEOBJECT) pfObjDir1->pFirstGenericItem)->pChildList;
  1687. pfObjStartDir2 = ((LPFILEOBJECT) pfObjDir2->pFirstGenericItem)->pChildList;
  1688. pszDir1Name = ((LPFILEOBJECT) pfObjDir1->pFirstGenericItem)->fName;
  1689. pszDir2Name = ((LPFILEOBJECT) pfObjDir2->pFirstGenericItem)->fName;
  1690. if (pfObjStartDir1 && pfObjStartDir2)
  1691. {
  1692. ReconcileDir(hWndParent,pHandlerItemID,pHANDLERITEMSETTINGS,pCallback,&ulProgressCurValue,
  1693. pszDir1Name,pfObjStartDir1,pszDir2Name,pfObjStartDir2);
  1694. }
  1695. }
  1696. }
  1697. synccomplete:
  1698. // set progress to max and clear status
  1699. ProgressSetItemProgValue(pCallback,pHANDLERITEMSETTINGS->ItemID,ulProgressMaxValue);
  1700. ProgressSetItemStatusText(pCallback,pHANDLERITEMSETTINGS->ItemID,TEXT(""));
  1701. // update item status based on result.
  1702. ProgressSetItemStatusType(pCallback,pHANDLERITEMSETTINGS->ItemID,pHandlerItemID->dwSyncMgrResultStatus);
  1703. if (pCallback)
  1704. {
  1705. pCallback->Release();
  1706. }
  1707. if (pfObjDir1)
  1708. {
  1709. ReleaseFileObjectList(pfObjDir1,pHANDLERITEMSETTINGS->fRecursive);
  1710. }
  1711. if (pfObjDir2)
  1712. {
  1713. ReleaseFileObjectList(pfObjDir2,pHANDLERITEMSETTINGS->fRecursive);
  1714. }
  1715. }
  1716. //+---------------------------------------------------------------------------
  1717. //
  1718. // Function: HandlerThreadWndProc, private
  1719. //
  1720. // Synopsis: WndProc for hwnd on thread handler was created on
  1721. //
  1722. // Arguments:
  1723. //
  1724. // Returns:
  1725. //
  1726. // Modifies:
  1727. //
  1728. //----------------------------------------------------------------------------
  1729. LRESULT CALLBACK HandlerThreadWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  1730. {
  1731. CSyncMgrHandler *pThis = (CSyncMgrHandler *) GetWindowLong(hWnd, DWL_THREADWNDPROCCLASS);
  1732. METHODARGS *pMethodArgs = (METHODARGS *) lParam;
  1733. BOOL fMethodCall = FALSE;
  1734. switch (msg)
  1735. {
  1736. case WM_CREATE :
  1737. {
  1738. CREATESTRUCT *pCreateStruct = (CREATESTRUCT *) lParam;
  1739. SetWindowLong(hWnd, DWL_THREADWNDPROCCLASS,(LONG) pCreateStruct->lpCreateParams );
  1740. pThis = (CSyncMgrHandler *) pCreateStruct->lpCreateParams ;
  1741. }
  1742. break;
  1743. case WM_DESTROY:
  1744. break;
  1745. case WM_WORKERMSG_PROGRESS:
  1746. Assert(pMethodArgs);
  1747. fMethodCall = TRUE;
  1748. if (pMethodArgs)
  1749. {
  1750. pMethodArgs->hr = E_UNEXPECTED;
  1751. if (pThis->m_pSyncMgrSynchronizeCallback)
  1752. {
  1753. PROGRESSMSG *pMsg = &(pMethodArgs->ProgressMsg);
  1754. Assert(msg == pMethodArgs->dwWorkerMsg);
  1755. pMethodArgs->hr =
  1756. pThis->m_pSyncMgrSynchronizeCallback->Progress(
  1757. pMsg->ItemID,
  1758. pMsg->lpSyncProgressItem);
  1759. }
  1760. Assert(!pMethodArgs->fAsync);
  1761. }
  1762. break;
  1763. case WM_WORKERMSG_PREPAREFORSYNCCOMPLETED:
  1764. Assert(pMethodArgs);
  1765. fMethodCall = TRUE;
  1766. if (pMethodArgs)
  1767. {
  1768. pMethodArgs->hr = E_UNEXPECTED;
  1769. if (pThis->m_pSyncMgrSynchronizeCallback)
  1770. {
  1771. PREPAREFORSYNCCOMPLETEDMSG *pMsg = &(pMethodArgs->PrepareForSyncCompletedMsg);
  1772. Assert(msg == pMethodArgs->dwWorkerMsg);
  1773. pMethodArgs->hr =
  1774. pThis->m_pSyncMgrSynchronizeCallback->PrepareForSyncCompleted(
  1775. pMsg->hr);
  1776. }
  1777. Assert(!pMethodArgs->fAsync);
  1778. }
  1779. break;
  1780. case WM_WORKERMSG_SYNCHRONIZECOMPLETED:
  1781. Assert(pMethodArgs);
  1782. fMethodCall = TRUE;
  1783. if (pMethodArgs)
  1784. {
  1785. pMethodArgs->hr = E_UNEXPECTED;
  1786. if (pThis->m_pSyncMgrSynchronizeCallback)
  1787. {
  1788. SYNCHRONIZECOMPLETEDMSG *pMsg = &(pMethodArgs->SynchronizeCompletedMsg);
  1789. Assert(msg == pMethodArgs->dwWorkerMsg);
  1790. pMethodArgs->hr =
  1791. pThis->m_pSyncMgrSynchronizeCallback->SynchronizeCompleted(
  1792. pMsg->hr);
  1793. }
  1794. Assert(!pMethodArgs->fAsync);
  1795. }
  1796. break;
  1797. case WM_WORKERMSG_SHOWPROPERTIESCOMPLETED:
  1798. Assert(pMethodArgs);
  1799. fMethodCall = TRUE;
  1800. if (pMethodArgs)
  1801. {
  1802. pMethodArgs->hr = E_UNEXPECTED;
  1803. if (pThis->m_pSyncMgrSynchronizeCallback)
  1804. {
  1805. SHOWPROPERTIESCOMPLETEDMSG *pMsg = &(pMethodArgs->ShowPropertiesCompletedMsg);
  1806. Assert(msg == pMethodArgs->dwWorkerMsg);
  1807. pMethodArgs->hr =
  1808. pThis->m_pSyncMgrSynchronizeCallback->ShowPropertiesCompleted(
  1809. pMsg->hr);
  1810. }
  1811. Assert(!pMethodArgs->fAsync);
  1812. }
  1813. break;
  1814. case WM_WORKERMSG_SHOWERRORCOMPLETED:
  1815. Assert(pMethodArgs);
  1816. fMethodCall = TRUE;
  1817. if (pMethodArgs)
  1818. {
  1819. pMethodArgs->hr = E_UNEXPECTED;
  1820. if (pThis->m_pSyncMgrSynchronizeCallback)
  1821. {
  1822. SHOWERRORCOMPLETEDMSG *pMsg = &(pMethodArgs->ShowErrorCompletedMsg);
  1823. Assert(msg == pMethodArgs->dwWorkerMsg);
  1824. pMethodArgs->hr =
  1825. pThis->m_pSyncMgrSynchronizeCallback->ShowErrorCompleted(
  1826. pMsg->hr,
  1827. pMsg->cbNumItems,
  1828. pMsg->pItemIDs
  1829. );
  1830. }
  1831. Assert(!pMethodArgs->fAsync);
  1832. }
  1833. break;
  1834. case WM_WORKERMSG_ENABLEMODELESS:
  1835. Assert(pMethodArgs);
  1836. fMethodCall = TRUE;
  1837. if (pMethodArgs)
  1838. {
  1839. pMethodArgs->hr = E_UNEXPECTED;
  1840. if (pThis->m_pSyncMgrSynchronizeCallback)
  1841. {
  1842. ENABLEMODELESSMSG *pMsg = &(pMethodArgs->EnableModelessMsg);
  1843. Assert(msg == pMethodArgs->dwWorkerMsg);
  1844. pMethodArgs->hr =
  1845. pThis->m_pSyncMgrSynchronizeCallback->EnableModeless(
  1846. pMsg->fEnable);
  1847. }
  1848. Assert(!pMethodArgs->fAsync);
  1849. }
  1850. break;
  1851. case WM_WORKERMSG_LOGERROR:
  1852. Assert(pMethodArgs);
  1853. fMethodCall = TRUE;
  1854. if (pMethodArgs)
  1855. {
  1856. pMethodArgs->hr = E_UNEXPECTED;
  1857. if (pThis->m_pSyncMgrSynchronizeCallback)
  1858. {
  1859. LOGERRORMSG *pMsg = &(pMethodArgs->LogErrorMsg);
  1860. Assert(msg == pMethodArgs->dwWorkerMsg);
  1861. pMethodArgs->hr =
  1862. pThis->m_pSyncMgrSynchronizeCallback->LogError(
  1863. pMsg->dwErrorLevel,
  1864. pMsg->lpcErrorText,
  1865. pMsg->lpSyncLogError);
  1866. }
  1867. Assert(!pMethodArgs->fAsync);
  1868. }
  1869. break;
  1870. case WM_WORKERMSG_DELETELOGERROR:
  1871. Assert(pMethodArgs);
  1872. fMethodCall = TRUE;
  1873. if (pMethodArgs)
  1874. {
  1875. pMethodArgs->hr = E_UNEXPECTED;
  1876. if (pThis->m_pSyncMgrSynchronizeCallback)
  1877. {
  1878. DELETELOGERRORMSG *pMsg = &(pMethodArgs->DeleteLogErrorMsg);
  1879. Assert(msg == pMethodArgs->dwWorkerMsg);
  1880. pMethodArgs->hr =
  1881. pThis->m_pSyncMgrSynchronizeCallback->DeleteLogError(
  1882. pMsg->ErrorID,
  1883. pMsg->dwReserved);
  1884. }
  1885. Assert(!pMethodArgs->fAsync);
  1886. }
  1887. break;
  1888. case WM_WORKERMSG_ESTABLISHCONNECTION:
  1889. Assert(pMethodArgs);
  1890. fMethodCall = TRUE;
  1891. if (pMethodArgs)
  1892. {
  1893. pMethodArgs->hr = E_UNEXPECTED;
  1894. if (pThis->m_pSyncMgrSynchronizeCallback)
  1895. {
  1896. ESTABLISHCONNECTIONMSG *pMsg = &(pMethodArgs->EstablishConnectionMsg);
  1897. Assert(msg == pMethodArgs->dwWorkerMsg);
  1898. pMethodArgs->hr =
  1899. pThis->m_pSyncMgrSynchronizeCallback->EstablishConnection(
  1900. pMsg->lpwszConnection,
  1901. pMsg->dwReserved
  1902. );
  1903. }
  1904. Assert(!pMethodArgs->fAsync);
  1905. }
  1906. break;
  1907. default:
  1908. break;
  1909. }
  1910. // if this was a method call and async then free methodArgs,
  1911. // on synchronous calls up to the caller to free.
  1912. if (fMethodCall && pMethodArgs && pMethodArgs->fAsync)
  1913. {
  1914. FREE(pMethodArgs);
  1915. }
  1916. return DefWindowProc(hWnd, msg, wParam, lParam);
  1917. }
  1918. //+---------------------------------------------------------------------------
  1919. //
  1920. // Function: WorkerThreadWndProc, private
  1921. //
  1922. // Synopsis: WndProc for hwnd on the worker thread.
  1923. //
  1924. // Arguments:
  1925. //
  1926. // Returns:
  1927. //
  1928. // Modifies:
  1929. //
  1930. //----------------------------------------------------------------------------
  1931. LRESULT CALLBACK WorkerThreadWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  1932. {
  1933. CSyncMgrHandler *pThis = (CSyncMgrHandler *) GetWindowLong(hWnd, DWL_THREADWNDPROCCLASS);
  1934. METHODARGS *pMethodArgs = (METHODARGS *) lParam;
  1935. BOOL fMethodCall = FALSE;
  1936. switch (msg)
  1937. {
  1938. case WM_CREATE :
  1939. {
  1940. CREATESTRUCT *pCreateStruct = (CREATESTRUCT *) lParam;
  1941. SetWindowLong(hWnd, DWL_THREADWNDPROCCLASS,(LONG) pCreateStruct->lpCreateParams );
  1942. pThis = (CSyncMgrHandler *) pCreateStruct->lpCreateParams ;
  1943. }
  1944. break;
  1945. case WM_DESTROY:
  1946. PostQuitMessage(0); // shut down this thread.
  1947. break;
  1948. case WM_WORKERMSG_SHOWPROPERTIES:
  1949. Assert(pMethodArgs);
  1950. fMethodCall = TRUE;
  1951. if (pMethodArgs)
  1952. {
  1953. SHOWPROPERTIESMSG *pShowPropertiesMsg = &(pMethodArgs->ShowPropertiesMsg);
  1954. Assert(WM_WORKERMSG_SHOWPROPERTIES == pMethodArgs->dwWorkerMsg);
  1955. pThis->ShowPropertiesCall(pShowPropertiesMsg->hWndParent,
  1956. pShowPropertiesMsg->ItemID);
  1957. Assert(pMethodArgs->fAsync);
  1958. }
  1959. break;
  1960. case WM_WORKERMSG_PREPFORSYNC:
  1961. Assert(pMethodArgs);
  1962. fMethodCall = TRUE;
  1963. if (pMethodArgs)
  1964. {
  1965. PREPAREFORSYNCMSG *pPrepareForSyncMsg = &(pMethodArgs->PrepareForSyncMsg);
  1966. Assert(WM_WORKERMSG_PREPFORSYNC == pMethodArgs->dwWorkerMsg);
  1967. pThis->PrepareForSyncCall(pPrepareForSyncMsg->cbNumItems,
  1968. pPrepareForSyncMsg->pItemIDs,
  1969. pPrepareForSyncMsg->hWndParent,
  1970. pPrepareForSyncMsg->dwReserved);
  1971. if (pPrepareForSyncMsg->pItemIDs)
  1972. {
  1973. FREE(pPrepareForSyncMsg->pItemIDs);
  1974. }
  1975. Assert(pMethodArgs->fAsync);
  1976. }
  1977. break;
  1978. case WM_WORKERMSG_SYNCHRONIZE:
  1979. Assert(pMethodArgs);
  1980. fMethodCall = TRUE;
  1981. if (pMethodArgs)
  1982. {
  1983. SYNCHRONIZEMSG *pSynchronizeMsg = &(pMethodArgs->SynchronizeMsg);
  1984. Assert(WM_WORKERMSG_SYNCHRONIZE == pMethodArgs->dwWorkerMsg);
  1985. Assert(pMethodArgs->fAsync);
  1986. pThis->SynchronizeCall(pSynchronizeMsg->hWndParent);
  1987. }
  1988. break;
  1989. case WM_WORKERMSG_SHOWERROR:
  1990. Assert(pMethodArgs);
  1991. fMethodCall = TRUE;
  1992. if (pMethodArgs)
  1993. {
  1994. SHOWERRORMSG *pShowErrorMsg = &(pMethodArgs->ShowErrorMsg);
  1995. Assert(pMethodArgs->fAsync);
  1996. Assert(WM_WORKERMSG_SHOWERROR == pMethodArgs->dwWorkerMsg);
  1997. pThis->ShowErrorCall(pShowErrorMsg->hWndParent,
  1998. pShowErrorMsg->ErrorID);
  1999. }
  2000. break;
  2001. case WM_WORKERMSG_RELEASE:
  2002. DestroyWindow(hWnd);
  2003. break;
  2004. default:
  2005. break;
  2006. }
  2007. // if this was a method call and async then free methodArgs,
  2008. // on synchronous calls up to the caller to free.
  2009. if (fMethodCall && pMethodArgs && pMethodArgs->fAsync)
  2010. {
  2011. FREE(pMethodArgs);
  2012. }
  2013. return DefWindowProc(hWnd, msg, wParam, lParam);
  2014. }
  2015. //+---------------------------------------------------------------------------
  2016. //
  2017. // Function: WorkerThread, private
  2018. //
  2019. // Synopsis: ThreadProc for WorkerThread.
  2020. //
  2021. // Arguments:
  2022. //
  2023. // Returns:
  2024. //
  2025. // Modifies:
  2026. //
  2027. //----------------------------------------------------------------------------
  2028. DWORD WINAPI WorkerThread( LPVOID lpArg )
  2029. {
  2030. MSG msg;
  2031. HRESULT hr;
  2032. HRESULT hrCoInitialize;
  2033. WorkerThreadArgs *pThreadArgs = (WorkerThreadArgs *) lpArg;
  2034. HWND hwndWorker;
  2035. pThreadArgs->hr = NOERROR;
  2036. hrCoInitialize = CoInitialize(NULL);
  2037. // need to do a PeekMessage and then set an event to make sure
  2038. // a message loop is created before the first PostMessage is sent.
  2039. PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  2040. // initialize the dialog box before returning to main thread.
  2041. if (FAILED(hrCoInitialize) )
  2042. {
  2043. pThreadArgs->hr = E_OUTOFMEMORY;
  2044. }
  2045. else
  2046. {
  2047. hwndWorker = CreateWindowEx(0,
  2048. SZ_SAMPLESYNCMGRWORKERWNDCLASS,
  2049. TEXT(""),
  2050. // must use WS_POPUP so the window does not get
  2051. // assigned a hot key by user.
  2052. (WS_DISABLED | WS_POPUP),
  2053. CW_USEDEFAULT,
  2054. CW_USEDEFAULT,
  2055. CW_USEDEFAULT,
  2056. CW_USEDEFAULT,
  2057. NULL,
  2058. NULL,
  2059. g_hmodThisDll,
  2060. pThreadArgs->pThis);
  2061. pThreadArgs->hwnd = hwndWorker;
  2062. pThreadArgs->hr = hwndWorker ? NOERROR : E_UNEXPECTED;
  2063. }
  2064. hr = pThreadArgs->hr;
  2065. // let the caller know the thread is done initializing.
  2066. if (pThreadArgs->hEvent)
  2067. SetEvent(pThreadArgs->hEvent);
  2068. if (NOERROR == hr)
  2069. {
  2070. // sit in loop receiving messages.
  2071. while (GetMessage(&msg, NULL, 0, 0))
  2072. {
  2073. TranslateMessage(&msg);
  2074. DispatchMessage(&msg);
  2075. }
  2076. }
  2077. if (SUCCEEDED(hrCoInitialize))
  2078. CoUninitialize();
  2079. return 0;
  2080. }
  2081. BOOL g_fWndRegistered = FALSE;
  2082. BOOL RegisterHandlerWndClasses(void)
  2083. {
  2084. if (!g_fWndRegistered)
  2085. {
  2086. ATOM aWndClass;
  2087. WNDCLASS xClass;
  2088. // register class for window created on handler thread.
  2089. xClass.style = 0;
  2090. xClass.lpfnWndProc = HandlerThreadWndProc;
  2091. xClass.cbClsExtra = 0;
  2092. xClass.cbWndExtra = sizeof(DWORD); // room for class this ptr
  2093. xClass.hInstance = g_hmodThisDll;
  2094. xClass.hIcon = NULL;
  2095. xClass.hCursor = NULL;
  2096. xClass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  2097. xClass.lpszMenuName = NULL;
  2098. xClass.lpszClassName = SZ_SAMPLESYNCMGRHANDLERWNDCLASS;
  2099. aWndClass = RegisterClass( &xClass );
  2100. // Register windows class.we need for handling thread communication
  2101. xClass.style = 0;
  2102. xClass.lpfnWndProc = WorkerThreadWndProc;
  2103. xClass.cbClsExtra = 0;
  2104. xClass.cbWndExtra = sizeof(DWORD); // room for class this ptr
  2105. xClass.hInstance = g_hmodThisDll;
  2106. xClass.hIcon = NULL;
  2107. xClass.hCursor = NULL;
  2108. xClass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  2109. xClass.lpszMenuName = NULL;
  2110. xClass.lpszClassName = SZ_SAMPLESYNCMGRWORKERWNDCLASS;
  2111. aWndClass = RegisterClass( &xClass );
  2112. g_fWndRegistered = TRUE;
  2113. }
  2114. return g_fWndRegistered;
  2115. }
  2116. // implementation of callback wrappers so all callback calls are sent to
  2117. // syncmgr on the thread we were created on. We only implement the
  2118. // methods we call.
  2119. CCallbackWrapper::CCallbackWrapper(HWND hwndCallback)
  2120. {
  2121. Assert(hwndCallback);
  2122. m_hwndCallback = hwndCallback;
  2123. m_cRef = 1;
  2124. }
  2125. CCallbackWrapper::~CCallbackWrapper()
  2126. {
  2127. m_hwndCallback = NULL;
  2128. Assert(0 == m_cRef);
  2129. }
  2130. //IUnknown methods
  2131. STDMETHODIMP CCallbackWrapper::QueryInterface(REFIID, LPVOID FAR *)
  2132. {
  2133. return E_NOTIMPL;
  2134. }
  2135. STDMETHODIMP_(ULONG) CCallbackWrapper::AddRef()
  2136. {
  2137. ++m_cRef;
  2138. return m_cRef;
  2139. }
  2140. STDMETHODIMP_(ULONG) CCallbackWrapper::Release()
  2141. {
  2142. DWORD cRefs;
  2143. --m_cRef;
  2144. cRefs = m_cRef;
  2145. if (0 == m_cRef)
  2146. {
  2147. delete this;
  2148. }
  2149. return cRefs;
  2150. }
  2151. // Callback methods.
  2152. STDMETHODIMP CCallbackWrapper::Progress(REFSYNCMGRITEMID ItemID,LPSYNCMGRPROGRESSITEM lpSyncProgressItem)
  2153. {
  2154. METHODARGS MethodArgs;
  2155. MethodArgs.fAsync = FALSE;
  2156. MethodArgs.hr = E_UNEXPECTED;
  2157. MethodArgs.dwWorkerMsg = WM_WORKERMSG_PROGRESS;
  2158. MethodArgs.ProgressMsg.ItemID = ItemID;
  2159. MethodArgs.ProgressMsg.lpSyncProgressItem = lpSyncProgressItem;
  2160. if (m_hwndCallback)
  2161. {
  2162. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2163. }
  2164. return MethodArgs.hr;
  2165. }
  2166. STDMETHODIMP CCallbackWrapper::PrepareForSyncCompleted(HRESULT hr)
  2167. {
  2168. METHODARGS MethodArgs;
  2169. MethodArgs.fAsync = FALSE;
  2170. MethodArgs.hr = E_UNEXPECTED;
  2171. MethodArgs.dwWorkerMsg = WM_WORKERMSG_PREPAREFORSYNCCOMPLETED;
  2172. MethodArgs.PrepareForSyncCompletedMsg.hr = hr;
  2173. if (m_hwndCallback)
  2174. {
  2175. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2176. }
  2177. return MethodArgs.hr;
  2178. }
  2179. STDMETHODIMP CCallbackWrapper::SynchronizeCompleted(HRESULT hr)
  2180. {
  2181. METHODARGS MethodArgs;
  2182. MethodArgs.fAsync = FALSE;
  2183. MethodArgs.hr = E_UNEXPECTED;
  2184. MethodArgs.dwWorkerMsg = WM_WORKERMSG_SYNCHRONIZECOMPLETED;
  2185. MethodArgs.SynchronizeCompletedMsg.hr = hr;
  2186. if (m_hwndCallback)
  2187. {
  2188. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2189. }
  2190. return MethodArgs.hr;
  2191. }
  2192. STDMETHODIMP CCallbackWrapper::ShowPropertiesCompleted(HRESULT hr)
  2193. {
  2194. METHODARGS MethodArgs;
  2195. MethodArgs.fAsync = FALSE;
  2196. MethodArgs.hr = E_UNEXPECTED;
  2197. MethodArgs.dwWorkerMsg = WM_WORKERMSG_SHOWPROPERTIESCOMPLETED;
  2198. MethodArgs.ShowPropertiesCompletedMsg.hr = hr;
  2199. if (m_hwndCallback)
  2200. {
  2201. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2202. }
  2203. return MethodArgs.hr;
  2204. }
  2205. STDMETHODIMP CCallbackWrapper::ShowErrorCompleted(HRESULT hr,ULONG cbNumItems,SYNCMGRITEMID *pItemIDs)
  2206. {
  2207. METHODARGS MethodArgs;
  2208. MethodArgs.fAsync = FALSE;
  2209. MethodArgs.hr = E_UNEXPECTED;
  2210. MethodArgs.dwWorkerMsg = WM_WORKERMSG_SHOWERRORCOMPLETED;
  2211. MethodArgs.ShowErrorCompletedMsg.hr = hr;
  2212. MethodArgs.ShowErrorCompletedMsg.cbNumItems = cbNumItems;
  2213. MethodArgs.ShowErrorCompletedMsg.pItemIDs = pItemIDs;
  2214. if (m_hwndCallback)
  2215. {
  2216. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2217. }
  2218. return MethodArgs.hr;
  2219. }
  2220. STDMETHODIMP CCallbackWrapper::EnableModeless(BOOL fEnable)
  2221. {
  2222. METHODARGS MethodArgs;
  2223. MethodArgs.fAsync = FALSE;
  2224. MethodArgs.hr = E_UNEXPECTED;
  2225. MethodArgs.dwWorkerMsg = WM_WORKERMSG_ENABLEMODELESS;
  2226. MethodArgs.EnableModelessMsg.fEnable = fEnable;
  2227. if (m_hwndCallback)
  2228. {
  2229. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2230. }
  2231. return MethodArgs.hr;
  2232. }
  2233. STDMETHODIMP CCallbackWrapper::LogError(DWORD dwErrorLevel,const WCHAR *lpcErrorText,LPSYNCMGRLOGERRORINFO lpSyncLogError)
  2234. {
  2235. METHODARGS MethodArgs;
  2236. MethodArgs.fAsync = FALSE;
  2237. MethodArgs.hr = E_UNEXPECTED;
  2238. MethodArgs.dwWorkerMsg = WM_WORKERMSG_LOGERROR;
  2239. MethodArgs.LogErrorMsg.dwErrorLevel = dwErrorLevel;
  2240. MethodArgs.LogErrorMsg.lpcErrorText = lpcErrorText;
  2241. MethodArgs.LogErrorMsg.lpSyncLogError = lpSyncLogError;
  2242. if (m_hwndCallback)
  2243. {
  2244. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2245. }
  2246. return MethodArgs.hr;
  2247. }
  2248. STDMETHODIMP CCallbackWrapper::DeleteLogError(REFSYNCMGRERRORID ErrorID,DWORD dwReserved)
  2249. {
  2250. METHODARGS MethodArgs;
  2251. MethodArgs.fAsync = FALSE;
  2252. MethodArgs.hr = E_UNEXPECTED;
  2253. MethodArgs.dwWorkerMsg = WM_WORKERMSG_DELETELOGERROR;
  2254. MethodArgs.DeleteLogErrorMsg.ErrorID = ErrorID;
  2255. MethodArgs.DeleteLogErrorMsg.dwReserved = dwReserved;
  2256. if (m_hwndCallback)
  2257. {
  2258. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2259. }
  2260. return MethodArgs.hr;
  2261. }
  2262. STDMETHODIMP CCallbackWrapper::EstablishConnection( WCHAR const * lpwszConnection, DWORD dwReserved)
  2263. {
  2264. METHODARGS MethodArgs;
  2265. MethodArgs.fAsync = FALSE;
  2266. MethodArgs.hr = E_UNEXPECTED;
  2267. MethodArgs.dwWorkerMsg = WM_WORKERMSG_ESTABLISHCONNECTION;
  2268. MethodArgs.EstablishConnectionMsg.lpwszConnection = lpwszConnection;
  2269. MethodArgs.EstablishConnectionMsg.dwReserved = dwReserved;
  2270. if (m_hwndCallback)
  2271. {
  2272. SendMessage(m_hwndCallback,MethodArgs.dwWorkerMsg,0,(LPARAM) &MethodArgs);
  2273. }
  2274. return MethodArgs.hr;
  2275. }