Ah, I'm an idiot. CoInitializeSecurity is per-process, not per thread.

I think this problem is related to the one described at 
http://lists.ironpython.com/pipermail/users-ironpython.com/2008-April/006941.html.
 If that's so, it suggests that loading the assembly manually with 
Assembly.Load instead of "require" - being sure to do whatever it takes to 
avoid triggering the AssemblyResolve event - might fix the problem.

Do you need to be in the MTA apartment? If so, you'd also need to create a new 
MTA thread or you'd need to start ir.exe with "-X:MTA".

From: ironruby-core-boun...@rubyforge.org 
[mailto:ironruby-core-boun...@rubyforge.org] On Behalf Of Orion Edwards
Sent: Wednesday, August 12, 2009 8:20 PM
To: ironruby-core@rubyforge.org
Subject: Re: [Ironruby-core] COM security question

Ack. I've worked around the problem by creating a custom version of ir.exe 
which calls CoInitializeSecurity.

It would be great if there were a less hacky way of doing this (that I wouldn't 
have to re-do when ironruby 1.0 comes out), but yeah :-(

Here's the code

namespace sec_ir
{
    class CoInitializeRubyConsoleHost : ConsoleHost
    {
        [RubyStackTraceHidden, MTAThread]
        static int Main( string[] args )
        {
            ComHelpers.CoInitializeSecurity();

            SetHome();
            return new CoInitializeRubyConsoleHost().Run(args);
        }

        // --------------------------------------------------------------------

        protected override CommandLine CreateCommandLine()
        {
            return new RubyCommandLine();
        }

        protected override Microsoft.Scripting.Hosting.LanguageSetup 
CreateLanguageSetup()
        {
            return Ruby.CreateRubySetup();
        }

        protected override OptionsParser CreateOptionsParser()
        {
            return new RubyOptionsParser();
        }

        protected override Type Provider
        {
            get
            {
                return typeof(RubyContext);
            }
        }

        // --------------------------------------------------------------------

        static void SetHome()
        {
            try
            {
                var platform = PlatformAdaptationLayer.Default;
                var homeDirectory = RubyUtils.GetHomeDirectory(platform);
                platform.SetEnvironmentVariable("HOME", homeDirectory);
            }
            catch( SecurityException exception )
            {
                if( exception.PermissionType != typeof(EnvironmentPermission) )
                    throw;
            }
        }
    }
}

static class ComHelpers
{
    /// <summary>
    /// Call CoInitializeSecurity with dwImpLevel set to Impersonate.
    /// </summary>
    public static void CoInitializeSecurity()
    {
        CoInitializeSecurity(IntPtr.Zero,
            -1,
            IntPtr.Zero,
            IntPtr.Zero,
            (uint)RpcAuthnLevel.PktPrivacy,
            (uint)RpcImpLevel.Impersonate,
            IntPtr.Zero,
            (uint)EoAuthnCap.DynamicCloaking,
            IntPtr.Zero);
    }

    /// <summary>
    /// Define RPC_C_AUTHN_LEVEL_ constants
    /// </summary>
    enum RpcAuthnLevel
    {
        Default = 0,
        None,
        Connect,
        Call,
        Pkt,
        PktIntegrity,
        PktPrivacy
    }

    /// <summary>
    /// Define RPC_C_IMP_LEVEL_ constants
    /// </summary>
    enum RpcImpLevel
    {
        Default = 0,
        Anonymous,
        Identify,
        Impersonate,
        Delegate
    }

    /// <summary>
    /// Define EOAC_ constants
    /// </summary>
    enum EoAuthnCap
    {
        None = 0x0000,
        MutualAuth = 0x0001,
        StaticCloaking = 0x0020,
        DynamicCloaking = 0x0040,
        AnyAuthority = 0x0080,
        MakeFullSIC = 0x0100,
        Default = 0x0800,
        SecureRefs = 0x0002,
        AccessControl = 0x0004,
        AppID = 0x0008,
        Dynamic = 0x0010,
        RequireFullSIC = 0x0200,
        AutoImpersonate = 0x0400,
        NoCustomMarshal = 0x2000,
        DisableAAA = 0x1000
    }

    // Create the call with PreserveSig:=FALSE so the COM InterOp
    // layer will perform the error checking and throw an
    // exception instead of returning an HRESULT.
    //
    [DllImport("Ole32.dll",
       ExactSpelling = true,
       EntryPoint = "CoInitializeSecurity",
       CallingConvention = CallingConvention.StdCall,
       SetLastError = false,
       PreserveSig = false)]
    static extern void CoInitializeSecurity(
        IntPtr pVoid,
        int cAuthSvc,
        IntPtr asAuthSvc,
        IntPtr pReserved1,
        uint dwAuthnLevel,
        uint dwImpLevel,
        IntPtr pAuthList,
        uint dwCapabilities,
        IntPtr pReserved3 );
}

_______________________________________________
Ironruby-core mailing list
Ironruby-core@rubyforge.org
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to