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