[MSV1_0]
[reactos.git] / reactos / dll / win32 / msv1_0 / msv1_0.c
index def4006..5581d78 100644 (file)
@@ -257,7 +257,7 @@ BuildTokenUser(OUT PTOKEN_USER User,
     if (User->User.Sid == NULL)
     {
         ERR("Could not create the user SID\n");
-        return STATUS_UNSUCCESSFUL;
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     User->User.Attributes = 0;
@@ -268,17 +268,30 @@ BuildTokenUser(OUT PTOKEN_USER User,
 
 static
 NTSTATUS
-BuildTokenGroups(IN PSID AccountDomainSid,
-                 IN PLUID LogonId,
-                 OUT PTOKEN_GROUPS *Groups,
-                 OUT PSID *PrimaryGroupSid,
-                 OUT PSID *OwnerSid)
+BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
+                       IN PSID AccountDomainSid,
+                       IN ULONG RelativeId)
+{
+    PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
+                                                RelativeId);
+    if (PrimaryGroup->PrimaryGroup == NULL)
+    {
+        ERR("Could not create the primary group SID\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
+                 IN PSID AccountDomainSid)
 {
-    SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
-    SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
     PTOKEN_GROUPS TokenGroups;
-#define MAX_GROUPS 8
+#define MAX_GROUPS 2
     DWORD GroupCount = 0;
     PSID Sid;
     NTSTATUS Status = STATUS_SUCCESS;
@@ -300,115 +313,8 @@ BuildTokenGroups(IN PSID AccountDomainSid,
     TokenGroups->Groups[GroupCount].Sid = Sid;
     TokenGroups->Groups[GroupCount].Attributes =
         SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    *PrimaryGroupSid = Sid;
     GroupCount++;
 
-    /* Member of 'Everyone' */
-    RtlAllocateAndInitializeSid(&WorldAuthority,
-                                1,
-                                SECURITY_WORLD_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    GroupCount++;
-
-#if 1
-    /* Member of 'Administrators' */
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                2,
-                                SECURITY_BUILTIN_DOMAIN_RID,
-                                DOMAIN_ALIAS_RID_ADMINS,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    GroupCount++;
-#else
-    TRACE("Not adding user to Administrators group\n");
-#endif
-
-    /* Member of 'Users' */
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                2,
-                                SECURITY_BUILTIN_DOMAIN_RID,
-                                DOMAIN_ALIAS_RID_USERS,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    GroupCount++;
-
-    /* Logon SID */
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                SECURITY_LOGON_IDS_RID_COUNT,
-                                SECURITY_LOGON_IDS_RID,
-                                LogonId->HighPart,
-                                LogonId->LowPart,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY | SE_GROUP_LOGON_ID;
-    GroupCount++;
-    *OwnerSid = Sid;
-
-    /* Member of 'Local users */
-    RtlAllocateAndInitializeSid(&LocalAuthority,
-                                1,
-                                SECURITY_LOCAL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    GroupCount++;
-
-    /* Member of 'Interactive users' */
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                1,
-                                SECURITY_INTERACTIVE_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &Sid);
-    TokenGroups->Groups[GroupCount].Sid = Sid;
-    TokenGroups->Groups[GroupCount].Attributes =
-        SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
-    GroupCount++;
 
     /* Member of 'Authenticated users' */
     RtlAllocateAndInitializeSid(&SystemAuthority,
@@ -436,211 +342,13 @@ BuildTokenGroups(IN PSID AccountDomainSid,
 }
 
 
-static
-NTSTATUS
-BuildTokenPrimaryGroup(PTOKEN_PRIMARY_GROUP PrimaryGroup,
-                       PSID PrimaryGroupSid)
-{
-    ULONG RidCount;
-    ULONG Size;
-
-    RidCount = *RtlSubAuthorityCountSid(PrimaryGroupSid);
-    Size = RtlLengthRequiredSid(RidCount);
-
-    PrimaryGroup->PrimaryGroup = DispatchTable.AllocateLsaHeap(Size);
-    if (PrimaryGroup->PrimaryGroup == NULL)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    RtlCopyMemory(PrimaryGroup->PrimaryGroup,
-                  PrimaryGroupSid,
-                  Size);
-
-    return STATUS_SUCCESS;
-}
-
-static
-NTSTATUS
-BuildTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges)
-{
-    /* FIXME shouldn't use hard-coded list of privileges */
-    static struct
-    {
-      LPCWSTR PrivName;
-      DWORD Attributes;
-    }
-    DefaultPrivs[] =
-    {
-      { L"SeMachineAccountPrivilege", 0 },
-      { L"SeSecurityPrivilege", 0 },
-      { L"SeTakeOwnershipPrivilege", 0 },
-      { L"SeLoadDriverPrivilege", 0 },
-      { L"SeSystemProfilePrivilege", 0 },
-      { L"SeSystemtimePrivilege", 0 },
-      { L"SeProfileSingleProcessPrivilege", 0 },
-      { L"SeIncreaseBasePriorityPrivilege", 0 },
-      { L"SeCreatePagefilePrivilege", 0 },
-      { L"SeBackupPrivilege", 0 },
-      { L"SeRestorePrivilege", 0 },
-      { L"SeShutdownPrivilege", 0 },
-      { L"SeDebugPrivilege", 0 },
-      { L"SeSystemEnvironmentPrivilege", 0 },
-      { L"SeChangeNotifyPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-      { L"SeRemoteShutdownPrivilege", 0 },
-      { L"SeUndockPrivilege", 0 },
-      { L"SeEnableDelegationPrivilege", 0 },
-      { L"SeImpersonatePrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-      { L"SeCreateGlobalPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
-    };
-    PTOKEN_PRIVILEGES Privileges = NULL;
-    ULONG i;
-    RPC_UNICODE_STRING PrivilegeName;
-    LSAPR_HANDLE PolicyHandle = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    Status = LsaIOpenPolicyTrusted(&PolicyHandle);
-    if (!NT_SUCCESS(Status))
-    {
-        goto done;
-    }
-
-    /* Allocate and initialize token privileges */
-    Privileges = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_PRIVILEGES) +
-                                               sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]) *
-                                               sizeof(LUID_AND_ATTRIBUTES));
-    if (Privileges == NULL)
-    {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto done;
-    }
-
-    Privileges->PrivilegeCount = 0;
-    for (i = 0; i < sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]); i++)
-    {
-        PrivilegeName.Length = wcslen(DefaultPrivs[i].PrivName) * sizeof(WCHAR);
-        PrivilegeName.MaximumLength = PrivilegeName.Length + sizeof(WCHAR);
-        PrivilegeName.Buffer = (LPWSTR)DefaultPrivs[i].PrivName;
-
-        Status = LsarLookupPrivilegeValue(PolicyHandle,
-                                          &PrivilegeName,
-                                          &Privileges->Privileges[Privileges->PrivilegeCount].Luid);
-        if (!NT_SUCCESS(Status))
-        {
-            WARN("Can't set privilege %S\n", DefaultPrivs[i].PrivName);
-        }
-        else
-        {
-            Privileges->Privileges[Privileges->PrivilegeCount].Attributes = DefaultPrivs[i].Attributes;
-            Privileges->PrivilegeCount++;
-        }
-    }
-
-    *TokenPrivileges = Privileges;
-
-done:
-    if (PolicyHandle != NULL)
-        LsarClose(PolicyHandle);
-
-    return Status;
-}
-
-
-static
-NTSTATUS
-BuildTokenOwner(PTOKEN_OWNER Owner,
-                PSID OwnerSid)
-{
-    ULONG RidCount;
-    ULONG Size;
-
-    RidCount = *RtlSubAuthorityCountSid(OwnerSid);
-    Size = RtlLengthRequiredSid(RidCount);
-
-    Owner->Owner = DispatchTable.AllocateLsaHeap(Size);
-    if (Owner->Owner == NULL)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    RtlCopyMemory(Owner->Owner,
-                  OwnerSid,
-                  Size);
-
-    return STATUS_SUCCESS;
-}
-
-
-static
-NTSTATUS
-BuildTokenDefaultDacl(PTOKEN_DEFAULT_DACL DefaultDacl,
-                      PSID OwnerSid)
-{
-    SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
-    PSID LocalSystemSid = NULL;
-    PACL Dacl = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                1,
-                                SECURITY_LOCAL_SYSTEM_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &LocalSystemSid);
-
-    Dacl = DispatchTable.AllocateLsaHeap(1024);
-    if (Dacl == NULL)
-    {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto done;
-    }
-
-    Status = RtlCreateAcl(Dacl, 1024, ACL_REVISION);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    RtlAddAccessAllowedAce(Dacl,
-                           ACL_REVISION,
-                           GENERIC_ALL,
-                           OwnerSid);
-
-    /* SID: S-1-5-18 */
-    RtlAddAccessAllowedAce(Dacl,
-                           ACL_REVISION,
-                           GENERIC_ALL,
-                           LocalSystemSid);
-
-    DefaultDacl->DefaultDacl = Dacl;
-
-done:
-    if (!NT_SUCCESS(Status))
-    {
-        if (Dacl != NULL)
-            DispatchTable.FreeLsaHeap(Dacl);
-    }
-
-    if (LocalSystemSid != NULL)
-        RtlFreeSid(LocalSystemSid);
-
-    return Status;
-}
-
-
 static
 NTSTATUS
 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
                             PRPC_SID AccountDomainSid,
-                            ULONG RelativeId,
-                            PLUID LogonId)
+                            PSAMPR_USER_INFO_BUFFER UserInfo)
 {
     PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
-    PSID OwnerSid = NULL;
-    PSID PrimaryGroupSid = NULL;
     ULONG i;
     NTSTATUS Status = STATUS_SUCCESS;
 
@@ -657,34 +365,18 @@ BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
 
     Status = BuildTokenUser(&Buffer->User,
                             (PSID)AccountDomainSid,
-                            RelativeId);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    Status = BuildTokenGroups((PSID)AccountDomainSid,
-                              LogonId,
-                              &Buffer->Groups,
-                              &PrimaryGroupSid,
-                              &OwnerSid);
+                            UserInfo->All.UserId);
     if (!NT_SUCCESS(Status))
         goto done;
 
     Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
