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.

898 lines
20 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: oleimpl.cxx
  4. //
  5. // Contents: This file contins the DLL entry points
  6. // LibMain
  7. // DllGetClassObject (Bindings key func)
  8. // CBasicBndCF (class factory)
  9. // CBasicBnd (actual class implementation)
  10. //
  11. // Classes: CBasicBndCF, CBasicBnd
  12. //
  13. //
  14. // History: 30-Nov-92 SarahJ Created
  15. // 31-Dec-93 ErikGav Chicago port
  16. // 30-Jun-94 AndyH Add call to another DLL
  17. //
  18. //---------------------------------------------------------------------
  19. // Turn off ole Cairol IUnknown
  20. #include <windows.h>
  21. #include <ole2.h>
  22. #include <debnot.h>
  23. #include <com.hxx>
  24. #include "oleimpl.hxx"
  25. extern "C" {
  26. #include "..\oledll2\oledll2.h"
  27. }
  28. ULONG g_UseCount = 0;
  29. CBasicBndCF *g_pcf = NULL;
  30. static const char *szFatalError = "OLEIMPL.DLL - Fatal Error";
  31. void MsgBox(char *pszMsg)
  32. {
  33. MessageBoxA(NULL, pszMsg, szFatalError, MB_OK);
  34. }
  35. void HrMsgBox(char *pszMsg, HRESULT hr)
  36. {
  37. char awcBuf[512];
  38. // Build string for output
  39. wsprintfA(awcBuf, "%s HRESULT = %lx", pszMsg, hr);
  40. // Display message box
  41. MessageBoxA(NULL, &awcBuf[0], szFatalError, MB_OK);
  42. }
  43. //+-------------------------------------------------------------------
  44. //
  45. // Function: LibMain
  46. //
  47. // Synopsis: Entry point to DLL - does little else
  48. // Added call to anther DLL. This is to test loading of in
  49. // InProcServer that uses another statically linked DLL.
  50. // The extra DLL (OleDll2.DLL) should not be on the path
  51. // when the test is run. The entry point FuntionInAnotherDLL
  52. // is exported by OleDll2.DLL
  53. //
  54. // Arguments:
  55. //
  56. // Returns: TRUE
  57. //
  58. // History: 21-Nov-92 SarahJ Created
  59. //
  60. //--------------------------------------------------------------------
  61. //
  62. // Entry point to DLL is traditional LibMain
  63. // Call FunctionInAnotherDLL().
  64. //
  65. extern "C" BOOL _cdecl LibMain ( HINSTANCE hinst,
  66. HANDLE segDS,
  67. UINT cbHeapSize,
  68. LPTSTR lpCmdLine)
  69. {
  70. FunctionInAnotherDLL();
  71. return TRUE;
  72. }
  73. //+-------------------------------------------------------------------
  74. //
  75. // Function: DllGetClassObject
  76. //
  77. // Synopsis: Called by client (from within BindToObject et al)
  78. // interface requested should be IUnknown or IClassFactory -
  79. // Creates ClassFactory object and returns pointer to it
  80. //
  81. // Arguments: REFCLSID clsid - class id
  82. // REFIID iid - interface id
  83. // void FAR* FAR* ppv- pointer to class factory interface
  84. //
  85. // Returns: TRUE
  86. //
  87. // History: 21-Nov-92 SarahJ Created
  88. //
  89. //--------------------------------------------------------------------
  90. STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
  91. {
  92. if (!GuidEqual(iid, IID_IUnknown) && !GuidEqual(iid, IID_IClassFactory))
  93. {
  94. return E_NOINTERFACE;
  95. }
  96. if (GuidEqual(clsid, CLSID_BasicBnd))
  97. {
  98. if (g_pcf)
  99. {
  100. *ppv = g_pcf;
  101. g_pcf->AddRef();
  102. }
  103. else
  104. {
  105. *ppv = new CBasicBndCF();
  106. }
  107. return (*ppv != NULL) ? S_OK : E_FAIL;
  108. }
  109. return E_FAIL;
  110. }
  111. STDAPI DllCanUnloadNow(void)
  112. {
  113. return (g_UseCount == 0)
  114. ? S_OK
  115. : S_FALSE;
  116. }
  117. //+-------------------------------------------------------------------
  118. //
  119. // Class: CBasicBndCF
  120. //
  121. // Synopsis: Class Factory for CBasicBnd
  122. //
  123. // Interfaces: IUnknown - QueryInterface, AddRef, Release
  124. // IClassFactory - CreateInstance
  125. //
  126. // History: 21-Nov-92 SarahJ Created
  127. //
  128. //--------------------------------------------------------------------
  129. //+-------------------------------------------------------------------
  130. //
  131. // Member: CBasicBndCF::CBasicBndCF()
  132. //
  133. // Synopsis: The constructor for CBAsicBnd.
  134. //
  135. // Arguments: None
  136. //
  137. // History: 21-Nov-92 SarahJ Created
  138. //
  139. //--------------------------------------------------------------------
  140. CBasicBndCF::CBasicBndCF() : _cRefs(1)
  141. {
  142. g_UseCount++;
  143. }
  144. //+-------------------------------------------------------------------
  145. //
  146. // Member: CBasicBnd::~CBasicBndObj()
  147. //
  148. // Synopsis: The destructor for CBAsicBnd.
  149. //
  150. // History: 21-Nov-92 SarahJ Created
  151. //
  152. //--------------------------------------------------------------------
  153. CBasicBndCF::~CBasicBndCF()
  154. {
  155. g_UseCount--;
  156. return;
  157. }
  158. //+-------------------------------------------------------------------
  159. //
  160. // Method: CBasicBndCF::QueryInterface
  161. //
  162. // Synopsis: Only IUnknown and IClassFactory supported
  163. //
  164. //--------------------------------------------------------------------
  165. STDMETHODIMP CBasicBndCF::QueryInterface(REFIID iid, void FAR * FAR * ppv)
  166. {
  167. if (GuidEqual(iid, IID_IUnknown) || GuidEqual(iid, IID_IClassFactory))
  168. {
  169. *ppv = this;
  170. AddRef();
  171. return S_OK;
  172. }
  173. else
  174. {
  175. *ppv = NULL;
  176. return E_NOINTERFACE;
  177. }
  178. }
  179. STDMETHODIMP_(ULONG) CBasicBndCF::AddRef(void)
  180. {
  181. return ++_cRefs;
  182. }
  183. STDMETHODIMP_(ULONG) CBasicBndCF::Release(void)
  184. {
  185. ULONG cRefs = --_cRefs;
  186. if (cRefs == 0)
  187. {
  188. delete this;
  189. }
  190. return cRefs;
  191. }
  192. //+-------------------------------------------------------------------
  193. //
  194. // Method: CBasicBndCF::CreateInstance
  195. //
  196. // Synopsis: This is called by Binding process to create the
  197. // actual class object
  198. //
  199. //--------------------------------------------------------------------
  200. STDMETHODIMP CBasicBndCF::CreateInstance(IUnknown FAR* pUnkOuter,
  201. REFIID iidInterface,
  202. void FAR* FAR* ppv)
  203. {
  204. HRESULT hresult = S_OK;
  205. class CUnknownBasicBnd *pubb = new FAR CUnknownBasicBnd(pUnkOuter);
  206. if (pubb == NULL)
  207. {
  208. return E_OUTOFMEMORY;
  209. }
  210. // Because when an aggregate is being requested, the controlling
  211. // must be returned, no QI is necessary.
  212. if (pUnkOuter == NULL)
  213. {
  214. hresult = pubb->QueryInterface(iidInterface, ppv);
  215. pubb->Release();
  216. }
  217. else
  218. {
  219. *ppv = (void *) pubb;
  220. }
  221. return hresult;
  222. }
  223. //+-------------------------------------------------------------------
  224. //
  225. // Method: CBasicBndCF::LockServer
  226. //
  227. // Synopsis: Who knows what this is for?
  228. //
  229. //--------------------------------------------------------------------
  230. STDMETHODIMP CBasicBndCF::LockServer(BOOL fLock)
  231. {
  232. return E_FAIL;
  233. }
  234. //+-------------------------------------------------------------------
  235. //
  236. // Member: CBasicBnd::CBasicBnd()
  237. //
  238. // Synopsis: The constructor for CBAsicBnd. I
  239. //
  240. // Arguments: None
  241. //
  242. // History: 21-Nov-92 SarahJ Created
  243. //
  244. //--------------------------------------------------------------------
  245. CBasicBnd::CBasicBnd(IUnknown *punk)
  246. : _punk(punk), _pmkContainer(NULL)
  247. {
  248. // Create storage for "contained" objects
  249. SCODE sc = StgCreateDocfile(NULL,
  250. STGM_DELETEONRELEASE|STGM_DFRALL|STGM_CREATE, 0, &_psStg1);
  251. if (sc != S_OK)
  252. {
  253. HrMsgBox("CBasicBnd::CBasicBnd Create of first storage failed", sc);
  254. }
  255. sc = StgCreateDocfile(NULL,
  256. STGM_DELETEONRELEASE|STGM_DFRALL|STGM_CREATE, 0, &_psStg2);
  257. if (sc != S_OK)
  258. {
  259. HrMsgBox("CBasicBnd::CBasicBnd Create of second storage failed", sc);
  260. }
  261. }
  262. //+-------------------------------------------------------------------
  263. //
  264. // Member: CBasicBnd::~CBasicBndObj()
  265. //
  266. // Synopsis: The destructor for CBAsicBnd.
  267. //
  268. // History: 21-Nov-92 SarahJ Created
  269. //
  270. //--------------------------------------------------------------------
  271. CBasicBnd::~CBasicBnd()
  272. {
  273. if (_pmkContainer)
  274. {
  275. _pmkContainer->Release();
  276. }
  277. if (_psStg1)
  278. {
  279. _psStg1->Release();
  280. }
  281. if (_psStg2)
  282. {
  283. _psStg2->Release();
  284. }
  285. return;
  286. }
  287. //+-------------------------------------------------------------------
  288. //
  289. // Member: CBasicBnd::QueryInterface
  290. //
  291. // Returns: S_OK
  292. //
  293. // History: 21-Nov-92 SarahJ Created
  294. //
  295. //--------------------------------------------------------------------
  296. STDMETHODIMP CBasicBnd::QueryInterface(REFIID iid, void **ppiuk)
  297. {
  298. return _punk->QueryInterface(iid, ppiuk);
  299. }
  300. //+-------------------------------------------------------------------
  301. //
  302. // Member: CBasicBnd::AddRef
  303. //
  304. // Synopsis: Standard stuff
  305. //
  306. // History: 21-Nov-92 SarahJ Created
  307. //
  308. //--------------------------------------------------------------------
  309. STDMETHODIMP_(ULONG) CBasicBnd::AddRef(void)
  310. {
  311. return _punk->AddRef();
  312. }
  313. //+-------------------------------------------------------------------
  314. //
  315. // Member: CBasicBnd::Release
  316. //
  317. // Synopsis: Standard stuff
  318. //
  319. // History: 21-Nov-92 SarahJ Created
  320. //
  321. //--------------------------------------------------------------------
  322. STDMETHODIMP_(ULONG) CBasicBnd::Release(void)
  323. {
  324. return _punk->Release();
  325. }
  326. //+-------------------------------------------------------------------
  327. //
  328. // Member: CBasicBnd::Load
  329. //
  330. // Synopsis: IPeristFile interface - needed 'cause we bind with
  331. // file moniker and BindToObject insists on calling this
  332. //
  333. // History: 21-Nov-92 SarahJ Created
  334. //
  335. //--------------------------------------------------------------------
  336. STDMETHODIMP CBasicBnd::Load(LPCWSTR lpszFileName, DWORD grfMode)
  337. {
  338. if (grfMode & ~(STGM_READWRITE | STGM_SHARE_EXCLUSIVE))
  339. {
  340. // Test requires default bind storage request and caller
  341. // has set some other bits so we fail.
  342. return STG_E_INVALIDPARAMETER;
  343. }
  344. return S_OK;
  345. }
  346. //+-------------------------------------------------------------------
  347. //
  348. // Member: CBasicBnd::Save
  349. //
  350. // Synopsis: IPeristFile interface - save
  351. // does little but here for commentry
  352. //
  353. // History: 21-Nov-92 SarahJ Created
  354. //
  355. //--------------------------------------------------------------------
  356. STDMETHODIMP CBasicBnd::Save(LPCWSTR lpszFileName, BOOL fRemember)
  357. {
  358. return S_OK;
  359. }
  360. //+-------------------------------------------------------------------
  361. //
  362. // Member: CBasicBnd::SaveCpmpleted
  363. // CBasicBnd::GetCurFile
  364. // CBasicBnd::IsDirty
  365. //
  366. // Synopsis: More IPeristFile interface methods
  367. //
  368. // History: 21-Nov-92 SarahJ Created
  369. //
  370. //--------------------------------------------------------------------
  371. STDMETHODIMP CBasicBnd::SaveCompleted(LPCWSTR lpszFileName)
  372. {
  373. return S_OK;
  374. }
  375. STDMETHODIMP CBasicBnd::GetCurFile(LPWSTR FAR *lpszFileName)
  376. {
  377. return S_OK;
  378. }
  379. STDMETHODIMP CBasicBnd::IsDirty()
  380. {
  381. return S_OK;
  382. }
  383. //+-------------------------------------------------------------------
  384. //
  385. // Interface: IPersist
  386. //
  387. // Synopsis: IPersist interface methods
  388. // Need to return a valid class id here
  389. //
  390. // History: 21-Nov-92 SarahJ Created
  391. //
  392. STDMETHODIMP CBasicBnd::GetClassID(LPCLSID classid)
  393. {
  394. *classid = CLSID_BasicBnd;
  395. return S_OK;
  396. }
  397. // *** IOleObject methods ***
  398. STDMETHODIMP CBasicBnd::SetClientSite(LPOLECLIENTSITE pClientSite)
  399. {
  400. return E_FAIL;
  401. }
  402. STDMETHODIMP CBasicBnd::GetClientSite(LPOLECLIENTSITE FAR* ppClientSite)
  403. {
  404. return E_FAIL;
  405. }
  406. STDMETHODIMP CBasicBnd::SetHostNames(
  407. LPCWSTR szContainerApp,
  408. LPCWSTR szContainerObj)
  409. {
  410. return E_FAIL;
  411. }
  412. STDMETHODIMP CBasicBnd::Close(DWORD dwSaveOption)
  413. {
  414. return E_FAIL;
  415. }
  416. STDMETHODIMP CBasicBnd::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pmk)
  417. {
  418. if (_pmkContainer)
  419. {
  420. _pmkContainer->Release();
  421. }
  422. _pmkContainer = pmk;
  423. pmk->AddRef();
  424. return S_OK;
  425. }
  426. STDMETHODIMP CBasicBnd::GetMoniker(
  427. DWORD dwAssign,
  428. DWORD dwWhichMoniker,
  429. LPMONIKER FAR* ppmk)
  430. {
  431. if (_pmkContainer != NULL)
  432. {
  433. *ppmk = _pmkContainer;
  434. _pmkContainer->AddRef();
  435. return S_OK;
  436. }
  437. return E_FAIL;
  438. }
  439. STDMETHODIMP CBasicBnd::InitFromData(
  440. LPDATAOBJECT pDataObject,
  441. BOOL fCreation,
  442. DWORD dwReserved)
  443. {
  444. return E_FAIL;
  445. }
  446. STDMETHODIMP CBasicBnd::GetClipboardData(
  447. DWORD dwReserved,
  448. LPDATAOBJECT FAR* ppDataObject)
  449. {
  450. return E_FAIL;
  451. }
  452. STDMETHODIMP CBasicBnd::DoVerb(
  453. LONG iVerb,
  454. LPMSG lpmsg,
  455. LPOLECLIENTSITE pActiveSite,
  456. LONG reserved,
  457. HWND hwndParent,
  458. LPCRECT lprcPosRect)
  459. {
  460. return E_FAIL;
  461. }
  462. STDMETHODIMP CBasicBnd::EnumVerbs(IEnumOLEVERB FAR* FAR* ppenumOleVerb)
  463. {
  464. return E_FAIL;
  465. }
  466. STDMETHODIMP CBasicBnd::Update(void)
  467. {
  468. return E_FAIL;
  469. }
  470. STDMETHODIMP CBasicBnd::IsUpToDate(void)
  471. {
  472. return E_FAIL;
  473. }
  474. STDMETHODIMP CBasicBnd::GetUserClassID(CLSID FAR* pClsid)
  475. {
  476. return E_FAIL;
  477. }
  478. STDMETHODIMP CBasicBnd::GetUserType(DWORD dwFormOfType, LPWSTR FAR* pszUserType)
  479. {
  480. return E_FAIL;
  481. }
  482. STDMETHODIMP CBasicBnd::SetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  483. {
  484. return E_FAIL;
  485. }
  486. STDMETHODIMP CBasicBnd::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  487. {
  488. return E_FAIL;
  489. }
  490. STDMETHODIMP CBasicBnd::Advise(
  491. IAdviseSink FAR* pAdvSink,
  492. DWORD FAR* pdwConnection)
  493. {
  494. return E_FAIL;
  495. }
  496. STDMETHODIMP CBasicBnd::Unadvise(DWORD dwConnection)
  497. {
  498. return E_FAIL;
  499. }
  500. STDMETHODIMP CBasicBnd::EnumAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
  501. {
  502. return E_FAIL;
  503. }
  504. STDMETHODIMP CBasicBnd::GetMiscStatus(DWORD dwAspect, DWORD FAR* pdwStatus)
  505. {
  506. return E_FAIL;
  507. }
  508. STDMETHODIMP CBasicBnd::SetColorScheme(LPLOGPALETTE lpLogpal)
  509. {
  510. return E_FAIL;
  511. }
  512. // *** IParseDisplayName method ***
  513. STDMETHODIMP CBasicBnd::ParseDisplayName(
  514. LPBC pbc,
  515. LPWSTR lpszDisplayName,
  516. ULONG FAR* pchEaten,
  517. LPMONIKER FAR* ppmkOut)
  518. {
  519. *pchEaten = wcslen(lpszDisplayName);
  520. return CreateItemMoniker(L"\\", lpszDisplayName, ppmkOut);
  521. }
  522. // *** IOleContainer methods ***
  523. STDMETHODIMP CBasicBnd::EnumObjects(
  524. DWORD grfFlags,
  525. LPENUMUNKNOWN FAR* ppenumUnknown)
  526. {
  527. return E_FAIL;
  528. }
  529. STDMETHODIMP CBasicBnd::LockContainer(BOOL fLock)
  530. {
  531. return E_FAIL;
  532. }
  533. // *** IOleItemContainer methods ***
  534. STDMETHODIMP CBasicBnd::GetObject(
  535. LPWSTR lpszItem,
  536. DWORD dwSpeedNeeded,
  537. LPBINDCTX pbc,
  538. REFIID riid,
  539. LPVOID FAR* ppvObject)
  540. {
  541. IStorage *psStorage;
  542. IOleObject *poo;
  543. IUnknown *punk;
  544. if (wcscmp(lpszItem, L"1") == 0)
  545. {
  546. psStorage = _psStg1;
  547. }
  548. else if (wcscmp(lpszItem, L"2") == 0)
  549. {
  550. psStorage = _psStg2;
  551. }
  552. else
  553. {
  554. return E_FAIL;
  555. }
  556. IOleClientSite * pocsObjCliSite;
  557. HRESULT hresult = QueryInterface(IID_IOleClientSite,
  558. (void **) &pocsObjCliSite);
  559. // Call OleCreate to create our embedded object
  560. hresult = OleCreate(
  561. CLSID_TestEmbed, // Class ID of the object we are
  562. // creating
  563. IID_IOleObject, // Interface by which we want to talk
  564. // to the object
  565. OLERENDER_NONE, // We don't want to draw the object
  566. // when it is not active
  567. NULL, // Used if we do draw the object when
  568. // it is non-active
  569. pocsObjCliSite, // IOleClientSite the server will use
  570. psStorage, // IStorage the server will use
  571. (void **) &poo); // Pointer to the object
  572. if (FAILED(hresult))
  573. {
  574. HrMsgBox("CBasicBnd::GetObject OlCreate Failed!", hresult);
  575. return hresult;
  576. }
  577. // Set the client site
  578. hresult = poo->SetClientSite(pocsObjCliSite);
  579. if (FAILED(hresult))
  580. {
  581. HrMsgBox("CBasicBnd::GetObject SetClientSite failed!", hresult);
  582. return hresult;
  583. }
  584. hresult = poo->QueryInterface(IID_IUnknown, (void **)&punk);
  585. if (FAILED(hresult))
  586. {
  587. HrMsgBox("CBasicBnd::GetObject QI to IUnknown failed!", hresult);
  588. return hresult;
  589. }
  590. hresult = OleRun(punk);
  591. if (FAILED(hresult))
  592. {
  593. HrMsgBox("CBasicBnd::GetObject OleRun failed!", hresult);
  594. return hresult;
  595. }
  596. punk->Release();
  597. LPRECT lprPosRect = (LPRECT) new RECT;
  598. hresult = poo->DoVerb(
  599. OLEIVERB_SHOW, // Verb we are invoking
  600. NULL, // MSG that causes us to do this verb
  601. pocsObjCliSite, // Client site of this object
  602. 0, // Reserved - definitive value?
  603. 0, // hwndParent - ???
  604. lprPosRect); // lprcPosRect - rectangle wrt hwndParent
  605. if (FAILED(hresult))
  606. {
  607. HrMsgBox("CBasicBnd::GetObject DoVerb failed!", hresult);
  608. return hresult;
  609. }
  610. delete lprPosRect;
  611. pocsObjCliSite->Release();
  612. *ppvObject = (void *) poo;
  613. return hresult;
  614. }
  615. STDMETHODIMP CBasicBnd::GetObjectStorage(
  616. LPWSTR lpszItem,
  617. LPBINDCTX pbc,
  618. REFIID riid,
  619. LPVOID FAR* ppvStorage)
  620. {
  621. return E_FAIL;
  622. }
  623. STDMETHODIMP CBasicBnd::IsRunning(LPWSTR lpszItem)
  624. {
  625. return E_FAIL;
  626. }
  627. CUnknownBasicBnd::CUnknownBasicBnd(IUnknown *punk)
  628. : _pbasicbnd(NULL), _cRefs(1)
  629. {
  630. if (punk == NULL)
  631. {
  632. punk = (IUnknown *) this;
  633. }
  634. // BUGBUG: No error checking!
  635. _pbasicbnd = new CBasicBnd(punk);
  636. g_UseCount++;
  637. }
  638. CUnknownBasicBnd::~CUnknownBasicBnd(void)
  639. {
  640. g_UseCount--;
  641. delete _pbasicbnd;
  642. }
  643. //+-------------------------------------------------------------------
  644. //
  645. // Member: CUnknownBasicBnd::QueryInterface
  646. //
  647. // Returns: S_OK
  648. //
  649. // History: 21-Nov-92 SarahJ Created
  650. //
  651. //--------------------------------------------------------------------
  652. STDMETHODIMP CUnknownBasicBnd::QueryInterface(
  653. REFIID iid,
  654. void **ppiuk)
  655. {
  656. if (GuidEqual(iid, IID_IUnknown))
  657. {
  658. *ppiuk = (IUnknown *) this;
  659. }
  660. else if (GuidEqual(iid, IID_IOleClientSite))
  661. {
  662. *ppiuk = (IOleClientSite *) _pbasicbnd;
  663. }
  664. else if (GuidEqual(iid, IID_IPersistFile)
  665. || GuidEqual(iid, IID_IPersist))
  666. {
  667. *ppiuk = (IPersistFile *) _pbasicbnd;
  668. }
  669. else if (GuidEqual(iid, IID_IOleObject))
  670. {
  671. *ppiuk = (IOleObject *) _pbasicbnd;
  672. }
  673. else if (GuidEqual(iid, IID_IOleItemContainer))
  674. {
  675. *ppiuk = (IOleItemContainer *)_pbasicbnd;
  676. }
  677. else if (GuidEqual(iid, IID_IOleContainer))
  678. {
  679. *ppiuk = (IOleContainer *)_pbasicbnd;
  680. }
  681. else if (GuidEqual(iid, IID_IParseDisplayName))
  682. {
  683. *ppiuk = (IParseDisplayName *)_pbasicbnd;
  684. }
  685. else
  686. {
  687. *ppiuk = NULL;
  688. return E_NOINTERFACE;
  689. }
  690. _pbasicbnd->AddRef();
  691. return S_OK;
  692. }
  693. STDMETHODIMP_(ULONG) CUnknownBasicBnd::AddRef(void)
  694. {
  695. return ++_cRefs;
  696. }
  697. STDMETHODIMP_(ULONG) CUnknownBasicBnd::Release(void)
  698. {
  699. ULONG cRefs = --_cRefs;
  700. if (cRefs == 0)
  701. {
  702. delete this;
  703. }
  704. return cRefs;
  705. }
  706. #ifdef CAIROLE_DOWNLEVEL
  707. extern "C"
  708. {
  709. EXPORTDEF void APINOT
  710. RegisterWithCommnot(void);
  711. EXPORTDEF void APINOT
  712. DeRegisterWithCommnot(void);
  713. }
  714. //+-------------------------------------------------------------------
  715. //
  716. // Function: RegisterWithCommnot
  717. //
  718. // Synopsis: Used by Cairo to work around DLL unloading problems
  719. //
  720. // Arguments: <none>
  721. //
  722. // History: 06-Oct-92 BryanT Created
  723. //
  724. //--------------------------------------------------------------------
  725. EXPORTIMP void APINOT
  726. RegisterWithCommnot( void )
  727. {
  728. }
  729. //+-------------------------------------------------------------------
  730. //
  731. // Function: DeRegisterWithCommnot
  732. //
  733. // Synopsis: Used by Cairo to work around DLL unloading problems
  734. //
  735. // Arguments: <none>
  736. //
  737. // History: 06-Oct-92 BryanT Created
  738. //
  739. // Notes: BUGBUG: Keep in touch with BryanT to see if this is
  740. // obsolete.
  741. //
  742. //--------------------------------------------------------------------
  743. EXPORTIMP void APINOT
  744. DeRegisterWithCommnot( void )
  745. {
  746. }
  747. #endif