I'm attempting to write a couple of NAnt tasks for interacting with Microsoft Virtual Server 2005 R2 SP1, and I've lifted the code found on "Virtual PC Guy's WebLog", in the "Controlling Virtual Server through PowerShell" post.
It doesn't work: I always get a failure when calling CreateVirtualMachine:
System.Runtime.InteropServices.COMException (0x80070542): Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)
at Microsoft.VirtualServer.Interop.VMVirtualServerClass.CreateVirtualMachine(String configurationName, String configurationPath)
My code is as follows:
var virtualServer = new VMVirtualServerClass();
SetSecurity(virtualServer);
var virtualMachine = virtualServer.CreateVirtualMachine("TEST",
@"D:\Virtual Server\TEST.vmc");
...where SetSecurity is defined as follows:
private static void SetSecurity(object dcomObject)
{
IntPtr pProxy = Marshal.GetIUnknownForObject(dcomObject);
int hr = CoSetProxyBlanket(pProxy,
RPC_C_AUTHN_DEFAULT,
RPC_C_AUTHZ_DEFAULT,
IntPtr.Zero,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
IntPtr.Zero,
EOAC_DYNAMIC_CLOAKING);
Marshal.ThrowExceptionForHR(hr);
}
private const uint RPC_C_AUTHN_NONE = 0;
private const uint RPC_C_AUTHN_WINNT = 10;
private const uint RPC_C_AUTHN_DEFAULT = 0xFFFFFFFF;
private const uint RPC_C_AUTHZ_NONE = 0;
private const uint RPC_C_AUTHZ_DEFAULT = 0xFFFFFFFF;
private const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0;
private const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6;
private const uint RPC_C_IMP_LEVEL_IDENTIFY = 2;
private const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3;
private const uint EOAC_NONE = 0;
private const uint EOAC_DYNAMIC_CLOAKING = 0x40;
private const uint EOAC_DEFAULT = 0x0800;
[DllImport("Ole32.dll")]
public static extern int CoSetProxyBlanket(IntPtr pProxy,
UInt32 dwAuthnSvc,
UInt32 dwAuthzSvc,
IntPtr pServerPrincName,
UInt32 dwAuthnLevel,
UInt32 dwImpLevel,
IntPtr pAuthInfo,
UInt32 dwCapabilities);
If I write a standalone program and add a call to CoInitializeSecurity
, then it works. However, I don't want a standalone program -- I want a set of NAnt tasks (so a DLL), and I don't want to call CoInitializeSecurity
, because there's no way of guaranteeing that some other NAnt task won't have called it already.
Has anyone got this working?