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//*******************************************************************************
28STDMETHODIMP 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));
107ErrExit:
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//*******************************************************************************
119STDMETHODIMP 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));
172ErrExit:
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//*******************************************************************************
183STDMETHODIMP 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
220ErrExit:
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//*******************************************************************************
230STDMETHODIMP 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
298ErrExit:
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//*******************************************************************************
308STDMETHODIMP 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));
345ErrExit:
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//*******************************************************************************
357STDMETHODIMP 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));
396ErrExit:
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//*******************************************************************************
409STDMETHODIMP 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));
447ErrExit:
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//*******************************************************************************
459STDMETHODIMP 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));
520ErrExit:
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//*******************************************************************************
532STDMETHODIMP 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));
571ErrExit:
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//*******************************************************************************
583STDMETHODIMP 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 }
605ErrExit:
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//*******************************************************************************
615STDMETHODIMP 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));
652ErrExit:
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//*******************************************************************************
662STDMETHODIMP 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 );
708ErrExit:
709
710 STOP_MD_PERF(FindManifestResourceByName);
711 END_ENTRYPOINT_NOTHROW;
712
713 return hr;
714} // RegMeta::FindManifestResourceByName
715
716extern 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//*******************************************************************************
727STDMETHODIMP 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
749ErrExit:
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