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.

1637 lines
46 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: MPXBSC.CXX
  7. //
  8. // Contents: Code to handle multiplexing multiple concurrent
  9. // IBindStatusCallback interfaces.
  10. //
  11. // Classes: CBSCHolder
  12. //
  13. // Functions:
  14. //
  15. // History: 01-04-96 JoeS (Joe Souza) Created
  16. // 01-15-96 JohannP (Johann Posch) Modified to new IBSC
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <mon.h>
  20. #include "mpxbsc.hxx"
  21. PerfDbgTag(tagCBSCHolder, "Urlmon", "Log CBSCHolder", DEB_BINDING);
  22. HRESULT GetObjectParam(IBindCtx *pbc, LPOLESTR pszKey, REFIID riid, IUnknown **ppUnk);
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Function: UrlMonInvokeExceptionFilterMSN
  26. //
  27. // Synopsis:
  28. //
  29. // Arguments: [lCode] --
  30. // [lpep] --
  31. //
  32. // Returns:
  33. //
  34. // History: 8-25-97 DanpoZ(Danpo Zhang) Created
  35. //
  36. // Notes:
  37. //
  38. //----------------------------------------------------------------------------
  39. LONG UrlMonInvokeExceptionFilterMSN( DWORD lCode, LPEXCEPTION_POINTERS lpep )
  40. {
  41. DEBUG_ENTER((DBG_CALLBACK,
  42. Int,
  43. "UrlMonInvokeExceptionFilterMSN",
  44. "%#x, %#x",
  45. lCode, lpep
  46. ));
  47. #if DBG == 1
  48. DbgLog2(tagCBSCHolder, NULL, "Exception 0x%#x at address 0x%#x",
  49. lCode, lpep->ExceptionRecord->ExceptionAddress);
  50. DebugBreak();
  51. #endif
  52. LONG exr = EXCEPTION_CONTINUE_EXECUTION;
  53. if( lCode == STATUS_ACCESS_VIOLATION )
  54. {
  55. char achProgname[256];
  56. achProgname[0] = 0;
  57. GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
  58. if( StrStrI(achProgname, "msnviewr.exe") )
  59. {
  60. exr = EXCEPTION_EXECUTE_HANDLER;
  61. }
  62. }
  63. DEBUG_LEAVE(exr);
  64. return exr;
  65. }
  66. //+---------------------------------------------------------------------------
  67. //
  68. // Function: GetBSCHolder
  69. //
  70. // Synopsis: Returns a holder for IBindStatusCallback
  71. //
  72. // Arguments: [pBC] --
  73. // [ppCBSHolder] --
  74. //
  75. // Returns:
  76. //
  77. // History:
  78. //
  79. // Notes:
  80. //
  81. //----------------------------------------------------------------------------
  82. HRESULT GetBSCHolder(LPBC pBC, CBSCHolder **ppCBSHolder)
  83. {
  84. DEBUG_ENTER((DBG_CALLBACK,
  85. Hresult,
  86. "GetBSCHolder",
  87. "%#x, %#x",
  88. pBC, ppCBSHolder
  89. ));
  90. PerfDbgLog(tagCBSCHolder, NULL, "+GetBSCHolder");
  91. UrlMkAssert((ppCBSHolder != NULL));
  92. HRESULT hr;
  93. CBSCHolder *pCBSCBHolder = NULL;
  94. hr = GetObjectParam(pBC, REG_BSCB_HOLDER, IID_IBindStatusCallbackHolder, (IUnknown **)&pCBSCBHolder);
  95. if (pCBSCBHolder == NULL)
  96. {
  97. pCBSCBHolder = new CBSCHolder;
  98. if (!pCBSCBHolder)
  99. {
  100. hr = E_OUTOFMEMORY;
  101. }
  102. else
  103. {
  104. hr = pBC->RegisterObjectParam(REG_BSCB_HOLDER, (IBindStatusCallback *) pCBSCBHolder);
  105. *ppCBSHolder = pCBSCBHolder;
  106. }
  107. }
  108. else
  109. {
  110. *ppCBSHolder = pCBSCBHolder;
  111. }
  112. PerfDbgLog1(tagCBSCHolder, NULL, "-GetBSCHolder (hr:%lx)", hr);
  113. DEBUG_LEAVE(hr);
  114. return hr;
  115. }
  116. CBSCHolder::CBSCHolder(void) : _CRefs(), _cElements(0)
  117. {
  118. DEBUG_ENTER((DBG_CALLBACK,
  119. None,
  120. "CBSCHolder::CBSCHolder",
  121. "this=%#x",
  122. this
  123. ));
  124. _pCBSCNode = NULL;
  125. _fBindStarted = FALSE;
  126. _fBindStopped = FALSE;
  127. _fHttpNegotiate = FALSE;
  128. _fAuthenticate = FALSE;
  129. _fHttpNegotiate2 = FALSE;
  130. DEBUG_LEAVE(0);
  131. }
  132. CBSCHolder::~CBSCHolder(void)
  133. {
  134. DEBUG_ENTER((DBG_CALLBACK,
  135. None,
  136. "CBSCHolder::~CBSCHolder",
  137. "this=%#x",
  138. this
  139. ));
  140. CBSCNode *pNode, *pNextNode;
  141. pNode = _pCBSCNode;
  142. while (pNode)
  143. {
  144. pNextNode = pNode->GetNextNode();
  145. delete pNode;
  146. pNode = pNextNode;
  147. }
  148. DEBUG_LEAVE(0);
  149. }
  150. STDMETHODIMP CBSCHolder::QueryInterface(REFIID riid, void **ppvObj)
  151. {
  152. DEBUG_ENTER((DBG_CALLBACK,
  153. Hresult,
  154. "CBSCHolder::IUnknown::QueryInterface",
  155. "this=%#x, %#x, %#x",
  156. this, &riid, ppvObj
  157. ));
  158. VDATEPTROUT(ppvObj, void *);
  159. VDATETHIS(this);
  160. HRESULT hr = NOERROR;
  161. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::QueryInterface");
  162. if ( (riid == IID_IUnknown)
  163. || (riid == IID_IBindStatusCallback)
  164. || (riid == IID_IBindStatusCallbackHolder) )
  165. {
  166. // the holder is not marshalled!!
  167. *ppvObj = (void*)(IBindStatusCallback *) this;
  168. }
  169. else if (riid == IID_IServiceProvider)
  170. {
  171. *ppvObj = (void*)(IServiceProvider *) this;
  172. }
  173. else if (riid == IID_IHttpNegotiate)
  174. {
  175. *ppvObj = (void*)(IHttpNegotiate *) this;
  176. }
  177. else if (riid == IID_IHttpNegotiate2)
  178. {
  179. *ppvObj = (void*)(IHttpNegotiate2 *) this;
  180. }
  181. else if (riid == IID_IAuthenticate)
  182. {
  183. *ppvObj = (void*)(IAuthenticate *) this;
  184. }
  185. else
  186. {
  187. *ppvObj = NULL;
  188. hr = E_NOINTERFACE;
  189. }
  190. if (hr == NOERROR)
  191. {
  192. AddRef();
  193. }
  194. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::QueryInterface (hr:%lx)", hr);
  195. DEBUG_LEAVE(hr);
  196. return hr;
  197. }
  198. STDMETHODIMP_(ULONG) CBSCHolder::AddRef(void)
  199. {
  200. DEBUG_ENTER((DBG_CALLBACK,
  201. Dword,
  202. "CBSCHolder::IUnknown::AddRef",
  203. "this=%#x",
  204. this
  205. ));
  206. LONG lRet = ++_CRefs;
  207. PerfDbgLog1(tagCBSCHolder, this, "CBSCHolder::AddRef (cRefs:%ld)", lRet);
  208. DEBUG_LEAVE(lRet);
  209. return lRet;
  210. }
  211. STDMETHODIMP_(ULONG) CBSCHolder::Release(void)
  212. {
  213. DEBUG_ENTER((DBG_CALLBACK,
  214. Dword,
  215. "CBSCHolder::IUnknown::Release",
  216. "this=%#x",
  217. this
  218. ));
  219. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::Release");
  220. UrlMkAssert((_CRefs > 0));
  221. LONG lRet = --_CRefs;
  222. if (_CRefs == 0)
  223. {
  224. delete this;
  225. }
  226. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::Release (cRefs:%ld)",lRet);
  227. DEBUG_LEAVE(lRet);
  228. return lRet;
  229. }
  230. //+---------------------------------------------------------------------------
  231. //
  232. // Method: CBSCHolder::GetBindInfo
  233. //
  234. // Synopsis:
  235. //
  236. // Arguments: [grfBINDINFOF] --
  237. // [pbindinfo] --
  238. //
  239. // Returns:
  240. //
  241. // History:
  242. //
  243. // Notes: Only the first BSC which also receives data gets called
  244. //
  245. //----------------------------------------------------------------------------
  246. HRESULT CBSCHolder::GetBindInfo(DWORD *grfBINDINFOF,BINDINFO * pbindinfo)
  247. {
  248. DEBUG_ENTER((DBG_CALLBACK,
  249. Hresult,
  250. "CBSCHolder::IBindStatusCallback::GetBindInfo",
  251. "this=%#x, %#x, %#x",
  252. this, grfBINDINFOF, pbindinfo
  253. ));
  254. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::GetBindInfo");
  255. HRESULT hr = E_FAIL;
  256. CBSCNode *pNode;
  257. pNode = _pCBSCNode;
  258. if (pNode && (pNode->GetFlags() & BSCO_GETBINDINFO))
  259. {
  260. UrlMkAssert(( pbindinfo && (pbindinfo->cbSize == sizeof(BINDINFO)) ));
  261. DEBUG_ENTER((DBG_CALLBACK,
  262. Hresult,
  263. "EXTERNAL_CLIENT::IBindStatusCallback::GetBindInfo",
  264. "this=%#x, %#x, %#x",
  265. pNode->GetBSCB(), grfBINDINFOF, pbindinfo
  266. ));
  267. // We only call the first link for GetBindInfo.
  268. hr = pNode->GetBSCB()->GetBindInfo(grfBINDINFOF, pbindinfo);
  269. DEBUG_LEAVE(hr);
  270. }
  271. else
  272. {
  273. UrlMkAssert((FALSE && "Not IBSC node called on GetBindInfo"));
  274. }
  275. PerfDbgLog2(tagCBSCHolder, this, "-CBSCHolder::CallGetBindInfo (grfBINDINFOF:%lx, hr:%lx)", grfBINDINFOF, hr);
  276. DEBUG_LEAVE(hr);
  277. return hr;
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Method: CBSCHolder::OnStartBinding
  282. //
  283. // Synopsis:
  284. //
  285. // Arguments: [grfBINDINFOF] --
  286. // [pib] --
  287. //
  288. // Returns:
  289. //
  290. // History:
  291. //
  292. // Notes:
  293. //
  294. //----------------------------------------------------------------------------
  295. HRESULT CBSCHolder::OnStartBinding(DWORD grfBINDINFOF, IBinding * pib)
  296. {
  297. DEBUG_ENTER((DBG_CALLBACK,
  298. Hresult,
  299. "CBSCHolder::IBindStatusCallback::OnStartBinding",
  300. "this=%#x, %#x, %#x",
  301. this, grfBINDINFOF, pib
  302. ));
  303. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnStartBinding");
  304. VDATETHIS(this);
  305. HRESULT hr = E_FAIL;
  306. CBSCNode *pNode;
  307. BOOL fFirstNode = TRUE;
  308. _fBindStarted = TRUE;
  309. pNode = _pCBSCNode;
  310. while (pNode)
  311. {
  312. grfBINDINFOF = pNode->GetFlags();
  313. if (fFirstNode)
  314. {
  315. grfBINDINFOF |= (BSCO_ONDATAAVAILABLE | BSCO_ONOBJECTAVAILABLE);
  316. }
  317. else
  318. {
  319. grfBINDINFOF &= ~(BSCO_ONDATAAVAILABLE | BSCO_ONOBJECTAVAILABLE);
  320. }
  321. DbgLog1(tagCBSCHolder, this, "CBSCHolder::OnStartBinding on (IBSC:%lx)", pNode->GetBSCB());
  322. DEBUG_ENTER((DBG_CALLBACK,
  323. Hresult,
  324. "EXTERNAL_CLIENT::IBindStatusCallback::OnStartBinding",
  325. "this=%#x, %#x, %#x",
  326. pNode->GetBSCB(), grfBINDINFOF, pib
  327. ));
  328. hr = pNode->GetBSCB()->OnStartBinding(grfBINDINFOF, pib);
  329. DEBUG_LEAVE(hr);
  330. pNode = pNode->GetNextNode();
  331. fFirstNode = FALSE;
  332. }
  333. // BUGBUG: hr is set to return code only from last node we called.
  334. // Is this what we want?
  335. // What if one of the earlier nodes failed?
  336. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnStartBinding (hr:%lx)", hr);
  337. DEBUG_LEAVE(hr);
  338. return hr;
  339. }
  340. //+---------------------------------------------------------------------------
  341. //
  342. // Method: CBSCHolder::OnProgress
  343. //
  344. // Synopsis:
  345. //
  346. // Arguments: [ULONG] --
  347. // [ulProgressMax] --
  348. // [ulStatusCode] --
  349. // [szStatusText] --
  350. //
  351. // Returns:
  352. //
  353. // History:
  354. //
  355. // Notes:
  356. //
  357. //----------------------------------------------------------------------------
  358. HRESULT CBSCHolder::OnProgress(ULONG ulProgress,ULONG ulProgressMax,
  359. ULONG ulStatusCode, LPCWSTR szStatusText)
  360. {
  361. DEBUG_ENTER((DBG_CALLBACK,
  362. Hresult,
  363. "CBSCHolder::IBindStatusCallback::OnProgress",
  364. "this=%#x, %#x, %#x, %#x, %.80wq",
  365. this, ulProgress, ulProgressMax, ulStatusCode, szStatusText
  366. ));
  367. PerfDbgLog4(tagCBSCHolder, this, "+CBSCHolder::OnProgress (StatusCode:%ld, StatusText:%ws, Progress:%ld, ProgressMax:%ld)",
  368. ulStatusCode, szStatusText?szStatusText:L"", ulProgress, ulProgressMax);
  369. VDATETHIS(this);
  370. HRESULT hr = NOERROR;
  371. CBSCNode *pNode;
  372. pNode = _pCBSCNode;
  373. while (pNode)
  374. {
  375. if (pNode->GetFlags() & BSCO_ONPROGRESS)
  376. {
  377. DEBUG_ENTER((DBG_CALLBACK,
  378. Hresult,
  379. "EXTERNAL_CLIENT::IBindStatusCallback::OnProgress",
  380. "this=%#x, %#x, %#x, %#x, %.80wq",
  381. pNode->GetBSCB(), ulProgress, ulProgressMax, ulStatusCode, szStatusText
  382. ));
  383. hr = pNode->GetBSCB()->OnProgress(ulProgress, ulProgressMax, ulStatusCode,szStatusText);
  384. DEBUG_LEAVE(hr);
  385. }
  386. pNode = pNode->GetNextNode();
  387. }
  388. // BUGBUG: hr is set to return code only from last node we called.
  389. // Is this what we want?
  390. // What if one of the earlier nodes failed?
  391. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnProgress (hr:%lx)", hr);
  392. DEBUG_LEAVE(hr);
  393. return hr;
  394. }
  395. //+---------------------------------------------------------------------------
  396. //
  397. // Method: CBSCHolder::OnDataAvailable
  398. //
  399. // Synopsis:
  400. //
  401. // Arguments: [DWORD] --
  402. // [FORMATETC] --
  403. // [pformatetc] --
  404. // [pstgmed] --
  405. //
  406. // Returns:
  407. //
  408. // History:
  409. //
  410. // Notes:
  411. //
  412. //----------------------------------------------------------------------------
  413. HRESULT CBSCHolder::OnDataAvailable(DWORD grfBSC,DWORD dwSize,FORMATETC *pformatetc, STGMEDIUM *pstgmed)
  414. {
  415. DEBUG_ENTER((DBG_CALLBACK,
  416. Hresult,
  417. "CBSCHolder::IBindStatusCallback::OnDataAvailable",
  418. "this=%#x, %#x, %#x, %#x, %#x",
  419. this, grfBSC, dwSize, pformatetc, pstgmed
  420. ));
  421. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnDataAvailable");
  422. VDATETHIS(this);
  423. HRESULT hr = E_FAIL;
  424. CBSCNode *pNode;
  425. pNode = _pCBSCNode;
  426. if (pNode && (pNode->GetFlags() & BSCO_ONDATAAVAILABLE))
  427. {
  428. DEBUG_ENTER((DBG_CALLBACK,
  429. Hresult,
  430. "EXTERNAL_CLIENT::IBindStatusCallback::OnDataAvailable",
  431. "this=%#x, %#x, %#x, %#x, %#x",
  432. pNode->GetBSCB(), grfBSC, dwSize, pformatetc, pstgmed
  433. ));
  434. hr = pNode->GetBSCB()->OnDataAvailable(grfBSC, dwSize, pformatetc, pstgmed);
  435. DEBUG_LEAVE(hr);
  436. //hr = NOERROR; //Trident BTS->BTO
  437. }
  438. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnDataAvailable (hr:%lx)", hr);
  439. DEBUG_LEAVE(hr);
  440. return hr;
  441. }
  442. //+---------------------------------------------------------------------------
  443. //
  444. // Method: CBSCHolder::OnObjectAvailable
  445. //
  446. // Synopsis:
  447. //
  448. // Arguments: [riid] --
  449. // [punk] --
  450. //
  451. // Returns:
  452. //
  453. // History:
  454. //
  455. // Notes:
  456. //
  457. //----------------------------------------------------------------------------
  458. HRESULT CBSCHolder::OnObjectAvailable(REFIID riid, IUnknown *punk)
  459. {
  460. DEBUG_ENTER((DBG_CALLBACK,
  461. Hresult,
  462. "CBSCHolder::IBindStatusCallback::OnObjectAvailable",
  463. "this=%#x, %#x, %#x",
  464. this, &riid, punk
  465. ));
  466. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnObjectAvailable");
  467. VDATETHIS(this);
  468. CBSCNode *pNode;
  469. pNode = _pCBSCNode;
  470. if (pNode && (pNode->GetFlags() & BSCO_ONOBJECTAVAILABLE))
  471. {
  472. DEBUG_ENTER((DBG_CALLBACK,
  473. Hresult,
  474. "EXTERNAL_CLIENT::IBindStatusCallback::OnObjectAvailable",
  475. "this=%#x, %#x, %#x",
  476. pNode->GetBSCB(), &riid, punk
  477. ));
  478. HRESULT hr = pNode->GetBSCB()->OnObjectAvailable(riid, punk);
  479. DEBUG_LEAVE(hr);
  480. }
  481. PerfDbgLog(tagCBSCHolder, this, "-CBSCHolder::OnObjectAvailable (hr:0)");
  482. DEBUG_LEAVE(NOERROR);
  483. return NOERROR;
  484. }
  485. //+---------------------------------------------------------------------------
  486. //
  487. // Method: CBSCHolder::OnLowResource
  488. //
  489. // Synopsis:
  490. //
  491. // Arguments: [reserved] --
  492. //
  493. // Returns:
  494. //
  495. // History:
  496. //
  497. // Notes:
  498. //
  499. //----------------------------------------------------------------------------
  500. HRESULT CBSCHolder::OnLowResource(DWORD reserved)
  501. {
  502. DEBUG_ENTER((DBG_CALLBACK,
  503. Hresult,
  504. "CBSCHolder::IBindStatusCallback::OnLowResource",
  505. "this=%#x, %#x",
  506. this, reserved
  507. ));
  508. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnLowResource");
  509. VDATETHIS(this);
  510. HRESULT hr = E_FAIL;
  511. CBSCNode *pNode;
  512. pNode = _pCBSCNode;
  513. while (pNode)
  514. {
  515. if (pNode->GetFlags() & BSCO_ONLOWRESOURCE)
  516. {
  517. DEBUG_ENTER((DBG_CALLBACK,
  518. Hresult,
  519. "EXTERNAL_CLIENT::IBindStatusCallback::OnLowResource",
  520. "this=%#x, %#x",
  521. pNode->GetBSCB(), reserved
  522. ));
  523. hr = pNode->GetBSCB()->OnLowResource(reserved);
  524. DEBUG_LEAVE(hr);
  525. }
  526. pNode = pNode->GetNextNode();
  527. }
  528. // BUGBUG: hr is set to return code only from last node we called.
  529. // Is this what we want?
  530. // What if one of the earlier nodes failed?
  531. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnLowResource (hr:%lx)", hr);
  532. DEBUG_LEAVE(hr);
  533. return hr;
  534. }
  535. //+---------------------------------------------------------------------------
  536. //
  537. // Method: CBSCHolder::OnStopBinding
  538. //
  539. // Synopsis:
  540. //
  541. // Arguments: [LPCWSTR] --
  542. // [szError] --
  543. //
  544. // Returns:
  545. //
  546. // History:
  547. //
  548. // Notes:
  549. //
  550. //----------------------------------------------------------------------------
  551. HRESULT CBSCHolder::OnStopBinding(HRESULT hrRes,LPCWSTR szError)
  552. {
  553. DEBUG_ENTER((DBG_CALLBACK,
  554. Hresult,
  555. "CBSCHolder::IBindStatusCallback::OnStopBinding",
  556. "this=%#x, %#x, %.80wq",
  557. this, hrRes, szError
  558. ));
  559. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnStopBinding");
  560. HRESULT hr = E_FAIL;
  561. CBSCNode *pNode;
  562. CBSCNode *pNodeNext;
  563. DWORD dwFault;
  564. VDATETHIS(this);
  565. _fBindStopped = TRUE; // Allow consumer to remove node on OnStopBinding.
  566. pNode = _pCBSCNode;
  567. while (pNode)
  568. {
  569. // save the next node since this node
  570. // we using now might get deleted
  571. // by RevokeBindStatusCallback
  572. pNodeNext = pNode->GetNextNode();
  573. pNode->SetLocalFlags(NODE_FLAG_REMOVEOK);
  574. PerfDbgLog2(tagCBSCHolder, this, "+CBSCHolder::OnStopBinding calling (Node:%lx, IBSC:%lx)",
  575. pNode,pNode->GetBSCB());
  576. // IE4 bug #32739, the CBSC might no longer be there (MSN)
  577. _try
  578. {
  579. DEBUG_ENTER((DBG_CALLBACK,
  580. Hresult,
  581. "EXTERNAL_CLIENT::IBindStatusCallback::OnStopBinding",
  582. "this=%#x, %#x, %.80wq",
  583. pNode->GetBSCB(), hrRes, szError
  584. ));
  585. hr = pNode->GetBSCB()->OnStopBinding(hrRes, szError);
  586. DEBUG_LEAVE(hr);
  587. }
  588. //_except(UrlMonInvokeExceptionFilterMSN(GetExceptionCode(), GetExceptionInformation()))
  589. __except(EXCEPTION_EXECUTE_HANDLER)
  590. {
  591. DEBUG_LEAVE(hr);
  592. #if DBG == 1
  593. {
  594. dwFault = GetExceptionCode();
  595. DbgLog1(tagCBSCHolder, this, "fault 0x%08x at OnStopBinding", dwFault);
  596. }
  597. #endif
  598. }
  599. #ifdef unix
  600. __endexcept
  601. #endif /* unix */
  602. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnStopBinding done (Node:%lx)", pNode);
  603. pNode = pNodeNext;
  604. }
  605. // Reset bind active flags.
  606. _fBindStarted = FALSE;
  607. _fBindStopped = FALSE;
  608. // BUGBUG: hr is set to return code only from last node we called.
  609. // Is this what we want?
  610. // What if one of the earlier nodes failed?
  611. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::OnStopBinding (hr:%lx)", hr);
  612. DEBUG_LEAVE(hr);
  613. return hr;
  614. }
  615. //+---------------------------------------------------------------------------
  616. //
  617. // Method: CBSCHolder::GetPriority
  618. //
  619. // Synopsis:
  620. //
  621. // Arguments: [pnPriority] --
  622. //
  623. // Returns:
  624. //
  625. // History:
  626. //
  627. // Notes:
  628. //
  629. //----------------------------------------------------------------------------
  630. HRESULT CBSCHolder::GetPriority(LONG * pnPriority)
  631. {
  632. DEBUG_ENTER((DBG_CALLBACK,
  633. Hresult,
  634. "CBSCHolder::IBindStatusCallback::GetPriority",
  635. "this=%#x, %#x",
  636. this, pnPriority
  637. ));
  638. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::GetPriority");
  639. HRESULT hr = E_FAIL;
  640. CBSCNode *pNode;
  641. pNode = _pCBSCNode;
  642. if (pNode && (pNode->GetFlags() & BSCO_GETPRIORITY))
  643. {
  644. DEBUG_ENTER((DBG_CALLBACK,
  645. Hresult,
  646. "EXTERNAL_CLIENT::IBindStatusCallback::GetPriority",
  647. "this=%#x, %#x",
  648. pNode->GetBSCB(), pnPriority
  649. ));
  650. hr = pNode->GetBSCB()->GetPriority(pnPriority);
  651. DEBUG_LEAVE(hr);
  652. }
  653. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::GetPriority (hr:%lx)", hr);
  654. DEBUG_LEAVE(S_FALSE);
  655. return S_FALSE;
  656. }
  657. //+---------------------------------------------------------------------------
  658. //
  659. // Method: CBSCHolder::QueryService
  660. //
  661. // Synopsis:
  662. //
  663. // Arguments: [rsid] --
  664. // [iid] --
  665. // [ppvObj] --
  666. //
  667. // Returns:
  668. //
  669. // History: 4-05-96 JohannP (Johann Posch) Created
  670. //
  671. // Notes:
  672. //
  673. //----------------------------------------------------------------------------
  674. HRESULT CBSCHolder::QueryService(REFGUID rsid, REFIID riid, void ** ppvObj)
  675. {
  676. DEBUG_ENTER((DBG_CALLBACK,
  677. Hresult,
  678. "CBSCHolder::IServiceProvider::QueryService",
  679. "this=%#x, %#x, %#x, %#x",
  680. this, &rsid, &riid, ppvObj
  681. ));
  682. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::QueryService");
  683. HRESULT hr = NOERROR;
  684. VDATETHIS(this);
  685. UrlMkAssert((ppvObj));
  686. *ppvObj = 0;
  687. hr = ObtainService(rsid, riid, ppvObj);
  688. UrlMkAssert(( (hr == E_NOINTERFACE) || ((hr == NOERROR) && *ppvObj) ));
  689. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::QueryService (hr:%lx)", hr);
  690. DEBUG_LEAVE(hr);
  691. return hr;
  692. }
  693. //+---------------------------------------------------------------------------
  694. //
  695. // Method: CBSCHolder::BeginningTransaction
  696. //
  697. // Synopsis:
  698. //
  699. // Arguments: [szURL] --
  700. // [szHeaders] --
  701. // [dwReserved] --
  702. // [pszAdditionalHeaders] --
  703. //
  704. // Returns:
  705. //
  706. //
  707. // Notes:
  708. //
  709. //----------------------------------------------------------------------------
  710. HRESULT CBSCHolder::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeaders,
  711. DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
  712. {
  713. DEBUG_ENTER((DBG_CALLBACK,
  714. Hresult,
  715. "CBSCHolder::IHttpNegotiate::BeginningTransaction",
  716. "this=%#x, %.80wq, %.80wq, %#x, %#x",
  717. this, szURL, szHeaders, dwReserved, pszAdditionalHeaders
  718. ));
  719. PerfDbgLog2(tagCBSCHolder, this, "+CBSCHolder::BeginningTransaction (szURL:%ws, szHeaders:%ws)", szURL, XDBG(szHeaders,""));
  720. VDATETHIS(this);
  721. HRESULT hr = NOERROR;
  722. CBSCNode *pNode;
  723. LPWSTR szTmp = NULL, szNew = NULL, szRunning = NULL;
  724. pNode = _pCBSCNode;
  725. UrlMkAssert((szURL));
  726. while (pNode)
  727. {
  728. if (pNode->GetHttpNegotiate())
  729. {
  730. DEBUG_ENTER((DBG_CALLBACK,
  731. Hresult,
  732. "EXTERNAL_CLIENT::IHttpNegotiate::BeginningTransaction",
  733. "this=%#x, %.80wq, %.80wq, %#x, %#x",
  734. pNode->GetHttpNegotiate(), szURL, szHeaders, dwReserved, pszAdditionalHeaders
  735. ));
  736. hr = pNode->GetHttpNegotiate()->BeginningTransaction(szURL, szHeaders, dwReserved, &szNew);
  737. DEBUG_LEAVE(hr);
  738. PerfDbgLog2(tagCBSCHolder, this, "CBSCHolder::BeginningTransaction (IHttpNegotiate:%lx, szNew:%ws)",
  739. pNode->GetHttpNegotiate(), XDBG(szNew,L""));
  740. // shdocvw might return uninitialized hr, so we
  741. // should just check for szNew not NULL and reset hr
  742. if( hr != NOERROR && szNew != NULL )
  743. {
  744. hr = NOERROR;
  745. }
  746. if (hr == NOERROR && szNew != NULL && szRunning != NULL)
  747. {
  748. szTmp = szRunning;
  749. szRunning = new WCHAR [wcslen(szTmp) + 1 + wcslen(szNew) + 1];
  750. if (szRunning)
  751. {
  752. if (szTmp)
  753. {
  754. wcscpy(szRunning, szTmp);
  755. wcscat(szRunning, szNew);
  756. }
  757. else
  758. {
  759. wcscpy(szRunning, szNew);
  760. }
  761. }
  762. else
  763. {
  764. hr = E_OUTOFMEMORY;
  765. }
  766. delete szTmp;
  767. delete szNew;
  768. if (hr != NOERROR)
  769. {
  770. goto BegTransExit;
  771. }
  772. }
  773. else
  774. {
  775. szRunning = szNew;
  776. }
  777. }
  778. pNode = pNode->GetNextNode();
  779. }
  780. *pszAdditionalHeaders = szRunning;
  781. BegTransExit:
  782. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::BeginningTransaction (pszAdditionalHeaders:%ws)", (hr || !*pszAdditionalHeaders) ? L"":*pszAdditionalHeaders);
  783. DEBUG_LEAVE(hr);
  784. return hr;
  785. }
  786. //+---------------------------------------------------------------------------
  787. //
  788. // Method: CBSCHolder::OnResponse
  789. //
  790. // Synopsis:
  791. //
  792. // Arguments: [LPCWSTR] --
  793. // [szResponseHeaders] --
  794. // [LPWSTR] --
  795. // [pszAdditionalRequestHeaders] --
  796. //
  797. // Returns:
  798. //
  799. // History: 4-05-96 JohannP (Johann Posch) Created
  800. //
  801. // Notes:
  802. //
  803. //----------------------------------------------------------------------------
  804. HRESULT CBSCHolder::OnResponse(DWORD dwResponseCode,LPCWSTR wzResponseHeaders,
  805. LPCWSTR wzRequestHeaders,LPWSTR *pszAdditionalRequestHeaders)
  806. {
  807. DEBUG_ENTER((DBG_CALLBACK,
  808. Hresult,
  809. "CBSCHolder::IHttpNegotiate::OnResponse",
  810. "this=%#x, %#x, %.80wq, %.80wq, %#x",
  811. this, dwResponseCode, wzResponseHeaders, wzRequestHeaders, pszAdditionalRequestHeaders
  812. ));
  813. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::OnResponse");
  814. VDATETHIS(this);
  815. HRESULT hr;
  816. CBSCNode *pNode;
  817. LPWSTR szTmp = NULL, szNew = NULL, szRunning = NULL;
  818. pNode = _pCBSCNode;
  819. hr = (IsStatusOk(dwResponseCode)) ? S_OK : S_FALSE;
  820. while (pNode)
  821. {
  822. if (pNode->GetHttpNegotiate())
  823. {
  824. PerfDbgLog1(tagCBSCHolder, this, "+CBSCHolder::OnResponse on Node: %lx", pNode);
  825. DEBUG_ENTER((DBG_CALLBACK,
  826. Hresult,
  827. "EXTERNAL_CLIENT::IHttpNegotiate::OnResponse",
  828. "this=%#x, %#x, %.80wq, %.80wq, %#x",
  829. pNode->GetHttpNegotiate(), dwResponseCode, wzResponseHeaders, wzRequestHeaders, pszAdditionalRequestHeaders
  830. ));
  831. hr = pNode->GetHttpNegotiate()->OnResponse(dwResponseCode, wzResponseHeaders, wzRequestHeaders, &szNew);
  832. DEBUG_LEAVE(hr);
  833. PerfDbgLog2(tagCBSCHolder, this, "-CBSCHolder::OnResponse on Node: %lx, hr:%lx", pNode, hr);
  834. if (hr == NOERROR && szNew != NULL && szRunning != NULL)
  835. {
  836. szTmp = szRunning;
  837. szRunning = new WCHAR [wcslen(szTmp) + 1 + wcslen(szNew) + 1];
  838. if (szRunning)
  839. {
  840. if (szTmp)
  841. {
  842. wcscpy(szRunning, szTmp);
  843. wcscat(szRunning, szNew);
  844. }
  845. else
  846. {
  847. wcscpy(szRunning, szNew);
  848. }
  849. }
  850. else
  851. {
  852. hr = E_OUTOFMEMORY;
  853. }
  854. delete szTmp;
  855. delete szNew;
  856. if (hr != NOERROR)
  857. {
  858. goto OnErrorExit;
  859. }
  860. }
  861. else
  862. {
  863. szRunning = szNew;
  864. }
  865. }
  866. pNode = pNode->GetNextNode();
  867. }
  868. if (pszAdditionalRequestHeaders)
  869. {
  870. *pszAdditionalRequestHeaders = szRunning;
  871. }
  872. if (hr == E_NOTIMPL)
  873. {
  874. hr = NOERROR;
  875. }
  876. OnErrorExit:
  877. PerfDbgLog(tagCBSCHolder, this, "-CBSCHolder::OnResponse");
  878. DEBUG_LEAVE(hr);
  879. return hr;
  880. }
  881. HRESULT CBSCHolder::GetRootSecurityId(BYTE* pbSecurityId, DWORD* cbSecurityId,
  882. DWORD_PTR dwReserved)
  883. {
  884. DEBUG_ENTER((DBG_CALLBACK,
  885. Hresult,
  886. "CBSCHolder::IHttpNegotiate2::GetRootSecurityId",
  887. "this=%#x, %#x, %#x, %#x",
  888. this, pbSecurityId, cbSecurityId, dwReserved
  889. ));
  890. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::GetRootSecurityId");
  891. VDATETHIS(this);
  892. HRESULT hr = E_FAIL;
  893. CBSCNode *pNode;
  894. pNode = _pCBSCNode;
  895. while (pNode)
  896. {
  897. if (pNode->GetHttpNegotiate2())
  898. {
  899. DEBUG_ENTER((DBG_CALLBACK,
  900. Hresult,
  901. "EXTERNAL_CLIENT::IHttpNegotiate2::GetRootSecurityId",
  902. "this=%#x, %#x, %#x, %#x",
  903. pNode->GetHttpNegotiate2(), pbSecurityId, cbSecurityId, dwReserved
  904. ));
  905. hr = pNode->GetHttpNegotiate2()->GetRootSecurityId( pbSecurityId, cbSecurityId, dwReserved );
  906. DEBUG_LEAVE(hr);
  907. if (SUCCEEDED(hr))
  908. {
  909. break;
  910. }
  911. }
  912. pNode = pNode->GetNextNode();
  913. }
  914. PerfDbgLog(tagCBSCHolder, this, "-CBSCHolder::Authenticate");
  915. DEBUG_LEAVE(hr);
  916. return hr;
  917. }
  918. //+---------------------------------------------------------------------------
  919. //
  920. // Method: CBSCHolder::Authenticate
  921. //
  922. // Synopsis:
  923. //
  924. // Arguments: [phwnd] --
  925. // [pszUsername] --
  926. // [pszPassword] --
  927. //
  928. // Returns:
  929. //
  930. // History:
  931. //
  932. // Notes:
  933. //
  934. //----------------------------------------------------------------------------
  935. HRESULT CBSCHolder::Authenticate(HWND* phwnd, LPWSTR *pszUsername,
  936. LPWSTR *pszPassword)
  937. {
  938. DEBUG_ENTER((DBG_CALLBACK,
  939. Hresult,
  940. "CBSCHolder::IAuthenticate::Authenticate",
  941. "this=%#x, %#x, %#x, %#x",
  942. this, phwnd, pszUsername, pszPassword
  943. ));
  944. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::Authenticate");
  945. VDATETHIS(this);
  946. HRESULT hr = NOERROR;
  947. CBSCNode *pNode;
  948. pNode = _pCBSCNode;
  949. while (pNode)
  950. {
  951. if (pNode->GetAuthenticate())
  952. {
  953. DEBUG_ENTER((DBG_CALLBACK,
  954. Hresult,
  955. "EXTERNAL_CLIENT::IAuthenticate::Authenticate",
  956. "this=%#x, %#x, %#x, %#x",
  957. pNode->GetAuthenticate(), phwnd, pszUsername, pszPassword
  958. ));
  959. hr = pNode->GetAuthenticate()->Authenticate(phwnd, pszUsername, pszPassword);
  960. DEBUG_LEAVE(hr);
  961. if (hr == S_OK)
  962. {
  963. break;
  964. }
  965. }
  966. pNode = pNode->GetNextNode();
  967. }
  968. PerfDbgLog(tagCBSCHolder, this, "-CBSCHolder::Authenticate");
  969. DEBUG_LEAVE(hr);
  970. return hr;
  971. }
  972. //+---------------------------------------------------------------------------
  973. //
  974. // Method: CBSCHolder::AddNode
  975. //
  976. // Synopsis:
  977. //
  978. // Arguments: [pIBSC] --
  979. // [grfFlags] --
  980. //
  981. // Returns:
  982. //
  983. // History:
  984. //
  985. // Notes:
  986. //
  987. //----------------------------------------------------------------------------
  988. HRESULT CBSCHolder::AddNode(IBindStatusCallback *pIBSC, DWORD grfFlags)
  989. {
  990. DEBUG_ENTER((DBG_CALLBACK,
  991. Hresult,
  992. "CBSCHolder::AddNode",
  993. "this=%#x, %#x, %#x",
  994. this, pIBSC, grfFlags
  995. ));
  996. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::AddNode");
  997. HRESULT hr = NOERROR;
  998. CLock lck(_mxs);
  999. CBSCNode *pFirstNode = _pCBSCNode;
  1000. CBSCNode *pNode;
  1001. CBSCNode *pNodeTmp;
  1002. LPVOID pvLocal = NULL;
  1003. // No new nodes allowed after binding has started.
  1004. if (_fBindStarted)
  1005. {
  1006. hr = E_FAIL;
  1007. goto AddNodeExit;
  1008. }
  1009. // Allocate memory for new pNode member.
  1010. pNode = new CBSCNode(pIBSC, grfFlags);
  1011. if (!pNode)
  1012. {
  1013. hr = E_OUTOFMEMORY;
  1014. }
  1015. else
  1016. {
  1017. // addref the IBSC pointer
  1018. pIBSC->AddRef();
  1019. // QI for IServiceProvider - QI addref IBSC
  1020. if (pIBSC->QueryInterface(IID_IServiceProvider, &pvLocal) == NOERROR)
  1021. {
  1022. pNode->SetServiceProvider((IServiceProvider *)pvLocal);
  1023. }
  1024. PerfDbgLog3(tagCBSCHolder, this, "CBSCHolder::AddNode (New Node:%lx, IBSC:%lx, IServiceProvider:%lx)",
  1025. pNode, pNode->GetBSCB(), pvLocal);
  1026. // If we have a node already
  1027. if (pFirstNode)
  1028. {
  1029. if (pNode->GetFlags() & BSCO_ONDATAAVAILABLE)
  1030. {
  1031. // If the new node gets the data, link it first.
  1032. pNode->SetNextNode(pFirstNode);
  1033. _pCBSCNode = pNode;
  1034. }
  1035. else
  1036. {
  1037. // The new node does not get data, link it second in list.
  1038. pNodeTmp = pFirstNode->GetNextNode();
  1039. pFirstNode->SetNextNode(pNode);
  1040. pNode->SetNextNode(pNodeTmp);
  1041. }
  1042. }
  1043. else
  1044. {
  1045. _pCBSCNode = pNode;
  1046. }
  1047. _cElements++;
  1048. }
  1049. AddNodeExit:
  1050. PerfDbgLog2(tagCBSCHolder, this, "-CBSCHolder::AddNode (NewNode:%lx, hr:%lx)", pNode, hr);
  1051. DEBUG_LEAVE(hr);
  1052. return hr;
  1053. }
  1054. //+---------------------------------------------------------------------------
  1055. //
  1056. // Method: CBSCHolder::RemoveNode
  1057. //
  1058. // Synopsis:
  1059. //
  1060. // Arguments: [pIBSC] --
  1061. //
  1062. // Returns:
  1063. //
  1064. // History:
  1065. //
  1066. // Notes:
  1067. //
  1068. //----------------------------------------------------------------------------
  1069. HRESULT CBSCHolder::RemoveNode(IBindStatusCallback *pIBSC)
  1070. {
  1071. DEBUG_ENTER((DBG_CALLBACK,
  1072. Hresult,
  1073. "CBSCHolder::RemoveNode",
  1074. "this=%#x, %#x",
  1075. this, pIBSC
  1076. ));
  1077. PerfDbgLog1(tagCBSCHolder, this, "+CBSCHolder::RemoveNode (IBSC:%lx)", pIBSC);
  1078. HRESULT hr = E_FAIL;
  1079. CLock lck(_mxs);
  1080. CBSCNode *pNextNode = NULL;
  1081. CBSCNode *pPrevNode = _pCBSCNode;
  1082. // If binding has started, removal of nodes not allowed until binding stops.
  1083. if (_fBindStarted && !_fBindStopped)
  1084. {
  1085. UrlMkAssert((FALSE && "IBSC in use - can not be revoked"));
  1086. goto RemoveNodeExit;
  1087. }
  1088. if (pPrevNode)
  1089. {
  1090. pNextNode = pPrevNode->GetNextNode();
  1091. }
  1092. else
  1093. {
  1094. TransAssert((_cElements == 0));
  1095. hr = S_FALSE;
  1096. goto RemoveNodeExit;
  1097. }
  1098. if (_pCBSCNode->GetBSCB() == pIBSC)
  1099. {
  1100. UrlMkAssert((_pCBSCNode->GetBSCB() == pIBSC));
  1101. if (!_fBindStarted || _pCBSCNode->CheckLocalFlags(NODE_FLAG_REMOVEOK))
  1102. {
  1103. PerfDbgLog2(tagCBSCHolder, this, "CBSCHolder::RemoveNode (Delete Node:%lx, IBSC:%lx)",
  1104. _pCBSCNode, _pCBSCNode->GetBSCB());
  1105. // release all obtained objects in the disdructor
  1106. delete _pCBSCNode;
  1107. _pCBSCNode = pNextNode;
  1108. _cElements--;
  1109. if (_cElements == 0)
  1110. {
  1111. hr = S_FALSE;
  1112. }
  1113. else
  1114. {
  1115. hr = S_OK;
  1116. }
  1117. }
  1118. }
  1119. else while (pNextNode)
  1120. {
  1121. PerfDbgLog2(tagCBSCHolder, this, "CBSCHolder::RemoveNode (pNextNode:%lx, pNextNode->pIBSC:%lx)",pNextNode,pNextNode->GetBSCB());
  1122. if (pNextNode->GetBSCB() == pIBSC && (!_fBindStarted || pNextNode->CheckLocalFlags(NODE_FLAG_REMOVEOK)))
  1123. {
  1124. //we found the Node
  1125. if (pPrevNode)
  1126. {
  1127. pPrevNode->SetNextNode(pNextNode->GetNextNode());
  1128. }
  1129. PerfDbgLog2(tagCBSCHolder, this, "CBSCHolder::RemoveNode (Delete Node:%lx, IBSC:%lx)",
  1130. pNextNode,pNextNode->GetBSCB());
  1131. // release all obtained objects in the disdructor
  1132. delete pNextNode;
  1133. hr = S_OK;
  1134. _cElements--;
  1135. UrlMkAssert((_cElements > 0));
  1136. break;
  1137. }
  1138. else
  1139. {
  1140. pPrevNode = pNextNode;
  1141. pNextNode = pNextNode->GetNextNode();
  1142. }
  1143. UrlMkAssert((hr == S_OK && "Node not found"));
  1144. }
  1145. RemoveNodeExit:
  1146. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::RemoveNode (hr:%lx)", hr);
  1147. DEBUG_LEAVE(hr);
  1148. return hr;
  1149. }
  1150. //+---------------------------------------------------------------------------
  1151. //
  1152. // Method: CBSCHolder::SetMainNode
  1153. //
  1154. // Synopsis:
  1155. //
  1156. // Arguments: [pIBSC] --
  1157. // [ppIBSCPrev] --
  1158. //
  1159. // Returns:
  1160. //
  1161. // History: 5-08-96 JohannP (Johann Posch) Created
  1162. //
  1163. // Notes:
  1164. //
  1165. //----------------------------------------------------------------------------
  1166. HRESULT CBSCHolder::SetMainNode(IBindStatusCallback *pIBSC, IBindStatusCallback **ppIBSCPrev)
  1167. {
  1168. DEBUG_ENTER((DBG_CALLBACK,
  1169. Hresult,
  1170. "CBSCHolder::SetMainNode",
  1171. "this=%#x, %#x, #x",
  1172. this, pIBSC, ppIBSCPrev
  1173. ));
  1174. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::SetMainNode");
  1175. HRESULT hr = NOERROR;
  1176. CLock lck(_mxs);
  1177. CBSCNode *pFirstNode = _pCBSCNode;
  1178. CBSCNode *pNode;
  1179. CBSCNode *pNodeTmp;
  1180. LPVOID pvLocal = NULL;
  1181. // No new nodes allowed after binding has started.
  1182. if (_fBindStarted)
  1183. {
  1184. hr = E_FAIL;
  1185. goto GetFirsNodeExit;
  1186. }
  1187. if (pFirstNode)
  1188. {
  1189. IBindStatusCallback *pBSC = pFirstNode->GetBSCB();
  1190. // addref the node here and return it
  1191. if (ppIBSCPrev)
  1192. {
  1193. pBSC->AddRef();
  1194. *ppIBSCPrev = pBSC;
  1195. }
  1196. hr = RemoveNode(pBSC);
  1197. }
  1198. pFirstNode = _pCBSCNode;
  1199. // Allocate memory for new pNode member.
  1200. pNode = new CBSCNode(pIBSC, BSCO_ALLONIBSC);
  1201. if (!pNode)
  1202. {
  1203. hr = E_OUTOFMEMORY;
  1204. }
  1205. else
  1206. {
  1207. // addref the IBSC pointer
  1208. pIBSC->AddRef();
  1209. hr = NOERROR;
  1210. // QI for IServiceProvider - QI addref IBSC
  1211. if (pIBSC->QueryInterface(IID_IServiceProvider, &pvLocal) == NOERROR)
  1212. {
  1213. pNode->SetServiceProvider((IServiceProvider *)pvLocal);
  1214. }
  1215. PerfDbgLog3(tagCBSCHolder, this, "CBSCHolder::SetMainNode (New Node:%lx, IBSC:%lx, IServiceProvider:%lx)",
  1216. pNode, pNode->GetBSCB(), pvLocal);
  1217. // If we have a node already
  1218. if (pFirstNode)
  1219. {
  1220. if (pNode->GetFlags() & BSCO_ONDATAAVAILABLE)
  1221. {
  1222. // If the new node gets the data, link it first.
  1223. pNode->SetNextNode(pFirstNode);
  1224. _pCBSCNode = pNode;
  1225. }
  1226. else
  1227. {
  1228. // The new node does not get data, link it second in list.
  1229. pNodeTmp = pFirstNode->GetNextNode();
  1230. pFirstNode->SetNextNode(pNode);
  1231. pNode->SetNextNode(pNodeTmp);
  1232. }
  1233. }
  1234. else
  1235. {
  1236. _pCBSCNode = pNode;
  1237. }
  1238. _cElements++;
  1239. }
  1240. GetFirsNodeExit:
  1241. PerfDbgLog2(tagCBSCHolder, this, "-CBSCHolder::SetMainNode (NewNode:%lx, hr:%lx)", pNode, hr);
  1242. DEBUG_LEAVE(hr);
  1243. return hr;
  1244. }
  1245. //+---------------------------------------------------------------------------
  1246. //
  1247. // Method: CBSCHolder::ObtainService
  1248. //
  1249. // Synopsis: Retrieves the requested service with QI and QueryService
  1250. // for all nodes. The interfaces is addref'd and kept in the node.
  1251. //
  1252. // Arguments: [rsid] --
  1253. // [riid] --
  1254. //
  1255. // Returns:
  1256. //
  1257. // History: 4-09-96 JohannP (Johann Posch) Created
  1258. //
  1259. // Notes: The obtained interfaces are released in the disdructor of the
  1260. // CNode.
  1261. //
  1262. //----------------------------------------------------------------------------
  1263. HRESULT CBSCHolder::ObtainService(REFGUID rsid, REFIID riid, void ** ppvObj)
  1264. {
  1265. DEBUG_ENTER((DBG_CALLBACK,
  1266. Hresult,
  1267. "CBSCHolder::ObtainService",
  1268. "this=%#x, %#x, #x, %#x",
  1269. this, &rsid, &riid, ppvObj
  1270. ));
  1271. PerfDbgLog(tagCBSCHolder, this, "+CBSCHolder::ObtainService");
  1272. HRESULT hr = NOERROR;
  1273. CBSCNode *pNode;
  1274. VDATETHIS(this);
  1275. LPVOID pvLocal = NULL;
  1276. pNode = _pCBSCNode;
  1277. // the old code was under the assumption that rsid was always the same
  1278. // as riid. it checked riid when it should have been checking rsid, and it
  1279. // always passed riid on in the place of rsid! All callers that I've
  1280. // seen that use IID_IHttpNegotiate and IID_IAuthenticate pass the
  1281. // same iid in both rsid and riid, so fixing this should be safe.
  1282. if (rsid == IID_IHttpNegotiate)
  1283. {
  1284. *ppvObj = (void*)(IHttpNegotiate *) this;
  1285. AddRef();
  1286. // loop once to get all interfaces
  1287. if (!_fHttpNegotiate)
  1288. {
  1289. while (pNode)
  1290. {
  1291. if ( (pNode->GetBSCB()->QueryInterface(riid, &pvLocal) == NOERROR)
  1292. || ( pNode->GetServiceProvider()
  1293. && (pNode->GetHttpNegotiate() == NULL)
  1294. && (pNode->GetServiceProvider()->QueryService(rsid, riid, &pvLocal)) == NOERROR)
  1295. )
  1296. {
  1297. // Note: the interface is addref'd by QI or QS
  1298. pNode->SetHttpNegotiate((IHttpNegotiate *)pvLocal);
  1299. }
  1300. pNode = pNode->GetNextNode();
  1301. }
  1302. _fHttpNegotiate = TRUE;
  1303. }
  1304. }
  1305. else if (rsid == IID_IAuthenticate)
  1306. {
  1307. *ppvObj = (void*)(IAuthenticate *) this;
  1308. AddRef();
  1309. if (!_fAuthenticate)
  1310. {
  1311. while (pNode)
  1312. {
  1313. if ( (pNode->GetBSCB()->QueryInterface(riid, &pvLocal) == NOERROR)
  1314. || ( pNode->GetServiceProvider()
  1315. && (pNode->GetAuthenticate() == NULL)
  1316. && (pNode->GetServiceProvider()->QueryService(rsid, riid, &pvLocal)) == NOERROR)
  1317. )
  1318. {
  1319. // Note: the interface is addref'd by QI or QS
  1320. pNode->SetAuthenticate((IAuthenticate *)pvLocal);
  1321. }
  1322. pNode = pNode->GetNextNode();
  1323. }
  1324. _fAuthenticate = TRUE;
  1325. }
  1326. }
  1327. else if (rsid == IID_IHttpNegotiate2)
  1328. {
  1329. *ppvObj = (void*)(IHttpNegotiate2 *) this;
  1330. AddRef();
  1331. // loop once to get all interfaces
  1332. if (!_fHttpNegotiate2)
  1333. {
  1334. while (pNode)
  1335. {
  1336. if ( (pNode->GetBSCB()->QueryInterface(riid, &pvLocal) == NOERROR)
  1337. || ( pNode->GetServiceProvider()
  1338. && (pNode->GetHttpNegotiate2() == NULL)
  1339. && (pNode->GetServiceProvider()->QueryService(rsid, riid, &pvLocal)) == NOERROR)
  1340. )
  1341. {
  1342. // Note: the interface is addref'd by QI or QS
  1343. pNode->SetHttpNegotiate2((IHttpNegotiate2 *)pvLocal);
  1344. }
  1345. pNode = pNode->GetNextNode();
  1346. }
  1347. _fHttpNegotiate2 = TRUE;
  1348. }
  1349. }
  1350. else
  1351. {
  1352. *ppvObj = NULL;
  1353. hr = E_NOINTERFACE;
  1354. while (pNode)
  1355. {
  1356. // old urlmon code did a QueryInterface on this object (CBSCHolder)
  1357. // without regard to rsid. That's QueryService badness, but CINet
  1358. // (and several other places) call QueryService using the same rsid/riid
  1359. // (in this case IID_IHttpSecurity) and *expect* the below QI to pick
  1360. // the interface off the BSCB. We should create an URLMON service id
  1361. // that means "ask the BSCB for this interface" and use that...
  1362. if ( (pNode->GetBSCB()->QueryInterface(riid, &pvLocal) == NOERROR)
  1363. || (pNode->GetServiceProvider()
  1364. && (pNode->GetServiceProvider()->QueryService(rsid, riid, &pvLocal)) == NOERROR)
  1365. )
  1366. {
  1367. *ppvObj = pvLocal;
  1368. hr = NOERROR;
  1369. // Note: the interface is addref'd by QI or QS
  1370. // stop looking at other nodes for this service
  1371. pNode = NULL;
  1372. }
  1373. if (pNode)
  1374. {
  1375. pNode = pNode->GetNextNode();
  1376. }
  1377. }
  1378. }
  1379. PerfDbgLog1(tagCBSCHolder, this, "-CBSCHolder::ObtainService (hr:%lx)", hr);
  1380. DEBUG_LEAVE(hr);
  1381. return hr;
  1382. }