-                                    PrimaryGroupSid);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    Status = BuildTokenPrivileges(&Buffer->Privileges);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    Status = BuildTokenOwner(&Buffer->Owner,
-                             OwnerSid);
+                                    (PSID)AccountDomainSid,
+                                    UserInfo->All.PrimaryGroupId);
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = BuildTokenDefaultDacl(&Buffer->DefaultDacl,
-                                   OwnerSid);
+    Status = BuildTokenGroups(&Buffer->Groups,
+                              (PSID)AccountDomainSid);
     if (!NT_SUCCESS(Status))
         goto done;
 
@@ -712,12 +404,6 @@ done:
             if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
                 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
 
-            if (Buffer->Privileges != NULL)
-                DispatchTable.FreeLsaHeap(Buffer->Privileges);
-
-            if (Buffer->Owner.Owner != NULL)
-                DispatchTable.FreeLsaHeap(Buffer->Owner.Owner);
-
             if (Buffer->DefaultDacl.DefaultDacl != NULL)
                 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
 
@@ -731,17 +417,42 @@ done:
 
 static
 NTSTATUS
-ChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
-               IN PVOID ProtocolSubmitBuffer,
-               IN PVOID ClientBufferBase,
-               IN ULONG SubmitBufferLength,
-               OUT PVOID *ProtocolReturnBuffer,
-               OUT PULONG ReturnBufferLength,
-               OUT PNTSTATUS ProtocolStatus)
+MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
+                   IN PVOID ProtocolSubmitBuffer,
+                   IN PVOID ClientBufferBase,
+                   IN ULONG SubmitBufferLength,
+                   OUT PVOID *ProtocolReturnBuffer,
+                   OUT PULONG ReturnBufferLength,
+                   OUT PNTSTATUS ProtocolStatus)
 {
     PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
     ULONG_PTR PtrOffset;
 
+    SAMPR_HANDLE ServerHandle = NULL;
+    SAMPR_HANDLE DomainHandle = NULL;
+    SAMPR_HANDLE UserHandle = NULL;
+    PRPC_SID DomainSid = NULL;
+    RPC_UNICODE_STRING Names[1];
+    SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
+    SAMPR_ULONG_ARRAY Use = {0, NULL};
+    NTSTATUS Status;
+
+    ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
+    ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
+    ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
+    ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
+    OEM_STRING LmPwdString;
+    CHAR LmPwdBuffer[15];
+    BOOLEAN OldLmPasswordPresent = FALSE;
+    BOOLEAN NewLmPasswordPresent = FALSE;
+
+    ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
+    ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
+    ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
+    ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
+    PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
+    PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
+
     TRACE("()\n");
 
     RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
@@ -749,18 +460,225 @@ ChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
     /* Fix-up pointers in the request buffer info */
     PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
 
-    RequestBuffer->DomainName.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->DomainName.Buffer + PtrOffset);
-    RequestBuffer->AccountName.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->AccountName.Buffer + PtrOffset);
-    RequestBuffer->OldPassword.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->OldPassword.Buffer + PtrOffset);
-    RequestBuffer->NewPassword.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->NewPassword.Buffer + PtrOffset);
+    RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
+    RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
+    RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
+    RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
 
     TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
     TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
     TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
     TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
 
