1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// ClassFactory.cpp
6//
7
8//
9// Dll* routines for entry points, and support for COM framework. The class
10// factory and other routines live in this module.
11//
12// This file is not included in the standalone metadata version, because standalone can't use COM,
13// let alone COM-activation. So this file gets linked into mscorwks.dll, and then the mscorwks
14// class factory delegates to this co-creation routine.
15//
16//*****************************************************************************
17#include "stdafx.h"
18
19#ifdef FEATURE_METADATA_IN_VM
20
21#include "classfactory.h"
22#include "disp.h"
23#include "regmeta.h"
24#include "mscoree.h"
25#include "corhost.h"
26
27#include "clrprivhosting.h"
28
29extern HRESULT TypeNameFactoryCreateObject(REFIID riid, void **ppUnk);
30
31#include <ndpversion.h>
32
33
34//********** Locals. **********************************************************
35HINSTANCE GetModuleInst();
36
37// @telesto - why does Telesto export any Co-classes at all?
38
39// This map contains the list of coclasses which are exported from this module.
40// NOTE: CLSID_CorMetaDataDispenser must be the first entry in this table!
41const COCLASS_REGISTER g_CoClasses[] =
42{
43// pClsid szProgID pfnCreateObject
44 { &CLSID_CorMetaDataDispenser, W("CorMetaDataDispenser"), Disp::CreateObject },
45 { NULL, NULL, NULL }
46};
47
48
49//*****************************************************************************
50// Called by COM to get a class factory for a given CLSID. If it is one we
51// support, instantiate a class factory object and prepare for create instance.
52//
53// Notes:
54// This gets invoked from mscorwks's DllGetClassObject.
55//*****************************************************************************
56STDAPI MetaDataDllGetClassObject( // Return code.
57 REFCLSID rclsid, // The class to desired.
58 REFIID riid, // Interface wanted on class factory.
59 LPVOID FAR *ppv) // Return interface pointer here.
60{
61 MDClassFactory *pClassFactory; // To create class factory object.
62 const COCLASS_REGISTER *pCoClass; // Loop control.
63 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
64
65 // Scan for the right one.
66 for (pCoClass=g_CoClasses; pCoClass->pClsid; pCoClass++)
67 {
68 if (*pCoClass->pClsid == rclsid)
69 {
70 // Allocate the new factory object.
71 pClassFactory = new (nothrow) MDClassFactory(pCoClass);
72 if (!pClassFactory)
73 return (E_OUTOFMEMORY);
74
75 // Pick the v-table based on the caller's request.
76 hr = pClassFactory->QueryInterface(riid, ppv);
77
78 // Always release the local reference, if QI failed it will be
79 // the only one and the object gets freed.
80 pClassFactory->Release();
81 break;
82 }
83 }
84 return hr;
85}
86
87
88//*****************************************************************************
89//
90//********** Class factory code.
91//
92//*****************************************************************************
93
94
95//*****************************************************************************
96// QueryInterface is called to pick a v-table on the co-class.
97//*****************************************************************************
98HRESULT STDMETHODCALLTYPE MDClassFactory::QueryInterface(
99 REFIID riid,
100 void **ppvObject)
101{
102 HRESULT hr;
103
104 // Avoid confusion.
105 *ppvObject = NULL;
106
107 // Pick the right v-table based on the IID passed in.
108 if (riid == IID_IUnknown)
109 *ppvObject = (IUnknown *) this;
110 else if (riid == IID_IClassFactory)
111 *ppvObject = (IClassFactory *) this;
112
113 // If successful, add a reference for out pointer and return.
114 if (*ppvObject)
115 {
116 hr = S_OK;
117 AddRef();
118 }
119 else
120 hr = E_NOINTERFACE;
121 return hr;
122}
123
124
125//*****************************************************************************
126// CreateInstance is called to create a new instance of the coclass for which
127// this class was created in the first place. The returned pointer is the
128// v-table matching the IID if there.
129//*****************************************************************************
130HRESULT STDMETHODCALLTYPE MDClassFactory::CreateInstance(
131 IUnknown *pUnkOuter,
132 REFIID riid,
133 void **ppvObject)
134{
135 HRESULT hr;
136
137 BEGIN_ENTRYPOINT_NOTHROW;
138
139
140 // Avoid confusion.
141 *ppvObject = NULL;
142 _ASSERTE(m_pCoClass);
143
144 // Aggregation is not supported by these objects.
145 if (pUnkOuter)
146 IfFailGo(CLASS_E_NOAGGREGATION);
147
148 // Ask the object to create an instance of itself, and check the iid.
149 hr = (*m_pCoClass->pfnCreateObject)(riid, ppvObject);
150
151ErrExit:
152 END_ENTRYPOINT_NOTHROW;
153
154 return hr;
155}
156
157HRESULT STDMETHODCALLTYPE
158MDClassFactory::LockServer(
159 BOOL fLock)
160{
161 // @FUTURE: Should we return E_NOTIMPL instead of S_OK?
162 return S_OK;
163}
164
165#endif //FEATURE_METADATA_IN_VM
166