我成功地从C#调用了advapi32的LsaEnumerateAccountRights()。 现在我如何解组它返回的LSA_UNICODE_STRING数组呢?

它是指向LSA_UNICODE_STRING结构数组的指针。 我找到了一些反向的代码,即从C#字符串创建一个LSA_UNICODE_STRING 。 您可以在下面的帮助程序代码部分中看到。

我所做的包括对LsaEnumerateAccountRights()的调用似乎工作得很好。 为数组指针和计数返回合理的值。

我不知道如何处理那些爆炸的字符串。 请帮忙? 好吗?

更新: nobugz的帮助函数在下面的答案中几乎是正确的,你只需UnicodeEncoding.CharSize来划分长度。 多亏了他,我现在可以在数组中看到FIRST字符串。 请参阅下面两个代码部分末尾的更新。

现在,我是如何做地狱世界的指针运算?

更新2.5:查看function代码的答案。 我丢失了旧的“错误”代码。

找到了! 在这篇博文中 。 现在修改后的代码完全有效。 它甚至是64位安全的!

主要代码:

 IntPtr sid = IntPtr.Zero; int sidSize = 0; StringBuilder domainName = new StringBuilder(); int nameSize = 0; int accountType = 0; LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize, domainName, ref nameSize, ref accountType); domainName = new StringBuilder(nameSize); sid = Marshal.AllocHGlobal(sidSize); bool result = LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize, domainName, ref nameSize, ref accountType); myResults.Text += String.Format("LookupAccountName(): Result {0}, SID {1}\n", result, sid); LSA_UNICODE_STRING systemName = string2LSAUS("\\\\" + tbHost.Text); IntPtr policyHandle = IntPtr.Zero; LSA_OBJECT_ATTRIBUTES objAttrs = new LSA_OBJECT_ATTRIBUTES(); uint retVal = LsaOpenPolicy(ref systemName, ref objAttrs, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, out policyHandle); myResults.Text += String.Format("LsaOpenPolicy(): Result {0}, Policy Handle {1}\n", retVal, policyHandle); IntPtr rightsArray = IntPtr.Zero; ulong rightsCount = 0; long lretVal = LsaEnumerateAccountRights(policyHandle, sid, out rightsArray, out rightsCount); retVal = LsaNtStatusToWinError(lretVal); if (retVal != 0) throw new System.ComponentModel.Win32Exception((int)retVal); myResults.Text += String.Format("LsaEnumerateAccountRights(): Result {0}, RightsArray {1}, Count {2}\n", retVal, rightsArray, rightsCount); LSA_UNICODE_STRING myLsaus = new LSA_UNICODE_STRING(); for (ulong i = 0; i < rightsCount; i++) { IntPtr itemAddr = new IntPtr(rightsArray.ToInt64() + (long)(i * (ulong) Marshal.SizeOf(myLsaus))); myLsaus = (WinNetUtils.LSA_UNICODE_STRING)Marshal.PtrToStructure(itemAddr, myLsaus.GetType()); string thisRight = WinNetUtils.LSAUS2string(myLsaus); NonBlockingPrint(wmiResults, "Right #{0}: {1}\n", i+1, thisRight); } LsaClose(policyHandle); 

辅助函数,导入等:

 public const int POLICY_VIEW_LOCAL_INFORMATION = 0x1; public const int POLICY_LOOKUP_NAMES = 0x00000800; [DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)] public static extern UInt32 LsaNtStatusToWinError( long Status); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)] public static extern bool ConvertStringSidToSid( string StringSid, out IntPtr pSid); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)] public static extern bool LookupAccountName( string lpSystemName, string lpAccountName, IntPtr psid, ref int cbsid, StringBuilder domainName, ref int cbdomainLength, ref int use ); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)] public static extern UInt32 LsaOpenPolicy( ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, Int32 DesiredAccess, out IntPtr PolicyHandle ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern long LsaEnumerateAccountRights( IntPtr PolicyHandle, IntPtr AccountSid, out /* LSA_UNICODE_STRING[] */ IntPtr UserRights, out ulong CountOfRights); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern long LsaClose( IntPtr PolicyHandle); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct LSA_UNICODE_STRING { public UInt16 Length; public UInt16 MaximumLength; public IntPtr Buffer; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct LSA_OBJECT_ATTRIBUTES { public IntPtr RootDirectory; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; public LSA_UNICODE_STRING ObjectName; public UInt32 Attributes; public UInt32 Length; } public static LSA_UNICODE_STRING string2LSAUS(string myString) { LSA_UNICODE_STRING retStr = new LSA_UNICODE_STRING(); retStr.Buffer = Marshal.StringToHGlobalUni(myString); retStr.Length = (UInt16)(myString.Length * UnicodeEncoding.CharSize); retStr.MaximumLength = (UInt16)((myString.Length + 1) * UnicodeEncoding.CharSize); return retStr; } public static string LSAUS2string(LSA_UNICODE_STRING lsaus) { char[] cvt = new char[lsaus.Length / UnicodeEncoding.CharSize]; Marshal.Copy(lsaus.Buffer, cvt, 0, lsaus.Length / UnicodeEncoding.CharSize); return new string(cvt); } 

这应该对你有用:

  private static string LSAUS2String(LSA_UNICODE_STRING lsa) { char[] cvt = new char[lsa.Length]; Marshal.Copy(lsa.Buffer, cvt, 0, lsa.Length); return new string(cvt); }