diff options
Diffstat (limited to 'src/ilasm/asmman.cpp')
-rw-r--r-- | src/ilasm/asmman.cpp | 1283 |
1 files changed, 1283 insertions, 0 deletions
diff --git a/src/ilasm/asmman.cpp b/src/ilasm/asmman.cpp new file mode 100644 index 0000000000..dba481faf2 --- /dev/null +++ b/src/ilasm/asmman.cpp @@ -0,0 +1,1283 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// asmman.cpp - manifest info handling (implementation of class AsmMan, see asmman.hpp) +// + +// +#include "ilasmpch.h" + +#include "assembler.h" +#include "strongname.h" +#ifndef FEATURE_CORECLR +#include "LegacyActivationShim.h" +#endif +#include <limits.h> +#include <fusion.h> + +extern WCHAR* pwzInputFiles[]; + +BinStr* BinStrToUnicode(BinStr* pSource, bool Swap) +{ + if(pSource) + { + pSource->appendInt8(0); + BinStr* tmp = new BinStr(); + char* pb = (char*)(pSource->ptr()); + int l=pSource->length(), L = sizeof(WCHAR)*l; + if(tmp) + { + WCHAR* wz = (WCHAR*)(tmp->getBuff(L)); + if(wz) + { + memset(wz,0,L); + WszMultiByteToWideChar(g_uCodePage,0,pb,-1,wz,l); + tmp->remove(L-(DWORD)wcslen(wz)*sizeof(WCHAR)); +#if BIGENDIAN + if (Swap) + SwapStringLength(wz, (DWORD)wcslen(wz)); +#endif + delete pSource; + } + else + { + delete tmp; + tmp = NULL; + fprintf(stderr,"\nOut of memory!\n"); + } + } + else + fprintf(stderr,"\nOut of memory!\n"); + return tmp; + } + return NULL; +} + +AsmManFile* AsmMan::GetFileByName(__in __nullterminated char* szFileName) +{ + AsmManFile* ret = NULL; + if(szFileName) + { + //AsmManFile X; + //X.szName = szFileName; + //ret = m_FileLst.FIND(&X); + //X.szName = NULL; + for(int i=0; (ret = m_FileLst.PEEK(i))&&strcmp(ret->szName,szFileName); i++); + } + return ret; +} + +mdToken AsmMan::GetFileTokByName(__in __nullterminated char* szFileName) +{ + AsmManFile* tmp = GetFileByName(szFileName); + return(tmp ? tmp->tkTok : mdFileNil); +} + +AsmManComType* AsmMan::GetComTypeByName(__in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName) +{ + AsmManComType* ret = NULL; + if(szComTypeName) + { + //AsmManComType X; + //X.szName = szComTypeName; + //ret = m_ComTypeLst.FIND(&X); + //X.szName = NULL; + for(int i=0; (ret = m_ComTypeLst.PEEK(i)) != NULL; i++) + { + if (strcmp(ret->szName, szComTypeName) == 0) + { + if (ret->szComTypeName == NULL && szComEnclosingTypeName == NULL) + { + break; + } + + if (ret->szComTypeName != NULL && szComEnclosingTypeName != NULL) + { + if (strcmp(ret->szComTypeName, szComEnclosingTypeName) == 0) + { + break; + } + } + } + } + } + return ret; +} + +mdToken AsmMan::GetComTypeTokByName( + __in_opt __nullterminated char* szComTypeName, + __in_opt __nullterminated char* szComEnclosingTypeName) +{ + AsmManComType* tmp = GetComTypeByName(szComTypeName, szComEnclosingTypeName); + return(tmp ? tmp->tkTok : mdExportedTypeNil); +} + +AsmManAssembly* AsmMan::GetAsmRefByName(__in __nullterminated const char* szAsmRefName) +{ + AsmManAssembly* ret = NULL; + if(szAsmRefName) + { + //AsmManAssembly X; + //X.szAlias = szAsmRefName; + //ret = m_AsmRefLst.FIND(&X); + //X.szAlias = NULL; + DWORD L = (DWORD)strlen(szAsmRefName); + for(int i=0; (ret = m_AsmRefLst.PEEK(i))&& + ((ret->dwAlias != L)||strcmp(ret->szAlias,szAsmRefName)); i++); + } + return ret; +} +mdToken AsmMan::GetAsmRefTokByName(__in __nullterminated const char* szAsmRefName) +{ + AsmManAssembly* tmp = GetAsmRefByName(szAsmRefName); + return(tmp ? tmp->tkTok : mdAssemblyRefNil); +} +//============================================================================================================== +void AsmMan::SetModuleName(__inout_opt __nullterminated char* szName) +{ + if(m_szScopeName == NULL) // ignore all duplicate declarations + { + if(szName && *szName) + { + ULONG L = (ULONG)strlen(szName); + if(L >= MAX_SCOPE_LENGTH) + { + ((Assembler*)m_pAssembler)->report->warn("Module name too long (%d chars, max.allowed: %d chars), truncated\n",L,MAX_SCOPE_LENGTH-1); + szName[MAX_SCOPE_LENGTH-1] = 0; + } + m_szScopeName = szName; + strcpy_s(((Assembler*)m_pAssembler)->m_szScopeName, MAX_SCOPE_LENGTH, szName); + } + } +} +//============================================================================================================== +// Borrowed from VM\assembly.cpp +#ifndef FEATURE_CORECLR +HRESULT GetHash(__in LPWSTR moduleName, + ALG_ID iHashAlg, + BYTE** pbCurrentValue, // should be NULL + DWORD *cbCurrentValue) +{ + HRESULT hr = E_FAIL; + HCRYPTPROV hProv = 0; + HCRYPTHASH hHash = 0; + DWORD dwCount = sizeof(DWORD); + PBYTE pbBuffer = NULL; + DWORD dwBufferLen; + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMapFile = NULL; + + hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, + 0, OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) return E_FAIL; + + dwBufferLen = SafeGetFileSize(hFile,NULL); + if (dwBufferLen == 0xffffffff) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMapFile == NULL) goto exit; + + pbBuffer = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + if (pbBuffer == NULL) goto exit; + + // No need to late bind this stuff, all these crypto API entry points happen + // to live in ADVAPI32. + + if ((!WszCryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) || + (!CryptCreateHash(hProv, iHashAlg, 0, 0, &hHash)) || + (!CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) || + (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *) cbCurrentValue, + &dwCount, 0))) { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto exit; + } + + *pbCurrentValue = new BYTE[*cbCurrentValue]; + if (!(*pbCurrentValue)) { + hr = E_OUTOFMEMORY; + goto exit; + } + + if(!CryptGetHashParam(hHash, HP_HASHVAL, *pbCurrentValue, cbCurrentValue, 0)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + delete[] *pbCurrentValue; + *pbCurrentValue = 0; + goto exit; + } + + hr = S_OK; + + exit: + if (pbBuffer) UnmapViewOfFile(pbBuffer); + if (hMapFile) CloseHandle(hMapFile); + CloseHandle(hFile); + if (hHash) + CryptDestroyHash(hHash); + if (hProv) + CryptReleaseContext(hProv, 0); + + return hr; +} +#endif // !FEATURE_CORECLR +//============================================================================================================== + +void AsmMan::AddFile(__in __nullterminated char* szName, DWORD dwAttr, BinStr* pHashBlob) +{ + AsmManFile* tmp = GetFileByName(szName); + Assembler* pAsm = (Assembler*)m_pAssembler; + if(tmp==NULL) + { + tmp = new AsmManFile; + if(tmp==NULL) + { + pAsm->report->error("\nOut of memory!\n"); + return; + } + memset(tmp,0,sizeof(AsmManFile)); + if((dwAttr & 0x80000000)!=0) pAsm->m_fEntryPointPresent = TRUE; + tmp->szName = szName; + tmp->dwAttr = dwAttr; + tmp->pHash = pHashBlob; + tmp->m_fNew = TRUE; + m_FileLst.PUSH(tmp); + tmp->tkTok = TokenFromRid(m_FileLst.COUNT(),mdtFile); + } + pAsm->m_tkCurrentCVOwner = 0; + if(tmp) pAsm->m_pCustomDescrList = &(tmp->m_CustomDescrList); +} +//============================================================================================================== + +void AsmMan::EmitFiles() +{ + AsmManFile* tmp; + Assembler* pAsm = (Assembler*)m_pAssembler; + int i; + HRESULT hr = S_OK; + mdToken tk; + for(i = 0; (tmp=m_FileLst.PEEK(i)) != NULL; i++) + { + BOOL fEntry = ((tmp->dwAttr & 0x80000000)!=0); + + wzUniBuf[0] = 0; + + BYTE* pHash=NULL; + DWORD cbHash= 0; + + if(!tmp->m_fNew) continue; + tmp->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,tmp->szName,-1,wzUniBuf,dwUniBuf); + if(tmp->pHash==NULL) // if hash not explicitly specified + { + if(m_pAssembly // and assembly is defined + && m_pAssembly->ulHashAlgorithm) // and hash algorithm is defined... + { // then try to compute it +#ifndef FEATURE_CORECLR + if(SUCCEEDED(GetHash(wzUniBuf,(ALG_ID)(m_pAssembly->ulHashAlgorithm),&pHash,&cbHash))) + { + tmp->pHash = new BinStr(pHash,cbHash); + } + else +#endif // !FEATURE_CORECLR + { + pHash = NULL; + cbHash = 0; + } + } + } + else + { + pHash = tmp->pHash->ptr(); + cbHash = tmp->pHash->length(); + } + + hr = m_pAsmEmitter->DefineFile(wzUniBuf, + (const void*)pHash, + cbHash, + tmp->dwAttr & 0x7FFFFFFF, + (mdFile*)&tk); + _ASSERTE(tk == tmp->tkTok); + if(FAILED(hr)) report->error("Failed to define file '%s': 0x%08X\n",tmp->szName,hr); + else + { + if(fEntry) + { + if (FAILED(pAsm->m_pCeeFileGen->SetEntryPoint(pAsm->m_pCeeFile, tmp->tkTok))) + { + pAsm->report->error("Failed to set external entry point for file '%s'\n",tmp->szName); + } + } + pAsm->EmitCustomAttributes(tmp->tkTok, &(tmp->m_CustomDescrList)); + } + } //end for(i = 0; tmp=m_FileLst.PEEK(i); i++) +} + +void AsmMan::StartAssembly(__in __nullterminated char* szName, __in_opt __nullterminated char* szAlias, DWORD dwAttr, BOOL isRef) +{ + if(!isRef && (0==strcmp(szName, "mscorlib"))) ((Assembler*)m_pAssembler)->m_fIsMscorlib = TRUE; + if(!isRef && (m_pAssembly != NULL)) + { + if(strcmp(szName, m_pAssembly->szName)) + report->error("Multiple assembly declarations\n"); + // if name is the same, just ignore it + m_pCurAsmRef = NULL; + } + else + { + if((m_pCurAsmRef = new AsmManAssembly)) + { + memset(m_pCurAsmRef,0,sizeof(AsmManAssembly)); + m_pCurAsmRef->usVerMajor = (USHORT)0xFFFF; + m_pCurAsmRef->usVerMinor = (USHORT)0xFFFF; + m_pCurAsmRef->usBuild = (USHORT)0xFFFF; + m_pCurAsmRef->usRevision = (USHORT)0xFFFF; + m_pCurAsmRef->szName = szName; + m_pCurAsmRef->szAlias = szAlias ? szAlias : szName; + m_pCurAsmRef->dwAlias = (DWORD)strlen(m_pCurAsmRef->szAlias); + m_pCurAsmRef->dwAttr = dwAttr; + m_pCurAsmRef->isRef = isRef; + m_pCurAsmRef->isAutodetect = FALSE; + m_pCurAsmRef->m_fNew = TRUE; + if(!isRef) m_pAssembly = m_pCurAsmRef; + } + else + report->error("Failed to allocate AsmManAssembly structure\n"); + } + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = m_pCurAsmRef ? &(m_pCurAsmRef->m_CustomDescrList) : NULL; + +} +// copied from asmparse.y +static void corEmitInt(BinStr* buff, unsigned data) +{ + unsigned cnt = CorSigCompressData(data, buff->getBuff(5)); + buff->remove(5 - cnt); +} + +void AsmMan::EmitDebuggableAttribute(mdToken tkOwner) +{ + mdToken tkCA; + Assembler* pAsm = (Assembler*)m_pAssembler; + mdToken tkTypeSpec, tkMscorlib, tkParamType; + BinStr *pbsSig = new BinStr(); + BinStr* bsBytes = new BinStr();; + char* szName; + tkMscorlib = pAsm->m_fIsMscorlib ? 1 : pAsm->GetBaseAsmRef(); + tkTypeSpec = pAsm->ResolveClassRef(tkMscorlib,"System.Diagnostics.DebuggableAttribute",NULL); + + EmitAssemblyRefs(); // just in case we gained 'mscorlib' AsmRef in GetAsmRef above + + BOOL fOldStyle = FALSE; + if(tkMscorlib == 1) + fOldStyle = (m_pAssembly->usVerMajor == 1); + else + { + AsmManAssembly *pAssembly = GetAsmRefByName("mscorlib"); + _ASSERTE(pAssembly != NULL); + PREFIX_ASSUME(pAssembly != NULL); + fOldStyle = (pAssembly->usVerMajor == 1); + } + + bsBytes->appendInt8(1); + bsBytes->appendInt8(0); + if(fOldStyle) + { + pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS); + corEmitInt(pbsSig,2); + pbsSig->appendInt8(ELEMENT_TYPE_VOID); + pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN); + pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN); + + //New to old: 0x101->(true,true),0x03->(true,false),0x103->(true,true)+warning + bsBytes->appendInt8(1); + bsBytes->appendInt8((pAsm->m_dwIncludeDebugInfo==0x03 ? 0 : 1)); + if(pAsm->m_dwIncludeDebugInfo == 0x103) + { + report->warn("\nOption /DEBUG=IMPL is invalid for legacy DebuggableAttribute, /DEBUG used.\n" ); + } + } + else + { + BinStr bsSigArg; + char buffer[80]; + sprintf_s(buffer,80, + "%s%c%s", + "System.Diagnostics.DebuggableAttribute", + NESTING_SEP, + "DebuggingModes" + ); + + tkParamType = pAsm->ResolveClassRef(tkMscorlib,buffer, NULL); + + bsSigArg.appendInt8(ELEMENT_TYPE_VALUETYPE); + + unsigned cnt = CorSigCompressToken(tkParamType, bsSigArg.getBuff(5)); + bsSigArg.remove(5 - cnt); + + pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS); + corEmitInt(pbsSig,1); + pbsSig->appendInt8(ELEMENT_TYPE_VOID); + pbsSig->append(&bsSigArg); + + bsBytes->appendInt32(pAsm->m_dwIncludeDebugInfo); + } + bsBytes->appendInt8(0); + bsBytes->appendInt8(0); + + szName = new char[16]; + strcpy_s(szName,16,".ctor"); + tkCA = pAsm->MakeMemberRef(tkTypeSpec,szName,pbsSig); + pAsm->DefineCV(new CustomDescr(tkOwner,tkCA,bsBytes)); +} + +void AsmMan::EndAssembly() +{ + if(m_pCurAsmRef) + { + if(m_pCurAsmRef->isRef) + { // list the assembly ref + if(GetAsmRefByName(m_pCurAsmRef->szAlias)) + { + //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName); + delete m_pCurAsmRef; + m_pCurAsmRef = NULL; + return; + } +#ifndef FEATURE_CORECLR + if(m_pCurAsmRef->isAutodetect) + { + IAssemblyName* pIAsmName; + HRESULT hr; + // Convert name to Unicode + WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf); + hr = CreateAssemblyNameObject(&pIAsmName,wzUniBuf,CANOF_PARSE_DISPLAY_NAME,NULL); + if(SUCCEEDED(hr)) + { + // set enumeration criteria: what is known about AsmRef (besides name) + if(m_pCurAsmRef->usVerMajor != (USHORT)0xFFFF) + pIAsmName->SetProperty(ASM_NAME_MAJOR_VERSION,&(m_pCurAsmRef->usVerMajor),2); + if(m_pCurAsmRef->usVerMinor != (USHORT)0xFFFF) + pIAsmName->SetProperty(ASM_NAME_MINOR_VERSION,&(m_pCurAsmRef->usVerMinor),2); + if(m_pCurAsmRef->usBuild != (USHORT)0xFFFF) + pIAsmName->SetProperty(ASM_NAME_BUILD_NUMBER,&(m_pCurAsmRef->usBuild),2); + if(m_pCurAsmRef->usRevision != (USHORT)0xFFFF) + pIAsmName->SetProperty(ASM_NAME_REVISION_NUMBER,&(m_pCurAsmRef->usRevision),2); + if(m_pCurAsmRef->pPublicKeyToken) + pIAsmName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, + m_pCurAsmRef->pPublicKeyToken->ptr(), + m_pCurAsmRef->pPublicKeyToken->length()); + if(m_pCurAsmRef->pLocale) + pIAsmName->SetProperty(ASM_NAME_CULTURE, + m_pCurAsmRef->pLocale->ptr(), + m_pCurAsmRef->pLocale->length()); + + // enumerate assemblies + IAssemblyEnum* pIAsmEnum = NULL; + hr = CreateAssemblyEnum(&pIAsmEnum, NULL, pIAsmName, ASM_CACHE_GAC, NULL); + if(SUCCEEDED(hr)) + { + IAssemblyName* pIAsmNameFound; + IAssemblyName* pIAsmNameLatestVer = NULL; + ULONGLONG ullVer=0, ullVerLatest=0; + DWORD dwVerHi, dwVerLo; + + // find the latest and greatest, if any + for(;;) + { + pIAsmNameFound = NULL; + hr = pIAsmEnum->GetNextAssembly(NULL,&pIAsmNameFound,0); + if(SUCCEEDED(hr) && pIAsmNameFound) + { + + pIAsmNameFound->GetVersion(&dwVerHi,&dwVerLo); + ullVer = (ULONGLONG)dwVerHi; + ullVer <<= sizeof(DWORD); + ullVer |= dwVerLo; + if(ullVer > ullVerLatest) + { + if(pIAsmNameLatestVer) + pIAsmNameLatestVer->Release(); + ullVerLatest = ullVer; + pIAsmNameLatestVer = pIAsmNameFound; + } + else + pIAsmNameFound->Release(); + } + else break; + } + // if found, fill the gaps + if(pIAsmNameLatestVer) + { + DWORD cbSize=0; + USHORT usDummy=0; + + if(m_pCurAsmRef->pPublicKeyToken == NULL) + { + cbSize = 1024; + pIAsmNameLatestVer->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, + wzUniBuf, &cbSize); + if(cbSize) + { + if((m_pCurAsmRef->pPublicKeyToken = new BinStr())) + memcpy(m_pCurAsmRef->pPublicKeyToken->getBuff(cbSize), + wzUniBuf, cbSize); + } + } + + if(m_pCurAsmRef->usVerMajor == (USHORT)0xFFFF) + { + cbSize = (DWORD)sizeof(WORD); + pIAsmNameLatestVer->GetProperty(ASM_NAME_MAJOR_VERSION, + &usDummy, &cbSize); + m_pCurAsmRef->usVerMajor = usDummy; + } + if(m_pCurAsmRef->usVerMinor == (USHORT)0xFFFF) + { + cbSize = (DWORD)sizeof(WORD); + pIAsmNameLatestVer->GetProperty(ASM_NAME_MINOR_VERSION, + &usDummy, &cbSize); + m_pCurAsmRef->usVerMinor = usDummy; + } + if(m_pCurAsmRef->usBuild == (USHORT)0xFFFF) + { + cbSize = (DWORD)sizeof(WORD); + pIAsmNameLatestVer->GetProperty(ASM_NAME_BUILD_NUMBER, + &usDummy, &cbSize); + m_pCurAsmRef->usBuild = usDummy; + } + if(m_pCurAsmRef->usRevision == (USHORT)0xFFFF) + { + cbSize = (DWORD)sizeof(WORD); + pIAsmNameLatestVer->GetProperty(ASM_NAME_REVISION_NUMBER, + &usDummy, &cbSize); + m_pCurAsmRef->usRevision = usDummy; + } + + if(m_pCurAsmRef->pLocale == NULL) + { + cbSize = 1024; + pIAsmNameLatestVer->GetProperty(ASM_NAME_CULTURE, + wzUniBuf, &cbSize); + + if(cbSize > (DWORD)sizeof(WCHAR)) + { + if((m_pCurAsmRef->pLocale = new BinStr())) + memcpy(m_pCurAsmRef->pLocale->getBuff(cbSize), + wzUniBuf, cbSize); + } + } + pIAsmNameLatestVer->Release(); + } + else + report->warn("Failed to autodetect assembly '%s'\n",m_pCurAsmRef->szName); + // if no assembly found, leave it as is, it might be not a GAC assembly + + pIAsmEnum->Release(); + } + else + report->error("Failed to enum assemblies %S, hr=0x%08X\n",wzUniBuf,hr); + pIAsmName->Release(); + } + else + report->error("Failed to create assembly name object for %S, hr=0x%08X\n",wzUniBuf,hr); + } // end if isAutodetect +#endif // !FEATURE_CORECLR + m_AsmRefLst.PUSH(m_pCurAsmRef); + m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef); + } + else + { + HRESULT hr = S_OK; + m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly); + + // Determine the strong name public key. This may have been set + // via a directive in the source or from the command line (which + // overrides the directive). From the command line we may have + // been provided with a file or the name of a CAPI key + // container. Either may contain a public key or a full key + // pair. + if (((Assembler*)m_pAssembler)->m_wzKeySourceName) + { + // Key file versus container is determined by the first + // character of the source ('@' for container). + if (*(((Assembler*)m_pAssembler)->m_wzKeySourceName) == L'@') + { +#ifdef FEATURE_CORECLR + report->error("Error: ilasm on CoreCLR does not support getting public key from container.\n"); + m_pCurAsmRef = NULL; + return; +#else + // Extract public key from container (works whether + // container has just a public key or an entire key + // pair). + m_sStrongName.m_wzKeyContainer = &((Assembler*)m_pAssembler)->m_wzKeySourceName[1]; + if (FAILED(hr = LegacyActivationShim::StrongNameGetPublicKey_HRESULT( + m_sStrongName.m_wzKeyContainer, + NULL, + 0, + &m_sStrongName.m_pbPublicKey, + &m_sStrongName.m_cbPublicKey))) + { + report->error("Failed to extract public key from '%S': 0x%08X\n",m_sStrongName.m_wzKeyContainer,hr); + m_pCurAsmRef = NULL; + return; + } + m_sStrongName.m_fFullSign = TRUE; + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedBySNApi; +#endif // FEATURE_CORECLR + } + else + { + // Read public key or key pair from file. + HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + { + hr = GetLastError(); + report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); + m_pCurAsmRef = NULL; + return; + } + + // Determine file size and allocate an appropriate buffer. + m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL); + if (m_sStrongName.m_cbPublicKey == 0xffffffff) { + report->error("File size too large\n"); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + + m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey]; + if (m_sStrongName.m_pbPublicKey == NULL) { + report->error("Failed to allocate key buffer\n"); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedByNew; + + // Read the file into the buffer. + DWORD dwBytesRead; + if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) { + hr = GetLastError(); + report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); + m_pCurAsmRef = NULL; + CloseHandle(hFile); + return; + } + + CloseHandle(hFile); + + // Guess whether we're full or delay signing based on + // whether the blob passed to us looks like a public + // key. (I.e. we may just have copied a full key pair + // into the public key buffer). + if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) && + (offsetof(PublicKeyBlob, PublicKey) + + ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey) + m_sStrongName.m_fFullSign = FALSE; + else + m_sStrongName.m_fFullSign = TRUE; + + // If we really have a key pair, we'll move it into a + // key container so the signing code gets the key pair + // from a consistent place. + if (m_sStrongName.m_fFullSign) + { +#ifdef FEATURE_CORECLR + report->error("Error: ilasm on CoreCLR does not support full sign.\n"); + m_pCurAsmRef = NULL; + return; +#else + m_sStrongName.m_pbPrivateKey = m_sStrongName.m_pbPublicKey; + m_sStrongName.m_cbPrivateKey = m_sStrongName.m_cbPublicKey; + + m_sStrongName.m_pbPublicKey = NULL; + m_sStrongName.m_cbPublicKey = NULL; + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated; + + // Retrieve the public key portion as a byte blob. + if (FAILED(hr = LegacyActivationShim::StrongNameGetPublicKey_HRESULT( + NULL, + m_sStrongName.m_pbPrivateKey, + m_sStrongName.m_cbPrivateKey, + &m_sStrongName.m_pbPublicKey, + &m_sStrongName.m_cbPublicKey))) + { + report->error("Failed to extract public key: 0x%08X\n",hr); + m_pCurAsmRef = NULL; + return; + } + + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedBySNApi; +#endif // FEATURE_CORECLR + } + } + } + else + { + if (m_pAssembly->pPublicKey) + { + m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr(); + m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length(); + } + else + { + m_sStrongName.m_pbPublicKey = NULL; + m_sStrongName.m_cbPublicKey = 0; + } + + m_sStrongName.m_wzKeyContainer = NULL; + m_sStrongName.m_fFullSign = FALSE; + m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated; + } + } + m_pCurAsmRef = NULL; + } + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); +} + +void FillAssemblyMetadata(AsmManAssembly *pAsm, ASSEMBLYMETADATA *pmd) +{ + pmd->usMajorVersion = pAsm->usVerMajor; + pmd->usMinorVersion = pAsm->usVerMinor; + pmd->usBuildNumber = pAsm->usBuild; + pmd->usRevisionNumber = pAsm->usRevision; + if(pmd->usMajorVersion == 0xFFFF) pmd->usMajorVersion = 0; + if(pmd->usMinorVersion == 0xFFFF) pmd->usMinorVersion = 0; + if(pmd->usBuildNumber == 0xFFFF) pmd->usBuildNumber = 0; + if(pmd->usRevisionNumber == 0xFFFF) pmd->usRevisionNumber = 0; + + if(pAsm->pLocale != NULL) + { + pmd->szLocale = (LPWSTR)(pAsm->pLocale->ptr()); + pmd->cbLocale = pAsm->pLocale->length()/((ULONG)sizeof(WCHAR)); + } + else + { + pmd->szLocale = NULL; + pmd->cbLocale = 0; + } + + pmd->rProcessor = NULL; + pmd->rOS = NULL; + pmd->ulProcessor = 0; + pmd->ulOS = 0; +} + +void AsmMan::EmitAssemblyRefs() +{ + int i; + HRESULT hr = S_OK; + ASSEMBLYMETADATA md; + mdToken tk; + + for(i=0; (m_pCurAsmRef=m_AsmRefLst.PEEK(i)) != NULL; i++) + { + if(!m_pCurAsmRef->m_fNew) continue; + m_pCurAsmRef->m_fNew = FALSE; + + wzUniBuf[0] = 0; + FillAssemblyMetadata(m_pCurAsmRef,&md); + + // See if we've got a full public key or the tokenized version (or neither). + BYTE *pbPublicKeyOrToken = NULL; + DWORD cbPublicKeyOrToken = 0; + DWORD dwFlags = m_pCurAsmRef->dwAttr; + if (m_pCurAsmRef->pPublicKeyToken) + { + pbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->ptr(); + cbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->length(); + + } + else if (m_pCurAsmRef->pPublicKey) + { + pbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->ptr(); + cbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->length(); + dwFlags |= afPublicKey; + } + // Convert name to Unicode + WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf); + hr = m_pAsmEmitter->DefineAssemblyRef( // S_OK or error. + pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + cbPublicKeyOrToken, // [IN] Count of bytes in the key or token. + (LPCWSTR)wzUniBuf, // [IN] Name of the assembly being referenced. + (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData. + (m_pCurAsmRef->pHashBlob ? (const void*)(m_pCurAsmRef->pHashBlob->ptr()) : NULL), // [IN] Hash Blob. + (m_pCurAsmRef->pHashBlob ? m_pCurAsmRef->pHashBlob->length() : 0), // [IN] Count of bytes in the Hash Blob. + dwFlags, // [IN] Flags. + (mdAssemblyRef*)&tk); // [OUT] Returned AssemblyRef token. + if(m_pCurAsmRef->tkTok != tk) + { + report->error("AsmRef'%S' tok %8.8X -> %8.8X\n",wzUniBuf,m_pCurAsmRef->tkTok,tk); + } + if(FAILED(hr)) report->error("Failed to define assembly ref '%s': 0x%08X\n",m_pCurAsmRef->szName,hr); + else + { + ((Assembler*)m_pAssembler)->EmitCustomAttributes(m_pCurAsmRef->tkTok, &(m_pCurAsmRef->m_CustomDescrList)); + } + } // end for(i=0; m_pCurAsmRef=m_AsmRefLst.PEEK(i); i++) +} + +void AsmMan::EmitAssembly() +{ + HRESULT hr = S_OK; + ASSEMBLYMETADATA md; + + wzUniBuf[0] = 0; + if(m_pAssembly == NULL) return; + if(!m_pAssembly->m_fNew) return; + m_pAssembly->m_fNew = FALSE; + + FillAssemblyMetadata(m_pAssembly, &md); + + // Convert name to Unicode + WszMultiByteToWideChar(g_uCodePage,0,m_pAssembly->szName,-1,wzUniBuf,dwUniBuf); + + hr = m_pAsmEmitter->DefineAssembly( // S_OK or error. + (const void*)(m_sStrongName.m_pbPublicKey), // [IN] Public key of the assembly. + m_sStrongName.m_cbPublicKey, // [IN] Count of bytes in the public key. + m_pAssembly->ulHashAlgorithm, // [IN] Hash algorithm used to hash the files. + (LPCWSTR)wzUniBuf, // [IN] Name of the assembly. + (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData. + m_pAssembly->dwAttr, // [IN] Flags. + (mdAssembly*)&(m_pAssembly->tkTok)); // [OUT] Returned Assembly token. + + if(FAILED(hr)) report->error("Failed to define assembly '%s': 0x%08X\n",m_pAssembly->szName,hr); + else + { + Assembler* pAsm = ((Assembler*)m_pAssembler); + pAsm->EmitSecurityInfo(m_pAssembly->tkTok, + m_pAssembly->m_pPermissions, + m_pAssembly->m_pPermissionSets); + if(pAsm->m_dwIncludeDebugInfo) + { + EmitDebuggableAttribute(m_pAssembly->tkTok); + } + pAsm->EmitCustomAttributes(m_pAssembly->tkTok, &(m_pAssembly->m_CustomDescrList)); + } +} + +void AsmMan::SetAssemblyPublicKey(BinStr* pPublicKey) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pPublicKey = pPublicKey; + } +} + +void AsmMan::SetAssemblyPublicKeyToken(BinStr* pPublicKeyToken) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pPublicKeyToken = pPublicKeyToken; + } +} + +void AsmMan::SetAssemblyHashAlg(ULONG ulAlgID) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->ulHashAlgorithm = ulAlgID; + } +} + +void AsmMan::SetAssemblyVer(USHORT usMajor, USHORT usMinor, USHORT usBuild, USHORT usRevision) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->usVerMajor = usMajor; + m_pCurAsmRef->usVerMinor = usMinor; + m_pCurAsmRef->usBuild = usBuild; + m_pCurAsmRef->usRevision = usRevision; + } +} + +void AsmMan::SetAssemblyLocale(BinStr* pLocale, BOOL bConvertToUnicode) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pLocale = bConvertToUnicode ? ::BinStrToUnicode(pLocale) : pLocale; + } +} + +void AsmMan::SetAssemblyHashBlob(BinStr* pHashBlob) +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->pHashBlob = pHashBlob; + } +} + +void AsmMan::SetAssemblyAutodetect() +{ + if(m_pCurAsmRef) + { + m_pCurAsmRef->isAutodetect = TRUE; + } +} + +void AsmMan::StartComType(__in __nullterminated char* szName, DWORD dwAttr) +{ + if((m_pCurComType = new AsmManComType)) + { + memset(m_pCurComType,0,sizeof(AsmManComType)); + m_pCurComType->szName = szName; + m_pCurComType->dwAttr = dwAttr; + m_pCurComType->m_fNew = TRUE; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurComType->m_CustomDescrList); + } + else + report->error("Failed to allocate AsmManComType structure\n"); +} + +void AsmMan::EndComType() +{ + if(m_pCurComType) + { + if(m_pAssembler) + { + Class* pClass =((Assembler*)m_pAssembler)->m_pCurClass; + if(pClass) + { + m_pCurComType->tkClass = pClass->m_cl; + if(pClass->m_pEncloser) + { + mdTypeDef tkEncloser = pClass->m_pEncloser->m_cl; + AsmManComType* pCT; + for(unsigned i=0; (pCT=m_ComTypeLst.PEEK(i)); i++) + { + if(pCT->tkClass == tkEncloser) + { + m_pCurComType->szComTypeName = pCT->szName; + break; + } + } + } + } + } + + if (IsTdNested(m_pCurComType->dwAttr) && GetComTypeByName(m_pCurComType->szName, m_pCurComType->szComTypeName) != NULL) + { + report->error("Invalid TypeDefID of exported type\n"); + delete m_pCurComType; + } + else + { + m_ComTypeLst.PUSH(m_pCurComType); + } + + m_pCurComType = NULL; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); + } +} + +void AsmMan::SetComTypeFile(__in __nullterminated char* szFileName) +{ + if(m_pCurComType) + { + m_pCurComType->szFileName = szFileName; + } +} + +void AsmMan::SetComTypeAsmRef(__in __nullterminated char* szAsmRefName) +{ + if(m_pCurComType) + { + m_pCurComType->szAsmRefName = szAsmRefName; + } +} + +void AsmMan::SetComTypeComType(__in __nullterminated char* szComTypeName) +{ + if(m_pCurComType) + { + m_pCurComType->szComTypeName = szComTypeName; + } +} +BOOL AsmMan::SetComTypeImplementationTok(mdToken tk) +{ + if(m_pCurComType) + { + switch(TypeFromToken(tk)) + { + case mdtAssemblyRef: + case mdtExportedType: + case mdtFile: + m_pCurComType->tkImpl = tk; + return TRUE; + } + } + return FALSE; +} +BOOL AsmMan::SetComTypeClassTok(mdToken tkClass) +{ + if((m_pCurComType)&&(TypeFromToken(tkClass)==mdtTypeDef)) + { + m_pCurComType->tkClass = tkClass; + return TRUE; + } + return FALSE; +} + +void AsmMan::StartManifestRes(__in __nullterminated char* szName, __in __nullterminated char* szAlias, DWORD dwAttr) +{ + if((m_pCurManRes = new AsmManRes)) + { + m_pCurManRes->szName = szName; + m_pCurManRes->szAlias = szAlias; + m_pCurManRes->dwAttr = dwAttr; + m_pCurManRes->m_fNew = TRUE; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList); + ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurManRes->m_CustomDescrList); + } + else + report->error("Failed to allocate AsmManRes structure\n"); +} + +void AsmMan::EndManifestRes() +{ + if(m_pCurManRes) + { + m_ManResLst.PUSH(m_pCurManRes); + m_pCurManRes = NULL; + ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0; + ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); + } +} + + +void AsmMan::SetManifestResFile(__in __nullterminated char* szFileName, ULONG ulOffset) +{ + if(m_pCurManRes) + { + m_pCurManRes->szFileName = szFileName; + m_pCurManRes->ulOffset = ulOffset; + } +} + +void AsmMan::SetManifestResAsmRef(__in __nullterminated char* szAsmRefName) +{ + if(m_pCurManRes) + { + m_pCurManRes->szAsmRefName = szAsmRefName; + } +} + +HRESULT AsmMan::EmitManifest() +{ + //AsmManAssembly* pAsmRef; + AsmManComType* pComType; + AsmManRes* pManRes; + HRESULT hr = S_OK; + + wzUniBuf[0] = 0; + + if(m_pAsmEmitter==NULL) + hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &m_pAsmEmitter); + + if(SUCCEEDED(hr)) + { + EmitFiles(); + EmitAssembly(); + + if((((Assembler*)m_pAssembler)->m_dwIncludeDebugInfo != 0) && (m_pAssembly == NULL) + && !(((Assembler*)m_pAssembler)->m_fENCMode)) + { + mdToken tkOwner, tkMscorlib; + tkMscorlib = ((Assembler*)m_pAssembler)->GetAsmRef("mscorlib"); + tkOwner = ((Assembler*)m_pAssembler)->ResolveClassRef(tkMscorlib, + "System.Runtime.CompilerServices.AssemblyAttributesGoHere", + NULL); + EmitDebuggableAttribute(tkOwner); + } + + // Emit all com types + unsigned i; + for(i = 0; (pComType = m_ComTypeLst.PEEK(i)); i++) + { + if(!pComType->m_fNew) continue; + pComType->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pComType->szName,-1,wzUniBuf,dwUniBuf); + mdToken tkImplementation = mdTokenNil; + if(pComType->tkImpl) tkImplementation = pComType->tkImpl; + else if(pComType->szFileName) + { + tkImplementation = GetFileTokByName(pComType->szFileName); + if(tkImplementation==mdFileNil) + { + report->error("Undefined File '%s' in ExportedType '%s'\n",pComType->szFileName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else if(pComType->szAsmRefName) + { + tkImplementation = GetAsmRefTokByName(pComType->szAsmRefName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined AssemblyRef '%s' in ExportedType '%s'\n",pComType->szAsmRefName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else if(pComType->szComTypeName) + { + char* szLastName = strrchr(pComType->szComTypeName, NESTING_SEP); + + if(szLastName) + { + *szLastName = 0; + szLastName ++; + tkImplementation = GetComTypeTokByName(szLastName, pComType->szComTypeName); + *(szLastName-1) = NESTING_SEP; // not really necessary + } + + else + { + tkImplementation = GetComTypeTokByName(pComType->szComTypeName); + } + + if(tkImplementation==mdExportedTypeNil) + { + report->error("Undefined ExportedType '%s' in ExportedType '%s'\n",pComType->szComTypeName,pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + } + else + { + report->warn("Undefined implementation in ExportedType '%s' -- ExportType not emitted\n",pComType->szName); + if(!((Assembler*)m_pAssembler)->OnErrGo) continue; + } + hr = m_pAsmEmitter->DefineExportedType( // S_OK or error. + (LPCWSTR)wzUniBuf, // [IN] Name of the Com Type. + tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the ComType. + (mdTypeDef)pComType->tkClass, // [IN] TypeDef token within the file. + pComType->dwAttr, // [IN] Flags. + (mdExportedType*)&(pComType->tkTok)); // [OUT] Returned ComType token. + if(FAILED(hr)) report->error("Failed to define ExportedType '%s': 0x%08X\n",pComType->szName,hr); + else + { + ((Assembler*)m_pAssembler)->EmitCustomAttributes(pComType->tkTok, &(pComType->m_CustomDescrList)); + } + } + + // Emit all manifest resources + m_dwMResSizeTotal = 0; + m_dwMResNum = 0; + for(i = 0; (pManRes = m_ManResLst.PEEK(i)); i++) + { + BOOL fOK = TRUE; + mdToken tkImplementation = mdFileNil; + + if(!pManRes->m_fNew) continue; + pManRes->m_fNew = FALSE; + + WszMultiByteToWideChar(g_uCodePage,0,pManRes->szAlias,-1,wzUniBuf,dwUniBuf); + if(pManRes->szAsmRefName) + { + tkImplementation = GetAsmRefTokByName(pManRes->szAsmRefName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined AssemblyRef '%s' in MResource '%s'\n",pManRes->szAsmRefName,pManRes->szName); + fOK = FALSE; + } + } + else if(pManRes->szFileName) + { + tkImplementation = GetFileTokByName(pManRes->szFileName); + if(RidFromToken(tkImplementation)==0) + { + report->error("Undefined File '%s' in MResource '%s'\n",pManRes->szFileName,pManRes->szName); + fOK = FALSE; + } + } + else // embedded mgd.resource, go after the file + { + HANDLE hFile = INVALID_HANDLE_VALUE; + int j; + WCHAR wzFileName[2048]; + WCHAR* pwz; + + pManRes->ulOffset = m_dwMResSizeTotal; + for(j=0; (hFile == INVALID_HANDLE_VALUE)&&(pwzInputFiles[j] != NULL); j++) + { + wcscpy_s(wzFileName,2048,pwzInputFiles[j]); + pwz = wcsrchr(wzFileName,'\\'); + if(pwz == NULL) pwz = wcsrchr(wzFileName,':'); + if(pwz == NULL) pwz = &wzFileName[0]; + else pwz++; + wcscpy_s(pwz,2048-(pwz-wzFileName),wzUniBuf); + hFile = WszCreateFile(wzFileName, GENERIC_READ, FILE_SHARE_READ, + 0, OPEN_EXISTING, 0, 0); + } + if (hFile == INVALID_HANDLE_VALUE) + { + report->error("Failed to open managed resource file '%s'\n",pManRes->szAlias); + fOK = FALSE; + } + else + { + if (m_dwMResNum >= MAX_MANIFEST_RESOURCES) + { + report->error("Too many resources (implementation limit: %d); skipping file '%s'\n",MAX_MANIFEST_RESOURCES,pManRes->szAlias); + fOK = FALSE; + } + else + { + m_dwMResSize[m_dwMResNum] = SafeGetFileSize(hFile,NULL); + if(m_dwMResSize[m_dwMResNum] == 0xFFFFFFFF) + { + report->error("Failed to get size of managed resource file '%s'\n",pManRes->szAlias); + fOK = FALSE; + } + else + { + m_dwMResSizeTotal += m_dwMResSize[m_dwMResNum]+sizeof(DWORD); + m_wzMResName[m_dwMResNum] = new WCHAR[wcslen(wzFileName)+1]; + wcscpy_s(m_wzMResName[m_dwMResNum],wcslen(wzFileName)+1,wzFileName); + m_fMResNew[m_dwMResNum] = TRUE; + m_dwMResNum++; + } + CloseHandle(hFile); + } + } + } + if(fOK || ((Assembler*)m_pAssembler)->OnErrGo) + { + WszMultiByteToWideChar(g_uCodePage,0,pManRes->szName,-1,wzUniBuf,dwUniBuf); + hr = m_pAsmEmitter->DefineManifestResource( // S_OK or error. + (LPCWSTR)wzUniBuf, // [IN] Name of the resource. + tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + pManRes->ulOffset, // [IN] Offset to the beginning of the resource within the file. + pManRes->dwAttr, // [IN] Flags. + (mdManifestResource*)&(pManRes->tkTok)); // [OUT] Returned ManifestResource token. + if(FAILED(hr)) + report->error("Failed to define manifest resource '%s': 0x%08X\n",pManRes->szName,hr); + } + } + + + m_pAsmEmitter->Release(); + m_pAsmEmitter = NULL; + } + else + report->error("Failed to obtain IMetaDataAssemblyEmit interface: 0x%08X\n",hr); + return hr; +} + |