2010-01-21 8 views
5

Es ist ein Zeiger auf ein Array von LSA_UNICODE_STRING Strukturen. Ich habe einen Code gefunden, der die Umkehrung ausführt, d. H., Er erzeugt eine LSA_UNICODE_STRING aus einer C# -Zeichenfolge. Sie können das im folgenden Hilfsprogramm sehen.Ich rief advapi32 LsaEnumerateAccountRights() erfolgreich von C#. Wie entmare ich nun das Array von LSA_UNICODE_STRING, das es zurückgibt?

Was ich habe bis einschließlich Anruf LsaEnumerateAccountRights() scheint gut zu funktionieren. Für den Array-Zeiger und für die Zählung werden sinnvolle Werte zurückgegeben.

Ich bin ratlos, wie man bei diese gestrandeten Saiten bekommen. Hilfe bitte? Schön bitte?

UPDATE: nobugz Helferfunktion in seiner Antwort unten ist fast richtig, Sie müssen nur die Länge durch UnicodeEncoding.CharSize teilen. Dank ihm kann ich jetzt die erste Zeichenfolge im Array sehen. Sehen Sie sich die Aktualisierungen am Ende der beiden folgenden Code-Abschnitte an.

Nun, wie die Unterwelt mache ich Zeigerarithmetik?

UPDATE 2.5: Siehe Antwort für den funktionierenden Code. Ich habe den alten, "falschen" Code verloren.

+0

Verwandte: https://stefsewell.com/2010/10/10/accessing-the-lsa- from-managed-code/Und: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.interop/2004-11/0394.html –

Antwort

9

es gefunden! In this blog post. Jetzt funktioniert der geänderte Code vollständig. Es ist sogar 64-Bit sicher!

Der Hauptcode:

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

Die Helferfunktionen, Importe usw.:

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); 
} 
+0

Sie sollten Ihre Antwort aus der Frage ziehen und sie hier platzieren. –

+0

Sie müssen auch sicherstellen, dass Sie LsaClose() aufrufen, um den Handle zu schließen. –

+0

Fertig und fertig. Leider habe ich den ursprünglichen nicht funktionierenden Code verloren, daher scheint die Frage unvollständig zu sein. – JCCyC

2

Dies sollte für Sie arbeiten:

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); 
    } 
+0

Es scheint, ich muss verwenden Marshal.PtrToStructure() für jedes Mitglied des Arrays, aber wie durchquere ich das Array? Zeigerarithmetik ??? – JCCyC

+0

PtrToStruktur? Nein, es ist eine Reihe von Char. Marshal.Copy kopiert es vom IntPtr in char []. Dann ist es einfach. –

+0

Entschuldigung, ich sprach über das übergeordnete Array, das Array von LSA_UNICODE_STRING. Ich habe es jetzt funktioniert (siehe oben). Danke für die Hilfe! – JCCyC