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 | // AssemblyMD.cpp |
6 | // |
7 | |
8 | // |
9 | // Implementation for the assembly meta data import code (code:IMetaDataAssemblyImport). |
10 | // |
11 | //***************************************************************************** |
12 | #include "stdafx.h" |
13 | #include "regmeta.h" |
14 | #include "mdutil.h" |
15 | #include "rwutil.h" |
16 | #include "mdlog.h" |
17 | #include "importhelper.h" |
18 | |
19 | #include <strongname.h> |
20 | |
21 | #ifdef _MSC_VER |
22 | #pragma warning(disable: 4102) |
23 | #endif |
24 | |
25 | //******************************************************************************* |
26 | // Get the properties for the given Assembly token. |
27 | //******************************************************************************* |
28 | STDMETHODIMP RegMeta::GetAssemblyProps( // S_OK or error. |
29 | mdAssembly mda, // [IN] The Assembly for which to get the properties. |
30 | const void **ppbPublicKey, // [OUT] Pointer to the public key. |
31 | ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. |
32 | ULONG *pulHashAlgId, // [OUT] Hash Algorithm. |
33 | __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. |
34 | ULONG cchName, // [IN] Size of buffer in wide chars. |
35 | ULONG *pchName, // [OUT] Actual # of wide chars in name. |
36 | ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. |
37 | DWORD *pdwAssemblyFlags) // [OUT] Flags. |
38 | { |
39 | HRESULT hr = S_OK; |
40 | |
41 | BEGIN_ENTRYPOINT_NOTHROW; |
42 | |
43 | AssemblyRec *pRecord; |
44 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
45 | |
46 | LOG((LOGMD, "RegMeta::GetAssemblyProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
47 | mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, szName, cchName, pchName, pMetaData, |
48 | pdwAssemblyFlags)); |
49 | |
50 | START_MD_PERF(); |
51 | LOCKREAD(); |
52 | |
53 | _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda)); |
54 | IfFailGo(pMiniMd->GetAssemblyRecord(RidFromToken(mda), &pRecord)); |
55 | |
56 | if (ppbPublicKey != NULL) |
57 | { |
58 | IfFailGo(pMiniMd->getPublicKeyOfAssembly(pRecord, (const BYTE **)ppbPublicKey, pcbPublicKey)); |
59 | } |
60 | if (pulHashAlgId) |
61 | *pulHashAlgId = pMiniMd->getHashAlgIdOfAssembly(pRecord); |
62 | if (pMetaData) |
63 | { |
64 | pMetaData->usMajorVersion = pMiniMd->getMajorVersionOfAssembly(pRecord); |
65 | pMetaData->usMinorVersion = pMiniMd->getMinorVersionOfAssembly(pRecord); |
66 | pMetaData->usBuildNumber = pMiniMd->getBuildNumberOfAssembly(pRecord); |
67 | pMetaData->usRevisionNumber = pMiniMd->getRevisionNumberOfAssembly(pRecord); |
68 | IfFailGo(pMiniMd->getLocaleOfAssembly(pRecord, pMetaData->szLocale, |
69 | pMetaData->cbLocale, &pMetaData->cbLocale)); |
70 | pMetaData->ulProcessor = 0; |
71 | pMetaData->ulOS = 0; |
72 | } |
73 | if (pdwAssemblyFlags) |
74 | { |
75 | *pdwAssemblyFlags = pMiniMd->getFlagsOfAssembly(pRecord); |
76 | |
77 | #ifdef FEATURE_WINDOWSPHONE |
78 | // Turn on the afPublicKey if PublicKey blob is not empty |
79 | DWORD cbPublicKey; |
80 | const BYTE *pbPublicKey; |
81 | IfFailGo(pMiniMd->getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey)); |
82 | if (cbPublicKey != 0) |
83 | *pdwAssemblyFlags |= afPublicKey; |
84 | #else |
85 | if (ppbPublicKey) |
86 | { |
87 | if (pcbPublicKey && *pcbPublicKey) |
88 | *pdwAssemblyFlags |= afPublicKey; |
89 | } |
90 | else |
91 | { |
92 | #ifdef _DEBUG |
93 | // Assert that afPublicKey is set if PublicKey blob is not empty |
94 | DWORD cbPublicKey; |
95 | const BYTE *pbPublicKey; |
96 | IfFailGo(pMiniMd->getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey)); |
97 | bool hasPublicKey = cbPublicKey != 0; |
98 | bool hasPublicKeyFlag = ( *pdwAssemblyFlags & afPublicKey ) != 0; |
99 | _ASSERTE( hasPublicKey == hasPublicKeyFlag ); |
100 | #endif |
101 | } |
102 | #endif // FEATURE_WINDOWSPHONE |
103 | } |
104 | // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK |
105 | if (szName || pchName) |
106 | IfFailGo(pMiniMd->getNameOfAssembly(pRecord, szName, cchName, pchName)); |
107 | ErrExit: |
108 | |
109 | STOP_MD_PERF(GetAssemblyProps); |
110 | |
111 | END_ENTRYPOINT_NOTHROW; |
112 | |
113 | return hr; |
114 | } // RegMeta::GetAssemblyProps |
115 | |
116 | //******************************************************************************* |
117 | // Get the properties for the given AssemblyRef token. |
118 | //******************************************************************************* |
119 | STDMETHODIMP RegMeta::GetAssemblyRefProps( // S_OK or error. |
120 | mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. |
121 | const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. |
122 | ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. |
123 | __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. |
124 | ULONG cchName, // [IN] Size of buffer in wide chars. |
125 | ULONG *pchName, // [OUT] Actual # of wide chars in name. |
126 | ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. |
127 | const void **ppbHashValue, // [OUT] Hash blob. |
128 | ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. |
129 | DWORD *pdwAssemblyRefFlags) // [OUT] Flags. |
130 | { |
131 | HRESULT hr = S_OK; |
132 | |
133 | BEGIN_ENTRYPOINT_NOTHROW; |
134 | |
135 | AssemblyRefRec *pRecord; |
136 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
137 | |
138 | LOG((LOGMD, "RegMeta::GetAssemblyRefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
139 | mdar, ppbPublicKeyOrToken, pcbPublicKeyOrToken, szName, cchName, |
140 | pchName, pMetaData, ppbHashValue, pdwAssemblyRefFlags)); |
141 | |
142 | START_MD_PERF(); |
143 | LOCKREAD(); |
144 | |
145 | _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar)); |
146 | IfFailGo(pMiniMd->GetAssemblyRefRecord(RidFromToken(mdar), &pRecord)); |
147 | |
148 | if (ppbPublicKeyOrToken != NULL) |
149 | { |
150 | IfFailGo(pMiniMd->getPublicKeyOrTokenOfAssemblyRef(pRecord, (const BYTE **)ppbPublicKeyOrToken, pcbPublicKeyOrToken)); |
151 | } |
152 | if (pMetaData) |
153 | { |
154 | pMetaData->usMajorVersion = pMiniMd->getMajorVersionOfAssemblyRef(pRecord); |
155 | pMetaData->usMinorVersion = pMiniMd->getMinorVersionOfAssemblyRef(pRecord); |
156 | pMetaData->usBuildNumber = pMiniMd->getBuildNumberOfAssemblyRef(pRecord); |
157 | pMetaData->usRevisionNumber = pMiniMd->getRevisionNumberOfAssemblyRef(pRecord); |
158 | IfFailGo(pMiniMd->getLocaleOfAssemblyRef(pRecord, pMetaData->szLocale, |
159 | pMetaData->cbLocale, &pMetaData->cbLocale)); |
160 | pMetaData->ulProcessor = 0; |
161 | pMetaData->ulOS = 0; |
162 | } |
163 | if (ppbHashValue != NULL) |
164 | { |
165 | IfFailGo(pMiniMd->getHashValueOfAssemblyRef(pRecord, (const BYTE **)ppbHashValue, pcbHashValue)); |
166 | } |
167 | if (pdwAssemblyRefFlags) |
168 | *pdwAssemblyRefFlags = pMiniMd->getFlagsOfAssemblyRef(pRecord); |
169 | // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK |
170 | if (szName || pchName) |
171 | IfFailGo(pMiniMd->getNameOfAssemblyRef(pRecord, szName, cchName, pchName)); |
172 | ErrExit: |
173 | |
174 | STOP_MD_PERF(GetAssemblyRefProps); |
175 | END_ENTRYPOINT_NOTHROW; |
176 | |
177 | return hr; |
178 | } // RegMeta::GetAssemblyRefProps |
179 | |
180 | //******************************************************************************* |
181 | // Get the properties for the given File token. |
182 | //******************************************************************************* |
183 | STDMETHODIMP RegMeta::GetFileProps( // S_OK or error. |
184 | mdFile mdf, // [IN] The File for which to get the properties. |
185 | __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. |
186 | ULONG cchName, // [IN] Size of buffer in wide chars. |
187 | ULONG *pchName, // [OUT] Actual # of wide chars in name. |
188 | const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. |
189 | ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. |
190 | DWORD *pdwFileFlags) // [OUT] Flags. |
191 | { |
192 | HRESULT hr = S_OK; |
193 | |
194 | BEGIN_ENTRYPOINT_NOTHROW; |
195 | |
196 | FileRec *pRecord; |
197 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
198 | |
199 | LOG((LOGMD, "RegMeta::GetFileProps(%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n" , |
200 | mdf, szName, cchName, pchName, ppbHashValue, pcbHashValue, pdwFileFlags)); |
201 | |
202 | START_MD_PERF(); |
203 | LOCKREAD(); |
204 | |
205 | _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf)); |
206 | IfFailGo(pMiniMd->GetFileRecord(RidFromToken(mdf), &pRecord)); |
207 | |
208 | if (ppbHashValue != NULL) |
209 | { |
210 | IfFailGo(pMiniMd->getHashValueOfFile(pRecord, (const BYTE **)ppbHashValue, pcbHashValue)); |
211 | } |
212 | if (pdwFileFlags != NULL) |
213 | *pdwFileFlags = pMiniMd->getFlagsOfFile(pRecord); |
214 | // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK |
215 | if ((szName != NULL) || (pchName != NULL)) |
216 | { |
217 | IfFailGo(pMiniMd->getNameOfFile(pRecord, szName, cchName, pchName)); |
218 | } |
219 | |
220 | ErrExit: |
221 | STOP_MD_PERF(GetFileProps); |
222 | END_ENTRYPOINT_NOTHROW; |
223 | |
224 | return hr; |
225 | } // RegMeta::GetFileProps |
226 | |
227 | //******************************************************************************* |
228 | // Get the properties for the given ExportedType token. |
229 | //******************************************************************************* |
230 | STDMETHODIMP RegMeta::GetExportedTypeProps( // S_OK or error. |
231 | mdExportedType mdct, // [IN] The ExportedType for which to get the properties. |
232 | __out_ecount_part_opt(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. |
233 | ULONG cchName, // [IN] Size of buffer in wide chars. |
234 | ULONG *pchName, // [OUT] Actual # of wide chars in name. |
235 | mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. |
236 | mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. |
237 | DWORD *pdwExportedTypeFlags) // [OUT] Flags. |
238 | { |
239 | HRESULT hr = S_OK; // A result. |
240 | |
241 | BEGIN_ENTRYPOINT_NOTHROW; |
242 | |
243 | ExportedTypeRec *pRecord; // The exported type. |
244 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
245 | int bTruncation=0; // Was there name truncation? |
246 | |
247 | LOG((LOGMD, "RegMeta::GetExportedTypeProps(%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n" , |
248 | mdct, szName, cchName, pchName, |
249 | ptkImplementation, ptkTypeDef, pdwExportedTypeFlags)); |
250 | |
251 | START_MD_PERF(); |
252 | LOCKREAD(); |
253 | |
254 | _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct)); |
255 | IfFailGo(pMiniMd->GetExportedTypeRecord(RidFromToken(mdct), &pRecord)); |
256 | |
257 | if (szName || pchName) |
258 | { |
259 | LPCSTR szTypeNamespace; |
260 | LPCSTR szTypeName; |
261 | |
262 | IfFailGo(pMiniMd->getTypeNamespaceOfExportedType(pRecord, &szTypeNamespace)); |
263 | PREFIX_ASSUME(szTypeNamespace != NULL); |
264 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzTypeNamespace, szTypeNamespace); |
265 | IfNullGo(wzTypeNamespace); |
266 | |
267 | IfFailGo(pMiniMd->getTypeNameOfExportedType(pRecord, &szTypeName)); |
268 | _ASSERTE(*szTypeName); |
269 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzTypeName, szTypeName); |
270 | IfNullGo(wzTypeName); |
271 | |
272 | if (szName) |
273 | bTruncation = ! (ns::MakePath(szName, cchName, wzTypeNamespace, wzTypeName)); |
274 | if (pchName) |
275 | { |
276 | if (bTruncation || !szName) |
277 | *pchName = ns::GetFullLength(wzTypeNamespace, wzTypeName); |
278 | else |
279 | *pchName = (ULONG)(wcslen(szName) + 1); |
280 | } |
281 | } |
282 | if (ptkImplementation) |
283 | *ptkImplementation = pMiniMd->getImplementationOfExportedType(pRecord); |
284 | if (ptkTypeDef) |
285 | *ptkTypeDef = pMiniMd->getTypeDefIdOfExportedType(pRecord); |
286 | if (pdwExportedTypeFlags) |
287 | *pdwExportedTypeFlags = pMiniMd->getFlagsOfExportedType(pRecord); |
288 | |
289 | if (bTruncation && hr == S_OK) |
290 | { |
291 | if ((szName != NULL) && (cchName > 0)) |
292 | { // null-terminate the truncated output string |
293 | szName[cchName - 1] = W('\0'); |
294 | } |
295 | hr = CLDB_S_TRUNCATION; |
296 | } |
297 | |
298 | ErrExit: |
299 | STOP_MD_PERF(GetExportedTypeProps); |
300 | END_ENTRYPOINT_NOTHROW; |
301 | |
302 | return hr; |
303 | } // RegMeta::GetExportedTypeProps |
304 | |
305 | //******************************************************************************* |
306 | // Get the properties for the given Resource token. |
307 | //******************************************************************************* |
308 | STDMETHODIMP RegMeta::GetManifestResourceProps( // S_OK or error. |
309 | mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. |
310 | __out_ecount_part_opt(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. |
311 | ULONG cchName, // [IN] Size of buffer in wide chars. |
312 | ULONG *pchName, // [OUT] Actual # of wide chars in name. |
313 | mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. |
314 | DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. |
315 | DWORD *pdwResourceFlags) // [OUT] Flags. |
316 | { |
317 | HRESULT hr = S_OK; |
318 | |
319 | BEGIN_ENTRYPOINT_NOTHROW; |
320 | |
321 | ManifestResourceRec *pRecord; |
322 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
323 | |
324 | LOG((LOGMD, "RegMeta::GetManifestResourceProps(" |
325 | "%#08x, %#08x, %#08x, %#08x, %#08x, %#08x, %#08x)\n" , |
326 | mdmr, szName, cchName, pchName, |
327 | ptkImplementation, pdwOffset, |
328 | pdwResourceFlags)); |
329 | |
330 | START_MD_PERF(); |
331 | LOCKREAD(); |
332 | |
333 | _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr)); |
334 | IfFailGo(pMiniMd->GetManifestResourceRecord(RidFromToken(mdmr), &pRecord)); |
335 | |
336 | if (ptkImplementation) |
337 | *ptkImplementation = pMiniMd->getImplementationOfManifestResource(pRecord); |
338 | if (pdwOffset) |
339 | *pdwOffset = pMiniMd->getOffsetOfManifestResource(pRecord); |
340 | if (pdwResourceFlags) |
341 | *pdwResourceFlags = pMiniMd->getFlagsOfManifestResource(pRecord); |
342 | // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK |
343 | if (szName || pchName) |
344 | IfFailGo(pMiniMd->getNameOfManifestResource(pRecord, szName, cchName, pchName)); |
345 | ErrExit: |
346 | |
347 | STOP_MD_PERF(GetManifestResourceProps); |
348 | END_ENTRYPOINT_NOTHROW; |
349 | |
350 | return hr; |
351 | } // RegMeta::GetManifestResourceProps |
352 | |
353 | |
354 | //******************************************************************************* |
355 | // Enumerating through all of the AssemblyRefs. |
356 | //******************************************************************************* |
357 | STDMETHODIMP RegMeta::EnumAssemblyRefs( // S_OK or error |
358 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
359 | mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. |
360 | ULONG cMax, // [IN] Max AssemblyRefs to put. |
361 | ULONG *pcTokens) // [OUT] Put # put here. |
362 | { |
363 | HRESULT hr = NOERROR; |
364 | |
365 | BEGIN_ENTRYPOINT_NOTHROW; |
366 | |
367 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
368 | HENUMInternal *pEnum; |
369 | |
370 | LOG((LOGMD, "MD RegMeta::EnumAssemblyRefs(%#08x, %#08x, %#08x, %#08x)\n" , |
371 | phEnum, rAssemblyRefs, cMax, pcTokens)); |
372 | START_MD_PERF(); |
373 | |
374 | LOCKREAD(); |
375 | |
376 | if (*ppmdEnum == 0) |
377 | { |
378 | // instantiate a new ENUM. |
379 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
380 | |
381 | // create the enumerator. |
382 | IfFailGo(HENUMInternal::CreateSimpleEnum( |
383 | mdtAssemblyRef, |
384 | 1, |
385 | pMiniMd->getCountAssemblyRefs() + 1, |
386 | &pEnum) ); |
387 | |
388 | // set the output parameter. |
389 | *ppmdEnum = pEnum; |
390 | } |
391 | else |
392 | pEnum = *ppmdEnum; |
393 | |
394 | // we can only fill the minimum of what the caller asked for or what we have left. |
395 | IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rAssemblyRefs, pcTokens)); |
396 | ErrExit: |
397 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
398 | |
399 | STOP_MD_PERF(EnumAssemblyRefs); |
400 | |
401 | END_ENTRYPOINT_NOTHROW; |
402 | |
403 | return hr; |
404 | } // RegMeta::EnumAssemblyRefs |
405 | |
406 | //******************************************************************************* |
407 | // Enumerating through all of the Files. |
408 | //******************************************************************************* |
409 | STDMETHODIMP RegMeta::EnumFiles( // S_OK or error |
410 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
411 | mdFile rFiles[], // [OUT] Put Files here. |
412 | ULONG cMax, // [IN] Max Files to put. |
413 | ULONG *pcTokens) // [OUT] Put # put here. |
414 | { |
415 | HRESULT hr = NOERROR; |
416 | |
417 | BEGIN_ENTRYPOINT_NOTHROW; |
418 | |
419 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
420 | HENUMInternal *pEnum; |
421 | |
422 | LOG((LOGMD, "MD RegMeta::EnumFiles(%#08x, %#08x, %#08x, %#08x)\n" , |
423 | phEnum, rFiles, cMax, pcTokens)); |
424 | START_MD_PERF(); |
425 | LOCKREAD(); |
426 | |
427 | if (*ppmdEnum == 0) |
428 | { |
429 | // instantiate a new ENUM. |
430 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
431 | |
432 | // create the enumerator. |
433 | IfFailGo(HENUMInternal::CreateSimpleEnum( |
434 | mdtFile, |
435 | 1, |
436 | pMiniMd->getCountFiles() + 1, |
437 | &pEnum) ); |
438 | |
439 | // set the output parameter. |
440 | *ppmdEnum = pEnum; |
441 | } |
442 | else |
443 | pEnum = *ppmdEnum; |
444 | |
445 | // we can only fill the minimum of what the caller asked for or what we have left. |
446 | IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rFiles, pcTokens)); |
447 | ErrExit: |
448 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
449 | |
450 | STOP_MD_PERF(EnumFiles); |
451 | END_ENTRYPOINT_NOTHROW; |
452 | |
453 | return hr; |
454 | } // RegMeta::EnumFiles |
455 | |
456 | //******************************************************************************* |
457 | // Enumerating through all of the ExportedTypes. |
458 | //******************************************************************************* |
459 | STDMETHODIMP RegMeta::EnumExportedTypes( // S_OK or error |
460 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
461 | mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. |
462 | ULONG cMax, // [IN] Max ExportedTypes to put. |
463 | ULONG *pcTokens) // [OUT] Put # put here. |
464 | { |
465 | HRESULT hr = NOERROR; |
466 | |
467 | BEGIN_ENTRYPOINT_NOTHROW; |
468 | |
469 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
470 | HENUMInternal *pEnum; |
471 | |
472 | LOG((LOGMD, "MD RegMeta::EnumExportedTypes(%#08x, %#08x, %#08x, %#08x)\n" , |
473 | phEnum, rExportedTypes, cMax, pcTokens)); |
474 | |
475 | START_MD_PERF(); |
476 | LOCKREAD(); |
477 | |
478 | if (*ppmdEnum == 0) |
479 | { |
480 | // instantiate a new ENUM. |
481 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
482 | |
483 | if (pMiniMd->HasDelete() && |
484 | ((m_OptionValue.m_ImportOption & MDImportOptionAllExportedTypes) == 0)) |
485 | { |
486 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtExportedType, &pEnum) ); |
487 | |
488 | // add all Types to the dynamic array if name is not _Delete |
489 | for (ULONG index = 1; index <= pMiniMd->getCountExportedTypes(); index ++ ) |
490 | { |
491 | ExportedTypeRec *pRec; |
492 | IfFailGo(pMiniMd->GetExportedTypeRecord(index, &pRec)); |
493 | LPCSTR szTypeName; |
494 | IfFailGo(pMiniMd->getTypeNameOfExportedType(pRec, &szTypeName)); |
495 | if (IsDeletedName(szTypeName)) |
496 | { |
497 | continue; |
498 | } |
499 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtExportedType) ) ); |
500 | } |
501 | } |
502 | else |
503 | { |
504 | // create the enumerator. |
505 | IfFailGo(HENUMInternal::CreateSimpleEnum( |
506 | mdtExportedType, |
507 | 1, |
508 | pMiniMd->getCountExportedTypes() + 1, |
509 | &pEnum) ); |
510 | } |
511 | |
512 | // set the output parameter. |
513 | *ppmdEnum = pEnum; |
514 | } |
515 | else |
516 | pEnum = *ppmdEnum; |
517 | |
518 | // we can only fill the minimum of what the caller asked for or what we have left. |
519 | IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rExportedTypes, pcTokens)); |
520 | ErrExit: |
521 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
522 | |
523 | STOP_MD_PERF(EnumExportedTypes); |
524 | END_ENTRYPOINT_NOTHROW; |
525 | |
526 | return hr; |
527 | } // RegMeta::EnumExportedTypes |
528 | |
529 | //******************************************************************************* |
530 | // Enumerating through all of the Resources. |
531 | //******************************************************************************* |
532 | STDMETHODIMP RegMeta::EnumManifestResources( // S_OK or error |
533 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
534 | mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. |
535 | ULONG cMax, // [IN] Max Resources to put. |
536 | ULONG *pcTokens) // [OUT] Put # put here. |
537 | { |
538 | HRESULT hr = NOERROR; |
539 | |
540 | BEGIN_ENTRYPOINT_NOTHROW; |
541 | |
542 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
543 | HENUMInternal *pEnum; |
544 | |
545 | LOG((LOGMD, "MD RegMeta::EnumManifestResources(%#08x, %#08x, %#08x, %#08x)\n" , |
546 | phEnum, rManifestResources, cMax, pcTokens)); |
547 | |
548 | START_MD_PERF(); |
549 | LOCKREAD(); |
550 | |
551 | if (*ppmdEnum == 0) |
552 | { |
553 | // instantiate a new ENUM. |
554 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
555 | |
556 | // create the enumerator. |
557 | IfFailGo(HENUMInternal::CreateSimpleEnum( |
558 | mdtManifestResource, |
559 | 1, |
560 | pMiniMd->getCountManifestResources() + 1, |
561 | &pEnum) ); |
562 | |
563 | // set the output parameter. |
564 | *ppmdEnum = pEnum; |
565 | } |
566 | else |
567 | pEnum = *ppmdEnum; |
568 | |
569 | // we can only fill the minimum of what the caller asked for or what we have left. |
570 | IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rManifestResources, pcTokens)); |
571 | ErrExit: |
572 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
573 | |
574 | STOP_MD_PERF(EnumManifestResources); |
575 | END_ENTRYPOINT_NOTHROW; |
576 | |
577 | return hr; |
578 | } // RegMeta::EnumManifestResources |
579 | |
580 | //******************************************************************************* |
581 | // Get the Assembly token for the given scope.. |
582 | //******************************************************************************* |
583 | STDMETHODIMP RegMeta::GetAssemblyFromScope( // S_OK or error |
584 | mdAssembly *ptkAssembly) // [OUT] Put token here. |
585 | { |
586 | HRESULT hr = NOERROR; |
587 | CMiniMdRW *pMiniMd = NULL; |
588 | |
589 | BEGIN_ENTRYPOINT_NOTHROW; |
590 | |
591 | LOG((LOGMD, "MD RegMeta::GetAssemblyFromScope(%#08x)\n" , ptkAssembly)); |
592 | START_MD_PERF(); |
593 | LOCKREAD(); |
594 | _ASSERTE(ptkAssembly); |
595 | |
596 | pMiniMd = &(m_pStgdb->m_MiniMd); |
597 | if (pMiniMd->getCountAssemblys()) |
598 | { |
599 | *ptkAssembly = TokenFromRid(1, mdtAssembly); |
600 | } |
601 | else |
602 | { |
603 | IfFailGo( CLDB_E_RECORD_NOTFOUND ); |
604 | } |
605 | ErrExit: |
606 | STOP_MD_PERF(GetAssemblyFromScope); |
607 | END_ENTRYPOINT_NOTHROW; |
608 | |
609 | return hr; |
610 | } // RegMeta::GetAssemblyFromScope |
611 | |
612 | //******************************************************************************* |
613 | // Find the ExportedType given the name. |
614 | //******************************************************************************* |
615 | STDMETHODIMP RegMeta::FindExportedTypeByName( // S_OK or error |
616 | LPCWSTR szName, // [IN] Name of the ExportedType. |
617 | mdExportedType tkEnclosingType, // [IN] Enclosing ExportedType. |
618 | mdExportedType *ptkExportedType) // [OUT] Put the ExportedType token here. |
619 | { |
620 | HRESULT hr = S_OK; // A result. |
621 | |
622 | BEGIN_ENTRYPOINT_NOTHROW; |
623 | |
624 | CMiniMdRW *pMiniMd = NULL; |
625 | LPSTR szNameUTF8 = NULL; |
626 | |
627 | LOG((LOGMD, "MD RegMeta::FindExportedTypeByName(%S, %#08x, %#08x)\n" , |
628 | MDSTR(szName), tkEnclosingType, ptkExportedType)); |
629 | |
630 | START_MD_PERF(); |
631 | LOCKREAD(); |
632 | |
633 | |
634 | // Validate name for prefix. |
635 | if (!szName) |
636 | IfFailGo(E_INVALIDARG); |
637 | |
638 | _ASSERTE(szName && ptkExportedType); |
639 | |
640 | pMiniMd = &(m_pStgdb->m_MiniMd); |
641 | UTF8STR(szName, szNameUTF8); |
642 | LPCSTR szTypeName; |
643 | LPCSTR szTypeNamespace; |
644 | |
645 | ns::SplitInline(szNameUTF8, szTypeNamespace, szTypeName); |
646 | |
647 | IfFailGo(ImportHelper::FindExportedType(pMiniMd, |
648 | szTypeNamespace, |
649 | szTypeName, |
650 | tkEnclosingType, |
651 | ptkExportedType)); |
652 | ErrExit: |
653 | STOP_MD_PERF(FindExportedTypeByName); |
654 | END_ENTRYPOINT_NOTHROW; |
655 | |
656 | return hr; |
657 | } // RegMeta::FindExportedTypeByName |
658 | |
659 | //******************************************************************************* |
660 | // Find the ManifestResource given the name. |
661 | //******************************************************************************* |
662 | STDMETHODIMP RegMeta::FindManifestResourceByName( // S_OK or error |
663 | LPCWSTR szName, // [IN] Name of the ManifestResource. |
664 | mdManifestResource *ptkManifestResource) // [OUT] Put the ManifestResource token here. |
665 | { |
666 | HRESULT hr = S_OK; |
667 | |
668 | BEGIN_ENTRYPOINT_NOTHROW; |
669 | |
670 | LPCUTF8 szNameTmp = NULL; |
671 | CMiniMdRW *pMiniMd = NULL; |
672 | |
673 | LOG((LOGMD, "MD RegMeta::FindManifestResourceByName(%S, %#08x)\n" , |
674 | MDSTR(szName), ptkManifestResource)); |
675 | |
676 | START_MD_PERF(); |
677 | LOCKREAD(); |
678 | |
679 | |
680 | // Validate name for prefix. |
681 | if (!szName) |
682 | IfFailGo(E_INVALIDARG); |
683 | |
684 | _ASSERTE(szName && ptkManifestResource); |
685 | |
686 | ManifestResourceRec *pRecord; |
687 | ULONG cRecords; // Count of records. |
688 | LPUTF8 szUTF8Name; // UTF8 version of the name passed in. |
689 | ULONG i; |
690 | |
691 | pMiniMd = &(m_pStgdb->m_MiniMd); |
692 | *ptkManifestResource = mdManifestResourceNil; |
693 | cRecords = pMiniMd->getCountManifestResources(); |
694 | UTF8STR(szName, szUTF8Name); |
695 | |
696 | // Search for the TypeRef. |
697 | for (i = 1; i <= cRecords; i++) |
698 | { |
699 | IfFailGo(pMiniMd->GetManifestResourceRecord(i, &pRecord)); |
700 | IfFailGo(pMiniMd->getNameOfManifestResource(pRecord, &szNameTmp)); |
701 | if (! strcmp(szUTF8Name, szNameTmp)) |
702 | { |
703 | *ptkManifestResource = TokenFromRid(i, mdtManifestResource); |
704 | goto ErrExit; |
705 | } |
706 | } |
707 | IfFailGo( CLDB_E_RECORD_NOTFOUND ); |
708 | ErrExit: |
709 | |
710 | STOP_MD_PERF(FindManifestResourceByName); |
711 | END_ENTRYPOINT_NOTHROW; |
712 | |
713 | return hr; |
714 | } // RegMeta::FindManifestResourceByName |
715 | |
716 | extern HRESULT STDMETHODCALLTYPE |
717 | GetAssembliesByName(LPCWSTR szAppBase, |
718 | LPCWSTR szPrivateBin, |
719 | LPCWSTR szAssemblyName, |
720 | IUnknown *ppIUnk[], |
721 | ULONG cMax, |
722 | ULONG *pcAssemblies); |
723 | |
724 | //******************************************************************************* |
725 | // Used to find assemblies either in Fusion cache or on disk at build time. |
726 | //******************************************************************************* |
727 | STDMETHODIMP RegMeta::FindAssembliesByName( // S_OK or error |
728 | LPCWSTR szAppBase, // [IN] optional - can be NULL |
729 | LPCWSTR szPrivateBin, // [IN] optional - can be NULL |
730 | LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting |
731 | IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here |
732 | ULONG cMax, // [IN] The max number to put |
733 | ULONG *pcAssemblies) // [OUT] The number of assemblies returned. |
734 | { |
735 | #ifdef FEATURE_METADATA_IN_VM |
736 | HRESULT hr = S_OK; |
737 | |
738 | BEGIN_ENTRYPOINT_NOTHROW; |
739 | |
740 | LOG((LOGMD, "RegMeta::FindAssembliesByName(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
741 | szAppBase, szPrivateBin, szAssemblyName, ppIUnk, cMax, pcAssemblies)); |
742 | START_MD_PERF(); |
743 | |
744 | // No need to lock this function. It is going through fusion to find the matching Assemblies by name |
745 | |
746 | IfFailGo(GetAssembliesByName(szAppBase, szPrivateBin, |
747 | szAssemblyName, ppIUnk, cMax, pcAssemblies)); |
748 | |
749 | ErrExit: |
750 | STOP_MD_PERF(FindAssembliesByName); |
751 | END_ENTRYPOINT_NOTHROW; |
752 | |
753 | return hr; |
754 | #else //!FEATURE_METADATA_IN_VM |
755 | // Calls to fusion are not suported outside VM |
756 | return E_NOTIMPL; |
757 | #endif //!FEATURE_METADATA_IN_VM |
758 | } // RegMeta::FindAssembliesByName |
759 | |