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