Beispiel #1
0
HRESULT LoadLoaderIntoAppDomain(_AppDomainPtr& pAppDomain, _AssemblyPtr& pLoaderAssembly, bool forceFromBytes)
{
	HRESULT hr;
	
	if (!forceFromBytes)
	{
		// Try regular load first 
		hr = pAppDomain->Load_2(_bstr_t(L"ExcelDna.Loader"), &pLoaderAssembly);
	}

	if (forceFromBytes || FAILED(hr) || pLoaderAssembly == NULL)
	{
		// Now try from resource bytes
		HRSRC hResInfoLoader = FindResource(hModuleCurrent, L"EXCELDNA.LOADER", L"ASSEMBLY");
		if (hResInfoLoader == NULL)
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_MISSINGEXCELDNALOADER, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return E_FAIL;
		}
		HGLOBAL hLoader = LoadResource(hModuleCurrent, hResInfoLoader);
		void* pLoader = LockResource(hLoader);
		ULONG sizeLoader = (ULONG)SizeofResource(hModuleCurrent, hResInfoLoader);
		
		SafeByteArray loaderBytes(pLoader, sizeLoader);

		hr = pAppDomain->Load_3(loaderBytes, &pLoaderAssembly);
		if (FAILED(hr))
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_EXCELDNALOADER, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return E_FAIL;
		}

		if (FAILED(hr))
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_EXCELDNALOADERNAME, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return E_FAIL;
		}
	}
	return S_OK;
}
DWORD load_assembly(BYTE* assemblyData, DWORD assemblySize)
{
	dprintf("[PSH] loading assembly of size %u", assemblySize);
	HRESULT hr = S_OK;
	SAFEARRAY* clrByteArray = NULL;
	SAFEARRAYBOUND bounds[1];
	_AssemblyPtr* loadedAssembly = new _AssemblyPtr();

	bounds[0].cElements = assemblySize;
	bounds[0].lLbound = 0;

	if (gClrAppDomainInterface == NULL)
	{
		dprintf("[PSH] Extension wasn't initialised");
		return ERROR_INVALID_HANDLE;
	}

	do
	{
		clrByteArray = SafeArrayCreate(VT_UI1, 1, bounds);
		if (clrByteArray == NULL)
		{
			dprintf("[PSH] Failed to create a usable safe array");
			hr = (HRESULT)ERROR_OUTOFMEMORY;
			break;
		}

		dprintf("[PSH] Safe array created");
		if (FAILED(hr = SafeArrayLock(clrByteArray)))
		{
			dprintf("[PSH] Safe array lock failed 0x%x", hr);
			break;
		}

		dprintf("[PSH] Copying binary data to target");
		memcpy(clrByteArray->pvData, assemblyData, assemblySize);
		SafeArrayUnlock(clrByteArray);

		if (FAILED(hr = gClrAppDomainInterface->Load_3(clrByteArray, (_Assembly**)loadedAssembly)))
		{
			dprintf("[PSH] Failed to load the assembly 0x%x", hr);
			break;
		}

		dprintf("[PSH] Assembly appears to have been loaded successfully");
		list_add(gLoadedAssemblies, loadedAssembly);
	} while (0);

	if (SUCCEEDED(hr))
	{
		return ERROR_SUCCESS;
	}
	else
	{
		delete loadedAssembly;
	}
	return (DWORD)hr;
}
Beispiel #3
0
HRESULT LoadAppDomain(ICorRuntimeHostPtr pHost, std::wstring addInFullPath, bool createSandboxedAppDomain, bool shadowCopyFiles, _AssemblyPtr& pLoaderAssembly , _AppDomainPtr& pAppDomain, bool& unloadAppDomain)
{
	HRESULT hr;
	std::wstring xllDirectory = addInFullPath;
	RemoveFileSpecFromPath(xllDirectory);
	unloadAppDomain = false;

	if (IsRunningOnCluster())
	{
		// Need to load into default AppDomain due to configuration issues of the cluster host.
		IUnknown *pAppDomainUnk = NULL;
		hr = pHost->CurrentDomain(&pAppDomainUnk);
		if (FAILED(hr) || pAppDomainUnk == NULL)
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_APPDOMAIN, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
		
			return E_FAIL;
		}
		// Assignment does QueryInterface
		pAppDomain = pAppDomainUnk;
		hr = LoadLoaderIntoAppDomain(pAppDomain, pLoaderAssembly, /*forceFromBytes=*/ true);
		if (FAILED(hr))
		{
			// Already showed error message there.
			return E_FAIL;
		}
		// Since we loaded into the default domain, don't unload the AppDomain later.
		unloadAppDomain = false;
		return S_OK;
	}
	// End of RunningOnCluster path.

	// Create and populate AppDomainSetup
	IUnknownPtr pAppDomainSetupUnk;
	hr = pHost->CreateDomainSetup(&pAppDomainSetupUnk);
	if (FAILED(hr) || pAppDomainSetupUnk == NULL)
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPDOMAINSETUP, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return E_FAIL;
	}

	IAppDomainSetupPtr pAppDomainSetup = pAppDomainSetupUnk;
	hr = pAppDomainSetup->put_ApplicationBase(_bstr_t(xllDirectory.c_str()));
	if (FAILED(hr))
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPLICATIONBASE, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return E_FAIL;
	}

	hr = pAppDomainSetup->put_ShadowCopyFiles(_bstr_t(shadowCopyFiles ? L"true" : L"false"));
	if (FAILED(hr))
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_SHADOWCOPYFILES, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return E_FAIL;
	}

	// AppDomainSetup.ApplicationName = "Excel-DNA: c:\MyAddins\MyAddIn.xll";
	_bstr_t appDomainName((std::wstring(L"Excel-DNA: ") + addInFullPath).c_str());
	pAppDomainSetup->put_ApplicationName(appDomainName);


	// Check if a .config file exists next to the .xll as MyAddIn.xll.config. Use it if it exists.
	std::wstring configFileName = addInFullPath + L".config";
	if (FileExists(configFileName.c_str()))
	{
		pAppDomainSetup->put_ConfigurationFile(_bstr_t(configFileName.c_str()));
	}
	else
	{
		// Try to load .config file from resources, store into a temp file
		HRSRC hResConfig = FindResource(hModuleCurrent, L"__MAIN__", L"CONFIG");
		if (hResConfig != NULL)
		{
			HGLOBAL hConfig = LoadResource(hModuleCurrent, hResConfig);
			void* pConfig = LockResource(hConfig);
			DWORD sizeConfig = SizeofResource(hModuleCurrent, hResConfig);

			std::wstring tempConfigFileName;
			hr = CreateTempFile(pConfig, sizeConfig, tempConfigFileName);
			if (SUCCEEDED(hr))
			{
				pAppDomainSetup->put_ConfigurationFile(_bstr_t(tempConfigFileName.c_str()));
			}
			// tempConfigFile will be deleted after the AppDomain has been unloaded.
		}
		else
		{
			// No config file - no problem.
		}
	}

	IUnknown *pAppDomainUnk = NULL;
	hr = pHost->CreateDomainEx(appDomainName, pAppDomainSetupUnk, 0, &pAppDomainUnk);
	if (FAILED(hr) || pAppDomainUnk == NULL)
	{
		ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
					IDS_MSG_BODY_APPDOMAIN, 
					IDS_MSG_FOOTER_UNEXPECTED,
					hr);
		return E_FAIL;
	}

	pAppDomain = pAppDomainUnk;

	hr = LoadLoaderIntoAppDomain(pAppDomain, pLoaderAssembly, /*forceLoadFromBytes=*/ false);
	if (FAILED(hr))
	{
		// Already showed message.
		return E_FAIL;
	}
	
	if (createSandboxedAppDomain)
	{
		_TypePtr pAppDomainHelperType;
		hr = pLoaderAssembly->GetType_2(_bstr_t(L"ExcelDna.Loader.AppDomainHelper"), &pAppDomainHelperType);
		if (FAILED(hr) || pAppDomainHelperType == NULL)
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_XLADDIN, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return E_FAIL;
		}

		_variant_t  sbRetVal;
		_variant_t  sbTarget;
		hr = pAppDomainHelperType->InvokeMember_3(_bstr_t("CreateFullTrustSandbox"), (BindingFlags)(BindingFlags_Static | BindingFlags_Public | BindingFlags_InvokeMethod), NULL, sbTarget, NULL, &sbRetVal);
		if (FAILED(hr))
		{
			ShowMessage(IDS_MSG_HEADER_APPDOMAIN, 
						IDS_MSG_BODY_XLADDININIT, 
						IDS_MSG_FOOTER_UNEXPECTED,
						hr);
			return E_FAIL;
		}

		_AppDomainPtr pSandbox(sbRetVal.punkVal);
		if (!IsEqualObject(pAppDomain, pSandbox))
		{
			// Unload the loader AppDomain.
			pLoaderAssembly.Release();
			pHost->UnloadDomain(pAppDomain);
			pAppDomain.Release();
			pAppDomain = pSandbox;

			//  Sort out the LoaderAssembly in the sandbox.
			hr = LoadLoaderIntoAppDomain(pAppDomain, pLoaderAssembly, /*forceLoadFromBytes=*/ false);
			if (FAILED(hr))
			{
				// Already showed message.
				return E_FAIL;
			}
		}
	}
	unloadAppDomain = true;
	return S_OK;
}