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