C#p /调用Secur32.dll问题

时间:2011-05-09 17:31:00

标签: c# pinvoke sspi

我正在尝试包装下面声明的Secur32.dll的EnumerateSecurityPackages函数:

SECURITY_STATUS SEC_Entry EnumerateSecurityPackages(
  __in  PULONG pcPackages,
  __in  PSecPkgInfo *ppPackageInfo
);

我有以下C#代码,但在尝试运行时遇到AccessViolationException。在调试器中,pcPackages变量确实设置正确,但我认为我对SecPkgInfos数组做错了。

[StructLayout(LayoutKind.Sequential)]
public struct SecPkgInfo
{
    public ulong fCapabilities;
    public ushort wVersion;
    public ushort wRPCID;
    public ulong cbMaxToken;
    public string Name;
    public string Comment;
}

[DllImport("Secur32.dll")]
public extern static int EnumerateSecurityPackages(
    ref ulong pcPackages,
    ref SecPkgInfo[] ppPackageInfo
);

///Calling code
ulong count = 0;
SecPkgInfo[] buffer = new SecPkgInfo[256];
EnumerateSecurityPackages(ref count, ref buffer);

任何想法我做错了什么?

2 个答案:

答案 0 :(得分:1)

您对SecPkgInfo的定义不正确,C是ULONG!= C#的ulong。您还需要非常清楚地指定如何通过MarshalAs编组名称和注释

答案 1 :(得分:1)

试试这段代码,它是从VB.Net(我的母语)转换而来,但在C#中运行正常。只需致电Call_EnumerateSecurityPackages(),它就会为您返回一个列表。

    public static List<SecPkgInfo> Call_EnumerateSecurityPackages()
    {
        //Will hold the number of security packages found
        UInt32 count = 0;

        //Will hold a pointer to our array
        IntPtr SourcePoint = IntPtr.Zero;

        //Call function
        int MSG = EnumerateSecurityPackages(ref count, ref SourcePoint);
        //See if there was an error
        if (MSG == 0)
        {
            //Create a copy of our pointer so that we can clear it later
            IntPtr ArrayPtr = new IntPtr(SourcePoint.ToInt32());
            //The type of our structure
            Type T = typeof(SecPkgInfo);
            //The size of our structure
            int ObjSize = Marshal.SizeOf(T);
            //We'll store our information in a standard list object
            List<SecPkgInfo> SecPackages = new List<SecPkgInfo>();

            //Create a loop and increment our pointer by the size of the SecPkgInfo structure, effectively walking the array
            for (ulong I = 0; I <= (count - 1); I++)
            {
                //This converts the current bytes at the pointer to the given structure
                SecPackages.Add((SecPkgInfo)Marshal.PtrToStructure(ArrayPtr, T));

                //Increment our pointer by the size of the structure
                ArrayPtr = IntPtr.Add(ArrayPtr, ObjSize);
            }

            //Cleanup our pointer
            MSG = FreeContextBuffer(ref SourcePoint);

            //Make sure cleanup worked
            if (MSG == 0)
            {
                //Return our values
                return SecPackages;
            }
            else
            {
                //Do something better with the error code here
                throw new ApplicationException("Error cleaning up pointer");
            }
        }
        else
        {
            //Do something better with the error code here
            throw new ApplicationException("Error calling native function");
        }

    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SecPkgInfo
    {
        //ulong is 32 bit so we need to use a 32 bit int
        public UInt32 fCapabilities;
        //ushort is 16 bit 
        public UInt16 wVersion;
        public UInt16 wRPCID;
        public UInt32 cbMaxToken;
        [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
        public string Name;
        [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
        public string Comment;
    }

    [DllImport("Secur32.dll")]
    public static extern int EnumerateSecurityPackages(ref UInt32 pcPackages, ref IntPtr ppPackageInfo);

    [DllImport("Secur32.dll")]
    public static extern int FreeContextBuffer(ref IntPtr pvContextBuffer);

以后使用,这是VB版本:

Public Shared Function Call_EnumerateSecurityPackages() As List(Of SecPkgInfo)
    ''//Will hold the number of security packages found
    Dim count As UInt32 = 0

    ''//Will hold a pointer to our array
    Dim SourcePoint As IntPtr

    ''//Call function
    Dim MSG = EnumerateSecurityPackages(count, SourcePoint)
    ''//See if there was an error
    If MSG = 0 Then
        ''//Create a copy of our pointer so that we can clear it later
        Dim ArrayPtr As New IntPtr(SourcePoint.ToInt32())
        ''//The type of our structure
        Dim T = GetType(SecPkgInfo)
        ''//The size of our structure
        Dim ObjSize = Marshal.SizeOf(T)
        ''//We will store our information in a standard list object
        Dim SecPackages As New List(Of SecPkgInfo)

        ''//Create a loop and increment our pointer by the size of the SecPkgInfo structure, effectively walking the array
        For I = 0 To (count - 1)
            ''//This converts the current bytes at the pointer to the given structure
            SecPackages.Add(CType(Marshal.PtrToStructure(ArrayPtr, T), SecPkgInfo))
            ''//Increment our pointer by the size of the structure
            ArrayPtr = IntPtr.Add(ArrayPtr, ObjSize)
        Next

        ''//Cleanup our pointer
        MSG = FreeContextBuffer(SourcePoint)

        ''//Make sure cleanup worked
        If MSG = 0 Then
            ''//Return our values
            Return SecPackages
        Else
            ''//Do something better with the error code here
            Throw New ApplicationException("Error cleaning up pointer")
        End If
    Else
        ''//Do something better with the error code here
        Throw New ApplicationException("Error calling native function")
    End If

End Function

<StructLayout(LayoutKind.Sequential)>
Public Structure SecPkgInfo
    Public fCapabilities As UInt32 ''//ulong is 32 bit so we need to use a 32 bit int
    Public wVersion As UInt16 ''//ushort is 16 bit 
    Public wRPCID As UInt16
    Public cbMaxToken As UInt32
    <MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)> Public Name As String
    <MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)> Public Comment As String
End Structure

<DllImport("Secur32.dll")>
Public Shared Function EnumerateSecurityPackages(ByRef pcPackages As UInt32, ByRef ppPackageInfo As IntPtr) As Integer
End Function

<DllImport("Secur32.dll")>
Public Shared Function FreeContextBuffer(ByRef pvContextBuffer As IntPtr) As Integer
End Function