USER_ALL_ACCESS
};
+PGENERIC_MAPPING pServerMapping = &ServerMapping;
+
/* FUNCTIONS *****************************************************************/
+static
+LARGE_INTEGER
+SampAddRelativeTimeToTime(IN LARGE_INTEGER AbsoluteTime,
+ IN LARGE_INTEGER RelativeTime)
+{
+ LARGE_INTEGER NewTime;
+
+ NewTime.QuadPart = AbsoluteTime.QuadPart - RelativeTime.QuadPart;
+
+ if (NewTime.QuadPart < 0)
+ NewTime.QuadPart = 0;
+
+ return NewTime;
+}
+
+
VOID
SampStartRpcServer(VOID)
{
NTAPI
SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle,
IN SECURITY_INFORMATION SecurityInformation,
- OUT PSAMPR_SR_SECURITY_DESCRIPTOR * SecurityDescriptor)
+ OUT PSAMPR_SR_SECURITY_DESCRIPTOR *SecurityDescriptor)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
NTAPI
SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT ServerObject;
+ NTSTATUS Status;
+
+ TRACE("(%p)\n", ServerHandle);
+
+ /* Validate the server handle */
+ Status = SampValidateDbObject(ServerHandle,
+ SamDbServerObject,
+ SAM_SERVER_SHUTDOWN,
+ &ServerObject);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Shut the server down */
+ RpcMgmtStopServerListening(0);
+
+ return STATUS_SUCCESS;
}
SAM_USER_FIXED_DATA FixedUserData;
PSAM_DB_OBJECT DomainObject;
PSAM_DB_OBJECT UserObject;
+ GROUP_MEMBERSHIP GroupMembership;
+ UCHAR LogonHours[23];
ULONG ulSize;
ULONG ulRid;
WCHAR szRid[9];
/* Initialize fixed user data */
memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
FixedUserData.Version = 1;
+ FixedUserData.Reserved = 0;
FixedUserData.LastLogon.QuadPart = 0;
FixedUserData.LastLogoff.QuadPart = 0;
FixedUserData.PasswordLastSet.QuadPart = 0;
FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
USER_PASSWORD_NOT_REQUIRED |
USER_NORMAL_ACCOUNT;
+ FixedUserData.CountryCode = 0;
+ FixedUserData.CodePage = 0;
+ FixedUserData.BadPasswordCount = 0;
+ FixedUserData.LogonCount = 0;
+ FixedUserData.AdminCount = 0;
+ FixedUserData.OperatorCount = 0;
/* Set fixed user data attribute */
Status = SampSetObjectAttribute(UserObject,
return Status;
}
- /* FIXME: Set default user attributes */
+ /* Set the Parameters attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"Parameters",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LogonHours attribute*/
+ *((PUSHORT)LogonHours) = 168;
+ memset(&(LogonHours[2]), 0xff, 21);
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"LogonHours",
+ REG_BINARY,
+ &LogonHours,
+ sizeof(LogonHours));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set Groups attribute*/
+ GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
+ GroupMembership.Attributes = SE_GROUP_MANDATORY |
+ SE_GROUP_ENABLED |
+ SE_GROUP_ENABLED_BY_DEFAULT;
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"Groups",
+ REG_BINARY,
+ &GroupMembership,
+ sizeof(GROUP_MEMBERSHIP));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LMPwd attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"LMPwd",
+ REG_BINARY,
+ &EmptyLmHash,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set NTPwd attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"NTPwd",
+ REG_BINARY,
+ &EmptyNtHash,
+ sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LMPwdHistory attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"LMPwdHistory",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set NTPwdHistory attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"NTPwdHistory",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* FIXME: Set SecDesc attribute*/
if (NT_SUCCESS(Status))
{
ULONG DataLength;
ULONG i, j;
NTSTATUS Status;
+ WCHAR NameBuffer[9];
TRACE("SamrGetAliasMembership(%p %p %p)\n",
DomainHandle, SidArray, Membership);
/* Validate the domain handle */
Status = SampValidateDbObject(DomainHandle,
SamDbDomainObject,
- DOMAIN_LOOKUP,
+ DOMAIN_GET_ALIAS_MEMBERSHIP,
&DomainObject);
if (!NT_SUCCESS(Status))
return Status;
KEY_READ,
&MembersKeyHandle);
TRACE("SampRegOpenKey returned %08lX\n", Status);
+
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ Status = STATUS_SUCCESS;
+ goto done;
+ }
+
if (!NT_SUCCESS(Status))
goto done;
MaxSidCount += ValueCount;
}
-
NtClose(MemberKeyHandle);
}
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ Status = STATUS_SUCCESS;
+
LocalFree(MemberSidString);
}
+ if (MaxSidCount == 0)
+ {
+ Status = STATUS_SUCCESS;
+ goto done;
+ }
+
TRACE("Maximum sid count: %lu\n", MaxSidCount);
RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
if (RidArray == NULL)
for (j = 0; j < ValueCount; j++)
{
- DataLength = sizeof(ULONG);
+ DataLength = 9 * sizeof(WCHAR);
Status = SampRegEnumerateValue(MemberKeyHandle,
j,
- NULL,
- NULL,
- NULL,
- (PVOID)&RidArray[j],
- &DataLength);
+ NameBuffer,
+ &DataLength,
+ NULL,
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ RidArray[j] = wcstoul(NameBuffer, NULL, 16);
+ }
}
}
LocalFree(MemberSidString);
}
-
done:
if (NT_SUCCESS(Status))
{
PSAMPR_GROUP_INFO_BUFFER *Buffer)
{
PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
- HANDLE MembersKeyHandle = NULL;
SAM_GROUP_FIXED_DATA FixedData;
+ ULONG MembersLength = 0;
ULONG Length = 0;
NTSTATUS Status;
InfoBuffer->General.Attributes = FixedData.Attributes;
- /* Open the Members subkey */
- Status = SampRegOpenKey(GroupObject->KeyHandle,
- L"Members",
- KEY_READ,
- &MembersKeyHandle);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Status 0x%08lx\n", Status);
+ Status = SampGetObjectAttribute(GroupObject,
+ L"Members",
+ NULL,
+ NULL,
+ &MembersLength);
+ if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
goto done;
- }
- /* Retrieve the number of members of the alias */
- Status = SampRegQueryKeyInfo(MembersKeyHandle,
- NULL,
- &InfoBuffer->General.MemberCount);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Status 0x%08lx\n", Status);
- goto done;
- }
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ InfoBuffer->General.MemberCount = 0;
+ else
+ InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG);
*Buffer = InfoBuffer;
done:
- if (MembersKeyHandle != NULL)
- SampRegCloseKey(MembersKeyHandle);
-
if (!NT_SUCCESS(Status))
{
if (InfoBuffer != NULL)
}
+static NTSTATUS
+SampSetGroupName(PSAM_DB_OBJECT GroupObject,
+ PSAMPR_GROUP_INFO_BUFFER Buffer)
+{
+ UNICODE_STRING OldGroupName = {0, 0, NULL};
+ UNICODE_STRING NewGroupName;
+ NTSTATUS Status;
+
+ Status = SampGetObjectAttributeString(GroupObject,
+ L"Name",
+ (PRPC_UNICODE_STRING)&OldGroupName);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ NewGroupName.Length = Buffer->Name.Name.Length;
+ NewGroupName.MaximumLength = Buffer->Name.Name.MaximumLength;
+ NewGroupName.Buffer = Buffer->Name.Name.Buffer;
+
+ if (!RtlEqualUnicodeString(&OldGroupName, &NewGroupName, TRUE))
+ {
+ Status = SampCheckAccountNameInDomain(GroupObject->ParentObject,
+ NewGroupName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
+ NewGroupName.Buffer, Status);
+ goto done;
+ }
+ }
+
+ Status = SampSetAccountNameInDomain(GroupObject->ParentObject,
+ L"Groups",
+ NewGroupName.Buffer,
+ GroupObject->RelativeId);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampRemoveAccountNameFromDomain(GroupObject->ParentObject,
+ L"Groups",
+ OldGroupName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampSetObjectAttribute(GroupObject,
+ L"Name",
+ REG_SZ,
+ NewGroupName.Buffer,
+ NewGroupName.Length + sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+ }
+
+done:
+ if (OldGroupName.Buffer != NULL)
+ midl_user_free(OldGroupName.Buffer);
+
+ return Status;
+}
+
+
static NTSTATUS
SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject,
PSAMPR_GROUP_INFO_BUFFER Buffer)
switch (GroupInformationClass)
{
case GroupNameInformation:
- Status = SampSetObjectAttribute(GroupObject,
- L"Name",
- REG_SZ,
- Buffer->Name.Name.Buffer,
- Buffer->Name.Name.Length + sizeof(WCHAR));
+ Status = SampSetGroupName(GroupObject,
+ Buffer);
break;
case GroupAttributeInformation:
IN unsigned long MemberId,
IN unsigned long Attributes)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT GroupObject;
+ PSAM_DB_OBJECT UserObject = NULL;
+ NTSTATUS Status;
+
+ TRACE("(%p %lu %lx)\n",
+ GroupHandle, MemberId, Attributes);
+
+ /* Validate the group handle */
+ Status = SampValidateDbObject(GroupHandle,
+ SamDbGroupObject,
+ GROUP_ADD_MEMBER,
+ &GroupObject);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Open the user object in the same domain */
+ Status = SampOpenUserObject(GroupObject->ParentObject,
+ MemberId,
+ 0,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampOpenUserObject() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ /* Add group membership to the user object */
+ Status = SampAddGroupMembershipToUser(UserObject,
+ GroupObject->RelativeId,
+ Attributes);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ /* Add the member to the group object */
+ Status = SampAddMemberToGroup(GroupObject,
+ MemberId);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status);
+ }
+
+done:
+ if (UserObject)
+ SampCloseDbObject(UserObject);
+
+ return Status;
}
+
/* Function 21 */
NTSTATUS
NTAPI
SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT GroupObject;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ TRACE("(%p)\n", GroupHandle);
+
+ /* Validate the group handle */
+ Status = SampValidateDbObject(*GroupHandle,
+ SamDbGroupObject,
+ DELETE,
+ &GroupObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Fail, if the group is built-in */
+ if (GroupObject->RelativeId < 1000)
+ {
+ TRACE("You can not delete a special account!\n");
+ return STATUS_SPECIAL_ACCOUNT;
+ }
+
+ /* Get the length of the Members attribute */
+ SampGetObjectAttribute(GroupObject,
+ L"Members",
+ NULL,
+ NULL,
+ &Length);
+
+ /* Fail, if the group has members */
+ if (Length != 0)
+ {
+ TRACE("There are still members in the group!\n");
+ return STATUS_MEMBER_IN_GROUP;
+ }
+
+ /* FIXME: Remove the group from all aliases */
+
+ /* Delete the group from the database */
+ Status = SampDeleteAccountDbObject(GroupObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Invalidate the handle */
+ *GroupHandle = NULL;
+
+ return STATUS_SUCCESS;
}
+
/* Function 24 */
NTSTATUS
NTAPI
SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
IN unsigned long MemberId)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ PSAM_DB_OBJECT GroupObject;
+ PSAM_DB_OBJECT UserObject = NULL;
+ NTSTATUS Status;
+
+ TRACE("(%p %lu)\n",
+ GroupHandle, MemberId);
+
+ /* Validate the group handle */
+ Status = SampValidateDbObject(GroupHandle,
+ SamDbGroupObject,
+ GROUP_REMOVE_MEMBER,
+ &GroupObject);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Open the user object in the same domain */
+ Status = SampOpenUserObject(GroupObject->ParentObject,
+ MemberId,
+ 0,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ /* Remove group membership from the user object */
+ Status = SampRemoveGroupMembershipFromUser(UserObject,
+ GroupObject->RelativeId);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ /* Remove the member from the group object */
+ Status = SampRemoveMemberFromGroup(GroupObject,
+ MemberId);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SampRemoveMemberFromGroup() failed (Status 0x%08lx)\n", Status);
+ }
+
+done:
+ if (UserObject)
+ SampCloseDbObject(UserObject);
+
+ return Status;
+}
+
+
+/* Function 25 */
+NTSTATUS
+NTAPI
+SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
+ OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
+{
+ PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
+ PSAM_DB_OBJECT GroupObject;
+ ULONG Length = 0;
+ ULONG i;
+ NTSTATUS Status;
+
+ /* Validate the group handle */
+ Status = SampValidateDbObject(GroupHandle,
+ SamDbGroupObject,
+ GROUP_LIST_MEMBERS,
+ &GroupObject);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ MembersBuffer = midl_user_allocate(sizeof(SAMPR_GET_MEMBERS_BUFFER));
+ if (MembersBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ SampGetObjectAttribute(GroupObject,
+ L"Members",
+ NULL,
+ NULL,
+ &Length);
+
+ if (Length == 0)
+ {
+ MembersBuffer->MemberCount = 0;
+ MembersBuffer->Members = NULL;
+ MembersBuffer->Attributes = NULL;
+
+ *Members = MembersBuffer;
+
+ return STATUS_SUCCESS;
+ }
+
+ MembersBuffer->Members = midl_user_allocate(Length);
+ if (MembersBuffer->Members == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ MembersBuffer->Attributes = midl_user_allocate(Length);
+ if (MembersBuffer->Attributes == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Status = SampGetObjectAttribute(GroupObject,
+ L"Members",
+ NULL,
+ MembersBuffer->Members,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttributes() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ MembersBuffer->MemberCount = Length / sizeof(ULONG);
+
+ for (i = 0; i < MembersBuffer->MemberCount; i++)
+ {
+ Status = SampGetUserGroupAttributes(GroupObject->ParentObject,
+ MembersBuffer->Members[i],
+ GroupObject->RelativeId,
+ &(MembersBuffer->Attributes[i]));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetUserGroupAttributes() failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+ }
+
+ *Members = MembersBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (MembersBuffer != NULL)
+ {
+ if (MembersBuffer->Members != NULL)
+ midl_user_free(MembersBuffer->Members);
+
+ if (MembersBuffer->Attributes != NULL)
+ midl_user_free(MembersBuffer->Attributes);
+
+ midl_user_free(MembersBuffer);
+ }
+ }
+
+ return Status;
+}
-/* Function 25 */
-NTSTATUS
-NTAPI
-SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
- OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
/* Function 26 */
NTSTATUS
IN unsigned long MemberId,
IN unsigned long Attributes)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT GroupObject;
+ NTSTATUS Status;
+
+ /* Validate the group handle */
+ Status = SampValidateDbObject(GroupHandle,
+ SamDbGroupObject,
+ GROUP_ADD_MEMBER,
+ &GroupObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ Status = SampSetUserGroupAttributes(GroupObject->ParentObject,
+ MemberId,
+ GroupObject->RelativeId,
+ Attributes);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetUserGroupAttributes failed with status 0x%08lx\n", Status);
+ }
+
+ return Status;
}
}
+static NTSTATUS
+SampSetAliasName(PSAM_DB_OBJECT AliasObject,
+ PSAMPR_ALIAS_INFO_BUFFER Buffer)
+{
+ UNICODE_STRING OldAliasName = {0, 0, NULL};
+ UNICODE_STRING NewAliasName;
+ NTSTATUS Status;
+
+ Status = SampGetObjectAttributeString(AliasObject,
+ L"Name",
+ (PRPC_UNICODE_STRING)&OldAliasName);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ NewAliasName.Length = Buffer->Name.Name.Length;
+ NewAliasName.MaximumLength = Buffer->Name.Name.MaximumLength;
+ NewAliasName.Buffer = Buffer->Name.Name.Buffer;
+
+ if (!RtlEqualUnicodeString(&OldAliasName, &NewAliasName, TRUE))
+ {
+ Status = SampCheckAccountNameInDomain(AliasObject->ParentObject,
+ NewAliasName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
+ NewAliasName.Buffer, Status);
+ goto done;
+ }
+ }
+
+ Status = SampSetAccountNameInDomain(AliasObject->ParentObject,
+ L"Aliases",
+ NewAliasName.Buffer,
+ AliasObject->RelativeId);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampRemoveAccountNameFromDomain(AliasObject->ParentObject,
+ L"Aliases",
+ OldAliasName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampSetObjectAttribute(AliasObject,
+ L"Name",
+ REG_SZ,
+ NewAliasName.Buffer,
+ NewAliasName.Length + sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+ }
+
+done:
+ if (OldAliasName.Buffer != NULL)
+ midl_user_free(OldAliasName.Buffer);
+
+ return Status;
+}
+
+
/* Function 29 */
NTSTATUS
NTAPI
switch (AliasInformationClass)
{
case AliasNameInformation:
- Status = SampSetObjectAttribute(AliasObject,
- L"Name",
- REG_SZ,
- Buffer->Name.Name.Buffer,
- Buffer->Name.Name.Length + sizeof(WCHAR));
+ Status = SampSetAliasName(AliasObject,
+ Buffer);
break;
case AliasAdminCommentInformation:
NTSTATUS
NTAPI
SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* Function 31 */
-NTSTATUS
-NTAPI
-SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
- IN PRPC_SID MemberId)
{
PSAM_DB_OBJECT AliasObject;
- LPWSTR MemberIdString = NULL;
- HANDLE MembersKeyHandle = NULL;
- HANDLE MemberKeyHandle = NULL;
- ULONG MemberIdLength;
NTSTATUS Status;
- TRACE("SamrAddMemberToAlias(%p %p)\n",
- AliasHandle, MemberId);
-
/* Validate the alias handle */
- Status = SampValidateDbObject(AliasHandle,
+ Status = SampValidateDbObject(*AliasHandle,
SamDbAliasObject,
- ALIAS_ADD_MEMBER,
+ DELETE,
&AliasObject);
if (!NT_SUCCESS(Status))
{
- TRACE("failed with status 0x%08lx\n", Status);
+ TRACE("SampValidateDbObject failed (Status 0x%08lx)\n", Status);
return Status;
}
- ConvertSidToStringSidW(MemberId, &MemberIdString);
- TRACE("Member SID: %S\n", MemberIdString);
-
- MemberIdLength = RtlLengthSid(MemberId);
-
- Status = SampRegCreateKey(AliasObject->KeyHandle,
- L"Members",
- KEY_WRITE,
- &MembersKeyHandle);
- if (!NT_SUCCESS(Status))
+ /* Fail, if the alias is built-in */
+ if (AliasObject->RelativeId < 1000)
{
- TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
- goto done;
+ TRACE("You can not delete a special account!\n");
+ return STATUS_SPECIAL_ACCOUNT;
}
- Status = SampRegSetValue(MembersKeyHandle,
- MemberIdString,
- REG_BINARY,
- MemberId,
- MemberIdLength);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
- goto done;
- }
+ /* FIXME: Remove all members from the alias */
- Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
- MemberIdString,
- KEY_WRITE,
- &MemberKeyHandle);
+ /* Delete the alias from the database */
+ Status = SampDeleteAccountDbObject(AliasObject);
if (!NT_SUCCESS(Status))
{
- TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
- goto done;
- }
-
- Status = SampRegSetValue(MemberKeyHandle,
- AliasObject->Name,
- REG_BINARY,
- MemberId,
- MemberIdLength);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
- goto done;
+ TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
+ return Status;
}
-done:
- if (MemberKeyHandle != NULL)
- SampRegCloseKey(MemberKeyHandle);
-
- if (MembersKeyHandle != NULL)
- SampRegCloseKey(MembersKeyHandle);
-
- if (MemberIdString != NULL)
- LocalFree(MemberIdString);
+ /* Invalidate the handle */
+ *AliasHandle = NULL;
return Status;
}
-/* Function 32 */
+/* Function 31 */
NTSTATUS
NTAPI
-SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
- IN PRPC_SID MemberId)
+SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
+ IN PRPC_SID MemberId)
{
PSAM_DB_OBJECT AliasObject;
- LPWSTR MemberIdString = NULL;
- HANDLE MembersKeyHandle = NULL;
- HANDLE MemberKeyHandle = NULL;
- ULONG ulValueCount;
NTSTATUS Status;
- TRACE("SamrRemoveMemberFromAlias(%p %p)\n",
- AliasHandle, MemberId);
+ TRACE("(%p %p)\n", AliasHandle, MemberId);
/* Validate the alias handle */
Status = SampValidateDbObject(AliasHandle,
SamDbAliasObject,
- ALIAS_REMOVE_MEMBER,
+ ALIAS_ADD_MEMBER,
&AliasObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
- ConvertSidToStringSidW(MemberId, &MemberIdString);
- TRACE("Member SID: %S\n", MemberIdString);
-
- Status = SampRegOpenKey(AliasObject->MembersKeyHandle,
- MemberIdString,
- KEY_WRITE | KEY_QUERY_VALUE,
- &MemberKeyHandle);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
- goto done;
- }
-
- Status = SampRegDeleteValue(MemberKeyHandle,
- AliasObject->Name);
+ Status = SampAddMemberToAlias(AliasObject,
+ MemberId);
if (!NT_SUCCESS(Status))
{
- TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
- goto done;
+ TRACE("failed with status 0x%08lx\n", Status);
}
- Status = SampRegQueryKeyInfo(MemberKeyHandle,
- NULL,
- &ulValueCount);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
- goto done;
- }
+ return Status;
+}
- if (ulValueCount == 0)
- {
- SampRegCloseKey(MemberKeyHandle);
- MemberKeyHandle = NULL;
- Status = SampRegDeleteKey(AliasObject->MembersKeyHandle,
- MemberIdString);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
- goto done;
- }
- }
+/* Function 32 */
+NTSTATUS
+NTAPI
+SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
+ IN PRPC_SID MemberId)
+{
+ PSAM_DB_OBJECT AliasObject;
+ NTSTATUS Status;
- Status = SampRegOpenKey(AliasObject->KeyHandle,
- L"Members",
- KEY_WRITE | KEY_QUERY_VALUE,
- &MembersKeyHandle);
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
- goto done;
- }
+ TRACE("(%p %p)\n", AliasHandle, MemberId);
- Status = SampRegDeleteValue(MembersKeyHandle,
- MemberIdString);
+ /* Validate the alias handle */
+ Status = SampValidateDbObject(AliasHandle,
+ SamDbAliasObject,
+ ALIAS_REMOVE_MEMBER,
+ &AliasObject);
if (!NT_SUCCESS(Status))
{
- TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
- goto done;
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
}
- Status = SampRegQueryKeyInfo(MembersKeyHandle,
- NULL,
- &ulValueCount);
+ Status = SampRemoveMemberFromAlias(AliasObject,
+ MemberId);
if (!NT_SUCCESS(Status))
{
- TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
- goto done;
- }
-
- if (ulValueCount == 0)
- {
- SampRegCloseKey(MembersKeyHandle);
- MembersKeyHandle = NULL;
-
- Status = SampRegDeleteKey(AliasObject->KeyHandle,
- L"Members");
- if (!NT_SUCCESS(Status))
- {
- TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
- goto done;
- }
+ TRACE("failed with status 0x%08lx\n", Status);
}
-done:
- if (MemberKeyHandle != NULL)
- SampRegCloseKey(MemberKeyHandle);
-
- if (MembersKeyHandle != NULL)
- SampRegCloseKey(MembersKeyHandle);
-
- if (MemberIdString != NULL)
- LocalFree(MemberIdString);
-
return Status;
}
NTAPI
SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT UserObject;
+ NTSTATUS Status;
+
+ TRACE("(%p)\n", UserHandle);
+
+ /* Validate the user handle */
+ Status = SampValidateDbObject(*UserHandle,
+ SamDbUserObject,
+ DELETE,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Fail, if the user is built-in */
+ if (UserObject->RelativeId < 1000)
+ {
+ TRACE("You can not delete a special account!\n");
+ return STATUS_SPECIAL_ACCOUNT;
+ }
+
+ /* FIXME: Remove the user from all groups */
+
+ /* FIXME: Remove the user from all aliases */
+
+ /* Delete the user from the database */
+ Status = SampDeleteAccountDbObject(UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Invalidate the handle */
+ *UserHandle = NULL;
+
+ return STATUS_SUCCESS;
}
PSAMPR_USER_INFO_BUFFER *Buffer)
{
PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ SAM_DOMAIN_FIXED_DATA DomainFixedData;
SAM_USER_FIXED_DATA FixedData;
+ LARGE_INTEGER PasswordCanChange;
+ LARGE_INTEGER PasswordMustChange;
ULONG Length = 0;
NTSTATUS Status;
if (InfoBuffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
+ /* Get the fixed size domain data */
+ Length = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject->ParentObject,
+ L"F",
+ NULL,
+ (PVOID)&DomainFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Get the fixed size user data */
Length = sizeof(SAM_USER_FIXED_DATA);
Status = SampGetObjectAttribute(UserObject,
L"F",
InfoBuffer->Logon.LogonCount = FixedData.LogonCount;
InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl;
-// OLD_LARGE_INTEGER PasswordCanChange;
-// OLD_LARGE_INTEGER PasswordMustChange;
+ PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
+ DomainFixedData.MinPasswordAge);
+ InfoBuffer->Logon.PasswordCanChange.LowPart = PasswordCanChange.LowPart;
+ InfoBuffer->Logon.PasswordCanChange.HighPart = PasswordCanChange.HighPart;
+
+ PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
+ DomainFixedData.MaxPasswordAge);
+ InfoBuffer->Logon.PasswordMustChange.LowPart = PasswordMustChange.LowPart;
+ InfoBuffer->Logon.PasswordMustChange.HighPart = PasswordMustChange.HighPart;
/* Get the Name string */
Status = SampGetObjectAttributeString(UserObject,
goto done;
}
- /* FIXME: LogonHours */
+ /* Get the LogonHours attribute */
+ Status = SampGetLogonHoursAttrbute(UserObject,
+ &InfoBuffer->Logon.LogonHours);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
*Buffer = InfoBuffer;
&InfoBuffer->Account.AdminComment);
if (!NT_SUCCESS(Status))
{
- TRACE("Status 0x%08lx\n", Status);
- goto done;
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the WorkStations string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"WorkStations",
+ &InfoBuffer->Account.WorkStations);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the LogonHours attribute */
+ Status = SampGetLogonHoursAttrbute(UserObject,
+ &InfoBuffer->Account.LogonHours);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Account.UserName.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.UserName.Buffer);
+
+ if (InfoBuffer->Account.FullName.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.FullName.Buffer);
+
+ if (InfoBuffer->Account.HomeDirectory.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer);
+
+ if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer);
+
+ if (InfoBuffer->Account.ScriptPath.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.ScriptPath.Buffer);
+
+ if (InfoBuffer->Account.ProfilePath.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.ProfilePath.Buffer);
+
+ if (InfoBuffer->Account.AdminComment.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.AdminComment.Buffer);
+
+ if (InfoBuffer->Account.WorkStations.Buffer != NULL)
+ midl_user_free(InfoBuffer->Account.WorkStations.Buffer);
+
+ if (InfoBuffer->Account.LogonHours.LogonHours != NULL)
+ midl_user_free(InfoBuffer->Account.LogonHours.LogonHours);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+SampQueryUserLogonHours(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ NTSTATUS Status;
+
+ TRACE("(%p %p)\n", UserObject, Buffer);
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ {
+ TRACE("Failed to allocate InfoBuffer!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- /* Get the WorkStations string */
- Status = SampGetObjectAttributeString(UserObject,
- L"WorkStations",
- &InfoBuffer->Account.WorkStations);
+ Status = SampGetLogonHoursAttrbute(UserObject,
+ &InfoBuffer->LogonHours.LogonHours);
if (!NT_SUCCESS(Status))
{
- TRACE("Status 0x%08lx\n", Status);
+ TRACE("SampGetLogonHoursAttrbute failed (Status 0x%08lx)\n", Status);
goto done;
}
- /* FIXME: LogonHours */
-
*Buffer = InfoBuffer;
done:
{
if (InfoBuffer != NULL)
{
- if (InfoBuffer->Account.UserName.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.UserName.Buffer);
-
- if (InfoBuffer->Account.FullName.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.FullName.Buffer);
-
- if (InfoBuffer->Account.HomeDirectory.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer);
-
- if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer);
-
- if (InfoBuffer->Account.ScriptPath.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.ScriptPath.Buffer);
-
- if (InfoBuffer->Account.ProfilePath.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.ProfilePath.Buffer);
-
- if (InfoBuffer->Account.AdminComment.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.AdminComment.Buffer);
-
- if (InfoBuffer->Account.WorkStations.Buffer != NULL)
- midl_user_free(InfoBuffer->Account.WorkStations.Buffer);
-
- if (InfoBuffer->Account.LogonHours.LogonHours != NULL)
- midl_user_free(InfoBuffer->Account.LogonHours.LogonHours);
+ if (InfoBuffer->LogonHours.LogonHours.LogonHours != NULL)
+ midl_user_free(InfoBuffer->LogonHours.LogonHours.LogonHours);
midl_user_free(InfoBuffer);
}
return Status;
}
-/* FIXME: SampQueryUserLogonHours */
static
NTSTATUS
if (!NT_SUCCESS(Status))
goto done;
- InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
- InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
+ InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
+ InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static
+NTSTATUS
+SampQueryUserInternal1(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ ULONG Length = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Fail, if the caller is not a trusted caller */
+ if (UserObject->Trusted == FALSE)
+ return STATUS_INVALID_INFO_CLASS;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Get the NT password */
+ Length = 0;
+ SampGetObjectAttribute(UserObject,
+ L"NTPwd",
+ NULL,
+ NULL,
+ &Length);
+
+ if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
+ {
+ Status = SampGetObjectAttribute(UserObject,
+ L"NTPwd",
+ NULL,
+ (PVOID)&InfoBuffer->Internal1.EncryptedNtOwfPassword,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+ }
+
+ InfoBuffer->Internal1.NtPasswordPresent = (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+
+ /* Get the LM password */
+ Length = 0;
+ SampGetObjectAttribute(UserObject,
+ L"LMPwd",
+ NULL,
+ NULL,
+ &Length);
+
+ if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
+ {
+ Status = SampGetObjectAttribute(UserObject,
+ L"LMPwd",
+ NULL,
+ (PVOID)&InfoBuffer->Internal1.EncryptedLmOwfPassword,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+ }
+
+ InfoBuffer->Internal1.LmPasswordPresent = (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+
+ InfoBuffer->Internal1.PasswordExpired = FALSE;
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserParameters(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Get the Parameters string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"Parameters",
+ &InfoBuffer->Parameters.Parameters);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ *Buffer = InfoBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (InfoBuffer != NULL)
+ {
+ if (InfoBuffer->Parameters.Parameters.Buffer != NULL)
+ midl_user_free(InfoBuffer->Parameters.Parameters.Buffer);
+
+ midl_user_free(InfoBuffer);
+ }
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
+SampQueryUserAll(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER *Buffer)
+{
+ PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
+ SAM_DOMAIN_FIXED_DATA DomainFixedData;
+ SAM_USER_FIXED_DATA FixedData;
+ LARGE_INTEGER PasswordCanChange;
+ LARGE_INTEGER PasswordMustChange;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ *Buffer = NULL;
+
+ InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
+ if (InfoBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Get the fixed size domain data */
+ Length = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject->ParentObject,
+ L"F",
+ NULL,
+ (PVOID)&DomainFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Get the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if (UserObject->Access & USER_READ_GENERAL)
+ {
+ /* Get the Name string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"Name",
+ &InfoBuffer->All.UserName);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the FullName string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"FullName",
+ &InfoBuffer->All.FullName);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the user ID*/
+ InfoBuffer->All.UserId = FixedData.UserId;
+
+ /* Get the primary group ID */
+ InfoBuffer->All.PrimaryGroupId = FixedData.PrimaryGroupId;
+
+ /* Get the AdminComment string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"AdminComment",
+ &InfoBuffer->All.AdminComment);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the UserComment string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"UserComment",
+ &InfoBuffer->All.UserComment);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK;
+// USER_ALL_USERNAME |
+// USER_ALL_FULLNAME |
+// USER_ALL_USERID |
+// USER_ALL_PRIMARYGROUPID |
+// USER_ALL_ADMINCOMMENT |
+// USER_ALL_USERCOMMENT;
+ }
+
+ if (UserObject->Access & USER_READ_LOGON)
+ {
+ /* Get the HomeDirectory string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"HomeDirectory",
+ &InfoBuffer->All.HomeDirectory);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the HomeDirectoryDrive string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"HomeDirectoryDrive",
+ &InfoBuffer->Home.HomeDirectoryDrive);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the ScriptPath string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"ScriptPath",
+ &InfoBuffer->All.ScriptPath);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the ProfilePath string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"ProfilePath",
+ &InfoBuffer->All.ProfilePath);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the WorkStations string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"WorkStations",
+ &InfoBuffer->All.WorkStations);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Get the LogonHours attribute */
+ Status = SampGetLogonHoursAttrbute(UserObject,
+ &InfoBuffer->All.LogonHours);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart;
+ InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart;
+
+ InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
+ InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
+
+ InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount;
+
+ InfoBuffer->All.LogonCount = FixedData.LogonCount;
+
+ PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
+ DomainFixedData.MinPasswordAge);
+ InfoBuffer->All.PasswordCanChange.LowPart = PasswordCanChange.LowPart;
+ InfoBuffer->All.PasswordCanChange.HighPart = PasswordCanChange.HighPart;
+
+ PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
+ DomainFixedData.MaxPasswordAge);
+ InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart;
+ InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart;
+
+ InfoBuffer->All. WhichFields |= USER_ALL_READ_LOGON_MASK;
+/*
+ USER_ALL_HOMEDIRECTORY |
+ USER_ALL_HOMEDIRECTORYDRIVE |
+ USER_ALL_SCRIPTPATH |
+ USER_ALL_PROFILEPATH |
+ USER_ALL_WORKSTATIONS |
+ USER_ALL_LASTLOGON |
+ USER_ALL_LASTLOGOFF |
+ USER_ALL_LOGONHOURS |
+ USER_ALL_BADPASSWORDCOUNT |
+ USER_ALL_LOGONCOUNT;
+ USER_ALL_PASSWORDCANCHANGE |
+ USER_ALL_PASSWORDMUSTCHANGE;
+*/
+ }
+
+ if (UserObject->Access & USER_READ_ACCOUNT)
+ {
+ InfoBuffer->All.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
+ InfoBuffer->All.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
+
+ InfoBuffer->All.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
+ InfoBuffer->All.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
+
+ InfoBuffer->All.UserAccountControl = FixedData.UserAccountControl;
+
+ /* Get the Parameters string */
+ Status = SampGetObjectAttributeString(UserObject,
+ L"Parameters",
+ &InfoBuffer->All.Parameters);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ InfoBuffer->All. WhichFields |= USER_ALL_READ_ACCOUNT_MASK;
+// USER_ALL_PASSWORDLASTSET |
+// USER_ALL_ACCOUNTEXPIRES |
+// USER_ALL_USERACCOUNTCONTROL |
+// USER_ALL_PARAMETERS;
+ }
+
+ if (UserObject->Access & USER_READ_PREFERENCES)
+ {
+ InfoBuffer->All.CountryCode = FixedData.CountryCode;
+
+ InfoBuffer->All.CodePage = FixedData.CodePage;
+
+ InfoBuffer->All. WhichFields |= USER_ALL_READ_PREFERENCES_MASK;
+// USER_ALL_COUNTRYCODE |
+// USER_ALL_CODEPAGE;
+ }
*Buffer = InfoBuffer;
{
if (InfoBuffer != NULL)
{
+ if (InfoBuffer->All.UserName.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.UserName.Buffer);
+
+ if (InfoBuffer->All.FullName.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.FullName.Buffer);
+
+ if (InfoBuffer->All.AdminComment.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.AdminComment.Buffer);
+
+ if (InfoBuffer->All.UserComment.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.UserComment.Buffer);
+
+ if (InfoBuffer->All.HomeDirectory.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.HomeDirectory.Buffer);
+
+ if (InfoBuffer->All.HomeDirectoryDrive.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.HomeDirectoryDrive.Buffer);
+
+ if (InfoBuffer->All.ScriptPath.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.ScriptPath.Buffer);
+
+ if (InfoBuffer->All.ProfilePath.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.ProfilePath.Buffer);
+
+ if (InfoBuffer->All.WorkStations.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.WorkStations.Buffer);
+
+ if (InfoBuffer->All.LogonHours.LogonHours != NULL)
+ midl_user_free(InfoBuffer->All.LogonHours.LogonHours);
+
+ if (InfoBuffer->All.Parameters.Buffer != NULL)
+ midl_user_free(InfoBuffer->All.Parameters.Buffer);
+
midl_user_free(InfoBuffer);
}
}
case UserControlInformation:
case UserExpiresInformation:
+ case UserParametersInformation:
DesiredAccess = USER_READ_ACCOUNT;
break;
USER_READ_ACCOUNT;
break;
+ case UserInternal1Information:
+ case UserAllInformation:
+ DesiredAccess = 0;
+ break;
+
default:
return STATUS_INVALID_INFO_CLASS;
}
Buffer);
break;
-// case UserLogonHoursInformation:
-// Status = SampQueryUserLogonHours(UserObject,
-// Buffer);
-// break;
+ case UserLogonHoursInformation:
+ Status = SampQueryUserLogonHours(UserObject,
+ Buffer);
+ break;
case UserAccountInformation:
Status = SampQueryUserAccount(UserObject,
Buffer);
break;
+ case UserInternal1Information:
+ Status = SampQueryUserInternal1(UserObject,
+ Buffer);
+ break;
+
+ case UserParametersInformation:
+ Status = SampQueryUserParameters(UserObject,
+ Buffer);
+ break;
+
+ case UserAllInformation:
+ Status = SampQueryUserAll(UserObject,
+ Buffer);
+ break;
+
+// case UserInternal4Information:
+// case UserInternal5Information:
+// case UserInternal4InformationNew:
+// case UserInternal5InformationNew:
+
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
+static NTSTATUS
+SampSetUserName(PSAM_DB_OBJECT UserObject,
+ PRPC_UNICODE_STRING NewUserName)
+{
+ UNICODE_STRING OldUserName = {0, 0, NULL};
+ NTSTATUS Status;
+
+ Status = SampGetObjectAttributeString(UserObject,
+ L"Name",
+ (PRPC_UNICODE_STRING)&OldUserName);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ if (!RtlEqualUnicodeString(&OldUserName, (PCUNICODE_STRING)NewUserName, TRUE))
+ {
+ Status = SampCheckAccountNameInDomain(UserObject->ParentObject,
+ NewUserName->Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
+ NewUserName->Buffer, Status);
+ goto done;
+ }
+ }
+
+ Status = SampSetAccountNameInDomain(UserObject->ParentObject,
+ L"Users",
+ NewUserName->Buffer,
+ UserObject->RelativeId);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampRemoveAccountNameFromDomain(UserObject->ParentObject,
+ L"Users",
+ OldUserName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"Name",
+ REG_SZ,
+ NewUserName->Buffer,
+ NewUserName->Length + sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+ }
+
+done:
+ if (OldUserName.Buffer != NULL)
+ midl_user_free(OldUserName.Buffer);
+
+ return Status;
+}
+
+
static NTSTATUS
SampSetUserGeneral(PSAM_DB_OBJECT UserObject,
PSAMPR_USER_INFO_BUFFER Buffer)
if (!NT_SUCCESS(Status))
goto done;
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->General.UserName.Buffer,
- Buffer->General.UserName.MaximumLength);
+ Status = SampSetUserName(UserObject,
+ &Buffer->General.UserName);
if (!NT_SUCCESS(Status))
goto done;
}
+static NTSTATUS
+SampSetUserInternal1(PSAM_DB_OBJECT UserObject,
+ PSAMPR_USER_INFO_BUFFER Buffer)
+{
+ SAM_USER_FIXED_DATA FixedData;
+ ULONG Length = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* FIXME: Decrypt NT password */
+ /* FIXME: Decrypt LM password */
+
+ Status = SampSetUserPassword(UserObject,
+ &Buffer->Internal1.EncryptedNtOwfPassword,
+ Buffer->Internal1.NtPasswordPresent,
+ &Buffer->Internal1.EncryptedLmOwfPassword,
+ Buffer->Internal1.LmPasswordPresent);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Get the fixed user attributes */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&FixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if (Buffer->Internal1.PasswordExpired)
+ {
+ /* The pasword was last set ages ago */
+ FixedData.PasswordLastSet.LowPart = 0;
+ FixedData.PasswordLastSet.HighPart = 0;
+ }
+ else
+ {
+ /* The pasword was last set right now */
+ Status = NtQuerySystemTime(&FixedData.PasswordLastSet);
+ if (!NT_SUCCESS(Status))
+ goto done;
+ }
+
+ /* Set the fixed user attributes */
+ Status = SampSetObjectAttribute(UserObject,
+ L"F",
+ REG_BINARY,
+ &FixedData,
+ Length);
+
+done:
+ return Status;
+}
+
+
static NTSTATUS
SampSetUserAll(PSAM_DB_OBJECT UserObject,
PSAMPR_USER_INFO_BUFFER Buffer)
if (WhichFields & USER_ALL_USERNAME)
{
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->All.UserName.Buffer,
- Buffer->All.UserName.MaximumLength);
+ Status = SampSetUserName(UserObject,
+ &Buffer->All.UserName);
if (!NT_SUCCESS(Status))
goto done;
}
REG_SZ,
Buffer->All.Parameters.Buffer,
Buffer->All.Parameters.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ goto done;
+ }
+
+ if (WhichFields & USER_ALL_LOGONHOURS)
+ {
+ Status = SampSetLogonHoursAttrbute(UserObject,
+ &Buffer->All.LogonHours);
+ if (!NT_SUCCESS(Status))
+ goto done;
}
if (WhichFields & (USER_ALL_PRIMARYGROUPID |
/*
FIXME:
- USER_ALL_LOGONHOURS
USER_ALL_NTPASSWORDPRESENT
USER_ALL_LMPASSWORDPRESENT
USER_ALL_PASSWORDEXPIRED
break;
case UserSetPasswordInformation:
+ case UserInternal1Information:
DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
break;
Status = SampSetUserPreferences(UserObject,
Buffer);
break;
-/*
+
case UserLogonHoursInformation:
- Status = SampSetUserLogonHours(UserObject,
- Buffer);
+ Status = SampSetLogonHoursAttrbute(UserObject,
+ &Buffer->LogonHours.LogonHours);
break;
-*/
+
case UserNameInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->Name.UserName.Buffer,
- Buffer->Name.UserName.MaximumLength);
+ Status = SampSetUserName(UserObject,
+ &Buffer->Name.UserName);
if (!NT_SUCCESS(Status))
break;
break;
case UserAccountNameInformation:
- Status = SampSetObjectAttribute(UserObject,
- L"Name",
- REG_SZ,
- Buffer->AccountName.UserName.Buffer,
- Buffer->AccountName.UserName.MaximumLength);
+ Status = SampSetUserName(UserObject,
+ &Buffer->AccountName.UserName);
break;
case UserFullNameInformation:
Buffer);
break;
-// case UserInternal1Information:
+ case UserInternal1Information:
+ Status = SampSetUserInternal1(UserObject,
+ Buffer);
+ break;
case UserParametersInformation:
Status = SampSetObjectAttribute(UserObject,
// case UserInternal4InformationNew:
// case UserInternal5InformationNew:
- default:
- Status = STATUS_INVALID_INFO_CLASS;
+ default:
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
+
+ return Status;
+}
+
+
+/* Function 38 */
+NTSTATUS
+NTAPI
+SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
+ IN unsigned char LmPresent,
+ IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
+ IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
+ IN unsigned char NtPresent,
+ IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
+ IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
+ IN unsigned char NtCrossEncryptionPresent,
+ IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
+ IN unsigned char LmCrossEncryptionPresent,
+ IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
+{
+ ENCRYPTED_LM_OWF_PASSWORD StoredLmPassword;
+ ENCRYPTED_NT_OWF_PASSWORD StoredNtPassword;
+ PENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
+ PENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
+ PENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
+ PENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
+ BOOLEAN StoredLmPresent = FALSE;
+ BOOLEAN StoredNtPresent = FALSE;
+ BOOLEAN StoredLmEmpty = TRUE;
+ BOOLEAN StoredNtEmpty = TRUE;
+ PSAM_DB_OBJECT UserObject;
+ ULONG Length;
+ SAM_USER_FIXED_DATA UserFixedData;
+ SAM_DOMAIN_FIXED_DATA DomainFixedData;
+ LARGE_INTEGER SystemTime;
+ NTSTATUS Status;
+
+ TRACE("(%p %u %p %p %u %p %p %u %p %u %p)\n",
+ UserHandle, LmPresent, OldLmEncryptedWithNewLm, NewLmEncryptedWithOldLm,
+ NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent,
+ NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt);
+
+ /* Validate the user handle */
+ Status = SampValidateDbObject(UserHandle,
+ SamDbUserObject,
+ USER_CHANGE_PASSWORD,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Get the current time */
+ Status = NtQuerySystemTime(&SystemTime);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Retrieve the LM password */
+ Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
+ Status = SampGetObjectAttribute(UserObject,
+ L"LMPwd",
+ NULL,
+ &StoredLmPassword,
+ &Length);
+ if (NT_SUCCESS(Status))
+ {
+ if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
+ {
+ StoredLmPresent = TRUE;
+ if (!RtlEqualMemory(&StoredLmPassword,
+ &EmptyLmHash,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ StoredLmEmpty = FALSE;
+ }
+ }
+
+ /* Retrieve the NT password */
+ Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+ Status = SampGetObjectAttribute(UserObject,
+ L"NTPwd",
+ NULL,
+ &StoredNtPassword,
+ &Length);
+ if (NT_SUCCESS(Status))
+ {
+ if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
+ {
+ StoredNtPresent = TRUE;
+ if (!RtlEqualMemory(&StoredNtPassword,
+ &EmptyNtHash,
+ sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+ StoredNtEmpty = FALSE;
+ }
+ }
+
+ /* Retrieve the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ &UserFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Check if we can change the password at this time */
+ if ((StoredNtEmpty == FALSE) || (StoredNtEmpty == FALSE))
+ {
+ /* Get fixed domain data */
+ Length = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject->ParentObject,
+ L"F",
+ NULL,
+ &DomainFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ if (DomainFixedData.MinPasswordAge.QuadPart > 0)
+ {
+ if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart))
+ return STATUS_ACCOUNT_RESTRICTION;
+ }
+ }
+
+ /* FIXME: Decrypt passwords */
+ OldLmPassword = OldLmEncryptedWithNewLm;
+ NewLmPassword = NewLmEncryptedWithOldLm;
+ OldNtPassword = OldNtEncryptedWithNewNt;
+ NewNtPassword = NewNtEncryptedWithOldNt;
+
+ /* Check if the old passwords match the stored ones */
+ if (NtPresent)
+ {
+ if (LmPresent)
+ {
+ if (!RtlEqualMemory(&StoredLmPassword,
+ OldLmPassword,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ {
+ TRACE("Old LM Password does not match!\n");
+ Status = STATUS_WRONG_PASSWORD;
+ }
+ else
+ {
+ if (!RtlEqualMemory(&StoredNtPassword,
+ OldNtPassword,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ {
+ TRACE("Old NT Password does not match!\n");
+ Status = STATUS_WRONG_PASSWORD;
+ }
+ }
+ }
+ else
+ {
+ if (!RtlEqualMemory(&StoredNtPassword,
+ OldNtPassword,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ {
+ TRACE("Old NT Password does not match!\n");
+ Status = STATUS_WRONG_PASSWORD;
+ }
+ }
+ }
+ else
+ {
+ if (LmPresent)
+ {
+ if (!RtlEqualMemory(&StoredLmPassword,
+ OldLmPassword,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ {
+ TRACE("Old LM Password does not match!\n");
+ Status = STATUS_WRONG_PASSWORD;
+ }
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ /* Store the new password hashes */
+ if (NT_SUCCESS(Status))
+ {
+ Status = SampSetUserPassword(UserObject,
+ NewNtPassword,
+ NtPresent,
+ NewLmPassword,
+ LmPresent);
+ if (NT_SUCCESS(Status))
+ {
+ /* Update PasswordLastSet */
+ UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart;
+
+ /* Set the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampSetObjectAttribute(UserObject,
+ L"F",
+ REG_BINARY,
+ &UserFixedData,
+ Length);
+ }
+ }
+
+ if (Status == STATUS_WRONG_PASSWORD)
+ {
+ /* Update BadPasswordCount and LastBadPasswordTime */
+ UserFixedData.BadPasswordCount++;
+ UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart;
+
+ /* Set the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampSetObjectAttribute(UserObject,
+ L"F",
+ REG_BINARY,
+ &UserFixedData,
+ Length);
}
return Status;
}
-/* Function 38 */
-NTSTATUS
-NTAPI
-SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
- IN unsigned char LmPresent,
- IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
- IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
- IN unsigned char NtPresent,
- IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
- IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
- IN unsigned char NtCrossEncryptionPresent,
- IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
- IN unsigned char LmCrossEncryptionPresent,
- IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
/* Function 39 */
NTSTATUS
NTAPI
SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
+ PSAM_DB_OBJECT UserObject;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ TRACE("SamrGetGroupsForUser(%p %p)\n",
+ UserHandle, Groups);
+
+ /* Validate the user handle */
+ Status = SampValidateDbObject(UserHandle,
+ SamDbUserObject,
+ USER_LIST_GROUPS,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Allocate the groups buffer */
+ GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER));
+ if (GroupsBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /*
+ * Get the size of the Groups attribute.
+ * Do not check the status code because in case of an error
+ * Length will be 0. And that is all we need.
+ */
+ SampGetObjectAttribute(UserObject,
+ L"Groups",
+ NULL,
+ NULL,
+ &Length);
+
+ /* If there is no Groups attribute, return a groups buffer without an array */
+ if (Length == 0)
+ {
+ GroupsBuffer->MembershipCount = 0;
+ GroupsBuffer->Groups = NULL;
+
+ *Groups = GroupsBuffer;
+
+ return STATUS_SUCCESS;
+ }
+
+ /* Allocate a buffer for the Groups attribute */
+ GroupsBuffer->Groups = midl_user_allocate(Length);
+ if (GroupsBuffer->Groups == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ /* Retrieve the Grous attribute */
+ Status = SampGetObjectAttribute(UserObject,
+ L"Groups",
+ NULL,
+ GroupsBuffer->Groups,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
+ goto done;
+ }
+
+ /* Calculate the membership count */
+ GroupsBuffer->MembershipCount = Length / sizeof(GROUP_MEMBERSHIP);
+
+ /* Return the groups buffer to the caller */
+ *Groups = GroupsBuffer;
+
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (GroupsBuffer != NULL)
+ {
+ if (GroupsBuffer->Groups != NULL)
+ midl_user_free(GroupsBuffer->Groups);
+
+ midl_user_free(GroupsBuffer);
+ }
+ }
+
+ return Status;
}
+
/* Function 40 */
NTSTATUS
NTAPI
return STATUS_NOT_IMPLEMENTED;
}
+
/* Function 44 */
NTSTATUS
NTAPI
SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ SAM_DOMAIN_FIXED_DATA DomainFixedData;
+ SAM_USER_FIXED_DATA UserFixedData;
+ PSAM_DB_OBJECT DomainObject;
+ PSAM_DB_OBJECT UserObject;
+ ULONG Length = 0;
+ NTSTATUS Status;
+
+ TRACE("(%p %p)\n",
+ UserHandle, PasswordInformation);
+
+ /* Validate the user handle */
+ Status = SampValidateDbObject(UserHandle,
+ SamDbUserObject,
+ 0,
+ &UserObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Validate the domain object */
+ Status = SampValidateDbObject((SAMPR_HANDLE)UserObject->ParentObject,
+ SamDbDomainObject,
+ DOMAIN_READ_PASSWORD_PARAMETERS,
+ &DomainObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Get fixed user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ (PVOID)&UserFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) ||
+ (UserFixedData.UserAccountControl & (USER_INTERDOMAIN_TRUST_ACCOUNT |
+ USER_WORKSTATION_TRUST_ACCOUNT |
+ USER_SERVER_TRUST_ACCOUNT)))
+ {
+ PasswordInformation->MinPasswordLength = 0;
+ PasswordInformation->PasswordProperties = 0;
+ }
+ else
+ {
+ /* Get fixed domain data */
+ Length = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(DomainObject,
+ L"F",
+ NULL,
+ (PVOID)&DomainFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength;
+ PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties;
+ }
+
+ return STATUS_SUCCESS;
}
+
/* Function 45 */
NTSTATUS
NTAPI
SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
IN PRPC_SID MemberSid)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PSAM_DB_OBJECT DomainObject;
+ ULONG Rid = 0;
+ NTSTATUS Status;
+
+ TRACE("(%p %p)\n",
+ DomainHandle, MemberSid);
+
+ /* Validate the domain object */
+ Status = SampValidateDbObject(DomainHandle,
+ SamDbDomainObject,
+ DOMAIN_LOOKUP,
+ &DomainObject);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Retrieve the RID from the MemberSID */
+ Status = SampGetRidFromSid((PSID)MemberSid,
+ &Rid);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Fail, if the RID represents a special account */
+ if (Rid < 1000)
+ {
+ TRACE("Cannot remove a special account (RID: %lu)\n", Rid);
+ return STATUS_SPECIAL_ACCOUNT;
+ }
+
+ /* Remove the member from all aliases in the domain */
+ Status = SampRemoveMemberFromAllAliases(DomainObject,
+ MemberSid);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status);
+ }
+
+ return Status;
}
+
/* Function 46 */
NTSTATUS
NTAPI
IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("(%p %lu %p)\n", DomainHandle, DomainInformationClass, Buffer);
+
+ return SamrQueryInformationDomain(DomainHandle,
+ DomainInformationClass,
+ Buffer);
}
+
/* Function 47 */
NTSTATUS
NTAPI
IN USER_INFORMATION_CLASS UserInformationClass,
OUT PSAMPR_USER_INFO_BUFFER *Buffer)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
+
+ return SamrQueryInformationUser(UserHandle,
+ UserInformationClass,
+ Buffer);
}
+
/* Function 48 */
NTSTATUS
NTAPI
OUT unsigned long *TotalReturned,
OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("%p %lu %lu %lu %lu %p %p %p\n",
+ DomainHandle, DisplayInformationClass, Index,
+ EntryCount, PreferredMaximumLength, TotalAvailable,
+ TotalReturned, Buffer);
+
+ return SamrQueryDisplayInformation(DomainHandle,
+ DisplayInformationClass,
+ Index,
+ EntryCount,
+ PreferredMaximumLength,
+ TotalAvailable,
+ TotalReturned,
+ Buffer);
}
+
/* Function 49 */
NTSTATUS
NTAPI
IN PRPC_UNICODE_STRING Prefix,
OUT unsigned long *Index)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("(%p %lu %p %p)\n",
+ DomainHandle, DisplayInformationClass, Prefix, Index);
+
+ return SamrGetDisplayEnumerationIndex(DomainHandle,
+ DisplayInformationClass,
+ Prefix,
+ Index);
}
SAM_USER_FIXED_DATA FixedUserData;
PSAM_DB_OBJECT DomainObject;
PSAM_DB_OBJECT UserObject;
+ GROUP_MEMBERSHIP GroupMembership;
+ UCHAR LogonHours[23];
ULONG ulSize;
ULONG ulRid;
WCHAR szRid[9];
/* Store the fixed domain attributes */
Status = SampSetObjectAttribute(DomainObject,
- L"F",
- REG_BINARY,
- &FixedDomainData,
- ulSize);
+ L"F",
+ REG_BINARY,
+ &FixedDomainData,
+ ulSize);
if (!NT_SUCCESS(Status))
{
TRACE("failed with status 0x%08lx\n", Status);
}
/* Initialize fixed user data */
- memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
FixedUserData.Version = 1;
+ FixedUserData.Reserved = 0;
FixedUserData.LastLogon.QuadPart = 0;
FixedUserData.LastLogoff.QuadPart = 0;
FixedUserData.PasswordLastSet.QuadPart = 0;
FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
USER_PASSWORD_NOT_REQUIRED |
AccountType;
+ FixedUserData.CountryCode = 0;
+ FixedUserData.CodePage = 0;
+ FixedUserData.BadPasswordCount = 0;
+ FixedUserData.LogonCount = 0;
+ FixedUserData.AdminCount = 0;
+ FixedUserData.OperatorCount = 0;
/* Set fixed user data attribute */
Status = SampSetObjectAttribute(UserObject,
return Status;
}
- /* FIXME: Set default user attributes */
+ /* Set the Parameters attribute */
+ Status = SampSetObjectAttribute(UserObject,
+ L"Parameters",
+ REG_SZ,
+ EmptyString.Buffer,
+ EmptyString.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LogonHours attribute*/
+ *((PUSHORT)LogonHours) = 168;
+ memset(&(LogonHours[2]), 0xff, 21);
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"LogonHours",
+ REG_BINARY,
+ &LogonHours,
+ sizeof(LogonHours));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set Groups attribute*/
+ GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
+ GroupMembership.Attributes = SE_GROUP_MANDATORY |
+ SE_GROUP_ENABLED |
+ SE_GROUP_ENABLED_BY_DEFAULT;
+
+ Status = SampSetObjectAttribute(UserObject,
+ L"Groups",
+ REG_BINARY,
+ &GroupMembership,
+ sizeof(GROUP_MEMBERSHIP));
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LMPwd attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"LMPwd",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set NTPwd attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"NTPwd",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set LMPwdHistory attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"LMPwdHistory",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Set NTPwdHistory attribute*/
+ Status = SampSetObjectAttribute(UserObject,
+ L"NTPwdHistory",
+ REG_BINARY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* FIXME: Set SecDesc attribute*/
if (NT_SUCCESS(Status))
{
OUT unsigned long *TotalReturned,
OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("%p %lu %lu %lu %lu %p %p %p\n",
+ DomainHandle, DisplayInformationClass, Index,
+ EntryCount, PreferredMaximumLength, TotalAvailable,
+ TotalReturned, Buffer);
+
+ return SamrQueryDisplayInformation(DomainHandle,
+ DisplayInformationClass,
+ Index,
+ EntryCount,
+ PreferredMaximumLength,
+ TotalAvailable,
+ TotalReturned,
+ Buffer);
}
return STATUS_NOT_IMPLEMENTED;
}
+
/* Function 57 */
NTSTATUS
NTAPI
OUT SAMPR_HANDLE *ServerHandle,
IN ACCESS_MASK DesiredAccess)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ TRACE("(%p %p %lx)\n", ServerName, ServerHandle, DesiredAccess);
+
+ return SamrConnect(ServerName,
+ ServerHandle,
+ DesiredAccess);
}