home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / olefact.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  15KB  |  589 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_OLE3_SEG
  14. #pragma code_seg(AFX_OLE3_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. /////////////////////////////////////////////////////////////////////////////
  25. // COleObjectFactory implementation
  26.  
  27. BEGIN_INTERFACE_MAP(COleObjectFactory, CCmdTarget)
  28.     INTERFACE_PART(COleObjectFactory, IID_IClassFactory, ClassFactory)
  29.     INTERFACE_PART(COleObjectFactory, IID_IClassFactory2, ClassFactory)
  30. END_INTERFACE_MAP()
  31.  
  32. #ifdef AFX_INIT_SEG
  33. #pragma code_seg(AFX_INIT_SEG)
  34. #endif
  35.  
  36. COleObjectFactory::COleObjectFactory(REFCLSID clsid,
  37.     CRuntimeClass* pRuntimeClass, BOOL bMultiInstance, LPCTSTR lpszProgID)
  38. {
  39.     ASSERT(pRuntimeClass == NULL ||
  40.         pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CCmdTarget)));
  41.     ASSERT(AfxIsValidAddress(&clsid, sizeof(CLSID), FALSE));
  42.     ASSERT(lpszProgID == NULL || AfxIsValidString(lpszProgID));
  43.  
  44.     // initialize to unregistered state
  45.     m_dwRegister = 0;   // not registered yet
  46.     m_bRegistered = FALSE;
  47.     m_clsid = clsid;
  48.     m_pRuntimeClass = pRuntimeClass;
  49.     m_bMultiInstance = bMultiInstance;
  50.     m_lpszProgID = lpszProgID;
  51.     m_bOAT = (BYTE) OAT_UNKNOWN;
  52.  
  53.     // licensing information
  54.     m_bLicenseChecked = FALSE;
  55.     m_bLicenseValid = FALSE;
  56.  
  57.     // add this factory to the list of factories
  58.     m_pNextFactory = NULL;
  59.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  60.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  61.     pModuleState->m_factoryList.AddHead(this);
  62.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  63.  
  64.     ASSERT_VALID(this);
  65. }
  66.  
  67. #ifdef AFX_TERM_SEG
  68. #pragma code_seg(AFX_TERM_SEG)
  69. #endif
  70.  
  71. COleObjectFactory::~COleObjectFactory()
  72. {
  73.     ASSERT_VALID(this);
  74.  
  75. #ifdef _AFXDLL
  76.     if (m_pModuleState == NULL)
  77.         return;
  78. #endif
  79.  
  80.     // deregister this class factory
  81.     Revoke();
  82.  
  83.     // remove this class factory from the list of active class factories
  84. #ifdef _AFXDLL
  85.     AFX_MODULE_STATE* pModuleState = m_pModuleState;
  86. #else
  87.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  88. #endif
  89.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  90.     BOOL bResult = pModuleState->m_factoryList.Remove(this);
  91.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  92.     if (bResult)
  93.         return;
  94.  
  95.     // check CDynLinkLibrary objects in case it was transfered during init
  96. #ifdef _AFXDLL
  97.     AfxLockGlobals(CRIT_DYNLINKLIST);
  98.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  99.         pDLL = pDLL->m_pNextDLL)
  100.     {
  101.         if (pDLL->m_factoryList.Remove(this))
  102.         {
  103.             AfxUnlockGlobals(CRIT_DYNLINKLIST);
  104.             return;
  105.         }
  106.     }
  107.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  108. #endif
  109. }
  110.  
  111. #ifdef AFX_INIT_SEG
  112. #pragma code_seg(AFX_INIT_SEG)
  113. #endif
  114.  
  115. BOOL COleObjectFactory::Unregister()
  116. {
  117.     return TRUE;
  118. }
  119.  
  120. BOOL COleObjectFactory::Register()
  121. {
  122.     ASSERT_VALID(this);
  123.     ASSERT(!m_bRegistered);  // registering server/factory twice?
  124.     ASSERT(m_clsid != CLSID_NULL);
  125.  
  126.     if (!afxContextIsDLL)
  127.     {
  128.         // In the application variants, the IClassFactory is registered
  129.         //  with the OLE DLLs.
  130.  
  131.         SCODE sc = ::CoRegisterClassObject(m_clsid, &m_xClassFactory,
  132.             CLSCTX_LOCAL_SERVER,
  133.             m_bMultiInstance ? REGCLS_SINGLEUSE : REGCLS_MULTIPLEUSE,
  134.             &m_dwRegister);
  135.         if (sc != S_OK)
  136.         {
  137. #ifdef _DEBUG
  138.             TRACE1("Warning: CoRegisterClassObject failed scode = %s.\n",
  139.                 ::AfxGetFullScodeString(sc));
  140. #endif
  141.             // registration failed.
  142.             return FALSE;
  143.         }
  144.         ASSERT(m_dwRegister != 0);
  145.     }
  146.  
  147.     ++m_bRegistered;
  148.     return TRUE;
  149. }
  150.  
  151. BOOL PASCAL COleObjectFactory::UnregisterAll()
  152. {
  153.     BOOL bResult = TRUE;
  154.     // register application factories
  155.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  156.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  157.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  158.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  159.     {
  160.         // unregister any registered, non-doctemplate factories
  161.         if (pFactory->IsRegistered() && !pFactory->Unregister())
  162.         {
  163.             bResult = FALSE;
  164.         }
  165.     }
  166.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  167.     return bResult;
  168. }
  169.  
  170. BOOL PASCAL COleObjectFactory::RegisterAll()
  171. {
  172.     BOOL bResult = TRUE;
  173.     // register application factories
  174.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  175.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  176.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  177.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  178.     {
  179.         // register any non-registered, non-doctemplate factories
  180.         if (!pFactory->IsRegistered() &&
  181.             pFactory->m_clsid != CLSID_NULL && !pFactory->Register())
  182.         {
  183.             bResult = FALSE;
  184.         }
  185.     }
  186.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  187. #ifdef _AFXDLL
  188.     // register extension DLL factories
  189.     AfxLockGlobals(CRIT_DYNLINKLIST);
  190.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  191.         pDLL = pDLL->m_pNextDLL)
  192.     {
  193.         for (pFactory = pDLL->m_factoryList;
  194.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  195.         {
  196.             // register any non-registered, non-doctemplate factories
  197.             if (!pFactory->IsRegistered() &&
  198.                 pFactory->m_clsid != CLSID_NULL && !pFactory->Register())
  199.             {
  200.                 bResult = FALSE;
  201.             }
  202.         }
  203.     }
  204.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  205. #endif
  206.     return bResult;
  207. }
  208.  
  209. #ifdef AFX_TERM_SEG
  210. #pragma code_seg(AFX_TERM_SEG)
  211. #endif
  212.  
  213. void COleObjectFactory::Revoke()
  214. {
  215.     ASSERT_VALID(this);
  216.  
  217.     if (m_bRegistered)
  218.     {
  219.         // revoke the registration of the class itself
  220.         if (m_dwRegister != 0)
  221.         {
  222.             ::CoRevokeClassObject(m_dwRegister);
  223.             m_dwRegister = 0;
  224.         }
  225.         m_bRegistered = FALSE;
  226.     }
  227. }
  228.  
  229. void PASCAL COleObjectFactory::RevokeAll()
  230. {
  231.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  232.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  233.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  234.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  235.     {
  236.         pFactory->Revoke();
  237.     }
  238.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  239. #ifdef _AFXDLL
  240.     AfxLockGlobals(CRIT_DYNLINKLIST);
  241.     // register extension DLL factories
  242.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  243.         pDLL = pDLL->m_pNextDLL)
  244.     {
  245.         for (pFactory = pDLL->m_factoryList;
  246.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  247.         {
  248.             pFactory->Revoke();
  249.         }
  250.     }
  251.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  252. #endif
  253. }
  254.  
  255. #ifdef AFX_OLE3_SEG
  256. #pragma code_seg(AFX_OLE3_SEG)
  257. #endif
  258.  
  259. void COleObjectFactory::UpdateRegistry(LPCTSTR lpszProgID)
  260. {
  261.     ASSERT_VALID(this);
  262.     ASSERT(lpszProgID == NULL || AfxIsValidString(lpszProgID));
  263.  
  264.     // use default prog-id if specific prog-id not given
  265.     if (lpszProgID == NULL)
  266.     {
  267.         lpszProgID = m_lpszProgID;
  268.         if (lpszProgID == NULL) // still no valid progID?
  269.             return;
  270.     }
  271.  
  272.     // call global helper to modify system registry
  273.     //  (progid, shortname, and long name are all equal in this case)
  274.     AfxOleRegisterServerClass(m_clsid, lpszProgID, lpszProgID, lpszProgID,
  275.         OAT_DISPATCH_OBJECT);
  276. }
  277.  
  278. BOOL PASCAL COleObjectFactory::UpdateRegistryAll(BOOL bRegister)
  279. {
  280.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  281.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  282.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  283.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  284.     {
  285.         if (!pFactory->UpdateRegistry(bRegister))
  286.         {
  287.             AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  288.             return FALSE;
  289.         }
  290.     }
  291.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  292. #ifdef _AFXDLL
  293.     AfxLockGlobals(CRIT_DYNLINKLIST);
  294.     // register extension DLL factories
  295.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  296.         pDLL = pDLL->m_pNextDLL)
  297.     {
  298.         for (pFactory = pDLL->m_factoryList;
  299.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  300.         {
  301.             if (!pFactory->UpdateRegistry(bRegister))
  302.             {
  303.                 AfxUnlockGlobals(CRIT_DYNLINKLIST);
  304.                 return FALSE;
  305.             }
  306.         }
  307.     }
  308.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  309. #endif
  310.  
  311.     return TRUE;
  312. }
  313.  
  314. CCmdTarget* COleObjectFactory::OnCreateObject()
  315. {
  316.     ASSERT_VALID(this);
  317.     ASSERT(AfxIsValidAddress(m_pRuntimeClass, sizeof(CRuntimeClass), FALSE));
  318.         // this implementation needs a runtime class
  319.  
  320.     // allocate object, throw exception on failure
  321.     CCmdTarget* pTarget = (CCmdTarget*)m_pRuntimeClass->CreateObject();
  322.     if (pTarget == NULL)
  323.         AfxThrowMemoryException();
  324.  
  325.     // make sure it is a CCmdTarget
  326.     ASSERT_KINDOF(CCmdTarget, pTarget);
  327.     ASSERT_VALID(pTarget);
  328.  
  329.     // return the new CCmdTarget object
  330.     return pTarget;
  331. }
  332.  
  333. BOOL COleObjectFactory::IsLicenseValid()
  334. {
  335.     if (!m_bLicenseChecked)
  336.     {
  337.         m_bLicenseValid = (BYTE)VerifyUserLicense();
  338.         m_bLicenseChecked = TRUE;
  339.     }
  340.     return m_bLicenseValid;
  341. }
  342.  
  343. BOOL COleObjectFactory::UpdateRegistry(BOOL bRegister)
  344. {
  345.     if (bRegister)
  346.         UpdateRegistry();   // will register with default m_lpszProgID
  347.  
  348.     return TRUE;
  349. }
  350.  
  351. BOOL COleObjectFactory::VerifyUserLicense()
  352. {
  353.     // May be overridden by subclass
  354.     return TRUE;
  355. }
  356.  
  357. BOOL COleObjectFactory::GetLicenseKey(DWORD, BSTR*)
  358. {
  359.     // May be overridden by subclass
  360.     return FALSE;
  361. }
  362.  
  363. BOOL COleObjectFactory::VerifyLicenseKey(BSTR bstrKey)
  364. {
  365.     // May be overridden by subclass
  366.  
  367.     BOOL bLicensed = FALSE;
  368.     BSTR bstr = NULL;
  369.  
  370.     if ((bstrKey != NULL) && GetLicenseKey(0, &bstr))
  371.     {
  372.         ASSERT(bstr != NULL);
  373.  
  374.         // if length and content match, it's good!
  375.  
  376.         UINT cch = SysStringByteLen(bstr);
  377.         if ((cch == SysStringByteLen(bstrKey)) &&
  378.             (memcmp(bstr, bstrKey, cch) == 0))
  379.         {
  380.             bLicensed = TRUE;
  381.         }
  382.  
  383.         SysFreeString(bstr);
  384.     }
  385.  
  386.     return bLicensed;
  387. }
  388.  
  389. /////////////////////////////////////////////////////////////////////////////
  390. // Implementation of COleObjectFactory::IClassFactory interface
  391.  
  392. STDMETHODIMP_(ULONG) COleObjectFactory::XClassFactory::AddRef()
  393. {
  394.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  395.     return pThis->InternalAddRef();
  396. }
  397.  
  398. STDMETHODIMP_(ULONG) COleObjectFactory::XClassFactory::Release()
  399. {
  400.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  401.     return pThis->InternalRelease();
  402. }
  403.  
  404. STDMETHODIMP COleObjectFactory::XClassFactory::QueryInterface(
  405.     REFIID iid, LPVOID* ppvObj)
  406. {
  407.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  408.     return pThis->InternalQueryInterface(&iid, ppvObj);
  409. }
  410.  
  411. STDMETHODIMP COleObjectFactory::XClassFactory::CreateInstance(
  412.     IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject)
  413. {
  414.     return CreateInstanceLic(pUnkOuter, NULL, riid, NULL, ppvObject);
  415. }
  416.  
  417. STDMETHODIMP COleObjectFactory::XClassFactory::LockServer(BOOL fLock)
  418. {
  419.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  420.     ASSERT_VALID(pThis);
  421.  
  422.     SCODE sc = E_UNEXPECTED;
  423.     TRY
  424.     {
  425.         if (fLock)
  426.             AfxOleLockApp();
  427.         else
  428.             AfxOleUnlockApp();
  429.         sc = S_OK;
  430.     }
  431.     END_TRY
  432.  
  433.     return sc;
  434. }
  435.  
  436. STDMETHODIMP COleObjectFactory::XClassFactory::GetLicInfo(
  437.     LPLICINFO pLicInfo)
  438. {
  439.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  440.     ASSERT_VALID(pThis);
  441.  
  442.     BSTR bstr = NULL;
  443.     pLicInfo->fLicVerified = pThis->IsLicenseValid();
  444.     pLicInfo->fRuntimeKeyAvail = pThis->GetLicenseKey(0, &bstr);
  445.     if (bstr != NULL)
  446.         SysFreeString(bstr);
  447.  
  448.     return S_OK;
  449. }
  450.  
  451. STDMETHODIMP COleObjectFactory::XClassFactory::RequestLicKey(
  452.     DWORD dwReserved, BSTR* pbstrKey)
  453. {
  454.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  455.     ASSERT_VALID(pThis);
  456.  
  457.     ASSERT(pbstrKey != NULL);
  458.  
  459.     *pbstrKey = NULL;
  460.  
  461.     if (pThis->IsLicenseValid())
  462.     {
  463.         if (pThis->GetLicenseKey(dwReserved, pbstrKey))
  464.             return S_OK;
  465.         else
  466.             return E_FAIL;
  467.     }
  468.     else
  469.         return CLASS_E_NOTLICENSED;
  470. }
  471.  
  472. STDMETHODIMP COleObjectFactory::XClassFactory::CreateInstanceLic(
  473.     LPUNKNOWN pUnkOuter, LPUNKNOWN /* pUnkReserved */, REFIID riid,
  474.     BSTR bstrKey, LPVOID* ppvObject)
  475. {
  476.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  477.     ASSERT_VALID(pThis);
  478.  
  479.     if (ppvObject == NULL)
  480.         return E_POINTER;
  481.     *ppvObject = NULL;
  482.  
  483.     if (((bstrKey != NULL) && !pThis->VerifyLicenseKey(bstrKey)) ||
  484.         ((bstrKey == NULL) && !pThis->IsLicenseValid()))
  485.         return CLASS_E_NOTLICENSED;
  486.  
  487.     // outer objects must ask for IUnknown only
  488.     ASSERT(pUnkOuter == NULL || riid == IID_IUnknown);
  489.  
  490.     // attempt to create the object
  491.     CCmdTarget* pTarget = NULL;
  492.     SCODE sc = E_OUTOFMEMORY;
  493.     TRY
  494.     {
  495.         // attempt to create the object
  496.         pTarget = pThis->OnCreateObject();
  497.         if (pTarget != NULL)
  498.         {
  499.             // check for aggregation on object not supporting it
  500.             sc = CLASS_E_NOAGGREGATION;
  501.             if (pUnkOuter == NULL || pTarget->m_xInnerUnknown != 0)
  502.             {
  503.                 // create aggregates used by the object
  504.                 pTarget->m_pOuterUnknown = pUnkOuter;
  505.                 sc = E_OUTOFMEMORY;
  506.                 if (pTarget->OnCreateAggregates())
  507.                     sc = S_OK;
  508.             }
  509.         }
  510.     }
  511.     END_TRY
  512.  
  513.     // finish creation
  514.     if (sc == S_OK)
  515.     {
  516.         DWORD dwRef = 1;
  517.         if (pUnkOuter != NULL)
  518.         {
  519.             // return inner unknown instead of IUnknown
  520.             *ppvObject = &pTarget->m_xInnerUnknown;
  521.         }
  522.         else
  523.         {
  524.             // query for requested interface
  525.             sc = pTarget->InternalQueryInterface(&riid, ppvObject);
  526.             if (sc == S_OK)
  527.             {
  528.                 dwRef = pTarget->InternalRelease();
  529.                 ASSERT(dwRef != 0);
  530.             }
  531.         }
  532.         if (dwRef != 1)
  533.             TRACE1("Warning: object created with reference of %ld\n", dwRef);
  534.     }
  535.  
  536.     // cleanup in case of errors
  537.     if (sc != S_OK)
  538.         delete pTarget;
  539.  
  540.     return sc;
  541. }
  542.  
  543. //////////////////////////////////////////////////////////////////////////////
  544. // Diagnostics
  545.  
  546. #ifdef _DEBUG
  547. void COleObjectFactory::AssertValid() const
  548. {
  549.     CCmdTarget::AssertValid();
  550.     ASSERT(m_lpszProgID == NULL || AfxIsValidString(m_lpszProgID));
  551.     ASSERT(m_pRuntimeClass == NULL ||
  552.         AfxIsValidAddress(m_pRuntimeClass, sizeof(CRuntimeClass), FALSE));
  553.     ASSERT(m_pNextFactory == NULL ||
  554.         AfxIsValidAddress(m_pNextFactory, sizeof(COleObjectFactory)));
  555. }
  556.  
  557. void COleObjectFactory::Dump(CDumpContext& dc) const
  558. {
  559.     USES_CONVERSION;
  560.  
  561.     CCmdTarget::Dump(dc);
  562.  
  563.     dc << "m_pNextFactory = " << (void*)m_pNextFactory;
  564.     dc << "\nm_dwRegister = " << m_dwRegister;
  565.     dc << "\nm_bRegistered = " << m_bRegistered;
  566.     LPOLESTR lpszClassID = NULL;
  567.     if (StringFromCLSID(m_clsid, &lpszClassID) == S_OK)
  568.     {
  569.         dc << "\nm_clsid = " << OLE2CT(lpszClassID);
  570.         CoTaskMemFree(lpszClassID);
  571.     }
  572.     dc << "\nm_pRuntimeClass = " << m_pRuntimeClass;
  573.     dc << "\nm_bMultiInstance = " << m_bMultiInstance;
  574.     dc << "\nm_lpszProgID = " << m_lpszProgID;
  575.     dc << "\nm_bLicenseChecked = " << m_bLicenseChecked;
  576.     dc << "\nm_bLicenseValid = " << m_bLicenseValid;
  577.  
  578.     dc << "\n";
  579. }
  580. #endif //_DEBUG
  581.  
  582. #ifdef AFX_INIT_SEG
  583. #pragma code_seg(AFX_INIT_SEG)
  584. #endif
  585.  
  586. IMPLEMENT_DYNAMIC(COleObjectFactory, CCmdTarget)
  587.  
  588. /////////////////////////////////////////////////////////////////////////////
  589.