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