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 | |
29 | extern HRESULT TypeNameFactoryCreateObject(REFIID riid, void **ppUnk); |
30 | |
31 | #include <ndpversion.h> |
32 | |
33 | |
34 | //********** Locals. ********************************************************** |
35 | HINSTANCE 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! |
41 | const 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 | //***************************************************************************** |
56 | STDAPI 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 | //***************************************************************************** |
98 | HRESULT 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 | //***************************************************************************** |
130 | HRESULT 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 | |
151 | ErrExit: |
152 | END_ENTRYPOINT_NOTHROW; |
153 | |
154 | return hr; |
155 | } |
156 | |
157 | HRESULT STDMETHODCALLTYPE |
158 | MDClassFactory::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 | |