@msdn=http://search.microsoft.com/search/results.aspx?qu=$$$ @pinvoke=http://pinvoke.net/$$$.htm Summary: Retrieve Local Policy Information for a Local or Remote Host !!!!C# Signature: [DllImport("Advapi32.dll")] private static extern uint LsaQueryInformationPolicy(IntPtr PolicyHandle, uint InformationClass, out IntPtr Buffer); !!!!VB Signature: Declare Function LsaQueryInformationPolicy Lib "Advapi32.dll" (ByVal PolicyHandle As IntPtr, ByVal InformationClass As UInteger, ByRef Buffer As IntPtr) As UInteger !!!!User-Defined Types: None. !!!!Alternative Managed API: Do you know one? Please contribute it! !!!!Notes: With all the different information you can get with just one command; this one sure is difficult. Very, very little documentation on this because Microsoft probably doesn't want easy access to these. My company has allowed me to contribute my findings as long as I mention it. We are Digital Boundary Group, based in London, Ontario, Canada, and we do penetration testing. Please visit us at http://digitalboundary.net I will be allowed to continue my contributions as long as my company does not lose credit for its contributions. !!!!Tips & Tricks: Please add some! !!!!Sample Code: public int GetRemoteAuditPolicy(ref string[,] Policies) { Policies = new string[9, 2] { { "System", "" }, { "Logon", "" }, { "Object Access", "" }, { "Privilige Use", "" }, { "Detailed Tracking", "" }, { "Policy Change", "" }, { "Account Management", "" }, { "Directory Service Access", "" }, { "Account Logon", "" } }; //Everything from here until the "Good Stuff", was copied from this site byte[] Sid = null; uint cbSid = 0; StringBuilder referencedDomainName = new StringBuilder(); uint cchReferencedDomainName = (uint)referencedDomainName.Capacity; SID_NAME_USE sidUse; int err = 0; if (!LookupAccountName(this.ResourceName, this.UserName, Sid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out sidUse)) { err = Marshal.GetLastWin32Error(); if (err == ERROR_INSUFFICIENT_BUFFER || err == ERROR_INVALID_FLAGS) { Sid = new byte[cbSid]; referencedDomainName.EnsureCapacity((int)cchReferencedDomainName); err = 0; if (!LookupAccountName(this.ResourceName, this.UserName, Sid, ref cbSid, referencedDomainName, ref cchReferencedDomainName, out sidUse)) err = Marshal.GetLastWin32Error(); //throw error here //return custom error constant } } LSA_UNICODE_STRING aSystemName = new LSA_UNICODE_STRING(); uint aAccess = (uint)( LSA_AccessPolicy.POLICY_AUDIT_LOG_ADMIN | LSA_AccessPolicy.POLICY_CREATE_ACCOUNT | LSA_AccessPolicy.POLICY_CREATE_PRIVILEGE | LSA_AccessPolicy.POLICY_CREATE_SECRET | LSA_AccessPolicy.POLICY_GET_PRIVATE_INFORMATION | LSA_AccessPolicy.POLICY_LOOKUP_NAMES | LSA_AccessPolicy.POLICY_NOTIFICATION | LSA_AccessPolicy.POLICY_SERVER_ADMIN | LSA_AccessPolicy.POLICY_SET_AUDIT_REQUIREMENTS | LSA_AccessPolicy.POLICY_SET_DEFAULT_QUOTA_LIMITS | LSA_AccessPolicy.POLICY_TRUST_ADMIN | LSA_AccessPolicy.POLICY_VIEW_AUDIT_INFORMATION | LSA_AccessPolicy.POLICY_VIEW_LOCAL_INFORMATION ); IntPtr aPolicyHandle = IntPtr.Zero; uint infoclass = (uint)POLICY_INFORMATION_CLASS.PolicyAuditEventsInformation; IntPtr bufptr = IntPtr.Zero; LSA_OBJECT_ATTRIBUTES aObjectAttributes = new LSA_OBJECT_ATTRIBUTES(); aObjectAttributes.Length = 0; aObjectAttributes.RootDirectory = IntPtr.Zero; aObjectAttributes.Attributes = 0; aObjectAttributes.SecurityDescriptor = IntPtr.Zero; aObjectAttributes.SecurityQualityOfService = IntPtr.Zero; aSystemName.SetTo(this.ResourceName); uint aOpenPolicyResult = LsaOpenPolicy(ref aSystemName, ref aObjectAttributes, aAccess, out aPolicyHandle); //Here's the "Good Stuff" folks //This example gets Audit Policy information uint retval = LsaQueryInformationPolicy(aPolicyHandle, infoclass, out bufptr); //do what you want with the retval, this is a pretty lazy example _POLICY_AUDIT_EVENTS_INFO pevents; //Marshal the pointer to structure; pretty standard stuff pevents = (_POLICY_AUDIT_EVENTS_INFO)Marshal.PtrToStructure(bufptr, typeof(_POLICY_AUDIT_EVENTS_INFO)); //Microsoft states that this could be an arbitrary number of elements because they may expand upon this in later Windows versions int[] policy_values = new int[pevents.MaximumAuditEventCount]; //pevents.MaximumAuditEventCount gives you the number of elements, take this number of elements and Marshall copy the array Marshal.Copy(pevents.EventAuditingOptions, policy_values, 0, pevents.MaximumAuditEventCount); //Only take the lowest array count int max_policies = Policies.GetLength(0); max_policies = max_policies > pevents.MaximumAuditEventCount ? pevents.MaximumAuditEventCount : max_policies; //Grade 10 programming class for (int x = 0; x < max_policies; x++) { switch (policy_values[x]) { case 0: Policies[x, 1] = "None"; break; case 1: Policies[x, 1] = "Success"; break; case 2: Policies[x, 1] = "Failure"; break; case 3: Policies[x, 1] = "Success/Failure"; break; } } return 0; } You'll need: enum POLICY_INFORMATION_CLASS { PolicyAuditLogInformation = 1, PolicyAuditEventsInformation, PolicyPrimaryDomainInformation, PolicyPdAccountInformation, PolicyAccountDomainInformation, PolicyLsaServerRoleInformation, PolicyReplicaSourceInformation, PolicyDefaultQuotaInformation, PolicyModificationInformation, PolicyAuditFullSetInformation, PolicyAuditFullQueryInformation, PolicyDnsDomainInformation } public enum LSA_AccessPolicy : long { POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L, POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L, POLICY_GET_PRIVATE_INFORMATION = 0x00000004L, POLICY_TRUST_ADMIN = 0x00000008L, POLICY_CREATE_ACCOUNT = 0x00000010L, POLICY_CREATE_SECRET = 0x00000020L, POLICY_CREATE_PRIVILEGE = 0x00000040L, POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L, POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L, POLICY_AUDIT_LOG_ADMIN = 0x00000200L, POLICY_SERVER_ADMIN = 0x00000400L, POLICY_LOOKUP_NAMES = 0x00000800L, POLICY_NOTIFICATION = 0x00001000L } public struct _POLICY_AUDIT_EVENTS_INFO { public bool AuditingMode; public IntPtr EventAuditingOptions; public Int32 MaximumAuditEventCount; } Microsoft also has an enumeration for the different policies; but like I said above, they strongly caution you to not fix the number of elements in the array because that can and probably will change. Use my array at the top of the function for now. Happy coding! http://digitalboundary.net Documentation: LsaQueryInformationPolicy@msdn on MSDN
Edit netapi32.LsaQuery...
You do not have permission to change this page. If you feel this is in error, please send feedback with the contact link on the main page.