//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
//
#include "common.h"
#include "reflectclasswriter.h"
// Forward declaration.
STDAPI GetMetaDataInternalInterfaceFromPublic(
IUnknown *pv, // [IN] Given interface.
REFIID riid, // [IN] desired interface
void **ppv); // [OUT] returned interface
//******************************************************
//*
//* constructor for RefClassWriter
//*
//******************************************************
HRESULT RefClassWriter::Init(ICeeGen *pCeeGen, IUnknown *pUnk, LPCWSTR szName)
{
CONTRACT(HRESULT) {
NOTHROW;
GC_NOTRIGGER;
// we know that the com implementation is ours so we use mode-any to simplify
// having to switch mode
MODE_ANY;
INJECT_FAULT(CONTRACT_RETURN(E_OUTOFMEMORY));
PRECONDITION(CheckPointer(pCeeGen));
PRECONDITION(CheckPointer(pUnk));
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_emitter) : TRUE);
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_importer) : TRUE);
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_pEmitHelper) : TRUE);
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_internalimport) : TRUE);
}
CONTRACT_END;
// Initialize the Import and Emitter interfaces
m_emitter = NULL;
m_importer = NULL;
m_internalimport = NULL;
m_pCeeFileGen = NULL;
m_ceeFile = NULL;
m_ulResourceSize = 0;
m_tkFile = mdFileNil;
m_pCeeGen = pCeeGen;
pCeeGen->AddRef();
// Get the interfaces
HRESULT hr = pUnk->QueryInterface(IID_IMetaDataEmit2, (void**)&m_emitter);
if (FAILED(hr))
RETURN(hr);
hr = pUnk->QueryInterface(IID_IMetaDataImport, (void**)&m_importer);
if (FAILED(hr))
RETURN(hr);
hr = pUnk->QueryInterface(IID_IMetaDataEmitHelper, (void**)&m_pEmitHelper);
if (FAILED(hr))
RETURN(hr);
hr = GetMetaDataInternalInterfaceFromPublic(pUnk, IID_IMDInternalImport, (void**)&m_internalimport);
if (FAILED(hr))
RETURN(hr);
// We will need to set this at some point.
hr = m_emitter->SetModuleProps(szName);
if (FAILED(hr))
RETURN(hr);
RETURN(S_OK);
}
//******************************************************
//*
//* destructor for RefClassWriter
//*
//******************************************************
RefClassWriter::~RefClassWriter()
{
CONTRACTL {
NOTHROW;
GC_TRIGGERS;
// we know that the com implementation is ours so we use mode-any to simplify
// having to switch mode
MODE_ANY;
FORBID_FAULT;
}
CONTRACTL_END;
if (m_emitter) {
m_emitter->Release();
}
if (m_importer) {
m_importer->Release();
}
if (m_pEmitHelper) {
m_pEmitHelper->Release();
}
if (m_internalimport) {
m_internalimport->Release();
}
if (m_pCeeGen) {
m_pCeeGen->Release();
m_pCeeGen = NULL;
}
if (m_pOnDiskEmitter) {
m_pOnDiskEmitter->Release();
m_pOnDiskEmitter = NULL;
}
#ifndef FEATURE_CORECLR
DestroyCeeFileGen();
#endif // FEATURE_CORECLR
}
#ifndef FEATURE_CORECLR
#include
// Loads mscorpe.dll (uses shim hosting API)
HRESULT
LoadMscorpeDll(HMODULE * phModule)
{
// Load SxS version of mscorpe.dll (i.e. mscorpehost.dll) and initialize it
return g_pCLRRuntime->LoadLibrary(W("mscorpe.dll"), phModule);
}
// Wrapper for mscorpe.dll calls
typedef MscorpeSxSWrapper MscorpeSxS;
//******************************************************
//*
//* Make sure that CeeFileGen for this module is created for emitting to disk
//*
//******************************************************
HRESULT
RefClassWriter::EnsureCeeFileGenCreated(
DWORD corhFlags,
DWORD peFlags)
{
CONTRACT(HRESULT) {
NOTHROW;
GC_TRIGGERS;
// we know that the com implementation is ours so we use mode-any to simplify
// having to switch mode
MODE_ANY;
INJECT_FAULT(CONTRACT_RETURN(E_OUTOFMEMORY));
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_pCeeFileGen) : (int)(m_pCeeFileGen == NULL));
POSTCONDITION(SUCCEEDED(RETVAL) ? CheckPointer(m_ceeFile) : (int)(m_pCeeFileGen == NULL));
}
CONTRACT_END;
HRESULT hr = NOERROR;
if (m_pCeeFileGen == NULL)
{
EX_TRY
{
IfFailGo(MscorpeSxS::CreateICeeFileGen(&m_pCeeFileGen));
IfFailGo(m_pCeeFileGen->CreateCeeFileFromICeeGen(m_pCeeGen, &m_ceeFile, peFlags));
IfFailGo(m_pCeeFileGen->ClearComImageFlags(m_ceeFile, COMIMAGE_FLAGS_ILONLY));
IfFailGo(m_pCeeFileGen->SetComImageFlags(m_ceeFile, corhFlags));
ErrExit:
;
}
EX_CATCH
{
hr = GET_EXCEPTION()->GetHR();
}
EX_END_CATCH(SwallowAllExceptions);
if (FAILED(hr))
{
DestroyCeeFileGen();
}
}
RETURN(hr);
} // RefClassWriter::EnsureCeeFileGenCreated
//******************************************************
//*
//* Destroy the instance of CeeFileGen that we created
//*
//******************************************************
HRESULT RefClassWriter::DestroyCeeFileGen()
{
CONTRACT(HRESULT) {
NOTHROW;
GC_TRIGGERS;
// we know that the com implementation is ours so we use mode-any to simplify
// having to switch mode
MODE_ANY;
FORBID_FAULT;
POSTCONDITION(m_pCeeFileGen == NULL);
POSTCONDITION(m_ceeFile == NULL);
}
CONTRACT_END;
HRESULT hr = NOERROR;
if (m_pCeeFileGen != NULL)
{
//Cleanup the HCEEFILE.
if (m_ceeFile != NULL)
{
hr = m_pCeeFileGen->DestroyCeeFile(&m_ceeFile);
_ASSERTE_MSG(SUCCEEDED(hr), "Destory CeeFile");
m_ceeFile = NULL;
}
//Cleanup the ICeeFileGen.
{
CONTRACT_VIOLATION(ThrowsViolation);
// code:EnsureCeeFileGenCreated already loaded the DLL
_ASSERTE(MscorpeSxS::Debug_IsLoaded());
hr = MscorpeSxS::DestroyICeeFileGen(&m_pCeeFileGen);
}
_ASSERTE_MSG(SUCCEEDED(hr), "Destroy ICeeFileGen");
m_pCeeFileGen = NULL;
}
RETURN(hr);
} // RefClassWriter::DestroyCeeFileGen
#endif //!FEATURE_CORECLR