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.

443 lines
12 KiB

  1. //=--------------------------------------------------------------------------=
  2. // ClassFactory.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 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 "pch.h"
  16. #include "LocalSrv.H"
  17. #include "ClassF.H"
  18. #include "Unknown.H" // for CREATEFNOFOBJECT
  19. //=--------------------------------------------------------------------------=
  20. // private module level data
  21. //=--------------------------------------------------------------------------=
  22. //
  23. // ASSERT and FAIL require this
  24. //
  25. SZTHISFILE
  26. // private routines for this file
  27. //
  28. HRESULT CreateOleObjectFromIndex(IUnknown *, int Index, void **, REFIID);
  29. // This is the GUID for a "phantom" interface which VB5 UserControls query
  30. // for to determine if the control doesn't require its license key to be
  31. // present if it's part of a composite UserControl being used in the
  32. // design environment.
  33. //
  34. static const GUID IID_ILicOnCompositeCtl =
  35. { 0x6e6e9780, 0x165d, 0x11d0, { 0xb3, 0xe6, 0x00, 0xa0, 0xc9, 0x0f, 0x27, 0x31 } };
  36. //=--------------------------------------------------------------------------=
  37. // CClassFactory::CClassFactory
  38. //=--------------------------------------------------------------------------=
  39. // create the object and initialize the refcount
  40. //
  41. // Parameters:
  42. // int - [in] index into our global table of objects for this guy
  43. //
  44. // Notes:
  45. //
  46. CClassFactory::CClassFactory
  47. (
  48. int iIndex
  49. )
  50. : m_iIndex(iIndex)
  51. {
  52. InterlockedIncrement(&g_cLocks);
  53. m_cRefs = 1;
  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. InterlockedDecrement(&g_cLocks);
  67. return;
  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. CHECK_POINTER(ppvObjOut);
  91. // we support IUnknown, and the two CF interfaces
  92. //
  93. if (DO_GUIDS_MATCH(riid, IID_IClassFactory)) {
  94. pv = (void *)(IClassFactory *)this;
  95. } else if (DO_GUIDS_MATCH(riid, IID_IClassFactory2)) {
  96. pv = (void *)(IClassFactory2 *)this;
  97. } else if (DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  98. pv = (void *)(IUnknown *)this;
  99. } else if (g_fUseRuntimeLicInCompositeCtl && riid == IID_ILicOnCompositeCtl) {
  100. pv = (void *)(IUnknown *)this;
  101. } else {
  102. *ppvObjOut = NULL;
  103. return E_NOINTERFACE;
  104. }
  105. ((IUnknown *)pv)->AddRef();
  106. *ppvObjOut = pv;
  107. return S_OK;
  108. }
  109. //=--------------------------------------------------------------------------=
  110. // CClassFactory::AddRef
  111. //=--------------------------------------------------------------------------=
  112. // adds a tick to the current reference count.
  113. //
  114. // Output:
  115. // ULONG - the new reference count
  116. //
  117. // Notes:
  118. //
  119. ULONG CClassFactory::AddRef
  120. (
  121. void
  122. )
  123. {
  124. return ++m_cRefs;
  125. }
  126. //=--------------------------------------------------------------------------=
  127. // CClassFactory::Release
  128. //=--------------------------------------------------------------------------=
  129. // removes a tick from the count, and delets the object if necessary
  130. //
  131. // Output:
  132. // ULONG - remaining refs
  133. //
  134. // Notes:
  135. //
  136. ULONG CClassFactory::Release
  137. (
  138. void
  139. )
  140. {
  141. ASSERT(m_cRefs, "No Refs, and we're being released!");
  142. if(--m_cRefs)
  143. return m_cRefs;
  144. delete this;
  145. return 0;
  146. }
  147. //=--------------------------------------------------------------------------=
  148. // CClassFactory::CreateInstance
  149. //=--------------------------------------------------------------------------=
  150. // create an instance of some sort of object.
  151. //
  152. // Parameters:
  153. // IUnknown * - [in] controlling IUknonwn for aggregation
  154. // REFIID - [in] interface id for new object
  155. // void ** - [out] pointer to new interface object.
  156. //
  157. // Output:
  158. // HRESULT - S_OK, E_NOINTERFACE, E_UNEXPECTED,
  159. // E_OUTOFMEMORY, E_INVALIDARG
  160. //
  161. // Notes:
  162. //
  163. STDMETHODIMP CClassFactory::CreateInstance
  164. (
  165. IUnknown *pUnkOuter,
  166. REFIID riid,
  167. void **ppvObjOut
  168. )
  169. {
  170. // check args
  171. //
  172. if (!ppvObjOut)
  173. return E_INVALIDARG;
  174. // check to see if we've done our licensing work. we do this as late
  175. // as possible that people calling CreateInstanceLic don't suffer from
  176. // a performance hit here.
  177. //
  178. // crit sect this for apartment threading, since it's global
  179. //
  180. ENTERCRITICALSECTION1(&g_CriticalSection);
  181. if (!g_fCheckedForLicense) {
  182. g_fMachineHasLicense = CheckForLicense();
  183. g_fCheckedForLicense = TRUE;
  184. }
  185. LEAVECRITICALSECTION1(&g_CriticalSection);
  186. // check to see if they have the appropriate license to create this stuff
  187. //
  188. if (!g_fMachineHasLicense)
  189. return CLASS_E_NOTLICENSED;
  190. // try to create one of the objects that we support
  191. //
  192. return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid);
  193. }
  194. //=--------------------------------------------------------------------------=
  195. // CClassFactory::LockServer
  196. //=--------------------------------------------------------------------------=
  197. // lock the server so we can't unload
  198. //
  199. // Parameters:
  200. // BOOL - [in] TRUE means addref, false means release lock count.
  201. //
  202. // Output:
  203. // HRESULT - S_OK, E_FAIL, E_OUTOFMEMORY, E_UNEXPECTED
  204. //
  205. // Notes:
  206. //
  207. STDMETHODIMP CClassFactory::LockServer
  208. (
  209. BOOL fLock
  210. )
  211. {
  212. // update the lock count. crit sect these in case of another thread.
  213. //
  214. if (fLock)
  215. InterlockedIncrement(&g_cLocks);
  216. else {
  217. ASSERT(g_cLocks, "D'oh! Lock Counting Problem");
  218. InterlockedDecrement(&g_cLocks);
  219. }
  220. return S_OK;
  221. }
  222. //=--------------------------------------------------------------------------=
  223. // CClassFactory::GetLicInfo
  224. //=--------------------------------------------------------------------------=
  225. // IClassFactory2 GetLicInfo
  226. //
  227. // Parameters:
  228. // LICINFO * - unclear
  229. //
  230. // Output:
  231. // HRESULT - unclear
  232. //
  233. // Notes:
  234. //
  235. STDMETHODIMP CClassFactory::GetLicInfo
  236. (
  237. LICINFO *pLicInfo
  238. )
  239. {
  240. CHECK_POINTER(pLicInfo);
  241. // crit sect this for apartment threading, since it's global
  242. //
  243. ENTERCRITICALSECTION1(&g_CriticalSection);
  244. if (!g_fCheckedForLicense) {
  245. g_fMachineHasLicense = CheckForLicense();
  246. g_fCheckedForLicense = TRUE;
  247. }
  248. LEAVECRITICALSECTION1(&g_CriticalSection);
  249. // This says whether RequestLicKey will work
  250. //
  251. pLicInfo->fRuntimeKeyAvail = g_fMachineHasLicense;
  252. // This says whether the standard CreateInstance will work
  253. //
  254. pLicInfo->fLicVerified = g_fMachineHasLicense;
  255. return S_OK;
  256. }
  257. //=--------------------------------------------------------------------------=
  258. // CClassFactory::RequestLicKey
  259. //=--------------------------------------------------------------------------=
  260. // IClassFactory2 RequestLicKey
  261. //
  262. // Parameters:
  263. // DWORD - [in] reserved
  264. // BSTR * - [out] unclear
  265. //
  266. // Output:
  267. // HRESULT - unclear
  268. //
  269. // Notes:
  270. //
  271. STDMETHODIMP CClassFactory::RequestLicKey
  272. (
  273. DWORD dwReserved,
  274. BSTR *pbstr
  275. )
  276. {
  277. // crit sect this for apartment threading, since it's global
  278. //
  279. ENTERCRITICALSECTION1(&g_CriticalSection);
  280. if (!g_fCheckedForLicense) {
  281. g_fMachineHasLicense = CheckForLicense();
  282. g_fCheckedForLicense = TRUE;
  283. }
  284. LEAVECRITICALSECTION1(&g_CriticalSection);
  285. // if the machine isn't licensed, then we're not about to give this to them !
  286. //
  287. if (!g_fMachineHasLicense)
  288. return CLASS_E_NOTLICENSED;
  289. *pbstr = GetLicenseKey();
  290. return (*pbstr) ? S_OK : E_OUTOFMEMORY;
  291. }
  292. //=--------------------------------------------------------------------------=
  293. // CClassFactory::CreateInstanceLic
  294. //=--------------------------------------------------------------------------=
  295. // create a new instance given a licensing key, etc ...
  296. //
  297. // Parameters:
  298. // IUnknown * - [in] controlling IUnknown for aggregation
  299. // IUnknown * - [in] reserved, must be NULL
  300. // REFIID - [in] IID We're looking for.
  301. // BSTR - [in] license key
  302. // void ** - [out] where to put the new object.
  303. //
  304. // Output:
  305. // HRESULT - unclear
  306. //
  307. // Notes:
  308. //
  309. STDMETHODIMP CClassFactory::CreateInstanceLic
  310. (
  311. IUnknown *pUnkOuter,
  312. IUnknown *pUnkReserved,
  313. REFIID riid,
  314. BSTR bstrKey,
  315. void **ppvObjOut
  316. )
  317. {
  318. *ppvObjOut = NULL;
  319. // crit sect this for apartment threading, since it's global
  320. //
  321. ENTERCRITICALSECTION1(&g_CriticalSection);
  322. if (!g_fCheckedForLicense) {
  323. g_fMachineHasLicense = CheckForLicense();
  324. g_fCheckedForLicense = TRUE;
  325. }
  326. LEAVECRITICALSECTION1(&g_CriticalSection);
  327. // go and see if the key they gave us matches.
  328. //
  329. if (!CheckLicenseKey(bstrKey))
  330. return CLASS_E_NOTLICENSED;
  331. // if it does, then go and create the object.
  332. //
  333. return CreateOleObjectFromIndex(pUnkOuter, m_iIndex, ppvObjOut, riid);
  334. }
  335. //=--------------------------------------------------------------------------=
  336. // CreateOleObjectFromIndex
  337. //=--------------------------------------------------------------------------=
  338. // given an index in our object table, create an object from it.
  339. //
  340. // Parameters:
  341. // IUnknown * - [in] Controlling Unknown, if any, for aggregation
  342. // int - [in] index into our global table
  343. // void ** - [out] where to put resulting object.
  344. // REFIID - [in] the interface they want resulting object to be.
  345. //
  346. // Output:
  347. // HRESULT - S_OK, E_OUTOFMEMORY, E_NOINTERFACE
  348. //
  349. // Notes:
  350. //
  351. HRESULT CreateOleObjectFromIndex
  352. (
  353. IUnknown *pUnkOuter,
  354. int iIndex,
  355. void **ppvObjOut,
  356. REFIID riid
  357. )
  358. {
  359. IUnknown *pUnk = NULL;
  360. HRESULT hr;
  361. // If the object specifies a pre-Create static function call that first.
  362. //
  363. if (PRECREATEFNOFOBJECT(iIndex) != NULL) {
  364. hr = PRECREATEFNOFOBJECT(iIndex)();
  365. IfFailRet(hr);
  366. }
  367. // go and create the object
  368. //
  369. ASSERT(CREATEFNOFOBJECT(iIndex), "WARNING: Attempt to create an object that doesn't have a Create function.");
  370. if (!CREATEFNOFOBJECT(iIndex))
  371. return E_FAIL;
  372. pUnk = CREATEFNOFOBJECT(iIndex)(pUnkOuter);
  373. // sanity check and make sure the object actually got allocated.
  374. //
  375. RETURN_ON_NULLALLOC(pUnk);
  376. // make sure we support aggregation here properly -- if they gave us
  377. // a controlling unknown, then they -must- ask for IUnknown, and we'll
  378. // give them the private unknown the object gave us.
  379. //
  380. if (pUnkOuter) {
  381. if (!DO_GUIDS_MATCH(riid, IID_IUnknown)) {
  382. pUnk->Release();
  383. return E_INVALIDARG;
  384. }
  385. *ppvObjOut = (void *)pUnk;
  386. hr = S_OK;
  387. } else {
  388. // QI for whatever the user wants.
  389. //
  390. hr = pUnk->QueryInterface(riid, ppvObjOut);
  391. pUnk->Release();
  392. RETURN_ON_FAILURE(hr);
  393. }
  394. return hr;
  395. }