C# p/invoke Secur32.dll 问题

发布于 2024-11-05 16:11:21 字数 962 浏览 0 评论 0原文

我正在尝试包装 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);

有什么想法我做错了吗?

I'm trying to wrap the Secur32.dll's EnumerateSecurityPackages function which is declared below:

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

I have the following C# code, but I get an AccessViolationException when I try to run it. In the debugger the pcPackages variable does get set correctly, but I think I'm doing something wrong with the array of 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);

Any ideas what I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

°如果伤别离去 2024-11-12 16:11:21

尝试一下这段代码,它是从 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

Try this code, its converted from VB.Net (my native language) but runs fine for me in C#. Just call Call_EnumerateSecurityPackages() and it will return a list for you.

    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);

And for future use, here's the VB version:

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
蓝天 2024-11-12 16:11:21

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

Your definition of SecPkgInfo is incorrect, C's ULONG != C#'s ulong. You also need to very clearly specify how to marshal Name and Comment via MarshalAs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文