/// <summary> /// Determine the source of a user or group. Either local, Active Directory, /// or Azure AD. /// </summary> /// <param name="sre"> /// A <see cref="SamRidEnumeration"/> object identifying the user or group. /// </param> /// <returns> /// One of the <see cref="PrincipalSource"/> enumerations identifying the /// source of the object. /// </returns> private PrincipalSource? GetPrincipalSource(SamRidEnumeration sre) { return GetPrincipalSource(RidToSid(sre.domainHandle, sre.RelativeId)); }
/// <summary> /// Create a populated LocalGroup object from a SamRidEnumeration object, /// using an already-opened SAM alias handle. /// </summary> /// <param name="sre"> /// A <see cref="SamRidEnumeration"/> object containing minimal information /// about a local group. /// </param> /// <param name="aliasHandle"> /// Handle to an open SAM alias. /// </param> /// <returns> /// A LocalGroup object, populated with group information. /// </returns> private LocalGroup MakeLocalGroupObject(SamRidEnumeration sre, IntPtr aliasHandle) { IntPtr buffer = IntPtr.Zero; UInt32 status = 0; try { ALIAS_GENERAL_INFORMATION generalInfo; status = SamApi.SamQueryInformationAlias(aliasHandle, ALIAS_INFORMATION_CLASS.AliasGeneralInformation, out buffer); ThrowOnFailure(status); generalInfo = ClrFacade.PtrToStructure<ALIAS_GENERAL_INFORMATION>(buffer); LocalGroup group = new LocalGroup() { PrincipalSource = GetPrincipalSource(sre), SID = RidToSid(sre.domainHandle, sre.RelativeId), Name = generalInfo.Name.ToString(), Description = generalInfo.AdminComment.ToString() }; return group; } finally { if (buffer != IntPtr.Zero) status = SamApi.SamFreeMemory(buffer); } }
/// <summary> /// Create a populated LocalUser object from a SamRidEnumeration object, /// using an already-opened SAM user handle. /// </summary> /// <param name="sre"> /// A <see cref="SamRidEnumeration"/> object containing minimal information /// about a local user. /// </param> /// <param name="userHandle"> /// Handle to an open SAM user. /// </param> /// <returns> /// A LocalUser object, populated with user information. /// </returns> private LocalUser MakeLocalUserObject(SamRidEnumeration sre, IntPtr userHandle) { IntPtr buffer = IntPtr.Zero; UInt32 status = 0; try { USER_ALL_INFORMATION allInfo; status = SamApi.SamQueryInformationUser(userHandle, USER_INFORMATION_CLASS.UserAllInformation, out buffer); ThrowOnFailure(status); allInfo = ClrFacade.PtrToStructure<USER_ALL_INFORMATION>(buffer); var userSid = RidToSid(sre.domainHandle, sre.RelativeId); LocalUser user = new LocalUser() { PrincipalSource = GetPrincipalSource(sre), SID = userSid, Name = allInfo.UserName.ToString(), FullName = allInfo.FullName.ToString(), Description = allInfo.AdminComment.ToString(), //TODO: why is this coming up as 864000000000 (number of ticks per day)? PasswordChangeableDate = DateTimeFromSam(allInfo.PasswordCanChange.QuadPart), PasswordExpires = DateTimeFromSam(allInfo.PasswordMustChange.QuadPart), //TODO: why is this coming up as 0X7FFFFFFFFFFFFFFF (largest signed 64-bit, and well out of range of DateTime)? AccountExpires = DateTimeFromSam(allInfo.AccountExpires.QuadPart), LastLogon = DateTimeFromSam(allInfo.LastLogon.QuadPart), PasswordLastSet = DateTimeFromSam(allInfo.PasswordLastSet.QuadPart), UserMayChangePassword = GetUserMayChangePassword(userHandle, userSid), PasswordRequired = (allInfo.UserAccountControl & SamApi.USER_PASSWORD_NOT_REQUIRED) == 0, Enabled = !((allInfo.UserAccountControl & SamApi.USER_ACCOUNT_DISABLED) == SamApi.USER_ACCOUNT_DISABLED) }; return user; } finally { if (buffer != IntPtr.Zero) status = SamApi.SamFreeMemory(buffer); } }
/// <summary> /// Create a populated LocalGroup object from a SamRidEnumeration object. /// </summary> /// <param name="sre"> /// A <see cref="SamRidEnumeration"/> object containing minimal information /// about a local group. /// </param> /// <returns> /// A LocalGroup object, populated with group information. /// </returns> private LocalGroup MakeLocalGroupObject(SamRidEnumeration sre) { IntPtr aliasHandle = IntPtr.Zero; var status = SamApi.SamOpenAlias(sre.domainHandle, Win32.MAXIMUM_ALLOWED, sre.RelativeId, out aliasHandle); ThrowOnFailure(status); try { return MakeLocalGroupObject(sre, aliasHandle); } finally { if (aliasHandle != IntPtr.Zero) status = SamApi.SamCloseHandle(aliasHandle); } }
/// <summary> /// Create a populated LocalUser object from a SamRidEnumeration object. /// </summary> /// <param name="sre"> /// A <see cref="SamRidEnumeration"/> object containing minimal information /// about a local user. /// </param> /// <returns> /// A LocalUser object, populated with user information. /// </returns> private LocalUser MakeLocalUserObject(SamRidEnumeration sre) { IntPtr userHandle = IntPtr.Zero; var status = SamApi.SamOpenUser(sre.domainHandle, (UInt32)ObjectAccess.UserRead, sre.RelativeId, out userHandle); ThrowOnFailure(status); try { return MakeLocalUserObject(sre, userHandle); } finally { if (userHandle != IntPtr.Zero) status = SamApi.SamCloseHandle(userHandle); } }