home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLEMON.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  8.7 KB  |  386 lines

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