Exemplo n.º 1
0
//*****************************************************************************
// This method will walk the byte codes of an IL method looking for tokens.
// For each token found, it will check to see if it has been moved, and if
// so, apply the new token value in its place.
//*****************************************************************************
HRESULT CeeFileGenWriter::MapTokensForMethod(
    CeeGenTokenMapper *pMapper,
    BYTE        *pCode,
    LPCWSTR     szMethodName)
{
    mdToken     tkTo;
    DWORD       PC;

    COR_ILMETHOD_DECODER method((COR_ILMETHOD*) pCode);

    // If compressed IL is being emitted, this routine will have no idea how to walk the tokens,
    // so don't do it
    if (m_dwMacroDefinitionSize != 0)
        return S_OK;

    pCode = const_cast<BYTE*>(method.Code);

    PC = 0;
    while (PC < method.GetCodeSize())
    {
        DWORD   Len;
        DWORD   i;
        OPCODE  instr;

        instr = DecodeOpcode(&pCode[PC], &Len);

        if (instr == CEE_COUNT)
        {
            _ASSERTE(0 && "Instruction decoding error\n");
            return E_FAIL;
        }


        PC += Len;

        switch (OpcodeInfo[instr].Type)
        {
            DWORD tk;

            default:
            {
                _ASSERTE(0 && "Unknown instruction\n");
                return E_FAIL;
            }

            case InlineNone:
            break;

            case ShortInlineI:
            case ShortInlineVar:
            case ShortInlineBrTarget:
            PC++;
            break;

            case InlineVar:
            PC += 2;
            break;

            case InlineI:
            case ShortInlineR:
            case InlineBrTarget:
            case InlineRVA:
            PC += 4;
            break;

            case InlineI8:
            case InlineR:
            PC += 8;
            break;

            case InlinePhi:
                {
                    DWORD cases = pCode[PC];
                    PC += 2 * cases + 1;
                    break;
                }

            case InlineSwitch:
            {
                DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);

                PC += 4;
                for (i = 0; i < cases; i++)
                {
                    PC += 4;
                }

                // skip bottom of loop which prints szString
                continue;
            }

            case InlineTok:
            case InlineSig:
            case InlineMethod:
            case InlineField:
            case InlineType:
            case InlineString:
            {
                tk = GET_UNALIGNED_VAL32(&pCode[PC]);

                if (pMapper->HasTokenMoved(tk, tkTo))
                {
                    SET_UNALIGNED_VAL32(&pCode[PC], tkTo);
                }

                PC += 4;
                break;
            }
        }
    }

    return S_OK;
}
Exemplo n.º 2
0
HRESULT CAsmLink::SetAssemblyProps(mdAssembly AssemblyID, mdToken FileToken, AssemblyOptions Option, VARIANT Value)
{
    ASSERT(m_bInited && !m_bPreClosed && m_pAssem && !m_bManifestEmitted);
    ASSERT(AssemblyID == TokenFromRid(mdtAssembly, 1) || AssemblyID == AssemblyIsUBM);
    ASSERT((RidFromToken(FileToken) < m_pAssem->CountFiles() && TypeFromToken(FileToken) == mdtFile) ||
        (FileToken == AssemblyID));

    HRESULT hr = S_OK;
    if (Option >= optLastAssemOption || OptionCAs[Option].flag & 0x40)
        return E_INVALIDARG;
    if (AssemblyID == AssemblyIsUBM || (OptionCAs[Option].flag & 0x02)) {
        CFile *file = NULL;
        if (FileToken == AssemblyID)
            file = m_pAssem;
        else if (FAILED(hr = m_pAssem->GetFile(FileToken, &file)))
            return hr;

        ASSERT(file->GetEmitScope());
        IMetaDataEmit* pEmit = file->GetEmitScope();
        CComPtr<IMetaDataImport> pImport;
        mdToken tkAttrib = mdTokenNil, tkCtor;
        DWORD cbValue = 0, cbSig = 4;
        BYTE pbValue[2048];
        PBYTE pBlob = pbValue;
        COR_SIGNATURE newSig[9];
        LPCWSTR wszStr = NULL;
        ULONG wLen = 0;

        if (FAILED(hr = pEmit->QueryInterface(IID_IMetaDataImport, (void**)&pImport)))
            return hr;

        // Find or Create the TypeRef (This always scopes it to MSCORLIB)
        if (FAILED(hr = file->GetTypeRef(OptionCAs[Option].name, &tkAttrib)))
            return hr;

        // Make the Blob
        newSig[0] = (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS);
        newSig[1] = 1; // One parameter
        newSig[2] = ELEMENT_TYPE_VOID;
        *(WORD*)pBlob = VAL16(1); // This is aligned
        pBlob += sizeof(WORD);

        if (V_VT(&Value) != OptionCAs[Option].vt)
            return E_INVALIDARG;
        switch(OptionCAs[Option].vt) {
        case VT_BOOL:
            *pBlob++ = (V_BOOL(&Value) == VARIANT_TRUE);
            newSig[3] = ELEMENT_TYPE_BOOLEAN;
            break;
        case VT_UI4:
            SET_UNALIGNED_VAL32(pBlob, V_UI4(&Value));
            pBlob += sizeof(ULONG);
            newSig[3] = ELEMENT_TYPE_U4;
            break;
        case VT_BSTR:
            if (Option == optAssemOS) {
                LPWSTR end = NULL;
                mdToken tkPlatform = mdTokenNil;
                newSig[1] = 2; // Two parameters
                newSig[3] = ELEMENT_TYPE_VALUETYPE;

                // Make the TypeRef
                if (FAILED(hr = file->GetTypeRef( PLATFORMID_NAME, &tkPlatform)))
                     break;

                cbSig = 5 + CorSigCompressToken(tkPlatform, newSig + 4);
                newSig[cbSig - 1] = ELEMENT_TYPE_STRING;
                SET_UNALIGNED_VAL32(pBlob, wcstoul(V_BSTR(&Value), &end, 0)); // Parse Hex, Octal, and Decimal
                pBlob += sizeof(ULONG);
                if (*end == L'.') {
                    wszStr = end++;
                    wLen = SysStringLen(V_BSTR(&Value)) - (UINT)(V_BSTR(&Value) - end);
                    goto ADDSTRING;
                } else {
                    hr = file->ReportError(ERR_InvalidOSString);
                    return hr;
                }
            } else {
                newSig[3] = ELEMENT_TYPE_STRING;
                wLen = SysStringLen(V_BSTR(&Value));
                wszStr = V_BSTR(&Value);
ADDSTRING:
                if (wLen == 0) {
                    // Too small for unilib
                    *pBlob++ = 0xFF;
                } else if (wLen & 0x80000000) {
                    // Too big!
                    return ReportOptionError(file, Option, E_INVALIDARG);
                } else if ((OptionCAs[Option].flag & 0x10) && wLen > MAX_PATH) {
                    // Too big!
                    return ReportOptionError(file, Option, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW)); // File name too long
                } else {
                    CHAR pUTF8[2048];
                    int iLen = wLen;
    
                    wLen = (UINT)UnicodeToUTF8(wszStr, &iLen, pUTF8, lengthof(pUTF8));

                    iLen = (int)CorSigCompressData( wLen, pBlob);
                    pBlob += iLen;
                    if (wLen > (UINT)(pbValue + lengthof(pbValue) - pBlob)) {
                        // Too big!
                        return ReportOptionError(file, Option, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
                    }
                    memcpy(pBlob, pUTF8, wLen);
                    pBlob += wLen;
                }
            }
            break;
        default:
            VSFAIL("Unknown Option Type!");
            newSig[3] = ELEMENT_TYPE_OBJECT;
            break;
        }
        hr = pImport->FindMemberRef(tkAttrib, L".ctor", newSig, cbSig, &tkCtor);
        if ((hr == CLDB_E_RECORD_NOTFOUND && FAILED(hr = pEmit->DefineMemberRef(tkAttrib, L".ctor", newSig, 4, &tkCtor))) ||
            FAILED(hr))
            return hr;
        cbValue = (DWORD)(pBlob - pbValue);

        // Emit the CA
        // This will also set the option if appropriate
        hr = EmitAssemblyCustomAttribute( AssemblyID, FileToken, tkCtor, pbValue, cbValue, 
            (OptionCAs[Option].flag & 0x08) ? TRUE : FALSE,
            (OptionCAs[Option].flag & 0x04) ? TRUE : FALSE);
    } else {
        // An assembly level custom attribute
        hr = m_pAssem->SetOption(Option, &Value);
    }
    return hr;
}
Exemplo n.º 3
0
BOOL RSAKey::ExportKey(DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
{
    DWORD dwByteLen1;
    DWORD dwByteLen2;
    DWORD dwDataLen;
    BOOL bPrivate;
    BLOBHEADER *pBlobHeader;
    RSAPUBKEY* pRSAPubKey;

    if ((dwBlobType != PUBLICKEYBLOB) && 
        ((dwBlobType != PRIVATEKEYBLOB) || (m_pPrivateExponent == NULL)))
    {
        SetLastError(NTE_BAD_TYPE);
        return FALSE;
    }

    bPrivate = (dwBlobType != PUBLICKEYBLOB);

    if (dwFlags != 0)
    {
        SetLastError(NTE_BAD_FLAGS);
        return FALSE;
    }

    dwByteLen1 = m_dwBitLen / 8;
    dwByteLen2 = dwByteLen1 / 2;

    dwDataLen = (pbData != NULL) ? *pdwDataLen : 0;
    *pdwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 
        (bPrivate ? (2 * dwByteLen1 + 5 * dwByteLen2) : dwByteLen1);
    if (dwDataLen < *pdwDataLen)
    {
        if (pbData != NULL)
        {
            SetLastError(ERROR_MORE_DATA);
            return FALSE;
        }
        return TRUE;
    }

    pBlobHeader = (BLOBHEADER *)pbData;
    pbData += sizeof(BLOBHEADER);

    pBlobHeader->bType = (BYTE)dwBlobType;
    pBlobHeader->bVersion = 0x02;
    SET_UNALIGNED_VAL16(&pBlobHeader->reserved, 0x0000);
    SET_UNALIGNED_VAL32(&pBlobHeader->aiKeyAlg, CALG_RSA_SIGN);

    pRSAPubKey = (RSAPUBKEY*)pbData;
    pbData += sizeof(RSAPUBKEY);

    SET_UNALIGNED_VAL32(&pRSAPubKey->magic, bPrivate ? 0x32415352 : 0x31415352); // 'RSA2' : 'RSA1'
    SET_UNALIGNED_VAL32(&pRSAPubKey->bitlen, m_dwBitLen);

    BigNum::GetBytes(m_pExponent, (BYTE*)&pRSAPubKey->pubexp, sizeof(DWORD));

#define HELPER(m_pMember, size) \
    BigNum::GetBytes(m_pMember, pbData, dwByteLen##size); \
    pbData += dwByteLen##size;

    HELPER(m_pModulus, 1);

    if (dwBlobType == PUBLICKEYBLOB)
        return TRUE;

    HELPER(m_pPrime1, 2);
    HELPER(m_pPrime2, 2);
    HELPER(m_pExponent1, 2);
    HELPER(m_pExponent2, 2);
    HELPER(m_pCoefficient, 2);
    HELPER(m_pPrivateExponent, 1);
#undef HELPER

    return TRUE;
}
Exemplo n.º 4
0
HRESULT CeeFileGenWriter::emitExeMain()
{
    // Note: code later on in this method assumes that mscoree.dll is at
    // index m_iDataDlls[0], with CorDllMain or CorExeMain at method[0]

    if (m_dllSwitch) {
        m_iDataDlls[0].m_methodName[0] = "_CorDllMain";
    } else {
        m_iDataDlls[0].m_methodName[0] = "_CorExeMain";
    }

    int iDataSizeIAT = 0;
    int iDataSizeRO = (m_dllCount + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
    CeeSection &iDataSectionRO = getTextSection();
    int iDataOffsetRO = iDataSectionRO.dataLen();
    int i;
    for (i=0; i < m_dllCount; i++) {
        m_iDataDlls[i].m_iltOffset = iDataSizeRO + iDataSizeIAT;
        iDataSizeIAT += (m_iDataDlls[i].m_numMethods + 1) * sizeof(IMAGE_THUNK_DATA);
    }

    iDataSizeRO += iDataSizeIAT;

    for (i=0; i < m_dllCount; i++) {
        int delta = (iDataSizeRO + iDataOffsetRO) % 16;
        // make sure is on a 16-byte offset
        if (delta != 0)
            iDataSizeRO += (16 - delta);
        _ASSERTE((iDataSizeRO + iDataOffsetRO) % 16 == 0);
        m_iDataDlls[i].m_ibnOffset = iDataSizeRO;
        for (int j=0; j < m_iDataDlls[i].m_numMethods; j++) {
            int nameLen = (int)(strlen(m_iDataDlls[i].m_methodName[j]) + 1);
            iDataSizeRO += sizeof(WORD) + nameLen + nameLen%2;
        }
    }
    for (i=0; i < m_dllCount; i++) {
        m_iDataDlls[i].m_nameOffset = iDataSizeRO;
        iDataSizeRO += (int)(strlen(m_iDataDlls[i].m_name) + 2);
    }                                                             

    char *iDataRO = iDataSectionRO.getBlock(iDataSizeRO);
    if (! iDataRO) {
        return E_OUTOFMEMORY;
    }
    memset(iDataRO, '\0', iDataSizeRO);

    setDirectoryEntry(iDataSectionRO, IMAGE_DIRECTORY_ENTRY_IMPORT, iDataSizeRO, iDataOffsetRO);

    IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)iDataRO;        
    for (i=0; i < m_dllCount; i++) {

        // fill in the import descriptors for each DLL
        IMAGE_IMPORT_DESC_FIELD(iid[i], OriginalFirstThunk) = VAL32((ULONG)(m_iDataDlls[i].m_iltOffset + iDataOffsetRO));
        iid[i].Name = VAL32(m_iDataDlls[i].m_nameOffset + iDataOffsetRO);
        iid[i].FirstThunk = VAL32((ULONG)(m_iDataDlls[i].m_iatOffset + m_iDataOffsetIAT));

        iDataSectionRO.addSectReloc(
            (unsigned)(iDataOffsetRO + (char *)(&IMAGE_IMPORT_DESC_FIELD(iid[i], OriginalFirstThunk)) - iDataRO), iDataSectionRO, srRelocAbsolute);
        iDataSectionRO.addSectReloc(
            (unsigned)(iDataOffsetRO + (char *)(&iid[i].Name) - iDataRO), iDataSectionRO, srRelocAbsolute);
        iDataSectionRO.addSectReloc(
            (unsigned)(iDataOffsetRO + (char *)(&iid[i].FirstThunk) - iDataRO), *m_iDataSectionIAT, srRelocAbsolute);

        // now fill in the import lookup table for each DLL
        IMAGE_THUNK_DATA *ilt = (IMAGE_THUNK_DATA*)
                        (iDataRO + m_iDataDlls[i].m_iltOffset);
        IMAGE_THUNK_DATA *iat = (IMAGE_THUNK_DATA*)
                        (m_iDataIAT + m_iDataDlls[i].m_iatOffset);

        int ibnOffset = m_iDataDlls[i].m_ibnOffset;
        for (int j=0; j < m_iDataDlls[i].m_numMethods; j++) 
        {
            SET_UNALIGNED_VAL32(&ilt[j].u1.AddressOfData, (ULONG_PTR)(ibnOffset + iDataOffsetRO));
            SET_UNALIGNED_VAL32(&iat[j].u1.AddressOfData, (ULONG_PTR)(ibnOffset + iDataOffsetRO));

            iDataSectionRO.addSectReloc(
                (unsigned)(iDataOffsetRO + (char *)(&ilt[j].u1.AddressOfData) - iDataRO), iDataSectionRO, srRelocAbsolute);
            m_iDataSectionIAT->addSectReloc(
                (unsigned)(m_iDataOffsetIAT + (char *)(&iat[j].u1.AddressOfData) - m_iDataIAT), iDataSectionRO, srRelocAbsolute);
            int nameLen = (int)(strlen(m_iDataDlls[i].m_methodName[j]) + 1);
            memcpy(iDataRO + ibnOffset + offsetof(IMAGE_IMPORT_BY_NAME, Name), 
                                    m_iDataDlls[i].m_methodName[j], nameLen);
            ibnOffset += sizeof(WORD) + nameLen + nameLen%2;
        }

        // now fill in the import lookup table for each DLL
        strcpy(iDataRO + m_iDataDlls[i].m_nameOffset, m_iDataDlls[i].m_name);
    };

    // Put the entry point code into the PE file
    unsigned entryPointOffset = getTextSection().dataLen();
    int iatOffset = (int)(entryPointOffset + (m_dllSwitch ? CorDllMainIATOffset : CorExeMainIATOffset));
    const int align = 4;
    // WinCE needs to have the IAT offset on a 4-byte boundary because it will be loaded and fixed up even
    // for RISC platforms, where DWORDs must be 4-byte aligned.  So compute number of bytes to round up by 
    // to put iat offset on 4-byte boundary
    int diff = ((iatOffset + align -1) & ~(align-1)) - iatOffset;
    if (diff) {
        // force to 4-byte boundary
        if(NULL==getTextSection().getBlock(diff)) return E_OUTOFMEMORY;
        entryPointOffset += diff;
    }
    _ASSERTE((getTextSection().dataLen() + (m_dllSwitch ? CorDllMainIATOffset : CorExeMainIATOffset)) % 4 == 0);

    getPEWriter().setEntryPointTextOffset(entryPointOffset);
    if (m_dllSwitch) {
        UCHAR *dllMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(DllMainTemplate));
        if(dllMainBuf==NULL) return E_OUTOFMEMORY;
        memcpy(dllMainBuf, DllMainTemplate, sizeof(DllMainTemplate));
        //mscoree.dll
        setAddrReloc(dllMainBuf+CorDllMainIATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
        addAddrReloc(getTextSection(), dllMainBuf, entryPointOffset+CorDllMainIATOffset, m_iDataSectionIAT);
    } else {
        UCHAR *exeMainBuf = (UCHAR*)getTextSection().getBlock(sizeof(ExeMainTemplate));
        if(exeMainBuf==NULL) return E_OUTOFMEMORY;
        memcpy(exeMainBuf, ExeMainTemplate, sizeof(ExeMainTemplate));
        //mscoree.dll
        setAddrReloc(exeMainBuf+CorExeMainIATOffset, m_iDataDlls[0].m_iatOffset + m_iDataOffsetIAT);
        addAddrReloc(getTextSection(), exeMainBuf, entryPointOffset+CorExeMainIATOffset, m_iDataSectionIAT);
    }

    // Now set our IAT entry since we're using the IAT
    setDirectoryEntry(*m_iDataSectionIAT, IMAGE_DIRECTORY_ENTRY_IAT, iDataSizeIAT, m_iDataOffsetIAT);

    return S_OK;
} // HRESULT CeeFileGenWriter::emitExeMain()
Exemplo n.º 5
0
HRESULT Assembler::CreatePEFile(WCHAR *pwzOutputFilename)
{
    HRESULT             hr;
	DWORD				mresourceSize = 0;
	BYTE*				mresourceData = NULL;
	//IUnknown *pUnknown = NULL;
//    DWORD               i;

	if(bClock) cMDEmitBegin = GetTickCount();
	if(m_fReportProgress) printf("Creating %s file\n", m_fOBJ ? "COFF" : "PE");
    if (!m_pEmitter)
    {
        printf("Error: Cannot create a PE file with no metadata\n");
        return E_FAIL;
    }
	if(!(m_fDLL || m_fEntryPointPresent))
	{
		printf("Error: No entry point declared for executable\n");
		if(!OnErrGo) return E_FAIL;
	}

    if (DoGlobalFixups() == FALSE)
        return E_FAIL;
	if(bClock) cMDEmit1 = GetTickCount();

	if(m_fOBJ)
	{
		// emit pseudo-relocs to pass file name and build number to PEWriter
		// this should be done BEFORE method emission!
		char* szInFileName = new char[strlen(m_szSourceFileName)+1];
		strcpy(szInFileName,m_szSourceFileName);
		m_pCeeFileGen->AddSectionReloc(m_pILSection,(DWORD)szInFileName,m_pILSection,(CeeSectionRelocType)0x7FFC);
		time_t tm;
		time(&tm);
		struct tm* loct = localtime(&tm);
		DWORD compid = 0x002E0000 | (loct->tm_mday + (loct->tm_mon+1)*100);
		m_pCeeFileGen->AddSectionReloc(m_pILSection,compid,m_pILSection,(CeeSectionRelocType)0x7FFB);
	}

    // Allocate space for a strong name signature if we're delay or full
    // signing the assembly.
    if (m_pManifest->m_sStrongName.m_pbPublicKey)
        if (FAILED(hr = AllocateStrongNameSignature()))
            goto exit;
	if(bClock) cMDEmit2 = GetTickCount();

	// Check undefined local TypeRefs
	if(m_LocalTypeRefDList.COUNT())
	{
		LocalTypeRefDescr*	pLTRD=NULL;
		BOOL	bIsUndefClass = FALSE;
        while((pLTRD = m_LocalTypeRefDList.POP()))
		{
			if(NULL == FindClass(pLTRD->m_szFullName))
			{
				report->msg("%s: Reference to undefined class '%s' (token 0x%08X)\n",
                    "Error", pLTRD->m_szFullName,pLTRD->m_tok);
				bIsUndefClass = TRUE;
			}
			delete pLTRD;
		}
        if(bIsUndefClass && !OnErrGo) return E_FAIL;
	}
	if(bClock) cMDEmit3 = GetTickCount();

	// Emit class members and globals:
	{
        Class *pSearch;
		int i;
		if(m_fReportProgress)	printf("\nEmitting members:\n");
        for (i=0; (pSearch = m_lstClass.PEEK(i)); i++)
		{
			if(m_fReportProgress)
			{
				if(i == 0)	printf("Global \t");
				else		printf("Class %d\t",i);
			}
			if(!EmitMembers(pSearch))
			{
				if(!OnErrGo) return E_FAIL;
			}
		}
	}
	if(bClock) cMDEmit4 = GetTickCount();

	if(m_MethodImplDList.COUNT())
	{
		if(m_fReportProgress) report->msg("Method Implementations (total): %d\n",m_MethodImplDList.COUNT());
		if(!EmitMethodImpls())
		{
			if(!OnErrGo) return E_FAIL;
		}
	}
	if(bClock) cMDEmitEnd = cRef2DefBegin = GetTickCount();
	// Now, when all items defined in this file are emitted, let's try to resolve member refs to member defs:
	if(m_MemberRefDList.COUNT())
	{
		MemberRefDescriptor*	pMRD;
		mdToken			tkMemberDef = 0;
		int i,j;
		unsigned ulTotal=0, ulDefs=0, ulRefs=0;
		Class	*pSearch;

		if(m_fReportProgress) printf("Resolving member refs: ");
        while((pMRD = m_MemberRefDList.POP()))
		{
			tkMemberDef = 0;
			MethodDescriptor* pListMD;
			mdToken			pMRD_tdClass = pMRD->m_tdClass;
			char*			pMRD_szName = pMRD->m_szName;
			ULONG			pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0);
			PCOR_SIGNATURE	pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL);
			ulTotal++;
			// MemberRef may reference a method or a field
			if((pMRD_pSig==NULL)||(*pMRD_pSig != IMAGE_CEE_CS_CALLCONV_FIELD))
			{
                for (i=0; (pSearch = m_lstClass.PEEK(i)); i++)
				{
					if(pMRD_tdClass != pSearch->m_cl) continue;
                    for(j=0; (pListMD = pSearch->m_MethodDList.PEEK(j)); j++)
					{
						if(pListMD->m_dwCSig  != pMRD_dwCSig)  continue;
						if(memcmp(pListMD->m_pSig,pMRD_pSig,pMRD_dwCSig)) continue;
						if(strcmp(pListMD->m_szName,pMRD_szName)) continue;
						tkMemberDef = pListMD->m_mdMethodTok;
						break;
					}
				}
			}
			if(tkMemberDef == 0)
			{
				if((pMRD_pSig==NULL)||(*pMRD_pSig == IMAGE_CEE_CS_CALLCONV_FIELD))
				{
					FieldDescriptor* pListFD;
                    for (i=0; (pSearch = m_lstClass.PEEK(i)); i++)
					{
						if(pMRD_tdClass != pSearch->m_cl) continue;
                        for(j=0; (pListFD = pSearch->m_FieldDList.PEEK(j)); j++)
						{
							if(pListFD->m_pbsSig)
							{
								if(pListFD->m_pbsSig->length()  != pMRD_dwCSig)  continue;
								if(memcmp(pListFD->m_pbsSig->ptr(),pMRD_pSig,pMRD_dwCSig)) continue;
							}
							else if(pMRD_dwCSig) continue;
							if(strcmp(pListFD->m_szName,pMRD_szName)) continue;
							tkMemberDef = pListFD->m_fdFieldTok;
							break;
						}
					}
				}
			}
			if(tkMemberDef==0)
			{ // could not resolve ref to def, make new ref and leave it this way
                if((pSearch = pMRD->m_pClass))
				{
					mdToken tkRef;
					BinStr* pbs = new BinStr();
					pbs->appendInt8(ELEMENT_TYPE_NAME);
					strcpy((char*)(pbs->getBuff((unsigned int)strlen(pSearch->m_szFQN)+1)),pSearch->m_szFQN);
					if(!ResolveTypeSpecToRef(pbs,&tkRef)) tkRef = mdTokenNil;
					delete pbs;

					if(RidFromToken(tkRef))
					{
						ULONG cTemp = (ULONG)(strlen(pMRD_szName)+1);
						WCHAR* wzMemberName = new WCHAR[cTemp];
						WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzMemberName,cTemp);

						hr = m_pEmitter->DefineMemberRef(tkRef, wzMemberName, pMRD_pSig, 
							pMRD_dwCSig, &tkMemberDef);
						ulRefs++;
						delete [] wzMemberName;
					}
				}
			}
			else ulDefs++;
			if(RidFromToken(tkMemberDef))
			{
				SET_UNALIGNED_VAL32((mdToken *)pMRD->m_ulOffset, tkMemberDef);
				delete pMRD;
			}
			else
			{
				report->msg("Error: unresolved member ref '%s' of class 0x%08X\n",pMRD->m_szName,pMRD->m_tdClass);
				hr = E_FAIL;
				delete pMRD;
				if(!OnErrGo) goto exit;
			}
		}
		if(m_fReportProgress) printf("%d -> %d defs, %d refs\n",ulTotal,ulDefs,ulRefs);
	}
	if(bClock) cRef2DefEnd = GetTickCount();
	// emit manifest info (if any)
	hr = S_OK;
	if(m_pManifest) 
	{
		if (FAILED(hr = m_pManifest->EmitManifest())) goto exit;
	}

	if(g_wzResourceFile)
	    if (FAILED(hr=m_pCeeFileGen->SetResourceFileName(m_pCeeFile, g_wzResourceFile))) goto exit;

	if (FAILED(hr=CreateTLSDirectory())) goto exit;

	if (FAILED(hr=CreateDebugDirectory())) goto exit;
    
    if (FAILED(hr=m_pCeeFileGen->SetOutputFileName(m_pCeeFile, pwzOutputFilename))) goto exit;

		// Reserve a buffer for the meta-data
	DWORD metaDataSize;	
	if (FAILED(hr=m_pEmitter->GetSaveSize(cssAccurate, &metaDataSize))) goto exit;
	BYTE* metaData;
	if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, metaDataSize, sizeof(DWORD), (void**) &metaData))) goto exit; 
	ULONG metaDataOffset;
	if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pILSection, &metaDataOffset))) goto exit;
	metaDataOffset -= metaDataSize;
	// set managed resource entry, if any
	if(m_pManifest && m_pManifest->m_dwMResSizeTotal)
	{
		mresourceSize = m_pManifest->m_dwMResSizeTotal;

		if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, mresourceSize, 
											sizeof(DWORD), (void**) &mresourceData))) goto exit; 
	    if (FAILED(hr=m_pCeeFileGen->SetManifestEntry(m_pCeeFile, mresourceSize, 0))) goto exit;
	}

	if(m_VTFList.COUNT())
	{
		GlobalLabel *pGlobalLabel;
		VTFEntry*	pVTFEntry;

		if(m_pVTable) delete m_pVTable; // can't have both; list takes precedence
		m_pVTable = new BinStr();
		hr = S_OK;
        for(WORD k=0; (pVTFEntry = m_VTFList.POP()); k++)
		{
            if((pGlobalLabel = FindGlobalLabel(pVTFEntry->m_szLabel)))
			{
				MethodDescriptor*	pMD;
				Class* pClass;
				m_pVTable->appendInt32(pGlobalLabel->m_GlobalOffset);
				m_pVTable->appendInt16(pVTFEntry->m_wCount);
				m_pVTable->appendInt16(pVTFEntry->m_wType);
                for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
				{
                    for(WORD j = 0; (pMD = pClass->m_MethodDList.PEEK(j)); j++)
					{
						if(pMD->m_wVTEntry == k+1)
						{
							char*	ptr;
							if(SUCCEEDED(hr = m_pCeeFileGen->ComputeSectionPointer(m_pGlobalDataSection,pGlobalLabel->m_GlobalOffset,&ptr)))
							{
								DWORD dwDelta = (pMD->m_wVTSlot-1)*((pVTFEntry->m_wType & COR_VTABLE_32BIT) ? (DWORD) sizeof(DWORD) : (DWORD) sizeof(__int64));
								ptr += dwDelta;
								mdMethodDef* mptr = (mdMethodDef*)ptr;
								*mptr = pMD->m_mdMethodTok;
								if(pMD->m_dwExportOrdinal != 0xFFFFFFFF)
								{
									EATEntry*	pEATE = new EATEntry;
									pEATE->dwOrdinal = pMD->m_dwExportOrdinal;
									pEATE->szAlias = pMD->m_szExportAlias ? pMD->m_szExportAlias : pMD->m_szName;
									pEATE->dwStubRVA = EmitExportStub(pGlobalLabel->m_GlobalOffset+dwDelta);
									m_EATList.PUSH(pEATE);
								}
							}
							else
								report->msg("Error: Failed to get pointer to label '%s' inVTable fixup\n",pVTFEntry->m_szLabel);
						}
					}
				}
			}
			else
			{
				report->msg("Error: Unresolved label '%s' in VTable fixup\n",pVTFEntry->m_szLabel);
				hr = E_FAIL;
			}
			delete pVTFEntry;
		}
		if(FAILED(hr)) goto exit;
	}
	if(m_pVTable)
	{
		//DWORD *pdw = (DWORD *)m_pVTable->ptr();
		ULONG i, N = m_pVTable->length()/sizeof(DWORD);
		ULONG ulVTableOffset;
		m_pCeeFileGen->GetSectionDataLen (m_pILSection, &ulVTableOffset);
		if (FAILED(hr=m_pCeeFileGen->SetVTableEntry(m_pCeeFile, m_pVTable->length(),(ULONG)(m_pVTable->ptr())))) goto exit;
		for(i = 0; i < N; i+=2)
		{
			m_pCeeFileGen->AddSectionReloc(m_pILSection, 
											ulVTableOffset+(i*sizeof(DWORD)),
											m_pGlobalDataSection, 
											srRelocAbsolute);
		}
	}
	if(m_EATList.COUNT())
	{
		if(FAILED(CreateExportDirectory())) goto exit;
	}
    if (m_fWindowsCE)
    {
        if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, 2, 10))) goto exit;

        if (FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, 0x10000))) goto exit;
    }
	else if(m_dwSubsystem)
	{
        if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, m_dwSubsystem, 4, 0))) goto exit;
	}
	
    if (FAILED(hr=m_pCeeFileGen->ClearComImageFlags(m_pCeeFile, COMIMAGE_FLAGS_ILONLY))) goto exit;
    if (FAILED(hr=m_pCeeFileGen->SetComImageFlags(m_pCeeFile, m_dwComImageFlags & ~COMIMAGE_FLAGS_STRONGNAMESIGNED))) goto exit;

	if(m_dwFileAlignment)
	{
		if(FAILED(hr=m_pCeeFileGen->SetFileAlignment(m_pCeeFile, m_dwFileAlignment))) goto exit;
	}
    if(m_stBaseAddress)
    {
        if(FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, m_stBaseAddress))) goto exit;
    }
		//Compute all the RVAs
	if (FAILED(hr=m_pCeeFileGen->LinkCeeFile(m_pCeeFile))) goto exit;

		// Fix up any fields that have RVA associated with them
	if (m_fHaveFieldsWithRvas) {
		hr = S_OK;
		ULONG dataSectionRVA;
		if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pGlobalDataSection, &dataSectionRVA))) goto exit;
		
		ULONG tlsSectionRVA;
		if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pTLSSection, &tlsSectionRVA))) goto exit;

		FieldDescriptor* pListFD;
		Class* pClass;
        for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
		{
            for(int j=0; (pListFD = pClass->m_FieldDList.PEEK(j)); j++)
			{
				if (pListFD->m_rvaLabel != 0) 
				{
					GlobalLabel *pLabel = FindGlobalLabel(pListFD->m_rvaLabel);
					if (pLabel == 0)
					{
						report->msg("Error:Could not find label '%s' for the field '%s'\n", pListFD->m_rvaLabel, pListFD->m_szName);
						hr = E_FAIL;
						continue;
					}
				
					DWORD rva = pLabel->m_GlobalOffset;
					if (pLabel->m_Section == m_pTLSSection)
						rva += tlsSectionRVA;
					else {
						_ASSERTE(pLabel->m_Section == m_pGlobalDataSection);
						rva += dataSectionRVA;
					}
					if (FAILED(m_pEmitter->SetFieldRVA(pListFD->m_fdFieldTok, rva))) goto exit;
				}
			}
		}
		if (FAILED(hr)) goto exit;
	}

	if(bClock) cFilegenBegin = GetTickCount();
	// actually output the meta-data
    if (FAILED(hr=m_pCeeFileGen->EmitMetaDataAt(m_pCeeFile, m_pEmitter, m_pILSection, metaDataOffset, metaData, metaDataSize))) goto exit;
	// actually output the resources
	if(mresourceSize && mresourceData)
	{
		size_t  i, N = m_pManifest->m_dwMResNum, sizeread, L;
		BYTE	*ptr = (BYTE*)mresourceData;
		BOOL	mrfail = FALSE;
		FILE*	pFile;
		char sz[2048];
		for(i=0; i < N; i++)
		{
			memset(sz,0,2048);
			WszWideCharToMultiByte(CP_ACP,0,m_pManifest->m_wzMResName[i],-1,sz,2047,NULL,NULL);
			L = m_pManifest->m_dwMResSize[i];
			sizeread = 0;
			memcpy(ptr,&L,sizeof(DWORD));
			ptr += sizeof(DWORD);
            if((pFile = fopen(sz,"rb")))
			{
				sizeread = fread((void *)ptr,1,L,pFile);
				fclose(pFile);
				ptr += sizeread;
			}
			else
			{
				report->msg("Error: failed to open mgd resource file '%ls'\n",m_pManifest->m_wzMResName[i]);
				mrfail = TRUE;
			}
			if(sizeread < L)
			{
				report->msg("Error: failed to read expected %d bytes from mgd resource file '%ls'\n",L,m_pManifest->m_wzMResName[i]);
				mrfail = TRUE;
				L -= sizeread;
				memset(ptr,0,L);
				ptr += L;
			}
		}
		if(mrfail) 
		{ 
			hr = E_FAIL;
			goto exit;
		}
	}

	// Generate the file -- moved to main
    //if (FAILED(hr=m_pCeeFileGen->GenerateCeeFile(m_pCeeFile))) goto exit;


    hr = S_OK;

exit:
    return hr;
}