Асинхронные подключаемые протоколы - PullRequest
3 голосов
/ 06 января 2010

Используя this в качестве ссылки, я пытаюсь создать асинхронный подключаемый протокол, который только временно доступен для моего приложения (и не зарегистрирован для всей системы). Я использую CoInternetGetSession и затем звоню RegisterNameSpace, чтобы сделать это. Однако, когда я звоню RegisterNameSpace, я получаю исключение AccessViolation: Attempting to read or write protected memory.

Есть идеи, что происходит?

Мой код выглядит так:

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000001-0000-0000-C000-000000000046")]
[ComVisible(true)]
public interface IClassFactory
{
    void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
    void LockServer(bool fLock);
}

/* Custom class to act as a class factory that create's an instance of the protocol */
[Guid("0b9c4422-2b6e-4c2d-91b0-9016053ab1b1")]
[ComVisible(true),ClassInterface(ClassInterfaceType.AutoDispatch)]
public class PluggableProtocolFactory : IClassFactory
{
    public Type AppType;
    public PluggableProtocolFactory(Type t)
    {
        this.AppType = t;
    }
    public void CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
    {
        riid = ProtocolSupport.GetGuid(this.AppType);
        IInternetProtocol p = Activator.CreateInstance(this.AppType) as IInternetProtocol;
        ppvObject = Marshal.GetComInterfaceForObject(p, typeof(IInternetProtocol));
    }

    public void LockServer(bool fLock)
    {
        var b = fLock;
    }

}

[ComVisible(true)]
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b")]
public interface IInternetSession
{
    void CreateBinding(); // Not Implemented
    void GetCache(); // Not Implemented
    void GetSessionOption(); // Not Implemented
    void RegisterMimeFilter([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
    void RegisterNameSpace([MarshalAs(UnmanagedType.Interface)] IClassFactory pCF, ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
                           UInt32 cPatterns, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPWStr)] string[] ppwzPatterns, UInt32 dwReserved);
    void SetCache(); // Not Implemented
    void SetSessionOption(); // Not Implemented
    void UnregisterMimeFilter(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzType);
    void UnregisterNameSpace(IClassFactory pCF, [MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol);
}

[ComVisible(false)] public interface IComRegister
{
    void Register(Type t);
    void Unregister(Type t);
}

[ComVisible(false), AttributeUsage(AttributeTargets.Class, AllowMultiple=true) ] 
public class AsyncProtocolAttribute : Attribute, IComRegister
{
    public string Name;
    public string Description;

    [DllImport("urlmon.dll",PreserveSig=false)]
    public static extern int CoInternetGetSession(UInt32 dwSessionMode /* = 0 */, ref IInternetSession ppIInternetSession, UInt32 dwReserved /* = 0 */);

    public void Register(Type t)
    {
        IInternetSession session = null;
        CoInternetGetSession(0, ref session, 0);
        Guid g = new Guid("79EAC9E4-BAF9-11CE-8C82-00AA004BA90B");
        session.RegisterNameSpace(new PluggableProtocolFactory(t), ref g, this.Name, 0, null, 0);

    }

Метод CreateInstance в PluggableProtocolFactory никогда не вызывается. (Точка останова там никогда не попадает), поэтому внутри метода RegisterNameSpace происходит что-то еще.

Я попытался запустить как администратор, так и обычный пользователь. Одна и та же ошибка в обоих случаях.

Ответы [ 2 ]

0 голосов
/ 09 января 2010

ОК, разобрался: объявление интерфейса IInternetSession было неверным:

Вот лучший, который я взял из моноблога :

[ComVisible(true), Guid("79eac9e7-baf9-11ce-8c82-00aa004ba90b"),InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSession
{
    [PreserveSig]
    int RegisterNameSpace(
        [In] IClassFactory classFactory,
        [In] ref Guid rclsid,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pwzProtocol,
        [In]
            int cPatterns,
        [In, MarshalAs(UnmanagedType.LPWStr)]
            string ppwzPatterns,
        [In] int dwReserved);

    [PreserveSig]
    int UnregisterNameSpace(
        [In] IClassFactory classFactory,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pszProtocol);

    int Bogus1();

    int Bogus2();

    int Bogus3();

    int Bogus4();

    int Bogus5();
}
0 голосов
/ 06 января 2010

Вы вызываете конструктор вашего PluggableProtocolFactory в своем методе RegisterNameSpace, но не метод CreateInstance. Я думаю, что в этом и заключается ваша проблема, никогда не создается экземпляр IInternetProtocol для передачи вашему методу.

...