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.

776 lines
21 KiB

  1. // ===========================================================================
  2. // File: CDL.CXX
  3. // The main code downloader file.
  4. //
  5. #include <cdlpch.h>
  6. // ---------------------------------------------------------------------------
  7. // %%Function: CClBinding::CClBinding
  8. // CClBinding (For client's IBinding for code download)
  9. // ---------------------------------------------------------------------------
  10. CClBinding::CClBinding(
  11. CCodeDownload *pcdl,
  12. IBindStatusCallback *pAssClientBSC,
  13. IBindCtx *pAssClientBC,
  14. REFCLSID rclsid,
  15. DWORD dwClsContext,
  16. LPVOID pvReserved,
  17. REFIID riid,
  18. IInternetHostSecurityManager *pHostSecurityManager): m_riid(riid)
  19. {
  20. DEBUG_ENTER((DBG_DOWNLOAD,
  21. None,
  22. "CClBinding::CClBinding",
  23. "this=%#x, %#x, %#x, %#x, %#x, %#x, %#x, %#x",
  24. this, pcdl, pAssClientBSC, pAssClientBC, &rclsid, dwClsContext, pvReserved, &riid,
  25. pHostSecurityManager
  26. ));
  27. m_cRef = 1; //equ of an internal addref
  28. m_dwState = CDL_NoOperation;
  29. m_pcdl = pcdl;
  30. m_pAssClientBSC = pAssClientBSC;
  31. m_pAssClientBC = pAssClientBC;
  32. m_pCodeInstall = NULL;
  33. m_pWindowForBindingUI = NULL;
  34. m_wszClassString = NULL;
  35. m_pHostSecurityManager = pHostSecurityManager;
  36. if (m_pHostSecurityManager)
  37. m_pHostSecurityManager->AddRef();
  38. m_pBindHost = NULL;
  39. m_hWnd = (HWND)INVALID_HANDLE_VALUE;
  40. m_dwClsContext = dwClsContext;
  41. m_pvReserved = pvReserved;
  42. memcpy(&m_clsid, &rclsid, sizeof(GUID));
  43. DEBUG_LEAVE(0);
  44. } // CClBinding
  45. // ---------------------------------------------------------------------------
  46. // %%Function: CClBinding::~CClBinding
  47. // ---------------------------------------------------------------------------
  48. CClBinding::~CClBinding()
  49. {
  50. DEBUG_ENTER((DBG_DOWNLOAD,
  51. None,
  52. "CClBinding::~CClBinding",
  53. "this=%#x",
  54. this
  55. ));
  56. if (m_wszClassString) {
  57. delete [] m_wszClassString;
  58. }
  59. DEBUG_LEAVE(0);
  60. } // ~CClBinding
  61. // ---------------------------------------------------------------------------
  62. // %%Function: CClBinding::ReleaseClient
  63. // ---------------------------------------------------------------------------
  64. HRESULT
  65. CClBinding::ReleaseClient()
  66. {
  67. DEBUG_ENTER((DBG_DOWNLOAD,
  68. Hresult,
  69. "CClBinding::ReleaseClient",
  70. "this=%#x",
  71. this
  72. ));
  73. SAFERELEASE(m_pAssClientBSC);
  74. SAFERELEASE(m_pAssClientBC);
  75. SAFERELEASE(m_pCodeInstall);
  76. SAFERELEASE(m_pWindowForBindingUI);
  77. SAFERELEASE(m_pBindHost);
  78. SAFERELEASE(m_pHostSecurityManager );
  79. DEBUG_LEAVE(S_OK);
  80. return S_OK;
  81. }
  82. // ---------------------------------------------------------------------------
  83. // %%Function: CClBinding::GetHWnd
  84. // ---------------------------------------------------------------------------
  85. HWND
  86. CClBinding::GetHWND(REFGUID rguidReason)
  87. {
  88. DEBUG_ENTER((DBG_DOWNLOAD,
  89. Dword,
  90. "CClBinding::GetHWND",
  91. "this=%#x, %#x",
  92. this, &rguidReason
  93. ));
  94. m_hWnd = (HWND)INVALID_HANDLE_VALUE; // don't cache hwnd
  95. // this degrades will
  96. // if CSite goes away but
  97. // code download was not
  98. // aborted.
  99. if (m_pcdl->IsSilentMode()) {
  100. DEBUG_LEAVE(m_hWnd);
  101. return m_hWnd;
  102. }
  103. GetIWindowForBindingUI();
  104. if (m_pWindowForBindingUI) {
  105. m_pWindowForBindingUI->GetWindow(rguidReason, &m_hWnd);
  106. } else {
  107. GetICodeInstall();
  108. if (m_pCodeInstall)
  109. HRESULT hr = m_pCodeInstall->GetWindow(rguidReason,&m_hWnd);
  110. }
  111. DEBUG_LEAVE(m_hWnd);
  112. return m_hWnd;
  113. }
  114. // ---------------------------------------------------------------------------
  115. // %%Function: GetHostSecurityManager
  116. // ---------------------------------------------------------------------------
  117. IInternetHostSecurityManager*
  118. GetHostSecurityManager(IBindStatusCallback *pclientbsc)
  119. {
  120. DEBUG_ENTER((DBG_DOWNLOAD,
  121. Pointer,
  122. "GetHostSecurityManager",
  123. "%#x",
  124. pclientbsc
  125. ));
  126. IInternetHostSecurityManager *pHostSecurityManager = NULL;
  127. // Get IInternetHostSecurityManager ptr
  128. HRESULT hr = pclientbsc->QueryInterface(IID_IInternetHostSecurityManager,
  129. (LPVOID *)&pHostSecurityManager);
  130. if (FAILED(hr)) {
  131. IServiceProvider *pServProv;
  132. hr = pclientbsc->QueryInterface(IID_IServiceProvider,
  133. (LPVOID *)&pServProv);
  134. if (hr == NOERROR) {
  135. pServProv->QueryService(IID_IInternetHostSecurityManager,IID_IInternetHostSecurityManager,
  136. (LPVOID *)&pHostSecurityManager);
  137. pServProv->Release();
  138. }
  139. }
  140. DEBUG_LEAVE(pHostSecurityManager);
  141. return pHostSecurityManager;
  142. }
  143. // ---------------------------------------------------------------------------
  144. // %%Function: CClBinding::GetHostSecurityManager
  145. // ---------------------------------------------------------------------------
  146. IInternetHostSecurityManager*
  147. CClBinding::GetHostSecurityManager()
  148. {
  149. DEBUG_ENTER((DBG_DOWNLOAD,
  150. Pointer,
  151. "CClBinding::GetHostSecurityManager",
  152. "this=%#x",
  153. this
  154. ));
  155. static BOOL fFailedOnce = FALSE;
  156. if (m_pHostSecurityManager)
  157. {
  158. DEBUG_LEAVE(m_pHostSecurityManager);
  159. return m_pHostSecurityManager;
  160. }
  161. if (fFailedOnce) {
  162. DEBUG_LEAVE(NULL);
  163. return NULL;
  164. }
  165. Assert(m_pcdl);
  166. Assert(m_pcdl->GetClientBSC());
  167. m_pHostSecurityManager = ::GetHostSecurityManager(m_pcdl->GetClientBSC());
  168. if (!m_pHostSecurityManager)
  169. fFailedOnce = TRUE;
  170. DEBUG_LEAVE(m_pHostSecurityManager);
  171. return m_pHostSecurityManager;
  172. }
  173. // ---------------------------------------------------------------------------
  174. // %%Function: CClBinding::GetBindHost
  175. // ---------------------------------------------------------------------------
  176. IBindHost*
  177. CClBinding::GetIBindHost()
  178. {
  179. DEBUG_ENTER((DBG_DOWNLOAD,
  180. Pointer,
  181. "CClBinding::GetIBindHost",
  182. "this=%#x",
  183. this
  184. ));
  185. static BOOL fFailedOnce = FALSE;
  186. if (m_pBindHost)
  187. {
  188. DEBUG_LEAVE(m_pBindHost);
  189. return m_pBindHost;
  190. }
  191. if (fFailedOnce) {
  192. DEBUG_LEAVE(NULL);
  193. return NULL;
  194. }
  195. Assert(m_pcdl);
  196. Assert(m_pcdl->GetClientBSC());
  197. // Get IBindHost ptr
  198. HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IBindHost,
  199. (LPVOID *)&m_pBindHost);
  200. if (FAILED(hr)) {
  201. IServiceProvider *pServProv;
  202. hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider,
  203. (LPVOID *)&pServProv);
  204. if (hr == NOERROR) {
  205. pServProv->QueryService(IID_IBindHost,IID_IBindHost,
  206. (LPVOID *)&m_pBindHost);
  207. pServProv->Release();
  208. }
  209. }
  210. if (!m_pBindHost)
  211. fFailedOnce = TRUE;
  212. DEBUG_LEAVE(m_pBindHost);
  213. return m_pBindHost;
  214. }
  215. // ---------------------------------------------------------------------------
  216. // %%Function: CClBinding::GetIWindowForBindingUI
  217. // ---------------------------------------------------------------------------
  218. IWindowForBindingUI*
  219. CClBinding::GetIWindowForBindingUI()
  220. {
  221. DEBUG_ENTER((DBG_DOWNLOAD,
  222. Pointer,
  223. "CClBinding::GetIWindowForBindingUI",
  224. "this=%#x",
  225. this
  226. ));
  227. if (m_pWindowForBindingUI)
  228. {
  229. DEBUG_LEAVE(m_pWindowForBindingUI);
  230. return m_pWindowForBindingUI;
  231. }
  232. Assert(m_pcdl);
  233. Assert(m_pcdl->GetClientBSC());
  234. // Get IWindowForBindingUI ptr
  235. HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IWindowForBindingUI,
  236. (LPVOID *)&m_pWindowForBindingUI);
  237. if (FAILED(hr)) {
  238. IServiceProvider *pServProv;
  239. hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider,
  240. (LPVOID *)&pServProv);
  241. if (hr == NOERROR) {
  242. pServProv->QueryService(IID_IWindowForBindingUI,IID_IWindowForBindingUI,
  243. (LPVOID *)&m_pWindowForBindingUI);
  244. pServProv->Release();
  245. }
  246. }
  247. if (!m_pWindowForBindingUI) {
  248. m_pcdl->CodeDownloadDebugOut(DEB_CODEDL, FALSE, ID_CDLDBG_NO_IWINDOWFORBINDINGUI);
  249. }
  250. DEBUG_LEAVE(m_pWindowForBindingUI);
  251. return m_pWindowForBindingUI;
  252. }
  253. // ---------------------------------------------------------------------------
  254. // %%Function: CClBinding::GetCodeInstall
  255. // ---------------------------------------------------------------------------
  256. ICodeInstall*
  257. CClBinding::GetICodeInstall()
  258. {
  259. DEBUG_ENTER((DBG_DOWNLOAD,
  260. Pointer,
  261. "CClBinding::GetICodeInstall",
  262. "this=%#x",
  263. this
  264. ));
  265. if (m_pCodeInstall)
  266. {
  267. DEBUG_LEAVE(m_pCodeInstall);
  268. return m_pCodeInstall;
  269. }
  270. Assert(m_pcdl);
  271. Assert(m_pcdl->GetClientBSC());
  272. // Get ICodeInstall ptr
  273. HRESULT hr = m_pcdl->GetClientBSC()->QueryInterface(IID_ICodeInstall,
  274. (LPVOID *)&m_pCodeInstall);
  275. if (FAILED(hr)) {
  276. IServiceProvider *pServProv;
  277. hr = m_pcdl->GetClientBSC()->QueryInterface(IID_IServiceProvider,
  278. (LPVOID *)&pServProv);
  279. if (hr == NOERROR) {
  280. pServProv->QueryService(IID_ICodeInstall,IID_ICodeInstall,
  281. (LPVOID *)&m_pCodeInstall);
  282. pServProv->Release();
  283. }
  284. }
  285. DEBUG_LEAVE(m_pCodeInstall);
  286. return m_pCodeInstall;
  287. }
  288. // ---------------------------------------------------------------------------
  289. // %%Function: CClBinding::AddRef
  290. // ---------------------------------------------------------------------------
  291. STDMETHODIMP_(ULONG)
  292. CClBinding::AddRef()
  293. {
  294. DEBUG_ENTER((DBG_DOWNLOAD,
  295. Dword,
  296. "CClBinding::IUnknown::AddRef",
  297. "this=%#x",
  298. this
  299. ));
  300. ULONG ulRet = m_cRef++;
  301. DEBUG_LEAVE(ulRet);
  302. return ulRet;
  303. }
  304. // ---------------------------------------------------------------------------
  305. // %%Function: CClBinding::Release
  306. // ---------------------------------------------------------------------------
  307. STDMETHODIMP_(ULONG)
  308. CClBinding::Release()
  309. {
  310. DEBUG_ENTER((DBG_DOWNLOAD,
  311. Dword,
  312. "CClBinding::IUnknown::Release",
  313. "this=%#x",
  314. this
  315. ));
  316. if (--m_cRef == 0) {
  317. delete this;
  318. DEBUG_LEAVE(0);
  319. return 0;
  320. }
  321. DEBUG_LEAVE(m_cRef);
  322. return m_cRef;
  323. }
  324. // ---------------------------------------------------------------------------
  325. // %%Function: CClBinding::QueryInterface
  326. // ---------------------------------------------------------------------------
  327. STDMETHODIMP
  328. CClBinding::QueryInterface(REFIID riid, void** ppv)
  329. {
  330. DEBUG_ENTER((DBG_DOWNLOAD,
  331. Pointer,
  332. "CClBinding::IUnknown::QueryInterface",
  333. "this=%#x, %#x, %#x",
  334. this, &riid, ppv
  335. ));
  336. *ppv = NULL;
  337. if (riid==IID_IUnknown || riid==IID_IBinding)
  338. {
  339. *ppv = this;
  340. AddRef();
  341. DEBUG_LEAVE(S_OK);
  342. return S_OK;
  343. }
  344. // BUGBUG: what about IWinInetInfo and IWinsock???
  345. DEBUG_LEAVE(E_NOINTERFACE);
  346. return E_NOINTERFACE;
  347. } // CClBinding::QueryInterface
  348. // ---------------------------------------------------------------------------
  349. // %%Function: CClBinding::Abort( void )
  350. // ---------------------------------------------------------------------------
  351. STDMETHODIMP CClBinding::Abort( void )
  352. {
  353. DEBUG_ENTER((DBG_DOWNLOAD,
  354. Hresult,
  355. "CClBinding::IBinding::Abort",
  356. "this=%#x",
  357. this
  358. ));
  359. Assert(m_pcdl);
  360. HRESULT hr = S_OK;
  361. CDownload *pdl = NULL;
  362. // BUGBUG: need to understand why this pointer might be null
  363. // nothing to do
  364. if (m_pcdl == NULL)
  365. {
  366. DEBUG_LEAVE(S_OK);
  367. return S_OK;
  368. }
  369. //BUGBUG: this is hack fix for a stress bug
  370. __try
  371. {
  372. pdl = m_pcdl->GetDownloadHead();
  373. if (m_pcdl->GetCountClientBindings() > 1)
  374. {
  375. }
  376. pdl->GetDLState();
  377. }
  378. __except(EXCEPTION_EXECUTE_HANDLER)
  379. {
  380. DEBUG_LEAVE(S_OK);
  381. return S_OK;
  382. }
  383. #ifdef unix
  384. __endexcept
  385. #endif /* unix */
  386. if (m_pcdl->GetCountClientBindings() > 1) {
  387. hr = m_pcdl->AbortBinding(this);// not sure what we should do with
  388. // a failed hr!
  389. if (SUCCEEDED(hr))
  390. {
  391. DEBUG_LEAVE(hr);
  392. return hr;
  393. }
  394. //else fall thru to really abort
  395. // we have some bad state inside
  396. }
  397. if (!m_pcdl->SafeToAbort()) {
  398. hr = m_pcdl->HandleUnSafeAbort(); // returns either S_FALSE or error
  399. if (hr == S_FALSE) // chose not to abort
  400. {
  401. DEBUG_LEAVE(hr);
  402. return hr; // indicated that we did not abort
  403. }
  404. else
  405. {
  406. DEBUG_LEAVE(S_OK);
  407. return S_OK; // means DoSetp will abort
  408. }
  409. }
  410. CUrlMkTls tls(hr); // hr passed by reference!
  411. Assert(SUCCEEDED(hr));
  412. Assert(tls->pCDLPacketMgr);
  413. // to mark that atleast one real URLMON bindign was aborted
  414. // in this case URLMON will post an OnStopBinding for that
  415. // and we will end up aborting all other bindings and the whole
  416. // code download. However if that's not the case then we were probably
  417. // in some post binding processing such as verifytrust cab extraction etc
  418. // and so we need to post a DoSetup() packet with UserCancelled flag set.
  419. // forward the call to all our IBindings
  420. do {
  421. if (!pdl->IsSignalled(m_pcdl)) {
  422. // packet processing pending for this state. we will check for
  423. // DLSTATE_ABORT in each packet processing state and if true
  424. // it will call CompleteOne(us), which marks each piece DLSTATE_DONE
  425. hr = pdl->Abort(m_pcdl);
  426. DEBUG_LEAVE(hr);
  427. return hr;
  428. }
  429. } while ((pdl = pdl->GetNext()) != NULL);
  430. m_pcdl->SetUserCancelled();
  431. DEBUG_LEAVE(hr);
  432. return hr;
  433. }
  434. STDMETHODIMP CClBinding::Suspend( void )
  435. {
  436. DEBUG_ENTER((DBG_DOWNLOAD,
  437. Hresult,
  438. "CClBinding::IBinding::Suspend",
  439. "this=%#x",
  440. this
  441. ));
  442. CDownload *pdl = m_pcdl->GetDownloadHead();
  443. if (m_dwState != CDL_Suspend)
  444. m_dwState = CDL_Suspend;
  445. else
  446. {
  447. DEBUG_LEAVE(S_OK);
  448. return S_OK;
  449. }
  450. // forward the call to all our IBindings
  451. do {
  452. if (pdl->GetBSC()->GetBinding())
  453. pdl->GetBSC()->GetBinding()->Suspend();
  454. } while ((pdl = pdl->GetNext()) != NULL);
  455. DEBUG_LEAVE(S_OK);
  456. return S_OK;
  457. }
  458. STDMETHODIMP CClBinding::Resume( void )
  459. {
  460. DEBUG_ENTER((DBG_DOWNLOAD,
  461. Hresult,
  462. "CClBinding::IBinding::Resume",
  463. "this=%#x",
  464. this
  465. ));
  466. CDownload *pdl = m_pcdl->GetDownloadHead();
  467. if (m_dwState == CDL_Suspend)
  468. m_dwState = CDL_Downloading;
  469. else
  470. {
  471. DEBUG_LEAVE(S_OK);
  472. return S_OK;
  473. }
  474. // forward the call to all our IBindings
  475. do {
  476. if (pdl->GetBSC()->GetBinding())
  477. pdl->GetBSC()->GetBinding()->Resume();
  478. } while ((pdl = pdl->GetNext()) != NULL);
  479. DEBUG_LEAVE(S_OK);
  480. return S_OK;
  481. }
  482. STDMETHODIMP CClBinding::SetPriority(LONG nPriority)
  483. {
  484. DEBUG_ENTER((DBG_DOWNLOAD,
  485. Hresult,
  486. "CClBinding::IBinding::SetPriority",
  487. "this=%#x, %#x",
  488. this, nPriority
  489. ));
  490. CDownload *pdl = m_pcdl->GetDownloadHead();
  491. m_nPriority = nPriority; // cache pri
  492. // pass on priorty to our IBindings
  493. do {
  494. if (pdl->GetBSC()->GetBinding())
  495. pdl->GetBSC()->GetBinding()->SetPriority(nPriority);
  496. } while ((pdl = pdl->GetNext()) != NULL);
  497. DEBUG_LEAVE(S_OK);
  498. return S_OK;
  499. }
  500. STDMETHODIMP CClBinding::GetPriority(LONG *pnPriority)
  501. {
  502. DEBUG_ENTER((DBG_DOWNLOAD,
  503. Hresult,
  504. "CClBinding::IBinding::GetPriority",
  505. "this=%#x, %#x",
  506. this, pnPriority
  507. ));
  508. *pnPriority = m_nPriority; // don't need to call our IBindings: pri cached
  509. DEBUG_LEAVE(S_OK);
  510. return S_OK;
  511. }
  512. STDMETHODIMP CClBinding::GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved)
  513. {
  514. DEBUG_ENTER((DBG_DOWNLOAD,
  515. Hresult,
  516. "CClBinding::IBinding::GetBindResult",
  517. "this=%#x, %#x, %#x, %#x, %#x",
  518. this, pclsidProtocol, pdwResult, pszResult, pdwReserved
  519. ));
  520. HRESULT hr = NOERROR;
  521. if (!pdwResult || !pszResult || pdwReserved)
  522. {
  523. hr = E_INVALIDARG;
  524. }
  525. else
  526. {
  527. *pdwResult = NOERROR;
  528. *pszResult = NULL;
  529. }
  530. DEBUG_LEAVE(hr);
  531. return hr;
  532. }
  533. // ---------------------------------------------------------------------------
  534. // %%Function: CClBinding::InstantiateObjectAndReport()
  535. // ---------------------------------------------------------------------------
  536. HRESULT
  537. CClBinding::InstantiateObjectAndReport(CCodeDownload *pcdl)
  538. {
  539. DEBUG_ENTER((DBG_DOWNLOAD,
  540. Hresult,
  541. "CClBinding::InstantiateObjectAndReport",
  542. "this=%#x, %#x",
  543. this, pcdl
  544. ));
  545. HRESULT hr = S_OK;
  546. LPVOID ppv = 0;
  547. CLSID myclsid;
  548. BOOL bLogGenOk;
  549. WCHAR *pwszOSBErrMsg = NULL;
  550. char *pszExactErrMsg = NULL;
  551. hr = GetClsidFromExtOrMime( m_clsid, myclsid, m_pcdl->GetMainExt(), m_pcdl->GetMainType(), NULL);
  552. if (SUCCEEDED(hr))
  553. hr = CoGetClassObject(myclsid, m_dwClsContext, m_pvReserved, m_riid, &ppv);
  554. if (SUCCEEDED(hr)) {
  555. (GetAssBSC())->OnObjectAvailable( m_riid, (IUnknown*) ppv);
  556. Assert(ppv);
  557. // release the IUnkown returned by CoGetClassObject
  558. ((IUnknown*)ppv)->Release();
  559. }
  560. if (FAILED(hr)) {
  561. bLogGenOk = pcdl->GenerateErrStrings(hr, &pszExactErrMsg,
  562. &pwszOSBErrMsg);
  563. if (!bLogGenOk) {
  564. pwszOSBErrMsg = NULL;
  565. pszExactErrMsg = NULL;
  566. }
  567. }
  568. (GetAssBSC())->OnStopBinding(hr, pwszOSBErrMsg);
  569. m_pcdl->CodeDownloadDebugOut(DEB_CODEDL, hr != S_OK, ID_CDLDBG_ONSTOPBINDING_CALLED,
  570. hr, (hr == S_OK)?"(SUCCESS)":"",
  571. myclsid.Data1, m_pcdl->GetMainURL(),
  572. m_pcdl->GetMainType(),
  573. m_pcdl->GetMainExt());
  574. SAFEDELETE(pwszOSBErrMsg);
  575. SAFEDELETE(pszExactErrMsg);
  576. DEBUG_LEAVE(hr);
  577. return hr;
  578. }
  579. HRESULT CClBinding::SetClassString(LPCWSTR pszClassString)
  580. {
  581. DEBUG_ENTER((DBG_DOWNLOAD,
  582. Hresult,
  583. "CClBinding::SetClassString",
  584. "this=%#x, %.80wq",
  585. this, pszClassString
  586. ));
  587. HRESULT hr = S_OK;
  588. if (m_wszClassString) {
  589. delete [] m_wszClassString;
  590. }
  591. if (!pszClassString) {
  592. m_wszClassString = NULL;
  593. }
  594. else {
  595. m_wszClassString = new WCHAR[lstrlenW(pszClassString) + 1];
  596. if (m_wszClassString) {
  597. StrCpyW(m_wszClassString, pszClassString);
  598. }
  599. else {
  600. hr = E_OUTOFMEMORY;
  601. }
  602. }
  603. DEBUG_LEAVE(hr);
  604. return hr;
  605. }
  606. const LPWSTR CClBinding::GetClassString()
  607. {
  608. DEBUG_ENTER((DBG_DOWNLOAD,
  609. Pointer,
  610. "CClBinding::GetClassString",
  611. "this=%#x",
  612. this
  613. ));
  614. DEBUG_LEAVE(m_wszClassString);
  615. return m_wszClassString;
  616. }