xref: /reactos/dll/win32/advapi32/misc/logon.c (revision d5399189)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS system libraries
4  * FILE:        lib/advapi32/misc/logon.c
5  * PURPOSE:     Logon functions
6  * PROGRAMMER:  Eric Kohl
7  */
8 
9 #include <advapi32.h>
10 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
11 
12 /* GLOBALS *****************************************************************/
13 
14 HANDLE LsaHandle = NULL;
15 ULONG AuthenticationPackage = 0;
16 
17 /* FUNCTIONS ***************************************************************/
18 
19 static
20 NTSTATUS
21 OpenLogonLsaHandle(VOID)
22 {
23     LSA_STRING LogonProcessName;
24     LSA_STRING PackageName;
25     LSA_OPERATIONAL_MODE SecurityMode = 0;
26     NTSTATUS Status;
27 
28     RtlInitAnsiString((PANSI_STRING)&LogonProcessName,
29                       "User32LogonProcess");
30 
31     Status = LsaRegisterLogonProcess(&LogonProcessName,
32                                      &LsaHandle,
33                                      &SecurityMode);
34     if (!NT_SUCCESS(Status))
35     {
36         TRACE("LsaRegisterLogonProcess failed (Status 0x%08lx)\n", Status);
37         goto done;
38     }
39 
40     RtlInitAnsiString((PANSI_STRING)&PackageName,
41                       MSV1_0_PACKAGE_NAME);
42 
43     Status = LsaLookupAuthenticationPackage(LsaHandle,
44                                             &PackageName,
45                                             &AuthenticationPackage);
46     if (!NT_SUCCESS(Status))
47     {
48         TRACE("LsaLookupAuthenticationPackage failed (Status 0x%08lx)\n", Status);
49         goto done;
50     }
51 
52     TRACE("AuthenticationPackage: 0x%08lx\n", AuthenticationPackage);
53 
54 done:
55     if (!NT_SUCCESS(Status))
56     {
57         if (LsaHandle != NULL)
58         {
59             Status = LsaDeregisterLogonProcess(LsaHandle);
60             if (!NT_SUCCESS(Status))
61             {
62                 TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
63             }
64         }
65     }
66 
67     return Status;
68 }
69 
70 
71 NTSTATUS
72 CloseLogonLsaHandle(VOID)
73 {
74     NTSTATUS Status = STATUS_SUCCESS;
75 
76     if (LsaHandle != NULL)
77     {
78         Status = LsaDeregisterLogonProcess(LsaHandle);
79         if (!NT_SUCCESS(Status))
80         {
81             TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
82         }
83     }
84 
85     return Status;
86 }
87 
88 
89 static
90 BOOL
91 CreateProcessAsUserCommon(
92     _In_ BOOL bUnicode,
93     _In_opt_ HANDLE hToken,
94     _In_opt_ LPCVOID lpApplicationName,
95     _Inout_opt_ LPVOID lpCommandLine,
96     _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
97     _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
98     _In_ BOOL bInheritHandles,
99     _In_ DWORD dwCreationFlags,
100     _In_opt_ LPVOID lpEnvironment,
101     _In_opt_ LPCVOID lpCurrentDirectory,
102     _In_ LPVOID lpStartupInfo,
103     _Out_ LPPROCESS_INFORMATION lpProcessInformation)
104 {
105     NTSTATUS Status;
106     PROCESS_ACCESS_TOKEN AccessToken;
107 
108     /* Create the process with a suspended main thread */
109     if (bUnicode)
110     {
111         /* Call the UNICODE version */
112         if (!CreateProcessW((LPCWSTR)lpApplicationName,
113                             (LPWSTR)lpCommandLine,
114                             lpProcessAttributes,
115                             lpThreadAttributes,
116                             bInheritHandles,
117                             dwCreationFlags | CREATE_SUSPENDED,
118                             lpEnvironment,
119                             (LPCWSTR)lpCurrentDirectory,
120                             (LPSTARTUPINFOW)lpStartupInfo,
121                             lpProcessInformation))
122         {
123             ERR("CreateProcessW failed, last error: %d\n", GetLastError());
124             return FALSE;
125         }
126     }
127     else
128     {
129         /* Call the ANSI version */
130         if (!CreateProcessA((LPCSTR)lpApplicationName,
131                             (LPSTR)lpCommandLine,
132                             lpProcessAttributes,
133                             lpThreadAttributes,
134                             bInheritHandles,
135                             dwCreationFlags | CREATE_SUSPENDED,
136                             lpEnvironment,
137                             (LPCSTR)lpCurrentDirectory,
138                             (LPSTARTUPINFOA)lpStartupInfo,
139                             lpProcessInformation))
140         {
141             ERR("CreateProcessA failed, last error: %d\n", GetLastError());
142             return FALSE;
143         }
144     }
145 
146     if (hToken != NULL)
147     {
148         OBJECT_ATTRIBUTES ObjectAttributes;
149         HANDLE hTokenDup;
150         BOOLEAN PrivilegeSet = FALSE;
151 
152         /* Duplicate the token for this new process */
153         InitializeObjectAttributes(&ObjectAttributes,
154                                    NULL,
155                                    0,
156                                    NULL,
157                                    NULL); // FIXME: Use a valid SecurityDescriptor!
158         Status = NtDuplicateToken(hToken,
159                                   0,
160                                   &ObjectAttributes,
161                                   FALSE,
162                                   TokenPrimary,
163                                   &hTokenDup);
164         if (!NT_SUCCESS(Status))
165         {
166             ERR("NtDuplicateToken failed, Status 0x%08x\n", Status);
167             TerminateProcess(lpProcessInformation->hProcess, Status);
168             SetLastError(RtlNtStatusToDosError(Status));
169             return FALSE;
170         }
171 
172         // FIXME: Do we always need SecurityImpersonation?
173         if (!ImpersonateSelf(SecurityImpersonation))
174         {
175             ERR("ImpersonateSelf(SecurityImpersonation) failed, last error: %d\n", GetLastError());
176             NtClose(hTokenDup);
177             TerminateProcess(lpProcessInformation->hProcess, RtlGetLastNtStatus());
178             // SetLastError(RtlNtStatusToDosError(Status));
179             return FALSE;
180         }
181 
182         /* Acquire the process primary token assignment privilege */
183         Status = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, TRUE, &PrivilegeSet);
184         if (!NT_SUCCESS(Status))
185         {
186             ERR("RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE) failed, Status 0x%08lx\n", Status);
187             RevertToSelf();
188             NtClose(hTokenDup);
189             TerminateProcess(lpProcessInformation->hProcess, Status);
190             SetLastError(RtlNtStatusToDosError(Status));
191             return FALSE;
192         }
193 
194         AccessToken.Token  = hTokenDup;
195         AccessToken.Thread = lpProcessInformation->hThread;
196 
197         /* Set the new process token */
198         Status = NtSetInformationProcess(lpProcessInformation->hProcess,
199                                          ProcessAccessToken,
200                                          (PVOID)&AccessToken,
201                                          sizeof(AccessToken));
202 
203         /* Restore the privileges */
204         RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, PrivilegeSet, TRUE, &PrivilegeSet);
205 
206         RevertToSelf();
207 
208         /* Close the duplicated token */
209         NtClose(hTokenDup);
210 
211         /* Check whether NtSetInformationProcess() failed */
212         if (!NT_SUCCESS(Status))
213         {
214             ERR("NtSetInformationProcess failed, Status 0x%08x\n", Status);
215             TerminateProcess(lpProcessInformation->hProcess, Status);
216             SetLastError(RtlNtStatusToDosError(Status));
217             return FALSE;
218         }
219     }
220 
221     /* Resume the main thread */
222     if (!(dwCreationFlags & CREATE_SUSPENDED))
223     {
224         ResumeThread(lpProcessInformation->hThread);
225     }
226 
227     return TRUE;
228 }
229 
230 
231 /*
232  * @implemented
233  */
234 BOOL
235 WINAPI
236 DECLSPEC_HOTPATCH
237 CreateProcessAsUserA(
238     _In_opt_ HANDLE hToken,
239     _In_opt_ LPCSTR lpApplicationName,
240     _Inout_opt_ LPSTR lpCommandLine,
241     _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
242     _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
243     _In_ BOOL bInheritHandles,
244     _In_ DWORD dwCreationFlags,
245     _In_opt_ LPVOID lpEnvironment,
246     _In_opt_ LPCSTR lpCurrentDirectory,
247     _In_ LPSTARTUPINFOA lpStartupInfo,
248     _Out_ LPPROCESS_INFORMATION lpProcessInformation)
249 {
250     TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
251         debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
252         dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
253 
254     /* Call the helper function */
255     return CreateProcessAsUserCommon(FALSE,
256                                      hToken,
257                                      lpApplicationName,
258                                      lpCommandLine,
259                                      lpProcessAttributes,
260                                      lpThreadAttributes,
261                                      bInheritHandles,
262                                      dwCreationFlags,
263                                      lpEnvironment,
264                                      lpCurrentDirectory,
265                                      lpStartupInfo,
266                                      lpProcessInformation);
267 }
268 
269 
270 /*
271  * @implemented
272  */
273 BOOL
274 WINAPI
275 DECLSPEC_HOTPATCH
276 CreateProcessAsUserW(
277     _In_opt_ HANDLE hToken,
278     _In_opt_ LPCWSTR lpApplicationName,
279     _Inout_opt_ LPWSTR lpCommandLine,
280     _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
281     _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
282     _In_ BOOL bInheritHandles,
283     _In_ DWORD dwCreationFlags,
284     _In_opt_ LPVOID lpEnvironment,
285     _In_opt_ LPCWSTR lpCurrentDirectory,
286     _In_ LPSTARTUPINFOW lpStartupInfo,
287     _Out_ LPPROCESS_INFORMATION lpProcessInformation)
288 {
289     TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_w(lpApplicationName),
290         debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
291         dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
292 
293     /* Call the helper function */
294     return CreateProcessAsUserCommon(TRUE,
295                                      hToken,
296                                      lpApplicationName,
297                                      lpCommandLine,
298                                      lpProcessAttributes,
299                                      lpThreadAttributes,
300                                      bInheritHandles,
301                                      dwCreationFlags,
302                                      lpEnvironment,
303                                      lpCurrentDirectory,
304                                      lpStartupInfo,
305                                      lpProcessInformation);
306 }
307 
308 
309 /*
310  * @implemented
311  */
312 BOOL
313 WINAPI
314 LogonUserA(
315     _In_ LPSTR lpszUsername,
316     _In_opt_ LPSTR lpszDomain,
317     _In_opt_ LPSTR lpszPassword,
318     _In_ DWORD dwLogonType,
319     _In_ DWORD dwLogonProvider,
320     _Out_opt_ PHANDLE phToken)
321 {
322     return LogonUserExA(lpszUsername,
323                         lpszDomain,
324                         lpszPassword,
325                         dwLogonType,
326                         dwLogonProvider,
327                         phToken,
328                         NULL,
329                         NULL,
330                         NULL,
331                         NULL);
332 }
333 
334 
335 /*
336  * @implemented
337  */
338 BOOL
339 WINAPI
340 LogonUserExA(
341     _In_ LPSTR lpszUsername,
342     _In_opt_ LPSTR lpszDomain,
343     _In_opt_ LPSTR lpszPassword,
344     _In_ DWORD dwLogonType,
345     _In_ DWORD dwLogonProvider,
346     _Out_opt_ PHANDLE phToken,
347     _Out_opt_ PSID *ppLogonSid,
348     _Out_opt_ PVOID *ppProfileBuffer,
349     _Out_opt_ LPDWORD pdwProfileLength,
350     _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
351 {
352     UNICODE_STRING UserName;
353     UNICODE_STRING Domain;
354     UNICODE_STRING Password;
355     BOOL ret = FALSE;
356 
357     UserName.Buffer = NULL;
358     Domain.Buffer = NULL;
359     Password.Buffer = NULL;
360 
361     if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
362     {
363         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
364         goto UsernameDone;
365     }
366 
367     if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
368     {
369         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
370         goto DomainDone;
371     }
372 
373     if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
374     {
375         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
376         goto PasswordDone;
377     }
378 
379     ret = LogonUserExW(UserName.Buffer,
380                        Domain.Buffer,
381                        Password.Buffer,
382                        dwLogonType,
383                        dwLogonProvider,
384                        phToken,
385                        ppLogonSid,
386                        ppProfileBuffer,
387                        pdwProfileLength,
388                        pQuotaLimits);
389 
390     if (Password.Buffer != NULL)
391         RtlFreeUnicodeString(&Password);
392 
393 PasswordDone:
394     if (Domain.Buffer != NULL)
395         RtlFreeUnicodeString(&Domain);
396 
397 DomainDone:
398     if (UserName.Buffer != NULL)
399         RtlFreeUnicodeString(&UserName);
400 
401 UsernameDone:
402     return ret;
403 }
404 
405 
406 /*
407  * @implemented
408  */
409 BOOL
410 WINAPI
411 LogonUserW(
412     _In_ LPWSTR lpszUsername,
413     _In_opt_ LPWSTR lpszDomain,
414     _In_opt_ LPWSTR lpszPassword,
415     _In_ DWORD dwLogonType,
416     _In_ DWORD dwLogonProvider,
417     _Out_opt_ PHANDLE phToken)
418 {
419     return LogonUserExW(lpszUsername,
420                         lpszDomain,
421                         lpszPassword,
422                         dwLogonType,
423                         dwLogonProvider,
424                         phToken,
425                         NULL,
426                         NULL,
427                         NULL,
428                         NULL);
429 }
430 
431 
432 /*
433  * @implemented
434  */
435 BOOL
436 WINAPI
437 LogonUserExW(
438     _In_ LPWSTR lpszUsername,
439     _In_opt_ LPWSTR lpszDomain,
440     _In_opt_ LPWSTR lpszPassword,
441     _In_ DWORD dwLogonType,
442     _In_ DWORD dwLogonProvider,
443     _Out_opt_ PHANDLE phToken,
444     _Out_opt_ PSID *ppLogonSid,
445     _Out_opt_ PVOID *ppProfileBuffer,
446     _Out_opt_ LPDWORD pdwProfileLength,
447     _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
448 {
449     SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
450     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
451     PSID LogonSid = NULL;
452     PSID LocalSid = NULL;
453     LSA_STRING OriginName;
454     UNICODE_STRING DomainName;
455     UNICODE_STRING UserName;
456     UNICODE_STRING Password;
457     PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
458     ULONG AuthInfoLength;
459     ULONG_PTR Ptr;
460     TOKEN_SOURCE TokenSource;
461     PTOKEN_GROUPS TokenGroups = NULL;
462     PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
463     ULONG ProfileBufferLength = 0;
464     LUID Luid = {0, 0};
465     LUID LogonId = {0, 0};
466     HANDLE TokenHandle = NULL;
467     QUOTA_LIMITS QuotaLimits;
468     SECURITY_LOGON_TYPE LogonType;
469     NTSTATUS SubStatus = STATUS_SUCCESS;
470     NTSTATUS Status;
471 
472     if ((ppProfileBuffer != NULL && pdwProfileLength == NULL) ||
473         (ppProfileBuffer == NULL && pdwProfileLength != NULL))
474     {
475         SetLastError(ERROR_INVALID_PARAMETER);
476         return FALSE;
477     }
478 
479     if (ppProfileBuffer != NULL && pdwProfileLength != NULL)
480     {
481         *ppProfileBuffer = NULL;
482         *pdwProfileLength = 0;
483     }
484 
485     if (phToken != NULL)
486         *phToken = NULL;
487 
488     switch (dwLogonType)
489     {
490         case LOGON32_LOGON_INTERACTIVE:
491             LogonType = Interactive;
492             break;
493 
494         case LOGON32_LOGON_NETWORK:
495             LogonType = Network;
496             break;
497 
498         case LOGON32_LOGON_BATCH:
499             LogonType = Batch;
500             break;
501 
502         case LOGON32_LOGON_SERVICE:
503             LogonType = Service;
504             break;
505 
506        default:
507             ERR("Invalid logon type: %ul\n", dwLogonType);
508             Status = STATUS_INVALID_PARAMETER;
509             goto done;
510     }
511 
512     if (LsaHandle == NULL)
513     {
514         Status = OpenLogonLsaHandle();
515         if (!NT_SUCCESS(Status))
516             goto done;
517     }
518 
519     RtlInitAnsiString((PANSI_STRING)&OriginName,
520                       "Advapi32 Logon");
521 
522     RtlInitUnicodeString(&DomainName,
523                          lpszDomain);
524 
525     RtlInitUnicodeString(&UserName,
526                          lpszUsername);
527 
528     RtlInitUnicodeString(&Password,
529                          lpszPassword);
530 
531     AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
532                      DomainName.MaximumLength +
533                      UserName.MaximumLength +
534                      Password.MaximumLength;
535 
536     AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
537                                HEAP_ZERO_MEMORY,
538                                AuthInfoLength);
539     if (AuthInfo == NULL)
540     {
541         Status = STATUS_INSUFFICIENT_RESOURCES;
542         goto done;
543     }
544 
545     AuthInfo->MessageType = MsV1_0InteractiveLogon;
546 
547     Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
548 
549     AuthInfo->LogonDomainName.Length = DomainName.Length;
550     AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
551     AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
552     if (DomainName.MaximumLength > 0)
553     {
554         RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
555                       DomainName.Buffer,
556                       DomainName.MaximumLength);
557 
558         Ptr += DomainName.MaximumLength;
559     }
560 
561     AuthInfo->UserName.Length = UserName.Length;
562     AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
563     AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
564     if (UserName.MaximumLength > 0)
565         RtlCopyMemory(AuthInfo->UserName.Buffer,
566                       UserName.Buffer,
567                       UserName.MaximumLength);
568 
569     Ptr += UserName.MaximumLength;
570 
571     AuthInfo->Password.Length = Password.Length;
572     AuthInfo->Password.MaximumLength = Password.MaximumLength;
573     AuthInfo->Password.Buffer = (PWCHAR)Ptr;
574     if (Password.MaximumLength > 0)
575         RtlCopyMemory(AuthInfo->Password.Buffer,
576                       Password.Buffer,
577                       Password.MaximumLength);
578 
579     /* Create the Logon SID */
580     AllocateLocallyUniqueId(&LogonId);
581     Status = RtlAllocateAndInitializeSid(&SystemAuthority,
582                                          SECURITY_LOGON_IDS_RID_COUNT,
583                                          SECURITY_LOGON_IDS_RID,
584                                          LogonId.HighPart,
585                                          LogonId.LowPart,
586                                          SECURITY_NULL_RID,
587                                          SECURITY_NULL_RID,
588                                          SECURITY_NULL_RID,
589                                          SECURITY_NULL_RID,
590                                          SECURITY_NULL_RID,
591                                          &LogonSid);
592     if (!NT_SUCCESS(Status))
593         goto done;
594 
595     /* Create the Local SID */
596     Status = RtlAllocateAndInitializeSid(&LocalAuthority,
597                                          1,
598                                          SECURITY_LOCAL_RID,
599                                          SECURITY_NULL_RID,
600                                          SECURITY_NULL_RID,
601                                          SECURITY_NULL_RID,
602                                          SECURITY_NULL_RID,
603                                          SECURITY_NULL_RID,
604                                          SECURITY_NULL_RID,
605                                          SECURITY_NULL_RID,
606                                          &LocalSid);
607     if (!NT_SUCCESS(Status))
608         goto done;
609 
610     /* Allocate and set the token groups */
611     TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
612                                   HEAP_ZERO_MEMORY,
613                                   sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
614     if (TokenGroups == NULL)
615     {
616         Status = STATUS_INSUFFICIENT_RESOURCES;
617         goto done;
618     }
619 
620     TokenGroups->GroupCount = 2;
621     TokenGroups->Groups[0].Sid = LogonSid;
622     TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
623                                         SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
624     TokenGroups->Groups[1].Sid = LocalSid;
625     TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
626                                         SE_GROUP_ENABLED_BY_DEFAULT;
627 
628     /* Set the token source */
629     strncpy(TokenSource.SourceName, "Advapi  ", sizeof(TokenSource.SourceName));
630     AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
631 
632     Status = LsaLogonUser(LsaHandle,
633                           &OriginName,
634                           LogonType,
635                           AuthenticationPackage,
636                           (PVOID)AuthInfo,
637                           AuthInfoLength,
638                           TokenGroups,
639                           &TokenSource,
640                           (PVOID*)&ProfileBuffer,
641                           &ProfileBufferLength,
642                           &Luid,
643                           &TokenHandle,
644                           &QuotaLimits,
645                           &SubStatus);
646     if (!NT_SUCCESS(Status))
647     {
648         ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
649         goto done;
650     }
651 
652     if (ProfileBuffer != NULL)
653     {
654         TRACE("ProfileBuffer: %p\n", ProfileBuffer);
655         TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
656 
657         TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
658         TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
659 
660         TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
661         TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
662     }
663 
664     TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
665 
666     if (TokenHandle != NULL)
667     {
668         TRACE("TokenHandle: %p\n", TokenHandle);
669     }
670 
671     if (phToken != NULL)
672         *phToken = TokenHandle;
673 
674     /* FIXME: return ppLogonSid and pQuotaLimits */
675 
676 done:
677     if (ProfileBuffer != NULL)
678         LsaFreeReturnBuffer(ProfileBuffer);
679 
680     if (!NT_SUCCESS(Status))
681     {
682         if (TokenHandle != NULL)
683             CloseHandle(TokenHandle);
684     }
685 
686     if (TokenGroups != NULL)
687         RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
688 
689     if (LocalSid != NULL)
690         RtlFreeSid(LocalSid);
691 
692     if (LogonSid != NULL)
693         RtlFreeSid(LogonSid);
694 
695     if (AuthInfo != NULL)
696         RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
697 
698     if (!NT_SUCCESS(Status))
699     {
700         SetLastError(RtlNtStatusToDosError(Status));
701         return FALSE;
702     }
703 
704     return TRUE;
705 }
706 
707 /* EOF */
708