home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / olemon.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  8.5 KB  |  375 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_OLE_SEG
  14. #pragma code_seg(AFX_OLE_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. #pragma inline_depth(0)
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // _AfxBindHost for CMonikerFile implementation
  28.  
  29. class _AfxBindHost: public IBindHost
  30. {
  31. private:
  32.     long m_dwRef;
  33. public:
  34.     inline _AfxBindHost() : m_dwRef(0) {}
  35.  
  36.     inline ~_AfxBindHost() { ASSERT(m_dwRef == 0); }
  37.  
  38.     STDMETHOD_(ULONG, AddRef)()
  39.     {
  40.         return InterlockedIncrement(&m_dwRef);
  41.     }
  42.  
  43.     STDMETHOD_(ULONG, Release)()
  44.     {
  45.         unsigned long lResult = InterlockedDecrement(&m_dwRef);
  46.         if (lResult == 0)
  47.             delete this;
  48.         return lResult;
  49.     }
  50.  
  51.     STDMETHOD(QueryInterface)(REFIID iid, void** ppvObject)
  52.     {
  53.         if (!ppvObject)
  54.             return E_POINTER;
  55.  
  56.         // check for the interfaces this object knows about
  57.         if (iid == IID_IUnknown || iid == IID_IBindHost)
  58.         {
  59.             *ppvObject = (IBindHost*)this;
  60.             InterlockedIncrement(&m_dwRef);
  61.             return S_OK;
  62.         }
  63.  
  64.         // otherwise, incorrect IID, and thus error
  65.         return E_NOINTERFACE;
  66.     }
  67.  
  68.     STDMETHOD(CreateMoniker)(
  69.     /* [in] */ LPOLESTR szName,
  70.     /* [in] */ IBindCtx __RPC_FAR *pBC,
  71.     /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk,
  72.     /* [in] */ DWORD dwReserved)
  73.     {
  74.         UNUSED_ALWAYS(dwReserved);
  75.         UNUSED_ALWAYS(pBC);
  76.  
  77.         if (!szName || !ppmk) return E_POINTER;
  78.         if (!*szName) return E_INVALIDARG;
  79.  
  80.         *ppmk = NULL;
  81.         HRESULT hr = S_OK;
  82.  
  83.         hr = CreateURLMoniker(NULL, szName, ppmk);
  84.         if (SUCCEEDED(hr) && !*ppmk)
  85.             hr = E_FAIL;
  86.         return hr;
  87.     }
  88.  
  89.     STDMETHOD(MonikerBindToStorage)(
  90.     /* [in] */ IMoniker __RPC_FAR *pMk,
  91.     /* [in] */ IBindCtx __RPC_FAR *pBC,
  92.     /* [in] */ IBindStatusCallback __RPC_FAR *pBSC,
  93.     /* [in] */ REFIID riid,
  94.     /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj)
  95.     {
  96.         if (!pMk || !ppvObj) return E_POINTER;
  97.  
  98.         *ppvObj = NULL;
  99.         HRESULT hr = S_OK;
  100.         IPTR(IBindCtx) BindCtx;
  101.         if (pBC)
  102.         {
  103.             BindCtx = pBC;
  104.             if (pBSC)
  105.             {
  106. #ifdef _DEBUG
  107.                 IPTR(IBindStatusCallback) pBSCPrev;
  108. #endif
  109.                 hr = RegisterBindStatusCallback(BindCtx, pBSC,
  110. #ifdef _DEBUG
  111.                     &pBSCPrev,
  112. #else
  113.                     NULL,
  114. #endif
  115.                     0);
  116.                 ASSERT(!pBSCPrev);
  117.                 if (FAILED(hr))
  118.                     return hr;
  119.             }
  120.         }
  121.         else
  122.         {
  123.             if (pBSC)
  124.                 hr = CreateAsyncBindCtx(0, pBSC, NULL, &BindCtx);
  125.             else
  126.                 hr = CreateBindCtx(0, &BindCtx);
  127.             if (SUCCEEDED(hr) && !BindCtx)
  128.                 hr = E_FAIL;
  129.             if (FAILED(hr))
  130.                 return hr;
  131.         }
  132.         return pMk->BindToStorage(BindCtx, NULL, riid, ppvObj);
  133.     }
  134.  
  135. private:
  136.     STDMETHOD(MonikerBindToObject)(
  137.     /* [in] */ IMoniker __RPC_FAR *pMk,
  138.     /* [in] */ IBindCtx __RPC_FAR *pBC,
  139.     /* [in] */ IBindStatusCallback __RPC_FAR *pBSC,
  140.     /* [in] */ REFIID riid,
  141.     /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj)
  142.     {
  143.         ASSERT(FALSE);
  144.         UNUSED_ALWAYS(pMk);
  145.         UNUSED_ALWAYS(pBC);
  146.         UNUSED_ALWAYS(pBSC);
  147.         UNUSED_ALWAYS(riid);
  148.         UNUSED_ALWAYS(ppvObj);
  149.         return E_NOTIMPL;
  150.     }
  151. };
  152.  
  153. /////////////////////////////////////////////////////////////////////////////
  154. // CMonikerFile implementation
  155.  
  156. CMonikerFile::~CMonikerFile()
  157. {
  158.     ASSERT_VALID(this);
  159.     Close();
  160. }
  161.  
  162. void CMonikerFile::Flush()
  163. {
  164.     ASSERT_VALID(this);
  165.     ASSERT(GetStream() != NULL);
  166.  
  167.     GetStream()->Commit(0);
  168. }
  169.  
  170. BOOL CMonikerFile::Open(LPCTSTR lpszUrl, IBindHost* pBindHost,
  171.     IBindStatusCallback* pBSC, IBindCtx* pBindCtx, CFileException* pError)
  172. {
  173.     ASSERT_VALID(this);
  174.     Close(); // These objects are reopenable
  175.     return Attach(lpszUrl, pBindHost, pBSC, pBindCtx, pError);
  176. }
  177.  
  178. BOOL CMonikerFile::Attach(LPCTSTR lpszUrl, IBindHost* pBindHost,
  179.     IBindStatusCallback* pBSC, IBindCtx* pBindCtx, CFileException* pError)
  180. {
  181.     ASSERT(!m_Moniker);
  182.     ASSERT(!GetStream());
  183.     USES_CONVERSION;
  184.  
  185.     ASSERT(NULL == lpszUrl || AfxIsValidString(lpszUrl));
  186.     ASSERT(NULL == pError ||
  187.         AfxIsValidAddress(pError, sizeof(CFileException)));
  188.     ASSERT(NULL != pBindHost);
  189.  
  190.     // Check for empty path
  191.     if (!lpszUrl || !*lpszUrl)
  192.     {
  193.         if (pError)
  194.         {
  195.             pError->m_cause=CFileException::badPath;
  196.             pError->m_strFileName=lpszUrl;
  197.         }
  198.         return FALSE;
  199.     }
  200.  
  201.     // Create the moniker
  202.     HRESULT hr;
  203.     IPTR(IMoniker) pMoniker;
  204.  
  205.     hr = pBindHost->CreateMoniker(T2OLE((LPTSTR) lpszUrl), pBindCtx,
  206.         reinterpret_cast<IMoniker**>(&pMoniker), 0);
  207.  
  208.     if (FAILED(hr))
  209.     {
  210.         if (pError) _AfxFillOleFileException(pError, hr);
  211.         return FALSE;
  212.     }
  213.  
  214.     return Attach(pMoniker, pBindHost, pBSC, pBindCtx, pError);
  215. }
  216.  
  217. BOOL CMonikerFile::Open(LPCTSTR lpszUrl, CFileException* pError)
  218. {
  219.     IPTR(IBindHost) pBindHost(CreateBindHost(), FALSE);
  220.     IPTR(IBindCtx) pBindCtx(CreateBindContext(pError), FALSE);
  221.  
  222.     return Open(lpszUrl, pBindHost, NULL, pBindCtx, pError);
  223. }
  224.  
  225. BOOL CMonikerFile::Open(IMoniker* pMoniker, CFileException* pError)
  226. {
  227.     Close(); // These objects are reopenable
  228.     IPTR(IBindHost) pBindHost(CreateBindHost(), FALSE);
  229.     IPTR(IBindCtx) pBindCtx(CreateBindContext(pError), FALSE);
  230.  
  231.     return Attach(pMoniker, pBindHost, NULL, pBindCtx, pError);
  232. }
  233.  
  234. BOOL CMonikerFile::Open(IMoniker* pMoniker, IBindHost* pBindHost,
  235.     IBindStatusCallback* pBSC, IBindCtx* pBindCtx, CFileException* pError)
  236. {
  237.     Close();
  238.     return Attach(pMoniker, pBindHost, pBSC, pBindCtx, pError);
  239. }
  240.  
  241. BOOL CMonikerFile::Attach(IMoniker* pMoniker, IBindHost* pBindHost,
  242.     IBindStatusCallback* pBSC, IBindCtx* pBindCtx, CFileException* pError)
  243. {
  244.     ASSERT_VALID(this);
  245.     ASSERT(pMoniker);
  246.     ASSERT(!m_Moniker);
  247.     ASSERT(!GetStream());
  248.     m_Moniker=pMoniker;
  249.  
  250.     IPTR(IStream) pStream;
  251.     HRESULT hr=pBindHost->MonikerBindToStorage(pMoniker, pBindCtx, pBSC,
  252.         IID_IStream, reinterpret_cast<void**>(&pStream));
  253.     if (FAILED(hr))
  254.     {
  255.         if (pError) _AfxFillOleFileException(pError, hr);
  256.         return FALSE;
  257.     }
  258.  
  259.     // If this is really a CAsyncMonikerFile, then we may have attached to the stream
  260.     // within MonikerBindToStorage, in which case we want to avoid doing so here.
  261.     if (pStream.GetInterfacePtr() && !GetStream())
  262.     {
  263.         // Attach this to the stream, transferring the reference
  264.         // COleStreamFile::Attach doesn't increment pStream's refcount
  265.         COleStreamFile::Attach(pStream);
  266.         pStream.Detach();
  267.     }
  268.  
  269.     return PostBindToStream(pError);
  270. }
  271.  
  272. void CMonikerFile::Close()
  273. {
  274.     if (m_Moniker.GetInterfacePtr())
  275.         m_Moniker.Release();
  276.     COleStreamFile::Close();
  277. }
  278.  
  279. BOOL CMonikerFile::Detach(CFileException* pError)
  280. {
  281.     ASSERT_VALID(this);
  282.     ASSERT(!!m_Moniker);
  283.  
  284.     TRY
  285.     {
  286.         Close();
  287.     }
  288.     CATCH (CFileException, e)
  289.     {
  290.         if (pError)
  291.         {
  292.             pError->m_cause=e->m_cause;
  293.             pError->m_lOsError=e->m_lOsError;
  294.             pError->m_strFileName=e->m_strFileName;
  295.         }
  296.         DELETE_EXCEPTION(e);
  297.         return FALSE;
  298.     }
  299.     END_CATCH;
  300.  
  301.     return TRUE;
  302. }
  303.  
  304. IBindHost* CMonikerFile::CreateBindHost()
  305. {
  306.     IBindHost* pBindHost = new _AfxBindHost();
  307.     pBindHost->AddRef();
  308.     return pBindHost;
  309. }
  310.  
  311. IBindCtx* CMonikerFile::CreateBindContext(CFileException* pError)
  312. {
  313.     UNUSED_ALWAYS(pError);
  314.     return NULL;
  315. }
  316.  
  317. // So that CMonikerFile can check for a null pStream and CAsyncMonikerFile can ignore it
  318. BOOL CMonikerFile::PostBindToStream(CFileException* pError)
  319. {
  320.     if (!GetStream())
  321.     {
  322.         if (pError) _AfxFillOleFileException(pError, E_UNEXPECTED);
  323.         TRY
  324.         {
  325.             Close();
  326.         }
  327.         CATCH_ALL(e)
  328.         {
  329.             DELETE_EXCEPTION(e);
  330.         }
  331.         END_CATCH_ALL
  332.         return FALSE;
  333.     }
  334.     return TRUE;
  335. }
  336.  
  337. /////////////////////////////////////////////////////////////////////////////
  338. // CMonikerFile diagnostics
  339.  
  340. #ifdef _DEBUG
  341. void CMonikerFile::AssertValid() const
  342. {
  343.     COleStreamFile::AssertValid();
  344. }
  345.  
  346. void CMonikerFile::Dump(CDumpContext& dc) const
  347. {
  348.     COleStreamFile::Dump(dc);
  349.  
  350.     dc << "\nm_Moniker = " << m_Moniker.GetInterfacePtr();
  351.     dc << "\n";
  352. }
  353. #endif
  354.  
  355. ////////////////////////////////////////////////////////////////////////////
  356.  
  357. #ifndef _AFX_ENABLE_INLINES
  358.  
  359. // expand inlines for OLE general APIs
  360. static char _szAfxOleInl[] = "afxole.inl";
  361. #undef THIS_FILE
  362. #define THIS_FILE _szAfxOleInl
  363. #define _AFXOLEMONIKER_INLINE
  364. #include "afxole.inl"
  365.  
  366. #endif //!_AFX_ENABLE_INLINES
  367.  
  368. #ifdef AFX_INIT_SEG
  369. #pragma code_seg(AFX_INIT_SEG)
  370. #endif
  371.  
  372. IMPLEMENT_DYNAMIC(CMonikerFile, COleStreamFile)
  373.  
  374. ////////////////////////////////////////////////////////////////////////////
  375.