У меня есть код, который использует методы из библиотеки SSPI (security.dll) через P / Invoke, которая отлично работала на всех протестированных платформах (Windows XP, Windows Server 2003 x86 и x64), однако мы находимся в процессемиграции на Windows Server 2008 и обнаружил, что вызовы P / Invoke приводят к сбою процесса.
Я собрал следующий код воспроизведения:
using System;
using System.Runtime.InteropServices;
namespace TestPInvoke
{
class Program
{
static void Main(string[] args)
{
try
{
// The following code works on all platforms tested (Windows Server 2003 x86/x64, Windows Server 2008 x64, Windows XP, Windows Vista)
var table1 = (SecurityFunctionTable)Marshal.PtrToStructure(InitReturningPtr(), typeof(SecurityFunctionTable));
Console.WriteLine(table1.dwVersion);
Console.WriteLine(table1.EnumerateSecurityPackages.ToInt64().ToString("x16"));
Console.ReadLine();
// This call crashes only on Windows Server 2008 and Windows Vista (but works fine on XP and 2K3)
var table2 = InitReturningClass();
Console.WriteLine(table2.dwVersion);
Console.WriteLine(table2.EnumerateSecurityPackages.ToInt64().ToString("x16"));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
Console.ReadLine();
}
[DllImport("security.dll", EntryPoint = "InitSecurityInterfaceW")]
public static extern IntPtr InitReturningPtr();
[DllImport("security.dll", EntryPoint = "InitSecurityInterfaceW")]
public static extern SecurityFunctionTable InitReturningClass();
[StructLayout(LayoutKind.Sequential)]
public class SecurityFunctionTable
{
public uint dwVersion;
public IntPtr EnumerateSecurityPackages;
public IntPtr QueryCredentialsAttributes;
// ...omitted for brevity
}
}
}
Проблема не изолированак этой конкретной DLL или функции, но любой вызов P / Invoke, который я пробовал, где возвращаемое значение нативной функции является указателем на структуру, которая неявно маршалируется в класс, демонстрирует проблему.
Так какУ меня есть функциональный обходной путь (с помощью Marshal.PtrToStructure), это не является серьезной проблемой, но мне любопытно узнать, почему он работает без (очевидных) проблем в XP и 2k3, но не в Vista и 2k8, и есть ли какие-либоспособ исправить метод, возвращающий класс, чтобы избежать более уродливого явного маршаллинга.