home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / classf.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  10.7 KB  |  397 lines

  1. //=--------------------------------------------------------------------------=
  2. // ClassF.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // contains the implementation of the ClassFactory object. we support 
  13. // IClassFactory and IClassFactory2
  14. //
  15. #include "IPServer.H"
  16. #include "LocalSrv.H"
  17.  
  18. #include "ClassF.H"
  19. #include "Globals.H"
  20. #include "Unknown.H"                    // for CREATEFNOFOBJECT
  21.  
  22. //=--------------------------------------------------------------------------=
  23. // private module level data
  24. //=--------------------------------------------------------------------------=
  25. //
  26.  
  27. // ASSERT and FAIL require this
  28. //
  29. SZTHISFILE
  30.  
  31. // private routines for this file
  32. //
  33. HRESULT   CreateOleObjectFromIndex(IUnknown *, int Index, void **, REFIID);
  34.  
  35. //=--------------------------------------------------------------------------=
  36. // CClassFactory::CClassFactory
  37. //=--------------------------------------------------------------------------=
  38. // create the object and initialize the refcount
  39. //
  40. // Parameters:
  41. //    int            - [in] index into our global table of objects for this guy
  42. //
  43. // Notes:
  44. //
  45. CClassFactory::CClassFactory
  46. (
  47.     int iIndex
  48. )
  49. : m_iIndex(iIndex)
  50. {
  51.     m_cRefs = 1;
  52. }
  53.  
  54.  
  55. //=--------------------------------------------------------------------------=
  56. // CClassFactory::CClassFactory
  57. //=--------------------------------------------------------------------------=
  58. // "Life levels all men.  Death reveals the eminent."
  59. // - George Bernard Shaw (1856 - 1950)
  60. //
  61. // Notes:
  62. //
  63. CClassFactory::~CClassFactory ()
  64. {
  65.     ASSERT(m_cRefs == 0, "Object being deleted with refs!");
  66.     return;
  67. }
  68.  
  69. //=--------------------------------------------------------------------------=
  70. // CClassFactory::QueryInterface
  71. //=--------------------------------------------------------------------------=
  72. // the user wants another interface.  we won't give 'em. very many.
  73. //
  74. // Parameters:
  75. //    REFIID        - [in]  interface they want
  76. //    void **       - [out] where they want to put the resulting object ptr.
  77. //
  78. // Output:
  79. //    HRESULT       - S_OK, E_NOINTERFACE
  80. //
  81. // Notes:
  82. //
  83. STDMETHODIMP CClassFactory::QueryInterface
  84. (
  85.     REFIID riid,
  86.     void **ppvObjOut
  87. )
  88. {
  89.     void *pv;
  90.  
  91.     CHECK_POINTER(ppvObjOut);
  92.  
  93.     // we support IUnknown, and the two CF interfaces
  94.     //
  95.     if (DO_GUIDS_MATCH(riid, IID_IClassFactory)) {
  96.         pv = (void *)(IClassFactory *)this;
  97.     } else if (DO_GUIDS_MATCH(riid, IID_IClassFactory2)) {
  98.         pv = (void *)(IClassFactory2 *)this;
  99.     } else if (DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  100.         pv = (void *)(IUnknown *)this;
  101.     } else {
  102.         *ppvObjOut = NULL;
  103.         return E_NOINTERFACE;
  104.     }
  105.  
  106.     ((IUnknown *)pv)->AddRef();
  107.     *ppvObjOut = pv;
  108.     return S_OK;
  109. }
  110.  
  111.  
  112.  
  113.  
  114. //=--------------------------------------------------------------------------=
  115. // CClassFactory::AddRef
  116. //=--------------------------------------------------------------------------=
  117. // adds a tick to the current reference count.
  118. //
  119. // Output:
  120. //    ULONG        - the new reference count
  121. //
  122. // Notes:
  123. //
  124. ULONG CClassFactory::AddRef
  125. (
  126.     void
  127. )
  128. {
  129.     return ++m_cRefs;
  130. }
  131.  
  132. //=--------------------------------------------------------------------------=
  133. // CClassFactory::Release
  134. //=--------------------------------------------------------------------------=
  135. // removes a tick from the count, and delets the object if necessary
  136. //
  137. // Output:
  138. //    ULONG         - remaining refs
  139. //
  140. // Notes:
  141. //
  142. ULONG CClassFactory::Release
  143. (
  144.     void
  145. )
  146. {
  147.     ASSERT(m_cRefs, "No Refs, and we're being released!");
  148.     if(--m_cRefs)
  149.         return m_cRefs;
  150.  
  151.     delete this;
  152.     return 0;
  153. }
  154.  
  155. //=--------------------------------------------------------------------------=
  156. // CClassFactory::CreateInstance
  157. //=--------------------------------------------------------------------------=
  158. // create an instance of some sort of object.
  159. //
  160. // Parameters:
  161. //    IUnknown *        - [in]  controlling IUknonwn for aggregation
  162. //    REFIID            - [in]  interface id for new object
  163. //    void **           - [out] pointer to new interface object.
  164. //
  165. // Output:
  166. //    HRESULT           - S_OK, E_NOINTERFACE, E_UNEXPECTED,
  167. //                        E_OUTOFMEMORY, E_INVALIDARG
  168. //
  169. // Notes:
  170. //
  171. STDMETHODIMP CClassFactory::CreateInstance
  172. (
  173.     IUnknown *pUnkOuter,
  174.     REFIID    riid,
  175.     void    **ppvObjOut
  176. )
  177. {
  178.     // check args
  179.     //
  180.     if (!ppvObjOut)
  181.         return E_INVALIDARG;
  182.  
  183.     // check to see if we've done our licensing work.  we do this as late
  184.     // as possible that people calling CreateInstanceLic don't suffer from
  185.     // a performance hit here.
  186.     //
  187.     // crit sect this for apartment threading, since it's global
  188.     //
  189.     EnterCriticalSection(&g_CriticalSection);
  190.     if (!g_fCheckedForLicense) {
  191.         g_fMachineHasLicense = CheckForLicense();
  192.         g_fCheckedForLicense = TRUE;
  193.     }
  194.     LeaveCriticalSection(&g_CriticalSection);
  195.  
  196.     // check to see if they have the appropriate license to create this stuff
  197.     //
  198.     if (!g_fMachineHasLicense)
  199.         return CLASS_E_NOTLICENSED;
  200.  
  201.     // try to create one of the objects that we support
  202.     //
  203.     return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid);
  204. }
  205.  
  206. //=--------------------------------------------------------------------------=
  207. // CClassFactory::LockServer
  208. //=--------------------------------------------------------------------------=
  209. // lock the server so we can't unload
  210. //
  211. // Parameters:
  212. //    BOOL        - [in] TRUE means addref, false means release lock count.
  213. //
  214. // Output:
  215. //    HRESULT     - S_OK, E_FAIL, E_OUTOFMEMORY, E_UNEXPECTED
  216. //
  217. // Notes:
  218. //
  219. STDMETHODIMP CClassFactory::LockServer
  220. (
  221.     BOOL fLock
  222. )
  223. {
  224.     // update the lock count.  crit sect these in case of another thread.
  225.     //
  226.     if (fLock)  
  227.         InterlockedIncrement(&g_cLocks);
  228.     else {
  229.         ASSERT(g_cLocks, "D'oh! Lock Counting Problem");
  230.         InterlockedDecrement(&g_cLocks);
  231.     }
  232.  
  233.     return S_OK;
  234. }
  235.  
  236. //=--------------------------------------------------------------------------=
  237. // CClassFactory::GetLicInfo
  238. //=--------------------------------------------------------------------------=
  239. // IClassFactory2 GetLicInfo
  240. //
  241. // Parameters:
  242. //    LICINFO *          - unclear
  243. //
  244. // Output:
  245. //    HRESULT            - unclear
  246. //
  247. // Notes:
  248. //
  249. STDMETHODIMP CClassFactory::GetLicInfo
  250. (
  251.     LICINFO *pLicInfo
  252. )
  253. {
  254.     CHECK_POINTER(pLicInfo);
  255.  
  256.     pLicInfo->cbLicInfo = sizeof(LICINFO);
  257.  
  258.     // This says whether RequestLicKey will work
  259.     //
  260.     pLicInfo->fRuntimeKeyAvail = g_fMachineHasLicense;
  261.  
  262.     // This says whether the standard CreateInstance will work
  263.     //
  264.     pLicInfo->fLicVerified = g_fMachineHasLicense;
  265.  
  266.     return S_OK;
  267. }
  268.  
  269.  
  270. //=--------------------------------------------------------------------------=
  271. // CClassFactory::RequestLicKey
  272. //=--------------------------------------------------------------------------=
  273. // IClassFactory2 RequestLicKey
  274. //
  275. // Parameters:
  276. //    DWORD             - [in]  reserved
  277. //    BSTR *            - [out] unclear
  278. //
  279. // Output:
  280. //    HRESULT           - unclear
  281. //
  282. // Notes:
  283. //
  284. STDMETHODIMP CClassFactory::RequestLicKey
  285. (
  286.     DWORD  dwReserved,
  287.     BSTR  *pbstr
  288. )
  289. {
  290.     // if the machine isn't licensed, then we're not about to give this to them !
  291.     //
  292.     if (!g_fMachineHasLicense)
  293.         return CLASS_E_NOTLICENSED;
  294.  
  295.     *pbstr = GetLicenseKey();
  296.     return (*pbstr) ? S_OK : E_OUTOFMEMORY;
  297. }
  298.  
  299.  
  300. //=--------------------------------------------------------------------------=
  301. // CClassFactory::CreateInstanceLic
  302. //=--------------------------------------------------------------------------=
  303. // create a new instance given a licensing key, etc ...
  304. //
  305. // Parameters:
  306. //    IUnknown *        - [in]  controlling IUnknown for aggregation
  307. //    IUnknown *        - [in]  reserved, must be NULL
  308. //    REFIID            - [in]  IID We're looking for.
  309. //    BSTR              - [in]  license key
  310. //    void **           - [out] where to put the new object.
  311. //
  312. // Output:
  313. //    HRESULT           - unclear
  314. //
  315. // Notes:
  316. //
  317. STDMETHODIMP CClassFactory::CreateInstanceLic
  318. (
  319.     IUnknown *pUnkOuter,
  320.     IUnknown *pUnkReserved,
  321.     REFIID    riid,
  322.     BSTR      bstrKey,
  323.     void    **ppvObjOut
  324. )
  325. {
  326.     *ppvObjOut = NULL;
  327.  
  328.     // go and see if the key they gave us matches.
  329.     //
  330.     if (!CheckLicenseKey(bstrKey))
  331.         return CLASS_E_NOTLICENSED;
  332.  
  333.     // if it does, then go and create the object.
  334.     //
  335.     return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid);
  336. }
  337.  
  338. //=--------------------------------------------------------------------------=
  339. // CreateOleObjectFromIndex
  340. //=--------------------------------------------------------------------------=
  341. // given an index in our object table, create an object from it.
  342. //
  343. // Parameters:
  344. //    IUnknown *       - [in]  Controlling Unknown, if any, for aggregation
  345. //    int              - [in]  index into our global table
  346. //    void **          - [out] where to put resulting object.
  347. //    REFIID           - [in]  the interface they want resulting object to be.
  348. //
  349. // Output:
  350. //    HRESULT          - S_OK, E_OUTOFMEMORY, E_NOINTERFACE
  351. //
  352. // Notes:
  353. //
  354. HRESULT CreateOleObjectFromIndex
  355. (
  356.     IUnknown *pUnkOuter,
  357.     int       iIndex,
  358.     void    **ppvObjOut,
  359.     REFIID    riid
  360. )
  361. {
  362.     IUnknown *pUnk = NULL;
  363.     HRESULT   hr;
  364.  
  365.     // go and create the object
  366.     //
  367.     ASSERT(CREATEFNOFOBJECT(iIndex), "All creatable objects must have creation fn!");
  368.     pUnk = CREATEFNOFOBJECT(iIndex)(pUnkOuter);
  369.  
  370.     // sanity check and make sure the object actually got allocated.
  371.     //
  372.     RETURN_ON_NULLALLOC(pUnk);
  373.  
  374.     // make sure we support aggregation here properly -- if they gave us
  375.     // a controlling unknown, then they -must- ask for IUnknown, and we'll
  376.     // give them the private unknown the object gave us.
  377.     //
  378.     if (pUnkOuter) {
  379.         if (!DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  380.             pUnk->Release();
  381.             return E_INVALIDARG;
  382.         }
  383.  
  384.         *ppvObjOut = (void *)pUnk;
  385.         hr = S_OK;
  386.     } else {
  387.  
  388.         // QI for whatever the user wants.
  389.         //
  390.         hr = pUnk->QueryInterface(riid, ppvObjOut);
  391.         pUnk->Release();
  392.         RETURN_ON_FAILURE(hr);
  393.     }
  394.  
  395.     return hr;
  396. }
  397.