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.

772 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cdlprot.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 02-06-1997 t-alans (Alan Shi) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <eapp.h>
  18. #include <tchar.h>
  19. #ifdef unix
  20. #include "../download/cdl.h"
  21. #else
  22. #include "..\download\cdl.h"
  23. #endif /* !unix */
  24. // From shlwapip.h
  25. LWSTDAPI_(HRESULT) CLSIDFromStringWrap(LPOLESTR lpsz, LPCLSID pclsid);
  26. #define VALUE_EQUAL_CHAR '='
  27. #define VALUE_SEPARATOR_CHAR ';'
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Method: CCdlProtocol::CCdlProtocol
  31. //
  32. // Synopsis:
  33. //
  34. // Arguments:
  35. //
  36. //
  37. //
  38. // Returns:
  39. //
  40. // History: 02-06-1997 t-alans (Alan Shi) Created
  41. //
  42. // Notes:
  43. //
  44. //----------------------------------------------------------------------------
  45. CCdlProtocol::CCdlProtocol(REFCLSID rclsid, IUnknown *pUnkOuter,
  46. IUnknown **ppUnkInner)
  47. : CBaseProtocol(rclsid, pUnkOuter, ppUnkInner)
  48. {
  49. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::CCdlProtocol \n", this));
  50. DllAddRef();
  51. _clsidReport = CLSID_NULL;
  52. _pCodeDLBSC = NULL;
  53. _fDataPending = TRUE;
  54. _fNotStarted = TRUE;
  55. _iid = IID_IUnknown;
  56. _pbc = NULL;
  57. _fGetClassObject = FALSE;
  58. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::CCdlProtocol \n", this));
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Method: CCdlProtocol::~CCdlProtocol
  63. //
  64. // Synopsis:
  65. //
  66. // Arguments:
  67. //
  68. //
  69. //
  70. // Returns:
  71. //
  72. // History: 02-06-1997 t-alans (Alan Shi) Created
  73. //
  74. // Notes:
  75. //
  76. //----------------------------------------------------------------------------
  77. CCdlProtocol::~CCdlProtocol()
  78. {
  79. if (_pbc)
  80. {
  81. _pbc->Release();
  82. }
  83. DllRelease();
  84. EProtDebugOut((DEB_PLUGPROT, "%p _IN/OUT CCdlProtocol::~CCdlProtocol \n", this));
  85. }
  86. //+---------------------------------------------------------------------------
  87. //
  88. // Method: CCdlProtocol::Start
  89. //
  90. // Synopsis:
  91. //
  92. // Arguments:
  93. //
  94. //
  95. //
  96. // Returns:
  97. //
  98. // History: 02-06-1997 t-alans (Alan Shi) Created
  99. //
  100. // Notes:
  101. //
  102. //----------------------------------------------------------------------------
  103. #ifdef _WIN64
  104. LWSTDAPI_(BOOL) StrToInt64ExW(LPCWSTR pszString, DWORD dwFlags, LONGLONG * pllRet);
  105. #endif
  106. STDMETHODIMP CCdlProtocol::Start(LPCWSTR pwzUrl,
  107. IOInetProtocolSink *pIOInetProtocolSink,
  108. IOInetBindInfo *pIOInetBindInfo,
  109. DWORD grfSTI,
  110. DWORD_PTR dwReserved)
  111. {
  112. DWORD cElFetched = 0;
  113. LPOLESTR pwzIID = NULL;
  114. BINDINFO bindinfo;
  115. DWORD grfBINDF = 0;
  116. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Start\n", this));
  117. HRESULT hr = NOERROR;
  118. WCHAR wzURL[MAX_URL_SIZE];
  119. EProtAssert((!_pProtSink && pIOInetBindInfo && pIOInetProtocolSink));
  120. EProtAssert((_pwzUrl == NULL));
  121. bindinfo.cbSize = sizeof(BINDINFO);
  122. pIOInetBindInfo->GetBindInfo(&grfBINDF, &bindinfo);
  123. if (grfBINDF & BINDF_GETCLASSOBJECT)
  124. {
  125. LPWSTR pwzBC = NULL;
  126. DWORD cElFetched = 0;
  127. hr = pIOInetBindInfo->GetBindString(BINDSTRING_PTR_BIND_CONTEXT,
  128. &pwzBC, 0,
  129. &cElFetched);
  130. if (SUCCEEDED(hr))
  131. {
  132. #ifdef _WIN64
  133. StrToInt64ExW(pwzBC, 0, (LONGLONG *)&_pbc);
  134. #else
  135. _pbc = (IBindCtx *)StrToIntW(pwzBC);
  136. #endif
  137. EProtAssert(_pbc);
  138. delete [] pwzBC;
  139. pwzBC = NULL;
  140. }
  141. else
  142. {
  143. hr = E_UNEXPECTED;
  144. goto Exit;
  145. }
  146. _fGetClassObject = TRUE;
  147. }
  148. grfSTI |= PI_FORCE_ASYNC;
  149. hr = CBaseProtocol::Start(pwzUrl, pIOInetProtocolSink, pIOInetBindInfo, grfSTI, dwReserved);
  150. if (SUCCEEDED(hr))
  151. {
  152. hr = pIOInetBindInfo->GetBindString(BINDSTRING_IID, &pwzIID, 0,
  153. &cElFetched);
  154. }
  155. if (hr == S_OK)
  156. {
  157. hr = CLSIDFromString(pwzIID, &_iid);
  158. delete [] pwzIID;
  159. }
  160. if (SUCCEEDED(hr))
  161. {
  162. hr = ParseURL();
  163. }
  164. Exit:
  165. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Start (hr:%lx)\n",this, hr));
  166. return hr;
  167. }
  168. //+---------------------------------------------------------------------------
  169. //
  170. // Method: CCdlProtocol::Continue
  171. //
  172. // Synopsis:
  173. //
  174. // Arguments:
  175. //
  176. //
  177. //
  178. // Returns:
  179. //
  180. // History: 02-06-1997 t-alans (Alan Shi) Created
  181. //
  182. // Notes:
  183. //
  184. //----------------------------------------------------------------------------
  185. STDMETHODIMP CCdlProtocol::Continue(PROTOCOLDATA *pStateInfoIn)
  186. {
  187. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Continue\n", this));
  188. HRESULT hr = E_FAIL;
  189. if (_fNotStarted && pStateInfoIn->dwState == CDL_STATE_BIND)
  190. {
  191. _fNotStarted = FALSE;
  192. hr = ParseURL();
  193. }
  194. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Continue (hr:%lx)\n",this, hr));
  195. return hr;
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Method: CCdlProtocol::Read
  200. //
  201. // Synopsis:
  202. //
  203. // Arguments:
  204. //
  205. //
  206. //
  207. // Returns:
  208. //
  209. // History: 02-06-1997 t-alans (Alan Shi) Created
  210. //
  211. // Notes:
  212. //
  213. //----------------------------------------------------------------------------
  214. STDMETHODIMP CCdlProtocol::Read(void *pv,ULONG cb,ULONG *pcbRead)
  215. {
  216. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Read\n", this));
  217. HRESULT hr;
  218. hr = (_fDataPending) ? (E_PENDING) : (S_FALSE);
  219. *pcbRead = (_fDataPending) ? (0x0) : (0x100);
  220. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Read\n", this));
  221. return hr;
  222. }
  223. //+---------------------------------------------------------------------------
  224. //
  225. // Method: CCdlProtocol::Abort
  226. //
  227. // Synopsis:
  228. //
  229. // Arguments:
  230. //
  231. //
  232. //
  233. // Returns:
  234. //
  235. // History: 02-06-1997 t-alans (Alan Shi) Created
  236. //
  237. // Notes:
  238. //
  239. //----------------------------------------------------------------------------
  240. STDMETHODIMP CCdlProtocol::Abort(HRESULT hrReason, DWORD dwOptions)
  241. {
  242. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Abort\n", this));
  243. HRESULT hr = E_UNEXPECTED;
  244. EProtAssert( _pCodeDLBSC != NULL );
  245. if (_pCodeDLBSC != NULL)
  246. {
  247. hr = _pCodeDLBSC->Abort();
  248. }
  249. #if 0
  250. if (_pProtSink)
  251. {
  252. hr = CBaseProtocol::Abort(hrReason, dwOptions);
  253. }
  254. #endif
  255. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Abort\n", this));
  256. return hr;
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Method: CCdlProtocol::Seek
  261. //
  262. // Synopsis:
  263. //
  264. // Arguments:
  265. //
  266. //
  267. //
  268. // Returns:
  269. //
  270. // History: 02-06-1997 t-alans (Alan Shi) Created
  271. //
  272. // Notes:
  273. //
  274. //----------------------------------------------------------------------------
  275. STDMETHODIMP CCdlProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
  276. ULARGE_INTEGER *plibNewPosition)
  277. {
  278. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::Seek\n", this));
  279. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::Seek\n", this));
  280. return E_NOTIMPL;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Method: CCdlProtocol::LockRequest
  285. //
  286. // Synopsis:
  287. //
  288. // Arguments:
  289. //
  290. //
  291. //
  292. // Returns:
  293. //
  294. // History: 02-06-1997 t-alans (Alan Shi) Created
  295. //
  296. // Notes:
  297. //
  298. //----------------------------------------------------------------------------
  299. STDMETHODIMP CCdlProtocol::LockRequest(DWORD dwOptions)
  300. {
  301. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::LockRequest\n", this));
  302. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::LockRequest\n", this));
  303. return E_NOTIMPL;
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // Method: CCdlProtocol::UnlockRequest
  308. //
  309. // Synopsis:
  310. //
  311. // Arguments:
  312. //
  313. //
  314. //
  315. // Returns:
  316. //
  317. // History: 02-06-1997 t-alans (Alan Shi) Created
  318. //
  319. // Notes:
  320. //
  321. //----------------------------------------------------------------------------
  322. STDMETHODIMP CCdlProtocol::UnlockRequest()
  323. {
  324. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::UnlockRequest\n", this));
  325. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::UnlockRequest\n", this));
  326. return E_NOTIMPL;
  327. }
  328. //+---------------------------------------------------------------------------
  329. //
  330. // Method: CCdlProtocol::ParseURL
  331. //
  332. // Synopsis:
  333. //
  334. // Arguments:
  335. //
  336. //
  337. //
  338. // Returns:
  339. //
  340. // History: 02-06-1997 t-alans (Alan Shi) Created
  341. //
  342. // Notes:
  343. //
  344. //----------------------------------------------------------------------------
  345. STDMETHODIMP CCdlProtocol::ParseURL()
  346. {
  347. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::ParseURL\n", this));
  348. HRESULT hr = MK_E_SYNTAX;
  349. WCHAR wzlURL[MAX_URL_SIZE];
  350. LPWSTR pwz = NULL;
  351. LPWSTR pwzValue = NULL;
  352. LPWSTR pwzTag = NULL;
  353. LPWSTR pwzPound = NULL;
  354. BOOL fGotRequiredField = FALSE;
  355. CodeDownloadData cdldata;
  356. CHAR szValue[MAX_PATH];
  357. cdldata.szDistUnit = NULL;
  358. cdldata.szClassString = NULL;
  359. cdldata.szURL = NULL;
  360. cdldata.szMimeType = NULL;
  361. cdldata.szExtension = NULL;
  362. cdldata.szDll = NULL;
  363. cdldata.dwFileVersionMS = 0;
  364. cdldata.dwFileVersionLS = 0;
  365. cdldata.dwFlags = 0;
  366. // URL is of the form:
  367. // (1) cdl://[unused]?[clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
  368. // [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
  369. // [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];...
  370. //
  371. // OR
  372. //
  373. // (2) cdl:[clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];
  374. // [clsid=xxx|codebase=xxx|mimetype=xxx|extension=xxx];...
  375. //
  376. //
  377. // NOTE: [distunit=xxx] added to support AsyncInstallDistributionUnit
  378. // [flags=xxx] added flags (as an integer so that we can dictate
  379. // silent mode, async. etc.
  380. wcscpy(wzlURL, _wzFullURL);
  381. // ensure correct format: "cdl://[stuff]?"
  382. pwz = wcschr(wzlURL, ':');
  383. pwz++;
  384. if (!(wcsnicmp(pwz, L"//", 2) && wcsnicmp(pwz, L"\\\\", 2)))
  385. {
  386. // URL is of form (1)
  387. pwz = wcschr(pwz, '?');
  388. if( pwz == NULL ) {
  389. // error, no '?' found
  390. hr = MK_E_SYNTAX;
  391. goto Exit;
  392. }
  393. pwz++; // pwz now points to the start of the param list (start boundry)
  394. }
  395. pwzValue = pwz + wcslen( pwz ); // points to NULL
  396. // If there is a pound, NULL terminate there instead
  397. pwzPound = pwzValue - 1;
  398. while (pwzPound >= pwz)
  399. {
  400. if (*pwzPound == VALUE_POUND_CHAR)
  401. {
  402. *pwzPound = NULL;
  403. pwzValue = pwzPound;
  404. break;
  405. }
  406. pwzPound--;
  407. }
  408. for ( ;; )
  409. {
  410. while (pwzValue >= pwz && *pwzValue != VALUE_EQUAL_CHAR &&
  411. *pwzValue != VALUE_SEPARATOR_CHAR)
  412. {
  413. pwzValue--;
  414. }
  415. if (pwzValue < pwz || *pwzValue == VALUE_SEPARATOR_CHAR)
  416. {
  417. // error, expected '='
  418. hr = MK_E_SYNTAX;
  419. goto Exit;
  420. }
  421. // pwzValue now points to '='
  422. *pwzValue = NULL;
  423. pwzTag = pwzValue;
  424. pwzValue++;
  425. while (pwzTag >= pwz && *pwzTag != VALUE_EQUAL_CHAR &&
  426. *pwzTag != VALUE_SEPARATOR_CHAR)
  427. {
  428. pwzTag--;
  429. }
  430. if (*pwzTag == VALUE_EQUAL_CHAR)
  431. {
  432. // error, expected either a separator, or the beginning
  433. hr = MK_E_SYNTAX;
  434. goto Exit;
  435. }
  436. pwzTag++;
  437. if (!wcsicmp(L"codebase", pwzTag))
  438. {
  439. cdldata.szURL = pwzValue;
  440. }
  441. else if (!wcsicmp(L"clsid", pwzTag))
  442. {
  443. cdldata.szClassString = pwzValue;
  444. fGotRequiredField = TRUE;
  445. }
  446. else if (!wcsicmp(L"mimetype", pwzTag))
  447. {
  448. cdldata.szMimeType = pwzValue;
  449. fGotRequiredField = TRUE;
  450. }
  451. else if (!wcsicmp(L"extension", pwzTag))
  452. {
  453. cdldata.szExtension = pwzValue;
  454. fGotRequiredField = TRUE;
  455. }
  456. else if (!wcsicmp(L"verMS", pwzTag))
  457. {
  458. //cdldata.dwFileVersionMS = _wtol(pwzValue);
  459. W2A(pwzValue, szValue, MAX_PATH);
  460. cdldata.dwFileVersionMS = atol(szValue);
  461. }
  462. else if (!wcsicmp(L"verLS", pwzTag))
  463. {
  464. //cdldata.dwFileVersionLS = _wtol(pwzValue);
  465. W2A(pwzValue, szValue, MAX_PATH);
  466. cdldata.dwFileVersionLS = atol(szValue);
  467. }
  468. else if (!wcsicmp(L"distunit", pwzTag))
  469. {
  470. cdldata.szDistUnit = pwzValue;
  471. fGotRequiredField = TRUE;
  472. }
  473. else if (!wcsicmp(L"flags", pwzTag))
  474. {
  475. cdldata.dwFlags = StrToIntW(pwzValue);
  476. }
  477. else if (!wcsicmp(L"version", pwzTag))
  478. {
  479. W2A(pwzValue, szValue, MAX_PATH);
  480. GetVersionFromString(szValue, &(cdldata.dwFileVersionMS), &(cdldata.dwFileVersionLS));
  481. }
  482. else if (!wcsicmp(L"dllname",pwzTag))
  483. {
  484. cdldata.szDll = pwzValue;
  485. }
  486. if (pwzTag <= pwz)
  487. {
  488. break; // we are done
  489. }
  490. else
  491. {
  492. pwzValue = pwzTag;
  493. pwzValue--;
  494. *pwzValue = NULL;
  495. pwzTag = NULL;
  496. }
  497. }
  498. // backwards compatability with clsid can be dist unit
  499. if(cdldata.szClassString && ! cdldata.szDistUnit)
  500. {
  501. cdldata.szDistUnit = cdldata.szClassString;
  502. }
  503. if(cdldata.szDistUnit && ! cdldata.szClassString)
  504. {
  505. cdldata.szClassString = cdldata.szDistUnit;
  506. }
  507. if (fGotRequiredField)
  508. {
  509. // The client must provide a host security manager for
  510. // CDL:// protocol bindings. Otherwise, a file:// URL codebase
  511. // will be executed without WVT UI.
  512. IInternetHostSecurityManager *phsm = NULL;
  513. IServiceProvider *psp = NULL;
  514. hr = _pProtSink->QueryInterface(IID_IServiceProvider,
  515. (void **)&psp);
  516. if (FAILED(hr)) {
  517. hr = TRUST_E_FAIL;
  518. goto Exit;
  519. }
  520. hr = psp->QueryService(IID_IInternetHostSecurityManager,
  521. IID_IInternetHostSecurityManager, (void **)&phsm);
  522. if (FAILED(hr)) {
  523. hr = TRUST_E_FAIL;
  524. goto Exit;
  525. }
  526. psp->Release();
  527. phsm->Release();
  528. if (IsEqualGUID(_clsidReport , CLSID_NULL))
  529. CLSIDFromString((LPOLESTR)cdldata.szClassString, &_clsidReport);
  530. hr = StartDownload(cdldata);
  531. }
  532. else
  533. {
  534. hr = MK_E_SYNTAX;
  535. }
  536. Exit:
  537. // if we error for any reason here, then CodeDL BSC was never initiated and we will
  538. // never get an BSC::OSB to shut up sink.
  539. if (hr != E_PENDING)
  540. {
  541. _fDataPending = FALSE;
  542. if (_pProtSink)
  543. {
  544. if (!IsEqualGUID(_clsidReport, CLSID_NULL))
  545. {
  546. LPOLESTR pwzStrClsId;
  547. StringFromCLSID(_clsidReport, &pwzStrClsId);
  548. _pProtSink->ReportProgress(BINDSTATUS_CLSIDCANINSTANTIATE, pwzStrClsId);
  549. delete [] pwzStrClsId;
  550. }
  551. _pProtSink->ReportResult(hr, 0, 0);
  552. }
  553. }
  554. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::ParseURL\n", this));
  555. return hr;
  556. }
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Method: CCdlProtocol::StartDownload
  560. //
  561. // Synopsis:
  562. //
  563. // Arguments:
  564. //
  565. //
  566. //
  567. // Returns:
  568. //
  569. // History: 02-06-1997 t-alans (Alan Shi) Created
  570. //
  571. // Notes:
  572. //
  573. //----------------------------------------------------------------------------
  574. STDMETHODIMP CCdlProtocol::StartDownload(CodeDownloadData &cdldata)
  575. {
  576. EProtDebugOut((DEB_PLUGPROT, "%p _IN CCdlProtocol::StartDownload\n", this));
  577. HRESULT hr = S_OK;
  578. IBindCtx *pbc = NULL;
  579. IUnknown *pUnk = NULL;
  580. // Kick off the download
  581. _pCodeDLBSC = new CCodeDLBSC(_pProtSink, _pOIBindInfo, this, _fGetClassObject);
  582. if (_pCodeDLBSC == NULL)
  583. {
  584. hr = E_OUTOFMEMORY;
  585. goto Exit;
  586. }
  587. hr = CreateBindCtx(0, &pbc);
  588. if (SUCCEEDED(hr))
  589. {
  590. hr = RegisterBindStatusCallback(pbc, _pCodeDLBSC, NULL, 0);
  591. if (_pCodeDLBSC != NULL)
  592. {
  593. _pCodeDLBSC->Release();
  594. }
  595. if (FAILED(hr))
  596. {
  597. goto Exit;
  598. }
  599. }
  600. cdldata.dwFlags = (_fGetClassObject) ? (CD_FLAGS_NEED_CLASSFACTORY) : (0);
  601. hr = AsyncInstallDistributionUnitEx(&cdldata, pbc, _iid, &pUnk, NULL);
  602. if (hr == MK_S_ASYNCHRONOUS)
  603. {
  604. hr = E_PENDING;
  605. }
  606. else
  607. {
  608. if (_fGetClassObject)
  609. {
  610. if (pUnk && SUCCEEDED(hr))
  611. {
  612. hr = RegisterIUnknown(pUnk);
  613. pUnk->Release();
  614. if (SUCCEEDED(hr))
  615. {
  616. hr = _pProtSink->ReportProgress(BINDSTATUS_IUNKNOWNAVAILABLE, NULL);
  617. }
  618. }
  619. _pProtSink->ReportResult(hr, 0, 0);
  620. }
  621. }
  622. Exit:
  623. if (pbc != NULL)
  624. {
  625. // NOTE: This instruction can cause deletion of this object,
  626. // referencing "this" afterwords may be a bad idea.
  627. pbc->Release();
  628. }
  629. EProtDebugOut((DEB_PLUGPROT, "%p OUT CCdlProtocol::StartDownload\n", this));
  630. return hr;
  631. }
  632. //+---------------------------------------------------------------------------
  633. //
  634. // Method: CCdlProtocol::SetDataPending
  635. //
  636. // Synopsis:
  637. //
  638. // Arguments:
  639. //
  640. //
  641. //
  642. // Returns:
  643. //
  644. // History: 02-06-1997 t-alans (Alan Shi) Created
  645. //
  646. // Notes:
  647. //
  648. //----------------------------------------------------------------------------
  649. void CCdlProtocol::SetDataPending(BOOL fPending)
  650. {
  651. _fDataPending = fPending;
  652. }
  653. //+---------------------------------------------------------------------------
  654. //
  655. // Method: CCdlProtocol::RegisterIUnknown
  656. //
  657. // Synopsis:
  658. //
  659. // Arguments:
  660. //
  661. //
  662. //
  663. // Returns:
  664. //
  665. // History: 11-12-1998 AlanShi (Alan Shi) Created
  666. //
  667. // Notes:
  668. //
  669. //----------------------------------------------------------------------------
  670. HRESULT CCdlProtocol::RegisterIUnknown(IUnknown *pUnk)
  671. {
  672. EProtAssert(_pbc);
  673. return _pbc->RegisterObjectParam(SZ_IUNKNOWN_PTR, pUnk);
  674. }