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.

1385 lines
36 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Hndlrmsg.cpp
  7. //
  8. // Contents: Takes care of handler specific messages
  9. //
  10. // Classes: CHndlrMsg
  11. //
  12. // Notes:
  13. //
  14. // History: 05-Nov-97 rogerg Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "precomp.h"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CHndlrMsg::CHndlrMsg, public
  21. //
  22. // Synopsis: Constructor
  23. //
  24. // Arguments:
  25. //
  26. // Returns:
  27. //
  28. // Modifies:
  29. //
  30. // History: 05-Nov-97 rogerg Created.
  31. //
  32. //----------------------------------------------------------------------------
  33. CHndlrMsg::CHndlrMsg()
  34. {
  35. m_pOneStopHandler = NULL;
  36. m_pOldOneStopHandler = NULL;
  37. m_dwSyncFlags = 0;
  38. m_pCallBack = NULL;
  39. m_cRef = 1;
  40. m_fDead = FALSE;
  41. m_fForceKilled = FALSE;
  42. m_dwNestCount = 0;
  43. m_fThreadInputAttached = FALSE;
  44. m_itemIDShowProperties = GUID_NULL;
  45. m_dwProxyThreadId = -1;
  46. m_dwThreadId = GetCurrentThreadId();
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // Member: CHndlrMsg::~CHndlrMsg, public
  51. //
  52. // Synopsis: Destructor
  53. //
  54. // Arguments:
  55. //
  56. // Returns:
  57. //
  58. // Modifies:
  59. //
  60. // History: 05-Nov-97 rogerg Created.
  61. //
  62. //----------------------------------------------------------------------------
  63. CHndlrMsg::~CHndlrMsg()
  64. {
  65. Assert(m_dwThreadId == GetCurrentThreadId() || m_fForceKilled);
  66. Assert(0 == m_dwNestCount || m_fForceKilled);
  67. Assert(0 == m_cRef || m_fForceKilled);
  68. }
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Member: CHndlrMsg::QueryInterface, public
  72. //
  73. // Synopsis: Standard QueryInterface
  74. //
  75. // Arguments: [iid] - Interface ID
  76. // [ppvObj] - Object return
  77. //
  78. // Returns: Appropriate status code
  79. //
  80. // Modifies: [ppvObj]
  81. //
  82. // History: 05-Nov-97 rogerg Created.
  83. //
  84. //----------------------------------------------------------------------------
  85. STDMETHODIMP CHndlrMsg::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  86. {
  87. Assert(m_dwThreadId == GetCurrentThreadId());
  88. Assert(0 == m_dwNestCount);
  89. return E_NOINTERFACE;
  90. }
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Member: CHndlrMsg::AddRef, public
  94. //
  95. // Synopsis: Add reference
  96. //
  97. // History: 05-Nov-97 rogerg Created.
  98. //
  99. //----------------------------------------------------------------------------
  100. STDMETHODIMP_(ULONG) CHndlrMsg::AddRef()
  101. {
  102. ULONG cRefs;
  103. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  104. Assert(m_dwThreadId == GetCurrentThreadId());
  105. Assert(0 == m_dwNestCount);
  106. m_dwNestCount++;
  107. cRefs = InterlockedIncrement((LONG *)& m_cRef);
  108. m_dwNestCount--;
  109. return cRefs;
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Member: CHndlrMsg::Release, public
  114. //
  115. // Synopsis: Release reference
  116. //
  117. // History: 05-Nov-97 rogerg Created.
  118. //
  119. //----------------------------------------------------------------------------
  120. STDMETHODIMP_(ULONG) CHndlrMsg::Release()
  121. {
  122. ULONG cRefs;
  123. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  124. Assert(m_dwThreadId == GetCurrentThreadId());
  125. Assert(0 == m_dwNestCount);
  126. m_dwNestCount++;
  127. cRefs = InterlockedDecrement( (LONG *) &m_cRef);
  128. if (0 == cRefs)
  129. {
  130. if (m_pCallBack)
  131. {
  132. SetupCallback(FALSE);
  133. }
  134. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  135. if (m_pOneStopHandler)
  136. {
  137. LPSYNCMGRSYNCHRONIZE OneStopHandler = m_pOneStopHandler;
  138. m_pOneStopHandler = NULL;
  139. // if have a callback then revoke it
  140. __try
  141. {
  142. OneStopHandler->Release();
  143. }
  144. __except(QueryHandleException())
  145. {
  146. AssertSz(0,"Exception in Handler's release method.");
  147. }
  148. }
  149. if (m_pOldOneStopHandler)
  150. {
  151. LPOLDSYNCMGRSYNCHRONIZE pOldOneStopHandler = m_pOldOneStopHandler;
  152. m_pOldOneStopHandler = NULL;
  153. // if have a callback then revoke it
  154. __try
  155. {
  156. pOldOneStopHandler->Release();
  157. }
  158. __except(QueryHandleException())
  159. {
  160. AssertSz(0,"Exception in Handler's release method.");
  161. }
  162. }
  163. if (m_pHndlrQueue)
  164. {
  165. m_pHndlrQueue->Release();
  166. m_pHndlrQueue = NULL;
  167. }
  168. m_fDead = TRUE;
  169. m_dwNestCount--;
  170. delete this;
  171. }
  172. else
  173. {
  174. m_dwNestCount--;
  175. }
  176. return cRefs;
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Member: CHndlrMsg::Initialize, public
  181. //
  182. // Synopsis: Calls Initialize method of the Handler
  183. //
  184. // Arguments: [dwReserved] - Reserved for now is NULL
  185. // [dwSyncFlags] - SyncFlags
  186. // [cbCookie] - Size of Cookie data if any
  187. // [lpCookie] - Pointer to Cookie data
  188. //
  189. // Returns: Whatever the handler tells us too.
  190. //
  191. // Modifies:
  192. //
  193. // History: 05-Nov-97 rogerg Created.
  194. //
  195. //----------------------------------------------------------------------------
  196. STDMETHODIMP CHndlrMsg::Initialize(DWORD dwReserved,
  197. DWORD dwSyncFlags,
  198. DWORD cbCookie,
  199. BYTE const*lpCookie)
  200. {
  201. HRESULT hr = E_UNEXPECTED;
  202. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  203. Assert(m_dwThreadId == GetCurrentThreadId());
  204. Assert(0 == m_dwNestCount);
  205. m_dwNestCount++;
  206. m_dwSyncFlags = dwSyncFlags;
  207. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  208. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  209. if (NULL != m_pOneStopHandler)
  210. {
  211. __try
  212. {
  213. hr = m_pOneStopHandler->Initialize(dwReserved,dwSyncFlags,cbCookie,lpCookie);
  214. }
  215. __except(QueryHandleException())
  216. {
  217. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  218. AssertSz(0,"Exception in Handler's Initialize method.");
  219. }
  220. }
  221. if (NULL != m_pOldOneStopHandler)
  222. {
  223. // old handlers can't handle cookie data unless it is their own
  224. if (SYNCMGRFLAG_INVOKE != (dwSyncFlags & SYNCMGRFLAG_EVENTMASK))
  225. {
  226. cbCookie = 0;
  227. lpCookie = NULL;
  228. }
  229. __try
  230. {
  231. hr = m_pOldOneStopHandler->Initialize(dwReserved,dwSyncFlags,cbCookie,lpCookie);
  232. }
  233. __except(QueryHandleException())
  234. {
  235. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  236. AssertSz(0,"Exception in Handler's Initialize method.");
  237. }
  238. }
  239. m_dwNestCount--;
  240. return hr;
  241. }
  242. //+---------------------------------------------------------------------------
  243. //
  244. // Member: CHndlrMsg::GetHandlerInfo, public
  245. //
  246. // Synopsis: Calls GetHandlerInfo method of the Handler
  247. //
  248. // Arguments: [ppSyncMgrHandlerInfo] -
  249. //
  250. // Returns: Whatever the handler tells us too.
  251. //
  252. // Modifies:
  253. //
  254. // History: 05-Nov-97 rogerg Created.
  255. //
  256. //----------------------------------------------------------------------------
  257. STDMETHODIMP CHndlrMsg::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
  258. {
  259. HRESULT hr = E_UNEXPECTED;
  260. Assert(m_dwThreadId == GetCurrentThreadId());
  261. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  262. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  263. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  264. if (NULL != m_pOneStopHandler)
  265. {
  266. __try
  267. {
  268. hr = m_pOneStopHandler->GetHandlerInfo(ppSyncMgrHandlerInfo);
  269. }
  270. __except(QueryHandleException())
  271. {
  272. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  273. AssertSz(0,"Exception in Handler's GetHandlerInfo method.");
  274. }
  275. }
  276. if (NULL != m_pOldOneStopHandler)
  277. {
  278. __try
  279. {
  280. hr = m_pOldOneStopHandler->GetHandlerInfo(ppSyncMgrHandlerInfo);
  281. }
  282. __except(QueryHandleException())
  283. {
  284. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  285. AssertSz(0,"Exception in Handler's GetHandlerInfo method.");
  286. }
  287. }
  288. return hr;
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Member: CHndlrMsg::EnumOfflineItems, public
  293. //
  294. // Synopsis: PlaceHolder for IOfflineSynchronize Enum method.
  295. // This shouldn't be called. AddHandlerItems should be
  296. // called instead
  297. //
  298. // Arguments: [ppenumOfflineItems] - returned enumerator
  299. //
  300. // Returns: Whatever the handler tells us too.
  301. //
  302. // Modifies:
  303. //
  304. // History: 05-Nov-97 rogerg Created.
  305. //
  306. //----------------------------------------------------------------------------
  307. STDMETHODIMP CHndlrMsg::EnumSyncMgrItems(ISyncMgrEnumItems** ppenumOffineItems)
  308. {
  309. Assert(m_dwThreadId == GetCurrentThreadId());
  310. Assert(0 == m_dwNestCount);
  311. m_dwNestCount++;
  312. AssertSz(0,"Shouldn't call this Method");
  313. *ppenumOffineItems = NULL;
  314. m_dwNestCount--;
  315. return E_NOTIMPL;
  316. }
  317. //+---------------------------------------------------------------------------
  318. //
  319. // Member: CHndlrMsg::GetItemObject, public
  320. //
  321. // Synopsis: Calls Handler's GetItemObject method
  322. //
  323. // Arguments: [ItemID] - Id of the item
  324. // [riid] - requested interface
  325. // [ppv] - out pointer for object
  326. //
  327. // Returns: Whatever the handler tells us too.
  328. //
  329. // Modifies:
  330. //
  331. // History: 05-Nov-97 rogerg Created.
  332. //
  333. //----------------------------------------------------------------------------
  334. STDMETHODIMP CHndlrMsg::GetItemObject(REFSYNCMGRITEMID ItemID,REFIID riid,void** ppv)
  335. {
  336. HRESULT hr = E_UNEXPECTED;
  337. Assert(m_dwThreadId == GetCurrentThreadId());
  338. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  339. Assert(0 == m_dwNestCount);
  340. m_dwNestCount++;
  341. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  342. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  343. if (NULL != m_pOneStopHandler)
  344. {
  345. __try
  346. {
  347. hr = m_pOneStopHandler->GetItemObject(ItemID,riid,ppv);
  348. }
  349. __except(QueryHandleException())
  350. {
  351. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  352. AssertSz(0,"Exception in Handler's GetItemObject method.");
  353. }
  354. Assert(E_NOTIMPL == hr); // currently noone should be implementing this.
  355. }
  356. if (NULL != m_pOldOneStopHandler)
  357. {
  358. __try
  359. {
  360. hr = m_pOldOneStopHandler->GetItemObject(ItemID,riid,ppv);
  361. }
  362. __except(QueryHandleException())
  363. {
  364. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  365. AssertSz(0,"Exception in Handler's GetItemObject method.");
  366. }
  367. Assert(E_NOTIMPL == hr); // currently noone should be implementing this.
  368. }
  369. m_dwNestCount--;
  370. return hr;
  371. }
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Member: CHndlrMsg::ShowProperties, public
  375. //
  376. // Synopsis: Calls Handler's ShowProperties method
  377. //
  378. // Arguments: [hwnd] - hwnd to use as parent to dialog
  379. // [itemID] - Identifies the Item
  380. //
  381. // Returns: Whatever the handler tells us.
  382. //
  383. // Modifies:
  384. //
  385. // History: 05-Nov-97 rogerg Created.
  386. //
  387. //----------------------------------------------------------------------------
  388. STDMETHODIMP CHndlrMsg::ShowProperties(HWND hwnd,REFSYNCMGRITEMID ItemID)
  389. {
  390. HRESULT hr = E_UNEXPECTED;
  391. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  392. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  393. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  394. // need to setup calback if showProperties is called
  395. // if can't setup callback then fail the ShowProperties call.
  396. // Review, ShowPropertiesCompleted doesn't give us the ItemID back so we
  397. // have to store it. This is fine but limits us to one ShowPropertiesCall
  398. // at a time on the handler. if update main interfaces change
  399. // ShowPropertiesCompleted to return the ItemID
  400. Assert(GUID_NULL == m_itemIDShowProperties);
  401. m_itemIDShowProperties = ItemID;
  402. hr = SetupCallback(TRUE); // set up the callback.
  403. if (NOERROR != hr)
  404. return hr;
  405. Assert(0 == m_dwNestCount);
  406. m_dwNestCount++;
  407. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  408. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  409. AttachThreadInput(TRUE);
  410. if (NULL != m_pOneStopHandler)
  411. {
  412. __try
  413. {
  414. hr = m_pOneStopHandler->ShowProperties(hwnd,ItemID);
  415. }
  416. __except(QueryHandleException())
  417. {
  418. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  419. AssertSz(0,"Exception in Handler's ShowProperties method.");
  420. }
  421. }
  422. if (NULL != m_pOldOneStopHandler)
  423. {
  424. __try
  425. {
  426. hr = m_pOldOneStopHandler->ShowProperties(hwnd,ItemID);
  427. }
  428. __except(QueryHandleException())
  429. {
  430. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  431. AssertSz(0,"Exception in Handler's ShowProperties method.");
  432. }
  433. }
  434. m_dwNestCount--;
  435. // if old interface need to make the callback ourselves
  436. if ( m_pOldOneStopHandler )
  437. {
  438. Assert(m_pCallBack);
  439. if (m_pCallBack && (NOERROR == hr))
  440. {
  441. m_pCallBack->ShowPropertiesCompleted(NOERROR);
  442. }
  443. }
  444. // if an error is returned set the showProperties guid back
  445. if (NOERROR != hr)
  446. {
  447. m_itemIDShowProperties = GUID_NULL;
  448. }
  449. return hr;
  450. }
  451. //+---------------------------------------------------------------------------
  452. //
  453. // Member: CHndlrMsg::SetProgressCallback, public
  454. //
  455. // Synopsis: PlaceHolder for SetProgressCallback. This member is currently
  456. // not used. Instead the SetupCallback method is called
  457. //
  458. // Arguments: [lpCallBack] - Pointer to Callback object
  459. //
  460. // Returns: Whatever the handler tells us.
  461. //
  462. // Modifies:
  463. //
  464. // History: 05-Nov-97 rogerg Created.
  465. //
  466. //----------------------------------------------------------------------------
  467. STDMETHODIMP CHndlrMsg::SetProgressCallback(ISyncMgrSynchronizeCallback *lpCallBack)
  468. {
  469. Assert(m_dwThreadId == GetCurrentThreadId());
  470. Assert(0 == m_dwNestCount);
  471. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  472. m_dwNestCount++;
  473. AssertSz(0,"Shouldn't call this method");
  474. m_dwNestCount--;
  475. return E_NOTIMPL;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Member: CHndlrMsg::PrepareForSync, public
  480. //
  481. // Synopsis: Calls Handler's ShowProperties method
  482. //
  483. // Arguments: [cbNumItems] - number of items so sync
  484. // [pItemIDs] - Array of Items
  485. // [hwnd] - Hwnd to use as the Parent of any dialogs
  486. // [dwReserved] - Just a reserved parameter
  487. //
  488. // Returns: Whatever the handler tells us.
  489. //
  490. // Modifies:
  491. //
  492. // History: 05-Nov-97 rogerg Created.
  493. //
  494. //----------------------------------------------------------------------------
  495. STDMETHODIMP CHndlrMsg::PrepareForSync(ULONG cbNumItems,SYNCMGRITEMID *pItemIDs,
  496. HWND hwnd,DWORD dwReserved)
  497. {
  498. HRESULT hr = E_UNEXPECTED;
  499. Assert(m_dwThreadId == GetCurrentThreadId());
  500. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  501. // Assert(0 == m_dwNestCount);// may not be zero if handler has yielded
  502. hr = SetupCallback(TRUE); // set up the callback.
  503. if (NOERROR != hr)
  504. return hr;
  505. m_dwNestCount++;
  506. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  507. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  508. if (m_pOneStopHandler)
  509. {
  510. __try
  511. {
  512. hr = m_pOneStopHandler->PrepareForSync(cbNumItems,pItemIDs,hwnd,dwReserved);
  513. }
  514. __except(QueryHandleException())
  515. {
  516. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  517. AssertSz(0,"Exception in Handler's PrepareForSync method.");
  518. }
  519. }
  520. if (m_pOldOneStopHandler)
  521. {
  522. __try
  523. {
  524. hr = m_pOldOneStopHandler->PrepareForSync(cbNumItems,pItemIDs,hwnd,dwReserved);
  525. }
  526. __except(QueryHandleException())
  527. {
  528. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  529. AssertSz(0,"Exception in Handler's PrepareForSync method.");
  530. }
  531. }
  532. m_dwNestCount--;
  533. return hr;
  534. }
  535. //+---------------------------------------------------------------------------
  536. //
  537. // Member: CHndlrMsg::Sychronize, public
  538. //
  539. // Synopsis: Calls Handler's Synchronize method
  540. //
  541. // Arguments: [hwnd] - hwnd to use as parent to dialog
  542. //
  543. // Returns: Whatever the handler tells us.
  544. //
  545. // Modifies:
  546. //
  547. // History: 05-Nov-97 rogerg Created.
  548. //
  549. //----------------------------------------------------------------------------
  550. STDMETHODIMP CHndlrMsg::Synchronize(HWND hwnd)
  551. {
  552. HRESULT hr = E_UNEXPECTED;
  553. Assert(m_dwThreadId == GetCurrentThreadId());
  554. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  555. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  556. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  557. // Assert(0 == m_dwNestCount);
  558. m_dwNestCount++;
  559. if (m_pOneStopHandler)
  560. {
  561. __try
  562. {
  563. hr = m_pOneStopHandler->Synchronize(hwnd);
  564. }
  565. __except(QueryHandleException())
  566. {
  567. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  568. AssertSz(0,"Exception in Handler's Synchronize method.");
  569. }
  570. }
  571. if (m_pOldOneStopHandler)
  572. {
  573. __try
  574. {
  575. hr = m_pOldOneStopHandler->Synchronize(hwnd);
  576. }
  577. __except(QueryHandleException())
  578. {
  579. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  580. AssertSz(0,"Exception in Handler's Synchronize method.");
  581. }
  582. }
  583. m_dwNestCount--;
  584. return hr;
  585. }
  586. //+---------------------------------------------------------------------------
  587. //
  588. // Member: CHndlrMsg::SetItemStatus, public
  589. //
  590. // Synopsis: Calls Handler's SetItemStatus method
  591. //
  592. // Arguments:
  593. //
  594. // Returns: Whatever the handler tells us.
  595. //
  596. // Modifies:
  597. //
  598. // History: 05-Nov-97 rogerg Created.
  599. //
  600. //----------------------------------------------------------------------------
  601. STDMETHODIMP CHndlrMsg::SetItemStatus(REFSYNCMGRITEMID ItemID,DWORD dwSyncMgrStatus)
  602. {
  603. HRESULT hr = NOERROR;
  604. Assert(m_dwThreadId == GetCurrentThreadId());
  605. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  606. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  607. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  608. m_dwNestCount++; // valid for this to come in when in sync call.
  609. if (m_pOneStopHandler)
  610. {
  611. __try
  612. {
  613. hr = m_pOneStopHandler->SetItemStatus(ItemID,dwSyncMgrStatus);
  614. }
  615. __except(QueryHandleException())
  616. {
  617. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  618. AssertSz(0,"Exception in Handler's SetItemStatus method.");
  619. }
  620. }
  621. if (m_pOldOneStopHandler)
  622. {
  623. __try
  624. {
  625. hr = m_pOldOneStopHandler->SetItemStatus(ItemID,dwSyncMgrStatus);
  626. }
  627. __except(QueryHandleException())
  628. {
  629. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  630. AssertSz(0,"Exception in Handler's SetItemStatus method.");
  631. }
  632. }
  633. m_dwNestCount--;
  634. return hr;
  635. }
  636. //+---------------------------------------------------------------------------
  637. //
  638. // Member: CHndlrMsg::ShowError, public
  639. //
  640. // Synopsis: Calls Handler's ShowError method
  641. //
  642. // Arguments: [hwnd] - hwnd to use as parent to dialog
  643. // [dwErrorID] - ErrorID passed in LogError
  644. //
  645. // Returns: Whatever the handler tells us.
  646. //
  647. // Modifies:
  648. //
  649. // History: 05-Nov-97 rogerg Created.
  650. //
  651. //----------------------------------------------------------------------------
  652. STDMETHODIMP CHndlrMsg::ShowError(HWND hWndParent,REFSYNCMGRERRORID ErrorID)
  653. {
  654. HRESULT hr = E_UNEXPECTED;
  655. ULONG cbNumItems;
  656. SYNCMGRITEMID *pItemIDs;
  657. Assert(m_dwThreadId == GetCurrentThreadId());
  658. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  659. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  660. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  661. m_dwNestCount++;
  662. // on a ShowError enablemodeless in the callback can
  663. // return true since user has shown an interest
  664. if (m_pCallBack)
  665. {
  666. m_pCallBack->SetEnableModeless(TRUE);
  667. }
  668. AttachThreadInput(TRUE);
  669. if (m_pOneStopHandler)
  670. {
  671. __try
  672. {
  673. hr = m_pOneStopHandler->ShowError(hWndParent,ErrorID);
  674. }
  675. __except(QueryHandleException())
  676. {
  677. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  678. AssertSz(0,"Exception in Handler's ShowError method.");
  679. }
  680. }
  681. if (m_pOldOneStopHandler)
  682. {
  683. __try
  684. {
  685. hr = m_pOldOneStopHandler->ShowError(hWndParent,ErrorID,&cbNumItems,&pItemIDs);
  686. }
  687. __except(QueryHandleException())
  688. {
  689. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  690. AssertSz(0,"Exception in Handler's ShowError method.");
  691. }
  692. }
  693. m_dwNestCount--;
  694. // if old interface need to make the callback ourselves
  695. if ( m_pOldOneStopHandler )
  696. {
  697. Assert(m_pCallBack);
  698. if (m_pCallBack && SUCCEEDED(hr))
  699. {
  700. m_pCallBack->ShowErrorCompleted(hr,cbNumItems,pItemIDs);
  701. if ( (S_SYNCMGR_RETRYSYNC == hr) && pItemIDs) // after completion routine free the pItems since [in] param.
  702. {
  703. CoTaskMemFree(pItemIDs);
  704. }
  705. }
  706. return SUCCEEDED(hr) ? NOERROR : hr;
  707. }
  708. // New interface won't have the numItems and Items Enum
  709. // on new interface ShowError should only return NOERROR so if retry or
  710. // other success is returned then return NOERROR;
  711. return hr;
  712. }
  713. //+---------------------------------------------------------------------------
  714. //
  715. // Member: CHndlrMsg::SetupCallback, private
  716. //
  717. // Synopsis: Sets up the callback for the handler
  718. //
  719. // Arguments: [fSet] - TRUE sets the Callbac, FALSE removes it
  720. //
  721. // Returns: NOERROR on Success
  722. //
  723. // Modifies:
  724. //
  725. // History: 05-Nov-97 rogerg Created.
  726. //
  727. //----------------------------------------------------------------------------
  728. STDMETHODIMP CHndlrMsg::SetupCallback(BOOL fSet)
  729. {
  730. HRESULT hr = E_UNEXPECTED;
  731. Assert(m_dwThreadId == GetCurrentThreadId());
  732. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  733. Assert(m_dwNestCount <= 1); // 1 since valid to be called from Release method.
  734. m_dwNestCount++;
  735. // possible to get called with fSet twice of true in the case
  736. // a retrysync occurs. If we already have a callback set
  737. // when a new request to set one comes in the just return.
  738. if (NULL != m_pCallBack && TRUE == fSet)
  739. {
  740. hr = NOERROR;
  741. }
  742. else
  743. {
  744. Assert( ( (NULL != m_pCallBack) && (FALSE == fSet) )
  745. || (TRUE == fSet)); // catch case OneStop calls this twice when already set
  746. if (NULL != m_pCallBack)
  747. {
  748. // set the callbacks CHndlrMsg pointer to NULL in case
  749. // object tries to call through after the release.
  750. m_pCallBack->SetHndlrMsg(NULL,FALSE);
  751. m_pCallBack->Release();
  752. m_pCallBack = NULL;
  753. }
  754. if (TRUE == fSet)
  755. {
  756. // if allocation fails, progress just gets set to NULL
  757. m_pCallBack = new COfflineSynchronizeCallback(this,m_CLSIDServer,m_dwSyncFlags,
  758. (SYNCMGRFLAG_MAYBOTHERUSER & m_dwSyncFlags) /* fAllowModeless */ );
  759. }
  760. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  761. if (m_pOneStopHandler)
  762. {
  763. __try
  764. {
  765. hr = m_pOneStopHandler->SetProgressCallback( (LPSYNCMGRSYNCHRONIZECALLBACK) m_pCallBack );
  766. }
  767. __except(QueryHandleException())
  768. {
  769. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  770. AssertSz(0,"Exception in Handler's SetProgressCallback method.");
  771. }
  772. }
  773. if (m_pOldOneStopHandler)
  774. {
  775. __try
  776. {
  777. hr = m_pOldOneStopHandler->SetProgressCallback( (LPOLDSYNCMGRSYNCHRONIZECALLBACK) m_pCallBack );
  778. }
  779. __except(QueryHandleException())
  780. {
  781. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  782. AssertSz(0,"Exception in Handler's SetProgressCallback method.");
  783. }
  784. }
  785. if ( (NOERROR != hr) && (NULL != m_pCallBack) )
  786. {
  787. m_pCallBack->SetHndlrMsg(NULL,FALSE);
  788. m_pCallBack->Release(); // on an error go ahead and release our copy too.
  789. m_pCallBack = NULL;
  790. }
  791. }
  792. m_dwNestCount--;
  793. return hr;
  794. }
  795. //+---------------------------------------------------------------------------
  796. //
  797. // Member: CHndlrMsg::SetHandlerInfo, private
  798. //
  799. // Synopsis: sets up the Handler info
  800. //
  801. // Arguments:
  802. //
  803. // Returns: NOERROR on Success
  804. //
  805. // Modifies:
  806. //
  807. // History: 28-Jul-98 rogerg Created.
  808. //
  809. //----------------------------------------------------------------------------
  810. STDMETHODIMP CHndlrMsg::SetHandlerInfo()
  811. {
  812. LPSYNCMGRHANDLERINFO pSyncMgrHandlerInfo = NULL;
  813. HRESULT hr = E_UNEXPECTED;
  814. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  815. hr = GetHandlerInfo(&pSyncMgrHandlerInfo);
  816. if (NOERROR != hr || (NULL == pSyncMgrHandlerInfo))
  817. {
  818. return hr;
  819. }
  820. if (!IsValidSyncMgrHandlerInfo(pSyncMgrHandlerInfo))
  821. {
  822. CoTaskMemFree(pSyncMgrHandlerInfo);
  823. return E_INVALIDARG;
  824. }
  825. Assert(m_pHndlrQueue);
  826. if (m_pHndlrQueue)
  827. {
  828. hr = m_pHndlrQueue->SetHandlerInfo(m_pHandlerId,pSyncMgrHandlerInfo);
  829. }
  830. if (pSyncMgrHandlerInfo)
  831. {
  832. CoTaskMemFree(pSyncMgrHandlerInfo);
  833. }
  834. return hr;
  835. }
  836. //+---------------------------------------------------------------------------
  837. //
  838. // Member: CHndlrMsg::AddtoItemList, private
  839. //
  840. // Synopsis: Adds a single Items to the queue
  841. //
  842. // Arguments: [poffItem] - Pointer to Item to add
  843. //
  844. // Returns: NOERROR on Success
  845. //
  846. // Modifies:
  847. //
  848. // History: 05-Nov-97 rogerg Created.
  849. //
  850. //----------------------------------------------------------------------------
  851. HRESULT CHndlrMsg::AddToItemList(LPSYNCMGRITEM poffItem)
  852. {
  853. HRESULT hr = E_UNEXPECTED;
  854. Assert(m_dwThreadId == GetCurrentThreadId());
  855. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  856. Assert(m_pHndlrQueue);
  857. if (!IsValidSyncMgrItem(poffItem))
  858. {
  859. return E_INVALIDARG;
  860. }
  861. if (m_pHndlrQueue)
  862. {
  863. hr = m_pHndlrQueue->AddItemToHandler(m_pHandlerId,poffItem);
  864. }
  865. return hr;
  866. }
  867. //+---------------------------------------------------------------------------
  868. //
  869. // Member: CHndlrMsg::AddHandlerItems, private
  870. //
  871. // Synopsis: Calls the handlers enumerator and adds each returned item
  872. // to the queue
  873. //
  874. // Arguments: [hwndList] - hwnd of ListView to add items too. (Not Used)
  875. //
  876. // Returns: Appropriate status code
  877. //
  878. // Modifies:
  879. //
  880. // History: 05-Nov-97 rogerg Created.
  881. //
  882. //----------------------------------------------------------------------------
  883. STDMETHODIMP CHndlrMsg::AddHandlerItems(HWND hwndList,DWORD *pcbNumItems)
  884. {
  885. HRESULT hr = E_UNEXPECTED;
  886. LPSYNCMGRENUMITEMS pEnumOffline = NULL;
  887. Assert(m_dwThreadId == GetCurrentThreadId());
  888. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  889. Assert(pcbNumItems);
  890. *pcbNumItems = 0;
  891. Assert(0 == m_dwNestCount);
  892. m_dwNestCount++;
  893. SetHandlerInfo(); // setup the toplevel handler info
  894. Assert(m_pOneStopHandler || m_pOldOneStopHandler);
  895. Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
  896. if (m_pOneStopHandler || m_pOldOneStopHandler)
  897. {
  898. if ( m_pOneStopHandler )
  899. {
  900. __try
  901. {
  902. hr = m_pOneStopHandler->EnumSyncMgrItems(&pEnumOffline);
  903. }
  904. __except(QueryHandleException())
  905. {
  906. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  907. AssertSz(0,"Exception in Handler's EnumSyncMgrItems method.");
  908. }
  909. }
  910. if ( m_pOldOneStopHandler )
  911. {
  912. __try
  913. {
  914. hr = m_pOldOneStopHandler->EnumSyncMgrItems(&pEnumOffline);
  915. }
  916. __except(QueryHandleException())
  917. {
  918. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  919. AssertSz(0,"Exception in Handler's EnumSyncMgrItems method.");
  920. }
  921. }
  922. // Review - Make sure preferences aren't deleted
  923. // in missing items case.
  924. if ( (NOERROR == hr || S_SYNCMGR_MISSINGITEMS == hr) && pEnumOffline)
  925. {
  926. SYNCMGRITEMNT5B2 offItem; // temporarily use NT5B2 structure since its bigger
  927. ULONG pceltFetched;
  928. Assert(sizeof(SYNCMGRITEMNT5B2) > sizeof(SYNCMGRITEM));
  929. // sit in loop getting data of objects to fill list box.
  930. // should really set up list in memory for OneStop to fill in or
  931. // main thread could pass in a callback interface.
  932. if (pEnumOffline)
  933. {
  934. __try
  935. {
  936. while(NOERROR == pEnumOffline->Next(1,(LPSYNCMGRITEM) &offItem,&pceltFetched))
  937. {
  938. if (NOERROR == AddToItemList((LPSYNCMGRITEM) &offItem))
  939. {
  940. ++(*pcbNumItems);
  941. }
  942. }
  943. pEnumOffline->Release();
  944. }
  945. __except(QueryHandleException())
  946. {
  947. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  948. AssertSz(0,"Exception in Handler's EnumOffline::Next method.");
  949. }
  950. }
  951. else
  952. {
  953. hr = E_UNEXPECTED;
  954. }
  955. }
  956. }
  957. m_dwNestCount--;
  958. return hr;
  959. }
  960. //+---------------------------------------------------------------------------
  961. //
  962. // Member: CHndlrMsg::CreateServer, private
  963. //
  964. // Synopsis: Creates and Instance of the handle
  965. //
  966. // Arguments: [pCLSIDServer] - CLSID of Handler
  967. // [pHndlrQueue] - pointer to queue handler should be added too
  968. // [wHandlerID] - ID of Handler in the queue
  969. //
  970. // Returns: Appropriate status code
  971. //
  972. // Modifies:
  973. //
  974. // History: 05-Nov-97 rogerg Created.
  975. //
  976. //----------------------------------------------------------------------------
  977. STDMETHODIMP CHndlrMsg::CreateServer(const CLSID *pCLSIDServer,CHndlrQueue *pHndlrQueue,
  978. HANDLERINFO *pHandlerId,DWORD dwProxyThreadId)
  979. {
  980. HRESULT hr = NOERROR;
  981. LPUNKNOWN pUnk;
  982. LPSYNCMGRENUMITEMS pEnumOffline = NULL;
  983. Assert(m_dwThreadId == GetCurrentThreadId());
  984. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  985. Assert(0 == m_dwNestCount);
  986. m_dwNestCount++;
  987. m_CLSIDServer = *pCLSIDServer;
  988. m_pHndlrQueue = pHndlrQueue;
  989. m_dwProxyThreadId = dwProxyThreadId;
  990. if (m_pHndlrQueue)
  991. {
  992. m_pHndlrQueue->AddRef();
  993. }
  994. m_pHandlerId = pHandlerId;
  995. hr = CoCreateInstance(m_CLSIDServer, NULL, CLSCTX_INPROC_SERVER,
  996. IID_IUnknown, (void **) &pUnk);
  997. if (NOERROR == hr)
  998. {
  999. __try
  1000. {
  1001. hr = pUnk->QueryInterface(IID_ISyncMgrSynchronize,(void **) &m_pOneStopHandler);
  1002. }
  1003. __except(QueryHandleException())
  1004. {
  1005. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  1006. AssertSz(0,"Exception in Handler's IUnknown::QI method.");
  1007. }
  1008. __try
  1009. {
  1010. pUnk->Release();
  1011. }
  1012. __except(QueryHandleException())
  1013. {
  1014. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  1015. AssertSz(0,"Exception in Handler's IUnknown::Release method.");
  1016. }
  1017. }
  1018. if (NOERROR != hr)
  1019. {
  1020. m_pOneStopHandler = NULL;
  1021. m_pOldOneStopHandler = NULL;
  1022. }
  1023. m_dwNestCount--;
  1024. return hr;
  1025. }
  1026. //+---------------------------------------------------------------------------
  1027. //
  1028. // Member: CHndlrMsg::SetHndlrQueue, private
  1029. //
  1030. // Synopsis: Assigns a new HndlrQueue.
  1031. //
  1032. // Arguments: [pHndlrQueue] - Pointer to the Queue
  1033. // [wHandlerId] - Id assigned to handler in the new queue
  1034. //
  1035. // !!!Warning - this is on the callers thread
  1036. //
  1037. // Returns: Appropriate status code
  1038. //
  1039. // Modifies:
  1040. //
  1041. // History: 05-Nov-97 rogerg Created.
  1042. //
  1043. //----------------------------------------------------------------------------
  1044. STDMETHODIMP CHndlrMsg::SetHndlrQueue(CHndlrQueue *pHndlrQueue,HANDLERINFO *pHandlerId,DWORD dwProxyThreadId)
  1045. {
  1046. CLock clockCallback(this);
  1047. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  1048. clockCallback.Enter();
  1049. Assert(0 == m_dwNestCount);
  1050. m_dwNestCount++;
  1051. if (pHndlrQueue != m_pHndlrQueue)
  1052. {
  1053. if (m_pHndlrQueue)
  1054. {
  1055. m_pHndlrQueue->Release();
  1056. }
  1057. m_pHndlrQueue = pHndlrQueue;
  1058. if (m_pHndlrQueue)
  1059. {
  1060. m_pHndlrQueue->AddRef();
  1061. }
  1062. }
  1063. AttachThreadInput(FALSE); // make sure thread input isn't set
  1064. // update handlr id and proxy which can change even if queue is same
  1065. // which can happen first queue that gets set in choice.
  1066. m_pHandlerId = pHandlerId;
  1067. m_dwProxyThreadId = dwProxyThreadId;
  1068. m_dwNestCount--;
  1069. clockCallback.Leave();
  1070. return NOERROR;
  1071. }
  1072. //+---------------------------------------------------------------------------
  1073. //
  1074. // Member: CHndlrMsg::GetHndlrQueue, private
  1075. //
  1076. // Synopsis: Gets current Queue,
  1077. // Can be called on any thread so progress callback
  1078. // gets this information.
  1079. //
  1080. // Arguments: [ppHndlrQueue] - Out param filled with Pointer to the Queue
  1081. // [pwHandlerId] - out param filled with Id assigned to handler
  1082. // in the new queue
  1083. //
  1084. // Returns: Appropriate status code
  1085. //
  1086. // Modifies:
  1087. //
  1088. // History: 05-Nov-97 rogerg Created.
  1089. //
  1090. //----------------------------------------------------------------------------
  1091. void CHndlrMsg::GetHndlrQueue(CHndlrQueue **ppHndlrQueue,HANDLERINFO **ppHandlerId,DWORD *pdwProxyThreadId)
  1092. {
  1093. CLock clockCallback(this);
  1094. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  1095. clockCallback.Enter();
  1096. *ppHndlrQueue = m_pHndlrQueue;
  1097. *ppHandlerId = m_pHandlerId;
  1098. *pdwProxyThreadId = m_dwProxyThreadId;
  1099. if (m_pHndlrQueue)
  1100. {
  1101. m_pHndlrQueue->AddRef();
  1102. }
  1103. clockCallback.Leave();
  1104. }
  1105. //+---------------------------------------------------------------------------
  1106. //
  1107. // Member: CHndlrMsg::AttachThreadInput, private
  1108. //
  1109. // Synopsis: Attaches the thread input of this thread
  1110. // with the calling proxy so UI works correctly.
  1111. //
  1112. // Arguments: [fAttach] - Bool to indicate if should attach or not.
  1113. //
  1114. // Returns: Appropriate status code
  1115. //
  1116. // Modifies:
  1117. //
  1118. // History: 05-Nov-97 rogerg Created.
  1119. //
  1120. //----------------------------------------------------------------------------
  1121. void CHndlrMsg::AttachThreadInput(BOOL fAttach)
  1122. {
  1123. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  1124. // if request is same as current state don't do anything.
  1125. if (m_fThreadInputAttached != fAttach )
  1126. {
  1127. m_fThreadInputAttached = fAttach;
  1128. ::AttachThreadInput(m_dwProxyThreadId,m_dwThreadId,fAttach);
  1129. }
  1130. }
  1131. //+---------------------------------------------------------------------------
  1132. //
  1133. // Member: CHndlrMsg::ForceKillHandler, private
  1134. //
  1135. // Synopsis: called directly by proxy when a thread is not
  1136. // responding. Does any necessary cleanup of classes in the handler
  1137. // thread before the proxy kills the thred
  1138. //
  1139. // Arguments:
  1140. //
  1141. // Returns: Appropriate status code
  1142. //
  1143. // Modifies:
  1144. //
  1145. // History: 17-Nov-98 rogerg Created.
  1146. //
  1147. //----------------------------------------------------------------------------
  1148. STDMETHODIMP CHndlrMsg::ForceKillHandler()
  1149. {
  1150. Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
  1151. m_fForceKilled = TRUE;
  1152. // if have a callback tell it we terminated but don't
  1153. // release it in case the handler calls the callback later.
  1154. if (m_pCallBack)
  1155. {
  1156. COfflineSynchronizeCallback* pCallback = m_pCallBack;
  1157. m_pCallBack = NULL;
  1158. pCallback->SetHndlrMsg(NULL,TRUE);
  1159. }
  1160. // delete our instance since should never be called again.
  1161. delete this;
  1162. return NOERROR;
  1163. }