[NETAPI32]
[reactos.git] / reactos / 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 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
696 &UserInfo2->usri2_last_logon);
697
698 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
699 &UserInfo2->usri2_last_logoff);
700
701 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
702 &UserInfo2->usri2_acct_expires);
703
704 UserInfo2->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED;
705 UserInfo2->usri2_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
706
707 if (UserInfo->LogonHours.UnitsPerWeek > 0)
708 {
709 UserInfo2->usri2_logon_hours = (PVOID)Ptr;
710
711 memcpy(UserInfo2->usri2_logon_hours,
712 UserInfo->LogonHours.LogonHours,
713 (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
714
715 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
716 }
717
718 UserInfo2->usri2_bad_pw_count = UserInfo->BadPasswordCount;
719 UserInfo2->usri2_num_logons = UserInfo->LogonCount;
720
721 UserInfo2->usri2_logon_server = Ptr;
722 memcpy(UserInfo2->usri2_logon_server,
723 LogonServer.Buffer,
724 LogonServer.Length);
725 UserInfo2->usri2_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
726 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
727
728 UserInfo2->usri2_country_code = UserInfo->CountryCode;
729 UserInfo2->usri2_code_page = UserInfo->CodePage;
730 break;
731
732 case 3:
733 UserInfo3 = (PUSER_INFO_3)LocalBuffer;
734
735 Ptr = (LPWSTR)((ULONG_PTR)UserInfo3 + sizeof(USER_INFO_3));
736
737 UserInfo3->usri3_name = Ptr;
738
739 memcpy(UserInfo3->usri3_name,
740 UserInfo->UserName.Buffer,
741 UserInfo->UserName.Length);
742 UserInfo3->usri3_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
743
744 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
745
746 UserInfo3->usri3_password = NULL;
747 UserInfo3->usri3_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
748
749 /* FIXME: usri3_priv */
750
751 UserInfo3->usri3_home_dir = Ptr;
752 memcpy(UserInfo3->usri3_home_dir,
753 UserInfo->HomeDirectory.Buffer,
754 UserInfo->HomeDirectory.Length);
755 UserInfo3->usri3_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
756 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
757
758 UserInfo3->usri3_comment = Ptr;
759 memcpy(UserInfo3->usri3_comment,
760 UserInfo->AdminComment.Buffer,
761 UserInfo->AdminComment.Length);
762 UserInfo3->usri3_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
763 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
764
765 UserInfo3->usri3_flags = GetAccountFlags(UserInfo->UserAccountControl,
766 Dacl);
767
768 UserInfo3->usri3_script_path = Ptr;
769 memcpy(UserInfo3->usri3_script_path,
770 UserInfo->ScriptPath.Buffer,
771 UserInfo->ScriptPath.Length);
772 UserInfo3->usri3_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
773 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length + sizeof(WCHAR));
774
775 /* FIXME: usri3_auth_flags */
776
777 UserInfo3->usri3_full_name = Ptr;
778 memcpy(UserInfo3->usri3_full_name,
779 UserInfo->FullName.Buffer,
780 UserInfo->FullName.Length);
781 UserInfo3->usri3_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
782 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
783
784 UserInfo3->usri3_usr_comment = Ptr;
785 memcpy(UserInfo3->usri3_usr_comment,
786 UserInfo->UserComment.Buffer,
787 UserInfo->UserComment.Length);
788 UserInfo3->usri3_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
789 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
790
791 UserInfo3->usri3_parms = Ptr;
792 memcpy(UserInfo3->usri3_parms,
793 UserInfo->Parameters.Buffer,
794 UserInfo->Parameters.Length);
795 UserInfo3->usri3_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
796 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
797
798 UserInfo3->usri3_workstations = Ptr;
799 memcpy(UserInfo3->usri3_workstations,
800 UserInfo->WorkStations.Buffer,
801 UserInfo->WorkStations.Length);
802 UserInfo3->usri3_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
803 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
804
805 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
806 &UserInfo3->usri3_last_logon);
807
808 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
809 &UserInfo3->usri3_last_logoff);
810
811 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
812 &UserInfo3->usri3_acct_expires);
813
814 UserInfo3->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED;
815 UserInfo3->usri3_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
816
817 if (UserInfo->LogonHours.UnitsPerWeek > 0)
818 {
819 UserInfo3->usri3_logon_hours = (PVOID)Ptr;
820
821 memcpy(UserInfo3->usri3_logon_hours,
822 UserInfo->LogonHours.LogonHours,
823 (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
824
825 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
826 }
827
828 UserInfo3->usri3_bad_pw_count = UserInfo->BadPasswordCount;
829 UserInfo3->usri3_num_logons = UserInfo->LogonCount;
830
831 UserInfo3->usri3_logon_server = Ptr;
832 memcpy(UserInfo3->usri3_logon_server,
833 LogonServer.Buffer,
834 LogonServer.Length);
835 UserInfo3->usri3_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
836 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
837
838 UserInfo3->usri3_country_code = UserInfo->CountryCode;
839 UserInfo3->usri3_code_page = UserInfo->CodePage;
840 UserInfo3->usri3_user_id = RelativeId;
841 UserInfo3->usri3_primary_group_id = UserInfo->PrimaryGroupId;
842
843 UserInfo3->usri3_profile = Ptr;
844 memcpy(UserInfo3->usri3_profile,
845 UserInfo->ProfilePath.Buffer,
846 UserInfo->ProfilePath.Length);
847 UserInfo3->usri3_profile[UserInfo->ProfilePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
848 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ProfilePath.Length + sizeof(WCHAR));
849
850 UserInfo3->usri3_home_dir_drive = Ptr;
851 memcpy(UserInfo3->usri3_home_dir_drive,
852 UserInfo->HomeDirectoryDrive.Buffer,
853 UserInfo->HomeDirectoryDrive.Length);
854 UserInfo3->usri3_home_dir_drive[UserInfo->HomeDirectoryDrive.Length / sizeof(WCHAR)] = UNICODE_NULL;
855 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR));
856
857 UserInfo3->usri3_password_expired = (UserInfo->UserAccountControl & USER_PASSWORD_EXPIRED);
858 break;
859
860 case 4:
861 UserInfo4 = (PUSER_INFO_4)LocalBuffer;
862
863 Ptr = (LPWSTR)((ULONG_PTR)UserInfo4 + sizeof(USER_INFO_4));
864
865 UserInfo4->usri4_name = Ptr;
866
867 memcpy(UserInfo4->usri4_name,
868 UserInfo->UserName.Buffer,
869 UserInfo->UserName.Length);
870 UserInfo4->usri4_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
871
872 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
873
874 UserInfo4->usri4_password = NULL;
875 UserInfo4->usri4_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
876
877 /* FIXME: usri4_priv */
878
879 UserInfo4->usri4_home_dir = Ptr;
880 memcpy(UserInfo4->usri4_home_dir,
881 UserInfo->HomeDirectory.Buffer,
882 UserInfo->HomeDirectory.Length);
883 UserInfo4->usri4_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
884 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
885
886 UserInfo4->usri4_comment = Ptr;
887 memcpy(UserInfo4->usri4_comment,
888 UserInfo->AdminComment.Buffer,
889 UserInfo->AdminComment.Length);
890 UserInfo4->usri4_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
891 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
892
893 UserInfo4->usri4_flags = GetAccountFlags(UserInfo->UserAccountControl,
894 Dacl);
895
896 UserInfo4->usri4_script_path = Ptr;
897 memcpy(UserInfo4->usri4_script_path,
898 UserInfo->ScriptPath.Buffer,
899 UserInfo->ScriptPath.Length);
900 UserInfo4->usri4_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
901 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ScriptPath.Length + sizeof(WCHAR));
902
903 /* FIXME: usri4_auth_flags */
904
905 UserInfo4->usri4_full_name = Ptr;
906 memcpy(UserInfo4->usri4_full_name,
907 UserInfo->FullName.Buffer,
908 UserInfo->FullName.Length);
909 UserInfo4->usri4_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
910 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
911
912 UserInfo4->usri4_usr_comment = Ptr;
913 memcpy(UserInfo4->usri4_usr_comment,
914 UserInfo->UserComment.Buffer,
915 UserInfo->UserComment.Length);
916 UserInfo4->usri4_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
917 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
918
919 UserInfo4->usri4_parms = Ptr;
920 memcpy(UserInfo4->usri4_parms,
921 UserInfo->Parameters.Buffer,
922 UserInfo->Parameters.Length);
923 UserInfo4->usri4_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
924 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
925
926 UserInfo4->usri4_workstations = Ptr;
927 memcpy(UserInfo4->usri4_workstations,
928 UserInfo->WorkStations.Buffer,
929 UserInfo->WorkStations.Length);
930 UserInfo4->usri4_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
931 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
932
933 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
934 &UserInfo4->usri4_last_logon);
935
936 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
937 &UserInfo4->usri4_last_logoff);
938
939 RtlTimeToSecondsSince1970(&UserInfo->AccountExpires,
940 &UserInfo4->usri4_acct_expires);
941
942 UserInfo4->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED;
943 UserInfo4->usri4_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
944
945 if (UserInfo->LogonHours.UnitsPerWeek > 0)
946 {
947 UserInfo4->usri4_logon_hours = (PVOID)Ptr;
948
949 memcpy(UserInfo4->usri4_logon_hours,
950 UserInfo->LogonHours.LogonHours,
951 (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
952
953 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
954 }
955
956 UserInfo4->usri4_bad_pw_count = UserInfo->BadPasswordCount;
957 UserInfo4->usri4_num_logons = UserInfo->LogonCount;
958
959 UserInfo4->usri4_logon_server = Ptr;
960 memcpy(UserInfo4->usri4_logon_server,
961 LogonServer.Buffer,
962 LogonServer.Length);
963 UserInfo4->usri4_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
964 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
965
966 UserInfo4->usri4_country_code = UserInfo->CountryCode;
967 UserInfo4->usri4_code_page = UserInfo->CodePage;
968
969 /* FIXME: usri4_user_sid */
970
971 UserInfo4->usri4_primary_group_id = UserInfo->PrimaryGroupId;
972
973 UserInfo4->usri4_profile = Ptr;
974 memcpy(UserInfo4->usri4_profile,
975 UserInfo->ProfilePath.Buffer,
976 UserInfo->ProfilePath.Length);
977 UserInfo4->usri4_profile[UserInfo->ProfilePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
978 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->ProfilePath.Length + sizeof(WCHAR));
979
980 UserInfo4->usri4_home_dir_drive = Ptr;
981 memcpy(UserInfo4->usri4_home_dir_drive,
982 UserInfo->HomeDirectoryDrive.Buffer,
983 UserInfo->HomeDirectoryDrive.Length);
984 UserInfo4->usri4_home_dir_drive[UserInfo->HomeDirectoryDrive.Length / sizeof(WCHAR)] = UNICODE_NULL;
985 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR));
986
987 UserInfo4->usri4_password_expired = (UserInfo->UserAccountControl & USER_PASSWORD_EXPIRED);
988 break;
989
990 case 10:
991 UserInfo10 = (PUSER_INFO_10)LocalBuffer;
992
993 Ptr = (LPWSTR)((ULONG_PTR)UserInfo10 + sizeof(USER_INFO_10));
994
995 UserInfo10->usri10_name = Ptr;
996
997 memcpy(UserInfo10->usri10_name,
998 UserInfo->UserName.Buffer,
999 UserInfo->UserName.Length);
1000 UserInfo10->usri10_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1001
1002 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1003
1004 UserInfo10->usri10_comment = Ptr;
1005 memcpy(UserInfo10->usri10_comment,
1006 UserInfo->AdminComment.Buffer,
1007 UserInfo->AdminComment.Length);
1008 UserInfo10->usri10_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1009 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1010
1011 UserInfo10->usri10_usr_comment = Ptr;
1012 memcpy(UserInfo10->usri10_usr_comment,
1013 UserInfo->UserComment.Buffer,
1014 UserInfo->UserComment.Length);
1015 UserInfo10->usri10_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1016 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
1017
1018 UserInfo10->usri10_full_name = Ptr;
1019 memcpy(UserInfo10->usri10_full_name,
1020 UserInfo->FullName.Buffer,
1021 UserInfo->FullName.Length);
1022 UserInfo10->usri10_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1023 break;
1024
1025 case 11:
1026 UserInfo11 = (PUSER_INFO_11)LocalBuffer;
1027
1028 Ptr = (LPWSTR)((ULONG_PTR)UserInfo11 + sizeof(USER_INFO_11));
1029
1030 UserInfo11->usri11_name = Ptr;
1031
1032 memcpy(UserInfo11->usri11_name,
1033 UserInfo->UserName.Buffer,
1034 UserInfo->UserName.Length);
1035 UserInfo11->usri11_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1036
1037 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1038
1039 UserInfo11->usri11_comment = Ptr;
1040 memcpy(UserInfo11->usri11_comment,
1041 UserInfo->AdminComment.Buffer,
1042 UserInfo->AdminComment.Length);
1043 UserInfo11->usri11_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1044 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1045
1046 UserInfo11->usri11_usr_comment = Ptr;
1047 memcpy(UserInfo11->usri11_usr_comment,
1048 UserInfo->UserComment.Buffer,
1049 UserInfo->UserComment.Length);
1050 UserInfo11->usri11_usr_comment[UserInfo->UserComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1051 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserComment.Length + sizeof(WCHAR));
1052
1053 UserInfo11->usri11_full_name = Ptr;
1054 memcpy(UserInfo11->usri11_full_name,
1055 UserInfo->FullName.Buffer,
1056 UserInfo->FullName.Length);
1057 UserInfo11->usri11_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1058 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1059
1060 /* FIXME: usri11_priv */
1061 /* FIXME: usri11_auth_flags */
1062
1063 UserInfo11->usri11_password_age = GetPasswordAge(&UserInfo->PasswordLastSet);
1064
1065 UserInfo11->usri11_home_dir = Ptr;
1066 memcpy(UserInfo11->usri11_home_dir,
1067 UserInfo->HomeDirectory.Buffer,
1068 UserInfo->HomeDirectory.Length);
1069 UserInfo11->usri11_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
1070 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
1071
1072 UserInfo11->usri11_parms = Ptr;
1073 memcpy(UserInfo11->usri11_parms,
1074 UserInfo->Parameters.Buffer,
1075 UserInfo->Parameters.Length);
1076 UserInfo11->usri11_parms[UserInfo->Parameters.Length / sizeof(WCHAR)] = UNICODE_NULL;
1077 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->Parameters.Length + sizeof(WCHAR));
1078
1079 RtlTimeToSecondsSince1970(&UserInfo->LastLogon,
1080 &UserInfo11->usri11_last_logon);
1081
1082 RtlTimeToSecondsSince1970(&UserInfo->LastLogoff,
1083 &UserInfo11->usri11_last_logoff);
1084
1085 UserInfo11->usri11_bad_pw_count = UserInfo->BadPasswordCount;
1086 UserInfo11->usri11_num_logons = UserInfo->LogonCount;
1087
1088 UserInfo11->usri11_logon_server = Ptr;
1089 memcpy(UserInfo11->usri11_logon_server,
1090 LogonServer.Buffer,
1091 LogonServer.Length);
1092 UserInfo11->usri11_logon_server[LogonServer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1093 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LogonServer.Length + sizeof(WCHAR));
1094
1095 UserInfo11->usri11_country_code = UserInfo->CountryCode;
1096
1097 UserInfo11->usri11_workstations = Ptr;
1098 memcpy(UserInfo11->usri11_workstations,
1099 UserInfo->WorkStations.Buffer,
1100 UserInfo->WorkStations.Length);
1101 UserInfo11->usri11_workstations[UserInfo->WorkStations.Length / sizeof(WCHAR)] = UNICODE_NULL;
1102 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->WorkStations.Length + sizeof(WCHAR));
1103
1104 UserInfo11->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED;
1105 UserInfo11->usri11_units_per_week = UserInfo->LogonHours.UnitsPerWeek;
1106
1107 if (UserInfo->LogonHours.UnitsPerWeek > 0)
1108 {
1109 UserInfo11->usri11_logon_hours = (PVOID)Ptr;
1110
1111 memcpy(UserInfo11->usri11_logon_hours,
1112 UserInfo->LogonHours.LogonHours,
1113 (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1114
1115 Ptr = (LPWSTR)((ULONG_PTR)Ptr + (((ULONG)UserInfo->LogonHours.UnitsPerWeek) + 7) / 8);
1116 }
1117
1118 UserInfo11->usri11_code_page = UserInfo->CodePage;
1119 break;
1120
1121 case 20:
1122 UserInfo20 = (PUSER_INFO_20)LocalBuffer;
1123
1124 Ptr = (LPWSTR)((ULONG_PTR)UserInfo20 + sizeof(USER_INFO_20));
1125
1126 UserInfo20->usri20_name = Ptr;
1127
1128 memcpy(UserInfo20->usri20_name,
1129 UserInfo->UserName.Buffer,
1130 UserInfo->UserName.Length);
1131 UserInfo20->usri20_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1132
1133 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1134
1135 UserInfo20->usri20_full_name = Ptr;
1136 memcpy(UserInfo20->usri20_full_name,
1137 UserInfo->FullName.Buffer,
1138 UserInfo->FullName.Length);
1139 UserInfo20->usri20_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1140 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1141
1142 UserInfo20->usri20_comment = Ptr;
1143 memcpy(UserInfo20->usri20_comment,
1144 UserInfo->AdminComment.Buffer,
1145 UserInfo->AdminComment.Length);
1146 UserInfo20->usri20_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1147 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1148
1149 UserInfo20->usri20_flags = GetAccountFlags(UserInfo->UserAccountControl,
1150 Dacl);
1151
1152 UserInfo20->usri20_user_id = RelativeId;
1153 break;
1154
1155 case 23:
1156 UserInfo23 = (PUSER_INFO_23)LocalBuffer;
1157
1158 Ptr = (LPWSTR)((ULONG_PTR)UserInfo23 + sizeof(USER_INFO_23));
1159
1160 UserInfo23->usri23_name = Ptr;
1161
1162 memcpy(UserInfo23->usri23_name,
1163 UserInfo->UserName.Buffer,
1164 UserInfo->UserName.Length);
1165 UserInfo23->usri23_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1166
1167 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
1168
1169 UserInfo23->usri23_full_name = Ptr;
1170 memcpy(UserInfo23->usri23_full_name,
1171 UserInfo->FullName.Buffer,
1172 UserInfo->FullName.Length);
1173 UserInfo23->usri23_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1174 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
1175
1176 UserInfo23->usri23_comment = Ptr;
1177 memcpy(UserInfo23->usri23_comment,
1178 UserInfo->AdminComment.Buffer,
1179 UserInfo->AdminComment.Length);
1180 UserInfo23->usri23_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
1181 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
1182
1183 UserInfo23->usri23_flags = GetAccountFlags(UserInfo->UserAccountControl,
1184 Dacl);
1185
1186 /* FIXME: usri23_user_sid */
1187 break;
1188 }
1189
1190 done:
1191 if (UserInfo != NULL)
1192 FreeUserInfo(UserInfo);
1193
1194 if (Dacl != NULL)
1195 HeapFree(GetProcessHeap(), 0, Dacl);
1196
1197 if (ApiStatus == NERR_Success)
1198 {
1199 *Buffer = LocalBuffer;
1200 }
1201 else
1202 {
1203 if (LocalBuffer != NULL)
1204 NetApiBufferFree(LocalBuffer);
1205 }
1206
1207 return ApiStatus;
1208 }
1209
1210
1211 static
1212 NET_API_STATUS
1213 SetUserInfo(SAM_HANDLE UserHandle,
1214 LPBYTE UserInfo,
1215 DWORD Level)
1216 {
1217 USER_ALL_INFORMATION UserAllInfo;
1218 PUSER_INFO_0 UserInfo0;
1219 PUSER_INFO_1 UserInfo1;
1220 PUSER_INFO_2 UserInfo2;
1221 PUSER_INFO_3 UserInfo3;
1222 PUSER_INFO_4 UserInfo4;
1223 PUSER_INFO_22 UserInfo22;
1224 PUSER_INFO_1003 UserInfo1003;
1225 PUSER_INFO_1006 UserInfo1006;
1226 PUSER_INFO_1007 UserInfo1007;
1227 PUSER_INFO_1008 UserInfo1008;
1228 PUSER_INFO_1009 UserInfo1009;
1229 PUSER_INFO_1011 UserInfo1011;
1230 PUSER_INFO_1012 UserInfo1012;
1231 PUSER_INFO_1013 UserInfo1013;
1232 PUSER_INFO_1014 UserInfo1014;
1233 PUSER_INFO_1017 UserInfo1017;
1234 PUSER_INFO_1018 UserInfo1018;
1235 PUSER_INFO_1024 UserInfo1024;
1236 PUSER_INFO_1025 UserInfo1025;
1237 PUSER_INFO_1051 UserInfo1051;
1238 PUSER_INFO_1052 UserInfo1052;
1239 PUSER_INFO_1053 UserInfo1053;
1240 PACL Dacl = NULL;
1241 NET_API_STATUS ApiStatus = NERR_Success;
1242 NTSTATUS Status = STATUS_SUCCESS;
1243
1244 ZeroMemory(&UserAllInfo, sizeof(USER_ALL_INFORMATION));
1245
1246 if ((Level == 1) || (Level == 2) || (Level == 3) ||
1247 (Level == 4) || (Level == 22) || (Level == 1008))
1248 {
1249 ApiStatus = GetUserDacl(UserHandle, &Dacl);
1250 if (ApiStatus != NERR_Success)
1251 goto done;
1252 }
1253
1254 switch (Level)
1255 {
1256 case 0:
1257 UserInfo0 = (PUSER_INFO_0)UserInfo;
1258
1259 RtlInitUnicodeString(&UserAllInfo.UserName,
1260 UserInfo0->usri0_name);
1261
1262 UserAllInfo.WhichFields |= USER_ALL_USERNAME;
1263 break;
1264
1265 case 1:
1266 UserInfo1 = (PUSER_INFO_1)UserInfo;
1267
1268 // usri1_name ignored
1269
1270 if (UserInfo1->usri1_password != NULL)
1271 {
1272 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1273 UserInfo1->usri1_password);
1274 UserAllInfo.NtPasswordPresent = TRUE;
1275 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1276 }
1277
1278 // usri1_password_age ignored
1279
1280 // UserInfo1->usri1_priv
1281
1282 if (UserInfo1->usri1_home_dir != NULL)
1283 {
1284 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1285 UserInfo1->usri1_home_dir);
1286 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1287 }
1288
1289 if (UserInfo1->usri1_comment != NULL)
1290 {
1291 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1292 UserInfo1->usri1_comment);
1293 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1294 }
1295
1296 ChangeUserDacl(Dacl, UserInfo1->usri1_flags);
1297 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1->usri1_flags);
1298 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1299
1300 if (UserInfo1->usri1_script_path != NULL)
1301 {
1302 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1303 UserInfo1->usri1_script_path);
1304 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1305 }
1306 break;
1307
1308 case 2:
1309 UserInfo2 = (PUSER_INFO_2)UserInfo;
1310
1311 // usri2_name ignored
1312
1313 if (UserInfo2->usri2_password != NULL)
1314 {
1315 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1316 UserInfo2->usri2_password);
1317 UserAllInfo.NtPasswordPresent = TRUE;
1318 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1319 }
1320
1321 // usri2_password_age ignored
1322
1323 // UserInfo2->usri2_priv;
1324
1325 if (UserInfo2->usri2_home_dir != NULL)
1326 {
1327 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1328 UserInfo2->usri2_home_dir);
1329 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1330 }
1331
1332 if (UserInfo2->usri2_comment != NULL)
1333 {
1334 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1335 UserInfo2->usri2_comment);
1336 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1337 }
1338
1339 ChangeUserDacl(Dacl, UserInfo2->usri2_flags);
1340 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo2->usri2_flags);
1341 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1342
1343 if (UserInfo2->usri2_script_path != NULL)
1344 {
1345 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1346 UserInfo2->usri2_script_path);
1347 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1348 }
1349
1350 // UserInfo2->usri2_auth_flags;
1351
1352 if (UserInfo2->usri2_full_name != NULL)
1353 {
1354 RtlInitUnicodeString(&UserAllInfo.FullName,
1355 UserInfo2->usri2_full_name);
1356 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1357 }
1358
1359 if (UserInfo2->usri2_usr_comment != NULL)
1360 {
1361 RtlInitUnicodeString(&UserAllInfo.UserComment,
1362 UserInfo2->usri2_usr_comment);
1363 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1364 }
1365
1366 if (UserInfo2->usri2_parms != NULL)
1367 {
1368 RtlInitUnicodeString(&UserAllInfo.Parameters,
1369 UserInfo2->usri2_parms);
1370 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1371 }
1372
1373 if (UserInfo2->usri2_workstations != NULL)
1374 {
1375 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1376 UserInfo2->usri2_workstations);
1377 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1378 }
1379
1380 // usri2_last_logon ignored
1381 // usri2_last_logoff ignored
1382
1383 if (UserInfo2->usri2_acct_expires == TIMEQ_FOREVER)
1384 {
1385 UserAllInfo.AccountExpires.LowPart = 0;
1386 UserAllInfo.AccountExpires.HighPart = 0;
1387 }
1388 else
1389 {
1390 RtlSecondsSince1970ToTime(UserInfo2->usri2_acct_expires,
1391 &UserAllInfo.AccountExpires);
1392 }
1393 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1394
1395 // usri2_max_storage ignored
1396
1397 // UserInfo2->usri2_units_per_week;
1398 // UserInfo2->usri2_logon_hours;
1399
1400 // usri2_bad_pw_count ignored
1401 // usri2_num_logons ignored
1402 // usri2_logon_server ignored
1403
1404 UserAllInfo.CountryCode = UserInfo2->usri2_country_code;
1405 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1406
1407 UserAllInfo.CodePage = UserInfo2->usri2_code_page;
1408 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1409 break;
1410
1411 case 3:
1412 UserInfo3 = (PUSER_INFO_3)UserInfo;
1413
1414 // usri3_name ignored
1415
1416 if (UserInfo3->usri3_password != NULL)
1417 {
1418 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1419 UserInfo3->usri3_password);
1420 UserAllInfo.NtPasswordPresent = TRUE;
1421 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1422 }
1423
1424 // usri3_password_age ignored
1425
1426 // UserInfo3->usri3_priv;
1427
1428 if (UserInfo3->usri3_home_dir != NULL)
1429 {
1430 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1431 UserInfo3->usri3_home_dir);
1432 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1433 }
1434
1435 if (UserInfo3->usri3_comment != NULL)
1436 {
1437 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1438 UserInfo3->usri3_comment);
1439 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1440 }
1441
1442 ChangeUserDacl(Dacl, UserInfo3->usri3_flags);
1443 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo3->usri3_flags);
1444 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1445
1446 if (UserInfo3->usri3_script_path != NULL)
1447 {
1448 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1449 UserInfo3->usri3_script_path);
1450 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1451 }
1452
1453 // UserInfo3->usri3_auth_flags;
1454
1455 if (UserInfo3->usri3_full_name != NULL)
1456 {
1457 RtlInitUnicodeString(&UserAllInfo.FullName,
1458 UserInfo3->usri3_full_name);
1459 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1460 }
1461
1462 if (UserInfo3->usri3_usr_comment != NULL)
1463 {
1464 RtlInitUnicodeString(&UserAllInfo.UserComment,
1465 UserInfo3->usri3_usr_comment);
1466 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1467 }
1468
1469 if (UserInfo3->usri3_parms != NULL)
1470 {
1471 RtlInitUnicodeString(&UserAllInfo.Parameters,
1472 UserInfo3->usri3_parms);
1473 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1474 }
1475
1476 if (UserInfo3->usri3_workstations != NULL)
1477 {
1478 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1479 UserInfo3->usri3_workstations);
1480 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1481 }
1482
1483 // usri3_last_logon ignored
1484 // usri3_last_logoff ignored
1485
1486 if (UserInfo3->usri3_acct_expires == TIMEQ_FOREVER)
1487 {
1488 UserAllInfo.AccountExpires.LowPart = 0;
1489 UserAllInfo.AccountExpires.HighPart = 0;
1490 }
1491 else
1492 {
1493 RtlSecondsSince1970ToTime(UserInfo3->usri3_acct_expires,
1494 &UserAllInfo.AccountExpires);
1495 }
1496 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1497
1498 // usri3_max_storage ignored
1499
1500 // UserInfo3->usri3_units_per_week;
1501 // UserInfo3->usri3_logon_hours;
1502
1503 // usri3_bad_pw_count ignored
1504 // usri3_num_logons ignored
1505 // usri3_logon_server ignored
1506
1507 UserAllInfo.CountryCode = UserInfo3->usri3_country_code;
1508 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1509
1510 UserAllInfo.CodePage = UserInfo3->usri3_code_page;
1511 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1512
1513 // usri3_user_id ignored
1514
1515 UserAllInfo.PrimaryGroupId = UserInfo3->usri3_primary_group_id;
1516 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1517
1518 if (UserInfo3->usri3_profile != NULL)
1519 {
1520 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1521 UserInfo3->usri3_profile);
1522 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1523 }
1524
1525 if (UserInfo3->usri3_home_dir_drive != NULL)
1526 {
1527 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1528 UserInfo3->usri3_home_dir_drive);
1529 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1530 }
1531
1532 UserAllInfo.PasswordExpired = (UserInfo3->usri3_password_expired != 0);
1533 UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1534 break;
1535
1536 case 4:
1537 UserInfo4 = (PUSER_INFO_4)UserInfo;
1538
1539 // usri4_name ignored
1540
1541 if (UserInfo4->usri4_password != NULL)
1542 {
1543 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1544 UserInfo4->usri4_password);
1545 UserAllInfo.NtPasswordPresent = TRUE;
1546 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1547 }
1548
1549 // usri4_password_age ignored
1550
1551 // UserInfo3->usri4_priv;
1552
1553 if (UserInfo4->usri4_home_dir != NULL)
1554 {
1555 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1556 UserInfo4->usri4_home_dir);
1557 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1558 }
1559
1560 if (UserInfo4->usri4_comment != NULL)
1561 {
1562 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1563 UserInfo4->usri4_comment);
1564 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1565 }
1566
1567 ChangeUserDacl(Dacl, UserInfo4->usri4_flags);
1568 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo4->usri4_flags);
1569 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1570
1571 if (UserInfo4->usri4_script_path != NULL)
1572 {
1573 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1574 UserInfo4->usri4_script_path);
1575 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1576 }
1577
1578 // UserInfo4->usri4_auth_flags;
1579
1580 if (UserInfo4->usri4_full_name != NULL)
1581 {
1582 RtlInitUnicodeString(&UserAllInfo.FullName,
1583 UserInfo4->usri4_full_name);
1584 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1585 }
1586
1587 if (UserInfo4->usri4_usr_comment != NULL)
1588 {
1589 RtlInitUnicodeString(&UserAllInfo.UserComment,
1590 UserInfo4->usri4_usr_comment);
1591 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1592 }
1593
1594 if (UserInfo4->usri4_parms != NULL)
1595 {
1596 RtlInitUnicodeString(&UserAllInfo.Parameters,
1597 UserInfo4->usri4_parms);
1598 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1599 }
1600
1601 if (UserInfo4->usri4_workstations != NULL)
1602 {
1603 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1604 UserInfo4->usri4_workstations);
1605 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1606 }
1607
1608 // usri4_last_logon ignored
1609 // usri4_last_logoff ignored
1610
1611 if (UserInfo4->usri4_acct_expires == TIMEQ_FOREVER)
1612 {
1613 UserAllInfo.AccountExpires.LowPart = 0;
1614 UserAllInfo.AccountExpires.HighPart = 0;
1615 }
1616 else
1617 {
1618 RtlSecondsSince1970ToTime(UserInfo4->usri4_acct_expires,
1619 &UserAllInfo.AccountExpires);
1620 }
1621 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1622
1623 // usri4_max_storage ignored
1624
1625 // UserInfo4->usri4_units_per_week;
1626 // UserInfo4->usri4_logon_hours;
1627
1628 // usri4_bad_pw_count ignored
1629 // usri4_num_logons ignored
1630 // usri4_logon_server ignored
1631
1632 UserAllInfo.CountryCode = UserInfo4->usri4_country_code;
1633 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1634
1635 UserAllInfo.CodePage = UserInfo4->usri4_code_page;
1636 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1637
1638 // usri4_user_sid ignored
1639
1640 UserAllInfo.PrimaryGroupId = UserInfo4->usri4_primary_group_id;
1641 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1642
1643 if (UserInfo4->usri4_profile != NULL)
1644 {
1645 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1646 UserInfo4->usri4_profile);
1647 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1648 }
1649
1650 if (UserInfo4->usri4_home_dir_drive != NULL)
1651 {
1652 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1653 UserInfo4->usri4_home_dir_drive);
1654 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1655 }
1656
1657 UserAllInfo.PasswordExpired = (UserInfo4->usri4_password_expired != 0);
1658 UserAllInfo.WhichFields |= USER_ALL_PASSWORDEXPIRED;
1659 break;
1660
1661 // case 21:
1662 // break;
1663
1664 case 22:
1665 UserInfo22 = (PUSER_INFO_22)UserInfo;
1666
1667 // usri22_name ignored
1668
1669 // UserInfo22->usri22_password[ENCRYPTED_PWLEN];
1670
1671 // usri22_password_age ignored
1672
1673 // UserInfo3->usri3_priv;
1674
1675 if (UserInfo22->usri22_home_dir != NULL)
1676 {
1677 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1678 UserInfo22->usri22_home_dir);
1679 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1680 }
1681
1682 if (UserInfo22->usri22_comment != NULL)
1683 {
1684 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1685 UserInfo22->usri22_comment);
1686 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1687 }
1688
1689 ChangeUserDacl(Dacl, UserInfo22->usri22_flags);
1690 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo22->usri22_flags);
1691 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1692
1693 if (UserInfo22->usri22_script_path != NULL)
1694 {
1695 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1696 UserInfo22->usri22_script_path);
1697 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1698 }
1699
1700 // UserInfo22->usri22_auth_flags;
1701
1702 if (UserInfo22->usri22_full_name != NULL)
1703 {
1704 RtlInitUnicodeString(&UserAllInfo.FullName,
1705 UserInfo22->usri22_full_name);
1706 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1707 }
1708
1709 if (UserInfo22->usri22_usr_comment != NULL)
1710 {
1711 RtlInitUnicodeString(&UserAllInfo.UserComment,
1712 UserInfo22->usri22_usr_comment);
1713 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1714 }
1715
1716 if (UserInfo22->usri22_parms != NULL)
1717 {
1718 RtlInitUnicodeString(&UserAllInfo.Parameters,
1719 UserInfo22->usri22_parms);
1720 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1721 }
1722
1723 if (UserInfo22->usri22_workstations != NULL)
1724 {
1725 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1726 UserInfo22->usri22_workstations);
1727 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1728 }
1729
1730 // usri22_last_logon ignored
1731 // usri22_last_logoff ignored
1732
1733 if (UserInfo22->usri22_acct_expires == TIMEQ_FOREVER)
1734 {
1735 UserAllInfo.AccountExpires.LowPart = 0;
1736 UserAllInfo.AccountExpires.HighPart = 0;
1737 }
1738 else
1739 {
1740 RtlSecondsSince1970ToTime(UserInfo22->usri22_acct_expires,
1741 &UserAllInfo.AccountExpires);
1742 }
1743 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1744
1745 // usri22_max_storage ignored
1746
1747 // UserInfo22->usri22_units_per_week;
1748 // UserInfo22->usri22_logon_hours;
1749
1750 // usri22_bad_pw_count ignored
1751 // usri22_num_logons ignored
1752 // usri22_logon_server ignored
1753
1754 UserAllInfo.CountryCode = UserInfo22->usri22_country_code;
1755 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1756
1757 UserAllInfo.CodePage = UserInfo22->usri22_code_page;
1758 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1759 break;
1760
1761 case 1003:
1762 UserInfo1003 = (PUSER_INFO_1003)UserInfo;
1763
1764 if (UserInfo1003->usri1003_password != NULL)
1765 {
1766 RtlInitUnicodeString(&UserAllInfo.NtPassword,
1767 UserInfo1003->usri1003_password);
1768 UserAllInfo.NtPasswordPresent = TRUE;
1769 UserAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
1770 }
1771 break;
1772
1773 // case 1005:
1774 // break;
1775
1776 case 1006:
1777 UserInfo1006 = (PUSER_INFO_1006)UserInfo;
1778
1779 if (UserInfo1006->usri1006_home_dir != NULL)
1780 {
1781 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
1782 UserInfo1006->usri1006_home_dir);
1783 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORY;
1784 }
1785 break;
1786
1787 case 1007:
1788 UserInfo1007 = (PUSER_INFO_1007)UserInfo;
1789
1790 if (UserInfo1007->usri1007_comment != NULL)
1791 {
1792 RtlInitUnicodeString(&UserAllInfo.AdminComment,
1793 UserInfo1007->usri1007_comment);
1794 UserAllInfo.WhichFields |= USER_ALL_ADMINCOMMENT;
1795 }
1796 break;
1797
1798 case 1008:
1799 UserInfo1008 = (PUSER_INFO_1008)UserInfo;
1800 ChangeUserDacl(Dacl, UserInfo1008->usri1008_flags);
1801 UserAllInfo.UserAccountControl = GetAccountControl(UserInfo1008->usri1008_flags);
1802 UserAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
1803 break;
1804
1805 case 1009:
1806 UserInfo1009 = (PUSER_INFO_1009)UserInfo;
1807
1808 if (UserInfo1009->usri1009_script_path != NULL)
1809 {
1810 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
1811 UserInfo1009->usri1009_script_path);
1812 UserAllInfo.WhichFields |= USER_ALL_SCRIPTPATH;
1813 }
1814 break;
1815
1816 // case 1010:
1817 // break;
1818
1819 case 1011:
1820 UserInfo1011 = (PUSER_INFO_1011)UserInfo;
1821
1822 if (UserInfo1011->usri1011_full_name != NULL)
1823 {
1824 RtlInitUnicodeString(&UserAllInfo.FullName,
1825 UserInfo1011->usri1011_full_name);
1826 UserAllInfo.WhichFields |= USER_ALL_FULLNAME;
1827 }
1828 break;
1829
1830 case 1012:
1831 UserInfo1012 = (PUSER_INFO_1012)UserInfo;
1832
1833 if (UserInfo1012->usri1012_usr_comment != NULL)
1834 {
1835 RtlInitUnicodeString(&UserAllInfo.UserComment,
1836 UserInfo1012->usri1012_usr_comment);
1837 UserAllInfo.WhichFields |= USER_ALL_USERCOMMENT;
1838 }
1839 break;
1840
1841 case 1013:
1842 UserInfo1013 = (PUSER_INFO_1013)UserInfo;
1843
1844 if (UserInfo1013->usri1013_parms != NULL)
1845 {
1846 RtlInitUnicodeString(&UserAllInfo.Parameters,
1847 UserInfo1013->usri1013_parms);
1848 UserAllInfo.WhichFields |= USER_ALL_PARAMETERS;
1849 }
1850 break;
1851
1852 case 1014:
1853 UserInfo1014 = (PUSER_INFO_1014)UserInfo;
1854
1855 if (UserInfo1014->usri1014_workstations != NULL)
1856 {
1857 RtlInitUnicodeString(&UserAllInfo.WorkStations,
1858 UserInfo1014->usri1014_workstations);
1859 UserAllInfo.WhichFields |= USER_ALL_WORKSTATIONS;
1860 }
1861 break;
1862
1863 case 1017:
1864 UserInfo1017 = (PUSER_INFO_1017)UserInfo;
1865
1866 if (UserInfo1017->usri1017_acct_expires == TIMEQ_FOREVER)
1867 {
1868 UserAllInfo.AccountExpires.LowPart = 0;
1869 UserAllInfo.AccountExpires.HighPart = 0;
1870 }
1871 else
1872 {
1873 RtlSecondsSince1970ToTime(UserInfo1017->usri1017_acct_expires,
1874 &UserAllInfo.AccountExpires);
1875 }
1876 UserAllInfo.WhichFields |= USER_ALL_ACCOUNTEXPIRES;
1877 break;
1878
1879 case 1018:
1880 UserInfo1018 = (PUSER_INFO_1018)UserInfo;
1881
1882 if (UserInfo1018->usri1018_max_storage != USER_MAXSTORAGE_UNLIMITED)
1883 {
1884 // FIXME: Report error
1885 return ERROR_INVALID_PARAMETER;
1886 }
1887 break;
1888
1889 // case 1020:
1890 // break;
1891
1892 case 1024:
1893 UserInfo1024 = (PUSER_INFO_1024)UserInfo;
1894
1895 UserAllInfo.CountryCode = UserInfo1024->usri1024_country_code;
1896 UserAllInfo.WhichFields |= USER_ALL_COUNTRYCODE;
1897 break;
1898
1899 case 1025:
1900 UserInfo1025 = (PUSER_INFO_1025)UserInfo;
1901
1902 UserAllInfo.CodePage = UserInfo1025->usri1025_code_page;
1903 UserAllInfo.WhichFields |= USER_ALL_CODEPAGE;
1904 break;
1905
1906 case 1051:
1907 UserInfo1051 = (PUSER_INFO_1051)UserInfo;
1908
1909 UserAllInfo.PrimaryGroupId = UserInfo1051->usri1051_primary_group_id;
1910 UserAllInfo.WhichFields |= USER_ALL_PRIMARYGROUPID;
1911 break;
1912
1913 case 1052:
1914 UserInfo1052 = (PUSER_INFO_1052)UserInfo;
1915
1916 if (UserInfo1052->usri1052_profile != NULL)
1917 {
1918 RtlInitUnicodeString(&UserAllInfo.ProfilePath,
1919 UserInfo1052->usri1052_profile);
1920 UserAllInfo.WhichFields |= USER_ALL_PROFILEPATH;
1921 }
1922 break;
1923
1924 case 1053:
1925 UserInfo1053 = (PUSER_INFO_1053)UserInfo;
1926
1927 if (UserInfo1053->usri1053_home_dir_drive != NULL)
1928 {
1929 RtlInitUnicodeString(&UserAllInfo.HomeDirectoryDrive,
1930 UserInfo1053->usri1053_home_dir_drive);
1931 UserAllInfo.WhichFields |= USER_ALL_HOMEDIRECTORYDRIVE;
1932 }
1933 break;
1934
1935 default:
1936 ERR("Unsupported level %lu!\n", Level);
1937 return ERROR_INVALID_PARAMETER;
1938 }
1939
1940 Status = SamSetInformationUser(UserHandle,
1941 UserAllInformation,
1942 &UserAllInfo);
1943 if (!NT_SUCCESS(Status))
1944 {
1945 ERR("SamSetInformationUser failed (Status %08lx)\n", Status);
1946 ApiStatus = NetpNtStatusToApiStatus(Status);
1947 goto done;
1948 }
1949
1950 done:
1951 if (Dacl != NULL)
1952 HeapFree(GetProcessHeap(), 0, Dacl);
1953
1954 return ApiStatus;
1955 }
1956
1957
1958 static
1959 NET_API_STATUS
1960 OpenUserByName(SAM_HANDLE DomainHandle,
1961 PUNICODE_STRING UserName,
1962 ULONG DesiredAccess,
1963 PSAM_HANDLE UserHandle)
1964 {
1965 PULONG RelativeIds = NULL;
1966 PSID_NAME_USE Use = NULL;
1967 NET_API_STATUS ApiStatus = NERR_Success;
1968 NTSTATUS Status = STATUS_SUCCESS;
1969
1970 /* Get the RID for the given user name */
1971 Status = SamLookupNamesInDomain(DomainHandle,
1972 1,
1973 UserName,
1974 &RelativeIds,
1975 &Use);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
1979 return NetpNtStatusToApiStatus(Status);
1980 }
1981
1982 /* Fail, if it is not an alias account */
1983 if (Use[0] != SidTypeUser)
1984 {
1985 ERR("Object is not a user!\n");
1986 ApiStatus = NERR_GroupNotFound;
1987 goto done;
1988 }
1989
1990 /* Open the alias account */
1991 Status = SamOpenUser(DomainHandle,
1992 DesiredAccess,
1993 RelativeIds[0],
1994 UserHandle);
1995 if (!NT_SUCCESS(Status))
1996 {
1997 ERR("SamOpenUser failed (Status %08lx)\n", Status);
1998 ApiStatus = NetpNtStatusToApiStatus(Status);
1999 goto done;
2000 }
2001
2002 done:
2003 if (RelativeIds != NULL)
2004 SamFreeMemory(RelativeIds);
2005
2006 if (Use != NULL)
2007 SamFreeMemory(Use);
2008
2009 return ApiStatus;
2010 }
2011
2012
2013 /************************************************************
2014 * NetUserAdd (NETAPI32.@)
2015 */
2016 NET_API_STATUS
2017 WINAPI
2018 NetUserAdd(LPCWSTR servername,
2019 DWORD level,
2020 LPBYTE bufptr,
2021 LPDWORD parm_err)
2022 {
2023 UNICODE_STRING ServerName;
2024 UNICODE_STRING UserName;
2025 SAM_HANDLE ServerHandle = NULL;
2026 SAM_HANDLE DomainHandle = NULL;
2027 SAM_HANDLE UserHandle = NULL;
2028 ULONG GrantedAccess;
2029 ULONG RelativeId;
2030 NET_API_STATUS ApiStatus = NERR_Success;
2031 NTSTATUS Status = STATUS_SUCCESS;
2032
2033 TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr, parm_err);
2034
2035 /* Check the info level */
2036 switch (level)
2037 {
2038 case 1:
2039 case 2:
2040 case 3:
2041 case 4:
2042 break;
2043
2044 default:
2045 return ERROR_INVALID_LEVEL;
2046 }
2047
2048 if (servername != NULL)
2049 RtlInitUnicodeString(&ServerName, servername);
2050
2051 /* Connect to the SAM Server */
2052 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2053 &ServerHandle,
2054 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2055 NULL);
2056 if (!NT_SUCCESS(Status))
2057 {
2058 ERR("SamConnect failed (Status %08lx)\n", Status);
2059 ApiStatus = NetpNtStatusToApiStatus(Status);
2060 goto done;
2061 }
2062
2063 /* Open the Account Domain */
2064 Status = OpenAccountDomain(ServerHandle,
2065 (servername != NULL) ? &ServerName : NULL,
2066 DOMAIN_CREATE_USER | DOMAIN_LOOKUP | DOMAIN_READ_PASSWORD_PARAMETERS,
2067 &DomainHandle);
2068 if (!NT_SUCCESS(Status))
2069 {
2070 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2071 ApiStatus = NetpNtStatusToApiStatus(Status);
2072 goto done;
2073 }
2074
2075 /* Initialize the user name string */
2076 RtlInitUnicodeString(&UserName,
2077 ((PUSER_INFO_1)bufptr)->usri1_name);
2078
2079 /* Create the user account */
2080 Status = SamCreateUser2InDomain(DomainHandle,
2081 &UserName,
2082 USER_NORMAL_ACCOUNT,
2083 USER_ALL_ACCESS | DELETE | WRITE_DAC,
2084 &UserHandle,
2085 &GrantedAccess,
2086 &RelativeId);
2087 if (!NT_SUCCESS(Status))
2088 {
2089 ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status);
2090 ApiStatus = NetpNtStatusToApiStatus(Status);
2091 goto done;
2092 }
2093
2094 /* Set user information */
2095 ApiStatus = SetUserInfo(UserHandle,
2096 bufptr,
2097 level);
2098 if (ApiStatus != NERR_Success)
2099 {
2100 ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
2101 goto done;
2102 }
2103
2104 done:
2105 if (UserHandle != NULL)
2106 {
2107 if (ApiStatus != NERR_Success)
2108 SamDeleteUser(UserHandle);
2109 else
2110 SamCloseHandle(UserHandle);
2111 }
2112
2113 if (DomainHandle != NULL)
2114 SamCloseHandle(DomainHandle);
2115
2116 if (ServerHandle != NULL)
2117 SamCloseHandle(ServerHandle);
2118
2119 return ApiStatus;
2120 }
2121
2122
2123 /******************************************************************************
2124 * NetUserChangePassword (NETAPI32.@)
2125 * PARAMS
2126 * domainname [I] Optional. Domain on which the user resides or the logon
2127 * domain of the current user if NULL.
2128 * username [I] Optional. Username to change the password for or the name
2129 * of the current user if NULL.
2130 * oldpassword [I] The user's current password.
2131 * newpassword [I] The password that the user will be changed to using.
2132 *
2133 * RETURNS
2134 * Success: NERR_Success.
2135 * Failure: NERR_* failure code or win error code.
2136 *
2137 */
2138 NET_API_STATUS
2139 WINAPI
2140 NetUserChangePassword(LPCWSTR domainname,
2141 LPCWSTR username,
2142 LPCWSTR oldpassword,
2143 LPCWSTR newpassword)
2144 {
2145 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
2146 PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
2147 ULONG RequestBufferSize;
2148 ULONG ResponseBufferSize = 0;
2149 LPWSTR Ptr;
2150 ANSI_STRING PackageName;
2151 ULONG AuthenticationPackage = 0;
2152 HANDLE LsaHandle = NULL;
2153 NET_API_STATUS ApiStatus = NERR_Success;
2154 NTSTATUS Status = STATUS_SUCCESS;
2155 NTSTATUS ProtocolStatus;
2156
2157 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
2158
2159 /* FIXME: handle null domain or user name */
2160
2161 /* Check the parameters */
2162 if ((oldpassword == NULL) ||
2163 (newpassword == NULL))
2164 return ERROR_INVALID_PARAMETER;
2165
2166 /* Connect to the LSA server */
2167 Status = LsaConnectUntrusted(&LsaHandle);
2168 if (!NT_SUCCESS(Status))
2169 return NetpNtStatusToApiStatus(Status);
2170
2171 /* Get the authentication package ID */
2172 RtlInitAnsiString(&PackageName,
2173 MSV1_0_PACKAGE_NAME);
2174
2175 Status = LsaLookupAuthenticationPackage(LsaHandle,
2176 &PackageName,
2177 &AuthenticationPackage);
2178 if (!NT_SUCCESS(Status))
2179 {
2180 ApiStatus = NetpNtStatusToApiStatus(Status);
2181 goto done;
2182 }
2183
2184 /* Calculate the request buffer size */
2185 RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
2186 ((wcslen(domainname) + 1) * sizeof(WCHAR)) +
2187 ((wcslen(username) + 1) * sizeof(WCHAR)) +
2188 ((wcslen(oldpassword) + 1) * sizeof(WCHAR)) +
2189 ((wcslen(newpassword) + 1) * sizeof(WCHAR));
2190
2191 /* Allocate the request buffer */
2192 ApiStatus = NetApiBufferAllocate(RequestBufferSize,
2193 (PVOID*)&RequestBuffer);
2194 if (ApiStatus != NERR_Success)
2195 goto done;
2196
2197 /* Initialize the request buffer */
2198 RequestBuffer->MessageType = MsV1_0ChangePassword;
2199 RequestBuffer->Impersonating = TRUE;
2200
2201 Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
2202
2203 /* Pack the domain name */
2204 RequestBuffer->DomainName.Length = wcslen(domainname) * sizeof(WCHAR);
2205 RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
2206 RequestBuffer->DomainName.Buffer = Ptr;
2207
2208 RtlCopyMemory(RequestBuffer->DomainName.Buffer,
2209 domainname,
2210 RequestBuffer->DomainName.MaximumLength);
2211
2212 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
2213
2214 /* Pack the user name */
2215 RequestBuffer->AccountName.Length = wcslen(username) * sizeof(WCHAR);
2216 RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
2217 RequestBuffer->AccountName.Buffer = Ptr;
2218
2219 RtlCopyMemory(RequestBuffer->AccountName.Buffer,
2220 username,
2221 RequestBuffer->AccountName.MaximumLength);
2222
2223 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
2224
2225 /* Pack the old password */
2226 RequestBuffer->OldPassword.Length = wcslen(oldpassword) * sizeof(WCHAR);
2227 RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
2228 RequestBuffer->OldPassword.Buffer = Ptr;
2229
2230 RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
2231 oldpassword,
2232 RequestBuffer->OldPassword.MaximumLength);
2233
2234 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
2235
2236 /* Pack the new password */
2237 RequestBuffer->NewPassword.Length = wcslen(newpassword) * sizeof(WCHAR);
2238 RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
2239 RequestBuffer->NewPassword.Buffer = Ptr;
2240
2241 RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
2242 newpassword,
2243 RequestBuffer->NewPassword.MaximumLength);
2244
2245 /* Call the authentication package */
2246 Status = LsaCallAuthenticationPackage(LsaHandle,
2247 AuthenticationPackage,
2248 RequestBuffer,
2249 RequestBufferSize,
2250 (PVOID*)&ResponseBuffer,
2251 &ResponseBufferSize,
2252 &ProtocolStatus);
2253 if (!NT_SUCCESS(Status))
2254 {
2255 ApiStatus = NetpNtStatusToApiStatus(Status);
2256 goto done;
2257 }
2258
2259 if (!NT_SUCCESS(ProtocolStatus))
2260 {
2261 ApiStatus = NetpNtStatusToApiStatus(ProtocolStatus);
2262 goto done;
2263 }
2264
2265 done:
2266 if (RequestBuffer != NULL)
2267 NetApiBufferFree(RequestBuffer);
2268
2269 if (ResponseBuffer != NULL)
2270 LsaFreeReturnBuffer(ResponseBuffer);
2271
2272 if (LsaHandle != NULL)
2273 NtClose(LsaHandle);
2274
2275 return ApiStatus;
2276 }
2277
2278
2279 /************************************************************
2280 * NetUserDel (NETAPI32.@)
2281 */
2282 NET_API_STATUS
2283 WINAPI
2284 NetUserDel(LPCWSTR servername,
2285 LPCWSTR username)
2286 {
2287 UNICODE_STRING ServerName;
2288 UNICODE_STRING UserName;
2289 SAM_HANDLE ServerHandle = NULL;
2290 SAM_HANDLE DomainHandle = NULL;
2291 SAM_HANDLE UserHandle = NULL;
2292 NET_API_STATUS ApiStatus = NERR_Success;
2293 NTSTATUS Status = STATUS_SUCCESS;
2294
2295 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
2296
2297 if (servername != NULL)
2298 RtlInitUnicodeString(&ServerName, servername);
2299
2300 RtlInitUnicodeString(&UserName, username);
2301
2302 /* Connect to the SAM Server */
2303 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2304 &ServerHandle,
2305 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2306 NULL);
2307 if (!NT_SUCCESS(Status))
2308 {
2309 ERR("SamConnect failed (Status %08lx)\n", Status);
2310 ApiStatus = NetpNtStatusToApiStatus(Status);
2311 goto done;
2312 }
2313
2314 /* Open the Builtin Domain */
2315 Status = OpenBuiltinDomain(ServerHandle,
2316 DOMAIN_LOOKUP,
2317 &DomainHandle);
2318 if (!NT_SUCCESS(Status))
2319 {
2320 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2321 ApiStatus = NetpNtStatusToApiStatus(Status);
2322 goto done;
2323 }
2324
2325 /* Open the user account in the builtin domain */
2326 ApiStatus = OpenUserByName(DomainHandle,
2327 &UserName,
2328 DELETE,
2329 &UserHandle);
2330 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
2331 {
2332 TRACE("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2333 goto done;
2334 }
2335
2336 if (UserHandle == NULL)
2337 {
2338 if (DomainHandle != NULL)
2339 {
2340 SamCloseHandle(DomainHandle);
2341 DomainHandle = NULL;
2342 }
2343
2344 /* Open the Acount Domain */
2345 Status = OpenAccountDomain(ServerHandle,
2346 (servername != NULL) ? &ServerName : NULL,
2347 DOMAIN_LOOKUP,
2348 &DomainHandle);
2349 if (!NT_SUCCESS(Status))
2350 {
2351 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2352 ApiStatus = NetpNtStatusToApiStatus(Status);
2353 goto done;
2354 }
2355
2356 /* Open the user account in the account domain */
2357 ApiStatus = OpenUserByName(DomainHandle,
2358 &UserName,
2359 DELETE,
2360 &UserHandle);
2361 if (ApiStatus != NERR_Success)
2362 {
2363 ERR("OpenUserByName failed (ApiStatus %lu)\n", ApiStatus);
2364 if (ApiStatus == ERROR_NONE_MAPPED)
2365 ApiStatus = NERR_UserNotFound;
2366 goto done;
2367 }
2368 }
2369
2370 /* Delete the user */
2371 Status = SamDeleteUser(UserHandle);
2372 if (!NT_SUCCESS(Status))
2373 {
2374 ERR("SamDeleteUser failed (Status %08lx)\n", Status);
2375 ApiStatus = NetpNtStatusToApiStatus(Status);
2376 goto done;
2377 }
2378
2379 done:
2380 if (UserHandle != NULL)
2381 SamCloseHandle(UserHandle);
2382
2383 if (DomainHandle != NULL)
2384 SamCloseHandle(DomainHandle);
2385
2386 if (ServerHandle != NULL)
2387 SamCloseHandle(ServerHandle);
2388
2389 return ApiStatus;
2390 }
2391
2392
2393 /************************************************************
2394 * NetUserEnum (NETAPI32.@)
2395 */
2396 NET_API_STATUS
2397 WINAPI
2398 NetUserEnum(LPCWSTR servername,
2399 DWORD level,
2400 DWORD filter,
2401 LPBYTE* bufptr,
2402 DWORD prefmaxlen,
2403 LPDWORD entriesread,
2404 LPDWORD totalentries,
2405 LPDWORD resume_handle)
2406 {
2407 UNICODE_STRING ServerName;
2408 PSAM_RID_ENUMERATION CurrentUser;
2409 PENUM_CONTEXT EnumContext = NULL;
2410 LPVOID Buffer = NULL;
2411 ULONG i;
2412 SAM_HANDLE UserHandle = NULL;
2413 NET_API_STATUS ApiStatus = NERR_Success;
2414 NTSTATUS Status = STATUS_SUCCESS;
2415
2416 TRACE("(%s %d 0x%d %p %d %p %p %p)\n", debugstr_w(servername), level,
2417 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2418
2419 *entriesread = 0;
2420 *totalentries = 0;
2421 *bufptr = NULL;
2422
2423 if (servername != NULL)
2424 RtlInitUnicodeString(&ServerName, servername);
2425
2426 if (resume_handle != NULL && *resume_handle != 0)
2427 {
2428 EnumContext = (PENUM_CONTEXT)*resume_handle;
2429 }
2430 else
2431 {
2432 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
2433 if (ApiStatus != NERR_Success)
2434 goto done;
2435
2436 EnumContext->EnumerationContext = 0;
2437 EnumContext->Buffer = NULL;
2438 EnumContext->Count = 0;
2439 EnumContext->Index = 0;
2440 EnumContext->BuiltinDone = FALSE;
2441
2442 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2443 &EnumContext->ServerHandle,
2444 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2445 NULL);
2446 if (!NT_SUCCESS(Status))
2447 {
2448 ERR("SamConnect failed (Status %08lx)\n", Status);
2449 ApiStatus = NetpNtStatusToApiStatus(Status);
2450 goto done;
2451 }
2452
2453 Status = OpenAccountDomain(EnumContext->ServerHandle,
2454 (servername != NULL) ? &ServerName : NULL,
2455 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2456 &EnumContext->AccountDomainHandle);
2457 if (!NT_SUCCESS(Status))
2458 {
2459 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2460 ApiStatus = NetpNtStatusToApiStatus(Status);
2461 goto done;
2462 }
2463
2464 Status = OpenBuiltinDomain(EnumContext->ServerHandle,
2465 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2466 &EnumContext->BuiltinDomainHandle);
2467 if (!NT_SUCCESS(Status))
2468 {
2469 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2470 ApiStatus = NetpNtStatusToApiStatus(Status);
2471 goto done;
2472 }
2473 }
2474
2475 // while (TRUE)
2476 // {
2477 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
2478 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2479
2480 if (EnumContext->Index >= EnumContext->Count)
2481 {
2482 // if (EnumContext->BuiltinDone == TRUE)
2483 // {
2484 // ApiStatus = NERR_Success;
2485 // goto done;
2486 // }
2487
2488 TRACE("Calling SamEnumerateUsersInDomain\n");
2489 Status = SamEnumerateUsersInDomain(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2490 &EnumContext->EnumerationContext,
2491 0,
2492 (PVOID *)&EnumContext->Buffer,
2493 prefmaxlen,
2494 &EnumContext->Count);
2495
2496 TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
2497 if (!NT_SUCCESS(Status))
2498 {
2499 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status);
2500 ApiStatus = NetpNtStatusToApiStatus(Status);
2501 goto done;
2502 }
2503
2504 if (Status == STATUS_MORE_ENTRIES)
2505 {
2506 ApiStatus = NERR_BufTooSmall;
2507 goto done;
2508 }
2509 else
2510 {
2511 EnumContext->BuiltinDone = TRUE;
2512 }
2513 }
2514
2515 TRACE("EnumContext: %lu\n", EnumContext);
2516 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2517 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
2518
2519 /* Get a pointer to the current user */
2520 CurrentUser = &EnumContext->Buffer[EnumContext->Index];
2521
2522 TRACE("RID: %lu\n", CurrentUser->RelativeId);
2523
2524 Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2525 READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
2526 CurrentUser->RelativeId,
2527 &UserHandle);
2528 if (!NT_SUCCESS(Status))
2529 {
2530 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2531 ApiStatus = NetpNtStatusToApiStatus(Status);
2532 goto done;
2533 }
2534
2535 ApiStatus = BuildUserInfoBuffer(UserHandle,
2536 level,
2537 CurrentUser->RelativeId,
2538 &Buffer);
2539 if (ApiStatus != NERR_Success)
2540 {
2541 ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus);
2542 goto done;
2543 }
2544
2545 SamCloseHandle(UserHandle);
2546 UserHandle = NULL;
2547
2548 EnumContext->Index++;
2549
2550 (*entriesread)++;
2551 // }
2552
2553 done:
2554 if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count)
2555 ApiStatus = ERROR_MORE_DATA;
2556
2557 if (EnumContext != NULL)
2558 *totalentries = EnumContext->Count;
2559
2560 if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
2561 {
2562 if (EnumContext != NULL)
2563 {
2564 if (EnumContext->BuiltinDomainHandle != NULL)
2565 SamCloseHandle(EnumContext->BuiltinDomainHandle);
2566
2567 if (EnumContext->AccountDomainHandle != NULL)
2568 SamCloseHandle(EnumContext->AccountDomainHandle);
2569
2570 if (EnumContext->ServerHandle != NULL)
2571 SamCloseHandle(EnumContext->ServerHandle);
2572
2573 if (EnumContext->Buffer != NULL)
2574 {
2575 for (i = 0; i < EnumContext->Count; i++)
2576 {
2577 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
2578 }
2579
2580 SamFreeMemory(EnumContext->Buffer);
2581 }
2582
2583 NetApiBufferFree(EnumContext);
2584 EnumContext = NULL;
2585 }
2586 }
2587
2588 if (UserHandle != NULL)
2589 SamCloseHandle(UserHandle);
2590
2591 if (resume_handle != NULL)
2592 *resume_handle = (DWORD_PTR)EnumContext;
2593
2594 *bufptr = (LPBYTE)Buffer;
2595
2596 TRACE("return %lu\n", ApiStatus);
2597
2598 return ApiStatus;
2599 }
2600
2601
2602 /************************************************************
2603 * NetUserGetGroups (NETAPI32.@)
2604 */
2605 NET_API_STATUS
2606 WINAPI
2607 NetUserGetGroups(LPCWSTR servername,
2608 LPCWSTR username,
2609 DWORD level,
2610 LPBYTE *bufptr,
2611 DWORD prefixmaxlen,
2612 LPDWORD entriesread,
2613 LPDWORD totalentries)
2614 {
2615 UNICODE_STRING ServerName;
2616 UNICODE_STRING UserName;
2617 SAM_HANDLE ServerHandle = NULL;
2618 SAM_HANDLE AccountDomainHandle = NULL;
2619 SAM_HANDLE UserHandle = NULL;
2620 PSID AccountDomainSid = NULL;
2621 PULONG RelativeIds = NULL;
2622 PSID_NAME_USE Use = NULL;
2623 PGROUP_MEMBERSHIP GroupMembership = NULL;
2624 ULONG GroupCount;
2625
2626 NET_API_STATUS ApiStatus = NERR_Success;
2627 NTSTATUS Status = STATUS_SUCCESS;
2628
2629 TRACE("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
2630 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
2631 totalentries);
2632
2633 if (servername != NULL)
2634 RtlInitUnicodeString(&ServerName, servername);
2635
2636 RtlInitUnicodeString(&UserName, username);
2637
2638 /* Connect to the SAM Server */
2639 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2640 &ServerHandle,
2641 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2642 NULL);
2643 if (!NT_SUCCESS(Status))
2644 {
2645 ERR("SamConnect failed (Status %08lx)\n", Status);
2646 ApiStatus = NetpNtStatusToApiStatus(Status);
2647 goto done;
2648 }
2649
2650 /* Get the Account Domain SID */
2651 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2652 &AccountDomainSid);
2653 if (!NT_SUCCESS(Status))
2654 {
2655 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2656 ApiStatus = NetpNtStatusToApiStatus(Status);
2657 goto done;
2658 }
2659
2660 /* Open the Account Domain */
2661 Status = SamOpenDomain(ServerHandle,
2662 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2663 AccountDomainSid,
2664 &AccountDomainHandle);
2665 if (!NT_SUCCESS(Status))
2666 {
2667 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2668 ApiStatus = NetpNtStatusToApiStatus(Status);
2669 goto done;
2670 }
2671
2672 /* Get the RID for the given user name */
2673 Status = SamLookupNamesInDomain(AccountDomainHandle,
2674 1,
2675 &UserName,
2676 &RelativeIds,
2677 &Use);
2678 if (!NT_SUCCESS(Status))
2679 {
2680 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
2681 if (Status == STATUS_NONE_MAPPED)
2682 ApiStatus = NERR_UserNotFound;
2683 else
2684 ApiStatus = NetpNtStatusToApiStatus(Status);
2685 goto done;
2686 }
2687
2688 /* Fail, if it is not a user account */
2689 if (Use[0] != SidTypeUser)
2690 {
2691 ERR("Account is not a User!\n");
2692 ApiStatus = NERR_UserNotFound;
2693 goto done;
2694 }
2695
2696 /* Open the user object */
2697 Status = SamOpenUser(AccountDomainHandle,
2698 USER_LIST_GROUPS,
2699 RelativeIds[0],
2700 &UserHandle);
2701 if (!NT_SUCCESS(Status))
2702 {
2703 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2704 ApiStatus = NetpNtStatusToApiStatus(Status);
2705 goto done;
2706 }
2707
2708 /* Get the group memberships of this user */
2709 Status = SamGetGroupsForUser(UserHandle,
2710 &GroupMembership,
2711 &GroupCount);
2712 if (!NT_SUCCESS(Status))
2713 {
2714 ERR("SamGetGroupsForUser failed (Status %08lx)\n", Status);
2715 ApiStatus = NetpNtStatusToApiStatus(Status);
2716 goto done;
2717 }
2718
2719 /* If there is no group membership, we're done */
2720 if (GroupCount == 0)
2721 {
2722 ApiStatus = NERR_Success;
2723 goto done;
2724 }
2725
2726
2727 done:
2728
2729 if (GroupMembership != NULL)
2730 SamFreeMemory(GroupMembership);
2731
2732 if (UserHandle != NULL)
2733 SamCloseHandle(UserHandle);
2734
2735 if (RelativeIds != NULL)
2736 SamFreeMemory(RelativeIds);
2737
2738 if (Use != NULL)
2739 SamFreeMemory(Use);
2740
2741 if (AccountDomainSid != NULL)
2742 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
2743
2744 if (AccountDomainHandle != NULL)
2745 SamCloseHandle(AccountDomainHandle);
2746
2747 if (ServerHandle != NULL)
2748 SamCloseHandle(ServerHandle);
2749
2750 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
2751 {
2752 *entriesread = 0;
2753 *totalentries = 0;
2754 }
2755 else
2756 {
2757 // *entriesread = Count;
2758 // *totalentries = Count;
2759 }
2760
2761 // *bufptr = (LPBYTE)Buffer;
2762
2763 return ApiStatus;
2764 }
2765
2766
2767 /************************************************************
2768 * NetUserGetInfo (NETAPI32.@)
2769 */
2770 NET_API_STATUS
2771 WINAPI
2772 NetUserGetInfo(LPCWSTR servername,
2773 LPCWSTR username,
2774 DWORD level,
2775 LPBYTE* bufptr)
2776 {
2777 UNICODE_STRING ServerName;
2778 UNICODE_STRING UserName;
2779 SAM_HANDLE ServerHandle = NULL;
2780 SAM_HANDLE AccountDomainHandle = NULL;
2781 SAM_HANDLE UserHandle = NULL;
2782 PULONG RelativeIds = NULL;
2783 PSID_NAME_USE Use = NULL;
2784 LPVOID Buffer = NULL;
2785 NET_API_STATUS ApiStatus = NERR_Success;
2786 NTSTATUS Status = STATUS_SUCCESS;
2787
2788 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername),
2789 debugstr_w(username), level, bufptr);
2790
2791 if (servername != NULL)
2792 RtlInitUnicodeString(&ServerName, servername);
2793
2794 RtlInitUnicodeString(&UserName, username);
2795
2796 /* Connect to the SAM Server */
2797 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2798 &ServerHandle,
2799 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2800 NULL);
2801 if (!NT_SUCCESS(Status))
2802 {
2803 ERR("SamConnect failed (Status %08lx)\n", Status);
2804 ApiStatus = NetpNtStatusToApiStatus(Status);
2805 goto done;
2806 }
2807
2808 /* Open the Account Domain */
2809 Status = OpenAccountDomain(ServerHandle,
2810 (servername != NULL) ? &ServerName : NULL,
2811 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2812 &AccountDomainHandle);
2813 if (!NT_SUCCESS(Status))
2814 {
2815 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2816 ApiStatus = NetpNtStatusToApiStatus(Status);
2817 goto done;
2818 }
2819
2820 /* Get the RID for the given user name */
2821 Status = SamLookupNamesInDomain(AccountDomainHandle,
2822 1,
2823 &UserName,
2824 &RelativeIds,
2825 &Use);
2826 if (!NT_SUCCESS(Status))
2827 {
2828 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2829 if (Status == STATUS_NONE_MAPPED)
2830 ApiStatus = NERR_UserNotFound;
2831 else
2832 ApiStatus = NetpNtStatusToApiStatus(Status);
2833 goto done;
2834 }
2835
2836 /* Check if the account is a user account */
2837 if (Use[0] != SidTypeUser)
2838 {
2839 ERR("No user found!\n");
2840 ApiStatus = NERR_UserNotFound;
2841 goto done;
2842 }
2843
2844 TRACE("RID: %lu\n", RelativeIds[0]);
2845
2846 /* Open the user object */
2847 Status = SamOpenUser(AccountDomainHandle,
2848 READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
2849 RelativeIds[0],
2850 &UserHandle);
2851 if (!NT_SUCCESS(Status))
2852 {
2853 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2854 ApiStatus = NetpNtStatusToApiStatus(Status);
2855 goto done;
2856 }
2857
2858 ApiStatus = BuildUserInfoBuffer(UserHandle,
2859 level,
2860 RelativeIds[0],
2861 &Buffer);
2862 if (ApiStatus != NERR_Success)
2863 {
2864 ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus);
2865 goto done;
2866 }
2867
2868 done:
2869 if (UserHandle != NULL)
2870 SamCloseHandle(UserHandle);
2871
2872 if (RelativeIds != NULL)
2873 SamFreeMemory(RelativeIds);
2874
2875 if (Use != NULL)
2876 SamFreeMemory(Use);
2877
2878 if (AccountDomainHandle != NULL)
2879 SamCloseHandle(AccountDomainHandle);
2880
2881 if (ServerHandle != NULL)
2882 SamCloseHandle(ServerHandle);
2883
2884 *bufptr = (LPBYTE)Buffer;
2885
2886 return ApiStatus;
2887 }
2888
2889
2890 /************************************************************
2891 * NetUserGetLocalGroups (NETAPI32.@)
2892 */
2893 NET_API_STATUS
2894 WINAPI
2895 NetUserGetLocalGroups(LPCWSTR servername,
2896 LPCWSTR username,
2897 DWORD level,
2898 DWORD flags,
2899 LPBYTE* bufptr,
2900 DWORD prefmaxlen,
2901 LPDWORD entriesread,
2902 LPDWORD totalentries)
2903 {
2904 UNICODE_STRING ServerName;
2905 UNICODE_STRING UserName;
2906 SAM_HANDLE ServerHandle = NULL;
2907 SAM_HANDLE BuiltinDomainHandle = NULL;
2908 SAM_HANDLE AccountDomainHandle = NULL;
2909 PSID AccountDomainSid = NULL;
2910 PSID UserSid = NULL;
2911 PULONG RelativeIds = NULL;
2912 PSID_NAME_USE Use = NULL;
2913 ULONG BuiltinMemberCount = 0;
2914 ULONG AccountMemberCount = 0;
2915 PULONG BuiltinAliases = NULL;
2916 PULONG AccountAliases = NULL;
2917 PUNICODE_STRING BuiltinNames = NULL;
2918 PUNICODE_STRING AccountNames = NULL;
2919 PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
2920 ULONG Size;
2921 ULONG Count = 0;
2922 ULONG Index;
2923 ULONG i;
2924 LPWSTR StrPtr;
2925 NET_API_STATUS ApiStatus = NERR_Success;
2926 NTSTATUS Status = STATUS_SUCCESS;
2927
2928 TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2929 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
2930 prefmaxlen, entriesread, totalentries);
2931
2932 if (level != 0)
2933 return ERROR_INVALID_LEVEL;
2934
2935 if (flags & ~LG_INCLUDE_INDIRECT)
2936 return ERROR_INVALID_PARAMETER;
2937
2938 if (flags & LG_INCLUDE_INDIRECT)
2939 {
2940 WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
2941 }
2942
2943 if (servername != NULL)
2944 RtlInitUnicodeString(&ServerName, servername);
2945
2946 RtlInitUnicodeString(&UserName, username);
2947
2948 /* Connect to the SAM Server */
2949 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2950 &ServerHandle,
2951 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2952 NULL);
2953 if (!NT_SUCCESS(Status))
2954 {
2955 ERR("SamConnect failed (Status %08lx)\n", Status);
2956 ApiStatus = NetpNtStatusToApiStatus(Status);
2957 goto done;
2958 }
2959
2960 /* Open the Builtin Domain */
2961 Status = OpenBuiltinDomain(ServerHandle,
2962 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2963 &BuiltinDomainHandle);
2964 if (!NT_SUCCESS(Status))
2965 {
2966 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2967 ApiStatus = NetpNtStatusToApiStatus(Status);
2968 goto done;
2969 }
2970
2971 /* Get the Account Domain SID */
2972 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2973 &AccountDomainSid);
2974 if (!NT_SUCCESS(Status))
2975 {
2976 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2977 ApiStatus = NetpNtStatusToApiStatus(Status);
2978 goto done;
2979 }
2980
2981 /* Open the Account Domain */
2982 Status = SamOpenDomain(ServerHandle,
2983 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2984 AccountDomainSid,
2985 &AccountDomainHandle);
2986 if (!NT_SUCCESS(Status))
2987 {
2988 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2989 ApiStatus = NetpNtStatusToApiStatus(Status);
2990 goto done;
2991 }
2992
2993 /* Get the RID for the given user name */
2994 Status = SamLookupNamesInDomain(AccountDomainHandle,
2995 1,
2996 &UserName,
2997 &RelativeIds,
2998 &Use);
2999 if (!NT_SUCCESS(Status))
3000 {
3001 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
3002 if (Status == STATUS_NONE_MAPPED)
3003 ApiStatus = NERR_UserNotFound;
3004 else
3005 ApiStatus = NetpNtStatusToApiStatus(Status);
3006 goto done;
3007 }
3008
3009 /* Fail, if it is not a user account */
3010 if (Use[0] != SidTypeUser)
3011 {
3012 ERR("Account is not a User!\n");
3013 ApiStatus = NERR_UserNotFound;
3014 goto done;
3015 }
3016
3017 /* Build the User SID from the Account Domain SID and the users RID */
3018 ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
3019 RelativeIds[0],
3020 &UserSid);
3021 if (ApiStatus != NERR_Success)
3022 {
3023 ERR("BuildSidFromSidAndRid failed!\n");
3024 goto done;
3025 }
3026
3027 /* Get alias memberships in the Builtin Domain */
3028 Status = SamGetAliasMembership(BuiltinDomainHandle,
3029 1,
3030 &UserSid,
3031 &BuiltinMemberCount,
3032 &BuiltinAliases);
3033 if (!NT_SUCCESS(Status))
3034 {
3035 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3036 ApiStatus = NetpNtStatusToApiStatus(Status);
3037 goto done;
3038 }
3039
3040 if (BuiltinMemberCount > 0)
3041 {
3042 /* Get the Names of the builtin alias members */
3043 Status = SamLookupIdsInDomain(BuiltinDomainHandle,
3044 BuiltinMemberCount,
3045 BuiltinAliases,
3046 &BuiltinNames,
3047 NULL);
3048 if (!NT_SUCCESS(Status))
3049 {
3050 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3051 ApiStatus = NetpNtStatusToApiStatus(Status);
3052 goto done;
3053 }
3054 }
3055
3056 /* Get alias memberships in the Account Domain */
3057 Status = SamGetAliasMembership(AccountDomainHandle,
3058 1,
3059 &UserSid,
3060 &AccountMemberCount,
3061 &AccountAliases);
3062 if (!NT_SUCCESS(Status))
3063 {
3064 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3065 ApiStatus = NetpNtStatusToApiStatus(Status);
3066 goto done;
3067 }
3068
3069 if (AccountMemberCount > 0)
3070 {
3071 /* Get the Names of the builtin alias members */
3072 Status = SamLookupIdsInDomain(AccountDomainHandle,
3073 AccountMemberCount,
3074 AccountAliases,
3075 &AccountNames,
3076 NULL);
3077 if (!NT_SUCCESS(Status))
3078 {
3079 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3080 ApiStatus = NetpNtStatusToApiStatus(Status);
3081 goto done;
3082 }
3083 }
3084
3085 /* Calculate the required buffer size */
3086 Size = 0;
3087
3088 for (i = 0; i < BuiltinMemberCount; i++)
3089 {
3090 if (BuiltinNames[i].Length > 0)
3091 {
3092 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3093 Count++;
3094 }
3095 }
3096
3097 for (i = 0; i < AccountMemberCount; i++)
3098 {
3099 if (AccountNames[i].Length > 0)
3100 {
3101 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length + sizeof(UNICODE_NULL));
3102 Count++;
3103 }
3104 }
3105
3106 if (Size == 0)
3107 {
3108 ApiStatus = NERR_Success;
3109 goto done;
3110 }
3111
3112 /* Allocate buffer */
3113 ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
3114 if (ApiStatus != NERR_Success)
3115 goto done;
3116
3117 ZeroMemory(Buffer, Size);
3118
3119 StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
3120
3121 /* Copy data to the allocated buffer */
3122 Index = 0;
3123 for (i = 0; i < BuiltinMemberCount; i++)
3124 {
3125 if (BuiltinNames[i].Length > 0)
3126 {
3127 CopyMemory(StrPtr,
3128 BuiltinNames[i].Buffer,
3129 BuiltinNames[i].Length);
3130 Buffer[Index].lgrui0_name = StrPtr;
3131
3132 StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3133 Index++;
3134 }
3135 }
3136
3137 for (i = 0; i < AccountMemberCount; i++)
3138 {
3139 if (AccountNames[i].Length > 0)
3140 {
3141 CopyMemory(StrPtr,
3142 AccountNames[i].Buffer,
3143 AccountNames[i].Length);
3144 Buffer[Index].lgrui0_name = StrPtr;
3145
3146 StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length + sizeof(UNICODE_NULL));
3147 Index++;
3148 }
3149 }
3150
3151 done:
3152 if (AccountNames != NULL)
3153 SamFreeMemory(AccountNames);
3154
3155 if (BuiltinNames != NULL)
3156 SamFreeMemory(BuiltinNames);
3157
3158 if (AccountAliases != NULL)
3159 SamFreeMemory(AccountAliases);
3160
3161 if (BuiltinAliases != NULL)
3162 SamFreeMemory(BuiltinAliases);
3163
3164 if (RelativeIds != NULL)
3165 SamFreeMemory(RelativeIds);
3166
3167 if (Use != NULL)
3168 SamFreeMemory(Use);
3169
3170 if (UserSid != NULL)
3171 NetApiBufferFree(UserSid);
3172
3173 if (AccountDomainSid != NULL)
3174 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3175
3176 if (AccountDomainHandle != NULL)
3177 SamCloseHandle(AccountDomainHandle);
3178
3179 if (BuiltinDomainHandle != NULL)
3180 SamCloseHandle(BuiltinDomainHandle);
3181
3182 if (ServerHandle != NULL)
3183 SamCloseHandle(ServerHandle);
3184
3185 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3186 {
3187 *entriesread = 0;
3188 *totalentries = 0;
3189 }
3190 else