[NTOS:IO] Implement the PlugPlayControl.PlugPlayControlEnumerateDevice request
[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_1018 UserInfo1018;
1438 PUSER_INFO_1020 UserInfo1020;
1439 PUSER_INFO_1024 UserInfo1024;
1440 PUSER_INFO_1025 UserInfo1025;
1441 PUSER_INFO_1051 UserInfo1051;
1442 PUSER_INFO_1052 UserInfo1052;
1443 PUSER_INFO_1053 UserInfo1053;
1444 PACL Dacl = NULL;
1445 NET_API_STATUS ApiStatus = NERR_Success;
1446 NTSTATUS Status = STATUS_SUCCESS;
1447
1448 ZeroMemory(&UserAllInfo, sizeof(USER_ALL_INFORMATION));
1449
1450 if ((Level == 1) || (Level == 2) || (Level == 3) ||
1451 (Level == 4) || (Level == 22) || (Level == 1008))
1452 {
1453 ApiStatus = GetUserDacl(UserHandle, &Dacl);
1454 if (ApiStatus != NERR_Success)
1455 goto done;
1456 }
1457
1458 switch (Level)
1459 {
1460 case 0:
1461 UserInfo0 = (PUSER_INFO_0)UserInfo;
1462
1463 RtlInitUnicodeString(&UserAllInfo.UserName,
1464 UserInfo0->usri0_name);
1465
1466 UserAllInfo.WhichFields |= USER_ALL_USERNAME;
1467 break;
1468
1469 case 1:
1470 UserInfo1 = (PUSER_INFO_1)UserInfo;
1471
1472 // usri1_name ignored
1473
1474 if (UserInfo1->usri1_password != NULL)
1475 {
1476 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1477 UserInfo1->usri1_password);
1478 UserAllInfo.NtPasswordPresent = TRUE;
1479 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1480 }
1481
1482 // usri1_password_age ignored
1483
1484 // UserInfo1->usri1_priv
1485
1486 if (UserInfo1->usri1_home_dir != NULL)
1487 {
1488 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1489 UserInfo1->usri1_home_dir);
1490 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1491 }
1492
1493 if (UserInfo1->usri1_comment != NULL)
1494 {
1495 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1496 UserInfo1->usri1_comment);
1497 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1498 }
1499
1500 ChangeUserDacl(Dacl, UserInfo1->usri1_flags);
1501 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1->usri1_flags);
1502 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1503
1504 if (UserInfo1->usri1_script_path != NULL)
1505 {
1506 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1507 UserInfo1->usri1_script_path);
1508 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1509 }
1510 break;
1511
1512 case 2:
1513 UserInfo2 = (PUSER_INFO_2)UserInfo;
1514
1515 // usri2_name ignored
1516
1517 if (UserInfo2->usri2_password != NULL)
1518 {
1519 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1520 UserInfo2->usri2_password);
1521 UserAllInfo.NtPasswordPresent = TRUE;
1522 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1523 }
1524
1525 // usri2_password_age ignored
1526
1527 // UserInfo2->usri2_priv;
1528
1529 if (UserInfo2->usri2_home_dir != NULL)
1530 {
1531 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1532 UserInfo2->usri2_home_dir);
1533 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1534 }
1535
1536 if (UserInfo2->usri2_comment != NULL)
1537 {
1538 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1539 UserInfo2->usri2_comment);
1540 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1541 }
1542
1543 ChangeUserDacl(Dacl, UserInfo2->usri2_flags);
1544 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo2->usri2_flags);
1545 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1546
1547 if (UserInfo2->usri2_script_path != NULL)
1548 {
1549 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1550 UserInfo2->usri2_script_path);
1551 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1552 }
1553
1554 // UserInfo2->usri2_auth_flags;
1555
1556 if (UserInfo2->usri2_full_name != NULL)
1557 {
1558 RtlInitUnicodeString(&UserAllInfo.FullName,
1559 UserInfo2->usri2_full_name);
1560 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1561 }
1562
1563 if (UserInfo2->usri2_usr_comment != NULL)
1564 {
1565 RtlInitUnicodeString(&UserAllInfo.UserComment,
1566 UserInfo2->usri2_usr_comment);
1567 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1568 }
1569
1570 if (UserInfo2->usri2_parms != NULL)
1571 {
1572 RtlInitUnicodeString(&UserAllInfo.Parameters,
1573 UserInfo2->usri2_parms);
1574 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1575 }
1576
1577 if (UserInfo2->usri2_workstations != NULL)
1578 {
1579 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1580 UserInfo2->usri2_workstations);
1581 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1582 }
1583
1584 // usri2_last_logon ignored
1585 // usri2_last_logoff ignored
1586
1587 if (UserInfo2->usri2_acct_expires == TIMEQ_FOREVER)
1588 {
1589 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1590 }
1591 else
1592 {
1593 RtlSecondsSince1970ToTime(UserInfo2->usri2_acct_expires,
1594 &UserAllInfo.AccountExpires);
1595 }
1596 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1597
1598 if (UserInfo2->usri2_max_storage != USER_MAXSTORAGE_UNLIMITED)
1599 {
1600 if (parm_err != NULL)
1601 *parm_err = USER_MAX_STORAGE_PARMNUM;
1602 ApiStatus = ERROR_INVALID_PARAMETER;
1603 break;
1604 }
1605
1606 if (UserInfo2->usri2_units_per_week > USHRT_MAX)
1607 {
1608 if (parm_err != NULL)
1609 *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1610 ApiStatus = ERROR_INVALID_PARAMETER;
1611 break;
1612 }
1613
1614 UserAllInfo.LogonHours.UnitsPerWeek = UserInfo2->usri2_units_per_week;
1615 UserAllInfo.LogonHours.LogonHours = UserInfo2->usri2_logon_hours;
1616 UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1617
1618 // usri2_bad_pw_count ignored
1619 // usri2_num_logons ignored
1620 // usri2_logon_server ignored
1621
1622 UserAllInfo.CountryCode = UserInfo2->usri2_country_code;
1623 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1624
1625 UserAllInfo.CodePage = UserInfo2->usri2_code_page;
1626 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1627 break;
1628
1629 case 3:
1630 UserInfo3 = (PUSER_INFO_3)UserInfo;
1631
1632 // usri3_name ignored
1633
1634 if (UserInfo3->usri3_password != NULL)
1635 {
1636 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1637 UserInfo3->usri3_password);
1638 UserAllInfo.NtPasswordPresent = TRUE;
1639 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1640 }
1641
1642 // usri3_password_age ignored
1643
1644 // UserInfo3->usri3_priv;
1645
1646 if (UserInfo3->usri3_home_dir != NULL)
1647 {
1648 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1649 UserInfo3->usri3_home_dir);
1650 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1651 }
1652
1653 if (UserInfo3->usri3_comment != NULL)
1654 {
1655 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1656 UserInfo3->usri3_comment);
1657 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1658 }
1659
1660 ChangeUserDacl(Dacl, UserInfo3->usri3_flags);
1661 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo3->usri3_flags);
1662 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1663
1664 if (UserInfo3->usri3_script_path != NULL)
1665 {
1666 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1667 UserInfo3->usri3_script_path);
1668 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1669 }
1670
1671 // UserInfo3->usri3_auth_flags;
1672
1673 if (UserInfo3->usri3_full_name != NULL)
1674 {
1675 RtlInitUnicodeString(&UserAllInfo.FullName,
1676 UserInfo3->usri3_full_name);
1677 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1678 }
1679
1680 if (UserInfo3->usri3_usr_comment != NULL)
1681 {
1682 RtlInitUnicodeString(&UserAllInfo.UserComment,
1683 UserInfo3->usri3_usr_comment);
1684 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1685 }
1686
1687 if (UserInfo3->usri3_parms != NULL)
1688 {
1689 RtlInitUnicodeString(&UserAllInfo.Parameters,
1690 UserInfo3->usri3_parms);
1691 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1692 }
1693
1694 if (UserInfo3->usri3_workstations != NULL)
1695 {
1696 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1697 UserInfo3->usri3_workstations);
1698 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1699 }
1700
1701 // usri3_last_logon ignored
1702 // usri3_last_logoff ignored
1703
1704 if (UserInfo3->usri3_acct_expires == TIMEQ_FOREVER)
1705 {
1706 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1707 }
1708 else
1709 {
1710 RtlSecondsSince1970ToTime(UserInfo3->usri3_acct_expires,
1711 &UserAllInfo.AccountExpires);
1712 }
1713 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1714
1715 if (UserInfo3->usri3_max_storage != USER_MAXSTORAGE_UNLIMITED)
1716 {
1717 if (parm_err != NULL)
1718 *parm_err = USER_MAX_STORAGE_PARMNUM;
1719 ApiStatus = ERROR_INVALID_PARAMETER;
1720 break;
1721 }
1722
1723 if (UserInfo3->usri3_units_per_week > USHRT_MAX)
1724 {
1725 if (parm_err != NULL)
1726 *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1727 ApiStatus = ERROR_INVALID_PARAMETER;
1728 break;
1729 }
1730
1731 UserAllInfo.LogonHours.UnitsPerWeek = UserInfo3->usri3_units_per_week;
1732 UserAllInfo.LogonHours.LogonHours = UserInfo3->usri3_logon_hours;
1733 UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1734
1735 // usri3_bad_pw_count ignored
1736 // usri3_num_logons ignored
1737 // usri3_logon_server ignored
1738
1739 UserAllInfo.CountryCode = UserInfo3->usri3_country_code;
1740 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1741
1742 UserAllInfo.CodePage = UserInfo3->usri3_code_page;
1743 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1744
1745 // usri3_user_id ignored
1746
1747 UserAllInfo.PrimaryGroupId = UserInfo3->usri3_primary_group_id;
1748 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1749
1750 if (UserInfo3->usri3_profile != NULL)
1751 {
1752 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1753 UserInfo3->usri3_profile);
1754 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1755 }
1756
1757 if (UserInfo3->usri3_home_dir_drive != NULL)
1758 {
1759 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1760 UserInfo3->usri3_home_dir_drive);
1761 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1762 }
1763
1764 UserAllInfo.PasswordExpired = (UserInfo3->usri3_password_expired != 0);
1765 UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1766 break;
1767
1768 case 4:
1769 UserInfo4 = (PUSER_INFO_4)UserInfo;
1770
1771 // usri4_name ignored
1772
1773 if (UserInfo4->usri4_password != NULL)
1774 {
1775 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1776 UserInfo4->usri4_password);
1777 UserAllInfo.NtPasswordPresent = TRUE;
1778 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1779 }
1780
1781 // usri4_password_age ignored
1782
1783 // UserInfo3->usri4_priv;
1784
1785 if (UserInfo4->usri4_home_dir != NULL)
1786 {
1787 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1788 UserInfo4->usri4_home_dir);
1789 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1790 }
1791
1792 if (UserInfo4->usri4_comment != NULL)
1793 {
1794 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1795 UserInfo4->usri4_comment);
1796 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1797 }
1798
1799 ChangeUserDacl(Dacl, UserInfo4->usri4_flags);
1800 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo4->usri4_flags);
1801 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1802
1803 if (UserInfo4->usri4_script_path != NULL)
1804 {
1805 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1806 UserInfo4->usri4_script_path);
1807 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1808 }
1809
1810 // UserInfo4->usri4_auth_flags;
1811
1812 if (UserInfo4->usri4_full_name != NULL)
1813 {
1814 RtlInitUnicodeString(&UserAllInfo.FullName,
1815 UserInfo4->usri4_full_name);
1816 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1817 }
1818
1819 if (UserInfo4->usri4_usr_comment != NULL)
1820 {
1821 RtlInitUnicodeString(&UserAllInfo.UserComment,
1822 UserInfo4->usri4_usr_comment);
1823 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1824 }
1825
1826 if (UserInfo4->usri4_parms != NULL)
1827 {
1828 RtlInitUnicodeString(&UserAllInfo.Parameters,
1829 UserInfo4->usri4_parms);
1830 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1831 }
1832
1833 if (UserInfo4->usri4_workstations != NULL)
1834 {
1835 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1836 UserInfo4->usri4_workstations);
1837 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1838 }
1839
1840 // usri4_last_logon ignored
1841 // usri4_last_logoff ignored
1842
1843 if (UserInfo4->usri4_acct_expires == TIMEQ_FOREVER)
1844 {
1845 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1846 }
1847 else
1848 {
1849 RtlSecondsSince1970ToTime(UserInfo4->usri4_acct_expires,
1850 &UserAllInfo.AccountExpires);
1851 }
1852 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1853
1854 if (UserInfo4->usri4_max_storage != USER_MAXSTORAGE_UNLIMITED)
1855 {
1856 if (parm_err != NULL)
1857 *parm_err = USER_MAX_STORAGE_PARMNUM;
1858 ApiStatus = ERROR_INVALID_PARAMETER;
1859 break;
1860 }
1861
1862 if (UserInfo4->usri4_units_per_week > USHRT_MAX)
1863 {
1864 if (parm_err != NULL)
1865 *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
1866 ApiStatus = ERROR_INVALID_PARAMETER;
1867 break;
1868 }
1869
1870 UserAllInfo.LogonHours.UnitsPerWeek = UserInfo4->usri4_units_per_week;
1871 UserAllInfo.LogonHours.LogonHours = UserInfo4->usri4_logon_hours;
1872 UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
1873
1874 // usri4_bad_pw_count ignored
1875 // usri4_num_logons ignored
1876 // usri4_logon_server ignored
1877
1878 UserAllInfo.CountryCode = UserInfo4->usri4_country_code;
1879 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1880
1881 UserAllInfo.CodePage = UserInfo4->usri4_code_page;
1882 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1883
1884 // usri4_user_sid ignored
1885
1886 UserAllInfo.PrimaryGroupId = UserInfo4->usri4_primary_group_id;
1887 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1888
1889 if (UserInfo4->usri4_profile != NULL)
1890 {
1891 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1892 UserInfo4->usri4_profile);
1893 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1894 }
1895
1896 if (UserInfo4->usri4_home_dir_drive != NULL)
1897 {
1898 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1899 UserInfo4->usri4_home_dir_drive);
1900 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1901 }
1902
1903 UserAllInfo.PasswordExpired = (UserInfo4->usri4_password_expired != 0);
1904 UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1905 break;
1906
1907 // case 21:
1908 // break;
1909
1910 case 22:
1911 UserInfo22 = (PUSER_INFO_22)UserInfo;
1912
1913 // usri22_name ignored
1914
1915 // UserInfo22->usri22_password[ENCRYPTED_PWLEN];
1916
1917 // usri22_password_age ignored
1918
1919 // UserInfo3->usri3_priv;
1920
1921 if (UserInfo22->usri22_home_dir != NULL)
1922 {
1923 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1924 UserInfo22->usri22_home_dir);
1925 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1926 }
1927
1928 if (UserInfo22->usri22_comment != NULL)
1929 {
1930 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1931 UserInfo22->usri22_comment);
1932 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1933 }
1934
1935 ChangeUserDacl(Dacl, UserInfo22->usri22_flags);
1936 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo22->usri22_flags);
1937 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1938
1939 if (UserInfo22->usri22_script_path != NULL)
1940 {
1941 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1942 UserInfo22->usri22_script_path);
1943 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1944 }
1945
1946 // UserInfo22->usri22_auth_flags;
1947
1948 if (UserInfo22->usri22_full_name != NULL)
1949 {
1950 RtlInitUnicodeString(&UserAllInfo.FullName,
1951 UserInfo22->usri22_full_name);
1952 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1953 }
1954
1955 if (UserInfo22->usri22_usr_comment != NULL)
1956 {
1957 RtlInitUnicodeString(&UserAllInfo.UserComment,
1958 UserInfo22->usri22_usr_comment);
1959 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1960 }
1961
1962 if (UserInfo22->usri22_parms != NULL)
1963 {
1964 RtlInitUnicodeString(&UserAllInfo.Parameters,
1965 UserInfo22->usri22_parms);
1966 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1967 }
1968
1969 if (UserInfo22->usri22_workstations != NULL)
1970 {
1971 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1972 UserInfo22->usri22_workstations);
1973 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1974 }
1975
1976 // usri22_last_logon ignored
1977 // usri22_last_logoff ignored
1978
1979 if (UserInfo22->usri22_acct_expires == TIMEQ_FOREVER)
1980 {
1981 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
1982 }
1983 else
1984 {
1985 RtlSecondsSince1970ToTime(UserInfo22->usri22_acct_expires,
1986 &UserAllInfo.AccountExpires);
1987 }
1988 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1989
1990 if (UserInfo22->usri22_max_storage != USER_MAXSTORAGE_UNLIMITED)
1991 {
1992 if (parm_err != NULL)
1993 *parm_err = USER_MAX_STORAGE_PARMNUM;
1994 ApiStatus = ERROR_INVALID_PARAMETER;
1995 break;
1996 }
1997
1998 if (UserInfo22->usri22_units_per_week > USHRT_MAX)
1999 {
2000 if (parm_err != NULL)
2001 *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
2002 ApiStatus = ERROR_INVALID_PARAMETER;
2003 break;
2004 }
2005
2006 UserAllInfo.LogonHours.UnitsPerWeek = UserInfo22->usri22_units_per_week;
2007 UserAllInfo.LogonHours.LogonHours = UserInfo22->usri22_logon_hours;
2008 UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
2009
2010 // usri22_bad_pw_count ignored
2011 // usri22_num_logons ignored
2012 // usri22_logon_server ignored
2013
2014 UserAllInfo.CountryCode = UserInfo22->usri22_country_code;
2015 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
2016
2017 UserAllInfo.CodePage = UserInfo22->usri22_code_page;
2018 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
2019 break;
2020
2021 case 1003:
2022 UserInfo1003 = (PUSER_INFO_1003)UserInfo;
2023
2024 if (UserInfo1003->usri1003_password != NULL)
2025 {
2026 RtlInitUnicodeString(&UserAllInfo.NtPassword,
2027 UserInfo1003->usri1003_password);
2028 UserAllInfo.NtPasswordPresent = TRUE;
2029 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
2030 }
2031 break;
2032
2033 // case 1005:
2034 // break;
2035
2036 case 1006:
2037 UserInfo1006 = (PUSER_INFO_1006)UserInfo;
2038
2039 if (UserInfo1006->usri1006_home_dir != NULL)
2040 {
2041 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
2042 UserInfo1006->usri1006_home_dir);
2043 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
2044 }
2045 break;
2046
2047 case 1007:
2048 UserInfo1007 = (PUSER_INFO_1007)UserInfo;
2049
2050 if (UserInfo1007->usri1007_comment != NULL)
2051 {
2052 RtlInitUnicodeString(&UserAllInfo.AdminComment,
2053 UserInfo1007->usri1007_comment);
2054 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
2055 }
2056 break;
2057
2058 case 1008:
2059 UserInfo1008 = (PUSER_INFO_1008)UserInfo;
2060 ChangeUserDacl(Dacl, UserInfo1008->usri1008_flags);
2061 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1008->usri1008_flags);
2062 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
2063 break;
2064
2065 case 1009:
2066 UserInfo1009 = (PUSER_INFO_1009)UserInfo;
2067
2068 if (UserInfo1009->usri1009_script_path != NULL)
2069 {
2070 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
2071 UserInfo1009->usri1009_script_path);
2072 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
2073 }
2074 break;
2075
2076 // case 1010:
2077 // break;
2078
2079 case 1011:
2080 UserInfo1011 = (PUSER_INFO_1011)UserInfo;
2081
2082 if (UserInfo1011->usri1011_full_name != NULL)
2083 {
2084 RtlInitUnicodeString(&UserAllInfo.FullName,
2085 UserInfo1011->usri1011_full_name);
2086 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
2087 }
2088 break;
2089
2090 case 1012:
2091 UserInfo1012 = (PUSER_INFO_1012)UserInfo;
2092
2093 if (UserInfo1012->usri1012_usr_comment != NULL)
2094 {
2095 RtlInitUnicodeString(&UserAllInfo.UserComment,
2096 UserInfo1012->usri1012_usr_comment);
2097 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
2098 }
2099 break;
2100
2101 case 1013:
2102 UserInfo1013 = (PUSER_INFO_1013)UserInfo;
2103
2104 if (UserInfo1013->usri1013_parms != NULL)
2105 {
2106 RtlInitUnicodeString(&UserAllInfo.Parameters,
2107 UserInfo1013->usri1013_parms);
2108 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
2109 }
2110 break;
2111
2112 case 1014:
2113 UserInfo1014 = (PUSER_INFO_1014)UserInfo;
2114
2115 if (UserInfo1014->usri1014_workstations != NULL)
2116 {
2117 RtlInitUnicodeString(&UserAllInfo.WorkStations,
2118 UserInfo1014->usri1014_workstations);
2119 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
2120 }
2121 break;
2122
2123 case 1017:
2124 UserInfo1017 = (PUSER_INFO_1017)UserInfo;
2125
2126 if (UserInfo1017->usri1017_acct_expires == TIMEQ_FOREVER)
2127 {
2128 UserAllInfo.AccountExpires.QuadPart = MAXLONGLONG;
2129 }
2130 else
2131 {
2132 RtlSecondsSince1970ToTime(UserInfo1017->usri1017_acct_expires,
2133 &UserAllInfo.AccountExpires);
2134 }
2135 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
2136 break;
2137
2138 case 1018:
2139 UserInfo1018 = (PUSER_INFO_1018)UserInfo;
2140
2141 if (UserInfo1018->usri1018_max_storage != USER_MAXSTORAGE_UNLIMITED)
2142 {
2143 if (parm_err != NULL)
2144 *parm_err = USER_MAX_STORAGE_PARMNUM;
2145 ApiStatus = ERROR_INVALID_PARAMETER;
2146 }
2147 break;
2148
2149 case 1020:
2150 UserInfo1020 = (PUSER_INFO_1020)UserInfo;
2151
2152 if (UserInfo1020->usri1020_units_per_week > USHRT_MAX)
2153 {
2154 if (parm_err != NULL)
2155 *parm_err = USER_UNITS_PER_WEEK_PARMNUM;
2156 ApiStatus = ERROR_INVALID_PARAMETER;
2157 break;
2158 }
2159
2160 UserAllInfo.LogonHours.UnitsPerWeek = UserInfo1020->usri1020_units_per_week;
2161 UserAllInfo.LogonHours.LogonHours = UserInfo1020->usri1020_logon_hours;
2162 UserAllInfo.WhichFields |= USER_ALL_LOGONHOURS;
2163 break;
2164
2165 case 1024:
2166 UserInfo1024 = (PUSER_INFO_1024)UserInfo;
2167
2168 UserAllInfo.CountryCode = UserInfo1024->usri1024_country_code;
2169 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
2170 break;
2171
2172 case 1025:
2173 UserInfo1025 = (PUSER_INFO_1025)UserInfo;
2174
2175 UserAllInfo.CodePage = UserInfo1025->usri1025_code_page;
2176 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
2177 break;
2178
2179 case 1051:
2180 UserInfo1051 = (PUSER_INFO_1051)UserInfo;
2181
2182 UserAllInfo.PrimaryGroupId = UserInfo1051->usri1051_primary_group_id;
2183 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
2184 break;
2185
2186 case 1052:
2187 UserInfo1052 = (PUSER_INFO_1052)UserInfo;
2188
2189 if (UserInfo1052->usri1052_profile != NULL)
2190 {
2191 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
2192 UserInfo1052->usri1052_profile);
2193 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
2194 }
2195 break;
2196
2197 case 1053:
2198 UserInfo1053 = (PUSER_INFO_1053)UserInfo;
2199
2200 if (UserInfo1053->usri1053_home_dir_drive != NULL)
2201 {
2202 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
2203 UserInfo1053->usri1053_home_dir_drive);
2204 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
2205 }
2206 break;
2207 }
2208
2209 if (ApiStatus != NERR_Success)
2210 goto done;
2211
2212 Status = SamSetInformationUser(UserHandle,
2213 UserAllInformation,
2214 &UserAllInfo);
2215 if (!NT_SUCCESS(Status))
2216 {
2217 ERR("SamSetInformationUser failed (Status %08lx)\n", Status);
2218 ApiStatus = NetpNtStatusToApiStatus(Status);
2219 goto done;
2220 }
2221
2222 done:
2223 if (Dacl != NULL)
2224 HeapFree(GetProcessHeap(), 0, Dacl);
2225
2226 return ApiStatus;
2227 }
2228
2229
2230 static
2231 NET_API_STATUS
2232 OpenUserByName(SAM_HANDLE DomainHandle,
2233 PUNICODE_STRING UserName,
2234 ULONG DesiredAccess,
2235 PSAM_HANDLE UserHandle)
2236 {
2237 PULONG RelativeIds = NULL;
2238 PSID_NAME_USE Use = NULL;
2239 NET_API_STATUS ApiStatus = NERR_Success;
2240 NTSTATUS Status = STATUS_SUCCESS;
2241
2242 /* Get the RID for the given user name */
2243 Status = SamLookupNamesInDomain(DomainHandle,
2244 1,
2245 UserName,
2246 &RelativeIds,
2247 &Use);
2248 if (!NT_SUCCESS(Status))
2249 {
2250 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
2251 return NetpNtStatusToApiStatus(Status);
2252 }
2253
2254 /* Fail, if it is not an alias account */
2255 if (Use[0] != SidTypeUser)
2256 {
2257 ERR("Object is not a user!\n");
2258 ApiStatus = NERR_GroupNotFound;
2259 goto done;
2260 }
2261
2262 /* Open the alias account */
2263 Status = SamOpenUser(DomainHandle,
2264 DesiredAccess,
2265 RelativeIds[0],
2266 UserHandle);
2267 if (!NT_SUCCESS(Status))
2268 {
2269 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2270 ApiStatus = NetpNtStatusToApiStatus(Status);
2271 goto done;
2272 }
2273
2274 done:
2275 if (RelativeIds != NULL)
2276 SamFreeMemory(RelativeIds);
2277
2278 if (Use != NULL)
2279 SamFreeMemory(Use);
2280
2281 return ApiStatus;
2282 }
2283
2284
2285 /************************************************************
2286 * NetUserAdd (NETAPI32.@)
2287 */
2288 NET_API_STATUS
2289 WINAPI
2290 NetUserAdd(LPCWSTR servername,
2291 DWORD level,
2292 LPBYTE bufptr,
2293 LPDWORD parm_err)
2294 {
2295 UNICODE_STRING ServerName;
2296 UNICODE_STRING UserName;
2297 SAM_HANDLE ServerHandle = NULL;
2298 SAM_HANDLE DomainHandle = NULL;
2299 SAM_HANDLE UserHandle = NULL;
2300 ULONG GrantedAccess;
2301 ULONG RelativeId;
2302 NET_API_STATUS ApiStatus = NERR_Success;
2303 NTSTATUS Status = STATUS_SUCCESS;
2304
2305 TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr, parm_err);
2306
2307 if (parm_err != NULL)
2308 *parm_err = PARM_ERROR_NONE;
2309
2310 /* Check the info level */
2311 switch (level)
2312 {
2313 case 1:
2314 case 2:
2315 case 3:
2316 case 4:
2317 break;
2318
2319 default:
2320 return ERROR_INVALID_LEVEL;
2321 }
2322
2323 if (servername != NULL)
2324 RtlInitUnicodeString(&ServerName, servername);
2325
2326 /* Connect to the SAM Server */
2327 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2328 &ServerHandle,
2329 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2330 NULL);
2331 if (!NT_SUCCESS(Status))
2332 {
2333 ERR("SamConnect failed (Status %08lx)\n", Status);
2334 ApiStatus = NetpNtStatusToApiStatus(Status);
2335 goto done;
2336 }
2337
2338 /* Open the Account Domain */
2339 Status = OpenAccountDomain(ServerHandle,
2340 (servername != NULL) ? &ServerName : NULL,
2341 DOMAIN_CREATE_USER | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
2342 &DomainHandle);
2343 if (!NT_SUCCESS(Status))
2344 {
2345 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2346 ApiStatus = NetpNtStatusToApiStatus(Status);
2347 goto done;
2348 }
2349
2350 /* Initialize the user name string */
2351 RtlInitUnicodeString(&UserName,
2352 ((PUSER_INFO_1)bufptr)->usri1_name);
2353
2354 /* Create the user account */
2355 Status = SamCreateUser2InDomain(DomainHandle,
2356 &UserName,
2357 USER_NORMAL_ACCOUNT,
2358 USER_ALL_ACCESS | DELETE | WRITE_DAC,
2359 &UserHandle,
2360 &GrantedAccess,
2361 &RelativeId);
2362 if (!NT_SUCCESS(Status))
2363 {
2364 ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status);
2365 ApiStatus = NetpNtStatusToApiStatus(Status);
2366 goto done;
2367 }
2368
2369 /* Set user information */
2370 ApiStatus = SetUserInfo(UserHandle,
2371 bufptr,
2372 level,
2373 parm_err);
2374 if (ApiStatus != NERR_Success)
2375 {
2376 ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
2377 goto done;
2378 }
2379
2380 done:
2381 if (UserHandle != NULL)
2382 {
2383 if (ApiStatus != NERR_Success)
2384 SamDeleteUser(UserHandle);
2385 else
2386 SamCloseHandle(UserHandle);
2387 }
2388
2389 if (DomainHandle != NULL)
2390 SamCloseHandle(DomainHandle);
2391
2392 if (ServerHandle != NULL)
2393 SamCloseHandle(ServerHandle);
2394
2395 return ApiStatus;
2396 }
2397
2398
2399 /******************************************************************************
2400 * NetUserChangePassword (NETAPI32.@)
2401 * PARAMS
2402 * domainname [I] Optional. Domain on which the user resides or the logon
2403 * domain of the current user if NULL.
2404 * username [I] Optional. Username to change the password for or the name
2405 * of the current user if NULL.
2406 * oldpassword [I] The user's current password.
2407 * newpassword [I] The password that the user will be changed to using.
2408 *
2409 * RETURNS
2410 * Success: NERR_Success.
2411 * Failure: NERR_* failure code or win error code.
2412 *
2413 */
2414 NET_API_STATUS
2415 WINAPI
2416 NetUserChangePassword(LPCWSTR domainname,
2417 LPCWSTR username,
2418 LPCWSTR oldpassword,
2419 LPCWSTR newpassword)
2420 {
2421 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
2422 PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
2423 ULONG RequestBufferSize;
2424 ULONG ResponseBufferSize = 0;
2425 LPWSTR Ptr;
2426 ANSI_STRING PackageName;
2427 ULONG AuthenticationPackage = 0;
2428 HANDLE LsaHandle = NULL;
2429 NET_API_STATUS ApiStatus = NERR_Success;
2430 NTSTATUS Status = STATUS_SUCCESS;
2431 NTSTATUS ProtocolStatus;
2432
2433 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2434
2435 /* FIXME: handle null domain or user name */
2436
2437 /* Check the parameters */
2438 if ((oldpassword == NULL) ||
2439 (newpassword == NULL))
2440 return ERROR_INVALID_PARAMETER;
2441
2442 /* Connect to the LSA server */
2443 Status = LsaConnectUntrusted(&LsaHandle);
2444 if (!NT_SUCCESS(Status))
2445 return NetpNtStatusToApiStatus(Status);
2446
2447 /* Get the authentication package ID */
2448 RtlInitAnsiString(&PackageName,
2449 MSV1_0_PACKAGE_NAME);
2450
2451 Status = LsaLookupAuthenticationPackage(LsaHandle,
2452 &PackageName,
2453 &AuthenticationPackage);
2454 if (!NT_SUCCESS(Status))
2455 {
2456 ApiStatus = NetpNtStatusToApiStatus(Status);
2457 goto done;
2458 }
2459
2460 /* Calculate the request buffer size */
2461 RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
2462 ((wcslen(domainname) + 1) * sizeof(WCHAR)) +
2463 ((wcslen(username) + 1) * sizeof(WCHAR)) +
2464 ((wcslen(oldpassword) + 1) * sizeof(WCHAR)) +
2465 ((wcslen(newpassword) + 1) * sizeof(WCHAR));
2466
2467 /* Allocate the request buffer */
2468 ApiStatus = NetApiBufferAllocate(RequestBufferSize,
2469 (PVOID*)&RequestBuffer);
2470 if (ApiStatus != NERR_Success)
2471 goto done;
2472
2473 /* Initialize the request buffer */
2474 RequestBuffer->MessageType = MsV1_0ChangePassword;
2475 RequestBuffer->Impersonating = TRUE;
2476
2477 Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
2478
2479 /* Pack the domain name */
2480 RequestBuffer->DomainName.Length = wcslen(domainname) * sizeof(WCHAR);
2481 RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
2482 RequestBuffer->DomainName.Buffer = Ptr;
2483
2484 RtlCopyMemory(RequestBuffer->DomainName.Buffer,
2485 domainname,
2486 RequestBuffer->DomainName.MaximumLength);
2487
2488 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
2489
2490 /* Pack the user name */
2491 RequestBuffer->AccountName.Length = wcslen(username) * sizeof(WCHAR);
2492 RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
2493 RequestBuffer->AccountName.Buffer = Ptr;
2494
2495 RtlCopyMemory(RequestBuffer->AccountName.Buffer,
2496 username,
2497 RequestBuffer->AccountName.MaximumLength);
2498
2499 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
2500
2501 /* Pack the old password */
2502 RequestBuffer->OldPassword.Length = wcslen(oldpassword) * sizeof(WCHAR);
2503 RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
2504 RequestBuffer->OldPassword.Buffer = Ptr;
2505
2506 RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
2507 oldpassword,
2508 RequestBuffer->OldPassword.MaximumLength);
2509
2510 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
2511
2512 /* Pack the new password */
2513 RequestBuffer->NewPassword.Length = wcslen(newpassword) * sizeof(WCHAR);
2514 RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
2515 RequestBuffer->NewPassword.Buffer = Ptr;
2516
2517 RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
2518 newpassword,
2519 RequestBuffer->NewPassword.MaximumLength);
2520
2521 /* Call the authentication package */
2522 Status = LsaCallAuthenticationPackage(LsaHandle,
2523 AuthenticationPackage,
2524 RequestBuffer,
2525 RequestBufferSize,
2526 (PVOID*)&ResponseBuffer,
2527 &ResponseBufferSize,
2528 &ProtocolStatus);
2529 if (!NT_SUCCESS(Status))
2530 {
2531 ApiStatus = NetpNtStatusToApiStatus(Status);
2532 goto done;
2533 }
2534
2535 if (!NT_SUCCESS(ProtocolStatus))
2536 {
2537 ApiStatus = NetpNtStatusToApiStatus(ProtocolStatus);
2538 goto done;
2539 }
2540
2541 done:
2542 if (RequestBuffer != NULL)
2543 NetApiBufferFree(RequestBuffer);
2544
2545 if (ResponseBuffer != NULL)
2546 LsaFreeReturnBuffer(ResponseBuffer);
2547
2548 if (LsaHandle != NULL)
2549 NtClose(LsaHandle);
2550
2551 return ApiStatus;
2552 }
2553
2554
2555 /************************************************************
2556 * NetUserDel (NETAPI32.@)
2557 */
2558 NET_API_STATUS
2559 WINAPI
2560 NetUserDel(LPCWSTR servername,
2561 LPCWSTR username)
2562 {
2563 UNICODE_STRING ServerName;
2564 UNICODE_STRING UserName;
2565 SAM_HANDLE ServerHandle = NULL;
2566 SAM_HANDLE DomainHandle = NULL;
2567 SAM_HANDLE UserHandle = NULL;
2568 NET_API_STATUS ApiStatus = NERR_Success;
2569 NTSTATUS Status = STATUS_SUCCESS;
2570
2571 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
2572
2573 if (servername != NULL)
2574 RtlInitUnicodeString(&ServerName, servername);
2575
2576 RtlInitUnicodeString(&UserName, username);
2577
2578 /* Connect to the SAM Server */
2579 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2580 &ServerHandle,
2581 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2582 NULL);
2583 if (!NT_SUCCESS(Status))
2584 {
2585 ERR("SamConnect failed (Status %08lx)\n", Status);
2586 ApiStatus = NetpNtStatusToApiStatus(Status);
2587 goto done;
2588 }
2589
2590 /* Open the Builtin Domain */
2591 Status = OpenBuiltinDomain(ServerHandle,
2592 DOMAIN_LOOKUP,
2593 &DomainHandle);
2594 if (!NT_SUCCESS(Status))
2595 {
2596 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2597 ApiStatus = NetpNtStatusToApiStatus(Status);
2598 goto done;
2599 }
2600
2601 /* Open the user account in the builtin domain */
2602 ApiStatus = OpenUserByName(DomainHandle,
2603 &UserName,
2604 DELETE,
2605 &UserHandle);
2606 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
2607 {
2608 TRACE("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2609 goto done;
2610 }
2611
2612 if (UserHandle == NULL)
2613 {
2614 if (DomainHandle != NULL)
2615 {
2616 SamCloseHandle(DomainHandle);
2617 DomainHandle = NULL;
2618 }
2619
2620 /* Open the Acount Domain */
2621 Status = OpenAccountDomain(ServerHandle,
2622 (servername != NULL) ? &ServerName : NULL,
2623 DOMAIN_LOOKUP,
2624 &DomainHandle);
2625 if (!NT_SUCCESS(Status))
2626 {
2627 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2628 ApiStatus = NetpNtStatusToApiStatus(Status);
2629 goto done;
2630 }
2631
2632 /* Open the user account in the account domain */
2633 ApiStatus = OpenUserByName(DomainHandle,
2634 &UserName,
2635 DELETE,
2636 &UserHandle);
2637 if (ApiStatus != NERR_Success)
2638 {
2639 ERR("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2640 if (ApiStatus == ERROR_NONE_MAPPED)
2641 ApiStatus = NERR_UserNotFound;
2642 goto done;
2643 }
2644 }
2645
2646 /* Delete the user */
2647 Status = SamDeleteUser(UserHandle);
2648 if (!NT_SUCCESS(Status))
2649 {
2650 ERR("SamDeleteUser failed (Status %08lx)\n", Status);
2651 ApiStatus = NetpNtStatusToApiStatus(Status);
2652 goto done;
2653 }
2654
2655 /* A successful delete invalidates the handle */
2656 UserHandle = NULL;
2657
2658 done:
2659 if (UserHandle != NULL)
2660 SamCloseHandle(UserHandle);
2661
2662 if (DomainHandle != NULL)
2663 SamCloseHandle(DomainHandle);
2664
2665 if (ServerHandle != NULL)
2666 SamCloseHandle(ServerHandle);
2667
2668 return ApiStatus;
2669 }
2670
2671 static
2672 NET_API_STATUS
2673 AllocateEnumContext(
2674 PENUM_CONTEXT *AllocatedEnumContext)
2675 {
2676 NET_API_STATUS ApiStatus;
2677 PENUM_CONTEXT EnumContext;
2678
2679 /* Allocate the context structure */
2680 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
2681 if (ApiStatus != NERR_Success)
2682 return ApiStatus;
2683
2684 /* Initialize the fields */
2685 EnumContext->EnumerationContext = 0;
2686 EnumContext->Buffer = NULL;
2687 EnumContext->Count = 0;
2688 EnumContext->Index = 0;
2689 EnumContext->BuiltinDone = FALSE;
2690
2691 /* Set a "unique" handle */
2692 EnumContext->EnumHandle = InterlockedIncrement(&g_EnumContextHandle);
2693 if (EnumContext->EnumHandle == 0)
2694 {
2695 EnumContext->EnumHandle = InterlockedIncrement(&g_EnumContextHandle);
2696 }
2697
2698 /* Insert the context in the list */
2699 EnterCriticalSection(&g_EnumContextListLock);
2700 InsertTailList(&g_EnumContextListHead, &EnumContext->ListLink);
2701 LeaveCriticalSection(&g_EnumContextListLock);
2702
2703 *AllocatedEnumContext = EnumContext;
2704 return NERR_Success;
2705 }
2706
2707 static
2708 VOID
2709 FreeEnumContext(
2710 PENUM_CONTEXT EnumContext)
2711
2712 {
2713 /* Remove the context from the list */
2714 EnterCriticalSection(&g_EnumContextListLock);
2715 RemoveEntryList(&EnumContext->ListLink);
2716 LeaveCriticalSection(&g_EnumContextListLock);
2717
2718 /* Free it */
2719 NetApiBufferFree(EnumContext);
2720 }
2721
2722 static
2723 PENUM_CONTEXT
2724 LookupEnumContext(
2725 SAM_ENUMERATE_HANDLE EnumerationHandle)
2726 {
2727 PENUM_CONTEXT FoundEnumContext = NULL;
2728 PLIST_ENTRY ListEntry;
2729
2730 /* Acquire the list lock */
2731 EnterCriticalSection(&g_EnumContextListLock);
2732
2733 /* Search the list for the handle */
2734 for (ListEntry = g_EnumContextListHead.Flink;
2735 ListEntry != &g_EnumContextListHead;
2736 ListEntry = ListEntry->Flink)
2737 {
2738 PENUM_CONTEXT EnumContext = CONTAINING_RECORD(ListEntry, ENUM_CONTEXT, ListLink);
2739 if (EnumContext->EnumHandle == EnumerationHandle)
2740 {
2741 FoundEnumContext = EnumContext;
2742 break;
2743 }
2744 }
2745
2746 /* Release the list lock */
2747 LeaveCriticalSection(&g_EnumContextListLock);
2748
2749 return FoundEnumContext;
2750 }
2751
2752 /************************************************************
2753 * NetUserEnum (NETAPI32.@)
2754 */
2755 NET_API_STATUS
2756 WINAPI
2757 NetUserEnum(LPCWSTR servername,
2758 DWORD level,
2759 DWORD filter,
2760 LPBYTE* bufptr,
2761 DWORD prefmaxlen,
2762 LPDWORD entriesread,
2763 LPDWORD totalentries,
2764 LPDWORD resume_handle)
2765 {
2766 UNICODE_STRING ServerName;
2767 PSAM_RID_ENUMERATION CurrentUser;
2768 PENUM_CONTEXT EnumContext = NULL;
2769 LPVOID Buffer = NULL;
2770 ULONG i;
2771 SAM_HANDLE UserHandle = NULL;
2772 ACCESS_MASK DesiredAccess;
2773 NET_API_STATUS ApiStatus = NERR_Success;
2774 NTSTATUS Status = STATUS_SUCCESS;
2775
2776 TRACE("(%s %d 0x%d %p %d %p %p %p)\n", debugstr_w(servername), level,
2777 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2778
2779 *entriesread = 0;
2780 *totalentries = 0;
2781 *bufptr = NULL;
2782
2783 if (servername != NULL)
2784 RtlInitUnicodeString(&ServerName, servername);
2785
2786 if (resume_handle != NULL && *resume_handle != 0)
2787 {
2788 EnumContext = LookupEnumContext(*resume_handle);
2789 }
2790 else
2791 {
2792 ApiStatus = AllocateEnumContext(&EnumContext);
2793 if (ApiStatus != NERR_Success)
2794 goto done;
2795
2796 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2797 &EnumContext->ServerHandle,
2798 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2799 NULL);
2800 if (!NT_SUCCESS(Status))
2801 {
2802 ERR("SamConnect failed (Status %08lx)\n", Status);
2803 ApiStatus = NetpNtStatusToApiStatus(Status);
2804 goto done;
2805 }
2806
2807 /* Get the Account Domain SID */
2808 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2809 &EnumContext->AccountDomainSid);
2810 if (!NT_SUCCESS(Status))
2811 {
2812 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2813 ApiStatus = NetpNtStatusToApiStatus(Status);
2814 goto done;
2815 }
2816
2817 /* Open the Account Domain */
2818 Status = SamOpenDomain(EnumContext->ServerHandle,
2819 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2820 EnumContext->AccountDomainSid,
2821 &EnumContext->AccountDomainHandle);
2822 if (!NT_SUCCESS(Status))
2823 {
2824 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2825 ApiStatus = NetpNtStatusToApiStatus(Status);
2826 goto done;
2827 }
2828
2829 /* Get the Builtin Domain SID */
2830 Status = GetBuiltinDomainSid(&EnumContext->BuiltinDomainSid);
2831 if (!NT_SUCCESS(Status))
2832 {
2833 ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
2834 ApiStatus = NetpNtStatusToApiStatus(Status);
2835 goto done;
2836 }
2837
2838 DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
2839 if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
2840 DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
2841
2842 /* Open the Builtin Domain */
2843 Status = SamOpenDomain(EnumContext->ServerHandle,
2844 DesiredAccess,
2845 EnumContext->BuiltinDomainSid,
2846 &EnumContext->BuiltinDomainHandle);
2847 if (!NT_SUCCESS(Status))
2848 {
2849 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2850 ApiStatus = NetpNtStatusToApiStatus(Status);
2851 goto done;
2852 }
2853 }
2854
2855 // while (TRUE)
2856 // {
2857 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
2858 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2859
2860 if (EnumContext->Index >= EnumContext->Count)
2861 {
2862 // if (EnumContext->BuiltinDone != FALSE)
2863 // {
2864 // ApiStatus = NERR_Success;
2865 // goto done;
2866 // }
2867
2868 TRACE("Calling SamEnumerateUsersInDomain\n");
2869 Status = SamEnumerateUsersInDomain(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2870 &EnumContext->EnumerationContext,
2871 0,
2872 (PVOID *)&EnumContext->Buffer,
2873 prefmaxlen,
2874 &EnumContext->Count);
2875
2876 TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
2877 if (!NT_SUCCESS(Status))
2878 {
2879 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status);
2880 ApiStatus = NetpNtStatusToApiStatus(Status);
2881 goto done;
2882 }
2883
2884 if (Status == STATUS_MORE_ENTRIES)
2885 {
2886 ApiStatus = NERR_BufTooSmall;
2887 goto done;
2888 }
2889 else
2890 {
2891 EnumContext->BuiltinDone = TRUE;
2892 }
2893 }
2894
2895 TRACE("EnumContext: %lu\n", EnumContext);
2896 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2897 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
2898
2899 /* Get a pointer to the current user */
2900 CurrentUser = &EnumContext->Buffer[EnumContext->Index];
2901
2902 TRACE("RID: %lu\n", CurrentUser->RelativeId);
2903
2904 DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT;
2905 if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
2906 DesiredAccess |= USER_LIST_GROUPS;
2907
2908 Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2909 DesiredAccess,
2910 CurrentUser->RelativeId,
2911 &UserHandle);
2912 if (!NT_SUCCESS(Status))
2913 {
2914 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2915 ApiStatus = NetpNtStatusToApiStatus(Status);
2916 goto done;
2917 }
2918
2919 ApiStatus = BuildUserInfoBuffer(EnumContext->BuiltinDomainHandle,
2920 UserHandle,
2921 EnumContext->AccountDomainSid,
2922 CurrentUser->RelativeId,
2923 level,
2924 &Buffer);
2925 if (ApiStatus != NERR_Success)
2926 {
2927 ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus);
2928 goto done;
2929 }
2930
2931 SamCloseHandle(UserHandle);
2932 UserHandle = NULL;
2933
2934 EnumContext->Index++;
2935
2936 (*entriesread)++;
2937 // }
2938
2939 done:
2940 if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Index < EnumContext->Count)
2941 ApiStatus = ERROR_MORE_DATA;
2942
2943 if (EnumContext != NULL)
2944 *totalentries = EnumContext->Count;
2945
2946 if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
2947 {
2948 if (EnumContext != NULL)
2949 {
2950 if (EnumContext->BuiltinDomainHandle != NULL)
2951 SamCloseHandle(EnumContext->BuiltinDomainHandle);
2952
2953 if (EnumContext->AccountDomainHandle != NULL)
2954 SamCloseHandle(EnumContext->AccountDomainHandle);
2955
2956 if (EnumContext->BuiltinDomainSid != NULL)
2957 RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->BuiltinDomainSid);
2958
2959 if (EnumContext->AccountDomainSid != NULL)
2960 RtlFreeHeap(RtlGetProcessHeap(), 0, EnumContext->AccountDomainSid);
2961
2962 if (EnumContext->ServerHandle != NULL)
2963 SamCloseHandle(EnumContext->ServerHandle);
2964
2965 if (EnumContext->Buffer != NULL)
2966 {
2967 for (i = 0; i < EnumContext->Count; i++)
2968 {
2969 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
2970 }
2971
2972 SamFreeMemory(EnumContext->Buffer);
2973 }
2974
2975 FreeEnumContext(EnumContext);
2976 EnumContext = NULL;
2977 }
2978 }
2979
2980 if (UserHandle != NULL)
2981 SamCloseHandle(UserHandle);
2982
2983 if (resume_handle != NULL)
2984 *resume_handle = EnumContext ? EnumContext->EnumHandle : 0;
2985
2986 *bufptr = (LPBYTE)Buffer;
2987
2988 TRACE("return %lu\n", ApiStatus);
2989
2990 return ApiStatus;
2991 }
2992
2993
2994 /************************************************************
2995 * NetUserGetGroups (NETAPI32.@)
2996 */
2997 NET_API_STATUS
2998 WINAPI
2999 NetUserGetGroups(LPCWSTR servername,
3000 LPCWSTR username,
3001 DWORD level,
3002 LPBYTE *bufptr,
3003 DWORD prefixmaxlen,
3004 LPDWORD entriesread,
3005 LPDWORD totalentries)
3006 {
3007 UNICODE_STRING ServerName;
3008 UNICODE_STRING UserName;
3009 SAM_HANDLE ServerHandle = NULL;
3010 SAM_HANDLE AccountDomainHandle = NULL;
3011 SAM_HANDLE UserHandle = NULL;
3012 PSID AccountDomainSid = NULL;
3013 PULONG RelativeIds = NULL;
3014 PSID_NAME_USE Use = NULL;
3015 PGROUP_MEMBERSHIP GroupMembership = NULL;
3016 ULONG GroupCount;
3017
3018 NET_API_STATUS ApiStatus = NERR_Success;
3019 NTSTATUS Status = STATUS_SUCCESS;
3020
3021 TRACE("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
3022 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
3023 totalentries);
3024
3025 if (servername != NULL)
3026 RtlInitUnicodeString(&ServerName, servername);
3027
3028 RtlInitUnicodeString(&UserName, username);
3029
3030 /* Connect to the SAM Server */
3031 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3032 &ServerHandle,
3033 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3034 NULL);
3035 if (!NT_SUCCESS(Status))
3036 {
3037 ERR("SamConnect failed (Status %08lx)\n", Status);
3038 ApiStatus = NetpNtStatusToApiStatus(Status);
3039 goto done;
3040 }
3041
3042 /* Get the Account Domain SID */
3043 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3044 &AccountDomainSid);
3045 if (!NT_SUCCESS(Status))
3046 {
3047 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3048 ApiStatus = NetpNtStatusToApiStatus(Status);
3049 goto done;
3050 }
3051
3052 /* Open the Account Domain */
3053 Status = SamOpenDomain(ServerHandle,
3054 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
3055 AccountDomainSid,
3056 &AccountDomainHandle);
3057 if (!NT_SUCCESS(Status))
3058 {
3059 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3060 ApiStatus = NetpNtStatusToApiStatus(Status);
3061 goto done;
3062 }
3063
3064 /* Get the RID for the given user name */
3065 Status = SamLookupNamesInDomain(AccountDomainHandle,
3066 1,
3067 &UserName,
3068 &RelativeIds,
3069 &Use);
3070 if (!NT_SUCCESS(Status))
3071 {
3072 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
3073 if (Status == STATUS_NONE_MAPPED)
3074 ApiStatus = NERR_UserNotFound;
3075 else
3076 ApiStatus = NetpNtStatusToApiStatus(Status);
3077 goto done;
3078 }
3079
3080 /* Fail, if it is not a user account */
3081 if (Use[0] != SidTypeUser)
3082 {
3083 ERR("Account is not a User!\n");
3084 ApiStatus = NERR_UserNotFound;
3085 goto done;
3086 }
3087
3088 /* Open the user object */
3089 Status = SamOpenUser(AccountDomainHandle,
3090 USER_LIST_GROUPS,
3091 RelativeIds[0],
3092 &UserHandle);
3093 if (!NT_SUCCESS(Status))
3094 {
3095 ERR("SamOpenUser failed (Status %08lx)\n", Status);
3096 ApiStatus = NetpNtStatusToApiStatus(Status);
3097 goto done;
3098 }
3099
3100 /* Get the group memberships of this user */
3101 Status = SamGetGroupsForUser(UserHandle,
3102 &GroupMembership,
3103 &GroupCount);
3104 if (!NT_SUCCESS(Status))
3105 {
3106 ERR("SamGetGroupsForUser failed (Status %08lx)\n", Status);
3107 ApiStatus = NetpNtStatusToApiStatus(Status);
3108 goto done;
3109 }
3110
3111 /* If there is no group membership, we're done */
3112 if (GroupCount == 0)
3113 {
3114 ApiStatus = NERR_Success;
3115 goto done;
3116 }
3117
3118
3119 done:
3120
3121 if (GroupMembership != NULL)
3122 SamFreeMemory(GroupMembership);
3123
3124 if (UserHandle != NULL)
3125 SamCloseHandle(UserHandle);
3126
3127 if (RelativeIds != NULL)
3128 SamFreeMemory(RelativeIds);
3129
3130 if (Use != NULL)
3131 SamFreeMemory(Use);
3132
3133 if (AccountDomainSid != NULL)
3134 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3135
3136 if (AccountDomainHandle != NULL)
3137 SamCloseHandle(AccountDomainHandle);
3138
3139 if (ServerHandle != NULL)
3140 SamCloseHandle(ServerHandle);
3141
3142 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3143 {
3144 *entriesread = 0;
3145 *totalentries = 0;
3146 }
3147 else
3148 {
3149 // *entriesread = Count;
3150 // *totalentries = Count;
3151 }
3152
3153 // *bufptr = (LPBYTE)Buffer;
3154
3155 return ApiStatus;
3156 }
3157
3158
3159 /************************************************************
3160 * NetUserGetInfo (NETAPI32.@)
3161 */
3162 NET_API_STATUS
3163 WINAPI
3164 NetUserGetInfo(LPCWSTR servername,
3165 LPCWSTR username,
3166 DWORD level,
3167 LPBYTE* bufptr)
3168 {
3169 UNICODE_STRING ServerName;
3170 UNICODE_STRING UserName;
3171 SAM_HANDLE ServerHandle = NULL;
3172 SAM_HANDLE AccountDomainHandle = NULL;
3173 SAM_HANDLE BuiltinDomainHandle = NULL;
3174 SAM_HANDLE UserHandle = NULL;
3175 PULONG RelativeIds = NULL;
3176 PSID_NAME_USE Use = NULL;
3177 LPVOID Buffer = NULL;
3178 PSID AccountDomainSid = NULL;
3179 PSID BuiltinDomainSid = NULL;
3180 ACCESS_MASK DesiredAccess;
3181 NET_API_STATUS ApiStatus = NERR_Success;
3182 NTSTATUS Status = STATUS_SUCCESS;
3183
3184 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername),
3185 debugstr_w(username), level, bufptr);
3186
3187 if (servername != NULL)
3188 RtlInitUnicodeString(&ServerName, servername);
3189
3190 RtlInitUnicodeString(&UserName, username);
3191
3192 /* Connect to the SAM Server */
3193 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3194 &ServerHandle,
3195 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3196 NULL);
3197 if (!NT_SUCCESS(Status))
3198 {
3199 ERR("SamConnect failed (Status %08lx)\n", Status);
3200 ApiStatus = NetpNtStatusToApiStatus(Status);
3201 goto done;
3202 }
3203
3204 /* Get the Builtin Domain SID */
3205 Status = GetBuiltinDomainSid(&BuiltinDomainSid);
3206 if (!NT_SUCCESS(Status))
3207 {
3208 ERR("GetBuiltinDomainSid failed (Status %08lx)\n", Status);
3209 ApiStatus = NetpNtStatusToApiStatus(Status);
3210 goto done;
3211 }
3212
3213 DesiredAccess = DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP;
3214 if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
3215 DesiredAccess |= DOMAIN_GET_ALIAS_MEMBERSHIP;
3216
3217 /* Open the Builtin Domain */
3218 Status = SamOpenDomain(ServerHandle,
3219 DesiredAccess,
3220 BuiltinDomainSid,
3221 &BuiltinDomainHandle);
3222 if (!NT_SUCCESS(Status))
3223 {
3224 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
3225 ApiStatus = NetpNtStatusToApiStatus(Status);
3226 goto done;
3227 }
3228
3229 /* Get the Account Domain SID */
3230 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3231 &AccountDomainSid);
3232 if (!NT_SUCCESS(Status))
3233 {
3234 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3235 ApiStatus = NetpNtStatusToApiStatus(Status);
3236 goto done;
3237 }
3238
3239 /* Open the Account Domain */
3240 Status = SamOpenDomain(ServerHandle,
3241 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
3242 AccountDomainSid,
3243 &AccountDomainHandle);
3244 if (!NT_SUCCESS(Status))
3245 {
3246 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3247 ApiStatus = NetpNtStatusToApiStatus(Status);
3248 goto done;
3249 }
3250
3251 /* Get the RID for the given user name */
3252 Status = SamLookupNamesInDomain(AccountDomainHandle,
3253 1,
3254 &UserName,
3255 &RelativeIds,
3256 &Use);
3257 if (!NT_SUCCESS(Status))
3258 {
3259 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
3260 if (Status == STATUS_NONE_MAPPED)
3261 ApiStatus = NERR_UserNotFound;
3262 else
3263 ApiStatus = NetpNtStatusToApiStatus(Status);
3264 goto done;
3265 }
3266
3267 /* Check if the account is a user account */
3268 if (Use[0] != SidTypeUser)
3269 {
3270 ERR("No user found!\n");
3271 ApiStatus = NERR_UserNotFound;
3272 goto done;
3273 }
3274
3275 TRACE("RID: %lu\n", RelativeIds[0]);
3276
3277 DesiredAccess = READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT;
3278 if ((level == 1) || (level == 2) || (level == 3) || (level == 4) || (level == 11))
3279 DesiredAccess |= USER_LIST_GROUPS;
3280
3281 /* Open the user object */
3282 Status = SamOpenUser(AccountDomainHandle,
3283 DesiredAccess,
3284 RelativeIds[0],
3285 &UserHandle);
3286 if (!NT_SUCCESS(Status))
3287 {
3288 ERR("SamOpenUser failed (Status %08lx)\n", Status);
3289 ApiStatus = NetpNtStatusToApiStatus(Status);
3290 goto done;
3291 }
3292
3293 ApiStatus = BuildUserInfoBuffer(BuiltinDomainHandle,
3294 UserHandle,
3295 AccountDomainSid,
3296 RelativeIds[0],
3297 level,
3298 &Buffer);
3299 if (ApiStatus != NERR_Success)
3300 {
3301 ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus);
3302 goto done;
3303 }
3304
3305 done:
3306 if (UserHandle != NULL)
3307 SamCloseHandle(UserHandle);
3308
3309 if (RelativeIds != NULL)
3310 SamFreeMemory(RelativeIds);
3311
3312 if (Use != NULL)
3313 SamFreeMemory(Use);
3314
3315 if (AccountDomainHandle != NULL)
3316 SamCloseHandle(AccountDomainHandle);
3317
3318 if (AccountDomainSid != NULL)
3319 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3320
3321 if (BuiltinDomainHandle != NULL)
3322 SamCloseHandle(BuiltinDomainHandle);
3323
3324 if (BuiltinDomainSid != NULL)
3325 RtlFreeHeap(RtlGetProcessHeap(), 0, BuiltinDomainSid);
3326
3327 if (ServerHandle != NULL)
3328 SamCloseHandle(ServerHandle);
3329
3330 *bufptr = (LPBYTE)Buffer;
3331
3332 return ApiStatus;
3333 }
3334
3335
3336 /************************************************************
3337 * NetUserGetLocalGroups (NETAPI32.@)
3338 */
3339 NET_API_STATUS
3340 WINAPI
3341 NetUserGetLocalGroups(LPCWSTR servername,
3342 LPCWSTR username,
3343 DWORD level,
3344 DWORD flags,
3345 LPBYTE* bufptr,
3346 DWORD prefmaxlen,
3347 LPDWORD entriesread,
3348 LPDWORD totalentries)
3349 {
3350 UNICODE_STRING ServerName;
3351 UNICODE_STRING UserName;
3352 SAM_HANDLE ServerHandle = NULL;
3353 SAM_HANDLE BuiltinDomainHandle = NULL;
3354 SAM_HANDLE AccountDomainHandle = NULL;
3355 PSID AccountDomainSid = NULL;
3356 PSID UserSid = NULL;
3357 PULONG RelativeIds = NULL;
3358 PSID_NAME_USE Use = NULL;
3359 ULONG BuiltinMemberCount = 0;
3360 ULONG AccountMemberCount = 0;
3361 PULONG BuiltinAliases = NULL;
3362 PULONG AccountAliases = NULL;
3363 PUNICODE_STRING BuiltinNames = NULL;
3364 PUNICODE_STRING AccountNames = NULL;
3365 PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
3366 ULONG Size;
3367 ULONG Count = 0;
3368 ULONG Index;
3369 ULONG i;
3370 LPWSTR StrPtr;
3371 NET_API_STATUS ApiStatus = NERR_Success;
3372 NTSTATUS Status = STATUS_SUCCESS;
3373
3374 TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
3375 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
3376 prefmaxlen, entriesread, totalentries);
3377
3378 if (level != 0)
3379 return ERROR_INVALID_LEVEL;
3380
3381 if (flags & ~LG_INCLUDE_INDIRECT)
3382 return ERROR_INVALID_PARAMETER;
3383
3384 if (flags & LG_INCLUDE_INDIRECT)
3385 {
3386 WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
3387 }
3388
3389 if (servername != NULL)
3390 RtlInitUnicodeString(&ServerName, servername);
3391
3392 RtlInitUnicodeString(&UserName, username);
3393
3394 /* Connect to the SAM Server */
3395 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3396 &ServerHandle,
3397 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3398 NULL);
3399 if (!NT_SUCCESS(Status))
3400 {
3401 ERR("SamConnect failed (Status %08lx)\n", Status);
3402 ApiStatus = NetpNtStatusToApiStatus(Status);
3403 goto done;
3404 }
3405
3406 /* Open the Builtin Domain */
3407 Status = OpenBuiltinDomain(ServerHandle,
3408 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
3409 &BuiltinDomainHandle);
3410 if (!NT_SUCCESS(Status))
3411 {
3412 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
3413 ApiStatus = NetpNtStatusToApiStatus(Status);
3414 goto done;
3415 }
3416
3417 /* Get the Account Domain SID */
3418 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3419 &AccountDomainSid);
3420 if (!NT_SUCCESS(Status))
3421 {
3422 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3423 ApiStatus = NetpNtStatusToApiStatus(Status);
3424 goto done;
3425 }
3426
3427 /* Open the Account Domain */
3428 Status = SamOpenDomain(ServerHandle,
3429 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
3430 AccountDomainSid,
3431 &AccountDomainHandle);
3432 if (!NT_SUCCESS(Status))
3433 {
3434 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3435 ApiStatus = NetpNtStatusToApiStatus(Status);
3436 goto done;
3437 }
3438
3439 /* Get the RID for the given user name */
3440 Status = SamLookupNamesInDomain(AccountDomainHandle,
3441 1,
3442 &UserName,
3443 &RelativeIds,
3444 &Use);
3445 if (!NT_SUCCESS(Status))
3446 {
3447 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
3448 if (Status == STATUS_NONE_MAPPED)
3449 ApiStatus = NERR_UserNotFound;
3450 else
3451 ApiStatus = NetpNtStatusToApiStatus(Status);
3452 goto done;
3453 }
3454
3455 /* Fail, if it is not a user account */
3456 if (Use[0] != SidTypeUser)
3457 {
3458 ERR("Account is not a User!\n");
3459 ApiStatus = NERR_UserNotFound;
3460 goto done;
3461 }
3462
3463 /* Build the User SID from the Account Domain SID and the users RID */
3464 ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
3465 RelativeIds[0],
3466 &UserSid);
3467 if (ApiStatus != NERR_Success)
3468 {
3469 ERR("BuildSidFromSidAndRid failed!\n");
3470 goto done;
3471 }
3472
3473 /* Get alias memberships in the Builtin Domain */
3474 Status = SamGetAliasMembership(BuiltinDomainHandle,
3475 1,
3476 &UserSid,
3477 &BuiltinMemberCount,
3478 &BuiltinAliases);
3479 if (!NT_SUCCESS(Status))
3480 {
3481 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3482 ApiStatus = NetpNtStatusToApiStatus(Status);
3483 goto done;
3484 }
3485
3486 if (BuiltinMemberCount > 0)
3487 {
3488 /* Get the Names of the builtin alias members */
3489 Status = SamLookupIdsInDomain(BuiltinDomainHandle,
3490 BuiltinMemberCount,
3491 BuiltinAliases,
3492 &BuiltinNames,
3493 NULL);
3494 if (!NT_SUCCESS(Status))
3495 {
3496 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3497 ApiStatus = NetpNtStatusToApiStatus(Status);
3498 goto done;
3499 }
3500 }
3501
3502 /* Get alias memberships in the Account Domain */
3503 Status = SamGetAliasMembership(AccountDomainHandle,
3504 1,
3505 &UserSid,
3506 &AccountMemberCount,
3507 &AccountAliases);
3508 if (!NT_SUCCESS(Status))
3509 {
3510 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3511 ApiStatus = NetpNtStatusToApiStatus(Status);
3512 goto done;
3513 }
3514
3515 if (AccountMemberCount > 0)
3516 {
3517 /* Get the Names of the builtin alias members */
3518 Status = SamLookupIdsInDomain(AccountDomainHandle,
3519 AccountMemberCount,
3520 AccountAliases,
3521 &AccountNames,
3522 NULL);
3523 if (!NT_SUCCESS(Status))
3524 {
3525 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3526 ApiStatus = NetpNtStatusToApiStatus(Status);
3527 goto done;
3528 }
3529 }
3530
3531 /* Calculate the required buffer size */
3532 Size = 0;
3533
3534 for (i = 0; i < BuiltinMemberCount; i++)
3535 {
3536 if (BuiltinNames[i].Length > 0)
3537 {
3538 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3539 Count++;
3540 }
3541 }
3542
3543 for (i = 0; i < AccountMemberCount; i++)
3544 {
3545 if (AccountNames[i].Length > 0)
3546 {
3547 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length + sizeof(UNICODE_NULL));
3548 Count++;
3549 }
3550 }
3551
3552 if (Size == 0)
3553 {
3554 ApiStatus = NERR_Success;
3555 goto done;
3556 }
3557
3558 /* Allocate buffer */
3559 ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
3560 if (ApiStatus != NERR_Success)
3561 goto done;
3562
3563 ZeroMemory(Buffer, Size);
3564
3565 StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
3566
3567 /* Copy data to the allocated buffer */
3568 Index = 0;
3569 for (i = 0; i < BuiltinMemberCount; i++)
3570 {
3571 if (BuiltinNames[i].Length > 0)
3572 {
3573 CopyMemory(StrPtr,
3574 BuiltinNames[i].Buffer,
3575 BuiltinNames[i].Length);
3576 Buffer[Index].lgrui0_name = StrPtr;
3577
3578 StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3579 Index++;
3580 }
3581 }
3582
3583 for (i = 0; i < AccountMemberCount; i++)
3584 {
3585 if (AccountNames[i].Length > 0)
3586 {
3587 CopyMemory(StrPtr,
3588 AccountNames[i].Buffer,
3589 AccountNames[i].Length);
3590 Buffer[Index].lgrui0_name = StrPtr;
3591
3592 StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length + sizeof(UNICODE_NULL));
3593 Index++;
3594 }
3595 }
3596
3597 done:
3598 if (AccountNames != NULL)
3599 SamFreeMemory(AccountNames);
3600
3601 if (BuiltinNames != NULL)
3602 SamFreeMemory(BuiltinNames);
3603
3604 if (AccountAliases != NULL)
3605 SamFreeMemory(AccountAliases);
3606
3607 if (BuiltinAliases != NULL)
3608 SamFreeMemory(BuiltinAliases);
3609
3610 if (RelativeIds != NULL)
3611 SamFreeMemory(RelativeIds);
3612
3613 if (Use != NULL)
3614 SamFreeMemory(Use);
3615
3616 if (UserSid != NULL)
3617 NetApiBufferFree(UserSid);
3618
3619 if (AccountDomainSid != NULL)
3620 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3621
3622 if (AccountDomainHandle != NULL)
3623 SamCloseHandle(AccountDomainHandle);
3624
3625 if (BuiltinDomainHandle != NULL)
3626 SamCloseHandle(BuiltinDomainHandle);
3627
3628 if (ServerHandle != NULL)
3629 SamCloseHandle(ServerHandle);
3630
3631 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3632 {
3633 *entriesread = 0;
3634 *totalentries = 0;
3635 }
3636 else
3637 {
3638 *entriesread = Count;
3639 *totalentries = Count;
3640 }
3641
3642 *bufptr = (LPBYTE)Buffer;
3643
3644 return ApiStatus;
3645 }
3646
3647
3648 /******************************************************************************
3649 * NetUserModalsGet (NETAPI32.@)
3650 *
3651 * Retrieves global information for all users and global groups in the security
3652 * database.
3653 *
3654 * PARAMS
3655 * servername [I] Specifies the DNS or the NetBIOS name of the remote server
3656 * on which the function is to execute.
3657 * level [I] Information level of the data.
3658 * 0 Return global passwords parameters. bufptr points to a
3659 * USER_MODALS_INFO_0 struct.
3660 * 1 Return logon server and domain controller information. bufptr
3661 * points to a USER_MODALS_INFO_1 struct.
3662 * 2 Return domain name and identifier. bufptr points to a
3663 * USER_MODALS_INFO_2 struct.
3664 * 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
3665 * struct.
3666 * bufptr [O] Buffer that receives the data.
3667 *
3668 * RETURNS
3669 * Success: NERR_Success.
3670 * Failure:
3671 * ERROR_ACCESS_DENIED - the user does not have access to the info.
3672 * NERR_InvalidComputer - computer name is invalid.
3673 */
3674 NET_API_STATUS
3675 WINAPI
3676 NetUserModalsGet(LPCWSTR servername,
3677 DWORD level,
3678 LPBYTE *bufptr)
3679 {
3680 UNICODE_STRING ServerName;
3681 SAM_HANDLE ServerHandle = NULL;
3682 SAM_HANDLE DomainHandle = NULL;
3683 PSID DomainSid = NULL;
3684 PDOMAIN_PASSWORD_INFORMATION PasswordInfo = NULL;
3685 PDOMAIN_LOGOFF_INFORMATION LogoffInfo = NULL;
3686 PDOMAIN_SERVER_ROLE_INFORMATION ServerRoleInfo = NULL;
3687 PDOMAIN_REPLICATION_INFORMATION ReplicationInfo = NULL;
3688 PDOMAIN_NAME_INFORMATION NameInfo = NULL;
3689 PDOMAIN_LOCKOUT_INFORMATION LockoutInfo = NULL;
3690 ULONG DesiredAccess;
3691 ULONG BufferSize;
3692 PUSER_MODALS_INFO_0 umi0;
3693 PUSER_MODALS_INFO_1 umi1;
3694 PUSER_MODALS_INFO_2 umi2;
3695 PUSER_MODALS_INFO_3 umi3;
3696 NET_API_STATUS ApiStatus = NERR_Success;
3697 NTSTATUS Status = STATUS_SUCCESS;
3698
3699 TRACE("(%s %d %p)\n", debugstr_w(servername), level, bufptr);
3700
3701 *bufptr = NULL;
3702
3703 if (servername != NULL)
3704 RtlInitUnicodeString(&ServerName, servername);
3705
3706 /* Connect to the SAM Server */
3707 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
3708 &ServerHandle,
3709 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
3710 NULL);
3711 if (!NT_SUCCESS(Status))
3712 {
3713 ERR("SamConnect failed (Status %08lx)\n", Status);
3714 ApiStatus = NetpNtStatusToApiStatus(Status);
3715 goto done;
3716 }
3717
3718 /* Get the Account Domain SID */
3719 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
3720 &DomainSid);
3721 if (!NT_SUCCESS(Status))
3722 {
3723 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
3724 ApiStatus = NetpNtStatusToApiStatus(Status);
3725 goto done;
3726 }
3727
3728 switch (level)
3729 {
3730 case 0:
3731 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS | DOMAIN_READ_PASSWORD_PARAMETERS;
3732 break;
3733
3734 case 1:
3735 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
3736 break;
3737
3738 case 2:
3739 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
3740 break;
3741
3742 case 3:
3743 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
3744 break;
3745
3746 default:
3747 ApiStatus = ERROR_INVALID_LEVEL;
3748 goto done;
3749 }
3750
3751 /* Open the Account Domain */
3752 Status = SamOpenDomain(ServerHandle,
3753 DesiredAccess,
3754 DomainSid,
3755 &DomainHandle);
3756 if (!NT_SUCCESS(Status))
3757 {
3758 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
3759 ApiStatus = NetpNtStatusToApiStatus(Status);
3760 goto done;
3761 }
3762
3763 switch (level)
3764 {
3765 case 0:
3766 /* return global passwords parameters */
3767 Status = SamQueryInformationDomain(DomainHandle,
3768 DomainPasswordInformation,
3769 (PVOID*)&PasswordInfo);
3770 if (!NT_SUCCESS(Status))
3771 {
3772 ApiStatus = NetpNtStatusToApiStatus(Status);
3773 goto done;
3774 }
3775
3776 Status = SamQueryInformationDomain(DomainHandle,
3777 DomainLogoffInformation,
3778 (PVOID*)&LogoffInfo);
3779 if (!NT_SUCCESS(Status))
3780 {
3781 ApiStatus = NetpNtStatusToApiStatus(Status);
3782 goto done;
3783 }
3784
3785 BufferSize = sizeof(USER_MODALS_INFO_0);
3786 break;
3787
3788 case 1:
3789 /* return logon server and domain controller info */
3790 Status = SamQueryInformationDomain(DomainHandle,
3791 DomainServerRoleInformation,
3792 (PVOID*)&ServerRoleInfo);
3793 if (!NT_SUCCESS(Status))
3794 {
3795 ApiStatus = NetpNtStatusToApiStatus(Status);
3796 goto done;
3797 }
3798
3799 Status = SamQueryInformationDomain(DomainHandle,
3800 DomainReplicationInformation,
3801 (PVOID*)&ReplicationInfo);
3802 if (!NT_SUCCESS(Status))
3803 {
3804 ApiStatus = NetpNtStatusToApiStatus(Status);
3805 goto done;
3806 }
3807
3808 BufferSize = sizeof(USER_MODALS_INFO_1) +
3809 ReplicationInfo->ReplicaSourceNodeName.Length + sizeof(WCHAR);
3810 break;
3811
3812 case 2:
3813 /* return domain name and identifier */
3814 Status = SamQueryInformationDomain(DomainHandle,
3815 DomainNameInformation,
3816 (PVOID*)&NameInfo);
3817 if (!NT_SUCCESS(Status))
3818 {
3819 ApiStatus = NetpNtStatusToApiStatus(Status);
3820 goto done;
3821 }
3822
3823 BufferSize = sizeof( USER_MODALS_INFO_2 ) +
3824 NameInfo->DomainName.Length + sizeof(WCHAR) +
3825 RtlLengthSid(DomainSid);
3826 break;
3827
3828 case 3:
3829 /* return lockout information */
3830 Status = SamQueryInformationDomain(DomainHandle,
3831 DomainLockoutInformation,
3832 (PVOID*)&LockoutInfo);
3833 if (!NT_SUCCESS(Status))
3834 {
3835 ApiStatus = NetpNtStatusToApiStatus(Status);
3836 goto done;
3837 }
3838
3839 BufferSize = sizeof(USER_MODALS_INFO_3);
3840 break;
3841
3842 default:
3843 TRACE("Invalid level %d is specified\n", level);
3844 ApiStatus = ERROR_INVALID_LEVEL;
3845 goto done;
3846 }
3847
3848
3849 ApiStatus = NetApiBufferAllocate(BufferSize,
3850 (LPVOID *)bufptr);
3851 if (ApiStatus != NERR_Success)
3852 {
3853 WARN("NetApiBufferAllocate() failed\n");
3854 goto done;
3855 }
3856
3857 switch (level)
3858 {
3859 case 0:
3860 umi0 = (PUSER_MODALS_INFO_0)*bufptr;
3861
3862 umi0->usrmod0_min_passwd_len = PasswordInfo->MinPasswordLength;
3863 umi0->usrmod0_max_passwd_age = (ULONG)(-PasswordInfo->MaxPasswordAge.QuadPart / 10000000);
3864 umi0->usrmod0_min_passwd_age =
3865 DeltaTimeToSeconds(PasswordInfo->MinPasswordAge);
3866 umi0->usrmod0_force_logoff =
3867 DeltaTimeToSeconds(LogoffInfo->ForceLogoff);
3868 umi0->usrmod0_password_hist_len = PasswordInfo->PasswordHistoryLength;
3869 break;
3870
3871 case 1:
3872 umi1 = (PUSER_MODALS_INFO_1)*bufptr;
3873
3874 switch (ServerRoleInfo->DomainServerRole)
3875 {
3876 case DomainServerRolePrimary:
3877 umi1->usrmod1_role = UAS_ROLE_PRIMARY;
3878 break;
3879
3880 case DomainServerRoleBackup:
3881 umi1->usrmod1_role = UAS_ROLE_BACKUP;
3882 break;
3883
3884 default:
3885 ApiStatus = NERR_InternalError;
3886 goto done;
3887 }
3888
3889 umi1->usrmod1_primary = (LPWSTR)(*bufptr + sizeof(USER_MODALS_INFO_1));
3890 RtlCopyMemory(umi1->usrmod1_primary,
3891 ReplicationInfo->ReplicaSourceNodeName.Buffer,
3892 ReplicationInfo->ReplicaSourceNodeName.Length);
3893 umi1->usrmod1_primary[ReplicationInfo->ReplicaSourceNodeName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3894 break;
3895
3896 case 2:
3897 umi2 = (PUSER_MODALS_INFO_2)*bufptr;
3898
3899 umi2->usrmod2_domain_name = (LPWSTR)(*bufptr + sizeof(USER_MODALS_INFO_2));
3900 RtlCopyMemory(umi2->usrmod2_domain_name,
3901 NameInfo->DomainName.Buffer,
3902 NameInfo->DomainName.Length);
3903 umi2->usrmod2_domain_name[NameInfo->DomainName.Length / sizeof(WCHAR)] = UNICODE_NULL;
3904
3905 umi2->usrmod2_domain_id = *bufptr +
3906 sizeof(USER_MODALS_INFO_2) +
3907 NameInfo->DomainName.Length + sizeof(WCHAR);
3908 RtlCopyMemory(umi2->usrmod2_domain_id,
3909 DomainSid,
3910 RtlLengthSid(DomainSid));
3911 break;
3912
3913 case 3:
3914 umi3 = (PUSER_MODALS_INFO_3)*bufptr;
3915 umi3->usrmod3_lockout_duration =
3916 DeltaTimeToSeconds(LockoutInfo->LockoutDuration);
3917 umi3->usrmod3_lockout_observation_window =
3918 DeltaTimeToSeconds(LockoutInfo->LockoutObservationWindow );
3919 umi3->usrmod3_lockout_threshold = LockoutInfo->LockoutThreshold;
3920 break;
3921 }
3922
3923 done:
3924 if (LockoutInfo != NULL)
3925 SamFreeMemory(LockoutInfo);
3926
3927 if (NameInfo != NULL)
3928 SamFreeMemory(NameInfo);
3929
3930 if (ReplicationInfo != NULL)
3931 SamFreeMemory(ReplicationInfo);
3932
3933 if (ServerRoleInfo != NULL)
3934 SamFreeMemory(ServerRoleInfo);
3935
3936 if (LogoffInfo != NULL)
3937 SamFreeMemory(LogoffInfo);
3938
3939 if (PasswordInfo != NULL)
3940 SamFreeMemory(PasswordInfo);
3941
3942 if (DomainSid != NULL)
3943 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainSid);
3944
3945 if (DomainHandle != NULL)
3946 SamCloseHandle(DomainHandle);
3947
3948 if (ServerHandle != NULL)
3949 SamCloseHandle(ServerHandle);
3950
3951 return ApiStatus;
3952 }
3953
3954
3955 /******************************************************************************
3956 * NetUserModalsSet (NETAPI32.@)
3957 */
3958 NET_API_STATUS
3959 WINAPI
3960 NetUserModalsSet(IN LPCWSTR servername,
3961 IN DWORD level,
3962 IN LPBYTE buf,
3963 OUT LPDWORD parm_err)
3964 {
3965 FIXME("(%s %d %p %p)\n", debugstr_w(servername), level, buf, parm_err);
3966 return ERROR_ACCESS_DENIED;
3967 }
3968
3969
3970 /******************************************************************************
3971 * NetUserSetGroups (NETAPI32.@)
3972 */
3973 NET_API_STATUS
3974 WINAPI
3975 NetUserSetGroups(LPCWSTR servername,
3976 LPCWSTR username,
3977 DWORD level,
3978 LPBYTE buf,
3979 DWORD num_entries)
3980 {
3981 FIXME("(%s %s %lu %p %lu)\n",
3982 debugstr_w(servername), debugstr_w(username), level, buf, num_entries);
3983 return ERROR_ACCESS_DENIED;
3984 }
3985
3986
3987 /******************************************************************************
3988 * NetUserSetInfo (NETAPI32.@)
3989 */
3990 NET_API_STATUS
3991 WINAPI
3992 NetUserSetInfo(LPCWSTR servername,
3993 LPCWSTR username,
3994 DWORD level,
3995 LPBYTE buf,
3996 LPDWORD parm_err)
3997 {
3998 UNICODE_STRING ServerName;
3999 UNICODE_STRING UserName;
4000 SAM_HANDLE ServerHandle = NULL;
4001 SAM_HANDLE AccountDomainHandle = NULL;
4002 SAM_HANDLE UserHandle = NULL;
4003 NET_API_STATUS ApiStatus = NERR_Success;
4004 NTSTATUS Status = STATUS_SUCCESS;
4005
4006 TRACE("(%s %s %lu %p %p)\n",
4007 debugstr_w(servername), debugstr_w(username), level, buf, parm_err);
4008
4009 if (parm_err != NULL)
4010 *parm_err = PARM_ERROR_NONE;
4011
4012 /* Check the info level */
4013 switch (level)
4014 {
4015 case 0:
4016 case 1:
4017 case 2:
4018 case 3:
4019 case 4:
4020 // case 21:
4021 case 22:
4022 case 1003:
4023 // case 1005:
4024 case 1006:
4025 case 1007:
4026 case 1008:
4027 case 1009:
4028 // case 1010:
4029 case 1011:
4030 case 1012:
4031 case 1013:
4032 case 1014:
4033 case 1017:
4034 case 1018:
4035 case 1020:
4036 case 1024:
4037 case 1025:
4038 case 1051:
4039 case 1052:
4040 case 1053:
4041 break;
4042
4043 default:
4044 return ERROR_INVALID_LEVEL;
4045 }
4046
4047 if (servername != NULL)
4048 RtlInitUnicodeString(&ServerName, servername);
4049
4050 RtlInitUnicodeString(&UserName, username);
4051
4052 /* Connect to the SAM Server */
4053 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
4054 &ServerHandle,
4055 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
4056 NULL);
4057 if (!NT_SUCCESS(Status))
4058 {
4059 ERR("SamConnect failed (Status %08lx)\n", Status);
4060 ApiStatus = NetpNtStatusToApiStatus(Status);
4061 goto done;
4062 }
4063
4064 /* Open the Account Domain */
4065 Status = OpenAccountDomain(ServerHandle,
4066 (servername != NULL) ? &ServerName : NULL,
4067 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
4068 &AccountDomainHandle);
4069 if (!NT_SUCCESS(Status))
4070 {
4071 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
4072 ApiStatus = NetpNtStatusToApiStatus(Status);
4073 goto done;
4074 }
4075
4076 /* Open the User Account */
4077 ApiStatus = OpenUserByName(AccountDomainHandle,
4078 &UserName,
4079 USER_ALL_ACCESS,
4080 &UserHandle);
4081 if (ApiStatus != NERR_Success)
4082 {
4083 ERR("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
4084 goto done;
4085 }
4086
4087 /* Set user information */
4088 ApiStatus = SetUserInfo(UserHandle,
4089 buf,
4090 level,
4091 parm_err);
4092 if (ApiStatus != NERR_Success)
4093 {
4094 ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
4095 }
4096
4097 done:
4098 if (UserHandle != NULL)
4099 SamCloseHandle(UserHandle);
4100
4101 if (AccountDomainHandle != NULL)
4102 SamCloseHandle(AccountDomainHandle);
4103
4104 if (ServerHandle != NULL)
4105 SamCloseHandle(ServerHandle);
4106
4107 return ApiStatus;
4108 }
4109
4110 /* EOF */