Hosting the CLR Question

G

Guest

In hosting the CLR I would like to create a new AppDomain the will be created with some "Evidence" that I supply it. I want my evidence to contain two class objects from the System.Security.Policy namespace. These are the Url and Zone classes. I can successfully create the Url class as it takes a string with the desired UrlName as the single argument to constructor. When I try to create the Zone class, which takes a System.Security.SecurityZone enum as the single arguement to it's constructor, I get an HRESULT error 0x80131513 (MissingMethodException). I'm passing the enum as a VT_I4 type variant. Would anyone know why this doesn't work? My simplified code example to just create the Url and Zone classes is included here below
Thanks
Bob Elwar

#include "stdafx.h
/
#import <mscorlib.tlb> raw_interfaces_only raw_interfaces_only high_property_prefixes("_get","_put","_putref") rename("ReportEvent", "_ReportEvent"
using namespace mscorlib
/
int main(int argc, char* argv[]

HRESULT hr
LPWSTR psClrVer = NULL; // E.g., L"v1.1.4322
LPWSTR pszWKSorSVR = L"svr"; // L"wks
ICorRuntimeHost *pHost = NULL
/
hr = CorBindToRuntimeEx(psClrVer,pszWKSorSVR,STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN| STARTUP_CONCURRENT_GC,CLSID_CorRuntimeHost,IID_ICorRuntimeHost,(void **)&pHost)
assert(SUCCEEDED(hr));
/
hr = pHost->Start()
assert(SUCCEEDED(hr))
/
IUnknown *punkAppDomain = NULL
hr = pHost->GetDefaultDomain(&punkAppDomain)
assert(SUCCEEDED(hr));
/
_AppDomain *pDefaultAppDomain = NULL
hr = punkAppDomain->QueryInterface(__uuidof(_AppDomain),(void**) &pDefaultAppDomain)
assert(SUCCEEDED(hr));
// Strings for CreateInstance_
BSTR asmUrlName = SysAllocString(L"mscorlib")
BSTR typeUrlName = SysAllocString(L"System.Security.Policy.Url")
// Create a variant BSTR to hold the Url name strin
VARIANT vUrlParam
VariantInit(&vUrlParam)
vUrlParam.vt = VT_BSTR
vUrlParam.bstrVal = SysAllocString(L"http://www.MyDomain.com/")
// Create a 1D array with one string elemen
SAFEARRAY* pUrlSAFEARRAY = SafeArrayCreateVector(VT_VARIANT, 0, 1)
LONG lngUrlIndex = 0
hr = SafeArrayPutElement(pUrlSAFEARRAY, &lngUrlIndex, &vUrlParam)
assert(SUCCEEDED(hr));
// Create an instance of Url using a parameterized constructo
_ObjectHandle* pUrlObjHandle
hr = pDefaultAppDomain->CreateInstance_3(asmUrlName, typeUrlName, VARIANT_TRUE, BindingFlags_Default, NULL, pUrlSAFEARRAY, NULL, NULL, NULL, &pUrlObjHandle)
assert(SUCCEEDED(hr));
// Strings for CreateInstance_
BSTR asmZoneName = SysAllocString(L"mscorlib")
BSTR typeZoneName = SysAllocString(L"System.Security.Policy.Zone")
// Create a variant I4 to hold the Zone Enu
VARIANT vZoneParam
VariantInit(&vZoneParam)
vZoneParam.vt = VT_I4
vZoneParam.lVal = SecurityZone_Internet
// Create a 1D array with one string elemen
SAFEARRAY* pZoneSAFEARRAY = SafeArrayCreateVector(VT_VARIANT, 0, 1)
LONG lngZoneIndex = 0
hr = SafeArrayPutElement(pZoneSAFEARRAY, &lngZoneIndex, &vZoneParam)
assert(SUCCEEDED(hr));
// Create an instance of Url using a parameterized constructo
_ObjectHandle* pZoneObjHandle
hr = pDefaultAppDomain->CreateInstance_3(asmZoneName, typeZoneName, VARIANT_TRUE, BindingFlags_Default, NULL, pZoneSAFEARRAY, NULL, NULL, NULL, &pZoneObjHandle)
assert(SUCCEEDED(hr));
/
return 0
 
T

Tian Min Huang

Hello Bob,

Thanks for your post. I am checking your code and will update you with my
information.

Have a nice day!

Regards,

HuangTM
Microsoft Online Partner Support
MCSE/MCSD

Get Secure! -- www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
T

Tian Min Huang

Hello,

I reproduced the problem on my side, and will need more time to investigate
it. In the meantime, I want to propose a different way to do this that I
believe that you will benefit in the long run. Creating evidence and
associating it with a domain is much, much easier to do in managed code
instead of trying to accomplish this in unmanaged code using COM interop.
Most of the evidence objects weren't designed to be accessed from COM so I
wouldn't be surprised if you run into more issues down the road (for
example, you'll find that they aren't derived from interfaces and they
aren't COMVisible).

What most people have been doing in these situations is to write a small
assembly that gets loaded into the default domain that does the real work
of creating both the evidence and the new domain. This small assembly is
then accessed through COM interop and the hosting api's. In your case you
could create a managed class (say DomainManager) that took the URL and
Security Zone, created the evidence and then created the new domain. You'd
create an instance of your class in the default domain from unmanaged code
using pDefaultAppDomain->CreateInstance and call a method to get the real
work done.

Specifically, do something like the following: (mostly in pseudo code)

1. Create a managed assembly with your helper class. Derive your class
from an interface to make it easier to access from COM:

namespace TimsHostRuntime
{
public interface IDomainManager
{
_AppDomain CreateDomainWithEvidence(string url,
SecurityZone¡­..)
}

public class DomainManager :IDomainManager
{
_AppDomain CreateDomainWithEvidence(string url,
SecurityZone¡­..)
{
// create the evidence and call AppDomain.CreateDomain
}
}
}

2. Run TlbExp on your assembly to get a typelib you can use from the
unmanaged side.

3. #import your type lib into your C++ file

#import <TimsHostRuntime.tlb>

using namespace TimsHostRuntime;

4. Create an instance of your type in the default domain:

// Load the DomainManager into the default domain
_ObjectHandle *pObjHandle = NULL;
hr = pDefaultDomain->CreateInstance(_bstr_t("TimsHostRuntime,
Version=5.0.0.0, PublicKeyToken=1124c916f503f9a4, culture=neutral"),

_bstr_t("TimsHostRuntime.DomainManager "),
&pObjHandle);
assert(SUCCEEDED(hr));
assert(pObjHandle);


// pObjHandle comes back in a variant. We need to pull the real pointer
to the
// object out.
IDomainManager *pDomainManager = NULL;
VARIANT v;

VariantInit(&v);
hr = pObjHandle->Unwrap(&v);
assert(v.pdispVal);

hr = v.pdispVal->QueryInterface(__uuidof(IDomainManager), (void**)
&pDomainManager);
assert(SUCCEEDED(hr));

5. Call your object through interop passing in the stuff to create the
evidence

hr = pDomainManager->CreateDomainWithEvidence(¡°www.blaa.com¡±, ¡­.);

You can either send an _AppDomain pointer back from
CreateDomainWithEvidence so you can interact directly with the domain or
you can just add more methods to your managed class as an indirection.

Another reason I'm suggesting this approach is that this is the direction
the hosting api's are heading in the next release of the CLR.

I hope this helps,

Regards,

HuangTM
Microsoft Online Partner Support
MCSE/MCSD

Get Secure! -- www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Tian,
Thanks for looking into this and verifing that it wasn't working. Yes I can use your alternative suggestion. As I was learning to host the CLR I have written a test program that exercises all the APIs and creating a domain using Evidence was the last one I wanted to get working (all the others seem to work as documented). If you do figure out how to get this working I would still be interested.

Also, Thanks for the heads up on the direction the hosting APIs are going to go. I'll be getting a copy of Whidbey on March 2 at Developer Days and was going to port my test program(a good reason for me to have the test program) as one of the first activities.
Thanks,
Bob Elward
 
T

Tian Min Huang

Hello Bob,

I discussed this issue with our Developer Team, and we'd like to share the
following information with you:

Based on our research, the error 0x80131513 is caused by the fact that the
enum is coming through the interop layer as an Int32 so reflection doesn't
know it's supposed to call the constructor that takes an enum. Said another
way, there's no way to represent an enum of a specific type in a VARIANT.
As you've seen, the best you can do is pass the value as an int.

I am afraid that there is not a good method to get this to work from
unmanaged code. As stated in my previous reply, I strongly recommend you
write a managed shim to do this.

Please feel free to let me know if you have any problems or concerns.

Regards,

HuangTM
Microsoft Online Partner Support
MCSE/MCSD

Get Secure! -- www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top