2011-05-09 59 views
1

我試圖包裹找到Secur32.dll的這是下面聲明EnumerateSecurityPackages功能:C#的P/Invoke找到Secur32.dll問題

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

任何想法我做錯了什麼?

回答

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 
1

您對SecPkgInfo的定義不正確,C的ULONG!= C#的ulong。你還需要非常清楚地指定如何通過元帥編組姓名和評論

+0

我切換ULONG爲int,這似乎仍然工作正常。我還在名稱和註釋中添加了以下內容:[MarshalAs(UnmanagedType.LPStr)],我仍然得到一個AccessViolationException「嘗試讀取或寫入受保護的內存,這通常表示其他內存已損壞。」 – chotchki 2011-05-09 17:45:29

+0

您需要檢查EnumerateSecurityPackages的語義 - 是否期望Name和Comment已指向現有緩衝區?誰將分配內存?此外,你想要編組爲LPWStr。 – 2011-05-09 18:37:10

+0

ULONG = uint32不是uint64。 – Joshua 2011-05-09 20:05:46