Leaked source code of windows server 2003
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.

682 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: stgconn.cxx
  7. //
  8. // Contents: Connection points for Async Storage/Stream Wrappers
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Dec-95 SusiA Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "astghead.cxx"
  18. #pragma hdrstop
  19. #include <sinklist.hxx>
  20. #include <utils.hxx>
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Member: CConnectionPoint::CConnectionPoint, public
  24. //
  25. // Synopsis: Constructor
  26. //
  27. // Arguments:
  28. //
  29. // History: 28-Dec-95 SusiA Created
  30. //
  31. //----------------------------------------------------------------------------
  32. CConnectionPoint::CConnectionPoint()
  33. {
  34. astgDebugOut((DEB_ITRACE, "In CConnectionPoint::CConnectionPoint:%p()\n", this));
  35. _cReferences = 1;
  36. _dwCookie = 0;
  37. _pSinkHead = NULL;
  38. _pParentCP = NULL;
  39. _fCSInitialized = FALSE;
  40. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::CConnectionPoint\n"));
  41. }
  42. CConnectionPoint::~CConnectionPoint()
  43. {
  44. astgDebugOut((DEB_ITRACE, "In CConnectionPoint::~CConnectionPoint:%p()\n", this));
  45. TakeCS();
  46. if (_pParentCP)
  47. _pParentCP->Release();
  48. // clean up the advise list
  49. CSinkList *psltemp = _pSinkHead;
  50. CSinkList *pslprev = NULL;
  51. while (psltemp)
  52. {
  53. pslprev = psltemp;
  54. psltemp = psltemp->GetNext();
  55. pslprev->GetProgressNotify()->Release();
  56. delete pslprev;
  57. }
  58. if (_fCSInitialized)
  59. {
  60. ReleaseCS();
  61. DeleteCriticalSection(&_csSinkList);
  62. }
  63. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::~CConnectionPoint\n"));
  64. }
  65. SCODE CConnectionPoint::Init()
  66. {
  67. if (FALSE == _fCSInitialized)
  68. {
  69. __try
  70. {
  71. InitializeCriticalSection(&_csSinkList);
  72. _fCSInitialized = TRUE;
  73. }
  74. __except( EXCEPTION_EXECUTE_HANDLER )
  75. {
  76. return HRESULT_FROM_WIN32( GetExceptionCode() );
  77. }
  78. }
  79. return S_OK;
  80. }
  81. #ifndef ASYNC
  82. void CConnectionPoint::Init(IConnectionPointContainer *pCPC)
  83. {
  84. _pCPC = pCPC;
  85. }
  86. //+---------------------------------------------------------------------------
  87. //
  88. // Member: CConnectionPoint::Notify, public
  89. //
  90. // Synopsis:
  91. //
  92. // Returns: Appropriate status code
  93. //
  94. // History: 14-Jan-96 SusiA Created
  95. // 27-Feb-96 SusiA Moved from Async wrappers
  96. //
  97. //----------------------------------------------------------------------------
  98. SCODE CConnectionPoint::Notify(SCODE scFailure,
  99. IFillLockBytes *piflb,
  100. BOOL fDefaultLockBytes)
  101. {
  102. SCODE sc = S_OK;
  103. BOOL fAccurate = (scFailure == E_PENDING);
  104. ULONG ulWaterMark;
  105. ULONG ulFailurePoint;
  106. HANDLE hNotifyEvent;
  107. if (fDefaultLockBytes)
  108. {
  109. CFillLockBytes *pflb = (CFillLockBytes *)piflb;
  110. pflb->GetFailureInfo(&ulWaterMark,
  111. &ulFailurePoint);
  112. pflb->ReleaseCriticalSection();
  113. while (((sc = NotifySinks(ulWaterMark,
  114. ulFailurePoint,
  115. fAccurate,
  116. STG_S_MONITORING)) == STG_S_BLOCK) ||
  117. (sc == STG_S_MONITORING) ||
  118. // S_OK is a synonym for STG_S_MONITORING
  119. (sc == S_OK))
  120. {
  121. DWORD dwFlags;
  122. // wait for an event to signal
  123. hNotifyEvent = pflb->GetNotificationEvent();
  124. WaitForSingleObject(hNotifyEvent, INFINITE);
  125. pflb->GetTerminationStatus(&dwFlags);
  126. // client terminated call?
  127. if (dwFlags == TERMINATED_ABNORMAL)
  128. return STG_E_INCOMPLETE;
  129. // download is complete
  130. else if (dwFlags == TERMINATED_NORMAL)
  131. return S_OK;
  132. else
  133. {
  134. //Note: Don't overwrite the failure point we recorded
  135. // before, since it may have been changed by some
  136. // other thread.
  137. //Don't need to take the critical section here, since
  138. //we don't care about the current failure point.
  139. ULONG ulFailurePointCurrent;
  140. pflb->GetFailureInfo(&ulWaterMark,
  141. &ulFailurePointCurrent);
  142. // all the data is available now
  143. if (ulWaterMark >= ulFailurePoint)
  144. {
  145. // we won't care what the return value is, so send STG_S_BLOCK,
  146. // and all sinks are will have fOwner == FALSE
  147. NotifySinks(ulWaterMark, ulFailurePoint, fAccurate, STG_S_BLOCK);
  148. break;
  149. }
  150. }
  151. }
  152. }
  153. if ((sc == STG_S_RETRYNOW) || (sc == STG_S_BLOCK) || (sc == STG_S_MONITORING))
  154. return S_OK;
  155. else return sc;
  156. }
  157. #endif
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Member: CConnectionPoint::NotifySinks, public
  161. //
  162. // Synopsis:
  163. //
  164. // Returns: Appropriate status code
  165. //
  166. // History: 23-Feb-96 SusiA Created
  167. //
  168. //----------------------------------------------------------------------------
  169. SCODE CConnectionPoint::NotifySinks(ULONG ulProgressCurrent,
  170. ULONG ulProgressMaximum,
  171. BOOL fAccurate,
  172. SCODE sc)
  173. {
  174. CSinkList *pslTemp;
  175. TakeCS();
  176. // closest node with a connection point that wants to determine
  177. // behavior does
  178. // priority first to last on this Connection Point, then the
  179. // parent connection point.
  180. pslTemp = GetHead();
  181. while (((sc == S_OK) ||(sc == STG_S_MONITORING))
  182. &&(pslTemp!=NULL))
  183. {
  184. sc = pslTemp->GetProgressNotify()
  185. ->OnProgress(ulProgressCurrent, ulProgressMaximum, fAccurate, TRUE);
  186. pslTemp = pslTemp->GetNext();
  187. }
  188. // notify the rest of the connections
  189. while (pslTemp !=NULL)
  190. {
  191. pslTemp->GetProgressNotify()
  192. ->OnProgress(ulProgressCurrent, ulProgressMaximum, fAccurate, FALSE);
  193. pslTemp = pslTemp->GetNext();
  194. }
  195. //call parent storage advise list next
  196. if (_pParentCP)
  197. sc = _pParentCP->NotifySinks(ulProgressCurrent,
  198. ulProgressMaximum,
  199. fAccurate,
  200. sc);
  201. ReleaseCS();
  202. return sc;
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Member: CConnectionPoint::QueryInterface, public
  207. //
  208. // Synopsis:
  209. //
  210. // Arguments:
  211. //
  212. // Returns: Appropriate status code
  213. //
  214. // Modifies:
  215. //
  216. // History: 01-Jan-96 SusiA Created
  217. //
  218. // Notes:
  219. //
  220. //----------------------------------------------------------------------------
  221. STDMETHODIMP CConnectionPoint::QueryInterface(REFIID iid, void **ppvObj)
  222. {
  223. SCODE sc = S_OK;
  224. astgDebugOut((DEB_TRACE,
  225. "In CConnectionPoint::QueryInterface:%p()\n",
  226. this));
  227. *ppvObj = NULL;
  228. if ((IsEqualIID(iid, IID_IUnknown)) ||
  229. (IsEqualIID(iid, IID_IDocfileAsyncConnectionPoint)))
  230. {
  231. *ppvObj = (IDocfileAsyncConnectionPoint *)this;
  232. CConnectionPoint::AddRef();
  233. }
  234. else
  235. {
  236. return E_NOINTERFACE;
  237. }
  238. astgDebugOut((DEB_TRACE, "Out CConnectionPoint::QueryInterface\n"));
  239. return ResultFromScode(sc);
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Member: CConnectionPoint::AddRef, public
  244. //
  245. // Synopsis:
  246. //
  247. // Arguments:
  248. //
  249. // Returns: Appropriate status code
  250. //
  251. // Modifies:
  252. //
  253. // History: 29-Dec-95 SusiA Created
  254. //
  255. // Notes:
  256. //
  257. //----------------------------------------------------------------------------
  258. STDMETHODIMP_(ULONG) CConnectionPoint::AddRef(void)
  259. {
  260. LONG lRet;
  261. astgDebugOut((DEB_TRACE,
  262. "In CConnectionPoint::AddRef:%p()\n",
  263. this));
  264. lRet = InterlockedIncrement(&_cReferences);
  265. astgDebugOut((DEB_TRACE, "Out CConnectionPoint::AddRef\n"));
  266. return lRet;
  267. }
  268. //+---------------------------------------------------------------------------
  269. //
  270. // Member: CConnectionPoint::Release, public
  271. //
  272. // Synopsis:
  273. //
  274. // Arguments:
  275. //
  276. // Returns: Appropriate status code
  277. //
  278. // Modifies:
  279. //
  280. // History: 30-Dec-95 SusiA Created
  281. //
  282. // Notes:
  283. //
  284. //----------------------------------------------------------------------------
  285. STDMETHODIMP_(ULONG) CConnectionPoint::Release(void)
  286. {
  287. LONG lRet;
  288. astgDebugOut((DEB_TRACE,
  289. "In CConnectionPoint::Release:%p()\n",
  290. this));
  291. astgAssert(_cReferences > 0);
  292. lRet = InterlockedDecrement(&_cReferences);
  293. if (lRet == 0)
  294. {
  295. delete this;
  296. }
  297. else if (lRet < 0)
  298. {
  299. astgAssert((lRet > 0) && "Connection point released too many times.");
  300. }
  301. astgDebugOut((DEB_TRACE, "Out CConnectionPoint::Release\n"));
  302. return lRet;
  303. }
  304. #ifndef ASYNC
  305. //+---------------------------------------------------------------------------
  306. //
  307. // Member: CConnectionPoint::GetConnectionInterface, public
  308. //
  309. // Synopsis:
  310. //
  311. // Arguments:
  312. //
  313. // Returns: Appropriate status code
  314. //
  315. // Modifies:
  316. //
  317. // History: 30-Dec-95 SusiA Created
  318. //
  319. // Notes:
  320. //
  321. //----------------------------------------------------------------------------
  322. STDMETHODIMP CConnectionPoint::GetConnectionInterface(IID *pIID)
  323. {
  324. astgDebugOut((DEB_ITRACE,
  325. "In CConnectionPoint::GetConnectionInterface:%p()\n",
  326. this));
  327. *pIID = IID_IProgressNotify;
  328. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::GetConnectionInterface\n"));
  329. return S_OK;
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Member: CConnectionPoint::GetConnectionPointContainer, public
  334. //
  335. // Synopsis:
  336. //
  337. // Arguments:
  338. //
  339. // Returns: Appropriate status code
  340. //
  341. // Modifies:
  342. //
  343. // History: 30-Dec-95 SusiA Created
  344. //
  345. // Notes:
  346. //
  347. //----------------------------------------------------------------------------
  348. STDMETHODIMP CConnectionPoint::GetConnectionPointContainer(
  349. IConnectionPointContainer ** ppCPC)
  350. {
  351. astgDebugOut((DEB_ITRACE,
  352. "In CConnectionPoint::GetConnectionPointContainer:%p()\n",
  353. this));
  354. *ppCPC = _pCPC;
  355. _pCPC->AddRef();
  356. astgDebugOut((DEB_ITRACE,
  357. "Out CConnectionPoint::GetConnectionPointContainer\n"));
  358. return S_OK;
  359. }
  360. #endif
  361. //+---------------------------------------------------------------------------
  362. //
  363. // Member: CConnectionPoint::Clone, public
  364. //
  365. // Synopsis:
  366. //
  367. // Arguments:
  368. //
  369. // Returns: Appropriate status code
  370. //
  371. // Modifies:
  372. //
  373. // History: 26-Feb-96 SusiA Created
  374. //
  375. // Notes:
  376. //
  377. //----------------------------------------------------------------------------
  378. SCODE CConnectionPoint::Clone( CConnectionPoint *pcp)
  379. {
  380. SCODE sc = S_OK;
  381. void *pv = NULL;
  382. astgDebugOut((DEB_ITRACE,"In CConnectionPoint::Clone:%p()\n", this));
  383. TakeCS();
  384. pcp->TakeCS();
  385. CSinkList *pslNew = NULL;
  386. CSinkList *pslPrev = NULL;
  387. CSinkList *pslOld = pcp->GetHead();
  388. while (pslOld != NULL)
  389. {
  390. astgMem(pslNew = new CSinkList);
  391. pslNew->SetNext(NULL);
  392. if (pslPrev)
  393. pslPrev->SetNext(pslNew);
  394. else
  395. _pSinkHead = pslNew;
  396. pslPrev = pslNew;
  397. pslNew->SetCookie(pslOld->GetCookie());
  398. //Note: The QueryInterface will give us a reference to hold on to.
  399. astgChk(pslOld->GetProgressNotify()->QueryInterface(IID_IProgressNotify, &pv));
  400. pslNew->SetProgressNotify((IProgressNotify *)pv);
  401. pslOld= pslOld->GetNext();
  402. }
  403. _dwCookie = pcp->GetCookie();
  404. astgDebugOut((DEB_ITRACE,"Out CConnectionPoint::Clone\n"));
  405. Err:
  406. while (_pSinkHead != NULL)
  407. {
  408. CSinkList *pSinkNext = _pSinkHead;
  409. delete _pSinkHead;
  410. _pSinkHead = pSinkNext;
  411. }
  412. pcp->ReleaseCS();
  413. ReleaseCS();
  414. return sc;
  415. }
  416. //+---------------------------------------------------------------------------
  417. //
  418. // Member: CConnectionPoint:: Advise, public
  419. //
  420. // Synopsis:
  421. //
  422. // Arguments:
  423. //
  424. // Returns: Appropriate status code
  425. //
  426. // Modifies:
  427. //
  428. // History: 29-Dec-95 SusiA Created
  429. //
  430. // Notes:
  431. //
  432. //----------------------------------------------------------------------------
  433. #ifdef ASYNC
  434. STDMETHODIMP CConnectionPoint::AddConnection(IProgressNotify *pSink,
  435. DWORD *pdwCookie)
  436. #else
  437. STDMETHODIMP CConnectionPoint::Advise(IUnknown *pUnkSink,
  438. DWORD *pdwCookie)
  439. #endif
  440. {
  441. SCODE sc = S_OK;
  442. CSinkList *pslNew = NULL;
  443. CSinkList *pslTemp = _pSinkHead;
  444. astgDebugOut((DEB_ITRACE, "In CConnectionPoint::Advise:%p()\n", this));
  445. TakeCS();
  446. IProgressNotify *ppn;
  447. astgMem(pslNew = new CSinkList);
  448. *pdwCookie = ++_dwCookie;
  449. pslNew->SetCookie(*pdwCookie);
  450. #ifdef ASYNC
  451. pSink->AddRef();
  452. pslNew->SetProgressNotify(pSink);
  453. #else
  454. void *pv;
  455. //Note: The QueryInterface will give us a reference to hold on to.
  456. astgChk(pUnkSink->QueryInterface(IID_IProgressNotify, &pv));
  457. pslNew->SetProgressNotify((IProgressNotify *)pv);
  458. #endif
  459. //Add new node to end of list
  460. if (pslTemp == NULL)
  461. _pSinkHead = pslNew;
  462. else
  463. {
  464. while(pslTemp->GetNext() != NULL)
  465. pslTemp = pslTemp->GetNext();
  466. pslTemp->SetNext(pslNew);
  467. }
  468. ReleaseCS();
  469. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::Advise\n"));
  470. return sc;
  471. Err:
  472. ReleaseCS();
  473. delete pslNew;
  474. return sc;
  475. }
  476. //+---------------------------------------------------------------------------
  477. //
  478. // Member: CConnectionPoint::Unadvise, public
  479. //
  480. // Synopsis:
  481. //
  482. // Arguments:
  483. //
  484. // Returns: Appropriate status code
  485. //
  486. // Modifies:
  487. //
  488. // History: 30-Dec-95 SusiA Created
  489. //
  490. // Notes:
  491. //
  492. //----------------------------------------------------------------------------
  493. #ifdef ASYNC
  494. STDMETHODIMP CConnectionPoint::RemoveConnection(DWORD dwCookie)
  495. #else
  496. STDMETHODIMP CConnectionPoint::Unadvise(DWORD dwCookie)
  497. #endif
  498. {
  499. CSinkList *pslTemp;
  500. CSinkList *pslPrev;
  501. astgDebugOut((DEB_ITRACE, "In CConnectionPoint::Unadvise:%p()\n", this));
  502. TakeCS();
  503. pslTemp = _pSinkHead;
  504. pslPrev = NULL;
  505. while ((pslTemp != NULL) && (pslTemp->GetCookie() != dwCookie))
  506. {
  507. pslPrev = pslTemp;
  508. pslTemp = pslTemp->GetNext();
  509. }
  510. if (pslTemp != NULL)
  511. {
  512. //Found the sink. Delete it from the list.
  513. if (pslPrev != NULL)
  514. {
  515. pslPrev->SetNext(pslTemp->GetNext());
  516. }
  517. else
  518. {
  519. _pSinkHead = pslTemp->GetNext();
  520. }
  521. pslTemp->GetProgressNotify()->Release();
  522. delete pslTemp;
  523. }
  524. else
  525. { //Client passed in unknown cookie.
  526. ReleaseCS();
  527. return E_UNEXPECTED;
  528. }
  529. ReleaseCS();
  530. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::Unadvise\n"));
  531. return S_OK;
  532. }
  533. #ifndef ASYNC
  534. //+---------------------------------------------------------------------------
  535. //
  536. // Member: CConnectionPoint::EnumConnections, public
  537. //
  538. // Synopsis:
  539. //
  540. // Arguments:
  541. //
  542. // Returns: Appropriate status code
  543. //
  544. // Modifies:
  545. //
  546. // History: 30-Dec-95 SusiA Created
  547. //
  548. // Notes:
  549. //
  550. //----------------------------------------------------------------------------
  551. STDMETHODIMP CConnectionPoint::EnumConnections(
  552. IEnumConnections **ppEnum)
  553. {
  554. astgDebugOut((DEB_ITRACE, "In CConnectionPoint::EnumConnections:%p()\n", this));
  555. astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::EnumConnections\n"));
  556. return E_NOTIMPL;
  557. }
  558. #endif
  559. #ifdef ASYNC
  560. STDMETHODIMP CConnectionPoint::GetParent(IDocfileAsyncConnectionPoint **ppdacp)
  561. {
  562. *ppdacp = _pParentCP;
  563. return S_OK;
  564. }
  565. #endif
  566. void CConnectionPoint::TakeCS(void)
  567. {
  568. astgAssert (_fCSInitialized);
  569. EnterCriticalSection(&_csSinkList);
  570. }
  571. void CConnectionPoint::ReleaseCS(void)
  572. {
  573. astgAssert (_fCSInitialized);
  574. LeaveCriticalSection(&_csSinkList);
  575. }