2010-01-21 7 views
5

यह LSA_UNICODE_STRING संरचनाओं की एक सरणी के लिए एक सूचक है। मुझे कुछ कोड मिला जो उलटा करता है, यानी, एक सी # स्ट्रिंग से LSA_UNICODE_STRING बनाएं। आप नीचे सहायक सहायक अनुभाग में देख सकते हैं।मैंने सी # से सफलतापूर्वक advapi32 के LsaEnumerateAccountRights() को बुलाया। अब मैं LSA_UNICODE_STRING की सरणी को कैसे अनमशल कर सकता हूं?

मेरे पास क्या है और LsaEnumerateAccountRights() पर कॉल सहित, ठीक काम करने लगता है। सरणी मान सरणी सूचक के लिए और गिनती के लिए वापस आते हैं।

मुझे पर उन विस्फोटक तारों को कैसे प्राप्त किया जाए, इस नुकसान के कारण मुझे नुकसान हुआ है। कृपया मदद करें? मान जाओ ना?

अद्यतन: नीचे दिए गए उत्तर में nobugz का सहायक कार्य सबसे सही है, आपको केवल लंबाई को UnicodeEncoding.CharSize से विभाजित करना होगा। उनके लिए धन्यवाद, अब मैं सरणी में पहली स्ट्रिंग देख सकता हूं। नीचे दोनों कोड खंडों के अंत में अद्यतन देखें।

अब, netherworld मैं पॉइंटर अंकगणित कैसे करता हूं?

अद्यतन 2.5: कार्य कोड के लिए उत्तर देखें। मैंने पुराना, "गलत" कोड खो दिया।

+0

संबंधित: https://stefsewell.com/2010/10/10/accessing-the-lsa- से प्रबंधित-कोड/और: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.interop/2004-11/0394.html –

उत्तर

9

यह मिला! this blog post में। अब नीचे संशोधित कोड पूरी तरह से काम करता है। यह 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); 
} 
+0

आपको अपना उत्तर प्रश्न से बाहर खींचना चाहिए और इसे यहां रखना चाहिए। –

+0

आपको यह सुनिश्चित करने की ज़रूरत है कि आप हैंडल को बंद करने के लिए LsaClose() को कॉल कर रहे हैं। –

+0

हो गया और किया गया। दुर्भाग्यवश, मैंने मूल गैर-निष्पादन कोड खो दिया, इसलिए सवाल अधूरा दिखता है। – JCCyC

2

यह आपके लिए काम करना चाहिए:

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

ऐसा लगता है कि मुझे उपयोग करना होगा सरणी के प्रत्येक सदस्य पर मार्शल.प्रेटोस्ट्रक्चर(), लेकिन मैं सरणी को कैसे पार करूं? सूचक अंकगणित ??? – JCCyC

+0

PtrToStructure? नहीं, यह चार की सरणी है। मार्शल.कॉपी इसे IntPtr से char [] तक कॉपी करता है। फिर यह आसान है। –

+0

क्षमा करें, मैं उच्च स्तरीय सरणी, LSA_UNICODE_STRING की सरणी के बारे में बात कर रहा था। मुझे अब यह काम मिल गया है (ऊपर देखें)। सहायता के लिए धन्यवाद! – JCCyC