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.
5 // asmman.cpp - manifest info handling (implementation of class AsmMan, see asmman.hpp)
11 #include "assembler.h"
12 #include "strongname.h"
16 extern WCHAR* pwzInputFiles[];
18 BinStr* BinStrToUnicode(BinStr* pSource, bool Swap)
22 pSource->appendInt8(0);
23 BinStr* tmp = new BinStr();
24 char* pb = (char*)(pSource->ptr());
25 int l=pSource->length(), L = sizeof(WCHAR)*l;
28 WCHAR* wz = (WCHAR*)(tmp->getBuff(L));
32 WszMultiByteToWideChar(g_uCodePage,0,pb,-1,wz,l);
33 tmp->remove(L-(DWORD)wcslen(wz)*sizeof(WCHAR));
36 SwapStringLength(wz, (DWORD)wcslen(wz));
44 fprintf(stderr,"\nOut of memory!\n");
48 fprintf(stderr,"\nOut of memory!\n");
54 AsmManFile* AsmMan::GetFileByName(__in __nullterminated char* szFileName)
56 AsmManFile* ret = NULL;
60 //X.szName = szFileName;
61 //ret = m_FileLst.FIND(&X);
63 for(int i=0; (ret = m_FileLst.PEEK(i))&&strcmp(ret->szName,szFileName); i++);
68 mdToken AsmMan::GetFileTokByName(__in __nullterminated char* szFileName)
70 AsmManFile* tmp = GetFileByName(szFileName);
71 return(tmp ? tmp->tkTok : mdFileNil);
74 AsmManComType* AsmMan::GetComTypeByName(__in_opt __nullterminated char* szComTypeName,
75 __in_opt __nullterminated char* szComEnclosingTypeName)
77 AsmManComType* ret = NULL;
81 //X.szName = szComTypeName;
82 //ret = m_ComTypeLst.FIND(&X);
84 for(int i=0; (ret = m_ComTypeLst.PEEK(i)) != NULL; i++)
86 if (strcmp(ret->szName, szComTypeName) == 0)
88 if (ret->szComTypeName == NULL && szComEnclosingTypeName == NULL)
93 if (ret->szComTypeName != NULL && szComEnclosingTypeName != NULL)
95 if (strcmp(ret->szComTypeName, szComEnclosingTypeName) == 0)
106 mdToken AsmMan::GetComTypeTokByName(
107 __in_opt __nullterminated char* szComTypeName,
108 __in_opt __nullterminated char* szComEnclosingTypeName)
110 AsmManComType* tmp = GetComTypeByName(szComTypeName, szComEnclosingTypeName);
111 return(tmp ? tmp->tkTok : mdExportedTypeNil);
114 AsmManAssembly* AsmMan::GetAsmRefByName(__in __nullterminated const char* szAsmRefName)
116 AsmManAssembly* ret = NULL;
120 //X.szAlias = szAsmRefName;
121 //ret = m_AsmRefLst.FIND(&X);
123 DWORD L = (DWORD)strlen(szAsmRefName);
124 for(int i=0; (ret = m_AsmRefLst.PEEK(i))&&
125 ((ret->dwAlias != L)||strcmp(ret->szAlias,szAsmRefName)); i++);
129 mdToken AsmMan::GetAsmRefTokByName(__in __nullterminated const char* szAsmRefName)
131 AsmManAssembly* tmp = GetAsmRefByName(szAsmRefName);
132 return(tmp ? tmp->tkTok : mdAssemblyRefNil);
134 AsmManAssembly* AsmMan::GetAsmRefByAsmName(__in __nullterminated const char* szAsmName)
136 AsmManAssembly* ret = NULL;
139 for(int i=0; (ret = m_AsmRefLst.PEEK(i))&&
140 (strcmp(ret->szName,szAsmName)); i++);
145 //==============================================================================================================
146 void AsmMan::SetModuleName(__inout_opt __nullterminated char* szName)
148 if(m_szScopeName == NULL) // ignore all duplicate declarations
150 if(szName && *szName)
152 ULONG L = (ULONG)strlen(szName);
153 if(L >= MAX_SCOPE_LENGTH)
155 ((Assembler*)m_pAssembler)->report->warn("Module name too long (%d chars, max.allowed: %d chars), truncated\n",L,MAX_SCOPE_LENGTH-1);
156 szName[MAX_SCOPE_LENGTH-1] = 0;
158 m_szScopeName = szName;
159 strcpy_s(((Assembler*)m_pAssembler)->m_szScopeName, MAX_SCOPE_LENGTH, szName);
163 //==============================================================================================================
165 void AsmMan::AddFile(__in __nullterminated char* szName, DWORD dwAttr, BinStr* pHashBlob)
167 AsmManFile* tmp = GetFileByName(szName);
168 Assembler* pAsm = (Assembler*)m_pAssembler;
171 tmp = new AsmManFile;
174 pAsm->report->error("\nOut of memory!\n");
177 memset(tmp,0,sizeof(AsmManFile));
178 if((dwAttr & 0x80000000)!=0) pAsm->m_fEntryPointPresent = TRUE;
179 tmp->szName = szName;
180 tmp->dwAttr = dwAttr;
181 tmp->pHash = pHashBlob;
184 tmp->tkTok = TokenFromRid(m_FileLst.COUNT(),mdtFile);
186 pAsm->m_tkCurrentCVOwner = 0;
187 if(tmp) pAsm->m_pCustomDescrList = &(tmp->m_CustomDescrList);
189 //==============================================================================================================
191 void AsmMan::EmitFiles()
194 Assembler* pAsm = (Assembler*)m_pAssembler;
198 for(i = 0; (tmp=m_FileLst.PEEK(i)) != NULL; i++)
200 BOOL fEntry = ((tmp->dwAttr & 0x80000000)!=0);
207 if(!tmp->m_fNew) continue;
210 WszMultiByteToWideChar(g_uCodePage,0,tmp->szName,-1,wzUniBuf,dwUniBuf);
211 if(tmp->pHash==NULL) // if hash not explicitly specified
213 if(m_pAssembly // and assembly is defined
214 && m_pAssembly->ulHashAlgorithm) // and hash algorithm is defined...
215 { // then try to compute it
224 pHash = tmp->pHash->ptr();
225 cbHash = tmp->pHash->length();
228 hr = m_pAsmEmitter->DefineFile(wzUniBuf,
231 tmp->dwAttr & 0x7FFFFFFF,
233 _ASSERTE(tk == tmp->tkTok);
234 if(FAILED(hr)) report->error("Failed to define file '%s': 0x%08X\n",tmp->szName,hr);
239 if (FAILED(pAsm->m_pCeeFileGen->SetEntryPoint(pAsm->m_pCeeFile, tmp->tkTok)))
241 pAsm->report->error("Failed to set external entry point for file '%s'\n",tmp->szName);
244 pAsm->EmitCustomAttributes(tmp->tkTok, &(tmp->m_CustomDescrList));
246 } //end for(i = 0; tmp=m_FileLst.PEEK(i); i++)
249 void AsmMan::StartAssembly(__in __nullterminated char* szName, __in_opt __nullterminated char* szAlias, DWORD dwAttr, BOOL isRef)
251 if(!isRef && (0==strcmp(szName, "mscorlib"))) ((Assembler*)m_pAssembler)->m_fIsMscorlib = TRUE;
252 if(!isRef && (m_pAssembly != NULL))
254 if(strcmp(szName, m_pAssembly->szName))
255 report->error("Multiple assembly declarations\n");
256 // if name is the same, just ignore it
261 if((m_pCurAsmRef = new AsmManAssembly))
263 memset(m_pCurAsmRef,0,sizeof(AsmManAssembly));
264 m_pCurAsmRef->usVerMajor = (USHORT)0xFFFF;
265 m_pCurAsmRef->usVerMinor = (USHORT)0xFFFF;
266 m_pCurAsmRef->usBuild = (USHORT)0xFFFF;
267 m_pCurAsmRef->usRevision = (USHORT)0xFFFF;
268 m_pCurAsmRef->szName = szName;
269 m_pCurAsmRef->szAlias = szAlias ? szAlias : szName;
270 m_pCurAsmRef->dwAlias = (DWORD)strlen(m_pCurAsmRef->szAlias);
271 m_pCurAsmRef->dwAttr = dwAttr;
272 m_pCurAsmRef->isRef = isRef;
273 m_pCurAsmRef->isAutodetect = FALSE;
274 m_pCurAsmRef->m_fNew = TRUE;
275 if(!isRef) m_pAssembly = m_pCurAsmRef;
278 report->error("Failed to allocate AsmManAssembly structure\n");
280 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
281 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
282 ((Assembler*)m_pAssembler)->m_pCustomDescrList = m_pCurAsmRef ? &(m_pCurAsmRef->m_CustomDescrList) : NULL;
285 // copied from asmparse.y
286 static void corEmitInt(BinStr* buff, unsigned data)
288 unsigned cnt = CorSigCompressData(data, buff->getBuff(5));
289 buff->remove(5 - cnt);
292 void AsmMan::EmitDebuggableAttribute(mdToken tkOwner)
295 Assembler* pAsm = (Assembler*)m_pAssembler;
296 mdToken tkTypeSpec, tkMscorlib, tkParamType;
297 BinStr *pbsSig = new BinStr();
298 BinStr* bsBytes = new BinStr();;
300 tkMscorlib = pAsm->m_fIsMscorlib ? 1 : pAsm->GetBaseAsmRef();
301 tkTypeSpec = pAsm->ResolveClassRef(tkMscorlib,"System.Diagnostics.DebuggableAttribute",NULL);
303 EmitAssemblyRefs(); // just in case we gained 'mscorlib' AsmRef in GetAsmRef above
305 BOOL fOldStyle = FALSE;
307 fOldStyle = (m_pAssembly->usVerMajor == 1);
310 AsmManAssembly *pAssembly = GetAsmRefByName("mscorlib");
311 if(pAssembly != NULL)
313 fOldStyle = (pAssembly->usVerMajor == 1);
317 bsBytes->appendInt8(1);
318 bsBytes->appendInt8(0);
321 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
322 corEmitInt(pbsSig,2);
323 pbsSig->appendInt8(ELEMENT_TYPE_VOID);
324 pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN);
325 pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN);
327 //New to old: 0x101->(true,true),0x03->(true,false),0x103->(true,true)+warning
328 bsBytes->appendInt8(1);
329 bsBytes->appendInt8((pAsm->m_dwIncludeDebugInfo==0x03 ? 0 : 1));
330 if(pAsm->m_dwIncludeDebugInfo == 0x103)
332 report->warn("\nOption /DEBUG=IMPL is invalid for legacy DebuggableAttribute, /DEBUG used.\n" );
341 "System.Diagnostics.DebuggableAttribute",
346 tkParamType = pAsm->ResolveClassRef(tkMscorlib,buffer, NULL);
348 bsSigArg.appendInt8(ELEMENT_TYPE_VALUETYPE);
350 unsigned cnt = CorSigCompressToken(tkParamType, bsSigArg.getBuff(5));
351 bsSigArg.remove(5 - cnt);
353 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
354 corEmitInt(pbsSig,1);
355 pbsSig->appendInt8(ELEMENT_TYPE_VOID);
356 pbsSig->append(&bsSigArg);
358 bsBytes->appendInt32(pAsm->m_dwIncludeDebugInfo);
360 bsBytes->appendInt8(0);
361 bsBytes->appendInt8(0);
363 szName = new char[16];
364 strcpy_s(szName,16,".ctor");
365 tkCA = pAsm->MakeMemberRef(tkTypeSpec,szName,pbsSig);
366 pAsm->DefineCV(new CustomDescr(tkOwner,tkCA,bsBytes));
369 void AsmMan::EndAssembly()
373 if(m_pCurAsmRef->isRef)
374 { // list the assembly ref
375 if(GetAsmRefByName(m_pCurAsmRef->szAlias))
377 //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName);
382 m_AsmRefLst.PUSH(m_pCurAsmRef);
383 m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef);
388 m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly);
390 // Determine the strong name public key. This may have been set
391 // via a directive in the source or from the command line (which
392 // overrides the directive). From the command line we may have
393 // been provided with a file or the name of a CAPI key
394 // container. Either may contain a public key or a full key
396 if (((Assembler*)m_pAssembler)->m_wzKeySourceName)
398 // Key file versus container is determined by the first
399 // character of the source ('@' for container).
400 if (*(((Assembler*)m_pAssembler)->m_wzKeySourceName) == L'@')
402 report->error("Error: ilasm on CoreCLR does not support getting public key from container.\n");
408 // Read public key or key pair from file.
409 HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName,
414 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
416 if(hFile == INVALID_HANDLE_VALUE)
419 report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
424 // Determine file size and allocate an appropriate buffer.
425 m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL);
426 if (m_sStrongName.m_cbPublicKey == 0xffffffff) {
427 report->error("File size too large\n");
433 m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey];
434 if (m_sStrongName.m_pbPublicKey == NULL) {
435 report->error("Failed to allocate key buffer\n");
440 m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedByNew;
442 // Read the file into the buffer.
444 if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) {
446 report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
454 // Guess whether we're full or delay signing based on
455 // whether the blob passed to us looks like a public
456 // key. (I.e. we may just have copied a full key pair
457 // into the public key buffer).
458 if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) &&
459 (offsetof(PublicKeyBlob, PublicKey) +
460 ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey)
461 m_sStrongName.m_fFullSign = FALSE;
463 m_sStrongName.m_fFullSign = TRUE;
465 // If we really have a key pair, we'll move it into a
466 // key container so the signing code gets the key pair
467 // from a consistent place.
468 if (m_sStrongName.m_fFullSign)
470 report->error("Error: ilasm on CoreCLR does not support full sign.\n");
478 if (m_pAssembly->pPublicKey)
480 m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr();
481 m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length();
485 m_sStrongName.m_pbPublicKey = NULL;
486 m_sStrongName.m_cbPublicKey = 0;
489 m_sStrongName.m_wzKeyContainer = NULL;
490 m_sStrongName.m_fFullSign = FALSE;
491 m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated;
496 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
499 void FillAssemblyMetadata(AsmManAssembly *pAsm, ASSEMBLYMETADATA *pmd)
501 pmd->usMajorVersion = pAsm->usVerMajor;
502 pmd->usMinorVersion = pAsm->usVerMinor;
503 pmd->usBuildNumber = pAsm->usBuild;
504 pmd->usRevisionNumber = pAsm->usRevision;
505 if(pmd->usMajorVersion == 0xFFFF) pmd->usMajorVersion = 0;
506 if(pmd->usMinorVersion == 0xFFFF) pmd->usMinorVersion = 0;
507 if(pmd->usBuildNumber == 0xFFFF) pmd->usBuildNumber = 0;
508 if(pmd->usRevisionNumber == 0xFFFF) pmd->usRevisionNumber = 0;
510 if(pAsm->pLocale != NULL)
512 pmd->szLocale = (LPWSTR)(pAsm->pLocale->ptr());
513 pmd->cbLocale = pAsm->pLocale->length()/((ULONG)sizeof(WCHAR));
517 pmd->szLocale = NULL;
521 pmd->rProcessor = NULL;
523 pmd->ulProcessor = 0;
527 void AsmMan::EmitAssemblyRefs()
534 for(i=0; (m_pCurAsmRef=m_AsmRefLst.PEEK(i)) != NULL; i++)
536 if(!m_pCurAsmRef->m_fNew) continue;
537 m_pCurAsmRef->m_fNew = FALSE;
540 FillAssemblyMetadata(m_pCurAsmRef,&md);
542 // See if we've got a full public key or the tokenized version (or neither).
543 BYTE *pbPublicKeyOrToken = NULL;
544 DWORD cbPublicKeyOrToken = 0;
545 DWORD dwFlags = m_pCurAsmRef->dwAttr;
546 if (m_pCurAsmRef->pPublicKeyToken)
548 pbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->ptr();
549 cbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->length();
552 else if (m_pCurAsmRef->pPublicKey)
554 pbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->ptr();
555 cbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->length();
556 dwFlags |= afPublicKey;
558 // Convert name to Unicode
559 WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf);
560 hr = m_pAsmEmitter->DefineAssemblyRef( // S_OK or error.
561 pbPublicKeyOrToken, // [IN] Public key or token of the assembly.
562 cbPublicKeyOrToken, // [IN] Count of bytes in the key or token.
563 (LPCWSTR)wzUniBuf, // [IN] Name of the assembly being referenced.
564 (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData.
565 (m_pCurAsmRef->pHashBlob ? (const void*)(m_pCurAsmRef->pHashBlob->ptr()) : NULL), // [IN] Hash Blob.
566 (m_pCurAsmRef->pHashBlob ? m_pCurAsmRef->pHashBlob->length() : 0), // [IN] Count of bytes in the Hash Blob.
567 dwFlags, // [IN] Flags.
568 (mdAssemblyRef*)&tk); // [OUT] Returned AssemblyRef token.
569 if(m_pCurAsmRef->tkTok != tk)
571 report->error("AsmRef'%S' tok %8.8X -> %8.8X\n",wzUniBuf,m_pCurAsmRef->tkTok,tk);
573 if(FAILED(hr)) report->error("Failed to define assembly ref '%s': 0x%08X\n",m_pCurAsmRef->szName,hr);
576 ((Assembler*)m_pAssembler)->EmitCustomAttributes(m_pCurAsmRef->tkTok, &(m_pCurAsmRef->m_CustomDescrList));
578 } // end for(i=0; m_pCurAsmRef=m_AsmRefLst.PEEK(i); i++)
581 void AsmMan::EmitAssembly()
587 if(m_pAssembly == NULL) return;
588 if(!m_pAssembly->m_fNew) return;
589 m_pAssembly->m_fNew = FALSE;
591 FillAssemblyMetadata(m_pAssembly, &md);
593 // Convert name to Unicode
594 WszMultiByteToWideChar(g_uCodePage,0,m_pAssembly->szName,-1,wzUniBuf,dwUniBuf);
596 hr = m_pAsmEmitter->DefineAssembly( // S_OK or error.
597 (const void*)(m_sStrongName.m_pbPublicKey), // [IN] Public key of the assembly.
598 m_sStrongName.m_cbPublicKey, // [IN] Count of bytes in the public key.
599 m_pAssembly->ulHashAlgorithm, // [IN] Hash algorithm used to hash the files.
600 (LPCWSTR)wzUniBuf, // [IN] Name of the assembly.
601 (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData.
602 m_pAssembly->dwAttr, // [IN] Flags.
603 (mdAssembly*)&(m_pAssembly->tkTok)); // [OUT] Returned Assembly token.
605 if(FAILED(hr)) report->error("Failed to define assembly '%s': 0x%08X\n",m_pAssembly->szName,hr);
608 Assembler* pAsm = ((Assembler*)m_pAssembler);
609 pAsm->EmitSecurityInfo(m_pAssembly->tkTok,
610 m_pAssembly->m_pPermissions,
611 m_pAssembly->m_pPermissionSets);
612 if(pAsm->m_dwIncludeDebugInfo)
614 EmitDebuggableAttribute(m_pAssembly->tkTok);
616 pAsm->EmitCustomAttributes(m_pAssembly->tkTok, &(m_pAssembly->m_CustomDescrList));
620 void AsmMan::SetAssemblyPublicKey(BinStr* pPublicKey)
624 m_pCurAsmRef->pPublicKey = pPublicKey;
628 void AsmMan::SetAssemblyPublicKeyToken(BinStr* pPublicKeyToken)
632 m_pCurAsmRef->pPublicKeyToken = pPublicKeyToken;
636 void AsmMan::SetAssemblyHashAlg(ULONG ulAlgID)
640 m_pCurAsmRef->ulHashAlgorithm = ulAlgID;
644 void AsmMan::SetAssemblyVer(USHORT usMajor, USHORT usMinor, USHORT usBuild, USHORT usRevision)
648 m_pCurAsmRef->usVerMajor = usMajor;
649 m_pCurAsmRef->usVerMinor = usMinor;
650 m_pCurAsmRef->usBuild = usBuild;
651 m_pCurAsmRef->usRevision = usRevision;
655 void AsmMan::SetAssemblyLocale(BinStr* pLocale, BOOL bConvertToUnicode)
659 m_pCurAsmRef->pLocale = bConvertToUnicode ? ::BinStrToUnicode(pLocale) : pLocale;
663 void AsmMan::SetAssemblyHashBlob(BinStr* pHashBlob)
667 m_pCurAsmRef->pHashBlob = pHashBlob;
671 void AsmMan::SetAssemblyAutodetect()
675 m_pCurAsmRef->isAutodetect = TRUE;
679 void AsmMan::StartComType(__in __nullterminated char* szName, DWORD dwAttr)
681 if((m_pCurComType = new AsmManComType))
683 memset(m_pCurComType,0,sizeof(AsmManComType));
684 m_pCurComType->szName = szName;
685 m_pCurComType->dwAttr = dwAttr;
686 m_pCurComType->m_fNew = TRUE;
687 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
688 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
689 ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurComType->m_CustomDescrList);
692 report->error("Failed to allocate AsmManComType structure\n");
695 void AsmMan::EndComType()
701 Class* pClass =((Assembler*)m_pAssembler)->m_pCurClass;
704 m_pCurComType->tkClass = pClass->m_cl;
705 if(pClass->m_pEncloser)
707 mdTypeDef tkEncloser = pClass->m_pEncloser->m_cl;
709 for(unsigned i=0; (pCT=m_ComTypeLst.PEEK(i)); i++)
711 if(pCT->tkClass == tkEncloser)
713 m_pCurComType->szComTypeName = pCT->szName;
721 if (IsTdNested(m_pCurComType->dwAttr) && GetComTypeByName(m_pCurComType->szName, m_pCurComType->szComTypeName) != NULL)
723 report->error("Invalid TypeDefID of exported type\n");
724 delete m_pCurComType;
728 m_ComTypeLst.PUSH(m_pCurComType);
731 m_pCurComType = NULL;
732 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
733 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
737 void AsmMan::SetComTypeFile(__in __nullterminated char* szFileName)
741 m_pCurComType->szFileName = szFileName;
745 void AsmMan::SetComTypeAsmRef(__in __nullterminated char* szAsmRefName)
749 m_pCurComType->szAsmRefName = szAsmRefName;
753 void AsmMan::SetComTypeComType(__in __nullterminated char* szComTypeName)
757 m_pCurComType->szComTypeName = szComTypeName;
760 BOOL AsmMan::SetComTypeImplementationTok(mdToken tk)
764 switch(TypeFromToken(tk))
767 case mdtExportedType:
769 m_pCurComType->tkImpl = tk;
775 BOOL AsmMan::SetComTypeClassTok(mdToken tkClass)
777 if((m_pCurComType)&&(TypeFromToken(tkClass)==mdtTypeDef))
779 m_pCurComType->tkClass = tkClass;
785 void AsmMan::StartManifestRes(__in __nullterminated char* szName, __in __nullterminated char* szAlias, DWORD dwAttr)
787 if((m_pCurManRes = new AsmManRes))
789 m_pCurManRes->szName = szName;
790 m_pCurManRes->szAlias = szAlias;
791 m_pCurManRes->dwAttr = dwAttr;
792 m_pCurManRes->m_fNew = TRUE;
793 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
794 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
795 ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurManRes->m_CustomDescrList);
798 report->error("Failed to allocate AsmManRes structure\n");
801 void AsmMan::EndManifestRes()
805 m_ManResLst.PUSH(m_pCurManRes);
807 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
808 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
813 void AsmMan::SetManifestResFile(__in __nullterminated char* szFileName, ULONG ulOffset)
817 m_pCurManRes->szFileName = szFileName;
818 m_pCurManRes->ulOffset = ulOffset;
822 void AsmMan::SetManifestResAsmRef(__in __nullterminated char* szAsmRefName)
826 m_pCurManRes->szAsmRefName = szAsmRefName;
830 HRESULT AsmMan::EmitManifest()
832 //AsmManAssembly* pAsmRef;
833 AsmManComType* pComType;
839 if(m_pAsmEmitter==NULL)
840 hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &m_pAsmEmitter);
847 if((((Assembler*)m_pAssembler)->m_dwIncludeDebugInfo != 0) && (m_pAssembly == NULL)
848 && !(((Assembler*)m_pAssembler)->m_fENCMode))
850 mdToken tkOwner, tkMscorlib;
851 tkMscorlib = ((Assembler*)m_pAssembler)->GetAsmRef("mscorlib");
852 tkOwner = ((Assembler*)m_pAssembler)->ResolveClassRef(tkMscorlib,
853 "System.Runtime.CompilerServices.AssemblyAttributesGoHere",
855 EmitDebuggableAttribute(tkOwner);
858 // Emit all com types
860 for(i = 0; (pComType = m_ComTypeLst.PEEK(i)); i++)
862 if(!pComType->m_fNew) continue;
863 pComType->m_fNew = FALSE;
865 WszMultiByteToWideChar(g_uCodePage,0,pComType->szName,-1,wzUniBuf,dwUniBuf);
866 mdToken tkImplementation = mdTokenNil;
867 if(pComType->tkImpl) tkImplementation = pComType->tkImpl;
868 else if(pComType->szFileName)
870 tkImplementation = GetFileTokByName(pComType->szFileName);
871 if(tkImplementation==mdFileNil)
873 report->error("Undefined File '%s' in ExportedType '%s'\n",pComType->szFileName,pComType->szName);
874 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
877 else if(pComType->szAsmRefName)
879 tkImplementation = GetAsmRefTokByName(pComType->szAsmRefName);
880 if(RidFromToken(tkImplementation)==0)
882 report->error("Undefined AssemblyRef '%s' in ExportedType '%s'\n",pComType->szAsmRefName,pComType->szName);
883 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
886 else if(pComType->szComTypeName)
888 char* szLastName = strrchr(pComType->szComTypeName, NESTING_SEP);
894 tkImplementation = GetComTypeTokByName(szLastName, pComType->szComTypeName);
895 *(szLastName-1) = NESTING_SEP; // not really necessary
900 tkImplementation = GetComTypeTokByName(pComType->szComTypeName);
903 if(tkImplementation==mdExportedTypeNil)
905 report->error("Undefined ExportedType '%s' in ExportedType '%s'\n",pComType->szComTypeName,pComType->szName);
906 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
911 report->warn("Undefined implementation in ExportedType '%s' -- ExportType not emitted\n",pComType->szName);
912 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
914 hr = m_pAsmEmitter->DefineExportedType( // S_OK or error.
915 (LPCWSTR)wzUniBuf, // [IN] Name of the Com Type.
916 tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the ComType.
917 (mdTypeDef)pComType->tkClass, // [IN] TypeDef token within the file.
918 pComType->dwAttr, // [IN] Flags.
919 (mdExportedType*)&(pComType->tkTok)); // [OUT] Returned ComType token.
920 if(FAILED(hr)) report->error("Failed to define ExportedType '%s': 0x%08X\n",pComType->szName,hr);
923 ((Assembler*)m_pAssembler)->EmitCustomAttributes(pComType->tkTok, &(pComType->m_CustomDescrList));
927 // Emit all manifest resources
928 m_dwMResSizeTotal = 0;
930 for(i = 0; (pManRes = m_ManResLst.PEEK(i)); i++)
933 mdToken tkImplementation = mdFileNil;
935 if(!pManRes->m_fNew) continue;
936 pManRes->m_fNew = FALSE;
938 WszMultiByteToWideChar(g_uCodePage,0,pManRes->szAlias,-1,wzUniBuf,dwUniBuf);
939 if(pManRes->szAsmRefName)
941 tkImplementation = GetAsmRefTokByName(pManRes->szAsmRefName);
942 if(RidFromToken(tkImplementation)==0)
944 report->error("Undefined AssemblyRef '%s' in MResource '%s'\n",pManRes->szAsmRefName,pManRes->szName);
948 else if(pManRes->szFileName)
950 tkImplementation = GetFileTokByName(pManRes->szFileName);
951 if(RidFromToken(tkImplementation)==0)
953 report->error("Undefined File '%s' in MResource '%s'\n",pManRes->szFileName,pManRes->szName);
957 else // embedded mgd.resource, go after the file
959 HANDLE hFile = INVALID_HANDLE_VALUE;
961 WCHAR wzFileName[2048];
964 pManRes->ulOffset = m_dwMResSizeTotal;
965 for(j=0; (hFile == INVALID_HANDLE_VALUE)&&(pwzInputFiles[j] != NULL); j++)
967 wcscpy_s(wzFileName,2048,pwzInputFiles[j]);
968 pwz = wcsrchr(wzFileName,'\\');
969 if(pwz == NULL) pwz = wcsrchr(wzFileName,':');
970 if(pwz == NULL) pwz = &wzFileName[0];
972 wcscpy_s(pwz,2048-(pwz-wzFileName),wzUniBuf);
973 hFile = WszCreateFile(wzFileName, GENERIC_READ, FILE_SHARE_READ,
974 0, OPEN_EXISTING, 0, 0);
976 if (hFile == INVALID_HANDLE_VALUE)
978 report->error("Failed to open managed resource file '%s'\n",pManRes->szAlias);
983 if (m_dwMResNum >= MAX_MANIFEST_RESOURCES)
985 report->error("Too many resources (implementation limit: %d); skipping file '%s'\n",MAX_MANIFEST_RESOURCES,pManRes->szAlias);
990 m_dwMResSize[m_dwMResNum] = SafeGetFileSize(hFile,NULL);
991 if(m_dwMResSize[m_dwMResNum] == 0xFFFFFFFF)
993 report->error("Failed to get size of managed resource file '%s'\n",pManRes->szAlias);
998 m_dwMResSizeTotal += m_dwMResSize[m_dwMResNum]+sizeof(DWORD);
999 m_wzMResName[m_dwMResNum] = new WCHAR[wcslen(wzFileName)+1];
1000 wcscpy_s(m_wzMResName[m_dwMResNum],wcslen(wzFileName)+1,wzFileName);
1001 m_fMResNew[m_dwMResNum] = TRUE;
1008 if(fOK || ((Assembler*)m_pAssembler)->OnErrGo)
1010 WszMultiByteToWideChar(g_uCodePage,0,pManRes->szName,-1,wzUniBuf,dwUniBuf);
1011 hr = m_pAsmEmitter->DefineManifestResource( // S_OK or error.
1012 (LPCWSTR)wzUniBuf, // [IN] Name of the resource.
1013 tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource.
1014 pManRes->ulOffset, // [IN] Offset to the beginning of the resource within the file.
1015 pManRes->dwAttr, // [IN] Flags.
1016 (mdManifestResource*)&(pManRes->tkTok)); // [OUT] Returned ManifestResource token.
1018 report->error("Failed to define manifest resource '%s': 0x%08X\n",pManRes->szName,hr);
1023 m_pAsmEmitter->Release();
1024 m_pAsmEmitter = NULL;
1027 report->error("Failed to obtain IMetaDataAssemblyEmit interface: 0x%08X\n",hr);