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 | // ==++== |
6 | // |
7 | |
8 | // |
9 | // ==--== |
10 | |
11 | #ifndef __SOS_MD_H__ |
12 | #define __SOS_MD_H__ |
13 | |
14 | #define IfErrGoTo(s, label) { \ |
15 | hresult = (s); \ |
16 | if(FAILED(hresult)){ \ |
17 | goto label; }} |
18 | |
19 | class CQuickBytes; |
20 | |
21 | // TODO: Cleanup code to allow SOS to directly include the metadata header files. |
22 | //#include "MetaData.h" |
23 | //#include "corpriv.h" |
24 | |
25 | /* |
26 | * |
27 | * Metadata definitions needed for PrettyPrint functions. |
28 | * The original definitions for the types and interfaces below exist in |
29 | * inc\MetaData.h and inc\CorPriv.h |
30 | * TODO: |
31 | * Cleanup code to allow SOS to directly include the metadata header files. |
32 | * Currently it's extremely difficult due to symbol redefinitions. |
33 | * Always keep the definitions below in sync with the originals. |
34 | * NOTES: |
35 | * Since SOS runs in a native debugger session, since it does not use EnC, |
36 | * and in order to minimize the amount of duplication we changed the |
37 | * method definitions that deal with UTSemReadWrite* arguments to take |
38 | * void* arguments instead. |
39 | * Also, some of the interface methods take CQuickBytes as arguments. |
40 | * If these methods are ever used it becomes crucial to maintain binary |
41 | * compatibility b/w the CQuickBytes defined in SOS and the definition |
42 | * from the EE. |
43 | * |
44 | */ |
45 | typedef enum tagEnumType |
46 | { |
47 | MDSimpleEnum = 0x0, // simple enumerator that doesn't allocate memory |
48 | MDDynamicArrayEnum = 0x2, // dynamic array that holds tokens |
49 | = 0x3, // Custom enumerator that doesnt work with the enum functions |
50 | } EnumType; |
51 | |
52 | struct HENUMInternal |
53 | { |
54 | DWORD m_tkKind; // kind of tables that the enum is holding the result |
55 | ULONG m_ulCount; // count of total entries holding by the enumerator |
56 | |
57 | EnumType m_EnumType; |
58 | |
59 | struct { |
60 | ULONG m_ulStart; |
61 | ULONG m_ulEnd; |
62 | ULONG m_ulCur; |
63 | } u; |
64 | |
65 | // m_cursor will go away when we no longer support running EE with uncompressed |
66 | // format. WHEN WE REMOVE THIS, REMOVE ITS VESTIAGES FROM ZeroEnum as well |
67 | // |
68 | char m_cursor[32]; // cursor holding query result for read/write mode |
69 | }; |
70 | |
71 | typedef struct _MDDefaultValue |
72 | { |
73 | #if DBG_TARGET_BIGENDIAN |
74 | _MDDefaultValue(void) |
75 | { |
76 | m_bType = ELEMENT_TYPE_END; |
77 | } |
78 | ~_MDDefaultValue(void) |
79 | { |
80 | if (m_bType == ELEMENT_TYPE_STRING) |
81 | { |
82 | delete[] m_wzValue; |
83 | } |
84 | } |
85 | #endif |
86 | |
87 | // type of default value |
88 | BYTE m_bType; // CorElementType for the default value |
89 | |
90 | // the default value |
91 | union |
92 | { |
93 | BOOL m_bValue; // ELEMENT_TYPE_BOOLEAN |
94 | CHAR m_cValue; // ELEMENT_TYPE_I1 |
95 | BYTE m_byteValue; // ELEMENT_TYPE_UI1 |
96 | SHORT m_sValue; // ELEMENT_TYPE_I2 |
97 | USHORT m_usValue; // ELEMENT_TYPE_UI2 |
98 | LONG m_lValue; // ELEMENT_TYPE_I4 |
99 | ULONG m_ulValue; // ELEMENT_TYPE_UI4 |
100 | LONGLONG m_llValue; // ELEMENT_TYPE_I8 |
101 | ULONGLONG m_ullValue; // ELEMENT_TYPE_UI8 |
102 | FLOAT m_fltValue; // ELEMENT_TYPE_R4 |
103 | DOUBLE m_dblValue; // ELEMENT_TYPE_R8 |
104 | LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING |
105 | IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS |
106 | }; |
107 | ULONG m_cbSize; // default value size (for blob) |
108 | |
109 | } MDDefaultValue; |
110 | |
111 | typedef struct |
112 | { |
113 | RID m_ridFieldCur; // indexing to the field table |
114 | RID m_ridFieldEnd; // end index to field table |
115 | } MD_CLASS_LAYOUT; |
116 | |
117 | typedef struct |
118 | { |
119 | USHORT usMajorVersion; // Major Version. |
120 | USHORT usMinorVersion; // Minor Version. |
121 | USHORT usBuildNumber; // Build Number. |
122 | USHORT usRevisionNumber; // Revision Number. |
123 | LPCSTR szLocale; // Locale. |
124 | DWORD *rProcessor; // Processor array. |
125 | ULONG ulProcessor; // [IN/OUT] Size of the processor array/Actual # of entries filled in. |
126 | OSINFO *rOS; // OSINFO array. |
127 | ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. |
128 | } AssemblyMetaDataInternal; |
129 | |
130 | typedef struct |
131 | { |
132 | mdMethodDef m_memberdef; |
133 | DWORD m_dwSemantics; |
134 | } ASSOCIATE_RECORD; |
135 | |
136 | typedef BOOL (*PSIGCOMPARE)(PCCOR_SIGNATURE, DWORD, PCCOR_SIGNATURE, DWORD, void*); |
137 | |
138 | EXTERN_GUID(IID_IMDInternalImport, 0xce0f34ed, 0xbbc6, 0x11d2, 0x94, 0x1e, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); |
139 | #undef INTERFACE |
140 | #define INTERFACE IMDInternalImport |
141 | DECLARE_INTERFACE_(IMDInternalImport, IUnknown) |
142 | { |
143 | //***************************************************************************** |
144 | // return the count of entries of a given kind in a scope |
145 | // For example, pass in mdtMethodDef will tell you how many MethodDef |
146 | // contained in a scope |
147 | //***************************************************************************** |
148 | STDMETHOD_(ULONG, GetCountWithTokenKind)(// return hresult |
149 | DWORD tkKind) PURE; // [IN] pass in the kind of token. |
150 | |
151 | //***************************************************************************** |
152 | // enumerator for typedef |
153 | //***************************************************************************** |
154 | STDMETHOD(EnumTypeDefInit)( // return hresult |
155 | HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data |
156 | |
157 | STDMETHOD_(ULONG, EnumTypeDefGetCount)( |
158 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information |
159 | |
160 | STDMETHOD_(void, EnumTypeDefReset)( |
161 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information |
162 | |
163 | STDMETHOD_(bool, EnumTypeDefNext)( // return hresult |
164 | HENUMInternal *phEnum, // [IN] input enum |
165 | mdTypeDef *ptd) PURE; // [OUT] return token |
166 | |
167 | STDMETHOD_(void, EnumTypeDefClose)( |
168 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information |
169 | |
170 | //***************************************************************************** |
171 | // enumerator for MethodImpl |
172 | //***************************************************************************** |
173 | STDMETHOD(EnumMethodImplInit)( // return hresult |
174 | mdTypeDef td, // [IN] TypeDef over which to scope the enumeration. |
175 | HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens. |
176 | HENUMInternal *phEnumDecl) PURE; // [OUT] buffer to fill for enumerator data for MethodDecl tokens. |
177 | |
178 | STDMETHOD_(ULONG, EnumMethodImplGetCount)( |
179 | HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. |
180 | HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. |
181 | |
182 | STDMETHOD_(void, EnumMethodImplReset)( |
183 | HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. |
184 | HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. |
185 | |
186 | STDMETHOD(EnumMethodImplNext)( // return hresult (S_OK = TRUE, S_FALSE = FALSE or error code) |
187 | HENUMInternal *phEnumBody, // [IN] input enum for MethodBody |
188 | HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl |
189 | mdToken *ptkBody, // [OUT] return token for MethodBody |
190 | mdToken *ptkDecl) PURE; // [OUT] return token for MethodDecl |
191 | |
192 | STDMETHOD_(void, EnumMethodImplClose)( |
193 | HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. |
194 | HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. |
195 | |
196 | //***************************************** |
197 | // Enumerator helpers for memberdef, memberref, interfaceimp, |
198 | // event, property, exception, param |
199 | //***************************************** |
200 | |
201 | STDMETHOD(EnumGlobalFunctionsInit)( // return hresult |
202 | HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data |
203 | |
204 | STDMETHOD(EnumGlobalFieldsInit)( // return hresult |
205 | HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data |
206 | |
207 | STDMETHOD(EnumInit)( // return S_FALSE if record not found |
208 | DWORD tkKind, // [IN] which table to work on |
209 | mdToken tkParent, // [IN] token to scope the search |
210 | HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill |
211 | |
212 | STDMETHOD(EnumAllInit)( // return S_FALSE if record not found |
213 | DWORD tkKind, // [IN] which table to work on |
214 | HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill |
215 | |
216 | STDMETHOD_(bool, EnumNext)( |
217 | HENUMInternal *phEnum, // [IN] the enumerator to retrieve information |
218 | mdToken *ptk) PURE; // [OUT] token to scope the search |
219 | |
220 | STDMETHOD_(ULONG, EnumGetCount)( |
221 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information |
222 | |
223 | STDMETHOD_(void, EnumReset)( |
224 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to be reset |
225 | |
226 | STDMETHOD_(void, EnumClose)( |
227 | HENUMInternal *phEnum) PURE; // [IN] the enumerator to be closed |
228 | |
229 | //***************************************** |
230 | // Enumerator helpers for declsecurity. |
231 | //***************************************** |
232 | STDMETHOD(EnumPermissionSetsInit)( // return S_FALSE if record not found |
233 | mdToken tkParent, // [IN] token to scope the search |
234 | CorDeclSecurity Action, // [IN] Action to scope the search |
235 | HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill |
236 | |
237 | //***************************************** |
238 | // Enumerator helpers for CustomAttribute |
239 | //***************************************** |
240 | STDMETHOD(EnumCustomAttributeByNameInit)(// return S_FALSE if record not found |
241 | mdToken tkParent, // [IN] token to scope the search |
242 | LPCSTR szName, // [IN] CustomAttribute's name to scope the search |
243 | HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill |
244 | |
245 | //***************************************** |
246 | // Nagivator helper to navigate back to the parent token given a token. |
247 | // For example, given a memberdef token, it will return the containing typedef. |
248 | // |
249 | // the mapping is as following: |
250 | // ---given child type---------parent type |
251 | // mdMethodDef mdTypeDef |
252 | // mdFieldDef mdTypeDef |
253 | // mdInterfaceImpl mdTypeDef |
254 | // mdParam mdMethodDef |
255 | // mdProperty mdTypeDef |
256 | // mdEvent mdTypeDef |
257 | // |
258 | //***************************************** |
259 | STDMETHOD(GetParentToken)( |
260 | mdToken tkChild, // [IN] given child token |
261 | mdToken *ptkParent) PURE; // [OUT] returning parent |
262 | |
263 | //***************************************** |
264 | // Custom value helpers |
265 | //***************************************** |
266 | STDMETHOD(GetCustomAttributeProps)( // S_OK or error. |
267 | mdCustomAttribute at, // [IN] The attribute. |
268 | mdToken *ptkType) PURE; // [OUT] Put attribute type here. |
269 | |
270 | STDMETHOD(GetCustomAttributeAsBlob)( |
271 | mdCustomAttribute cv, // [IN] given custom value token |
272 | void const **ppBlob, // [OUT] return the pointer to internal blob |
273 | ULONG *pcbSize) PURE; // [OUT] return the size of the blob |
274 | |
275 | // returned void in v1.0/v1.1 |
276 | STDMETHOD (GetScopeProps)( |
277 | LPCSTR *pszName, // [OUT] scope name |
278 | GUID *pmvid) PURE; // [OUT] version id |
279 | |
280 | // finding a particular method |
281 | STDMETHOD(FindMethodDef)( |
282 | mdTypeDef classdef, // [IN] given typedef |
283 | LPCSTR szName, // [IN] member name |
284 | PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature |
285 | ULONG cbSigBlob, // [IN] count of bytes in the signature blob |
286 | mdMethodDef *pmd) PURE; // [OUT] matching memberdef |
287 | |
288 | // return a iSeq's param given a MethodDef |
289 | STDMETHOD(FindParamOfMethod)( // S_OK or error. |
290 | mdMethodDef md, // [IN] The owning method of the param. |
291 | ULONG iSeq, // [IN] The sequence # of the param. |
292 | mdParamDef *pparamdef) PURE; // [OUT] Put ParamDef token here. |
293 | |
294 | //***************************************** |
295 | // |
296 | // GetName* functions |
297 | // |
298 | //***************************************** |
299 | |
300 | // return the name and namespace of typedef |
301 | STDMETHOD(GetNameOfTypeDef)( |
302 | mdTypeDef classdef, // given classdef |
303 | LPCSTR *pszname, // return class name(unqualified) |
304 | LPCSTR *psznamespace) PURE; // return the name space name |
305 | |
306 | STDMETHOD(GetIsDualOfTypeDef)( |
307 | mdTypeDef classdef, // [IN] given classdef. |
308 | ULONG *pDual) PURE; // [OUT] return dual flag here. |
309 | |
310 | STDMETHOD(GetIfaceTypeOfTypeDef)( |
311 | mdTypeDef classdef, // [IN] given classdef. |
312 | ULONG *pIface) PURE; // [OUT] 0=dual, 1=vtable, 2=dispinterface |
313 | |
314 | // get the name of either methoddef |
315 | STDMETHOD(GetNameOfMethodDef)( // return the name of the memberdef in UTF8 |
316 | mdMethodDef md, // given memberdef |
317 | LPCSTR *pszName) PURE; |
318 | |
319 | STDMETHOD(GetNameAndSigOfMethodDef)( |
320 | mdMethodDef methoddef, // [IN] given memberdef |
321 | PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature |
322 | ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob |
323 | LPCSTR *pszName) PURE; |
324 | |
325 | // return the name of a FieldDef |
326 | STDMETHOD(GetNameOfFieldDef)( |
327 | mdFieldDef fd, // given memberdef |
328 | LPCSTR *pszName) PURE; |
329 | |
330 | // return the name of typeref |
331 | STDMETHOD(GetNameOfTypeRef)( |
332 | mdTypeRef classref, // [IN] given typeref |
333 | LPCSTR *psznamespace, // [OUT] return typeref name |
334 | LPCSTR *pszname) PURE; // [OUT] return typeref namespace |
335 | |
336 | // return the resolutionscope of typeref |
337 | STDMETHOD(GetResolutionScopeOfTypeRef)( |
338 | mdTypeRef classref, // given classref |
339 | mdToken *ptkResolutionScope) PURE; |
340 | |
341 | // Find the type token given the name. |
342 | STDMETHOD(FindTypeRefByName)( |
343 | LPCSTR szNamespace, // [IN] Namespace for the TypeRef. |
344 | LPCSTR szName, // [IN] Name of the TypeRef. |
345 | mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef. |
346 | mdTypeRef *ptk) PURE; // [OUT] TypeRef token returned. |
347 | |
348 | // return the TypeDef properties |
349 | // returned void in v1.0/v1.1 |
350 | STDMETHOD(GetTypeDefProps)( |
351 | mdTypeDef classdef, // given classdef |
352 | DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract |
353 | mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here |
354 | |
355 | // return the item's guid |
356 | STDMETHOD(GetItemGuid)( |
357 | mdToken tkObj, // [IN] given item. |
358 | CLSID *pGuid) PURE; // [out[ put guid here. |
359 | |
360 | // Get enclosing class of the NestedClass. |
361 | STDMETHOD(GetNestedClassProps)( // S_OK or error |
362 | mdTypeDef tkNestedClass, // [IN] NestedClass token. |
363 | mdTypeDef *ptkEnclosingClass) PURE; // [OUT] EnclosingClass token. |
364 | |
365 | // Get count of Nested classes given the enclosing class. |
366 | STDMETHOD(GetCountNestedClasses)( // return count of Nested classes. |
367 | mdTypeDef tkEnclosingClass, // Enclosing class. |
368 | ULONG *pcNestedClassesCount) PURE; |
369 | |
370 | // Return array of Nested classes given the enclosing class. |
371 | STDMETHOD(GetNestedClasses)( // Return actual count. |
372 | mdTypeDef tkEnclosingClass, // [IN] Enclosing class. |
373 | mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens. |
374 | ULONG ulNestedClasses, // [IN] Size of array. |
375 | ULONG *pcNestedClasses) PURE; |
376 | |
377 | // return the ModuleRef properties |
378 | // returned void in v1.0/v1.1 |
379 | STDMETHOD(GetModuleRefProps)( |
380 | mdModuleRef mur, // [IN] moduleref token |
381 | LPCSTR *pszName) PURE; // [OUT] buffer to fill with the moduleref name |
382 | |
383 | //***************************************** |
384 | // |
385 | // GetSig* functions |
386 | // |
387 | //***************************************** |
388 | STDMETHOD(GetSigOfMethodDef)( |
389 | mdMethodDef methoddef, // [IN] given memberdef |
390 | ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob |
391 | PCCOR_SIGNATURE *ppSig) PURE; |
392 | |
393 | STDMETHOD(GetSigOfFieldDef)( |
394 | mdMethodDef methoddef, // [IN] given memberdef |
395 | ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob |
396 | PCCOR_SIGNATURE *ppSig) PURE; |
397 | |
398 | STDMETHOD(GetSigFromToken)( |
399 | mdToken tk, |
400 | ULONG * pcbSig, |
401 | PCCOR_SIGNATURE * ppSig) PURE; |
402 | |
403 | |
404 | |
405 | //***************************************** |
406 | // get method property |
407 | //***************************************** |
408 | STDMETHOD(GetMethodDefProps)( |
409 | mdMethodDef md, // The method for which to get props. |
410 | DWORD *pdwFlags) PURE; |
411 | |
412 | //***************************************** |
413 | // return method implementation informaiton, like RVA and implflags |
414 | //***************************************** |
415 | // returned void in v1.0/v1.1 |
416 | STDMETHOD(GetMethodImplProps)( |
417 | mdToken tk, // [IN] MethodDef |
418 | ULONG *pulCodeRVA, // [OUT] CodeRVA |
419 | DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags |
420 | |
421 | //***************************************** |
422 | // return method implementation informaiton, like RVA and implflags |
423 | //***************************************** |
424 | STDMETHOD(GetFieldRVA)( |
425 | mdFieldDef fd, // [IN] fielddef |
426 | ULONG *pulCodeRVA) PURE; // [OUT] CodeRVA |
427 | |
428 | //***************************************** |
429 | // get field property |
430 | //***************************************** |
431 | STDMETHOD(GetFieldDefProps)( |
432 | mdFieldDef fd, // [IN] given fielddef |
433 | DWORD *pdwFlags) PURE; // [OUT] return fdPublic, fdPrive, etc flags |
434 | |
435 | //***************************************************************************** |
436 | // return default value of a token(could be paramdef, fielddef, or property |
437 | //***************************************************************************** |
438 | STDMETHOD(GetDefaultValue)( |
439 | mdToken tk, // [IN] given FieldDef, ParamDef, or Property |
440 | MDDefaultValue *pDefaultValue) PURE;// [OUT] default value to fill |
441 | |
442 | |
443 | //***************************************** |
444 | // get dispid of a MethodDef or a FieldDef |
445 | //***************************************** |
446 | STDMETHOD(GetDispIdOfMemberDef)( // return hresult |
447 | mdToken tk, // [IN] given methoddef or fielddef |
448 | ULONG *pDispid) PURE; // [OUT] Put the dispid here. |
449 | |
450 | //***************************************** |
451 | // return TypeRef/TypeDef given an InterfaceImpl token |
452 | //***************************************** |
453 | STDMETHOD(GetTypeOfInterfaceImpl)( // return the TypeRef/typedef token for the interfaceimpl |
454 | mdInterfaceImpl iiImpl, // given a interfaceimpl |
455 | mdToken *ptkType) PURE; |
456 | |
457 | //***************************************** |
458 | // look up function for TypeDef |
459 | //***************************************** |
460 | STDMETHOD(FindTypeDef)( |
461 | LPCSTR szNamespace, // [IN] Namespace for the TypeDef. |
462 | LPCSTR szName, // [IN] Name of the TypeDef. |
463 | mdToken tkEnclosingClass, // [IN] TypeRef/TypeDef Token for the enclosing class. |
464 | mdTypeDef *ptypedef) PURE; // [IN] return typedef |
465 | |
466 | //***************************************** |
467 | // return name and sig of a memberref |
468 | //***************************************** |
469 | STDMETHOD(GetNameAndSigOfMemberRef)( // return name here |
470 | mdMemberRef memberref, // given memberref |
471 | PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature |
472 | ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob |
473 | LPCSTR *pszName) PURE; |
474 | |
475 | //***************************************************************************** |
476 | // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef |
477 | //***************************************************************************** |
478 | STDMETHOD(GetParentOfMemberRef)( |
479 | mdMemberRef memberref, // given memberref |
480 | mdToken *ptkParent) PURE; // return the parent token |
481 | |
482 | STDMETHOD(GetParamDefProps)( |
483 | mdParamDef paramdef, // given a paramdef |
484 | USHORT *pusSequence, // [OUT] slot number for this parameter |
485 | DWORD *pdwAttr, // [OUT] flags |
486 | LPCSTR *pszName) PURE; // [OUT] return the name of the parameter |
487 | |
488 | STDMETHOD(GetPropertyInfoForMethodDef)( // Result. |
489 | mdMethodDef md, // [IN] memberdef |
490 | mdProperty *ppd, // [OUT] put property token here |
491 | LPCSTR *pName, // [OUT] put pointer to name here |
492 | ULONG *pSemantic) PURE; // [OUT] put semantic here |
493 | |
494 | //***************************************** |
495 | // class layout/sequence information |
496 | //***************************************** |
497 | STDMETHOD(GetClassPackSize)( // return error if class doesn't have packsize |
498 | mdTypeDef td, // [IN] give typedef |
499 | ULONG *pdwPackSize) PURE; // [OUT] 1, 2, 4, 8, or 16 |
500 | |
501 | STDMETHOD(GetClassTotalSize)( // return error if class doesn't have total size info |
502 | mdTypeDef td, // [IN] give typedef |
503 | ULONG *pdwClassSize) PURE; // [OUT] return the total size of the class |
504 | |
505 | STDMETHOD(GetClassLayoutInit)( |
506 | mdTypeDef td, // [IN] give typedef |
507 | MD_CLASS_LAYOUT *pLayout) PURE; // [OUT] set up the status of query here |
508 | |
509 | STDMETHOD(GetClassLayoutNext)( |
510 | MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here |
511 | mdFieldDef *pfd, // [OUT] return the fielddef |
512 | ULONG *pulOffset) PURE; // [OUT] return the offset/ulSequence associate with it |
513 | |
514 | //***************************************** |
515 | // marshal information of a field |
516 | //***************************************** |
517 | STDMETHOD(GetFieldMarshal)( // return error if no native type associate with the token |
518 | mdFieldDef fd, // [IN] given fielddef |
519 | PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature |
520 | ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType |
521 | |
522 | |
523 | //***************************************** |
524 | // property APIs |
525 | //***************************************** |
526 | // find a property by name |
527 | STDMETHOD(FindProperty)( |
528 | mdTypeDef td, // [IN] given a typdef |
529 | LPCSTR szPropName, // [IN] property name |
530 | mdProperty *pProp) PURE; // [OUT] return property token |
531 | |
532 | // returned void in v1.0/v1.1 |
533 | STDMETHOD(GetPropertyProps)( |
534 | mdProperty prop, // [IN] property token |
535 | LPCSTR *szProperty, // [OUT] property name |
536 | DWORD *pdwPropFlags, // [OUT] property flags. |
537 | PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob |
538 | ULONG *pcbSig) PURE; // [OUT] count of bytes in *ppvSig |
539 | |
540 | //********************************** |
541 | // Event APIs |
542 | //********************************** |
543 | STDMETHOD(FindEvent)( |
544 | mdTypeDef td, // [IN] given a typdef |
545 | LPCSTR szEventName, // [IN] event name |
546 | mdEvent *pEvent) PURE; // [OUT] return event token |
547 | |
548 | // returned void in v1.0/v1.1 |
549 | STDMETHOD(GetEventProps)( |
550 | mdEvent ev, // [IN] event token |
551 | LPCSTR *pszEvent, // [OUT] Event name |
552 | DWORD *pdwEventFlags, // [OUT] Event flags. |
553 | mdToken *ptkEventType) PURE; // [OUT] EventType class |
554 | |
555 | |
556 | //********************************** |
557 | // find a particular associate of a property or an event |
558 | //********************************** |
559 | STDMETHOD(FindAssociate)( |
560 | mdToken evprop, // [IN] given a property or event token |
561 | DWORD associate, // [IN] given a associate semantics(setter, getter, testdefault, reset, AddOn, RemoveOn, Fire) |
562 | mdMethodDef *pmd) PURE; // [OUT] return method def token |
563 | |
564 | // Note, void function in v1.0/v1.1 |
565 | STDMETHOD(EnumAssociateInit)( |
566 | mdToken evprop, // [IN] given a property or an event token |
567 | HENUMInternal *phEnum) PURE; // [OUT] cursor to hold the query result |
568 | |
569 | // returned void in v1.0/v1.1 |
570 | STDMETHOD(GetAllAssociates)( |
571 | HENUMInternal *phEnum, // [IN] query result form GetPropertyAssociateCounts |
572 | ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output |
573 | ULONG cAssociateRec) PURE; // [IN] size of the buffer |
574 | |
575 | |
576 | //********************************** |
577 | // Get info about a PermissionSet. |
578 | //********************************** |
579 | // returned void in v1.0/v1.1 |
580 | STDMETHOD(GetPermissionSetProps)( |
581 | mdPermission pm, // [IN] the permission token. |
582 | DWORD *pdwAction, // [OUT] CorDeclSecurity. |
583 | void const **ppvPermission, // [OUT] permission blob. |
584 | ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. |
585 | |
586 | //**************************************** |
587 | // Get the String given the String token. |
588 | // Returns a pointer to the string, or NULL in case of error. |
589 | //**************************************** |
590 | STDMETHOD(GetUserString)( |
591 | mdString stk, // [IN] the string token. |
592 | ULONG *pchString, // [OUT] count of characters in the string. |
593 | BOOL *pbIs80Plus, // [OUT] specifies where there are extended characters >= 0x80. |
594 | LPCWSTR *pwszUserString) PURE; |
595 | |
596 | //***************************************************************************** |
597 | // p-invoke APIs. |
598 | //***************************************************************************** |
599 | STDMETHOD(GetPinvokeMap)( |
600 | mdToken tk, // [IN] FieldDef, MethodDef. |
601 | DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. |
602 | LPCSTR *pszImportName, // [OUT] Import name. |
603 | mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. |
604 | |
605 | //***************************************************************************** |
606 | // helpers to convert a text signature to a com format |
607 | //***************************************************************************** |
608 | STDMETHOD(ConvertTextSigToComSig)( // Return hresult. |
609 | BOOL fCreateTrIfNotFound, // [IN] create typeref if not found |
610 | LPCSTR pSignature, // [IN] class file format signature |
611 | CQuickBytes *pqbNewSig, // [OUT] place holder for CLR signature |
612 | ULONG *pcbCount) PURE; // [OUT] the result size of signature |
613 | |
614 | //***************************************************************************** |
615 | // Assembly MetaData APIs. |
616 | //***************************************************************************** |
617 | // returned void in v1.0/v1.1 |
618 | STDMETHOD(GetAssemblyProps)( |
619 | mdAssembly mda, // [IN] The Assembly for which to get the properties. |
620 | const void **ppbPublicKey, // [OUT] Pointer to the public key. |
621 | ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. |
622 | ULONG *pulHashAlgId, // [OUT] Hash Algorithm. |
623 | LPCSTR *pszName, // [OUT] Buffer to fill with name. |
624 | AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. |
625 | DWORD *pdwAssemblyFlags) PURE;// [OUT] Flags. |
626 | |
627 | // returned void in v1.0/v1.1 |
628 | STDMETHOD(GetAssemblyRefProps)( |
629 | mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. |
630 | const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. |
631 | ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. |
632 | LPCSTR *pszName, // [OUT] Buffer to fill with name. |
633 | AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. |
634 | const void **ppbHashValue, // [OUT] Hash blob. |
635 | ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. |
636 | DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. |
637 | |
638 | // returned void in v1.0/v1.1 |
639 | STDMETHOD(GetFileProps)( |
640 | mdFile mdf, // [IN] The File for which to get the properties. |
641 | LPCSTR *pszName, // [OUT] Buffer to fill with name. |
642 | const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. |
643 | ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. |
644 | DWORD *pdwFileFlags) PURE; // [OUT] Flags. |
645 | |
646 | // returned void in v1.0/v1.1 |
647 | STDMETHOD(GetExportedTypeProps)( |
648 | mdExportedType mdct, // [IN] The ExportedType for which to get the properties. |
649 | LPCSTR *pszNamespace, // [OUT] Namespace. |
650 | LPCSTR *pszName, // [OUT] Name. |
651 | mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. |
652 | mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. |
653 | DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. |
654 | |
655 | // returned void in v1.0/v1.1 |
656 | STDMETHOD(GetManifestResourceProps)( |
657 | mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. |
658 | LPCSTR *pszName, // [OUT] Buffer to fill with name. |
659 | mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. |
660 | DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. |
661 | DWORD *pdwResourceFlags) PURE;// [OUT] Flags. |
662 | |
663 | STDMETHOD(FindExportedTypeByName)( // S_OK or error |
664 | LPCSTR szNamespace, // [IN] Namespace of the ExportedType. |
665 | LPCSTR szName, // [IN] Name of the ExportedType. |
666 | mdExportedType tkEnclosingType, // [IN] ExportedType for the enclosing class. |
667 | mdExportedType *pmct) PURE; // [OUT] Put ExportedType token here. |
668 | |
669 | STDMETHOD(FindManifestResourceByName)( // S_OK or error |
670 | LPCSTR szName, // [IN] Name of the ManifestResource. |
671 | mdManifestResource *pmmr) PURE; // [OUT] Put ManifestResource token here. |
672 | |
673 | STDMETHOD(GetAssemblyFromScope)( // S_OK or error |
674 | mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. |
675 | |
676 | STDMETHOD(GetCustomAttributeByName)( // S_OK or error |
677 | mdToken tkObj, // [IN] Object with Custom Attribute. |
678 | LPCUTF8 szName, // [IN] Name of desired Custom Attribute. |
679 | const void **ppData, // [OUT] Put pointer to data here. |
680 | ULONG *pcbData) PURE; // [OUT] Put size of data here. |
681 | |
682 | // Note: The return type of this method was void in v1 |
683 | STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. |
684 | mdTypeSpec typespec, // [IN] Signature token. |
685 | PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. |
686 | ULONG *pcbSig) PURE; // [OUT] return size of signature. |
687 | |
688 | STDMETHOD(SetUserContextData)( // S_OK or E_NOTIMPL |
689 | IUnknown *pIUnk) PURE; // The user context. |
690 | |
691 | STDMETHOD_(BOOL, IsValidToken)( // True or False. |
692 | mdToken tk) PURE; // [IN] Given token. |
693 | |
694 | STDMETHOD(TranslateSigWithScope)( |
695 | IMDInternalImport *pAssemImport, // [IN] import assembly scope. |
696 | const void *pbHashValue, // [IN] hash value for the import assembly. |
697 | ULONG cbHashValue, // [IN] count of bytes in the hash value. |
698 | PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope |
699 | ULONG cbSigBlob, // [IN] count of bytes of signature |
700 | IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope. |
701 | IMetaDataEmit *emit, // [IN] emit interface |
702 | CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature |
703 | ULONG *pcbSig) PURE; // [OUT] count of bytes in the translated signature |
704 | |
705 | // since SOS does not need to call method below, change return value to IUnknown* (from IMetaModelCommon*) |
706 | STDMETHOD_(IUnknown*, GetMetaModelCommon)( // Return MetaModelCommon interface. |
707 | ) PURE; |
708 | |
709 | STDMETHOD_(IUnknown *, GetCachedPublicInterface)(BOOL fWithLock) PURE; // return the cached public interface |
710 | STDMETHOD(SetCachedPublicInterface)(IUnknown *pUnk) PURE; // no return value |
711 | // since SOS does not use the next 2 methods replace UTSemReadWrite* with void* in the signature |
712 | STDMETHOD_(void*, GetReaderWriterLock)() PURE; // return the reader writer lock |
713 | STDMETHOD(SetReaderWriterLock)(void * pSem) PURE; |
714 | |
715 | STDMETHOD_(mdModule, GetModuleFromScope)() PURE; // [OUT] Put mdModule token here. |
716 | |
717 | |
718 | //----------------------------------------------------------------- |
719 | // Additional custom methods |
720 | |
721 | // finding a particular method |
722 | STDMETHOD(FindMethodDefUsingCompare)( |
723 | mdTypeDef classdef, // [IN] given typedef |
724 | LPCSTR szName, // [IN] member name |
725 | PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature |
726 | ULONG cbSigBlob, // [IN] count of bytes in the signature blob |
727 | PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures |
728 | void* pSignatureArgs, // [IN] Additional info to supply the compare function |
729 | mdMethodDef *pmd) PURE; // [OUT] matching memberdef |
730 | |
731 | // Additional v2 methods. |
732 | |
733 | //***************************************** |
734 | // return a field offset for a given field |
735 | //***************************************** |
736 | STDMETHOD(GetFieldOffset)( |
737 | mdFieldDef fd, // [IN] fielddef |
738 | ULONG *pulOffset) PURE; // [OUT] FieldOffset |
739 | |
740 | STDMETHOD(GetMethodSpecProps)( |
741 | mdMethodSpec ms, // [IN] The method instantiation |
742 | mdToken *tkParent, // [OUT] MethodDef or MemberRef |
743 | PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data |
744 | ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob |
745 | |
746 | STDMETHOD(GetTableInfoWithIndex)( |
747 | ULONG index, // [IN] pass in the table index |
748 | void **pTable, // [OUT] pointer to table at index |
749 | void **pTableSize) PURE; // [OUT] size of table at index |
750 | |
751 | STDMETHOD(ApplyEditAndContinue)( |
752 | void *pDeltaMD, // [IN] the delta metadata |
753 | ULONG cbDeltaMD, // [IN] length of pData |
754 | IMDInternalImport **ppv) PURE; // [OUT] the resulting metadata interface |
755 | |
756 | //********************************** |
757 | // Generics APIs |
758 | //********************************** |
759 | STDMETHOD(GetGenericParamProps)( // S_OK or error. |
760 | mdGenericParam rd, // [IN] The type parameter |
761 | ULONG* pulSequence, // [OUT] Parameter sequence number |
762 | DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) |
763 | mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) |
764 | DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use) |
765 | LPCSTR *szName) PURE; // [OUT] The name |
766 | |
767 | STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. |
768 | mdGenericParamConstraint rd, // [IN] The constraint token |
769 | mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained |
770 | mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint |
771 | |
772 | //***************************************************************************** |
773 | // This function gets the "built for" version of a metadata scope. |
774 | // NOTE: if the scope has never been saved, it will not have a built-for |
775 | // version, and an empty string will be returned. |
776 | //***************************************************************************** |
777 | STDMETHOD(GetVersionString)( // S_OK or error. |
778 | LPCSTR *pVer) PURE; // [OUT] Put version string here. |
779 | |
780 | |
781 | STDMETHOD(SafeAndSlowEnumCustomAttributeByNameInit)(// return S_FALSE if record not found |
782 | mdToken tkParent, // [IN] token to scope the search |
783 | LPCSTR szName, // [IN] CustomAttribute's name to scope the search |
784 | HENUMInternal *phEnum) PURE; // [OUT] The enumerator |
785 | |
786 | STDMETHOD(SafeAndSlowEnumCustomAttributeByNameNext)(// return S_FALSE if record not found |
787 | mdToken tkParent, // [IN] token to scope the search |
788 | LPCSTR szName, // [IN] CustomAttribute's name to scope the search |
789 | HENUMInternal *phEnum, // [IN] The enumerator |
790 | mdCustomAttribute *mdAttribute) PURE; // [OUT] The custom attribute that was found |
791 | |
792 | |
793 | STDMETHOD(GetTypeDefRefTokenInTypeSpec)(// return S_FALSE if enclosing type does not have a token |
794 | mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at |
795 | mdToken *tkEnclosedToken) PURE; // [OUT] The enclosed type token |
796 | |
797 | #define MD_STREAM_VER_1X 0x10000 |
798 | #define MD_STREAM_VER_2_B1 0x10001 |
799 | #define MD_STREAM_VER_2 0x20000 |
800 | STDMETHOD_(DWORD, GetMetadataStreamVersion)() PURE; //returns DWORD with major version of |
801 | // MD stream in senior word and minor version--in junior word |
802 | |
803 | STDMETHOD(GetNameOfCustomAttribute)(// S_OK or error |
804 | mdCustomAttribute mdAttribute, // [IN] The Custom Attribute |
805 | LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute. |
806 | LPCUTF8 *pszName) PURE; // [OUT] Name of Custom Attribute. |
807 | |
808 | STDMETHOD(SetOptimizeAccessForSpeed)(// S_OK or error |
809 | BOOL fOptSpeed) PURE; |
810 | |
811 | STDMETHOD(SetVerifiedByTrustedSource)(// S_OK or error |
812 | BOOL fVerified) PURE; |
813 | |
814 | }; // IMDInternalImport |
815 | |
816 | EXTERN_GUID(IID_IMetaDataHelper, 0xad93d71d, 0xe1f2, 0x11d1, 0x94, 0x9, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); |
817 | |
818 | #undef INTERFACE |
819 | #define INTERFACE IMetaDataHelper |
820 | DECLARE_INTERFACE_(IMetaDataHelper, IUnknown) |
821 | { |
822 | // helper functions |
823 | // This function is exposing the ability to translate signature from a given |
824 | // source scope to a given target scope. |
825 | // |
826 | STDMETHOD(TranslateSigWithScope)( |
827 | IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface |
828 | const void *pbHashValue, // [IN] Hash Blob for Assembly. |
829 | ULONG cbHashValue, // [IN] Count of bytes. |
830 | IMetaDataImport *import, // [IN] importing interface |
831 | PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope |
832 | ULONG cbSigBlob, // [IN] count of bytes of signature |
833 | IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface |
834 | IMetaDataEmit *emit, // [IN] emit interface |
835 | PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature |
836 | ULONG cbTranslatedSigMax, |
837 | ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature |
838 | |
839 | STDMETHOD(GetMetadata)( |
840 | ULONG ulSelect, // [IN] Selector. |
841 | void **ppData) PURE; // [OUT] Put pointer to data here. |
842 | |
843 | STDMETHOD_(IUnknown *, GetCachedInternalInterface)(BOOL fWithLock) PURE; // S_OK or error |
844 | STDMETHOD(SetCachedInternalInterface)(IUnknown * pUnk) PURE; // S_OK or error |
845 | // since SOS does not use the next 2 methods replace UTSemReadWrite* with void* in the signature |
846 | STDMETHOD_(void*, GetReaderWriterLock)() PURE; // return the reader writer lock |
847 | STDMETHOD(SetReaderWriterLock)(void * pSem) PURE; |
848 | }; |
849 | |
850 | /********************************************************************************/ |
851 | |
852 | // Fine grained formatting flags used by the PrettyPrint APIs below. |
853 | // Upto FormatStubInfo they mirror the values used by TypeString, after that |
854 | // they're used to enable specifying differences between the ILDASM-style |
855 | // output and the C#-like output prefered by the rest of SOS. |
856 | typedef enum |
857 | { |
858 | FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible |
859 | FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names |
860 | FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings) |
861 | FormatAssembly = 0x00000004, // Include assembly display name in type names |
862 | FormatSignature = 0x00000008, // Include signature in method names |
863 | FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names |
864 | FormatDebug = 0x00000020, // For debug printing of types only |
865 | FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T] |
866 | FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub} |
867 | // following flags are not present in TypeString::FormatFlags |
868 | FormatSlashSep = 0x00000100, // Whether nested types are NS.C1/C2 or NS.C1+C2 |
869 | FormatKwInNames = 0x00000200, // Whether "class" and "valuetype" appear in type names in certain instances |
870 | FormatCSharp = 0x0000004b, // Used to generate a C#-like string representation of the token |
871 | FormatILDasm = 0x000003ff, // Used to generate an ILDASM-style string representation of the token |
872 | } |
873 | PPFormatFlags; |
874 | |
875 | char* asString(CQuickBytes *out); |
876 | |
877 | PCCOR_SIGNATURE PrettyPrintType( |
878 | PCCOR_SIGNATURE typePtr, // type to convert, |
879 | CQuickBytes *out, // where to put the pretty printed string |
880 | IMDInternalImport *pIMDI, // ptr to IMDInternal class with ComSig |
881 | DWORD formatFlags = FormatILDasm); |
882 | |
883 | const char* PrettyPrintClass( |
884 | CQuickBytes *out, // where to put the pretty printed string |
885 | mdToken tk, // The class token to look up |
886 | IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig |
887 | DWORD formatFlags = FormatILDasm); |
888 | |
889 | // We have a proliferation of functions that translate a (module/token) pair to |
890 | // a string, but none of them were as complete as PrettyPrintClass. Most were |
891 | // not handling generic instantiations appropriately. PrettyPrintClassFromToken |
892 | // provides this missing functionality. If passed "FormatCSharp" it will generate |
893 | // a name fitting the format used throughout SOS, with the exception of !dumpil |
894 | // (due to its ILDASM ancestry). |
895 | // TODO: Refactor the code in PrettyPrintClassFromToken, NameForTypeDef_s, |
896 | // TODO: NameForToken_s, MDInfo::TypeDef/RefName |
897 | void PrettyPrintClassFromToken( |
898 | TADDR moduleAddr, // the module containing the token |
899 | mdToken tok, // the class token to look up |
900 | __out_ecount(cbName) WCHAR* mdName, // where to put the pretty printed string |
901 | size_t cbName, // the capacity of the buffer |
902 | DWORD formatFlags = FormatCSharp); // the format flags for the types |
903 | |
904 | inline HRESULT GetMDInternalFromImport(IMetaDataImport* pIMDImport, IMDInternalImport **ppIMDI) |
905 | { |
906 | HRESULT hresult = E_FAIL; |
907 | IUnknown *pUnk = NULL; |
908 | IMetaDataHelper *pIMDH = NULL; |
909 | |
910 | IfErrGoTo(pIMDImport->QueryInterface(IID_IMetaDataHelper, (void**)&pIMDH), Cleanup); |
911 | pUnk = pIMDH->GetCachedInternalInterface(FALSE); |
912 | if (pUnk == NULL) |
913 | goto Cleanup; |
914 | IfErrGoTo(pUnk->QueryInterface(IID_IMDInternalImport, (void**)ppIMDI), Cleanup); |
915 | |
916 | Cleanup: |
917 | if (pUnk) |
918 | pUnk->Release(); |
919 | if (pIMDH != NULL) |
920 | pIMDH->Release(); |
921 | |
922 | return hresult; |
923 | } |
924 | |
925 | #endif |
926 | |
927 | |