+    /* Connect to the SAM server */
+    Status = SamIConnect(NULL,
+                         &ServerHandle,
+                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+                         TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
 
-    return STATUS_SUCCESS;
+    /* Get the domain SID */
+    Status = SamrLookupDomainInSamServer(ServerHandle,
+                                         (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
+                                         &DomainSid);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
+        goto done;
+    }
+
+    /* Open the domain */
+    Status = SamrOpenDomain(ServerHandle,
+                            DOMAIN_LOOKUP,
+                            DomainSid,
+                            &DomainHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
+        goto done;
+    }
+
+    Names[0].Length = RequestBuffer->AccountName.Length;
+    Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
+    Names[0].Buffer = RequestBuffer->AccountName.Buffer;
+
+    /* Try to get the RID for the user name */
+    Status = SamrLookupNamesInDomain(DomainHandle,
+                                     1,
+                                     Names,
+                                     &RelativeIds,
+                                     &Use);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
+        Status = STATUS_NO_SUCH_USER;
+        goto done;
+    }
+
+    /* Fail, if it is not a user account */
+    if (Use.Element[0] != SidTypeUser)
+    {
+        TRACE("Account is not a user account!\n");
+        Status = STATUS_NO_SUCH_USER;
+        goto done;
+    }
+
+    /* Open the user object */
+    Status = SamrOpenUser(DomainHandle,
+                          USER_CHANGE_PASSWORD,
+                          RelativeIds.Element[0],
+                          &UserHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
+        goto done;
+    }
+
+
+    /* Calculate the NT hash for the old password */
+    Status = SystemFunction007(&RequestBuffer->OldPassword,
+                               (LPBYTE)&OldNtPassword);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Calculate the NT hash for the new password */
+    Status = SystemFunction007(&RequestBuffer->NewPassword,
+                               (LPBYTE)&NewNtPassword);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Calculate the LM password and hash for the old password */
+    LmPwdString.Length = 15;
+    LmPwdString.MaximumLength = 15;
+    LmPwdString.Buffer = LmPwdBuffer;
+    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
+
+    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
+                                               &RequestBuffer->OldPassword,
+                                               FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Calculate the LM hash value of the password */
+        Status = SystemFunction006(LmPwdString.Buffer,
+                                   (LPSTR)&OldLmPassword);
+        if (NT_SUCCESS(Status))
+        {
+            OldLmPasswordPresent = TRUE;
+        }
+    }
+
+    /* Calculate the LM password and hash for the new password */
+    LmPwdString.Length = 15;
+    LmPwdString.MaximumLength = 15;
+    LmPwdString.Buffer = LmPwdBuffer;
+    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
+
+    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
+                                               &RequestBuffer->NewPassword,
+                                               FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Calculate the LM hash value of the password */
+        Status = SystemFunction006(LmPwdString.Buffer,
+                                   (LPSTR)&NewLmPassword);
+        if (NT_SUCCESS(Status))
+        {
+            NewLmPasswordPresent = TRUE;
+        }
+    }
+
+    /* Encrypt the old and new LM passwords, if they exist */
+    if (OldLmPasswordPresent && NewLmPasswordPresent)
+    {
+        /* Encrypt the old LM password */
+        Status = SystemFunction012((const BYTE *)&OldLmPassword,
+                                   (const BYTE *)&NewLmPassword,
+                                   (LPBYTE)&OldLmEncryptedWithNewLm);
+        if (!NT_SUCCESS(Status))
+        {
+            TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
+            goto done;
+        }
+
+        /* Encrypt the new LM password */
+        Status = SystemFunction012((const BYTE *)&NewLmPassword,
+                                   (const BYTE *)&OldLmPassword,
+                                   (LPBYTE)&NewLmEncryptedWithOldLm);
+        if (!NT_SUCCESS(Status))
+        {
+            TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
+            goto done;
+        }
+
+        pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
+        pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
+    }
+
+    /* Encrypt the old NT password */
+    Status = SystemFunction012((const BYTE *)&OldNtPassword,
+                               (const BYTE *)&NewNtPassword,
+                               (LPBYTE)&OldNtEncryptedWithNewNt);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Encrypt the new NT password */
+    Status = SystemFunction012((const BYTE *)&NewNtPassword,
+                               (const BYTE *)&OldNtPassword,
+                               (LPBYTE)&NewNtEncryptedWithOldNt);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Change the password */
+    Status = SamrChangePasswordUser(UserHandle,
+                                    OldLmPasswordPresent && NewLmPasswordPresent,
+                                    pOldLmEncryptedWithNewLm,
+                                    pNewLmEncryptedWithOldLm,
+                                    TRUE,
+                                    &OldNtEncryptedWithNewNt,
+                                    &NewNtEncryptedWithOldNt,
+                                    FALSE,
+                                    NULL,
+                                    FALSE,
+                                    NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
+        goto done;
+    }
+
+done:
+    if (UserHandle != NULL)
+        SamrCloseHandle(&UserHandle);
+
+    SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
+    SamIFree_SAMPR_ULONG_ARRAY(&Use);
+
+    if (DomainHandle != NULL)
+        SamrCloseHandle(&DomainHandle);
+
+    if (DomainSid != NULL)
+        SamIFreeVoid(DomainSid);
+
+    if (ServerHandle != NULL)
+        SamrCloseHandle(&ServerHandle);
+
+    return Status;
 }
 
 
