マネージド コードでの実装を作成しました。しかし、ありがとう、あなたの実装に基づいて、これらがどのように機能するかを理解することができました。
using System;
using System.Runtime.InteropServices;
using System.Net;
namespace PM.Runtime.InteropServices {
[Flags]
public enum CLSCTX : uint {
INPROC_SERVER = 0x1,
INPROC_HANDLER = 0x2,
LOCAL_SERVER = 0x4,
INPROC_SERVER16 = 0x8,
REMOTE_SERVER = 0x10,
INPROC_HANDLER16 = 0x20,
RESERVED1 = 0x40,
RESERVED2 = 0x80,
RESERVED3 = 0x100,
RESERVED4 = 0x200,
NO_CODE_DOWNLOAD = 0x400,
RESERVED5 = 0x800,
NO_CUSTOM_MARSHAL = 0x1000,
ENABLE_CODE_DOWNLOAD = 0x2000,
NO_FAILURE_LOG = 0x4000,
DISABLE_AAA = 0x8000,
ENABLE_AAA = 0x10000,
FROM_DEFAULT_CONTEXT = 0x20000,
ACTIVATE_32_BIT_SERVER = 0x40000,
ACTIVATE_64_BIT_SERVER = 0x80000,
ENABLE_CLOAKING = 0x100000,
APPCONTAINER = 0x400000,
ACTIVATE_AAA_AS_IU = 0x800000,
PS_DLL = 0x80000000,
INPROC = INPROC_SERVER | INPROC_HANDLER,
SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
ALL = SERVER | INPROC_HANDLER
}
#region Native Pointers
public abstract class PtrHandle : IDisposable {
~PtrHandle() { Dispose(false); }
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
public abstract IntPtr Handle { get; }
public static implicit operator IntPtr(PtrHandle managedPtr) {
return managedPtr != null ? managedPtr.Handle : IntPtr.Zero;
}
}
public class PinnedObject<T> : PtrHandle {
private GCHandle _handle;
public PinnedObject(ref T obj) {
_handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
}
protected override void Dispose(bool disposing) {
_handle.Free();
}
public override IntPtr Handle {
get { return _handle.AddrOfPinnedObject(); }
}
}
public class GlobalPtr : PtrHandle {
private IntPtr _handle = IntPtr.Zero;
protected GlobalPtr() {}
protected override void Dispose(bool disposing) {
Free(ref _handle); // always release unmanaged memory...
}
protected void SetHandle(IntPtr handle) {
Free(ref _handle);
_handle = handle;
}
// get handle back with: Marshal.PtrToStructure<T>(nativePtr.Handle, T value);
protected void SetHandle<T>(ref T value, bool deleteOld = false) where T: struct {
Free(ref _handle);
_handle = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)));
try {
Marshal.StructureToPtr(value, _handle, deleteOld);
} catch {
Free(ref _handle);
throw;
}
}
public sealed override IntPtr Handle {
get { return _handle; }
}
public static void Free<T>(ref T handle) where T: GlobalPtr {
if (handle != null) {
handle.Dispose();
handle = null;
}
}
public static void Free(ref IntPtr handle) {
if (handle != IntPtr.Zero) {
Marshal.FreeHGlobal(handle);
handle = IntPtr.Zero;
}
}
}
public class LPAStr : GlobalPtr {
public LPAStr(string value) {
SetHandle(Marshal.StringToHGlobalAnsi(value));
}
}
public class LPWStr : GlobalPtr {
public LPWStr(string value) {
SetHandle(Marshal.StringToHGlobalUni(value));
}
}
public class PinnedStruct<T> : GlobalPtr where T: struct {
public PinnedStruct(ref T value) {
SetHandle<T>(ref value);
}
}
#endregion
public class WINNTAuthnInfo {
public NetworkCredential Credential;
public uint AuthnLevel;
public uint ImpersonationLevel;
public WINNTAuthnInfo(NetworkCredential Credential,
uint AuthnLevel = ComUtils.RPC_C_AUTHN_LEVEL_DEFAULT,
uint ImpersonationLevel = ComUtils.RPC_C_IMP_LEVEL_IMPERSONATE) {
this.Credential = Credential;
this.AuthnLevel = AuthnLevel;
this.ImpersonationLevel = ImpersonationLevel;
}
public static explicit operator WINNTAuthnInfo(NetworkCredential credential) {
return new WINNTAuthnInfo(credential);
}
}
public static class ComUtils {
private static class Guids {
public const string IID_IUnknown = "00000000-0000-0000-C000-000000000046";
public const string IID_IDispatch = "00020400-0000-0000-C000-000000000046";
}
// IID constants...
public static readonly Guid IID_IUnknown = new Guid(Guids.IID_IUnknown);
public static readonly Guid IID_IDispatch = new Guid(Guids.IID_IDispatch);
#region Constants
// HResult codes...
public const int S_OK = 0;
public const int E_ABORT = -2147467260;
public const int E_ACCESSDENIED = -2147024891;
public const int E_FAIL = -2147467259;
public const int E_HANDLE = -2147024890;
public const int E_INVALIDARG = -2147024809;
public const int E_NOINTERFACE = -2147467262;
public const int E_NOTIMPL = -2147467263;
public const int E_OUTOFMEMORY = -2147024882;
public const int E_POINTER = -2147467261;
public const int E_UNEXPECTED = -2147418113;
public const int REGDB_E_CLASSNOTREG
= -2147221164;
// Some private values...
private const int SEC_WINNT_AUTH_IDENTITY_ANSI = 1;
private const int SEC_WINNT_AUTH_IDENTITY_UNICODE = 2;
public const uint RPC_C_AUTHN_NONE = 0;
public const uint RPC_C_AUTHN_DCE_PRIVATE = 1;
public const uint RPC_C_AUTHN_DCE_PUBLIC = 2;
public const uint RPC_C_AUTHN_DEC_PUBLIC = 4;
public const uint RPC_C_AUTHN_GSS_NEGOTIATE = 9;
public const uint RPC_C_AUTHN_WINNT = 10;
public const uint RPC_C_AUTHN_GSS_SCHANNEL = 14;
public const uint RPC_C_AUTHN_GSS_KERBEROS = 16;
public const uint RPC_C_AUTHN_DPA = 17;
public const uint RPC_C_AUTHN_MSN = 18;
public const uint RPC_C_AUTHN_KERNEL = 20;
public const uint RPC_C_AUTHN_DIGEST = 21;
public const uint RPC_C_AUTHN_NEGO_EXTENDER = 30;
public const uint RPC_C_AUTHN_PKU2U = 31;
public const uint RPC_C_AUTHN_MQ = 100;
public const uint RPC_C_AUTHN_DEFAULT = 0xFFFFFFFF;
public const uint RPC_C_AUTHZ_NONE = 0;
public const uint RPC_C_AUTHZ_NAME = 1;
public const uint RPC_C_AUTHZ_DCE = 2;
public const uint RPC_C_AUTHZ_DEFAULT = 0xFFFFFFFF;
public const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0;
public const uint RPC_C_AUTHN_LEVEL_NONE = 1;
public const uint RPC_C_AUTHN_LEVEL_CONNECT = 2;
public const uint RPC_C_AUTHN_LEVEL_CALL = 3;
public const uint RPC_C_AUTHN_LEVEL_PKT = 4;
public const uint RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5;
public const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6;
public const uint RPC_C_IMP_LEVEL_DEFAULT = 0;
public const uint RPC_C_IMP_LEVEL_ANONYMOUS = 1;
public const uint RPC_C_IMP_LEVEL_IDENTIFY = 2;
public const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3;
public const uint RPC_C_IMP_LEVEL_DELEGATE = 4;
public const uint EOAC_NONE = 0;
#endregion
#region Internal unmanaged pointers...
private class WINNTAuthidEntityPtr : GlobalPtr {
public LPWStr _hdomain = null;
public LPWStr _huser = null;
public LPWStr _hpass = null;
public static WINNTAuthidEntityPtr Create(NetworkCredential credential) {
return credential != null
? new WINNTAuthidEntityPtr(credential) : null;
}
public WINNTAuthidEntityPtr(NetworkCredential credential) {
if (credential == null)
throw new ArgumentNullException("Credential");
try {
string pasword = credential.Password;
var authIdentity = new NativeMethods.COAUTHIDENTITY() {
User = (_huser = new LPWStr(credential.UserName)),
Domain = (_hdomain = new LPWStr(credential.Domain)),
Password = (_hpass = new LPWStr(pasword)),
UserLength = (credential.UserName == null ? 0 : credential.UserName.Length),
DomainLength = (credential.Domain == null ? 0 : credential.Domain .Length),
PasswordLength = (credential.Password == null ? 0 : pasword .Length),
Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE
};
SetHandle<NativeMethods.COAUTHIDENTITY>(ref authIdentity);
} catch {
Free<LPWStr>(ref _hpass);
Free<LPWStr>(ref _hdomain);
Free<LPWStr>(ref _huser);
throw;
}
}
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
Free<LPWStr>(ref _hpass);
Free<LPWStr>(ref _hdomain);
Free<LPWStr>(ref _huser);
}
}
private class WINNTAuthInfoPtr : GlobalPtr {
private WINNTAuthidEntityPtr _identity = null;
public static WINNTAuthInfoPtr Create(WINNTAuthnInfo authInfo) {
return authInfo != null
? new WINNTAuthInfoPtr(authInfo.Credential, authInfo.AuthnLevel, authInfo.ImpersonationLevel) : null;
}
public WINNTAuthInfoPtr(NetworkCredential credential = null,
uint AuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT,
uint ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE) {
_identity = WINNTAuthidEntityPtr.Create(credential);
try {
var authInfo = new NativeMethods.COAUTHINFO() {
dwAuthnSvc = RPC_C_AUTHN_WINNT,
dwAuthzSvc = RPC_C_AUTHZ_NONE,
pwszServerPrincName = IntPtr.Zero,
dwAuthnLevel = AuthnLevel,
dwImpersonationLevel = ImpersonationLevel,
pAuthIdentityData = _identity,
dwCapabilities = EOAC_NONE
};
SetHandle<NativeMethods.COAUTHINFO>(ref authInfo);
} catch {
Free<WINNTAuthidEntityPtr>(ref _identity);
throw;
}
}
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
Free<WINNTAuthidEntityPtr>(ref _identity);
}
internal IntPtr Identity { get { return _identity; } }
}
#endregion
public static object CreateInstance(
string progId,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.SERVER) {
return CreateInstanceEx(
NativeMethods.CLSIDFromProgID(progId), IID_IUnknown,
pUnkOuter, dwClsContext);
}
public static object CreateInstance2(
string progId, Guid intfId,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.SERVER) {
return CreateInstanceEx(
NativeMethods.CLSIDFromProgID(progId), intfId,
pUnkOuter, dwClsContext);
}
public static object CreateRemoteInstance(string remoteServer,
string progId, WINNTAuthnInfo authInfo = null,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.REMOTE_SERVER) {
return CreateRemoteInstanceEx(remoteServer,
NativeMethods.CLSIDFromProgID(progId), IID_IUnknown, authInfo,
pUnkOuter, dwClsContext);
}
public static object CreateRemoteInstance2(string remoteServer,
string progId, Guid intfId, WINNTAuthnInfo authInfo = null,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.REMOTE_SERVER) {
return CreateRemoteInstanceEx(remoteServer,
NativeMethods.CLSIDFromProgID(progId), intfId, authInfo,
pUnkOuter, dwClsContext);
}
public static object CreateInstanceEx(
Guid classId, Guid intfId,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.SERVER) {
return NativeMethods.CoCreateInstance(
classId, pUnkOuter, dwClsContext, intfId);
}
public static object CreateRemoteInstanceEx(string remoteServer,
Guid classId, Guid intfId, WINNTAuthnInfo authInfo = null,
object pUnkOuter = null, CLSCTX dwClsContext = CLSCTX.REMOTE_SERVER) {
using (var authInfoPtr = WINNTAuthInfoPtr.Create(authInfo))
using (var intfIdPtr = new PinnedObject<Guid>(ref intfId)) {
NativeMethods.COSERVERINFO si = new NativeMethods.COSERVERINFO() {
dwReserved1 = 0,
pwszName = remoteServer,
pAuthInfo = authInfoPtr,
dwReserved2 = 0
};
NativeMethods.MULTI_QI[] moi = new NativeMethods.MULTI_QI[1];
moi[0] = new NativeMethods.MULTI_QI() {
pIID = intfIdPtr,
pItf = null,
hr = 0
};
NativeMethods.CoCreateInstanceEx(classId, pUnkOuter, dwClsContext, ref si, 1, moi);
if (moi[0].hr < 0)
Marshal.ThrowExceptionForHR(moi[0].hr);
if (moi[0].pItf == null)
Marshal.ThrowExceptionForHR(E_POINTER);
if (authInfoPtr != null && authInfo != null)
SetSecurity(moi[0].pItf, authInfoPtr.Identity, authInfo.AuthnLevel, authInfo.ImpersonationLevel);
return moi[0].pItf;
}
}
private static object SetSecurity(object objDCOM,
IntPtr authidEntity,
uint AuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT,
uint ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE) {
//IntPtr ptrInterface = Marshal.GetIUnknownForObject(objDCOM);
NativeMethods.CoSetProxyBlanket(
objDCOM, // pProxy
RPC_C_AUTHN_WINNT, // dwAuthnSvc
RPC_C_AUTHZ_NONE, // dwAuthzSvc
IntPtr.Zero, // pServerPrincName
AuthnLevel, // dwAuthnLevel
ImpersonationLevel, // dwImpLevel
authidEntity, // pAuthInfo
EOAC_NONE); // dwCapabilities
return objDCOM;
}
public static object SetSecurity(object objDCOM, WINNTAuthnInfo authInfo) {
if (authInfo == null)
throw new ArgumentNullException("Authentication-Info");
using (var authidEntity = WINNTAuthidEntityPtr.Create(authInfo.Credential))
return SetSecurity(objDCOM,
authidEntity, authInfo.AuthnLevel, authInfo.ImpersonationLevel);
}
public static object SetSecurity(object objDCOM,
NetworkCredential credential,
uint AuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT,
uint ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE) {
using (var authidEntity = WINNTAuthidEntityPtr.Create(credential))
return SetSecurity(objDCOM,
authidEntity, AuthnLevel, ImpersonationLevel);
}
private static class NativeMethods {
public static Guid CLSIDFromProgID(string progId) {
Guid classId;
int hr = NativeMethods.CLSIDFromProgID(progId, out classId);
if (hr < 0)
Marshal.ThrowExceptionForHR(hr);
return classId;
}
[DllImport("ole32.dll")]
public static extern int ProgIDFromCLSID(
[In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)]out string lplpszProgID);
[DllImport("ole32.dll")]
public static extern int CLSIDFromProgID(
[MarshalAs(UnmanagedType.LPWStr)]string lpszProgID, out Guid pclsid);
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
[StructLayout(LayoutKind.Sequential)]
public struct COAUTHIDENTITY {
//[MarshalAs(UnmanagedType.LPWStr)]
public IntPtr User;
public int UserLength;
//[MarshalAs(UnmanagedType.LPWStr)]
public IntPtr Domain;
public int DomainLength;
//[MarshalAs(UnmanagedType.LPWStr)]
public IntPtr Password;
public int PasswordLength;
public int Flags;
};
[StructLayout(LayoutKind.Sequential)]
public struct COAUTHINFO {
public uint dwAuthnSvc;
public uint dwAuthzSvc;
//[MarshalAs(UnmanagedType.LPWStr)]
public IntPtr pwszServerPrincName;
public uint dwAuthnLevel;
public uint dwImpersonationLevel;
public IntPtr pAuthIdentityData;
public uint dwCapabilities;
}
[StructLayout(LayoutKind.Sequential)]
public struct COSERVERINFO {
public uint dwReserved1;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszName;
public IntPtr pAuthInfo;
public uint dwReserved2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MULTI_QI {
public IntPtr pIID;
[MarshalAs(UnmanagedType.Interface)] public object pItf;
public int hr;
}
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern void CoCreateInstanceEx(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsCtx,
[In]ref COSERVERINFO pServerInfo,
uint cmq,
[In, Out] MULTI_QI[] pResults);
[DllImport("Ole32.dll", PreserveSig = false)]
public static extern void CoSetProxyBlanket(
[MarshalAs(UnmanagedType.Interface)]
object pProxy, // IntPtr pProxy,
uint dwAuthnSvc,
uint dwAuthzSvc,
IntPtr pServerPrincName,
uint dwAuthLevel,
uint dwImpLevel,
IntPtr pAuthInfo,
uint dwCapabilities);
}
}
}