xref: /reactos/dll/win32/netapi32/user.c (revision 1fe58c40)
1 /*
2  * Copyright 2002 Andriy Palamarchuk
3  *
4  * netapi32 user functions
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /*
22  *  TODO:
23  *    Implement NetUserGetGroups (WIP)
24  *    Implement NetUserSetGroups
25  *    NetUserGetLocalGroups does not support LG_INCLUDE_INDIRECT yet.
26  *    Add missing information levels.
27  *    ...
28  */
29 
30 #include "netapi32.h"
31 
32 #include <ndk/kefuncs.h>
33 #include <ndk/obfuncs.h>
34 
35 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
36 
37 typedef struct _ENUM_CONTEXT
38 {
39     SAM_HANDLE ServerHandle;
40     SAM_HANDLE BuiltinDomainHandle;
41     SAM_HANDLE AccountDomainHandle;
42     PSID BuiltinDomainSid;
43     PSID AccountDomainSid;
44 
45     SAM_ENUMERATE_HANDLE EnumerationContext;
46     PSAM_RID_ENUMERATION Buffer;
47     ULONG Count;
48     ULONG Index;
49     BOOLEAN BuiltinDone;
50 
51 } ENUM_CONTEXT, *PENUM_CONTEXT;
52 
53 
54 static
55 ULONG
56 DeltaTimeToSeconds(LARGE_INTEGER DeltaTime)
57 {
58     LARGE_INTEGER Seconds;
59 
60     if (DeltaTime.QuadPart == 0)
61         return 0;
62 
63     Seconds.QuadPart = -DeltaTime.QuadPart / 10000000;
64 
65     if (Seconds.HighPart != 0)
66         return TIMEQ_FOREVER;
67 
68     return Seconds.LowPart;
69 }
70 
71 
72 static
73 NTSTATUS
74 GetAllowedWorldAce(IN PACL Acl,
75                    OUT PACCESS_ALLOWED_ACE *Ace)
76 {
77     SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
78     ULONG WorldSid[sizeof(SID) / sizeof(ULONG) + SID_MAX_SUB_AUTHORITIES];
79     ACL_SIZE_INFORMATION AclSize;
80     PVOID LocalAce = NULL;
81     ULONG i;
82     NTSTATUS Status;
83 
84     *Ace = NULL;
85 
86     RtlInitializeSid((PSID)WorldSid,
87                      &WorldAuthority,
88                      1);
89     *(RtlSubAuthoritySid((PSID)WorldSid, 0)) = SECURITY_WORLD_RID;
90 
91     Status = RtlQueryInformationAcl(Acl,
92                                     &AclSize,
93                                     sizeof(AclSize),
94                                     AclSizeInformation);
95     if (!NT_SUCCESS(Status))
96         return Status;
97 
98     for (i = 0; i < AclSize.AceCount; i++)
99     {
100         Status = RtlGetAce(Acl, i, &LocalAce);
101         if (!NT_SUCCESS(Status))
102             return Status;
103 
104         if (((PACE_HEADER)LocalAce)->AceType != ACCESS_ALLOWED_ACE_TYPE)
105             continue;
106 
107         if (RtlEqualSid((PSID)WorldSid,
108                         (PSID)&((PACCESS_ALLOWED_ACE)LocalAce)->SidStart))
109         {
110             *Ace = (PACCESS_ALLOWED_ACE)LocalAce;
111             return STATUS_SUCCESS;
112         }
113     }
114 
115     return STATUS_SUCCESS;
116 }
117 
118 
119 static
120 ULONG
121 GetAccountFlags(ULONG AccountControl,
122                 PACL Dacl)
123 {
124     PACCESS_ALLOWED_ACE Ace = NULL;
125     ULONG Flags = UF_SCRIPT;
126     NTSTATUS Status;
127 
128     if (Dacl != NULL)
129     {
130         Status = GetAllowedWorldAce(Dacl, &Ace);
131         if (NT_SUCCESS(Status))
132         {
133             if (Ace == NULL)
134             {
135                 Flags |= UF_PASSWD_CANT_CHANGE;
136             }
137             else if ((Ace->Mask & USER_CHANGE_PASSWORD) == 0)
138             {
139                 Flags |= UF_PASSWD_CANT_CHANGE;
140             }
141         }
142     }
143 
144     if (AccountControl & USER_ACCOUNT_DISABLED)
145         Flags |= UF_ACCOUNTDISABLE;
146 
147     if (AccountControl & USER_HOME_DIRECTORY_REQUIRED)
148         Flags |= UF_HOMEDIR_REQUIRED;
149 
150     if (AccountControl & USER_PASSWORD_NOT_REQUIRED)
151         Flags |= UF_PASSWD_NOTREQD;
152 
153     if (AccountControl & USER_ACCOUNT_AUTO_LOCKED)
154         Flags |= UF_LOCKOUT;
155 
156     if (AccountControl & USER_DONT_EXPIRE_PASSWORD)
157         Flags |= UF_DONT_EXPIRE_PASSWD;
158 
159 /*
160     if (AccountControl & USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED)
161         Flags |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED;
162 
163     if (AccountControl & USER_SMARTCARD_REQUIRED)
164         Flags |= UF_SMARTCARD_REQUIRED;
165 
166     if (AccountControl & USER_TRUSTED_FOR_DELEGATION)
167         Flags |= UF_TRUSTED_FOR_DELEGATION;
168 
169     if (AccountControl & USER_NOT_DELEGATED)
170         Flags |= UF_NOT_DELEGATED;
171 
172     if (AccountControl & USER_USE_DES_KEY_ONLY)
173         Flags |= UF_USE_DES_KEY_ONLY;
174 
175     if (AccountControl & USER_DONT_REQUIRE_PREAUTH)
176         Flags |= UF_DONT_REQUIRE_PREAUTH;
177 
178     if (AccountControl & USER_PASSWORD_EXPIRED)
179         Flags |= UF_PASSWORD_EXPIRED;
180 */
181 
182     /* Set account type flags */
183     if (AccountControl & USER_TEMP_DUPLICATE_ACCOUNT)
184         Flags |= UF_TEMP_DUPLICATE_ACCOUNT;
185     else if (AccountControl & USER_NORMAL_ACCOUNT)
186         Flags |= UF_NORMAL_ACCOUNT;
187     else if (AccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT)
188         Flags |= UF_INTERDOMAIN_TRUST_ACCOUNT;
189     else if (AccountControl & USER_WORKSTATION_TRUST_ACCOUNT)
190         Flags |= UF_WORKSTATION_TRUST_ACCOUNT;
191     else if (AccountControl & USER_SERVER_TRUST_ACCOUNT)
192         Flags |= UF_SERVER_TRUST_ACCOUNT;
193 
194     return Flags;
195 }
196 
197 
198 static
199 ULONG
200 GetAccountControl(ULONG Flags)
201 {
202     ULONG AccountControl = 0;
203 
204     if (Flags & UF_ACCOUNTDISABLE)
205         AccountControl |= USER_ACCOUNT_DISABLED;
206 
207     if (Flags & UF_HOMEDIR_REQUIRED)
208         AccountControl |= USER_HOME_DIRECTORY_REQUIRED;
209 
210     if (Flags & UF_PASSWD_NOTREQD)
211         AccountControl |= USER_PASSWORD_NOT_REQUIRED;
212 
213     if (Flags & UF_LOCKOUT)
214         AccountControl |= USER_ACCOUNT_AUTO_LOCKED;
215 
216     if (Flags & UF_DONT_EXPIRE_PASSWD)
217         AccountControl |= USER_DONT_EXPIRE_PASSWORD;
218 
219     /* Set account type flags */
220     if (Flags & UF_TEMP_DUPLICATE_ACCOUNT)
221         AccountControl |= USER_TEMP_DUPLICATE_ACCOUNT;
222     else if (Flags & UF_NORMAL_ACCOUNT)
223         AccountControl |= USER_NORMAL_ACCOUNT;
224     else if (Flags & UF_INTERDOMAIN_TRUST_ACCOUNT)
225         AccountControl |= USER_INTERDOMAIN_TRUST_ACCOUNT;
226     else if (Flags & UF_WORKSTATION_TRUST_ACCOUNT)
227         AccountControl |= USER_WORKSTATION_TRUST_ACCOUNT;
228     else if (Flags & UF_SERVER_TRUST_ACCOUNT)
229         AccountControl |= USER_SERVER_TRUST_ACCOUNT;
230 
231     return AccountControl;
232 }
233 
234 
235 static
236 DWORD
237 GetPasswordAge(IN PLARGE_INTEGER PasswordLastSet)
238 {
239     LARGE_INTEGER SystemTime;
240     ULONG SystemSecondsSince1970;
241     ULONG PasswordSecondsSince1970;
242     NTSTATUS Status;
243 
244     Status = NtQuerySystemTime(&SystemTime);
245     if (!NT_SUCCESS(Status))
246         return 0;
247 
248     RtlTimeToSecondsSince1970(&SystemTime, &SystemSecondsSince1970);
249     RtlTimeToSecondsSince1970(PasswordLastSet, &PasswordSecondsSince1970);
250 
251     return SystemSecondsSince1970 - PasswordSecondsSince1970;
252 }
253 
254 
255 static
256 VOID
257 ChangeUserDacl(IN PACL Dacl,
258                IN ULONG Flags)
259 {
260     PACCESS_ALLOWED_ACE Ace = NULL;
261     NTSTATUS Status;
262 
263     if (Dacl == NULL)
264         return;
265 
266     Status = GetAllowedWorldAce(Dacl, &Ace);
267     if (!NT_SUCCESS(Status))
268         return;
269 
270     if (Flags & UF_PASSWD_CANT_CHANGE)
271         Ace->Mask &= ~USER_CHANGE_PASSWORD;
272     else
273         Ace->Mask |= USER_CHANGE_PASSWORD;
274 }
275 
276 
277 static
278 NET_API_STATUS
279 GetUserDacl(IN SAM_HANDLE UserHandle,
280             OUT PACL *Dacl)
281 {
282     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
283     PACL SamDacl;
284     PACL LocalDacl;
285     BOOLEAN Defaulted;
286     BOOLEAN Present;
287     ACL_SIZE_INFORMATION AclSize;
288     NET_API_STATUS ApiStatus;
289     NTSTATUS Status;
290 
291     TRACE("(%p %p)\n", UserHandle, Dacl);
292 
293     *Dacl = NULL;
294 
295     Status = SamQuerySecurityObject(UserHandle,
296                                     DACL_SECURITY_INFORMATION,
297                                     &SecurityDescriptor);
298     if (!NT_SUCCESS(Status))
299     {
300         TRACE("SamQuerySecurityObject() failed (Status 0x%08lx)\n", Status);
301         ApiStatus = NetpNtStatusToApiStatus(Status);
302         goto done;
303     }
304 
305     Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
306                                           &Present,
307                                           &SamDacl,
308                                           &Defaulted);
309     if (!NT_SUCCESS(Status))
310     {
311         TRACE("RtlGetDaclSecurityDescriptor() failed (Status 0x%08lx)\n", Status);
312         ApiStatus = NERR_InternalError;
313         goto done;
314     }
315 
316     if (Present == FALSE)
317     {
318         TRACE("No DACL present\n");
319         ApiStatus = NERR_Success;
320         goto done;
321     }
322 
323     Status = RtlQueryInformationAcl(SamDacl,
324                                     &AclSize,
325                                     sizeof(AclSize),
326                                     AclSizeInformation);
327     if (!NT_SUCCESS(Status))
328     {
329         TRACE("RtlQueryInformationAcl() failed (Status 0x%08lx)\n", Status);
330         ApiStatus = NERR_InternalError;
331         goto done;
332     }
333 
334     LocalDacl = HeapAlloc(GetProcessHeap(), 0, AclSize.AclBytesInUse);
335     if (LocalDacl == NULL)
336     {
337         TRACE("Memory allocation failed\n");
338         ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
339         goto done;
340     }
341 
342     RtlCopyMemory(LocalDacl, SamDacl, AclSize.AclBytesInUse);
343 
344     *Dacl = LocalDacl;
345 
346     ApiStatus = NERR_Success;
347 
348 done:
349     if (SecurityDescriptor != NULL)
350         SamFreeMemory(SecurityDescriptor);
351 
352     TRACE("done (ApiStatus: 0x%08lx)\n", ApiStatus);
353 
354     return ApiStatus;
355 }
356 
357 
358 static
359 VOID
360 FreeUserInfo(PUSER_ALL_INFORMATION UserInfo)
361 {
362     if (UserInfo->UserName.Buffer != NULL)
363         SamFreeMemory(UserInfo->UserName.Buffer);
364 
365     if (UserInfo->FullName.Buffer != NULL)
366         SamFreeMemory(UserInfo->FullName.Buffer);
367 
368     if (UserInfo->HomeDirectory.Buffer != NULL)
369         SamFreeMemory(UserInfo->HomeDirectory.Buffer);
370 
371     if (UserInfo->HomeDirectoryDrive.Buffer != NULL)
372         SamFreeMemory(UserInfo->HomeDirectoryDrive.Buffer);
373 
374     if (UserInfo->ScriptPath.Buffer != NULL)
375         SamFreeMemory(UserInfo->ScriptPath.Buffer);
376 
377     if (UserInfo->ProfilePath.Buffer != NULL)
378         SamFreeMemory(UserInfo->ProfilePath.Buffer);
379 
380     if (UserInfo->AdminComment.Buffer != NULL)
381         SamFreeMemory(UserInfo->AdminComment.Buffer);
382 
383     if (UserInfo->WorkStations.Buffer != NULL)
384         SamFreeMemory(UserInfo->WorkStations.Buffer);
385 
386     if (UserInfo->UserComment.Buffer != NULL)
387         SamFreeMemory(UserInfo->UserComment.Buffer);
388 
389     if (UserInfo->Parameters.Buffer != NULL)
390         SamFreeMemory(UserInfo->Parameters.Buffer);
391 
392     if (UserInfo->PrivateData.Buffer != NULL)
393         SamFreeMemory(UserInfo->PrivateData.Buffer);
394 
395     if (UserInfo->LogonHours.LogonHours != NULL)
396         SamFreeMemory(UserInfo->LogonHours.LogonHours);
397 
398     SamFreeMemory(UserInfo);
399 }
400 
401 
402 static
403 NET_API_STATUS
404 GetUserPrivileges(
405     _In_ SAM_HANDLE BuiltinDomainHandle,
406     _In_ SAM_HANDLE UserHandle,
407     _In_ PSID AccountDomainSid,
408     _In_ ULONG RelativeId,
409     _Out_ PDWORD Priv,
410     _Out_ PDWORD AuthFlags)
411 {
412     PGROUP_MEMBERSHIP GroupMembership = NULL;
413     ULONG GroupCount, SidCount, AliasCount, i;
414     PSID *SidArray = NULL;
415     PULONG AliasArray = NULL;
416     BOOL bAdmin = FALSE, bUser = FALSE;
417     NET_API_STATUS ApiStatus = NERR_Success;
418     NTSTATUS Status;
419 
420     FIXME("GetUserPrivileges(%p)\n", UserHandle);
421 
422     /* Get the users group memberships */
423     Status = SamGetGroupsForUser(UserHandle,
424                                  &GroupMembership,
425                                  &GroupCount);
426     if (!NT_SUCCESS(Status))
427     {
428         ERR("SamGetGroupsForUser() failed (Status 0x%08lx)\n", Status);
429         ApiStatus = NetpNtStatusToApiStatus(Status);
430         goto done;
431     }
432 
433     /* Allocate the SID array */
434     ApiStatus = NetApiBufferAllocate((GroupCount + 1) * sizeof(PSID),
435                                      (PVOID*)&SidArray);
436     if (ApiStatus != NERR_Success)
437     {
438         goto done;
439     }
440 
441     /* Add the user to the SID array */
442     SidCount = 0;
443     ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
444                                       RelativeId,
445                                       &SidArray[0]);
446     if (ApiStatus != NERR_Success)
447     {
448         goto done;
449     }
450 
451     SidCount++;
452 
453     /* Add the groups to the SID array */
454     for (i = 0; i < GroupCount; i++)
455     {
456         ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
457                                           GroupMembership[i].RelativeId,
458                                           &SidArray[i + 1]);
459         if (ApiStatus != NERR_Success)
460         {
461             goto done;
462         }
463 
464         SidCount++;
465     }
466 
467     /* Get aliases for the user and his groups */
468     Status = SamGetAliasMembership(BuiltinDomainHandle,
469                                    SidCount,
470                                    SidArray,
471                                    &AliasCount,
472                                    &AliasArray);
473     if (!NT_SUCCESS(Status))
474     {
475         ERR("SamGetAliasMembership() failed (Status 0x%08lx)\n", Status);
476         ApiStatus = NetpNtStatusToApiStatus(Status);
477         goto done;
478     }
479 
480     *AuthFlags = 0;
481 
482     /* Set the AuthFlags */
483     for (i = 0; i < AliasCount; i++)
484     {
485         switch (AliasArray[i])
486         {
487             case DOMAIN_ALIAS_RID_ADMINS:
488                 bAdmin = TRUE;
489                 break;
490 
491             case DOMAIN_ALIAS_RID_USERS:
492                 bUser = TRUE;
493                 break;
494 
495             case DOMAIN_ALIAS_RID_ACCOUNT_OPS:
496                 *AuthFlags |= AF_OP_ACCOUNTS;
497                 break;
498 
499             case DOMAIN_ALIAS_RID_SYSTEM_OPS:
500                 *AuthFlags |= AF_OP_SERVER;
501                 break;
502 
503             case DOMAIN_ALIAS_RID_PRINT_OPS:
504                 *AuthFlags |= AF_OP_PRINT;
505                 break;
506         }
507     }
508 
509     /* Set the prvileges */
510     if (bAdmin)
511     {
512         *Priv = USER_PRIV_ADMIN;
513     }
514     else if (bUser)
515     {
516         *Priv = USER_PRIV_USER;
517     }
518     else
519     {
520         *Priv = USER_PRIV_GUEST;
521     }
522 
523 done:
524     if (AliasArray != NULL)
525         SamFreeMemory(AliasArray);
526 
527     if (SidArray != NULL)
528     {
529         for (i = 0; i < SidCount; i++)
530             NetApiBufferFree(SidArray[i]);
531 
532         NetApiBufferFree(SidArray);
533     }
534 
535     if (GroupMembership != NULL)
536         SamFreeMemory(GroupMembership);
537 
538     return ApiStatus;
539 }
540 
541 
542 static
543 NET_API_STATUS
544 BuildUserInfoBuffer(
545     _In_ SAM_HANDLE BuiltinDomainHandle,
546     _In_ SAM_HANDLE UserHandle,
547     _In_ PSID AccountDomainSid,
548     _In_ ULONG RelativeId,
549     _In_ DWORD level,
550     _Out_ LPVOID *Buffer)
551 {
552     UNICODE_STRING LogonServer = RTL_CONSTANT_STRING(L"\\\\*");
553     PUSER_ALL_INFORMATION UserInfo = NULL;
554     LPVOID LocalBuffer = NULL;
555     PACL Dacl = NULL;
556     DWORD Priv = 0, AuthFlags = 0;
557     PUSER_INFO_0 UserInfo0;
558     PUSER_INFO_1 UserInfo1;
559     PUSER_INFO_2 UserInfo2;
560     PUSER_INFO_3 UserInfo3;
561     PUSER_INFO_4 UserInfo4;
562     PUSER_INFO_10 UserInfo10;
563     PUSER_INFO_11 UserInfo11;
564     PUSER_INFO_20 UserInfo20;
565     PUSER_INFO_23 UserInfo23;
566     LPWSTR Ptr;
567     ULONG Size = 0;
568     NTSTATUS Status;
569     NET_API_STATUS ApiStatus = NERR_Success;
570 
571     *Buffer = NULL;
572 
573     Status = SamQueryInformationUser(UserHandle,
574                                      UserAllInformation,
575                                      (PVOID *)&UserInfo);
576     if (!NT_SUCCESS(Status))
577     {
578         ERR("SamQueryInformationUser failed (Status %08lx)\n", Status);
579         ApiStatus = NetpNtStatusToApiStatus(Status);
580         goto done;
581     }
582 
583     if ((level == 1) || (level == 2) || (level == 3) ||
584         (level == 4) || (level == 20) || (level == 23))
585     {
586         ApiStatus = GetUserDacl(UserHandle, &Dacl);
587         if (ApiStatus != NERR_Success)
588             goto done;
589     }
590 
591     if ((level == 1) || (level == 2) || (level == 3) ||
592         (level == 4) || (level == 11))
593     {
594         ApiStatus = GetUserPrivileges(BuiltinDomainHandle,
595                                       UserHandle,
596                                       AccountDomainSid,
597                                       RelativeId,
598                                       &Priv,
599                                       &AuthFlags);
600         if (ApiStatus != NERR_Success)
601             goto done;
602     }
603 
604     switch (level)
605     {
606         case 0:
607             Size = sizeof(USER_INFO_0) +
608                    UserInfo->UserName.Length + sizeof(WCHAR);
609             break;
610 
611         case 1:
612             Size = sizeof(USER_INFO_1) +
613                    UserInfo->UserName.Length + sizeof(WCHAR) +
614                    UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
615                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
616                    UserInfo->ScriptPath.Length + sizeof(WCHAR);
617             break;
618 
619         case 2:
620             Size = sizeof(USER_INFO_2) +
621                    UserInfo->UserName.Length + sizeof(WCHAR) +
622                    UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
623                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
624                    UserInfo->ScriptPath.Length + sizeof(WCHAR) +
625                    UserInfo->FullName.Length + sizeof(WCHAR) +
626                    UserInfo->UserComment.Length + sizeof(WCHAR) +
627                    UserInfo->Parameters.Length + sizeof(WCHAR) +
628                    UserInfo->WorkStations.Length + sizeof(WCHAR) +
629                    LogonServer.Length + sizeof(WCHAR);
630 
631             if (UserInfo->LogonHours.UnitsPerWeek > 0)
632                 Size += (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8;
633             break;
634 
635         case 3:
636             Size = sizeof(USER_INFO_3) +
637                    UserInfo->UserName.Length + sizeof(WCHAR) +
638                    UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
639                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
640                    UserInfo->ScriptPath.Length + sizeof(WCHAR) +
641                    UserInfo->FullName.Length + sizeof(WCHAR) +
642                    UserInfo->UserComment.Length + sizeof(WCHAR) +
643                    UserInfo->Parameters.Length + sizeof(WCHAR) +
644                    UserInfo->WorkStations.Length + sizeof(WCHAR) +
645                    LogonServer.Length + sizeof(WCHAR) +
646                    UserInfo->ProfilePath.Length + sizeof(WCHAR) +
647                    UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR);
648 
649             if (UserInfo->LogonHours.UnitsPerWeek > 0)
650                 Size += (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8;
651             break;
652 
653         case 4:
654             Size = sizeof(USER_INFO_4) +
655                    UserInfo->UserName.Length + sizeof(WCHAR) +
656                    UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
657                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
658                    UserInfo->ScriptPath.Length + sizeof(WCHAR) +
659                    UserInfo->FullName.Length + sizeof(WCHAR) +
660                    UserInfo->UserComment.Length + sizeof(WCHAR) +
661                    UserInfo->Parameters.Length + sizeof(WCHAR) +
662                    UserInfo->WorkStations.Length + sizeof(WCHAR) +
663                    LogonServer.Length + sizeof(WCHAR) +
664                    UserInfo->ProfilePath.Length + sizeof(WCHAR) +
665                    UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR);
666 
667             if (UserInfo->LogonHours.UnitsPerWeek > 0)
668                 Size += (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8;
669 
670             Size += RtlLengthSid(AccountDomainSid) + sizeof(ULONG);
671             break;
672 
673         case 10:
674             Size = sizeof(USER_INFO_10) +
675                    UserInfo->UserName.Length + sizeof(WCHAR) +
676                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
677                    UserInfo->UserComment.Length + sizeof(WCHAR) +
678                    UserInfo->FullName.Length + sizeof(WCHAR);
679             break;
680 
681         case 11:
682             Size = sizeof(USER_INFO_11) +
683                    UserInfo->UserName.Length + sizeof(WCHAR) +
684                    UserInfo->AdminComment.Length + sizeof(WCHAR) +
685                    UserInfo->UserComment.Length + sizeof(WCHAR) +
686                    UserInfo->FullName.Length + sizeof(WCHAR) +
687                    UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
688                    UserInfo->Parameters.Length + sizeof(WCHAR) +
689                    LogonServer.Length + sizeof(WCHAR) +
690                    UserInfo->WorkStations.Length + sizeof(WCHAR);
691 
692             if (UserInfo->LogonHours.UnitsPerWeek > 0)
693                 Size += (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8;
694             break;
695 
696         case 20:
697             Size = sizeof(USER_INFO_20) +
698                    UserInfo->UserName.Length + sizeof(WCHAR) +
699                    UserInfo->FullName.Length + sizeof(WCHAR) +
700                    UserInfo->AdminComment.Length + sizeof(WCHAR);
701             break;
702 
703         case 23:
704             Size = sizeof(USER_INFO_23) +
705                    UserInfo->UserName.Length + sizeof(WCHAR) +
706                    UserInfo->FullName.Length + sizeof(WCHAR) +
707                    UserInfo->AdminComment.Length + sizeof(WCHAR);
708 
709             Size += RtlLengthSid(AccountDomainSid) + sizeof(ULONG);
710             break;
711 
712         default:
713             ApiStatus = ERROR_INVALID_LEVEL;
714             goto done;
715     }
716 
717     ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer);
718     if (ApiStatus != NERR_Success)
719         goto done;
720 
721     ZeroMemory(LocalBuffer, Size);
722 
723     switch (level)
724     {
725         case 0:
726             UserInfo0 = (PUSER_INFO_0)LocalBuffer;
727 
728             Ptr = (LPWSTR)((ULONG_PTR)UserInfo0 + sizeof(USER_INFO_0));
729 
730             UserInfo0->usri0_name = Ptr;
731 
732             memcpy(UserInfo0->usri0_name,
733                    UserInfo->UserName.Buffer,
734                    UserInfo->UserName.Length);
735             UserInfo0->usri0_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
736             break;
737 
738         case 1:
739             UserInfo1 = (PUSER_INFO_1)LocalBuffer;
740 
741             Ptr = (LPWSTR)((ULONG_PTR)UserInfo1 + sizeof(USER_INFO_1));
742 
743             UserInfo1->usri1_name = Ptr;
744 
745             memcpy(UserInfo1->usri1_name,
746                    UserInfo->UserName.Buffer,
747                    UserInfo->UserName.Length);
748             UserInfo1->usri1_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
749 
750             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
751 
752             UserInfo1->usri1_password = NULL;
753             UserInfo1->usri1_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
754 
755             UserInfo1->usri1_priv = Priv;
756 
757             UserInfo1->usri1_home_dir = Ptr;
758             memcpy(UserInfo1->usri1_home_dir,
759                    UserInfo->HomeDirectory.Buffer,
760                    UserInfo->HomeDirectory.Length);
761             UserInfo1->usri1_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
762             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
763 
764             UserInfo1->usri1_comment = Ptr;
765             memcpy(UserInfo1->usri1_comment,
766                    UserInfo->AdminComment.Buffer,
767                    UserInfo->AdminComment.Length);
768             UserInfo1->usri1_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
769             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
770 
771             UserInfo1->usri1_flags = GetAccountFlags(UserInfo->UserAccountControl,
772                                                      Dacl);
773 
774             UserInfo1->usri1_script_path = Ptr;
775             memcpy(UserInfo1->usri1_script_path,
776                    UserInfo->ScriptPath.Buffer,
777                    UserInfo->ScriptPath.Length);
778             UserInfo1->usri1_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
779             break;
780 
781         case 2:
782             UserInfo2 = (PUSER_INFO_2)LocalBuffer;
783 
784             Ptr = (LPWSTR)((ULONG_PTR)UserInfo2 + sizeof(USER_INFO_2));
785 
786             UserInfo2->usri2_name = Ptr;
787 
788             memcpy(UserInfo2->usri2_name,
789                    UserInfo->UserName.Buffer,
790                    UserInfo->UserName.Length);
791             UserInfo2->usri2_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
792 
793             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
794 
795             UserInfo2->usri2_password = NULL;
796             UserInfo2->usri2_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
797 
798             UserInfo2->usri2_priv = Priv;
799 
800             UserInfo2->usri2_home_dir = Ptr;
801             memcpy(UserInfo2->usri2_home_dir,
802                    UserInfo->HomeDirectory.Buffer,
803                    UserInfo->HomeDirectory.Length);
804             UserInfo2->usri2_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
805             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
806 
807             UserInfo2->usri2_comment = Ptr;
808             memcpy(UserInfo2->usri2_comment,
809                    UserInfo->AdminComment.Buffer,
810                    UserInfo->AdminComment.Length);
811             UserInfo2->usri2_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
812             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
813 
814             UserInfo2->usri2_flags = GetAccountFlags(UserInfo->UserAccountControl,
815                                                      Dacl);
816 
817             UserInfo2->usri2_script_path = Ptr;
818             memcpy(UserInfo2->usri2_script_path,
819                    UserInfo->ScriptPath.Buffer,
820                    UserInfo->ScriptPath.Length);
821             UserInfo2->usri2_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
822             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length + sizeof(WCHAR));
823 
824             UserInfo2->usri2_auth_flags = AuthFlags;
825 
826             UserInfo2->usri2_full_name = Ptr;
827             memcpy(UserInfo2->usri2_full_name,
828                    UserInfo->FullName.Buffer,
829                    UserInfo->FullName.Length);
830             UserInfo2->usri2_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
831             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
832 
833             UserInfo2->usri2_usr_comment = Ptr;
834             memcpy(UserInfo2->usri2_usr_comment,
835                    UserInfo->UserComment.Buffer,
836                    UserInfo->UserComment.Length);
837             UserInfo2->usri2_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
838             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
839 
840             UserInfo2->usri2_parms = Ptr;
841             memcpy(UserInfo2->usri2_parms,
842                    UserInfo->Parameters.Buffer,
843                    UserInfo->Parameters.Length);
844             UserInfo2->usri2_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
845             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
846 
847             UserInfo2->usri2_workstations = Ptr;
848             memcpy(UserInfo2->usri2_workstations,
849                    UserInfo->WorkStations.Buffer,
850                    UserInfo->WorkStations.Length);
851             UserInfo2->usri2_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
852             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
853 
854             if (UserInfo->LastLogon.QuadPart == 0)
855                 UserInfo2->usri2_last_logon = 0;
856             else
857                 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
858                                           &UserInfo2->usri2_last_logon);
859 
860             if (UserInfo->LastLogoff.QuadPart == 0)
861                 UserInfo2->usri2_last_logoff = 0;
862             else
863                 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
864                                           &UserInfo2->usri2_last_logoff);
865 
866             if (UserInfo->AccountExpires.QuadPart == MAXLONGLONG)
867                 UserInfo2->usri2_acct_expires = TIMEQ_FOREVER;
868             else
869                 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
870                                           &UserInfo2->usri2_acct_expires);
871 
872             UserInfo2->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED;
873             UserInfo2->usri2_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
874 
875             if (UserInfo->LogonHours.UnitsPerWeek > 0)
876             {
877                 UserInfo2->usri2_logon_hours = (PVOID)Ptr;
878 
879                 memcpy(UserInfo2->usri2_logon_hours,
880                        UserInfo->LogonHours.LogonHours,
881                        (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
882 
883                 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
884             }
885 
886             UserInfo2->usri2_bad_pw_count = UserInfo->BadPasswordCount;
887             UserInfo2->usri2_num_logons = UserInfo->LogonCount;
888 
889             UserInfo2->usri2_logon_server = Ptr;
890             memcpy(UserInfo2->usri2_logon_server,
891                    LogonServer.Buffer,
892                    LogonServer.Length);
893             UserInfo2->usri2_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
894             Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
895 
896             UserInfo2->usri2_country_code = UserInfo->CountryCode;
897             UserInfo2->usri2_code_page = UserInfo->CodePage;
898             break;
899 
900         case 3:
901             UserInfo3 = (PUSER_INFO_3)LocalBuffer;
902 
903             Ptr = (LPWSTR)((ULONG_PTR)UserInfo3 + sizeof(USER_INFO_3));
904 
905             UserInfo3->usri3_name = Ptr;
906 
907             memcpy(UserInfo3->usri3_name,
908                    UserInfo->UserName.Buffer,
909                    UserInfo->UserName.Length);
910             UserInfo3->usri3_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
911 
912             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
913 
914             UserInfo3->usri3_password = NULL;
915             UserInfo3->usri3_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
916 
917             UserInfo3->usri3_priv = Priv;
918 
919             UserInfo3->usri3_home_dir = Ptr;
920             memcpy(UserInfo3->usri3_home_dir,
921                    UserInfo->HomeDirectory.Buffer,
922                    UserInfo->HomeDirectory.Length);
923             UserInfo3->usri3_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
924             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
925 
926             UserInfo3->usri3_comment = Ptr;
927             memcpy(UserInfo3->usri3_comment,
928                    UserInfo->AdminComment.Buffer,
929                    UserInfo->AdminComment.Length);
930             UserInfo3->usri3_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
931             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
932 
933             UserInfo3->usri3_flags = GetAccountFlags(UserInfo->UserAccountControl,
934                                                      Dacl);
935 
936             UserInfo3->usri3_script_path = Ptr;
937             memcpy(UserInfo3->usri3_script_path,
938                    UserInfo->ScriptPath.Buffer,
939                    UserInfo->ScriptPath.Length);
940             UserInfo3->usri3_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
941             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length + sizeof(WCHAR));
942 
943             UserInfo3->usri3_auth_flags = AuthFlags;
944 
945             UserInfo3->usri3_full_name = Ptr;
946             memcpy(UserInfo3->usri3_full_name,
947                    UserInfo->FullName.Buffer,
948                    UserInfo->FullName.Length);
949             UserInfo3->usri3_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
950             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
951 
952             UserInfo3->usri3_usr_comment = Ptr;
953             memcpy(UserInfo3->usri3_usr_comment,
954                    UserInfo->UserComment.Buffer,
955                    UserInfo->UserComment.Length);
956             UserInfo3->usri3_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
957             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
958 
959             UserInfo3->usri3_parms = Ptr;
960             memcpy(UserInfo3->usri3_parms,
961                    UserInfo->Parameters.Buffer,
962                    UserInfo->Parameters.Length);
963             UserInfo3->usri3_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
964             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
965 
966             UserInfo3->usri3_workstations = Ptr;
967             memcpy(UserInfo3->usri3_workstations,
968                    UserInfo->WorkStations.Buffer,
969                    UserInfo->WorkStations.Length);
970             UserInfo3->usri3_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
971             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
972 
973             if (UserInfo->LastLogon.QuadPart == 0)
974                 UserInfo3->usri3_last_logon = 0;
975             else
976                 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
977                                           &UserInfo3->usri3_last_logon);
978 
979             if (UserInfo->LastLogoff.QuadPart == 0)
980                 UserInfo3->usri3_last_logoff = 0;
981             else
982                 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
983                                           &UserInfo3->usri3_last_logoff);
984 
985             if (UserInfo->AccountExpires.QuadPart == MAXLONGLONG)
986                 UserInfo3->usri3_acct_expires = TIMEQ_FOREVER;
987             else
988                 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
989                                           &UserInfo3->usri3_acct_expires);
990 
991             UserInfo3->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED;
992             UserInfo3->usri3_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
993 
994             if (UserInfo->LogonHours.UnitsPerWeek > 0)
995             {
996                 UserInfo3->usri3_logon_hours = (PVOID)Ptr;
997 
998                 memcpy(UserInfo3->usri3_logon_hours,
999                        UserInfo->LogonHours.LogonHours,
1000                        (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1001 
1002                 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1003             }
1004 
1005             UserInfo3->usri3_bad_pw_count = UserInfo->BadPasswordCount;
1006             UserInfo3->usri3_num_logons = UserInfo->LogonCount;
1007 
1008             UserInfo3->usri3_logon_server = Ptr;
1009             memcpy(UserInfo3->usri3_logon_server,
1010                    LogonServer.Buffer,
1011                    LogonServer.Length);
1012             UserInfo3->usri3_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1013             Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
1014 
1015             UserInfo3->usri3_country_code = UserInfo->CountryCode;
1016             UserInfo3->usri3_code_page = UserInfo->CodePage;
1017             UserInfo3->usri3_user_id = RelativeId;
1018             UserInfo3->usri3_primary_group_id = UserInfo->PrimaryGroupId;
1019 
1020             UserInfo3->usri3_profile = Ptr;
1021             memcpy(UserInfo3->usri3_profile,
1022                    UserInfo->ProfilePath.Buffer,
1023                    UserInfo->ProfilePath.Length);
1024             UserInfo3->usri3_profile[UserInfo->ProfilePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
1025             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ProfilePath.Length + sizeof(WCHAR));
1026 
1027             UserInfo3->usri3_home_dir_drive = Ptr;
1028             memcpy(UserInfo3->usri3_home_dir_drive,
1029                    UserInfo->HomeDirectoryDrive.Buffer,
1030                    UserInfo->HomeDirectoryDrive.Length);
1031             UserInfo3->usri3_home_dir_drive[UserInfo->HomeDirectoryDrive.Length / sizeof(WCHAR)] = UNICODE_NULL;
1032             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR));
1033 
1034             UserInfo3->usri3_password_expired = (UserInfo->UserAccountControl & USER_PASSWORD_EXPIRED);
1035             break;
1036 
1037         case 4:
1038             UserInfo4 = (PUSER_INFO_4)LocalBuffer;
1039 
1040             Ptr = (LPWSTR)((ULONG_PTR)UserInfo4 + sizeof(USER_INFO_4));
1041 
1042             UserInfo4->usri4_name = Ptr;
1043 
1044             memcpy(UserInfo4->usri4_name,
1045                    UserInfo->UserName.Buffer,
1046                    UserInfo->UserName.Length);
1047             UserInfo4->usri4_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1048 
1049             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1050 
1051             UserInfo4->usri4_password = NULL;
1052             UserInfo4->usri4_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
1053 
1054             UserInfo4->usri4_priv = Priv;
1055 
1056             UserInfo4->usri4_home_dir = Ptr;
1057             memcpy(UserInfo4->usri4_home_dir,
1058                    UserInfo->HomeDirectory.Buffer,
1059                    UserInfo->HomeDirectory.Length);
1060             UserInfo4->usri4_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
1061             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
1062 
1063             UserInfo4->usri4_comment = Ptr;
1064             memcpy(UserInfo4->usri4_comment,
1065                    UserInfo->AdminComment.Buffer,
1066                    UserInfo->AdminComment.Length);
1067             UserInfo4->usri4_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1068             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1069 
1070             UserInfo4->usri4_flags = GetAccountFlags(UserInfo->UserAccountControl,
1071                                                      Dacl);
1072 
1073             UserInfo4->usri4_script_path = Ptr;
1074             memcpy(UserInfo4->usri4_script_path,
1075                    UserInfo->ScriptPath.Buffer,
1076                    UserInfo->ScriptPath.Length);
1077             UserInfo4->usri4_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
1078             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length + sizeof(WCHAR));
1079 
1080             UserInfo4->usri4_auth_flags = AuthFlags;
1081 
1082             UserInfo4->usri4_full_name = Ptr;
1083             memcpy(UserInfo4->usri4_full_name,
1084                    UserInfo->FullName.Buffer,
1085                    UserInfo->FullName.Length);
1086             UserInfo4->usri4_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1087             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1088 
1089             UserInfo4->usri4_usr_comment = Ptr;
1090             memcpy(UserInfo4->usri4_usr_comment,
1091                    UserInfo->UserComment.Buffer,
1092                    UserInfo->UserComment.Length);
1093             UserInfo4->usri4_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1094             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
1095 
1096             UserInfo4->usri4_parms = Ptr;
1097             memcpy(UserInfo4->usri4_parms,
1098                    UserInfo->Parameters.Buffer,
1099                    UserInfo->Parameters.Length);
1100             UserInfo4->usri4_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
1101             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
1102 
1103             UserInfo4->usri4_workstations = Ptr;
1104             memcpy(UserInfo4->usri4_workstations,
1105                    UserInfo->WorkStations.Buffer,
1106                    UserInfo->WorkStations.Length);
1107             UserInfo4->usri4_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
1108             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
1109 
1110             if (UserInfo->LastLogon.QuadPart == 0)
1111                 UserInfo4->usri4_last_logon = 0;
1112             else
1113                 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
1114                                           &UserInfo4->usri4_last_logon);
1115 
1116             if (UserInfo->LastLogoff.QuadPart == 0)
1117                 UserInfo4->usri4_last_logoff = 0;
1118             else
1119                 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
1120                                           &UserInfo4->usri4_last_logoff);
1121 
1122             if (UserInfo->AccountExpires.QuadPart == MAXLONGLONG)
1123                 UserInfo4->usri4_acct_expires = TIMEQ_FOREVER;
1124             else
1125                 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
1126                                           &UserInfo4->usri4_acct_expires);
1127 
1128             UserInfo4->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED;
1129             UserInfo4->usri4_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
1130 
1131             if (UserInfo->LogonHours.UnitsPerWeek > 0)
1132             {
1133                 UserInfo4->usri4_logon_hours = (PVOID)Ptr;
1134 
1135                 memcpy(UserInfo4->usri4_logon_hours,
1136                        UserInfo->LogonHours.LogonHours,
1137                        (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1138 
1139                 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1140             }
1141 
1142             UserInfo4->usri4_bad_pw_count = UserInfo->BadPasswordCount;
1143             UserInfo4->usri4_num_logons = UserInfo->LogonCount;
1144 
1145             UserInfo4->usri4_logon_server = Ptr;
1146             memcpy(UserInfo4->usri4_logon_server,
1147                    LogonServer.Buffer,
1148                    LogonServer.Length);
1149             UserInfo4->usri4_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1150             Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
1151 
1152             UserInfo4->usri4_country_code = UserInfo->CountryCode;
1153             UserInfo4->usri4_code_page = UserInfo->CodePage;
1154 
1155             UserInfo4->usri4_user_sid = (PVOID)Ptr;
1156             CopySidFromSidAndRid(UserInfo4->usri4_user_sid, AccountDomainSid, RelativeId);
1157             Ptr = (LPWSTR)((ULONG_PTR)Ptr + RtlLengthSid(AccountDomainSid) + sizeof(ULONG));
1158 
1159             UserInfo4->usri4_primary_group_id = UserInfo->PrimaryGroupId;
1160 
1161             UserInfo4->usri4_profile = Ptr;
1162             memcpy(UserInfo4->usri4_profile,
1163                    UserInfo->ProfilePath.Buffer,
1164                    UserInfo->ProfilePath.Length);
1165             UserInfo4->usri4_profile[UserInfo->ProfilePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
1166             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ProfilePath.Length + sizeof(WCHAR));
1167 
1168             UserInfo4->usri4_home_dir_drive = Ptr;
1169             memcpy(UserInfo4->usri4_home_dir_drive,
1170                    UserInfo->HomeDirectoryDrive.Buffer,
1171                    UserInfo->HomeDirectoryDrive.Length);
1172             UserInfo4->usri4_home_dir_drive[UserInfo->HomeDirectoryDrive.Length / sizeof(WCHAR)] = UNICODE_NULL;
1173             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR));
1174 
1175             UserInfo4->usri4_password_expired = (UserInfo->UserAccountControl & USER_PASSWORD_EXPIRED);
1176             break;
1177 
1178         case 10:
1179             UserInfo10 = (PUSER_INFO_10)LocalBuffer;
1180 
1181             Ptr = (LPWSTR)((ULONG_PTR)UserInfo10 + sizeof(USER_INFO_10));
1182 
1183             UserInfo10->usri10_name = Ptr;
1184 
1185             memcpy(UserInfo10->usri10_name,
1186                    UserInfo->UserName.Buffer,
1187                    UserInfo->UserName.Length);
1188             UserInfo10->usri10_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1189 
1190             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1191 
1192             UserInfo10->usri10_comment = Ptr;
1193             memcpy(UserInfo10->usri10_comment,
1194                    UserInfo->AdminComment.Buffer,
1195                    UserInfo->AdminComment.Length);
1196             UserInfo10->usri10_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1197             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1198 
1199             UserInfo10->usri10_usr_comment = Ptr;
1200             memcpy(UserInfo10->usri10_usr_comment,
1201                    UserInfo->UserComment.Buffer,
1202                    UserInfo->UserComment.Length);
1203             UserInfo10->usri10_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1204             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
1205 
1206             UserInfo10->usri10_full_name = Ptr;
1207             memcpy(UserInfo10->usri10_full_name,
1208                    UserInfo->FullName.Buffer,
1209                    UserInfo->FullName.Length);
1210             UserInfo10->usri10_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1211             break;
1212 
1213         case 11:
1214             UserInfo11 = (PUSER_INFO_11)LocalBuffer;
1215 
1216             Ptr = (LPWSTR)((ULONG_PTR)UserInfo11 + sizeof(USER_INFO_11));
1217 
1218             UserInfo11->usri11_name = Ptr;
1219 
1220             memcpy(UserInfo11->usri11_name,
1221                    UserInfo->UserName.Buffer,
1222                    UserInfo->UserName.Length);
1223             UserInfo11->usri11_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1224 
1225             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1226 
1227             UserInfo11->usri11_comment = Ptr;
1228             memcpy(UserInfo11->usri11_comment,
1229                    UserInfo->AdminComment.Buffer,
1230                    UserInfo->AdminComment.Length);
1231             UserInfo11->usri11_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1232             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1233 
1234             UserInfo11->usri11_usr_comment = Ptr;
1235             memcpy(UserInfo11->usri11_usr_comment,
1236                    UserInfo->UserComment.Buffer,
1237                    UserInfo->UserComment.Length);
1238             UserInfo11->usri11_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1239             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
1240 
1241             UserInfo11->usri11_full_name = Ptr;
1242             memcpy(UserInfo11->usri11_full_name,
1243                    UserInfo->FullName.Buffer,
1244                    UserInfo->FullName.Length);
1245             UserInfo11->usri11_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1246             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1247 
1248             UserInfo11->usri11_priv = Priv;
1249             UserInfo11->usri11_auth_flags = AuthFlags;
1250 
1251             UserInfo11->usri11_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
1252 
1253             UserInfo11->usri11_home_dir = Ptr;
1254             memcpy(UserInfo11->usri11_home_dir,
1255                    UserInfo->HomeDirectory.Buffer,
1256                    UserInfo->HomeDirectory.Length);
1257             UserInfo11->usri11_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
1258             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
1259 
1260             UserInfo11->usri11_parms = Ptr;
1261             memcpy(UserInfo11->usri11_parms,
1262                    UserInfo->Parameters.Buffer,
1263                    UserInfo->Parameters.Length);
1264             UserInfo11->usri11_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
1265             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
1266 
1267             if (UserInfo->LastLogon.QuadPart == 0)
1268                 UserInfo11->usri11_last_logon = 0;
1269             else
1270                 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
1271                                           &UserInfo11->usri11_last_logon);
1272 
1273             if (UserInfo->LastLogoff.QuadPart == 0)
1274                 UserInfo11->usri11_last_logoff = 0;
1275             else
1276                 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
1277                                           &UserInfo11->usri11_last_logoff);
1278 
1279             UserInfo11->usri11_bad_pw_count = UserInfo->BadPasswordCount;
1280             UserInfo11->usri11_num_logons = UserInfo->LogonCount;
1281 
1282             UserInfo11->usri11_logon_server = Ptr;
1283             memcpy(UserInfo11->usri11_logon_server,
1284                    LogonServer.Buffer,
1285                    LogonServer.Length);
1286             UserInfo11->usri11_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1287             Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
1288 
1289             UserInfo11->usri11_country_code = UserInfo->CountryCode;
1290 
1291             UserInfo11->usri11_workstations = Ptr;
1292             memcpy(UserInfo11->usri11_workstations,
1293                    UserInfo->WorkStations.Buffer,
1294                    UserInfo->WorkStations.Length);
1295             UserInfo11->usri11_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
1296             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
1297 
1298             UserInfo11->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED;
1299             UserInfo11->usri11_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
1300 
1301             if (UserInfo->LogonHours.UnitsPerWeek > 0)
1302             {
1303                 UserInfo11->usri11_logon_hours = (PVOID)Ptr;
1304 
1305                 memcpy(UserInfo11->usri11_logon_hours,
1306                        UserInfo->LogonHours.LogonHours,
1307                        (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1308 
1309                 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1310             }
1311 
1312             UserInfo11->usri11_code_page = UserInfo->CodePage;
1313             break;
1314 
1315         case 20:
1316             UserInfo20 = (PUSER_INFO_20)LocalBuffer;
1317 
1318             Ptr = (LPWSTR)((ULONG_PTR)UserInfo20 + sizeof(USER_INFO_20));
1319 
1320             UserInfo20->usri20_name = Ptr;
1321 
1322             memcpy(UserInfo20->usri20_name,
1323                    UserInfo->UserName.Buffer,
1324                    UserInfo->UserName.Length);
1325             UserInfo20->usri20_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1326 
1327             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1328 
1329             UserInfo20->usri20_full_name = Ptr;
1330             memcpy(UserInfo20->usri20_full_name,
1331                    UserInfo->FullName.Buffer,
1332                    UserInfo->FullName.Length);
1333             UserInfo20->usri20_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1334             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1335 
1336             UserInfo20->usri20_comment = Ptr;
1337             memcpy(UserInfo20->usri20_comment,
1338                    UserInfo->AdminComment.Buffer,
1339                    UserInfo->AdminComment.Length);
1340             UserInfo20->usri20_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1341             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1342 
1343             UserInfo20->usri20_flags = GetAccountFlags(UserInfo->UserAccountControl,
1344                                                        Dacl);
1345 
1346             UserInfo20->usri20_user_id = RelativeId;
1347             break;
1348 
1349         case 23:
1350             UserInfo23 = (PUSER_INFO_23)LocalBuffer;
1351 
1352             Ptr = (LPWSTR)((ULONG_PTR)UserInfo23 + sizeof(USER_INFO_23));
1353 
1354             UserInfo23->usri23_name = Ptr;
1355 
1356             memcpy(UserInfo23->usri23_name,
1357                    UserInfo->UserName.Buffer,
1358                    UserInfo->UserName.Length);
1359             UserInfo23->usri23_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1360 
1361             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1362 
1363             UserInfo23->usri23_full_name = Ptr;
1364             memcpy(UserInfo23->usri23_full_name,
1365                    UserInfo->FullName.Buffer,
1366                    UserInfo->FullName.Length);
1367             UserInfo23->usri23_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1368             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1369 
1370             UserInfo23->usri23_comment = Ptr;
1371             memcpy(UserInfo23->usri23_comment,
1372                    UserInfo->AdminComment.Buffer,
1373                    UserInfo->AdminComment.Length);
1374             UserInfo23->usri23_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1375             Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1376 
1377             UserInfo23->usri23_flags = GetAccountFlags(UserInfo->UserAccountControl,
1378                                                        Dacl);
1379 
1380             UserInfo23->usri23_user_sid = (PVOID)Ptr;
1381             CopySidFromSidAndRid(UserInfo23->usri23_user_sid, AccountDomainSid, RelativeId);
1382             Ptr = (LPWSTR)((ULONG_PTR)Ptr + RtlLengthSid(AccountDomainSid) + sizeof(ULONG));
1383             break;
1384     }
1385 
1386 done:
1387     if (UserInfo != NULL)
1388         FreeUserInfo(UserInfo);
1389 
1390     if (Dacl != NULL)
1391         HeapFree(GetProcessHeap(), 0, Dacl);
1392 
1393     if (ApiStatus == NERR_Success)
1394     {
1395         *Buffer = LocalBuffer;
1396     }
1397     else
1398     {
1399         if (LocalBuffer != NULL)
1400             NetApiBufferFree(LocalBuffer);
1401     }
1402 
1403     return ApiStatus;
1404 }
1405 
1406 
1407 static
1408 NET_API_STATUS
1409 SetUserInfo(SAM_HANDLE UserHandle,
1410             LPBYTE UserInfo,
1411             DWORD Level,
1412             PDWORD parm_err)
1413 {
1414     USER_ALL_INFORMATION UserAllInfo;
1415     PUSER_INFO_0 UserInfo0;
1416     PUSER_INFO_1 UserInfo1;
1417     PUSER_INFO_2 UserInfo2;
1418     PUSER_INFO_3 UserInfo3;
1419     PUSER_INFO_4 UserInfo4;
1420     PUSER_INFO_22 UserInfo22;
1421     PUSER_INFO_1003 UserInfo1003;
1422     PUSER_INFO_1006 UserInfo1006;
1423     PUSER_INFO_1007 UserInfo1007;
1424     PUSER_INFO_1008 UserInfo1008;
1425     PUSER_INFO_1009 UserInfo1009;
1426     PUSER_INFO_1011 UserInfo1011;
1427     PUSER_INFO_1012 UserInfo1012;
1428     PUSER_INFO_1013 UserInfo1013;
1429     PUSER_INFO_1014 UserInfo1014;
1430     PUSER_INFO_1017 UserInfo1017;
1431     PUSER_INFO_1018 UserInfo1018;
1432     PUSER_INFO_1020 UserInfo1020;
1433     PUSER_INFO_1024 UserInfo1024;
1434     PUSER_INFO_1025 UserInfo1025;
1435     PUSER_INFO_1051 UserInfo1051;
1436     PUSER_INFO_1052 UserInfo1052;
1437     PUSER_INFO_1053 UserInfo1053;
1438     PACL Dacl = NULL;
1439     NET_API_STATUS ApiStatus = NERR_Success;
1440     NTSTATUS Status = STATUS_SUCCESS;
1441 
1442     ZeroMemory(&UserAllInfo, sizeof(USER_ALL_INFORMATION));
1443 
1444     if ((Level == 1) || (Level == 2) || (Level == 3) ||
1445         (Level == 4) || (Level == 22) || (Level == 1008))
1446     {
1447         ApiStatus = GetUserDacl(UserHandle, &Dacl);
1448         if (ApiStatus != NERR_Success)
1449             goto done;
1450     }
1451 
1452     switch (Level)
1453     {
1454         case 0:
1455             UserInfo0 = (PUSER_INFO_0)UserInfo;
1456 
1457             RtlInitUnicodeString(&UserAllInfo.UserName,
1458                                  UserInfo0->usri0_name);
1459 
1460             UserAllInfo.WhichFields |= USER_ALL_USERNAME;
1461             break;
1462 
1463         case 1:
1464             UserInfo1 = (PUSER_INFO_1)UserInfo;
1465 
1466             // usri1_name ignored
1467 
1468             if (UserInfo1->usri1_password != NULL)
1469             {
1470                 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1471                                      UserInfo1->usri1_password);
1472                 UserAllInfo.NtPasswordPresent = TRUE;
1473                 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1474             }
1475 
1476             // usri1_password_age ignored
1477 
1478 //          UserInfo1->usri1_priv
1479 
1480             if (UserInfo1->usri1_home_dir != NULL)
1481             {
1482                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1483                                      UserInfo1->usri1_home_dir);
1484                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1485             }
1486 
1487             if (UserInfo1->usri1_comment != NULL)
1488             {
1489                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1490                                      UserInfo1->usri1_comment);
1491                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1492             }
1493 
1494             ChangeUserDacl(Dacl, UserInfo1->usri1_flags);
1495             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1->usri1_flags);
1496             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1497 
1498             if (UserInfo1->usri1_script_path != NULL)
1499             {
1500                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1501                                      UserInfo1->usri1_script_path);
1502                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1503             }
1504             break;
1505 
1506         case 2:
1507             UserInfo2 = (PUSER_INFO_2)UserInfo;
1508 
1509             // usri2_name ignored
1510 
1511             if (UserInfo2->usri2_password != NULL)
1512             {
1513                 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1514                                      UserInfo2->usri2_password);
1515                 UserAllInfo.NtPasswordPresent = TRUE;
1516                 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1517             }
1518 
1519             // usri2_password_age ignored
1520 
1521 //          UserInfo2->usri2_priv;
1522 
1523             if (UserInfo2->usri2_home_dir != NULL)
1524             {
1525                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1526                                      UserInfo2->usri2_home_dir);
1527                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1528             }
1529 
1530             if (UserInfo2->usri2_comment != NULL)
1531             {
1532                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1533                                      UserInfo2->usri2_comment);
1534                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1535             }
1536 
1537             ChangeUserDacl(Dacl, UserInfo2->usri2_flags);
1538             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo2->usri2_flags);
1539             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1540 
1541             if (UserInfo2->usri2_script_path != NULL)
1542             {
1543                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1544                                      UserInfo2->usri2_script_path);
1545                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1546             }
1547 
1548 //          UserInfo2->usri2_auth_flags;
1549 
1550             if (UserInfo2->usri2_full_name != NULL)
1551             {
1552                 RtlInitUnicodeString(&UserAllInfo.FullName,
1553                                      UserInfo2->usri2_full_name);
1554                 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1555             }
1556 
1557             if (UserInfo2->usri2_usr_comment != NULL)
1558             {
1559                 RtlInitUnicodeString(&UserAllInfo.UserComment,
1560                                      UserInfo2->usri2_usr_comment);
1561                 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1562             }
1563 
1564             if (UserInfo2->usri2_parms != NULL)
1565             {
1566                 RtlInitUnicodeString(&UserAllInfo.Parameters,
1567                                      UserInfo2->usri2_parms);
1568                 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1569             }
1570 
1571             if (UserInfo2->usri2_workstations != NULL)
1572             {
1573                 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1574                                      UserInfo2->usri2_workstations);
1575                 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1576             }
1577 
1578             // usri2_last_logon ignored
1579             // usri2_last_logoff ignored
1580 
1581             if (UserInfo2->usri2_acct_expires == TIMEQ_FOREVER)
1582             {
1583                 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1584             }
1585             else
1586             {
1587                 RtlSecondsSince1970ToTime(UserInfo2->usri2_acct_expires,
1588                                           &UserAllInfo.AccountExpires);
1589             }
1590             UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1591 
1592             if (UserInfo2->usri2_max_storage != USER_MAXSTORAGE_UNLIMITED)
1593             {
1594                 if (parm_err != NULL)
1595                     *parm_err = USER_MAX_STORAGE_PARMNUM;
1596                 ApiStatus = ERROR_INVALID_PARAMETER;
1597                 break;
1598             }
1599 
1600             if (UserInfo2->usri2_units_per_week > USHRT_MAX)
1601             {
1602                 if (parm_err != NULL)
1603                     *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1604                 ApiStatus = ERROR_INVALID_PARAMETER;
1605                 break;
1606             }
1607 
1608             UserAllInfo.LogonHours.UnitsPerWeek = UserInfo2->usri2_units_per_week;
1609             UserAllInfo.LogonHours.LogonHours = UserInfo2->usri2_logon_hours;
1610             UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1611 
1612             // usri2_bad_pw_count ignored
1613             // usri2_num_logons ignored
1614             // usri2_logon_server ignored
1615 
1616             UserAllInfo.CountryCode = UserInfo2->usri2_country_code;
1617             UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1618 
1619             UserAllInfo.CodePage = UserInfo2->usri2_code_page;
1620             UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1621             break;
1622 
1623         case 3:
1624             UserInfo3 = (PUSER_INFO_3)UserInfo;
1625 
1626             // usri3_name ignored
1627 
1628             if (UserInfo3->usri3_password != NULL)
1629             {
1630                 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1631                                      UserInfo3->usri3_password);
1632                 UserAllInfo.NtPasswordPresent = TRUE;
1633                 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1634             }
1635 
1636             // usri3_password_age ignored
1637 
1638 //          UserInfo3->usri3_priv;
1639 
1640             if (UserInfo3->usri3_home_dir != NULL)
1641             {
1642                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1643                                      UserInfo3->usri3_home_dir);
1644                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1645             }
1646 
1647             if (UserInfo3->usri3_comment != NULL)
1648             {
1649                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1650                                      UserInfo3->usri3_comment);
1651                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1652             }
1653 
1654             ChangeUserDacl(Dacl, UserInfo3->usri3_flags);
1655             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo3->usri3_flags);
1656             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1657 
1658             if (UserInfo3->usri3_script_path != NULL)
1659             {
1660                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1661                                      UserInfo3->usri3_script_path);
1662                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1663             }
1664 
1665 //          UserInfo3->usri3_auth_flags;
1666 
1667             if (UserInfo3->usri3_full_name != NULL)
1668             {
1669                 RtlInitUnicodeString(&UserAllInfo.FullName,
1670                                      UserInfo3->usri3_full_name);
1671                 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1672             }
1673 
1674             if (UserInfo3->usri3_usr_comment != NULL)
1675             {
1676                 RtlInitUnicodeString(&UserAllInfo.UserComment,
1677                                      UserInfo3->usri3_usr_comment);
1678                 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1679             }
1680 
1681             if (UserInfo3->usri3_parms != NULL)
1682             {
1683                 RtlInitUnicodeString(&UserAllInfo.Parameters,
1684                                      UserInfo3->usri3_parms);
1685                 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1686             }
1687 
1688             if (UserInfo3->usri3_workstations != NULL)
1689             {
1690                 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1691                                      UserInfo3->usri3_workstations);
1692                 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1693             }
1694 
1695             // usri3_last_logon ignored
1696             // usri3_last_logoff ignored
1697 
1698             if (UserInfo3->usri3_acct_expires == TIMEQ_FOREVER)
1699             {
1700                 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1701             }
1702             else
1703             {
1704                 RtlSecondsSince1970ToTime(UserInfo3->usri3_acct_expires,
1705                                           &UserAllInfo.AccountExpires);
1706             }
1707             UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1708 
1709             if (UserInfo3->usri3_max_storage != USER_MAXSTORAGE_UNLIMITED)
1710             {
1711                 if (parm_err != NULL)
1712                     *parm_err = USER_MAX_STORAGE_PARMNUM;
1713                 ApiStatus = ERROR_INVALID_PARAMETER;
1714                 break;
1715             }
1716 
1717             if (UserInfo3->usri3_units_per_week > USHRT_MAX)
1718             {
1719                 if (parm_err != NULL)
1720                     *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1721                 ApiStatus = ERROR_INVALID_PARAMETER;
1722                 break;
1723             }
1724 
1725             UserAllInfo.LogonHours.UnitsPerWeek = UserInfo3->usri3_units_per_week;
1726             UserAllInfo.LogonHours.LogonHours = UserInfo3->usri3_logon_hours;
1727             UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1728 
1729             // usri3_bad_pw_count ignored
1730             // usri3_num_logons ignored
1731             // usri3_logon_server ignored
1732 
1733             UserAllInfo.CountryCode = UserInfo3->usri3_country_code;
1734             UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1735 
1736             UserAllInfo.CodePage = UserInfo3->usri3_code_page;
1737             UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1738 
1739             // usri3_user_id ignored
1740 
1741             UserAllInfo.PrimaryGroupId = UserInfo3->usri3_primary_group_id;
1742             UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1743 
1744             if (UserInfo3->usri3_profile != NULL)
1745             {
1746                 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1747                                      UserInfo3->usri3_profile);
1748                 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1749             }
1750 
1751             if (UserInfo3->usri3_home_dir_drive != NULL)
1752             {
1753                 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1754                                      UserInfo3->usri3_home_dir_drive);
1755                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1756             }
1757 
1758             UserAllInfo.PasswordExpired = (UserInfo3->usri3_password_expired != 0);
1759             UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1760             break;
1761 
1762         case 4:
1763             UserInfo4 = (PUSER_INFO_4)UserInfo;
1764 
1765             // usri4_name ignored
1766 
1767             if (UserInfo4->usri4_password != NULL)
1768             {
1769                 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1770                                      UserInfo4->usri4_password);
1771                 UserAllInfo.NtPasswordPresent = TRUE;
1772                 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1773             }
1774 
1775             // usri4_password_age ignored
1776 
1777 //          UserInfo3->usri4_priv;
1778 
1779             if (UserInfo4->usri4_home_dir != NULL)
1780             {
1781                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1782                                      UserInfo4->usri4_home_dir);
1783                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1784             }
1785 
1786             if (UserInfo4->usri4_comment != NULL)
1787             {
1788                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1789                                      UserInfo4->usri4_comment);
1790                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1791             }
1792 
1793             ChangeUserDacl(Dacl, UserInfo4->usri4_flags);
1794             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo4->usri4_flags);
1795             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1796 
1797             if (UserInfo4->usri4_script_path != NULL)
1798             {
1799                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1800                                      UserInfo4->usri4_script_path);
1801                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1802             }
1803 
1804 //          UserInfo4->usri4_auth_flags;
1805 
1806             if (UserInfo4->usri4_full_name != NULL)
1807             {
1808                 RtlInitUnicodeString(&UserAllInfo.FullName,
1809                                      UserInfo4->usri4_full_name);
1810                 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1811             }
1812 
1813             if (UserInfo4->usri4_usr_comment != NULL)
1814             {
1815                 RtlInitUnicodeString(&UserAllInfo.UserComment,
1816                                      UserInfo4->usri4_usr_comment);
1817                 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1818             }
1819 
1820             if (UserInfo4->usri4_parms != NULL)
1821             {
1822                 RtlInitUnicodeString(&UserAllInfo.Parameters,
1823                                      UserInfo4->usri4_parms);
1824                 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1825             }
1826 
1827             if (UserInfo4->usri4_workstations != NULL)
1828             {
1829                 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1830                                      UserInfo4->usri4_workstations);
1831                 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1832             }
1833 
1834             // usri4_last_logon ignored
1835             // usri4_last_logoff ignored
1836 
1837             if (UserInfo4->usri4_acct_expires == TIMEQ_FOREVER)
1838             {
1839                 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1840             }
1841             else
1842             {
1843                 RtlSecondsSince1970ToTime(UserInfo4->usri4_acct_expires,
1844                                           &UserAllInfo.AccountExpires);
1845             }
1846             UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1847 
1848             if (UserInfo4->usri4_max_storage != USER_MAXSTORAGE_UNLIMITED)
1849             {
1850                 if (parm_err != NULL)
1851                     *parm_err = USER_MAX_STORAGE_PARMNUM;
1852                 ApiStatus = ERROR_INVALID_PARAMETER;
1853                 break;
1854             }
1855 
1856             if (UserInfo4->usri4_units_per_week > USHRT_MAX)
1857             {
1858                 if (parm_err != NULL)
1859                     *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1860                 ApiStatus = ERROR_INVALID_PARAMETER;
1861                 break;
1862             }
1863 
1864             UserAllInfo.LogonHours.UnitsPerWeek = UserInfo4->usri4_units_per_week;
1865             UserAllInfo.LogonHours.LogonHours = UserInfo4->usri4_logon_hours;
1866             UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1867 
1868             // usri4_bad_pw_count ignored
1869             // usri4_num_logons ignored
1870             // usri4_logon_server ignored
1871 
1872             UserAllInfo.CountryCode = UserInfo4->usri4_country_code;
1873             UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1874 
1875             UserAllInfo.CodePage = UserInfo4->usri4_code_page;
1876             UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1877 
1878             // usri4_user_sid ignored
1879 
1880             UserAllInfo.PrimaryGroupId = UserInfo4->usri4_primary_group_id;
1881             UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1882 
1883             if (UserInfo4->usri4_profile != NULL)
1884             {
1885                 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1886                                      UserInfo4->usri4_profile);
1887                 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1888             }
1889 
1890             if (UserInfo4->usri4_home_dir_drive != NULL)
1891             {
1892                 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1893                                      UserInfo4->usri4_home_dir_drive);
1894                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1895             }
1896 
1897             UserAllInfo.PasswordExpired = (UserInfo4->usri4_password_expired != 0);
1898             UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1899             break;
1900 
1901 //        case 21:
1902 //            break;
1903 
1904         case 22:
1905             UserInfo22 = (PUSER_INFO_22)UserInfo;
1906 
1907             // usri22_name ignored
1908 
1909 //          UserInfo22->usri22_password[ENCRYPTED_PWLEN];
1910 
1911             // usri22_password_age ignored
1912 
1913 //          UserInfo3->usri3_priv;
1914 
1915             if (UserInfo22->usri22_home_dir != NULL)
1916             {
1917                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1918                                      UserInfo22->usri22_home_dir);
1919                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1920             }
1921 
1922             if (UserInfo22->usri22_comment != NULL)
1923             {
1924                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1925                                      UserInfo22->usri22_comment);
1926                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1927             }
1928 
1929             ChangeUserDacl(Dacl, UserInfo22->usri22_flags);
1930             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo22->usri22_flags);
1931             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1932 
1933             if (UserInfo22->usri22_script_path != NULL)
1934             {
1935                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1936                                      UserInfo22->usri22_script_path);
1937                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1938             }
1939 
1940 //          UserInfo22->usri22_auth_flags;
1941 
1942             if (UserInfo22->usri22_full_name != NULL)
1943             {
1944                 RtlInitUnicodeString(&UserAllInfo.FullName,
1945                                      UserInfo22->usri22_full_name);
1946                 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1947             }
1948 
1949             if (UserInfo22->usri22_usr_comment != NULL)
1950             {
1951                 RtlInitUnicodeString(&UserAllInfo.UserComment,
1952                                      UserInfo22->usri22_usr_comment);
1953                 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1954             }
1955 
1956             if (UserInfo22->usri22_parms != NULL)
1957             {
1958                 RtlInitUnicodeString(&UserAllInfo.Parameters,
1959                                      UserInfo22->usri22_parms);
1960                 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1961             }
1962 
1963             if (UserInfo22->usri22_workstations != NULL)
1964             {
1965                 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1966                                      UserInfo22->usri22_workstations);
1967                 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1968             }
1969 
1970             // usri22_last_logon ignored
1971             // usri22_last_logoff ignored
1972 
1973             if (UserInfo22->usri22_acct_expires == TIMEQ_FOREVER)
1974             {
1975                 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1976             }
1977             else
1978             {
1979                 RtlSecondsSince1970ToTime(UserInfo22->usri22_acct_expires,
1980                                           &UserAllInfo.AccountExpires);
1981             }
1982             UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1983 
1984             if (UserInfo22->usri22_max_storage != USER_MAXSTORAGE_UNLIMITED)
1985             {
1986                 if (parm_err != NULL)
1987                     *parm_err = USER_MAX_STORAGE_PARMNUM;
1988                 ApiStatus = ERROR_INVALID_PARAMETER;
1989                 break;
1990             }
1991 
1992             if (UserInfo22->usri22_units_per_week > USHRT_MAX)
1993             {
1994                 if (parm_err != NULL)
1995                     *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1996                 ApiStatus = ERROR_INVALID_PARAMETER;
1997                 break;
1998             }
1999 
2000             UserAllInfo.LogonHours.UnitsPerWeek = UserInfo22->usri22_units_per_week;
2001             UserAllInfo.LogonHours.LogonHours = UserInfo22->usri22_logon_hours;
2002             UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
2003 
2004             // usri22_bad_pw_count ignored
2005             // usri22_num_logons ignored
2006             // usri22_logon_server ignored
2007 
2008             UserAllInfo.CountryCode = UserInfo22->usri22_country_code;
2009             UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
2010 
2011             UserAllInfo.CodePage = UserInfo22->usri22_code_page;
2012             UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
2013             break;
2014 
2015         case 1003:
2016             UserInfo1003 = (PUSER_INFO_1003)UserInfo;
2017 
2018             if (UserInfo1003->usri1003_password != NULL)
2019             {
2020                 RtlInitUnicodeString(&UserAllInfo.NtPassword,
2021                                      UserInfo1003->usri1003_password);
2022                 UserAllInfo.NtPasswordPresent = TRUE;
2023                 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
2024             }
2025             break;
2026 
2027 //        case 1005:
2028 //            break;
2029 
2030         case 1006:
2031             UserInfo1006 = (PUSER_INFO_1006)UserInfo;
2032 
2033             if (UserInfo1006->usri1006_home_dir != NULL)
2034             {
2035                 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
2036                                      UserInfo1006->usri1006_home_dir);
2037                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
2038             }
2039             break;
2040 
2041         case 1007:
2042             UserInfo1007 = (PUSER_INFO_1007)UserInfo;
2043 
2044             if (UserInfo1007->usri1007_comment != NULL)
2045             {
2046                 RtlInitUnicodeString(&UserAllInfo.AdminComment,
2047                                      UserInfo1007->usri1007_comment);
2048                 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
2049             }
2050             break;
2051 
2052         case 1008:
2053             UserInfo1008 = (PUSER_INFO_1008)UserInfo;
2054             ChangeUserDacl(Dacl, UserInfo1008->usri1008_flags);
2055             UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1008->usri1008_flags);
2056             UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
2057             break;
2058 
2059         case 1009:
2060             UserInfo1009 = (PUSER_INFO_1009)UserInfo;
2061 
2062             if (UserInfo1009->usri1009_script_path != NULL)
2063             {
2064                 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
2065                                      UserInfo1009->usri1009_script_path);
2066                 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
2067             }
2068             break;
2069 
2070 //        case 1010:
2071 //            break;
2072 
2073         case 1011:
2074             UserInfo1011 = (PUSER_INFO_1011)UserInfo;
2075 
2076             if (UserInfo1011->usri1011_full_name != NULL)
2077             {
2078                 RtlInitUnicodeString(&UserAllInfo.FullName,
2079                                      UserInfo1011->usri1011_full_name);
2080                 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
2081             }
2082             break;
2083 
2084         case 1012:
2085             UserInfo1012 = (PUSER_INFO_1012)UserInfo;
2086 
2087             if (UserInfo1012->usri1012_usr_comment != NULL)
2088             {
2089                 RtlInitUnicodeString(&UserAllInfo.UserComment,
2090                                      UserInfo1012->usri1012_usr_comment);
2091                 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
2092             }
2093             break;
2094 
2095         case 1013:
2096             UserInfo1013 = (PUSER_INFO_1013)UserInfo;
2097 
2098             if (UserInfo1013->usri1013_parms != NULL)
2099             {
2100                 RtlInitUnicodeString(&UserAllInfo.Parameters,
2101                                      UserInfo1013->usri1013_parms);
2102                 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
2103             }
2104             break;
2105 
2106         case 1014:
2107             UserInfo1014 = (PUSER_INFO_1014)UserInfo;
2108 
2109             if (UserInfo1014->usri1014_workstations != NULL)
2110             {
2111                 RtlInitUnicodeString(&UserAllInfo.WorkStations,
2112                                      UserInfo1014->usri1014_workstations);
2113                 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
2114             }
2115             break;
2116 
2117         case 1017:
2118             UserInfo1017 = (PUSER_INFO_1017)UserInfo;
2119 
2120             if (UserInfo1017->usri1017_acct_expires == TIMEQ_FOREVER)
2121             {
2122                 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
2123             }
2124             else
2125             {
2126                 RtlSecondsSince1970ToTime(UserInfo1017->usri1017_acct_expires,
2127                                           &UserAllInfo.AccountExpires);
2128             }
2129             UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
2130             break;
2131 
2132         case 1018:
2133             UserInfo1018 = (PUSER_INFO_1018)UserInfo;
2134 
2135             if (UserInfo1018->usri1018_max_storage != USER_MAXSTORAGE_UNLIMITED)
2136             {
2137                 if (parm_err != NULL)
2138                     *parm_err = USER_MAX_STORAGE_PARMNUM;
2139                 ApiStatus = ERROR_INVALID_PARAMETER;
2140             }
2141             break;
2142 
2143         case 1020:
2144             UserInfo1020 = (PUSER_INFO_1020)UserInfo;
2145 
2146             if (UserInfo1020->usri1020_units_per_week > USHRT_MAX)
2147             {
2148                 if (parm_err != NULL)
2149                     *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
2150                 ApiStatus = ERROR_INVALID_PARAMETER;
2151                 break;
2152             }
2153 
2154             UserAllInfo.LogonHours.UnitsPerWeek = UserInfo1020->usri1020_units_per_week;
2155             UserAllInfo.LogonHours.LogonHours = UserInfo1020->usri1020_logon_hours;
2156             UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
2157             break;
2158 
2159         case 1024:
2160             UserInfo1024 = (PUSER_INFO_1024)UserInfo;
2161 
2162             UserAllInfo.CountryCode = UserInfo1024->usri1024_country_code;
2163             UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
2164             break;
2165 
2166         case 1025:
2167             UserInfo1025 = (PUSER_INFO_1025)UserInfo;
2168 
2169             UserAllInfo.CodePage = UserInfo1025->usri1025_code_page;
2170             UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
2171             break;
2172 
2173         case 1051:
2174             UserInfo1051 = (PUSER_INFO_1051)UserInfo;
2175 
2176             UserAllInfo.PrimaryGroupId = UserInfo1051->usri1051_primary_group_id;
2177             UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
2178             break;
2179 
2180         case 1052:
2181             UserInfo1052 = (PUSER_INFO_1052)UserInfo;
2182 
2183             if (UserInfo1052->usri1052_profile != NULL)
2184             {
2185                 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
2186                                      UserInfo1052->usri1052_profile);
2187                 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
2188             }
2189             break;
2190 
2191         case 1053:
2192             UserInfo1053 = (PUSER_INFO_1053)UserInfo;
2193 
2194             if (UserInfo1053->usri1053_home_dir_drive != NULL)
2195             {
2196                 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
2197                                      UserInfo1053->usri1053_home_dir_drive);
2198                 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
2199             }
2200             break;
2201     }
2202 
2203     if (ApiStatus != NERR_Success)
2204         goto done;
2205 
2206     Status = SamSetInformationUser(UserHandle,
2207                                    UserAllInformation,
2208                                    &UserAllInfo);
2209     if (!NT_SUCCESS(Status))
2210     {
2211         ERR("SamSetInformationUser failed (Status %08lx)\n", Status);
2212         ApiStatus = NetpNtStatusToApiStatus(Status);
2213         goto done;
2214     }
2215 
2216 done:
2217     if (Dacl != NULL)
2218         HeapFree(GetProcessHeap(), 0, Dacl);
2219 
2220     return ApiStatus;
2221 }
2222 
2223 
2224 static
2225 NET_API_STATUS
2226 OpenUserByName(SAM_HANDLE DomainHandle,
2227                PUNICODE_STRING UserName,
2228                ULONG DesiredAccess,
2229                PSAM_HANDLE UserHandle)
2230 {
2231     PULONG RelativeIds = NULL;
2232     PSID_NAME_USE Use = NULL;
2233     NET_API_STATUS ApiStatus = NERR_Success;
2234     NTSTATUS Status = STATUS_SUCCESS;
2235 
2236     /* Get the RID for the given user name */
2237     Status = SamLookupNamesInDomain(DomainHandle,
2238                                     1,
2239                                     UserName,
2240                                     &RelativeIds,
2241                                     &Use);
2242     if (!NT_SUCCESS(Status))
2243     {
2244         ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
2245         return NetpNtStatusToApiStatus(Status);
2246     }
2247 
2248     /* Fail, if it is not an alias account */
2249     if (Use[0] != SidTypeUser)
2250     {
2251         ERR("Object is not a user!\n");
2252         ApiStatus = NERR_GroupNotFound;
2253         goto done;
2254     }
2255 
2256     /* Open the alias account */
2257     Status = SamOpenUser(DomainHandle,
2258                          DesiredAccess,
2259                          RelativeIds[0],
2260                          UserHandle);
2261     if (!NT_SUCCESS(Status))
2262     {
2263         ERR("SamOpenUser failed (Status %08lx)\n", Status);
2264         ApiStatus = NetpNtStatusToApiStatus(Status);
2265         goto done;
2266     }
2267 
2268 done:
2269     if (RelativeIds != NULL)
2270         SamFreeMemory(RelativeIds);
2271 
2272     if (Use != NULL)
2273         SamFreeMemory(Use);
2274 
2275     return ApiStatus;
2276 }
2277 
2278 
2279 /************************************************************
2280  * NetUserAdd (NETAPI32.@)
2281  */
2282 NET_API_STATUS
2283 WINAPI
2284 NetUserAdd(LPCWSTR servername,
2285            DWORD level,
2286            LPBYTE bufptr,
2287            LPDWORD parm_err)
2288 {
2289     UNICODE_STRING ServerName;
2290     UNICODE_STRING UserName;
2291     SAM_HANDLE ServerHandle = NULL;
2292     SAM_HANDLE DomainHandle = NULL;
2293     SAM_HANDLE UserHandle = NULL;
2294     ULONG GrantedAccess;
2295     ULONG RelativeId;
2296     NET_API_STATUS ApiStatus = NERR_Success;
2297     NTSTATUS Status = STATUS_SUCCESS;
2298 
2299     TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr, parm_err);
2300 
2301     if (parm_err != NULL)
2302         *parm_err = PARM_ERROR_NONE;
2303 
2304     /* Check the info level */
2305     switch (level)
2306     {
2307         case 1:
2308         case 2:
2309         case 3:
2310         case 4:
2311             break;
2312 
2313         default:
2314             return ERROR_INVALID_LEVEL;
2315     }
2316 
2317     if (servername != NULL)
2318         RtlInitUnicodeString(&ServerName, servername);
2319 
2320     /* Connect to the SAM Server */
2321     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2322                         &ServerHandle,
2323                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2324                         NULL);
2325     if (!NT_SUCCESS(Status))
2326     {
2327         ERR("SamConnect failed (Status %08lx)\n", Status);
2328         ApiStatus = NetpNtStatusToApiStatus(Status);
2329         goto done;
2330     }
2331 
2332     /* Open the Account Domain */
2333     Status = OpenAccountDomain(ServerHandle,
2334                                (servername != NULL) ? &ServerName : NULL,
2335                                DOMAIN_CREATE_USER | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
2336                                &DomainHandle);
2337     if (!NT_SUCCESS(Status))
2338     {
2339         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2340         ApiStatus = NetpNtStatusToApiStatus(Status);
2341         goto done;
2342     }
2343 
2344     /* Initialize the user name string */
2345     RtlInitUnicodeString(&UserName,
2346                          ((PUSER_INFO_1)bufptr)->usri1_name);
2347 
2348     /* Create the user account */
2349     Status = SamCreateUser2InDomain(DomainHandle,
2350                                     &UserName,
2351                                     USER_NORMAL_ACCOUNT,
2352                                     USER_ALL_ACCESS | DELETE | WRITE_DAC,
2353                                     &UserHandle,
2354                                     &GrantedAccess,
2355                                     &RelativeId);
2356     if (!NT_SUCCESS(Status))
2357     {
2358         ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status);
2359         ApiStatus = NetpNtStatusToApiStatus(Status);
2360         goto done;
2361     }
2362 
2363     /* Set user information */
2364     ApiStatus = SetUserInfo(UserHandle,
2365                             bufptr,
2366                             level,
2367                             parm_err);
2368     if (ApiStatus != NERR_Success)
2369     {
2370         ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
2371         goto done;
2372     }
2373 
2374 done:
2375     if (UserHandle != NULL)
2376     {
2377         if (ApiStatus != NERR_Success)
2378             SamDeleteUser(UserHandle);
2379         else
2380             SamCloseHandle(UserHandle);
2381     }
2382 
2383     if (DomainHandle != NULL)
2384         SamCloseHandle(DomainHandle);
2385 
2386     if (ServerHandle != NULL)
2387         SamCloseHandle(ServerHandle);
2388 
2389     return ApiStatus;
2390 }
2391 
2392 
2393 /******************************************************************************
2394  *                NetUserChangePassword  (NETAPI32.@)
2395  * PARAMS
2396  *  domainname  [I] Optional. Domain on which the user resides or the logon
2397  *                  domain of the current user if NULL.
2398  *  username    [I] Optional. Username to change the password for or the name
2399  *                  of the current user if NULL.
2400  *  oldpassword [I] The user's current password.
2401  *  newpassword [I] The password that the user will be changed to using.
2402  *
2403  * RETURNS
2404  *  Success: NERR_Success.
2405  *  Failure: NERR_* failure code or win error code.
2406  *
2407  */
2408 NET_API_STATUS
2409 WINAPI
2410 NetUserChangePassword(LPCWSTR domainname,
2411                       LPCWSTR username,
2412                       LPCWSTR oldpassword,
2413                       LPCWSTR newpassword)
2414 {
2415     PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
2416     PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
2417     ULONG RequestBufferSize;
2418     ULONG ResponseBufferSize = 0;
2419     LPWSTR Ptr;
2420     ANSI_STRING PackageName;
2421     ULONG AuthenticationPackage = 0;
2422     HANDLE LsaHandle = NULL;
2423     NET_API_STATUS ApiStatus = NERR_Success;
2424     NTSTATUS Status = STATUS_SUCCESS;
2425     NTSTATUS ProtocolStatus;
2426 
2427     TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2428 
2429     /* FIXME: handle null domain or user name */
2430 
2431     /* Check the parameters */
2432     if ((oldpassword == NULL) ||
2433         (newpassword == NULL))
2434         return ERROR_INVALID_PARAMETER;
2435 
2436     /* Connect to the LSA server */
2437     Status = LsaConnectUntrusted(&LsaHandle);
2438     if (!NT_SUCCESS(Status))
2439         return NetpNtStatusToApiStatus(Status);
2440 
2441     /* Get the authentication package ID */
2442     RtlInitAnsiString(&PackageName,
2443                       MSV1_0_PACKAGE_NAME);
2444 
2445     Status = LsaLookupAuthenticationPackage(LsaHandle,
2446                                             &PackageName,
2447                                             &AuthenticationPackage);
2448     if (!NT_SUCCESS(Status))
2449     {
2450         ApiStatus = NetpNtStatusToApiStatus(Status);
2451         goto done;
2452     }
2453 
2454     /* Calculate the request buffer size */
2455     RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
2456                         ((wcslen(domainname) + 1) * sizeof(WCHAR)) +
2457                         ((wcslen(username) + 1) * sizeof(WCHAR)) +
2458                         ((wcslen(oldpassword) + 1) * sizeof(WCHAR)) +
2459                         ((wcslen(newpassword) + 1) * sizeof(WCHAR));
2460 
2461     /* Allocate the request buffer */
2462     ApiStatus = NetApiBufferAllocate(RequestBufferSize,
2463                                      (PVOID*)&RequestBuffer);
2464     if (ApiStatus != NERR_Success)
2465         goto done;
2466 
2467     /* Initialize the request buffer */
2468     RequestBuffer->MessageType = MsV1_0ChangePassword;
2469     RequestBuffer->Impersonating = TRUE;
2470 
2471     Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
2472 
2473     /* Pack the domain name */
2474     RequestBuffer->DomainName.Length = wcslen(domainname) * sizeof(WCHAR);
2475     RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
2476     RequestBuffer->DomainName.Buffer = Ptr;
2477 
2478     RtlCopyMemory(RequestBuffer->DomainName.Buffer,
2479                   domainname,
2480                   RequestBuffer->DomainName.MaximumLength);
2481 
2482     Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
2483 
2484     /* Pack the user name */
2485     RequestBuffer->AccountName.Length = wcslen(username) * sizeof(WCHAR);
2486     RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
2487     RequestBuffer->AccountName.Buffer = Ptr;
2488 
2489     RtlCopyMemory(RequestBuffer->AccountName.Buffer,
2490                   username,
2491                   RequestBuffer->AccountName.MaximumLength);
2492 
2493     Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
2494 
2495     /* Pack the old password */
2496     RequestBuffer->OldPassword.Length = wcslen(oldpassword) * sizeof(WCHAR);
2497     RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
2498     RequestBuffer->OldPassword.Buffer = Ptr;
2499 
2500     RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
2501                   oldpassword,
2502                   RequestBuffer->OldPassword.MaximumLength);
2503 
2504     Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
2505 
2506     /* Pack the new password */
2507     RequestBuffer->NewPassword.Length = wcslen(newpassword) * sizeof(WCHAR);
2508     RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
2509     RequestBuffer->NewPassword.Buffer = Ptr;
2510 
2511     RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
2512                   newpassword,
2513                   RequestBuffer->NewPassword.MaximumLength);
2514 
2515     /* Call the authentication package */
2516     Status = LsaCallAuthenticationPackage(LsaHandle,
2517                                           AuthenticationPackage,
2518                                           RequestBuffer,
2519                                           RequestBufferSize,
2520                                           (PVOID*)&ResponseBuffer,
2521                                           &ResponseBufferSize,
2522                                           &ProtocolStatus);
2523     if (!NT_SUCCESS(Status))
2524     {
2525         ApiStatus = NetpNtStatusToApiStatus(Status);
2526         goto done;
2527     }
2528 
2529     if (!NT_SUCCESS(ProtocolStatus))
2530     {
2531         ApiStatus = NetpNtStatusToApiStatus(ProtocolStatus);
2532         goto done;
2533     }
2534 
2535 done:
2536     if (RequestBuffer != NULL)
2537         NetApiBufferFree(RequestBuffer);
2538 
2539     if (ResponseBuffer != NULL)
2540         LsaFreeReturnBuffer(ResponseBuffer);
2541 
2542     if (LsaHandle != NULL)
2543         NtClose(LsaHandle);
2544 
2545     return ApiStatus;
2546 }
2547 
2548 
2549 /************************************************************
2550  * NetUserDel  (NETAPI32.@)
2551  */
2552 NET_API_STATUS
2553 WINAPI
2554 NetUserDel(LPCWSTR servername,
2555            LPCWSTR username)
2556 {
2557     UNICODE_STRING ServerName;
2558     UNICODE_STRING UserName;
2559     SAM_HANDLE ServerHandle = NULL;
2560     SAM_HANDLE DomainHandle = NULL;
2561     SAM_HANDLE UserHandle = NULL;
2562     NET_API_STATUS ApiStatus = NERR_Success;
2563     NTSTATUS Status = STATUS_SUCCESS;
2564 
2565     TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
2566 
2567     if (servername != NULL)
2568         RtlInitUnicodeString(&ServerName, servername);
2569 
2570     RtlInitUnicodeString(&UserName, username);
2571 
2572     /* Connect to the SAM Server */
2573     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2574                         &ServerHandle,
2575                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2576                         NULL);
2577     if (!NT_SUCCESS(Status))
2578     {
2579         ERR("SamConnect failed (Status %08lx)\n", Status);
2580         ApiStatus = NetpNtStatusToApiStatus(Status);
2581         goto done;
2582     }
2583 
2584     /* Open the Builtin Domain */
2585     Status = OpenBuiltinDomain(ServerHandle,
2586                                DOMAIN_LOOKUP,
2587                                &DomainHandle);
2588     if (!NT_SUCCESS(Status))
2589     {
2590         ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2591         ApiStatus = NetpNtStatusToApiStatus(Status);
2592         goto done;
2593     }
2594 
2595     /* Open the user account in the builtin domain */
2596     ApiStatus = OpenUserByName(DomainHandle,
2597                                &UserName,
2598                                DELETE,
2599                                &UserHandle);
2600     if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
2601     {
2602         TRACE("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2603         goto done;
2604     }
2605 
2606     if (UserHandle == NULL)
2607     {
2608         if (DomainHandle != NULL)
2609         {
2610             SamCloseHandle(DomainHandle);
2611             DomainHandle = NULL;
2612         }
2613 
2614         /* Open the Acount Domain */
2615         Status = OpenAccountDomain(ServerHandle,
2616                                    (servername != NULL) ? &ServerName : NULL,
2617                                    DOMAIN_LOOKUP,
2618                                    &DomainHandle);
2619         if (!NT_SUCCESS(Status))
2620         {
2621             ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2622             ApiStatus = NetpNtStatusToApiStatus(Status);
2623             goto done;
2624         }
2625 
2626         /* Open the user account in the account domain */
2627         ApiStatus = OpenUserByName(DomainHandle,
2628                                    &UserName,
2629                                    DELETE,
2630                                    &UserHandle);
2631         if (ApiStatus != NERR_Success)
2632         {
2633             ERR("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2634             if (ApiStatus == ERROR_NONE_MAPPED)
2635                 ApiStatus = NERR_UserNotFound;
2636             goto done;
2637         }
2638     }
2639 
2640     /* Delete the user */
2641     Status = SamDeleteUser(UserHandle);
2642     if (!NT_SUCCESS(Status))
2643     {
2644         ERR("SamDeleteUser failed (Status %08lx)\n", Status);
2645         ApiStatus = NetpNtStatusToApiStatus(Status);
2646         goto done;
2647     }
2648 
2649     /* A successful delete invalidates the handle */
2650     UserHandle = NULL;
2651 
2652 done:
2653     if (UserHandle != NULL)
2654         SamCloseHandle(UserHandle);
2655 
2656     if (DomainHandle != NULL)
2657         SamCloseHandle(DomainHandle);
2658 
2659     if (ServerHandle != NULL)
2660         SamCloseHandle(ServerHandle);
2661 
2662     return ApiStatus;
2663 }
2664 
2665 
2666 /************************************************************
2667  * NetUserEnum  (NETAPI32.@)
2668  */
2669 NET_API_STATUS
2670 WINAPI
2671 NetUserEnum(LPCWSTR servername,
2672             DWORD level,
2673             DWORD filter,
2674             LPBYTE* bufptr,
2675             DWORD prefmaxlen,
2676             LPDWORD entriesread,
2677             LPDWORD totalentries,
2678             LPDWORD resume_handle)
2679 {
2680     UNICODE_STRING ServerName;
2681     PSAM_RID_ENUMERATION CurrentUser;
2682     PENUM_CONTEXT EnumContext = NULL;
2683     LPVOID Buffer = NULL;
2684     ULONG i;
2685     SAM_HANDLE UserHandle = NULL;
2686     ACCESS_MASK DesiredAccess;
2687     NET_API_STATUS ApiStatus = NERR_Success;
2688     NTSTATUS Status = STATUS_SUCCESS;
2689 
2690     TRACE("(%s %d 0x%d %p %d %p %p %p)\n", debugstr_w(servername), level,
2691           filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2692 
2693     *entriesread = 0;
2694     *totalentries = 0;
2695     *bufptr = NULL;
2696 
2697     if (servername != NULL)
2698         RtlInitUnicodeString(&ServerName, servername);
2699 
2700     if (resume_handle != NULL && *resume_handle != 0)
2701     {
2702         EnumContext = (PENUM_CONTEXT)*resume_handle;
2703     }
2704     else
2705     {
2706         ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
2707         if (ApiStatus != NERR_Success)
2708             goto done;
2709 
2710         EnumContext->EnumerationContext = 0;
2711         EnumContext->Buffer = NULL;
2712         EnumContext->Count = 0;
2713         EnumContext->Index = 0;
2714         EnumContext->BuiltinDone = FALSE;
2715 
2716         Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2717                             &EnumContext->ServerHandle,
2718                             SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2719                             NULL);
2720         if (!NT_SUCCESS(Status))
2721         {
2722             ERR("SamConnect failed (Status %08lx)\n", Status);
2723             ApiStatus = NetpNtStatusToApiStatus(Status);
2724             goto done;
2725         }
2726 
2727         /* Get the Account Domain SID */
2728         Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2729                                      &EnumContext->AccountDomainSid);
2730         if (!NT_SUCCESS(Status))
2731         {
2732             ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2733             ApiStatus = NetpNtStatusToApiStatus(Status);
2734             goto done;
2735         }
2736 
2737         /* Open the Account Domain */
2738         Status = SamOpenDomain(EnumContext->ServerHandle,
2739                                DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2740                                EnumContext->AccountDomainSid,
2741                                &EnumContext->AccountDomainHandle);
2742         if (!NT_SUCCESS(Status))
2743         {
2744             ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2745             ApiStatus = NetpNtStatusToApiStatus(Status);
2746             goto done;
2747         }
2748 
2749         /* Get the Builtin Domain SID */
2750         Status = GetBuiltinDomainSid(&EnumContext->BuiltinDomainSid);
2751         if (!NT_SUCCESS(Status))
2752         {
2753             ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
2754             ApiStatus = NetpNtStatusToApiStatus(Status);
2755             goto done;
2756         }
2757 
2758         DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
2759         if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
2760             DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
2761 
2762         /* Open the Builtin Domain */
2763         Status = SamOpenDomain(EnumContext->ServerHandle,
2764                                DesiredAccess,
2765                                EnumContext->BuiltinDomainSid,
2766                                &EnumContext->BuiltinDomainHandle);
2767         if (!NT_SUCCESS(Status))
2768         {
2769             ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2770             ApiStatus = NetpNtStatusToApiStatus(Status);
2771             goto done;
2772         }
2773     }
2774 
2775 //    while (TRUE)
2776 //    {
2777         TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
2778         TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2779 
2780         if (EnumContext->Index >= EnumContext->Count)
2781         {
2782 //            if (EnumContext->BuiltinDone != FALSE)
2783 //            {
2784 //                ApiStatus = NERR_Success;
2785 //                goto done;
2786 //            }
2787 
2788             TRACE("Calling SamEnumerateUsersInDomain\n");
2789             Status = SamEnumerateUsersInDomain(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2790                                                &EnumContext->EnumerationContext,
2791                                                0,
2792                                                (PVOID *)&EnumContext->Buffer,
2793                                                prefmaxlen,
2794                                                &EnumContext->Count);
2795 
2796             TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
2797             if (!NT_SUCCESS(Status))
2798             {
2799                 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status);
2800                 ApiStatus = NetpNtStatusToApiStatus(Status);
2801                 goto done;
2802             }
2803 
2804             if (Status == STATUS_MORE_ENTRIES)
2805             {
2806                 ApiStatus = NERR_BufTooSmall;
2807                 goto done;
2808             }
2809             else
2810             {
2811                 EnumContext->BuiltinDone = TRUE;
2812             }
2813         }
2814 
2815         TRACE("EnumContext: %lu\n", EnumContext);
2816         TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2817         TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
2818 
2819         /* Get a pointer to the current user */
2820         CurrentUser = &EnumContext->Buffer[EnumContext->Index];
2821 
2822         TRACE("RID: %lu\n", CurrentUser->RelativeId);
2823 
2824         DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT;
2825         if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
2826             DesiredAccess |= USER_LIST_GROUPS;
2827 
2828         Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2829                              DesiredAccess,
2830                              CurrentUser->RelativeId,
2831                              &UserHandle);
2832         if (!NT_SUCCESS(Status))
2833         {
2834             ERR("SamOpenUser failed (Status %08lx)\n", Status);
2835             ApiStatus = NetpNtStatusToApiStatus(Status);
2836             goto done;
2837         }
2838 
2839         ApiStatus = BuildUserInfoBuffer(EnumContext->BuiltinDomainHandle,
2840                                         UserHandle,
2841                                         EnumContext->AccountDomainSid,
2842                                         CurrentUser->RelativeId,
2843                                         level,
2844                                         &Buffer);
2845         if (ApiStatus != NERR_Success)
2846         {
2847             ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus);
2848             goto done;
2849         }
2850 
2851         SamCloseHandle(UserHandle);
2852         UserHandle = NULL;
2853 
2854         EnumContext->Index++;
2855 
2856         (*entriesread)++;
2857 //    }
2858 
2859 done:
2860     if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Index < EnumContext->Count)
2861         ApiStatus = ERROR_MORE_DATA;
2862 
2863     if (EnumContext != NULL)
2864         *totalentries = EnumContext->Count;
2865 
2866     if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
2867     {
2868         if (EnumContext != NULL)
2869         {
2870             if (EnumContext->BuiltinDomainHandle != NULL)
2871                 SamCloseHandle(EnumContext->BuiltinDomainHandle);
2872 
2873             if (EnumContext->AccountDomainHandle != NULL)
2874                 SamCloseHandle(EnumContext->AccountDomainHandle);
2875 
2876             if (EnumContext->BuiltinDomainSid != NULL)
2877                 RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->BuiltinDomainSid);
2878 
2879             if (EnumContext->AccountDomainSid != NULL)
2880                 RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->AccountDomainSid);
2881 
2882             if (EnumContext->ServerHandle != NULL)
2883                 SamCloseHandle(EnumContext->ServerHandle);
2884 
2885             if (EnumContext->Buffer != NULL)
2886             {
2887                 for (i = 0; i < EnumContext->Count; i++)
2888                 {
2889                     SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
2890                 }
2891 
2892                 SamFreeMemory(EnumContext->Buffer);
2893             }
2894 
2895             NetApiBufferFree(EnumContext);
2896             EnumContext = NULL;
2897         }
2898     }
2899 
2900     if (UserHandle != NULL)
2901         SamCloseHandle(UserHandle);
2902 
2903     if (resume_handle != NULL)
2904         *resume_handle = (DWORD_PTR)EnumContext;
2905 
2906     *bufptr = (LPBYTE)Buffer;
2907 
2908     TRACE("return %lu\n", ApiStatus);
2909 
2910     return ApiStatus;
2911 }
2912 
2913 
2914 /************************************************************
2915  * NetUserGetGroups (NETAPI32.@)
2916  */
2917 NET_API_STATUS
2918 WINAPI
2919 NetUserGetGroups(LPCWSTR servername,
2920                  LPCWSTR username,
2921                  DWORD level,
2922                  LPBYTE *bufptr,
2923                  DWORD prefixmaxlen,
2924                  LPDWORD entriesread,
2925                  LPDWORD totalentries)
2926 {
2927     UNICODE_STRING ServerName;
2928     UNICODE_STRING UserName;
2929     SAM_HANDLE ServerHandle = NULL;
2930     SAM_HANDLE AccountDomainHandle = NULL;
2931     SAM_HANDLE UserHandle = NULL;
2932     PSID AccountDomainSid = NULL;
2933     PULONG RelativeIds = NULL;
2934     PSID_NAME_USE Use = NULL;
2935     PGROUP_MEMBERSHIP GroupMembership = NULL;
2936     ULONG GroupCount;
2937 
2938     NET_API_STATUS ApiStatus = NERR_Success;
2939     NTSTATUS Status = STATUS_SUCCESS;
2940 
2941     TRACE("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
2942           debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
2943           totalentries);
2944 
2945     if (servername != NULL)
2946         RtlInitUnicodeString(&ServerName, servername);
2947 
2948     RtlInitUnicodeString(&UserName, username);
2949 
2950     /* Connect to the SAM Server */
2951     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2952                         &ServerHandle,
2953                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2954                         NULL);
2955     if (!NT_SUCCESS(Status))
2956     {
2957         ERR("SamConnect failed (Status %08lx)\n", Status);
2958         ApiStatus = NetpNtStatusToApiStatus(Status);
2959         goto done;
2960     }
2961 
2962     /* Get the Account Domain SID */
2963     Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2964                                  &AccountDomainSid);
2965     if (!NT_SUCCESS(Status))
2966     {
2967         ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2968         ApiStatus = NetpNtStatusToApiStatus(Status);
2969         goto done;
2970     }
2971 
2972     /* Open the Account Domain */
2973     Status = SamOpenDomain(ServerHandle,
2974                            DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2975                            AccountDomainSid,
2976                            &AccountDomainHandle);
2977     if (!NT_SUCCESS(Status))
2978     {
2979         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2980         ApiStatus = NetpNtStatusToApiStatus(Status);
2981         goto done;
2982     }
2983 
2984     /* Get the RID for the given user name */
2985     Status = SamLookupNamesInDomain(AccountDomainHandle,
2986                                     1,
2987                                     &UserName,
2988                                     &RelativeIds,
2989                                     &Use);
2990     if (!NT_SUCCESS(Status))
2991     {
2992         ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
2993         if (Status == STATUS_NONE_MAPPED)
2994             ApiStatus = NERR_UserNotFound;
2995         else
2996             ApiStatus = NetpNtStatusToApiStatus(Status);
2997         goto done;
2998     }
2999 
3000     /* Fail, if it is not a user account */
3001     if (Use[0] != SidTypeUser)
3002     {
3003         ERR("Account is not a User!\n");
3004         ApiStatus = NERR_UserNotFound;
3005         goto done;
3006     }
3007 
3008     /* Open the user object */
3009     Status = SamOpenUser(AccountDomainHandle,
3010                          USER_LIST_GROUPS,
3011                          RelativeIds[0],
3012                          &UserHandle);
3013     if (!NT_SUCCESS(Status))
3014     {
3015         ERR("SamOpenUser failed (Status %08lx)\n", Status);
3016         ApiStatus = NetpNtStatusToApiStatus(Status);
3017         goto done;
3018     }
3019 
3020     /* Get the group memberships of this user */
3021     Status = SamGetGroupsForUser(UserHandle,
3022                                  &GroupMembership,
3023                                  &GroupCount);
3024     if (!NT_SUCCESS(Status))
3025     {
3026         ERR("SamGetGroupsForUser failed (Status %08lx)\n", Status);
3027         ApiStatus = NetpNtStatusToApiStatus(Status);
3028         goto done;
3029     }
3030 
3031     /* If there is no group membership, we're done */
3032     if (GroupCount == 0)
3033     {
3034         ApiStatus = NERR_Success;
3035         goto done;
3036     }
3037 
3038 
3039 done:
3040 
3041     if (GroupMembership != NULL)
3042         SamFreeMemory(GroupMembership);
3043 
3044     if (UserHandle != NULL)
3045         SamCloseHandle(UserHandle);
3046 
3047     if (RelativeIds != NULL)
3048         SamFreeMemory(RelativeIds);
3049 
3050     if (Use != NULL)
3051         SamFreeMemory(Use);
3052 
3053     if (AccountDomainSid != NULL)
3054         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3055 
3056     if (AccountDomainHandle != NULL)
3057         SamCloseHandle(AccountDomainHandle);
3058 
3059     if (ServerHandle != NULL)
3060         SamCloseHandle(ServerHandle);
3061 
3062     if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3063     {
3064         *entriesread = 0;
3065         *totalentries = 0;
3066     }
3067     else
3068     {
3069 //        *entriesread = Count;
3070 //        *totalentries = Count;
3071     }
3072 
3073 //    *bufptr = (LPBYTE)Buffer;
3074 
3075     return ApiStatus;
3076 }
3077 
3078 
3079 /************************************************************
3080  * NetUserGetInfo  (NETAPI32.@)
3081  */
3082 NET_API_STATUS
3083 WINAPI
3084 NetUserGetInfo(LPCWSTR servername,
3085                LPCWSTR username,
3086                DWORD level,
3087                LPBYTE* bufptr)
3088 {
3089     UNICODE_STRING ServerName;
3090     UNICODE_STRING UserName;
3091     SAM_HANDLE ServerHandle = NULL;
3092     SAM_HANDLE AccountDomainHandle = NULL;
3093     SAM_HANDLE BuiltinDomainHandle = NULL;
3094     SAM_HANDLE UserHandle = NULL;
3095     PULONG RelativeIds = NULL;
3096     PSID_NAME_USE Use = NULL;
3097     LPVOID Buffer = NULL;
3098     PSID AccountDomainSid = NULL;
3099     PSID BuiltinDomainSid = NULL;
3100     ACCESS_MASK DesiredAccess;
3101     NET_API_STATUS ApiStatus = NERR_Success;
3102     NTSTATUS Status = STATUS_SUCCESS;
3103 
3104     TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername),
3105           debugstr_w(username), level, bufptr);
3106 
3107     if (servername != NULL)
3108         RtlInitUnicodeString(&ServerName, servername);
3109 
3110     RtlInitUnicodeString(&UserName, username);
3111 
3112     /* Connect to the SAM Server */
3113     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3114                         &ServerHandle,
3115                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3116                         NULL);
3117     if (!NT_SUCCESS(Status))
3118     {
3119         ERR("SamConnect failed (Status %08lx)\n", Status);
3120         ApiStatus = NetpNtStatusToApiStatus(Status);
3121         goto done;
3122     }
3123 
3124     /* Get the Builtin Domain SID */
3125     Status = GetBuiltinDomainSid(&BuiltinDomainSid);
3126     if (!NT_SUCCESS(Status))
3127     {
3128         ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
3129         ApiStatus = NetpNtStatusToApiStatus(Status);
3130         goto done;
3131     }
3132 
3133     DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
3134     if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
3135         DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
3136 
3137     /* Open the Builtin Domain */
3138     Status = SamOpenDomain(ServerHandle,
3139                            DesiredAccess,
3140                            BuiltinDomainSid,
3141                            &BuiltinDomainHandle);
3142     if (!NT_SUCCESS(Status))
3143     {
3144         ERR("SamOpenDomain failed (Status %08lx)\n", Status);
3145         ApiStatus = NetpNtStatusToApiStatus(Status);
3146         goto done;
3147     }
3148 
3149     /* Get the Account Domain SID */
3150     Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3151                                  &AccountDomainSid);
3152     if (!NT_SUCCESS(Status))
3153     {
3154         ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3155         ApiStatus = NetpNtStatusToApiStatus(Status);
3156         goto done;
3157     }
3158 
3159     /* Open the Account Domain */
3160     Status = SamOpenDomain(ServerHandle,
3161                            DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
3162                            AccountDomainSid,
3163                            &AccountDomainHandle);
3164     if (!NT_SUCCESS(Status))
3165     {
3166         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3167         ApiStatus = NetpNtStatusToApiStatus(Status);
3168         goto done;
3169     }
3170 
3171     /* Get the RID for the given user name */
3172     Status = SamLookupNamesInDomain(AccountDomainHandle,
3173                                     1,
3174                                     &UserName,
3175                                     &RelativeIds,
3176                                     &Use);
3177     if (!NT_SUCCESS(Status))
3178     {
3179         ERR("SamOpenDomain failed (Status %08lx)\n", Status);
3180         if (Status == STATUS_NONE_MAPPED)
3181             ApiStatus = NERR_UserNotFound;
3182         else
3183             ApiStatus = NetpNtStatusToApiStatus(Status);
3184         goto done;
3185     }
3186 
3187     /* Check if the account is a user account */
3188     if (Use[0] != SidTypeUser)
3189     {
3190         ERR("No user found!\n");
3191         ApiStatus = NERR_UserNotFound;
3192         goto done;
3193     }
3194 
3195     TRACE("RID: %lu\n", RelativeIds[0]);
3196 
3197     DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT;
3198     if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
3199         DesiredAccess |= USER_LIST_GROUPS;
3200 
3201     /* Open the user object */
3202     Status = SamOpenUser(AccountDomainHandle,
3203                          DesiredAccess,
3204                          RelativeIds[0],
3205                          &UserHandle);
3206     if (!NT_SUCCESS(Status))
3207     {
3208         ERR("SamOpenUser failed (Status %08lx)\n", Status);
3209         ApiStatus = NetpNtStatusToApiStatus(Status);
3210         goto done;
3211     }
3212 
3213     ApiStatus = BuildUserInfoBuffer(BuiltinDomainHandle,
3214                                     UserHandle,
3215                                     AccountDomainSid,
3216                                     RelativeIds[0],
3217                                     level,
3218                                     &Buffer);
3219     if (ApiStatus != NERR_Success)
3220     {
3221         ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus);
3222         goto done;
3223     }
3224 
3225 done:
3226     if (UserHandle != NULL)
3227         SamCloseHandle(UserHandle);
3228 
3229     if (RelativeIds != NULL)
3230         SamFreeMemory(RelativeIds);
3231 
3232     if (Use != NULL)
3233         SamFreeMemory(Use);
3234 
3235     if (AccountDomainHandle != NULL)
3236         SamCloseHandle(AccountDomainHandle);
3237 
3238     if (AccountDomainSid != NULL)
3239         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3240 
3241     if (BuiltinDomainHandle != NULL)
3242         SamCloseHandle(BuiltinDomainHandle);
3243 
3244     if (BuiltinDomainSid != NULL)
3245         RtlFreeHeap(RtlGetProcessHeap(), 0, BuiltinDomainSid);
3246 
3247     if (ServerHandle != NULL)
3248         SamCloseHandle(ServerHandle);
3249 
3250     *bufptr = (LPBYTE)Buffer;
3251 
3252     return ApiStatus;
3253 }
3254 
3255 
3256 /************************************************************
3257  * NetUserGetLocalGroups  (NETAPI32.@)
3258  */
3259 NET_API_STATUS
3260 WINAPI
3261 NetUserGetLocalGroups(LPCWSTR servername,
3262                       LPCWSTR username,
3263                       DWORD level,
3264                       DWORD flags,
3265                       LPBYTE* bufptr,
3266                       DWORD prefmaxlen,
3267                       LPDWORD entriesread,
3268                       LPDWORD totalentries)
3269 {
3270     UNICODE_STRING ServerName;
3271     UNICODE_STRING UserName;
3272     SAM_HANDLE ServerHandle = NULL;
3273     SAM_HANDLE BuiltinDomainHandle = NULL;
3274     SAM_HANDLE AccountDomainHandle = NULL;
3275     PSID AccountDomainSid = NULL;
3276     PSID UserSid = NULL;
3277     PULONG RelativeIds = NULL;
3278     PSID_NAME_USE Use = NULL;
3279     ULONG BuiltinMemberCount = 0;
3280     ULONG AccountMemberCount = 0;
3281     PULONG BuiltinAliases = NULL;
3282     PULONG AccountAliases = NULL;
3283     PUNICODE_STRING BuiltinNames = NULL;
3284     PUNICODE_STRING AccountNames = NULL;
3285     PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
3286     ULONG Size;
3287     ULONG Count = 0;
3288     ULONG Index;
3289     ULONG i;
3290     LPWSTR StrPtr;
3291     NET_API_STATUS ApiStatus = NERR_Success;
3292     NTSTATUS Status = STATUS_SUCCESS;
3293 
3294     TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
3295           debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
3296           prefmaxlen, entriesread, totalentries);
3297 
3298     if (level != 0)
3299         return ERROR_INVALID_LEVEL;
3300 
3301     if (flags & ~LG_INCLUDE_INDIRECT)
3302         return ERROR_INVALID_PARAMETER;
3303 
3304     if (flags & LG_INCLUDE_INDIRECT)
3305     {
3306         WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
3307     }
3308 
3309     if (servername != NULL)
3310         RtlInitUnicodeString(&ServerName, servername);
3311 
3312     RtlInitUnicodeString(&UserName, username);
3313 
3314     /* Connect to the SAM Server */
3315     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3316                         &ServerHandle,
3317                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3318                         NULL);
3319     if (!NT_SUCCESS(Status))
3320     {
3321         ERR("SamConnect failed (Status %08lx)\n", Status);
3322         ApiStatus = NetpNtStatusToApiStatus(Status);
3323         goto done;
3324     }
3325 
3326     /* Open the Builtin Domain */
3327     Status = OpenBuiltinDomain(ServerHandle,
3328                                DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
3329                                &BuiltinDomainHandle);
3330     if (!NT_SUCCESS(Status))
3331     {
3332         ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
3333         ApiStatus = NetpNtStatusToApiStatus(Status);
3334         goto done;
3335     }
3336 
3337     /* Get the Account Domain SID */
3338     Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3339                                  &AccountDomainSid);
3340     if (!NT_SUCCESS(Status))
3341     {
3342         ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3343         ApiStatus = NetpNtStatusToApiStatus(Status);
3344         goto done;
3345     }
3346 
3347     /* Open the Account Domain */
3348     Status = SamOpenDomain(ServerHandle,
3349                            DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
3350                            AccountDomainSid,
3351                            &AccountDomainHandle);
3352     if (!NT_SUCCESS(Status))
3353     {
3354         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3355         ApiStatus = NetpNtStatusToApiStatus(Status);
3356         goto done;
3357     }
3358 
3359     /* Get the RID for the given user name */
3360     Status = SamLookupNamesInDomain(AccountDomainHandle,
3361                                     1,
3362                                     &UserName,
3363                                     &RelativeIds,
3364                                     &Use);
3365     if (!NT_SUCCESS(Status))
3366     {
3367         ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
3368         if (Status == STATUS_NONE_MAPPED)
3369             ApiStatus = NERR_UserNotFound;
3370         else
3371             ApiStatus = NetpNtStatusToApiStatus(Status);
3372         goto done;
3373     }
3374 
3375     /* Fail, if it is not a user account */
3376     if (Use[0] != SidTypeUser)
3377     {
3378         ERR("Account is not a User!\n");
3379         ApiStatus = NERR_UserNotFound;
3380         goto done;
3381     }
3382 
3383     /* Build the User SID from the Account Domain SID and the users RID */
3384     ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
3385                                       RelativeIds[0],
3386                                       &UserSid);
3387     if (ApiStatus != NERR_Success)
3388     {
3389         ERR("BuildSidFromSidAndRid failed!\n");
3390         goto done;
3391     }
3392 
3393     /* Get alias memberships in the Builtin Domain */
3394     Status = SamGetAliasMembership(BuiltinDomainHandle,
3395                                    1,
3396                                    &UserSid,
3397                                    &BuiltinMemberCount,
3398                                    &BuiltinAliases);
3399     if (!NT_SUCCESS(Status))
3400     {
3401         ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3402         ApiStatus = NetpNtStatusToApiStatus(Status);
3403         goto done;
3404     }
3405 
3406     if (BuiltinMemberCount > 0)
3407     {
3408         /* Get the Names of the builtin alias members */
3409         Status = SamLookupIdsInDomain(BuiltinDomainHandle,
3410                                       BuiltinMemberCount,
3411                                       BuiltinAliases,
3412                                       &BuiltinNames,
3413                                       NULL);
3414         if (!NT_SUCCESS(Status))
3415         {
3416             ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3417             ApiStatus = NetpNtStatusToApiStatus(Status);
3418             goto done;
3419         }
3420     }
3421 
3422     /* Get alias memberships in the Account Domain */
3423     Status = SamGetAliasMembership(AccountDomainHandle,
3424                                    1,
3425                                    &UserSid,
3426                                    &AccountMemberCount,
3427                                    &AccountAliases);
3428     if (!NT_SUCCESS(Status))
3429     {
3430         ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3431         ApiStatus = NetpNtStatusToApiStatus(Status);
3432         goto done;
3433     }
3434 
3435     if (AccountMemberCount > 0)
3436     {
3437         /* Get the Names of the builtin alias members */
3438         Status = SamLookupIdsInDomain(AccountDomainHandle,
3439                                       AccountMemberCount,
3440                                       AccountAliases,
3441                                       &AccountNames,
3442                                       NULL);
3443         if (!NT_SUCCESS(Status))
3444         {
3445             ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3446             ApiStatus = NetpNtStatusToApiStatus(Status);
3447             goto done;
3448         }
3449     }
3450 
3451     /* Calculate the required buffer size */
3452     Size = 0;
3453 
3454     for (i = 0; i < BuiltinMemberCount; i++)
3455     {
3456         if (BuiltinNames[i].Length > 0)
3457         {
3458             Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3459             Count++;
3460         }
3461     }
3462 
3463     for (i = 0; i < AccountMemberCount; i++)
3464     {
3465         if (AccountNames[i].Length > 0)
3466         {
3467             Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length + sizeof(UNICODE_NULL));
3468             Count++;
3469         }
3470     }
3471 
3472     if (Size == 0)
3473     {
3474         ApiStatus = NERR_Success;
3475         goto done;
3476     }
3477 
3478     /* Allocate buffer */
3479     ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
3480     if (ApiStatus != NERR_Success)
3481         goto done;
3482 
3483     ZeroMemory(Buffer, Size);
3484 
3485     StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
3486 
3487     /* Copy data to the allocated buffer */
3488     Index = 0;
3489     for (i = 0; i < BuiltinMemberCount; i++)
3490     {
3491         if (BuiltinNames[i].Length > 0)
3492         {
3493             CopyMemory(StrPtr,
3494                        BuiltinNames[i].Buffer,
3495                        BuiltinNames[i].Length);
3496             Buffer[Index].lgrui0_name = StrPtr;
3497 
3498             StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3499             Index++;
3500         }
3501     }
3502 
3503     for (i = 0; i < AccountMemberCount; i++)
3504     {
3505         if (AccountNames[i].Length > 0)
3506         {
3507             CopyMemory(StrPtr,
3508                        AccountNames[i].Buffer,
3509                        AccountNames[i].Length);
3510             Buffer[Index].lgrui0_name = StrPtr;
3511 
3512             StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length + sizeof(UNICODE_NULL));
3513             Index++;
3514         }
3515     }
3516 
3517 done:
3518     if (AccountNames != NULL)
3519         SamFreeMemory(AccountNames);
3520 
3521     if (BuiltinNames != NULL)
3522         SamFreeMemory(BuiltinNames);
3523 
3524     if (AccountAliases != NULL)
3525         SamFreeMemory(AccountAliases);
3526 
3527     if (BuiltinAliases != NULL)
3528         SamFreeMemory(BuiltinAliases);
3529 
3530     if (RelativeIds != NULL)
3531         SamFreeMemory(RelativeIds);
3532 
3533     if (Use != NULL)
3534         SamFreeMemory(Use);
3535 
3536     if (UserSid != NULL)
3537         NetApiBufferFree(UserSid);
3538 
3539     if (AccountDomainSid != NULL)
3540         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3541 
3542     if (AccountDomainHandle != NULL)
3543         SamCloseHandle(AccountDomainHandle);
3544 
3545     if (BuiltinDomainHandle != NULL)
3546         SamCloseHandle(BuiltinDomainHandle);
3547 
3548     if (ServerHandle != NULL)
3549         SamCloseHandle(ServerHandle);
3550 
3551     if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3552     {
3553         *entriesread = 0;
3554         *totalentries = 0;
3555     }
3556     else
3557     {
3558         *entriesread = Count;
3559         *totalentries = Count;
3560     }
3561 
3562     *bufptr = (LPBYTE)Buffer;
3563 
3564     return ApiStatus;
3565 }
3566 
3567 
3568 /******************************************************************************
3569  * NetUserModalsGet  (NETAPI32.@)
3570  *
3571  * Retrieves global information for all users and global groups in the security
3572  * database.
3573  *
3574  * PARAMS
3575  *  servername [I] Specifies the DNS or the NetBIOS name of the remote server
3576  *                 on which the function is to execute.
3577  *  level      [I] Information level of the data.
3578  *     0   Return global passwords parameters. bufptr points to a
3579  *         USER_MODALS_INFO_0 struct.
3580  *     1   Return logon server and domain controller information. bufptr
3581  *         points to a USER_MODALS_INFO_1 struct.
3582  *     2   Return domain name and identifier. bufptr points to a
3583  *         USER_MODALS_INFO_2 struct.
3584  *     3   Return lockout information. bufptr points to a USER_MODALS_INFO_3
3585  *         struct.
3586  *  bufptr     [O] Buffer that receives the data.
3587  *
3588  * RETURNS
3589  *  Success: NERR_Success.
3590  *  Failure:
3591  *     ERROR_ACCESS_DENIED - the user does not have access to the info.
3592  *     NERR_InvalidComputer - computer name is invalid.
3593  */
3594 NET_API_STATUS
3595 WINAPI
3596 NetUserModalsGet(LPCWSTR servername,
3597                  DWORD level,
3598                  LPBYTE *bufptr)
3599 {
3600     UNICODE_STRING ServerName;
3601     SAM_HANDLE ServerHandle = NULL;
3602     SAM_HANDLE DomainHandle = NULL;
3603     PSID DomainSid = NULL;
3604     PDOMAIN_PASSWORD_INFORMATION PasswordInfo = NULL;
3605     PDOMAIN_LOGOFF_INFORMATION LogoffInfo = NULL;
3606     PDOMAIN_SERVER_ROLE_INFORMATION ServerRoleInfo = NULL;
3607     PDOMAIN_REPLICATION_INFORMATION ReplicationInfo = NULL;
3608     PDOMAIN_NAME_INFORMATION NameInfo = NULL;
3609     PDOMAIN_LOCKOUT_INFORMATION LockoutInfo = NULL;
3610     ULONG DesiredAccess;
3611     ULONG BufferSize;
3612     PUSER_MODALS_INFO_0 umi0;
3613     PUSER_MODALS_INFO_1 umi1;
3614     PUSER_MODALS_INFO_2 umi2;
3615     PUSER_MODALS_INFO_3 umi3;
3616     NET_API_STATUS ApiStatus = NERR_Success;
3617     NTSTATUS Status = STATUS_SUCCESS;
3618 
3619     TRACE("(%s %d %p)\n", debugstr_w(servername), level, bufptr);
3620 
3621     *bufptr = NULL;
3622 
3623     if (servername != NULL)
3624         RtlInitUnicodeString(&ServerName, servername);
3625 
3626     /* Connect to the SAM Server */
3627     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3628                         &ServerHandle,
3629                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3630                         NULL);
3631     if (!NT_SUCCESS(Status))
3632     {
3633         ERR("SamConnect failed (Status %08lx)\n", Status);
3634         ApiStatus = NetpNtStatusToApiStatus(Status);
3635         goto done;
3636     }
3637 
3638     /* Get the Account Domain SID */
3639     Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3640                                  &DomainSid);
3641     if (!NT_SUCCESS(Status))
3642     {
3643         ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3644         ApiStatus = NetpNtStatusToApiStatus(Status);
3645         goto done;
3646     }
3647 
3648     switch (level)
3649     {
3650         case 0:
3651             DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS | DOMAIN_READ_PASSWORD_PARAMETERS;
3652             break;
3653 
3654         case 1:
3655             DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
3656             break;
3657 
3658         case 2:
3659             DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
3660             break;
3661 
3662         case 3:
3663             DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
3664             break;
3665 
3666         default:
3667             ApiStatus = ERROR_INVALID_LEVEL;
3668             goto done;
3669     }
3670 
3671     /* Open the Account Domain */
3672     Status = SamOpenDomain(ServerHandle,
3673                            DesiredAccess,
3674                            DomainSid,
3675                            &DomainHandle);
3676     if (!NT_SUCCESS(Status))
3677     {
3678         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3679         ApiStatus = NetpNtStatusToApiStatus(Status);
3680         goto done;
3681     }
3682 
3683     switch (level)
3684     {
3685         case 0:
3686             /* return global passwords parameters */
3687             Status = SamQueryInformationDomain(DomainHandle,
3688                                                DomainPasswordInformation,
3689                                                (PVOID*)&PasswordInfo);
3690             if (!NT_SUCCESS(Status))
3691             {
3692                 ApiStatus = NetpNtStatusToApiStatus(Status);
3693                 goto done;
3694             }
3695 
3696             Status = SamQueryInformationDomain(DomainHandle,
3697                                                DomainLogoffInformation,
3698                                                (PVOID*)&LogoffInfo);
3699             if (!NT_SUCCESS(Status))
3700             {
3701                 ApiStatus = NetpNtStatusToApiStatus(Status);
3702                 goto done;
3703             }
3704 
3705             BufferSize = sizeof(USER_MODALS_INFO_0);
3706             break;
3707 
3708         case 1:
3709             /* return logon server and domain controller info */
3710             Status = SamQueryInformationDomain(DomainHandle,
3711                                                DomainServerRoleInformation,
3712                                                (PVOID*)&ServerRoleInfo);
3713             if (!NT_SUCCESS(Status))
3714             {
3715                 ApiStatus = NetpNtStatusToApiStatus(Status);
3716                 goto done;
3717             }
3718 
3719             Status = SamQueryInformationDomain(DomainHandle,
3720                                                DomainReplicationInformation,
3721                                                (PVOID*)&ReplicationInfo);
3722             if (!NT_SUCCESS(Status))
3723             {
3724                 ApiStatus = NetpNtStatusToApiStatus(Status);
3725                 goto done;
3726             }
3727 
3728             BufferSize = sizeof(USER_MODALS_INFO_1) +
3729                          ReplicationInfo->ReplicaSourceNodeName.Length + sizeof(WCHAR);
3730             break;
3731 
3732         case 2:
3733             /* return domain name and identifier */
3734             Status = SamQueryInformationDomain(DomainHandle,
3735                                                DomainNameInformation,
3736                                                (PVOID*)&NameInfo);
3737             if (!NT_SUCCESS(Status))
3738             {
3739                 ApiStatus = NetpNtStatusToApiStatus(Status);
3740                 goto done;
3741             }
3742 
3743             BufferSize = sizeof( USER_MODALS_INFO_2 ) +
3744                          NameInfo->DomainName.Length + sizeof(WCHAR) +
3745                          RtlLengthSid(DomainSid);
3746             break;
3747 
3748         case 3:
3749             /* return lockout information */
3750             Status = SamQueryInformationDomain(DomainHandle,
3751                                                DomainLockoutInformation,
3752                                                (PVOID*)&LockoutInfo);
3753             if (!NT_SUCCESS(Status))
3754             {
3755                 ApiStatus = NetpNtStatusToApiStatus(Status);
3756                 goto done;
3757             }
3758 
3759             BufferSize = sizeof(USER_MODALS_INFO_3);
3760             break;
3761 
3762         default:
3763             TRACE("Invalid level %d is specified\n", level);
3764             ApiStatus = ERROR_INVALID_LEVEL;
3765             goto done;
3766     }
3767 
3768 
3769     ApiStatus = NetApiBufferAllocate(BufferSize,
3770                                      (LPVOID *)bufptr);
3771     if (ApiStatus != NERR_Success)
3772     {
3773         WARN("NetApiBufferAllocate() failed\n");
3774         goto done;
3775     }
3776 
3777     switch (level)
3778     {
3779         case 0:
3780             umi0 = (PUSER_MODALS_INFO_0)*bufptr;
3781 
3782             umi0->usrmod0_min_passwd_len = PasswordInfo->MinPasswordLength;
3783             umi0->usrmod0_max_passwd_age = (ULONG)(-PasswordInfo->MaxPasswordAge.QuadPart / 10000000);
3784             umi0->usrmod0_min_passwd_age =
3785                 DeltaTimeToSeconds(PasswordInfo->MinPasswordAge);
3786             umi0->usrmod0_force_logoff =
3787                 DeltaTimeToSeconds(LogoffInfo->ForceLogoff);
3788             umi0->usrmod0_password_hist_len = PasswordInfo->PasswordHistoryLength;
3789             break;
3790 
3791         case 1:
3792             umi1 = (PUSER_MODALS_INFO_1)*bufptr;
3793 
3794             switch (ServerRoleInfo->DomainServerRole)
3795             {
3796                 case DomainServerRolePrimary:
3797                     umi1->usrmod1_role = UAS_ROLE_PRIMARY;
3798                     break;
3799 
3800                 case DomainServerRoleBackup:
3801                     umi1->usrmod1_role = UAS_ROLE_BACKUP;
3802                     break;
3803 
3804                 default:
3805                     ApiStatus = NERR_InternalError;
3806                     goto done;
3807             }
3808 
3809             umi1->usrmod1_primary = (LPWSTR)(*bufptr + sizeof(USER_MODALS_INFO_1));
3810             RtlCopyMemory(umi1->usrmod1_primary,
3811                           ReplicationInfo->ReplicaSourceNodeName.Buffer,
3812                           ReplicationInfo->ReplicaSourceNodeName.Length);
3813             umi1->usrmod1_primary[ReplicationInfo->ReplicaSourceNodeName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3814             break;
3815 
3816         case 2:
3817             umi2 = (PUSER_MODALS_INFO_2)*bufptr;
3818 
3819             umi2->usrmod2_domain_name = (LPWSTR)(*bufptr + sizeof(USER_MODALS_INFO_2));
3820             RtlCopyMemory(umi2->usrmod2_domain_name,
3821                           NameInfo->DomainName.Buffer,
3822                           NameInfo->DomainName.Length);
3823             umi2->usrmod2_domain_name[NameInfo->DomainName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3824 
3825             umi2->usrmod2_domain_id = *bufptr +
3826                                       sizeof(USER_MODALS_INFO_2) +
3827                                       NameInfo->DomainName.Length + sizeof(WCHAR);
3828             RtlCopyMemory(umi2->usrmod2_domain_id,
3829                           DomainSid,
3830                           RtlLengthSid(DomainSid));
3831             break;
3832 
3833         case 3:
3834             umi3 = (PUSER_MODALS_INFO_3)*bufptr;
3835             umi3->usrmod3_lockout_duration =
3836                 DeltaTimeToSeconds(LockoutInfo->LockoutDuration);
3837             umi3->usrmod3_lockout_observation_window =
3838                 DeltaTimeToSeconds(LockoutInfo->LockoutObservationWindow );
3839             umi3->usrmod3_lockout_threshold = LockoutInfo->LockoutThreshold;
3840             break;
3841     }
3842 
3843 done:
3844     if (LockoutInfo != NULL)
3845         SamFreeMemory(LockoutInfo);
3846 
3847     if (NameInfo != NULL)
3848         SamFreeMemory(NameInfo);
3849 
3850     if (ReplicationInfo != NULL)
3851         SamFreeMemory(ReplicationInfo);
3852 
3853     if (ServerRoleInfo != NULL)
3854         SamFreeMemory(ServerRoleInfo);
3855 
3856     if (LogoffInfo != NULL)
3857         SamFreeMemory(LogoffInfo);
3858 
3859     if (PasswordInfo != NULL)
3860         SamFreeMemory(PasswordInfo);
3861 
3862     if (DomainSid != NULL)
3863         RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
3864 
3865     if (DomainHandle != NULL)
3866         SamCloseHandle(DomainHandle);
3867 
3868     if (ServerHandle != NULL)
3869         SamCloseHandle(ServerHandle);
3870 
3871     return ApiStatus;
3872 }
3873 
3874 
3875 /******************************************************************************
3876  * NetUserModalsSet  (NETAPI32.@)
3877  */
3878 NET_API_STATUS
3879 WINAPI
3880 NetUserModalsSet(IN LPCWSTR servername,
3881                  IN DWORD level,
3882                  IN LPBYTE buf,
3883                  OUT LPDWORD parm_err)
3884 {
3885     FIXME("(%s %d %p %p)\n", debugstr_w(servername), level, buf, parm_err);
3886     return ERROR_ACCESS_DENIED;
3887 }
3888 
3889 
3890 /******************************************************************************
3891  * NetUserSetGroups  (NETAPI32.@)
3892  */
3893 NET_API_STATUS
3894 WINAPI
3895 NetUserSetGroups(LPCWSTR servername,
3896                  LPCWSTR username,
3897                  DWORD level,
3898                  LPBYTE buf,
3899                  DWORD num_entries)
3900 {
3901     FIXME("(%s %s %lu %p %lu)\n",
3902           debugstr_w(servername), debugstr_w(username), level, buf, num_entries);
3903     return ERROR_ACCESS_DENIED;
3904 }
3905 
3906 
3907 /******************************************************************************
3908  * NetUserSetInfo  (NETAPI32.@)
3909  */
3910 NET_API_STATUS
3911 WINAPI
3912 NetUserSetInfo(LPCWSTR servername,
3913                LPCWSTR username,
3914                DWORD level,
3915                LPBYTE buf,
3916                LPDWORD parm_err)
3917 {
3918     UNICODE_STRING ServerName;
3919     UNICODE_STRING UserName;
3920     SAM_HANDLE ServerHandle = NULL;
3921     SAM_HANDLE AccountDomainHandle = NULL;
3922     SAM_HANDLE UserHandle = NULL;
3923     NET_API_STATUS ApiStatus = NERR_Success;
3924     NTSTATUS Status = STATUS_SUCCESS;
3925 
3926     TRACE("(%s %s %lu %p %p)\n",
3927           debugstr_w(servername), debugstr_w(username), level, buf, parm_err);
3928 
3929     if (parm_err != NULL)
3930         *parm_err = PARM_ERROR_NONE;
3931 
3932     /* Check the info level */
3933     switch (level)
3934     {
3935         case 0:
3936         case 1:
3937         case 2:
3938         case 3:
3939         case 4:
3940 //        case 21:
3941         case 22:
3942         case 1003:
3943 //        case 1005:
3944         case 1006:
3945         case 1007:
3946         case 1008:
3947         case 1009:
3948 //        case 1010:
3949         case 1011:
3950         case 1012:
3951         case 1013:
3952         case 1014:
3953         case 1017:
3954         case 1018:
3955         case 1020:
3956         case 1024:
3957         case 1025:
3958         case 1051:
3959         case 1052:
3960         case 1053:
3961             break;
3962 
3963         default:
3964             return ERROR_INVALID_LEVEL;
3965     }
3966 
3967     if (servername != NULL)
3968         RtlInitUnicodeString(&ServerName, servername);
3969 
3970     RtlInitUnicodeString(&UserName, username);
3971 
3972     /* Connect to the SAM Server */
3973     Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3974                         &ServerHandle,
3975                         SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3976                         NULL);
3977     if (!NT_SUCCESS(Status))
3978     {
3979         ERR("SamConnect failed (Status %08lx)\n", Status);
3980         ApiStatus = NetpNtStatusToApiStatus(Status);
3981         goto done;
3982     }
3983 
3984     /* Open the Account Domain */
3985     Status = OpenAccountDomain(ServerHandle,
3986                                (servername != NULL) ? &ServerName : NULL,
3987                                DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
3988                                &AccountDomainHandle);
3989     if (!NT_SUCCESS(Status))
3990     {
3991         ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3992         ApiStatus = NetpNtStatusToApiStatus(Status);
3993         goto done;
3994     }
3995 
3996     /* Open the User Account */
3997     ApiStatus = OpenUserByName(AccountDomainHandle,
3998                                &UserName,
3999                                USER_ALL_ACCESS,
4000                                &UserHandle);
4001     if (ApiStatus != NERR_Success)
4002     {
4003         ERR("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
4004         goto done;
4005     }
4006 
4007     /* Set user information */
4008     ApiStatus = SetUserInfo(UserHandle,
4009                             buf,
4010                             level,
4011                             parm_err);
4012     if (ApiStatus != NERR_Success)
4013     {
4014         ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
4015     }
4016 
4017 done:
4018     if (UserHandle != NULL)
4019         SamCloseHandle(UserHandle);
4020 
4021     if (AccountDomainHandle != NULL)
4022         SamCloseHandle(AccountDomainHandle);
4023 
4024     if (ServerHandle != NULL)
4025         SamCloseHandle(ServerHandle);
4026 
4027     return ApiStatus;
4028 }
4029 
4030 /* EOF */
4031