@@ -807,36 +725,49 @@ MsvpCheckPassword(PUNICODE_STRING UserPassword,
         UserNtPasswordPresent = TRUE;
     }
 
-    Status = STATUS_SUCCESS;
+    Status = STATUS_WRONG_PASSWORD;
 
+    /* Succeed, if no password has been set */
+    if (UserInfo->All.NtPasswordPresent == FALSE &&
+        UserInfo->All.LmPasswordPresent == FALSE)
+    {
+        TRACE("No password check!\n");
+        Status = STATUS_SUCCESS;
+        goto done;
+    }
+
+    /* Succeed, if NT password matches */
     if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
     {
         TRACE("Check NT password hashes:\n");
-        if (!RtlEqualMemory(&UserNtPassword,
-                            UserInfo->All.NtOwfPassword.Buffer,
-                            sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+        if (RtlEqualMemory(&UserNtPassword,
+                           UserInfo->All.NtOwfPassword.Buffer,
+                           sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
         {
-            TRACE("  failed!\n");
-            Status = STATUS_WRONG_PASSWORD;
+            TRACE("  success!\n");
+            Status = STATUS_SUCCESS;
+            goto done;
         }
+
+        TRACE("  failed!\n");
     }
-    else if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
+
+    /* Succeed, if LM password matches */
+    if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
     {
         TRACE("Check LM password hashes:\n");
-        if (!RtlEqualMemory(&UserLmPassword,
-                            UserInfo->All.LmOwfPassword.Buffer,
-                            sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+        if (RtlEqualMemory(&UserLmPassword,
+                           UserInfo->All.LmOwfPassword.Buffer,
+                           sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
         {
-            TRACE("  failed!\n");
-            Status = STATUS_WRONG_PASSWORD;
+            TRACE("  success!\n");
+            Status = STATUS_SUCCESS;
+            goto done;
         }
-    }
-    else
-    {
-        TRACE("No matching hashes available!\n");
-        Status = STATUS_WRONG_PASSWORD;
+        TRACE("  failed!\n");
     }
 
+done:
     return Status;
 }
 
@@ -878,13 +809,13 @@ LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
             break;
 
         case MsV1_0ChangePassword:
-            Status = ChangePassword(ClientRequest,
-                                    ProtocolSubmitBuffer,
-                                    ClientBufferBase,
-                                    SubmitBufferLength,
-                                    ProtocolReturnBuffer,
-                                    ReturnBufferLength,
-                                    ProtocolStatus);
+            Status = MsvpChangePassword(ClientRequest,
+                                        ProtocolSubmitBuffer,
+                                        ClientBufferBase,
+                                        SubmitBufferLength,
+                                        ProtocolReturnBuffer,
+                                        ReturnBufferLength,
+                                        ProtocolStatus);
             break;
 
         case MsV1_0ChangeCachedPassword:
@@ -1204,8 +1135,7 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
     /* Build and fill the token information buffer */
     Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
                                          AccountDomainSid,
-                                         RelativeIds.Element[0],
-                                         LogonId);
+                                         UserInfo);
     if (!NT_SUCCESS(Status))
     {
         TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);