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; } 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 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) { { // 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 = 2; // 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) { 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 = 0; // Retrieve the public key portion as a byte blob. if (!StrongNameGetPublicKey(NULL, m_sStrongName.m_pbPrivateKey, m_sStrongName.m_cbPrivateKey, &m_sStrongName.m_pbPublicKey, &m_sStrongName.m_cbPublicKey)) { hr = StrongNameErrorInfo(); report->error("Failed to extract public key: 0x%08X\n",hr); m_pCurAsmRef = NULL; return; } m_sStrongName.m_dwPublicKeyAllocated = 2; } } } else if (m_pAssembly->pPublicKey) { m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr(); m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length(); m_sStrongName.m_wzKeyContainer = NULL; m_sStrongName.m_fFullSign = FALSE; m_sStrongName.m_dwPublicKeyAllocated = 0; } 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 = 0; } } m_pCurAsmRef = NULL; } ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); }
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) { 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 { 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; }
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; }
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; } 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'@') { report->error("Error: ilasm on CoreCLR does not support getting public key from container.\n"); m_pCurAsmRef = NULL; return; } 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) { report->error("Error: ilasm on CoreCLR does not support full sign.\n"); m_pCurAsmRef = NULL; return; } } } 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(); }