xref: /reactos/dll/win32/msv1_0/msv1_0.c (revision 845faec4)
1 /*
2  * PROJECT:     Authentication Package DLL
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/win32/msv1_0/msv1_0.c
5  * PURPOSE:     Main file
6  * COPYRIGHT:   Copyright 2013 Eric Kohl
7  */
8 
9 /* INCLUDES ****************************************************************/
10 
11 #include "msv1_0.h"
12 
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
14 
15 
16 /* GLOBALS *****************************************************************/
17 
18 LSA_DISPATCH_TABLE DispatchTable;
19 
20 
21 /* FUNCTIONS ***************************************************************/
22 
23 static
24 NTSTATUS
25 GetDomainSid(PRPC_SID *Sid)
26 {
27     LSAPR_HANDLE PolicyHandle = NULL;
28     PLSAPR_POLICY_INFORMATION PolicyInfo = NULL;
29     ULONG Length = 0;
30     NTSTATUS Status;
31 
32     Status = LsaIOpenPolicyTrusted(&PolicyHandle);
33     if (!NT_SUCCESS(Status))
34     {
35         TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status);
36         return Status;
37     }
38 
39     Status = LsarQueryInformationPolicy(PolicyHandle,
40                                         PolicyAccountDomainInformation,
41                                         &PolicyInfo);
42     if (!NT_SUCCESS(Status))
43     {
44         TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status);
45         goto done;
46     }
47 
48     Length = RtlLengthSid(PolicyInfo->PolicyAccountDomainInfo.Sid);
49 
50     *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
51     if (*Sid == NULL)
52     {
53         ERR("Failed to allocate SID\n");
54         Status = STATUS_INSUFFICIENT_RESOURCES;
55         goto done;
56     }
57 
58     memcpy(*Sid, PolicyInfo->PolicyAccountDomainInfo.Sid, Length);
59 
60 done:
61     if (PolicyInfo != NULL)
62         LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation,
63                                           PolicyInfo);
64 
65     if (PolicyHandle != NULL)
66         LsarClose(&PolicyHandle);
67 
68     return Status;
69 }
70 
71 
72 static
73 NTSTATUS
74 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
75                               IN PSAMPR_USER_INFO_BUFFER UserInfo,
76                               IN PUNICODE_STRING LogonServer,
77                               OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
78                               OUT PULONG ProfileBufferLength)
79 {
80     PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
81     PVOID ClientBaseAddress = NULL;
82     LPWSTR Ptr;
83     ULONG BufferLength;
84     NTSTATUS Status = STATUS_SUCCESS;
85 
86     *ProfileBuffer = NULL;
87     *ProfileBufferLength = 0;
88 
89     BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
90                    UserInfo->All.FullName.Length + sizeof(WCHAR) +
91                    UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
92                    UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
93                    UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
94                    UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
95                    LogonServer->Length + sizeof(WCHAR);
96 
97     LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
98     if (LocalBuffer == NULL)
99     {
100         TRACE("Failed to allocate the local buffer!\n");
101         Status = STATUS_INSUFFICIENT_RESOURCES;
102         goto done;
103     }
104 
105     Status = DispatchTable.AllocateClientBuffer(ClientRequest,
106                                                 BufferLength,
107                                                 &ClientBaseAddress);
108     if (!NT_SUCCESS(Status))
109     {
110         TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
111         goto done;
112     }
113 
114     TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
115 
116     Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
117 
118     LocalBuffer->MessageType = MsV1_0InteractiveProfile;
119     LocalBuffer->LogonCount = UserInfo->All.LogonCount;
120     LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
121 
122     LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
123     LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
124 
125 //    LocalBuffer->LogoffTime.LowPart =
126 //    LocalBuffer->LogoffTime.HighPart =
127 
128 //    LocalBuffer->KickOffTime.LowPart =
129 //    LocalBuffer->KickOffTime.HighPart =
130 
131     LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
132     LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
133 
134     LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
135     LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
136 
137     LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
138     LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
139 
140     LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
141     LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
142     LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
143     memcpy(Ptr,
144            UserInfo->All.ScriptPath.Buffer,
145            UserInfo->All.ScriptPath.Length);
146 
147     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
148 
149     LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
150     LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
151     LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
152     memcpy(Ptr,
153            UserInfo->All.HomeDirectory.Buffer,
154            UserInfo->All.HomeDirectory.Length);
155 
156     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
157 
158     LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
159     LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
160     LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
161     memcpy(Ptr,
162            UserInfo->All.FullName.Buffer,
163            UserInfo->All.FullName.Length);
164     TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
165 
166     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
167 
168     LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
169     LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
170     LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
171     memcpy(Ptr,
172            UserInfo->All.ProfilePath.Buffer,
173            UserInfo->All.ProfilePath.Length);
174 
175     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
176 
177     LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
178     LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
179     LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
180     memcpy(Ptr,
181            UserInfo->All.HomeDirectoryDrive.Buffer,
182            UserInfo->All.HomeDirectoryDrive.Length);
183 
184     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
185 
186     LocalBuffer->LogonServer.Length = LogonServer->Length;
187     LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
188     LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
189     memcpy(Ptr,
190            LogonServer->Buffer,
191            LogonServer->Length);
192 
193     LocalBuffer->UserFlags = 0;
194 
195     Status = DispatchTable.CopyToClientBuffer(ClientRequest,
196                                               BufferLength,
197                                               ClientBaseAddress,
198                                               LocalBuffer);
199     if (!NT_SUCCESS(Status))
200     {
201         TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
202         goto done;
203     }
204 
205     *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
206     *ProfileBufferLength = BufferLength;
207 
208 done:
209     if (LocalBuffer != NULL)
210         DispatchTable.FreeLsaHeap(LocalBuffer);
211 
212     if (!NT_SUCCESS(Status))
213     {
214         if (ClientBaseAddress != NULL)
215             DispatchTable.FreeClientBuffer(ClientRequest,
216                                            ClientBaseAddress);
217     }
218 
219     return Status;
220 }
221 
222 
223 static
224 PSID
225 AppendRidToSid(PSID SrcSid,
226                ULONG Rid)
227 {
228     PSID DstSid = NULL;
229     UCHAR RidCount;
230 
231     RidCount = *RtlSubAuthorityCountSid(SrcSid);
232     if (RidCount >= 8)
233         return NULL;
234 
235     DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
236     if (DstSid == NULL)
237         return NULL;
238 
239     RtlCopyMemory(DstSid,
240                   SrcSid,
241                   RtlLengthRequiredSid(RidCount));
242 
243     *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
244     *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
245 
246     return DstSid;
247 }
248 
249 static
250 NTSTATUS
251 BuildTokenUser(OUT PTOKEN_USER User,
252                IN PSID AccountDomainSid,
253                IN ULONG RelativeId)
254 {
255     User->User.Sid = AppendRidToSid(AccountDomainSid,
256                                     RelativeId);
257     if (User->User.Sid == NULL)
258     {
259         ERR("Could not create the user SID\n");
260         return STATUS_INSUFFICIENT_RESOURCES;
261     }
262 
263     User->User.Attributes = 0;
264 
265     return STATUS_SUCCESS;
266 }
267 
268 
269 static
270 NTSTATUS
271 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
272                        IN PSID AccountDomainSid,
273                        IN ULONG RelativeId)
274 {
275     PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
276                                                 RelativeId);
277     if (PrimaryGroup->PrimaryGroup == NULL)
278     {
279         ERR("Could not create the primary group SID\n");
280         return STATUS_INSUFFICIENT_RESOURCES;
281     }
282 
283     return STATUS_SUCCESS;
284 }
285 
286 
287 static
288 NTSTATUS
289 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
290                  IN PSID AccountDomainSid)
291 {
292     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
293     PTOKEN_GROUPS TokenGroups;
294 #define MAX_GROUPS 2
295     DWORD GroupCount = 0;
296     PSID Sid;
297     NTSTATUS Status = STATUS_SUCCESS;
298 
299     TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
300                                                 MAX_GROUPS * sizeof(SID_AND_ATTRIBUTES));
301     if (TokenGroups == NULL)
302     {
303         return STATUS_INSUFFICIENT_RESOURCES;
304     }
305 
306     Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
307     if (Sid == NULL)
308     {
309 
310     }
311 
312     /* Member of the domain */
313     TokenGroups->Groups[GroupCount].Sid = Sid;
314     TokenGroups->Groups[GroupCount].Attributes =
315         SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
316     GroupCount++;
317 
318 
319     /* Member of 'Authenticated users' */
320     RtlAllocateAndInitializeSid(&SystemAuthority,
321                                 1,
322                                 SECURITY_AUTHENTICATED_USER_RID,
323                                 SECURITY_NULL_RID,
324                                 SECURITY_NULL_RID,
325                                 SECURITY_NULL_RID,
326                                 SECURITY_NULL_RID,
327                                 SECURITY_NULL_RID,
328                                 SECURITY_NULL_RID,
329                                 SECURITY_NULL_RID,
330                                 &Sid);
331     TokenGroups->Groups[GroupCount].Sid = Sid;
332     TokenGroups->Groups[GroupCount].Attributes =
333         SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
334     GroupCount++;
335 
336     TokenGroups->GroupCount = GroupCount;
337     ASSERT(TokenGroups->GroupCount <= MAX_GROUPS);
338 
339     *Groups = TokenGroups;
340 
341     return Status;
342 }
343 
344 
345 static
346 NTSTATUS
347 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
348                             PRPC_SID AccountDomainSid,
349                             PSAMPR_USER_INFO_BUFFER UserInfo)
350 {
351     PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
352     ULONG i;
353     NTSTATUS Status = STATUS_SUCCESS;
354 
355     Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
356     if (Buffer == NULL)
357     {
358         TRACE("Failed to allocate the local buffer!\n");
359         Status = STATUS_INSUFFICIENT_RESOURCES;
360         goto done;
361     }
362 
363     /* FIXME: */
364     Buffer->ExpirationTime.QuadPart = -1;
365 
366     Status = BuildTokenUser(&Buffer->User,
367                             (PSID)AccountDomainSid,
368                             UserInfo->All.UserId);
369     if (!NT_SUCCESS(Status))
370         goto done;
371 
372     Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
373                                     (PSID)AccountDomainSid,
374                                     UserInfo->All.PrimaryGroupId);
375     if (!NT_SUCCESS(Status))
376         goto done;
377 
378     Status = BuildTokenGroups(&Buffer->Groups,
379                               (PSID)AccountDomainSid);
380     if (!NT_SUCCESS(Status))
381         goto done;
382 
383     *TokenInformation = Buffer;
384 
385 done:
386     if (!NT_SUCCESS(Status))
387     {
388         if (Buffer != NULL)
389         {
390             if (Buffer->User.User.Sid != NULL)
391                 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
392 
393             if (Buffer->Groups != NULL)
394             {
395                 for (i = 0; i < Buffer->Groups->GroupCount; i++)
396                 {
397                     if (Buffer->Groups->Groups[i].Sid != NULL)
398                         DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
399                 }
400 
401                 DispatchTable.FreeLsaHeap(Buffer->Groups);
402             }
403 
404             if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
405                 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
406 
407             if (Buffer->DefaultDacl.DefaultDacl != NULL)
408                 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
409 
410             DispatchTable.FreeLsaHeap(Buffer);
411         }
412     }
413 
414     return Status;
415 }
416 
417 
418 static
419 NTSTATUS
420 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
421                    IN PVOID ProtocolSubmitBuffer,
422                    IN PVOID ClientBufferBase,
423                    IN ULONG SubmitBufferLength,
424                    OUT PVOID *ProtocolReturnBuffer,
425                    OUT PULONG ReturnBufferLength,
426                    OUT PNTSTATUS ProtocolStatus)
427 {
428     PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
429     ULONG_PTR PtrOffset;
430 
431     SAMPR_HANDLE ServerHandle = NULL;
432     SAMPR_HANDLE DomainHandle = NULL;
433     SAMPR_HANDLE UserHandle = NULL;
434     PRPC_SID DomainSid = NULL;
435     RPC_UNICODE_STRING Names[1];
436     SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
437     SAMPR_ULONG_ARRAY Use = {0, NULL};
438     NTSTATUS Status;
439 
440     ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
441     ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
442     ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
443     ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
444     OEM_STRING LmPwdString;
445     CHAR LmPwdBuffer[15];
446     BOOLEAN OldLmPasswordPresent = FALSE;
447     BOOLEAN NewLmPasswordPresent = FALSE;
448 
449     ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
450     ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
451     ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
452     ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
453     PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
454     PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
455 
456     TRACE("()\n");
457 
458     RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
459 
460     /* Fix-up pointers in the request buffer info */
461     PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
462 
463     RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
464     RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
465     RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
466     RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
467 
468     TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
469     TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
470     TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
471     TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
472 
473     /* Connect to the SAM server */
474     Status = SamIConnect(NULL,
475                          &ServerHandle,
476                          SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
477                          TRUE);
478     if (!NT_SUCCESS(Status))
479     {
480         TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
481         goto done;
482     }
483 
484     /* Get the domain SID */
485     Status = SamrLookupDomainInSamServer(ServerHandle,
486                                          (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
487                                          &DomainSid);
488     if (!NT_SUCCESS(Status))
489     {
490         TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
491         goto done;
492     }
493 
494     /* Open the domain */
495     Status = SamrOpenDomain(ServerHandle,
496                             DOMAIN_LOOKUP,
497                             DomainSid,
498                             &DomainHandle);
499     if (!NT_SUCCESS(Status))
500     {
501         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
502         goto done;
503     }
504 
505     Names[0].Length = RequestBuffer->AccountName.Length;
506     Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
507     Names[0].Buffer = RequestBuffer->AccountName.Buffer;
508 
509     /* Try to get the RID for the user name */
510     Status = SamrLookupNamesInDomain(DomainHandle,
511                                      1,
512                                      Names,
513                                      &RelativeIds,
514                                      &Use);
515     if (!NT_SUCCESS(Status))
516     {
517         TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
518         Status = STATUS_NO_SUCH_USER;
519         goto done;
520     }
521 
522     /* Fail, if it is not a user account */
523     if (Use.Element[0] != SidTypeUser)
524     {
525         TRACE("Account is not a user account!\n");
526         Status = STATUS_NO_SUCH_USER;
527         goto done;
528     }
529 
530     /* Open the user object */
531     Status = SamrOpenUser(DomainHandle,
532                           USER_CHANGE_PASSWORD,
533                           RelativeIds.Element[0],
534                           &UserHandle);
535     if (!NT_SUCCESS(Status))
536     {
537         TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
538         goto done;
539     }
540 
541 
542     /* Calculate the NT hash for the old password */
543     Status = SystemFunction007(&RequestBuffer->OldPassword,
544                                (LPBYTE)&OldNtPassword);
545     if (!NT_SUCCESS(Status))
546     {
547         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
548         goto done;
549     }
550 
551     /* Calculate the NT hash for the new password */
552     Status = SystemFunction007(&RequestBuffer->NewPassword,
553                                (LPBYTE)&NewNtPassword);
554     if (!NT_SUCCESS(Status))
555     {
556         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
557         goto done;
558     }
559 
560     /* Calculate the LM password and hash for the old password */
561     LmPwdString.Length = 15;
562     LmPwdString.MaximumLength = 15;
563     LmPwdString.Buffer = LmPwdBuffer;
564     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
565 
566     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
567                                                &RequestBuffer->OldPassword,
568                                                FALSE);
569     if (NT_SUCCESS(Status))
570     {
571         /* Calculate the LM hash value of the password */
572         Status = SystemFunction006(LmPwdString.Buffer,
573                                    (LPSTR)&OldLmPassword);
574         if (NT_SUCCESS(Status))
575         {
576             OldLmPasswordPresent = TRUE;
577         }
578     }
579 
580     /* Calculate the LM password and hash for the new password */
581     LmPwdString.Length = 15;
582     LmPwdString.MaximumLength = 15;
583     LmPwdString.Buffer = LmPwdBuffer;
584     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
585 
586     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
587                                                &RequestBuffer->NewPassword,
588                                                FALSE);
589     if (NT_SUCCESS(Status))
590     {
591         /* Calculate the LM hash value of the password */
592         Status = SystemFunction006(LmPwdString.Buffer,
593                                    (LPSTR)&NewLmPassword);
594         if (NT_SUCCESS(Status))
595         {
596             NewLmPasswordPresent = TRUE;
597         }
598     }
599 
600     /* Encrypt the old and new LM passwords, if they exist */
601     if (OldLmPasswordPresent && NewLmPasswordPresent)
602     {
603         /* Encrypt the old LM password */
604         Status = SystemFunction012((const BYTE *)&OldLmPassword,
605                                    (const BYTE *)&NewLmPassword,
606                                    (LPBYTE)&OldLmEncryptedWithNewLm);
607         if (!NT_SUCCESS(Status))
608         {
609             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
610             goto done;
611         }
612 
613         /* Encrypt the new LM password */
614         Status = SystemFunction012((const BYTE *)&NewLmPassword,
615                                    (const BYTE *)&OldLmPassword,
616                                    (LPBYTE)&NewLmEncryptedWithOldLm);
617         if (!NT_SUCCESS(Status))
618         {
619             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
620             goto done;
621         }
622 
623         pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
624         pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
625     }
626 
627     /* Encrypt the old NT password */
628     Status = SystemFunction012((const BYTE *)&OldNtPassword,
629                                (const BYTE *)&NewNtPassword,
630                                (LPBYTE)&OldNtEncryptedWithNewNt);
631     if (!NT_SUCCESS(Status))
632     {
633         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
634         goto done;
635     }
636 
637     /* Encrypt the new NT password */
638     Status = SystemFunction012((const BYTE *)&NewNtPassword,
639                                (const BYTE *)&OldNtPassword,
640                                (LPBYTE)&NewNtEncryptedWithOldNt);
641     if (!NT_SUCCESS(Status))
642     {
643         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
644         goto done;
645     }
646 
647     /* Change the password */
648     Status = SamrChangePasswordUser(UserHandle,
649                                     OldLmPasswordPresent && NewLmPasswordPresent,
650                                     pOldLmEncryptedWithNewLm,
651                                     pNewLmEncryptedWithOldLm,
652                                     TRUE,
653                                     &OldNtEncryptedWithNewNt,
654                                     &NewNtEncryptedWithOldNt,
655                                     FALSE,
656                                     NULL,
657                                     FALSE,
658                                     NULL);
659     if (!NT_SUCCESS(Status))
660     {
661         TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
662         goto done;
663     }
664 
665 done:
666     if (UserHandle != NULL)
667         SamrCloseHandle(&UserHandle);
668 
669     SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
670     SamIFree_SAMPR_ULONG_ARRAY(&Use);
671 
672     if (DomainHandle != NULL)
673         SamrCloseHandle(&DomainHandle);
674 
675     if (DomainSid != NULL)
676         SamIFreeVoid(DomainSid);
677 
678     if (ServerHandle != NULL)
679         SamrCloseHandle(&ServerHandle);
680 
681     return Status;
682 }
683 
684 
685 static
686 NTSTATUS
687 MsvpCheckPassword(PUNICODE_STRING UserPassword,
688                   PSAMPR_USER_INFO_BUFFER UserInfo)
689 {
690     ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
691     ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
692     BOOLEAN UserLmPasswordPresent = FALSE;
693     BOOLEAN UserNtPasswordPresent = FALSE;
694     OEM_STRING LmPwdString;
695     CHAR LmPwdBuffer[15];
696     NTSTATUS Status;
697 
698     TRACE("(%p %p)\n", UserPassword, UserInfo);
699 
700     /* Calculate the LM password and hash for the users password */
701     LmPwdString.Length = 15;
702     LmPwdString.MaximumLength = 15;
703     LmPwdString.Buffer = LmPwdBuffer;
704     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
705 
706     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
707                                                UserPassword,
708                                                FALSE);
709     if (NT_SUCCESS(Status))
710     {
711         /* Calculate the LM hash value of the users password */
712         Status = SystemFunction006(LmPwdString.Buffer,
713                                    (LPSTR)&UserLmPassword);
714         if (NT_SUCCESS(Status))
715         {
716             UserLmPasswordPresent = TRUE;
717         }
718     }
719 
720     /* Calculate the NT hash of the users password */
721     Status = SystemFunction007(UserPassword,
722                                (LPBYTE)&UserNtPassword);
723     if (NT_SUCCESS(Status))
724     {
725         UserNtPasswordPresent = TRUE;
726     }
727 
728     Status = STATUS_WRONG_PASSWORD;
729 
730     /* Succeed, if no password has been set */
731     if (UserInfo->All.NtPasswordPresent == FALSE &&
732         UserInfo->All.LmPasswordPresent == FALSE)
733     {
734         TRACE("No password check!\n");
735         Status = STATUS_SUCCESS;
736         goto done;
737     }
738 
739     /* Succeed, if NT password matches */
740     if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
741     {
742         TRACE("Check NT password hashes:\n");
743         if (RtlEqualMemory(&UserNtPassword,
744                            UserInfo->All.NtOwfPassword.Buffer,
745                            sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
746         {
747             TRACE("  success!\n");
748             Status = STATUS_SUCCESS;
749             goto done;
750         }
751 
752         TRACE("  failed!\n");
753     }
754 
755     /* Succeed, if LM password matches */
756     if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
757     {
758         TRACE("Check LM password hashes:\n");
759         if (RtlEqualMemory(&UserLmPassword,
760                            UserInfo->All.LmOwfPassword.Buffer,
761                            sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
762         {
763             TRACE("  success!\n");
764             Status = STATUS_SUCCESS;
765             goto done;
766         }
767         TRACE("  failed!\n");
768     }
769 
770 done:
771     return Status;
772 }
773 
774 
775 /*
776  * @unimplemented
777  */
778 NTSTATUS
779 NTAPI
780 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
781                  IN PVOID ProtocolSubmitBuffer,
782                  IN PVOID ClientBufferBase,
783                  IN ULONG SubmitBufferLength,
784                  OUT PVOID *ProtocolReturnBuffer,
785                  OUT PULONG ReturnBufferLength,
786                  OUT PNTSTATUS ProtocolStatus)
787 {
788     ULONG MessageType;
789     NTSTATUS Status;
790 
791     TRACE("()\n");
792 
793     if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
794         return STATUS_INVALID_PARAMETER;
795 
796     MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
797 
798     *ProtocolReturnBuffer = NULL;
799     *ReturnBufferLength = 0;
800 
801     switch (MessageType)
802     {
803         case MsV1_0Lm20ChallengeRequest:
804         case MsV1_0Lm20GetChallengeResponse:
805         case MsV1_0EnumerateUsers:
806         case MsV1_0GetUserInfo:
807         case MsV1_0ReLogonUsers:
808             Status = STATUS_NOT_IMPLEMENTED;
809             break;
810 
811         case MsV1_0ChangePassword:
812             Status = MsvpChangePassword(ClientRequest,
813                                         ProtocolSubmitBuffer,
814                                         ClientBufferBase,
815                                         SubmitBufferLength,
816                                         ProtocolReturnBuffer,
817                                         ReturnBufferLength,
818                                         ProtocolStatus);
819             break;
820 
821         case MsV1_0ChangeCachedPassword:
822         case MsV1_0GenericPassthrough:
823         case MsV1_0CacheLogon:
824         case MsV1_0SubAuth:
825         case MsV1_0DeriveCredential:
826         case MsV1_0CacheLookup:
827             Status = STATUS_NOT_IMPLEMENTED;
828             break;
829 
830         default:
831             return STATUS_INVALID_PARAMETER;
832     }
833 
834     return Status;
835 }
836 
837 
838 /*
839  * @unimplemented
840  */
841 NTSTATUS
842 NTAPI
843 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
844                             IN PVOID ProtocolSubmitBuffer,
845                             IN PVOID ClientBufferBase,
846                             IN ULONG SubmitBufferLength,
847                             OUT PVOID *ProtocolReturnBuffer,
848                             OUT PULONG ReturnBufferLength,
849                             OUT PNTSTATUS ProtocolStatus)
850 {
851     TRACE("()\n");
852     return STATUS_NOT_IMPLEMENTED;
853 }
854 
855 
856 /*
857  * @unimplemented
858  */
859 NTSTATUS
860 NTAPI
861 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
862                           IN PVOID ProtocolSubmitBuffer,
863                           IN PVOID ClientBufferBase,
864                           IN ULONG SubmitBufferLength,
865                           OUT PVOID *ProtocolReturnBuffer,
866                           OUT PULONG ReturnBufferLength,
867                           OUT PNTSTATUS ProtocolStatus)
868 {
869     TRACE("()\n");
870     return STATUS_NOT_IMPLEMENTED;
871 }
872 
873 
874 /*
875  * @unimplemented
876  */
877 NTSTATUS
878 NTAPI
879 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
880                        IN PLSA_DISPATCH_TABLE LsaDispatchTable,
881                        IN PLSA_STRING Database OPTIONAL,
882                        IN PLSA_STRING Confidentiality OPTIONAL,
883                        OUT PLSA_STRING *AuthenticationPackageName)
884 {
885     PANSI_STRING NameString;
886     PCHAR NameBuffer;
887 
888     TRACE("(%lu %p %p %p %p)\n",
889           AuthenticationPackageId, LsaDispatchTable, Database,
890           Confidentiality, AuthenticationPackageName);
891 
892     /* Get the dispatch table entries */
893     DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
894     DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
895     DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
896     DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
897     DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
898     DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
899     DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
900     DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
901     DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
902     DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
903     DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
904 
905     /* Return the package name */
906     NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
907     if (NameString == NULL)
908         return STATUS_INSUFFICIENT_RESOURCES;
909 
910     NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
911     if (NameBuffer == NULL)
912     {
913         DispatchTable.FreeLsaHeap(NameString);
914         return STATUS_INSUFFICIENT_RESOURCES;
915     }
916 
917     strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
918 
919     RtlInitAnsiString(NameString, NameBuffer);
920 
921     *AuthenticationPackageName = (PLSA_STRING)NameString;
922 
923     return STATUS_SUCCESS;
924 }
925 
926 
927 /*
928  * @unimplemented
929  */
930 VOID
931 NTAPI
932 LsaApLogonTerminated(IN PLUID LogonId)
933 {
934     TRACE("()\n");
935 }
936 
937 
938 /*
939  * @unimplemented
940  */
941 NTSTATUS
942 NTAPI
943 LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
944                IN SECURITY_LOGON_TYPE LogonType,
945                IN PVOID AuthenticationInformation,
946                IN PVOID ClientAuthenticationBase,
947                IN ULONG AuthenticationInformationLength,
948                OUT PVOID *ProfileBuffer,
949                OUT PULONG ProfileBufferLength,
950                OUT PLUID LogonId,
951                OUT PNTSTATUS SubStatus,
952                OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
953                OUT PVOID *TokenInformation,
954                OUT PLSA_UNICODE_STRING *AccountName,
955                OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
956 {
957     PMSV1_0_INTERACTIVE_LOGON LogonInfo;
958 
959     SAMPR_HANDLE ServerHandle = NULL;
960     SAMPR_HANDLE DomainHandle = NULL;
961     SAMPR_HANDLE UserHandle = NULL;
962     PRPC_SID AccountDomainSid = NULL;
963     RPC_UNICODE_STRING Names[1];
964     SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
965     SAMPR_ULONG_ARRAY Use = {0, NULL};
966     PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
967     UNICODE_STRING LogonServer;
968     BOOLEAN SessionCreated = FALSE;
969     LARGE_INTEGER LogonTime;
970 //    LARGE_INTEGER AccountExpires;
971     LARGE_INTEGER PasswordMustChange;
972     LARGE_INTEGER PasswordLastSet;
973     NTSTATUS Status;
974 
975     TRACE("()\n");
976 
977     TRACE("LogonType: %lu\n", LogonType);
978     TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
979     TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
980 
981     *ProfileBuffer = NULL;
982     *ProfileBufferLength = 0;
983     *SubStatus = STATUS_SUCCESS;
984 
985     if (LogonType == Interactive ||
986         LogonType == Batch ||
987         LogonType == Service)
988     {
989         ULONG_PTR PtrOffset;
990 
991         LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;
992 
993         /* Fix-up pointers in the authentication info */
994         PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;
995 
996         LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
997         LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
998         LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
999 
1000         TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1001         TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1002         TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1003 
1004         RtlInitUnicodeString(&LogonServer, L"Testserver");
1005     }
1006     else
1007     {
1008         FIXME("LogonType %lu is not supported yet!\n", LogonType);
1009         return STATUS_NOT_IMPLEMENTED;
1010     }
1011 
1012     /* Get the logon time */
1013     NtQuerySystemTime(&LogonTime);
1014 
1015     /* Get the domain SID */
1016     Status = GetDomainSid(&AccountDomainSid);
1017     if (!NT_SUCCESS(Status))
1018     {
1019         TRACE("GetDomainSid() failed (Status 0x%08lx)\n", Status);
1020         return Status;
1021     }
1022 
1023     /* Connect to the SAM server */
1024     Status = SamIConnect(NULL,
1025                          &ServerHandle,
1026                          SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1027                          TRUE);
1028     if (!NT_SUCCESS(Status))
1029     {
1030         TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1031         goto done;
1032     }
1033 
1034     /* Open the account domain */
1035     Status = SamrOpenDomain(ServerHandle,
1036                             DOMAIN_LOOKUP,
1037                             AccountDomainSid,
1038                             &DomainHandle);
1039     if (!NT_SUCCESS(Status))
1040     {
1041         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1042         goto done;
1043     }
1044 
1045     Names[0].Length = LogonInfo->UserName.Length;
1046     Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1047     Names[0].Buffer = LogonInfo->UserName.Buffer;
1048 
1049     /* Try to get the RID for the user name */
1050     Status = SamrLookupNamesInDomain(DomainHandle,
1051                                      1,
1052                                      Names,
1053                                      &RelativeIds,
1054                                      &Use);
1055     if (!NT_SUCCESS(Status))
1056     {
1057         TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1058         Status = STATUS_NO_SUCH_USER;
1059         goto done;
1060     }
1061 
1062     /* Fail, if it is not a user account */
1063     if (Use.Element[0] != SidTypeUser)
1064     {
1065         TRACE("Account is not a user account!\n");
1066         Status = STATUS_NO_SUCH_USER;
1067         goto done;
1068     }
1069 
1070     /* Open the user object */
1071     Status = SamrOpenUser(DomainHandle,
1072                           USER_READ_GENERAL | USER_READ_LOGON |
1073                           USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1074                           RelativeIds.Element[0],
1075                           &UserHandle);
1076     if (!NT_SUCCESS(Status))
1077     {
1078         TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
1079         goto done;
1080     }
1081 
1082     Status = SamrQueryInformationUser(UserHandle,
1083                                       UserAllInformation,
1084                                       &UserInfo);
1085     if (!NT_SUCCESS(Status))
1086     {
1087         TRACE("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1088         goto done;
1089     }
1090 
1091     TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1092 
1093     /* Check the password */
1094     if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1095     {
1096         Status = MsvpCheckPassword(&(LogonInfo->Password),
1097                                    UserInfo);
1098         if (!NT_SUCCESS(Status))
1099         {
1100             TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
1101             goto done;
1102         }
1103     }
1104 
1105     /* Check account restrictions for non-administrator accounts */
1106     if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1107     {
1108         /* Check if the account has been disabled */
1109         if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1110         {
1111             ERR("Account disabled!\n");
1112             *SubStatus = STATUS_ACCOUNT_DISABLED;
1113             Status = STATUS_ACCOUNT_RESTRICTION;
1114             goto done;
1115         }
1116 
1117         /* Check if the account has been locked */
1118         if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1119         {
1120             ERR("Account locked!\n");
1121             *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1122             Status = STATUS_ACCOUNT_RESTRICTION;
1123             goto done;
1124         }
1125 
1126 #if 0
1127         /* Check if the account expired */
1128         AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1129         AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1130 
1131         if (AccountExpires.QuadPart != 0 &&
1132             LogonTime.QuadPart >= AccountExpires.QuadPart)
1133         {
1134             ERR("Account expired!\n");
1135             *SubStatus = STATUS_ACCOUNT_EXPIRED;
1136             Status = STATUS_ACCOUNT_RESTRICTION;
1137             goto done;
1138         }
1139 #endif
1140 
1141         /* Check if the password expired */
1142         PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1143         PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1144         PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1145         PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1146 
1147         if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1148         {
1149             ERR("Password expired!\n");
1150             if (PasswordLastSet.QuadPart == 0)
1151                 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1152             else
1153                 *SubStatus = STATUS_PASSWORD_EXPIRED;
1154 
1155             Status = STATUS_ACCOUNT_RESTRICTION;
1156             goto done;
1157         }
1158 
1159         /* FIXME: more checks */
1160         // STATUS_INVALID_LOGON_HOURS;
1161         // STATUS_INVALID_WORKSTATION;
1162     }
1163 
1164     /* Return logon information */
1165 
1166     /* Create and return a new logon id */
1167     Status = NtAllocateLocallyUniqueId(LogonId);
1168     if (!NT_SUCCESS(Status))
1169     {
1170         TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1171         goto done;
1172     }
1173 
1174     /* Create the logon session */
1175     Status = DispatchTable.CreateLogonSession(LogonId);
1176     if (!NT_SUCCESS(Status))
1177     {
1178         TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1179         goto done;
1180     }
1181 
1182     SessionCreated = TRUE;
1183 
1184     /* Build and fill the interactive profile buffer */
1185     Status = BuildInteractiveProfileBuffer(ClientRequest,
1186                                            UserInfo,
1187                                            &LogonServer,
1188                                            (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1189                                            ProfileBufferLength);
1190     if (!NT_SUCCESS(Status))
1191     {
1192         TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1193         goto done;
1194     }
1195 
1196     /* Return the token information type */
1197     *TokenInformationType = LsaTokenInformationV1;
1198 
1199     /* Build and fill the token information buffer */
1200     Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1201                                          AccountDomainSid,
1202                                          UserInfo);
1203     if (!NT_SUCCESS(Status))
1204     {
1205         TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1206         goto done;
1207     }
1208 
1209 done:
1210     /* Return the account name */
1211     *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1212     if (*AccountName != NULL)
1213     {
1214         (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1215                                                                sizeof(UNICODE_NULL));
1216         if ((*AccountName)->Buffer != NULL)
1217         {
1218             (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1219                                             sizeof(UNICODE_NULL);
1220             RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1221         }
1222     }
1223 
1224     if (!NT_SUCCESS(Status))
1225     {
1226         if (SessionCreated != FALSE)
1227             DispatchTable.DeleteLogonSession(LogonId);
1228 
1229         if (*ProfileBuffer != NULL)
1230         {
1231             DispatchTable.FreeClientBuffer(ClientRequest,
1232                                            *ProfileBuffer);
1233             *ProfileBuffer = NULL;
1234         }
1235     }
1236 
1237     if (UserHandle != NULL)
1238         SamrCloseHandle(&UserHandle);
1239 
1240     SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1241                                     UserAllInformation);
1242     SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1243     SamIFree_SAMPR_ULONG_ARRAY(&Use);
1244 
1245     if (DomainHandle != NULL)
1246         SamrCloseHandle(&DomainHandle);
1247 
1248     if (ServerHandle != NULL)
1249         SamrCloseHandle(&ServerHandle);
1250 
1251     if (AccountDomainSid != NULL)
1252         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1253 
1254     if (Status == STATUS_NO_SUCH_USER ||
1255         Status == STATUS_WRONG_PASSWORD)
1256     {
1257         *SubStatus = Status;
1258         Status = STATUS_LOGON_FAILURE;
1259     }
1260 
1261     TRACE("LsaApLogonUser done (Status 0x%08lx  SubStatus 0x%08lx)\n", Status, *SubStatus);
1262 
1263     return Status;
1264 }
1265 
1266 
1267 /*
1268  * @unimplemented
1269  */
1270 #if 0
1271 NTSTATUS
1272 NTAPI
1273 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
1274                  IN SECURITY_LOGON_TYPE LogonType,
1275                  IN PVOID AuthenticationInformation,
1276                  IN PVOID ClientAuthenticationBase,
1277                  IN ULONG AuthenticationInformationLength,
1278                  OUT PVOID *ProfileBuffer,
1279                  OUT PULONG ProfileBufferLength,
1280                  OUT PLUID LogonId,
1281                  OUT PNTSTATUS SubStatus,
1282                  OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1283                  OUT PVOID *TokenInformation,
1284                  OUT PUNICODE_STRING *AccountName,
1285                  OUT PUNICODE_STRING *AuthenticatingAuthority,
1286                  OUT PUNICODE_STRING *MachineName)
1287 {
1288     TRACE("()\n");
1289 
1290     TRACE("LogonType: %lu\n", LogonType);
1291     TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
1292     TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
1293 
1294     return STATUS_NOT_IMPLEMENTED;
1295 }
1296 
1297 
1298 /*
1299  * @unimplemented
1300  */
1301 NTSTATUS
1302 NTAPI
1303 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1304                   IN SECURITY_LOGON_TYPE LogonType,
1305                   IN PVOID ProtocolSubmitBuffer,
1306                   IN PVOID ClientBufferBase,
1307                   IN ULONG SubmitBufferSize,
1308                   OUT PVOID *ProfileBuffer,
1309                   OUT PULONG ProfileBufferSize,
1310                   OUT PLUID LogonId,
1311                   OUT PNTSTATUS SubStatus,
1312                   OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1313                   OUT PVOID *TokenInformation,
1314                   OUT PUNICODE_STRING *AccountName,
1315                   OUT PUNICODE_STRING *AuthenticatingAuthority,
1316                   OUT PUNICODE_STRING *MachineName,
1317                   OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
1318                   OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials)
1319 {
1320     TRACE("()\n");
1321 
1322     TRACE("LogonType: %lu\n", LogonType);
1323     TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1324     TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1325 
1326 
1327     return STATUS_NOT_IMPLEMENTED;
1328 }
1329 #endif
1330 
1331 /* EOF */
1332