02fee928963f126540a6a810d41b98936d763105
[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 /* A successful delete invalidates the handle */
2380 UserHandle = NULL;
2381
2382 done:
2383 if (UserHandle != NULL)
2384 SamCloseHandle(UserHandle);
2385
2386 if (DomainHandle != NULL)
2387 SamCloseHandle(DomainHandle);
2388
2389 if (ServerHandle != NULL)
2390 SamCloseHandle(ServerHandle);
2391
2392 return ApiStatus;
2393 }
2394
2395
2396 /************************************************************
2397 * NetUserEnum (NETAPI32.@)
2398 */
2399 NET_API_STATUS
2400 WINAPI
2401 NetUserEnum(LPCWSTR servername,
2402 DWORD level,
2403 DWORD filter,
2404 LPBYTE* bufptr,
2405 DWORD prefmaxlen,
2406 LPDWORD entriesread,
2407 LPDWORD totalentries,
2408 LPDWORD resume_handle)
2409 {
2410 UNICODE_STRING ServerName;
2411 PSAM_RID_ENUMERATION CurrentUser;
2412 PENUM_CONTEXT EnumContext = NULL;
2413 LPVOID Buffer = NULL;
2414 ULONG i;
2415 SAM_HANDLE UserHandle = NULL;
2416 NET_API_STATUS ApiStatus = NERR_Success;
2417 NTSTATUS Status = STATUS_SUCCESS;
2418
2419 TRACE("(%s %d 0x%d %p %d %p %p %p)\n", debugstr_w(servername), level,
2420 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
2421
2422 *entriesread = 0;
2423 *totalentries = 0;
2424 *bufptr = NULL;
2425
2426 if (servername != NULL)
2427 RtlInitUnicodeString(&ServerName, servername);
2428
2429 if (resume_handle != NULL && *resume_handle != 0)
2430 {
2431 EnumContext = (PENUM_CONTEXT)*resume_handle;
2432 }
2433 else
2434 {
2435 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
2436 if (ApiStatus != NERR_Success)
2437 goto done;
2438
2439 EnumContext->EnumerationContext = 0;
2440 EnumContext->Buffer = NULL;
2441 EnumContext->Count = 0;
2442 EnumContext->Index = 0;
2443 EnumContext->BuiltinDone = FALSE;
2444
2445 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2446 &EnumContext->ServerHandle,
2447 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2448 NULL);
2449 if (!NT_SUCCESS(Status))
2450 {
2451 ERR("SamConnect failed (Status %08lx)\n", Status);
2452 ApiStatus = NetpNtStatusToApiStatus(Status);
2453 goto done;
2454 }
2455
2456 Status = OpenAccountDomain(EnumContext->ServerHandle,
2457 (servername != NULL) ? &ServerName : NULL,
2458 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2459 &EnumContext->AccountDomainHandle);
2460 if (!NT_SUCCESS(Status))
2461 {
2462 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2463 ApiStatus = NetpNtStatusToApiStatus(Status);
2464 goto done;
2465 }
2466
2467 Status = OpenBuiltinDomain(EnumContext->ServerHandle,
2468 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2469 &EnumContext->BuiltinDomainHandle);
2470 if (!NT_SUCCESS(Status))
2471 {
2472 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2473 ApiStatus = NetpNtStatusToApiStatus(Status);
2474 goto done;
2475 }
2476 }
2477
2478 // while (TRUE)
2479 // {
2480 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
2481 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2482
2483 if (EnumContext->Index >= EnumContext->Count)
2484 {
2485 // if (EnumContext->BuiltinDone == TRUE)
2486 // {
2487 // ApiStatus = NERR_Success;
2488 // goto done;
2489 // }
2490
2491 TRACE("Calling SamEnumerateUsersInDomain\n");
2492 Status = SamEnumerateUsersInDomain(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2493 &EnumContext->EnumerationContext,
2494 0,
2495 (PVOID *)&EnumContext->Buffer,
2496 prefmaxlen,
2497 &EnumContext->Count);
2498
2499 TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
2500 if (!NT_SUCCESS(Status))
2501 {
2502 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status);
2503 ApiStatus = NetpNtStatusToApiStatus(Status);
2504 goto done;
2505 }
2506
2507 if (Status == STATUS_MORE_ENTRIES)
2508 {
2509 ApiStatus = NERR_BufTooSmall;
2510 goto done;
2511 }
2512 else
2513 {
2514 EnumContext->BuiltinDone = TRUE;
2515 }
2516 }
2517
2518 TRACE("EnumContext: %lu\n", EnumContext);
2519 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
2520 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
2521
2522 /* Get a pointer to the current user */
2523 CurrentUser = &EnumContext->Buffer[EnumContext->Index];
2524
2525 TRACE("RID: %lu\n", CurrentUser->RelativeId);
2526
2527 Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
2528 READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
2529 CurrentUser->RelativeId,
2530 &UserHandle);
2531 if (!NT_SUCCESS(Status))
2532 {
2533 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2534 ApiStatus = NetpNtStatusToApiStatus(Status);
2535 goto done;
2536 }
2537
2538 ApiStatus = BuildUserInfoBuffer(UserHandle,
2539 level,
2540 CurrentUser->RelativeId,
2541 &Buffer);
2542 if (ApiStatus != NERR_Success)
2543 {
2544 ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus);
2545 goto done;
2546 }
2547
2548 SamCloseHandle(UserHandle);
2549 UserHandle = NULL;
2550
2551 EnumContext->Index++;
2552
2553 (*entriesread)++;
2554 // }
2555
2556 done:
2557 if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count)
2558 ApiStatus = ERROR_MORE_DATA;
2559
2560 if (EnumContext != NULL)
2561 *totalentries = EnumContext->Count;
2562
2563 if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
2564 {
2565 if (EnumContext != NULL)
2566 {
2567 if (EnumContext->BuiltinDomainHandle != NULL)
2568 SamCloseHandle(EnumContext->BuiltinDomainHandle);
2569
2570 if (EnumContext->AccountDomainHandle != NULL)
2571 SamCloseHandle(EnumContext->AccountDomainHandle);
2572
2573 if (EnumContext->ServerHandle != NULL)
2574 SamCloseHandle(EnumContext->ServerHandle);
2575
2576 if (EnumContext->Buffer != NULL)
2577 {
2578 for (i = 0; i < EnumContext->Count; i++)
2579 {
2580 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
2581 }
2582
2583 SamFreeMemory(EnumContext->Buffer);
2584 }
2585
2586 NetApiBufferFree(EnumContext);
2587 EnumContext = NULL;
2588 }
2589 }
2590
2591 if (UserHandle != NULL)
2592 SamCloseHandle(UserHandle);
2593
2594 if (resume_handle != NULL)
2595 *resume_handle = (DWORD_PTR)EnumContext;
2596
2597 *bufptr = (LPBYTE)Buffer;
2598
2599 TRACE("return %lu\n", ApiStatus);
2600
2601 return ApiStatus;
2602 }
2603
2604
2605 /************************************************************
2606 * NetUserGetGroups (NETAPI32.@)
2607 */
2608 NET_API_STATUS
2609 WINAPI
2610 NetUserGetGroups(LPCWSTR servername,
2611 LPCWSTR username,
2612 DWORD level,
2613 LPBYTE *bufptr,
2614 DWORD prefixmaxlen,
2615 LPDWORD entriesread,
2616 LPDWORD totalentries)
2617 {
2618 UNICODE_STRING ServerName;
2619 UNICODE_STRING UserName;
2620 SAM_HANDLE ServerHandle = NULL;
2621 SAM_HANDLE AccountDomainHandle = NULL;
2622 SAM_HANDLE UserHandle = NULL;
2623 PSID AccountDomainSid = NULL;
2624 PULONG RelativeIds = NULL;
2625 PSID_NAME_USE Use = NULL;
2626 PGROUP_MEMBERSHIP GroupMembership = NULL;
2627 ULONG GroupCount;
2628
2629 NET_API_STATUS ApiStatus = NERR_Success;
2630 NTSTATUS Status = STATUS_SUCCESS;
2631
2632 TRACE("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
2633 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
2634 totalentries);
2635
2636 if (servername != NULL)
2637 RtlInitUnicodeString(&ServerName, servername);
2638
2639 RtlInitUnicodeString(&UserName, username);
2640
2641 /* Connect to the SAM Server */
2642 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2643 &ServerHandle,
2644 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2645 NULL);
2646 if (!NT_SUCCESS(Status))
2647 {
2648 ERR("SamConnect failed (Status %08lx)\n", Status);
2649 ApiStatus = NetpNtStatusToApiStatus(Status);
2650 goto done;
2651 }
2652
2653 /* Get the Account Domain SID */
2654 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2655 &AccountDomainSid);
2656 if (!NT_SUCCESS(Status))
2657 {
2658 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2659 ApiStatus = NetpNtStatusToApiStatus(Status);
2660 goto done;
2661 }
2662
2663 /* Open the Account Domain */
2664 Status = SamOpenDomain(ServerHandle,
2665 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2666 AccountDomainSid,
2667 &AccountDomainHandle);
2668 if (!NT_SUCCESS(Status))
2669 {
2670 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2671 ApiStatus = NetpNtStatusToApiStatus(Status);
2672 goto done;
2673 }
2674
2675 /* Get the RID for the given user name */
2676 Status = SamLookupNamesInDomain(AccountDomainHandle,
2677 1,
2678 &UserName,
2679 &RelativeIds,
2680 &Use);
2681 if (!NT_SUCCESS(Status))
2682 {
2683 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
2684 if (Status == STATUS_NONE_MAPPED)
2685 ApiStatus = NERR_UserNotFound;
2686 else
2687 ApiStatus = NetpNtStatusToApiStatus(Status);
2688 goto done;
2689 }
2690
2691 /* Fail, if it is not a user account */
2692 if (Use[0] != SidTypeUser)
2693 {
2694 ERR("Account is not a User!\n");
2695 ApiStatus = NERR_UserNotFound;
2696 goto done;
2697 }
2698
2699 /* Open the user object */
2700 Status = SamOpenUser(AccountDomainHandle,
2701 USER_LIST_GROUPS,
2702 RelativeIds[0],
2703 &UserHandle);
2704 if (!NT_SUCCESS(Status))
2705 {
2706 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2707 ApiStatus = NetpNtStatusToApiStatus(Status);
2708 goto done;
2709 }
2710
2711 /* Get the group memberships of this user */
2712 Status = SamGetGroupsForUser(UserHandle,
2713 &GroupMembership,
2714 &GroupCount);
2715 if (!NT_SUCCESS(Status))
2716 {
2717 ERR("SamGetGroupsForUser failed (Status %08lx)\n", Status);
2718 ApiStatus = NetpNtStatusToApiStatus(Status);
2719 goto done;
2720 }
2721
2722 /* If there is no group membership, we're done */
2723 if (GroupCount == 0)
2724 {
2725 ApiStatus = NERR_Success;
2726 goto done;
2727 }
2728
2729
2730 done:
2731
2732 if (GroupMembership != NULL)
2733 SamFreeMemory(GroupMembership);
2734
2735 if (UserHandle != NULL)
2736 SamCloseHandle(UserHandle);
2737
2738 if (RelativeIds != NULL)
2739 SamFreeMemory(RelativeIds);
2740
2741 if (Use != NULL)
2742 SamFreeMemory(Use);
2743
2744 if (AccountDomainSid != NULL)
2745 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
2746
2747 if (AccountDomainHandle != NULL)
2748 SamCloseHandle(AccountDomainHandle);
2749
2750 if (ServerHandle != NULL)
2751 SamCloseHandle(ServerHandle);
2752
2753 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
2754 {
2755 *entriesread = 0;
2756 *totalentries = 0;
2757 }
2758 else
2759 {
2760 // *entriesread = Count;
2761 // *totalentries = Count;
2762 }
2763
2764 // *bufptr = (LPBYTE)Buffer;
2765
2766 return ApiStatus;
2767 }
2768
2769
2770 /************************************************************
2771 * NetUserGetInfo (NETAPI32.@)
2772 */
2773 NET_API_STATUS
2774 WINAPI
2775 NetUserGetInfo(LPCWSTR servername,
2776 LPCWSTR username,
2777 DWORD level,
2778 LPBYTE* bufptr)
2779 {
2780 UNICODE_STRING ServerName;
2781 UNICODE_STRING UserName;
2782 SAM_HANDLE ServerHandle = NULL;
2783 SAM_HANDLE AccountDomainHandle = NULL;
2784 SAM_HANDLE UserHandle = NULL;
2785 PULONG RelativeIds = NULL;
2786 PSID_NAME_USE Use = NULL;
2787 LPVOID Buffer = NULL;
2788 NET_API_STATUS ApiStatus = NERR_Success;
2789 NTSTATUS Status = STATUS_SUCCESS;
2790
2791 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername),
2792 debugstr_w(username), level, bufptr);
2793
2794 if (servername != NULL)
2795 RtlInitUnicodeString(&ServerName, servername);
2796
2797 RtlInitUnicodeString(&UserName, username);
2798
2799 /* Connect to the SAM Server */
2800 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2801 &ServerHandle,
2802 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2803 NULL);
2804 if (!NT_SUCCESS(Status))
2805 {
2806 ERR("SamConnect failed (Status %08lx)\n", Status);
2807 ApiStatus = NetpNtStatusToApiStatus(Status);
2808 goto done;
2809 }
2810
2811 /* Open the Account Domain */
2812 Status = OpenAccountDomain(ServerHandle,
2813 (servername != NULL) ? &ServerName : NULL,
2814 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
2815 &AccountDomainHandle);
2816 if (!NT_SUCCESS(Status))
2817 {
2818 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2819 ApiStatus = NetpNtStatusToApiStatus(Status);
2820 goto done;
2821 }
2822
2823 /* Get the RID for the given user name */
2824 Status = SamLookupNamesInDomain(AccountDomainHandle,
2825 1,
2826 &UserName,
2827 &RelativeIds,
2828 &Use);
2829 if (!NT_SUCCESS(Status))
2830 {
2831 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
2832 if (Status == STATUS_NONE_MAPPED)
2833 ApiStatus = NERR_UserNotFound;
2834 else
2835 ApiStatus = NetpNtStatusToApiStatus(Status);
2836 goto done;
2837 }
2838
2839 /* Check if the account is a user account */
2840 if (Use[0] != SidTypeUser)
2841 {
2842 ERR("No user found!\n");
2843 ApiStatus = NERR_UserNotFound;
2844 goto done;
2845 }
2846
2847 TRACE("RID: %lu\n", RelativeIds[0]);
2848
2849 /* Open the user object */
2850 Status = SamOpenUser(AccountDomainHandle,
2851 READ_CONTROL | USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
2852 RelativeIds[0],
2853 &UserHandle);
2854 if (!NT_SUCCESS(Status))
2855 {
2856 ERR("SamOpenUser failed (Status %08lx)\n", Status);
2857 ApiStatus = NetpNtStatusToApiStatus(Status);
2858 goto done;
2859 }
2860
2861 ApiStatus = BuildUserInfoBuffer(UserHandle,
2862 level,
2863 RelativeIds[0],
2864 &Buffer);
2865 if (ApiStatus != NERR_Success)
2866 {
2867 ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus);
2868 goto done;
2869 }
2870
2871 done:
2872 if (UserHandle != NULL)
2873 SamCloseHandle(UserHandle);
2874
2875 if (RelativeIds != NULL)
2876 SamFreeMemory(RelativeIds);
2877
2878 if (Use != NULL)
2879 SamFreeMemory(Use);
2880
2881 if (AccountDomainHandle != NULL)
2882 SamCloseHandle(AccountDomainHandle);
2883
2884 if (ServerHandle != NULL)
2885 SamCloseHandle(ServerHandle);
2886
2887 *bufptr = (LPBYTE)Buffer;
2888
2889 return ApiStatus;
2890 }
2891
2892
2893 /************************************************************
2894 * NetUserGetLocalGroups (NETAPI32.@)
2895 */
2896 NET_API_STATUS
2897 WINAPI
2898 NetUserGetLocalGroups(LPCWSTR servername,
2899 LPCWSTR username,
2900 DWORD level,
2901 DWORD flags,
2902 LPBYTE* bufptr,
2903 DWORD prefmaxlen,
2904 LPDWORD entriesread,
2905 LPDWORD totalentries)
2906 {
2907 UNICODE_STRING ServerName;
2908 UNICODE_STRING UserName;
2909 SAM_HANDLE ServerHandle = NULL;
2910 SAM_HANDLE BuiltinDomainHandle = NULL;
2911 SAM_HANDLE AccountDomainHandle = NULL;
2912 PSID AccountDomainSid = NULL;
2913 PSID UserSid = NULL;
2914 PULONG RelativeIds = NULL;
2915 PSID_NAME_USE Use = NULL;
2916 ULONG BuiltinMemberCount = 0;
2917 ULONG AccountMemberCount = 0;
2918 PULONG BuiltinAliases = NULL;
2919 PULONG AccountAliases = NULL;
2920 PUNICODE_STRING BuiltinNames = NULL;
2921 PUNICODE_STRING AccountNames = NULL;
2922 PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
2923 ULONG Size;
2924 ULONG Count = 0;
2925 ULONG Index;
2926 ULONG i;
2927 LPWSTR StrPtr;
2928 NET_API_STATUS ApiStatus = NERR_Success;
2929 NTSTATUS Status = STATUS_SUCCESS;
2930
2931 TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
2932 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
2933 prefmaxlen, entriesread, totalentries);
2934
2935 if (level != 0)
2936 return ERROR_INVALID_LEVEL;
2937
2938 if (flags & ~LG_INCLUDE_INDIRECT)
2939 return ERROR_INVALID_PARAMETER;
2940
2941 if (flags & LG_INCLUDE_INDIRECT)
2942 {
2943 WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
2944 }
2945
2946 if (servername != NULL)
2947 RtlInitUnicodeString(&ServerName, servername);
2948
2949 RtlInitUnicodeString(&UserName, username);
2950
2951 /* Connect to the SAM Server */
2952 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
2953 &ServerHandle,
2954 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
2955 NULL);
2956 if (!NT_SUCCESS(Status))
2957 {
2958 ERR("SamConnect failed (Status %08lx)\n", Status);
2959 ApiStatus = NetpNtStatusToApiStatus(Status);
2960 goto done;
2961 }
2962
2963 /* Open the Builtin Domain */
2964 Status = OpenBuiltinDomain(ServerHandle,
2965 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2966 &BuiltinDomainHandle);
2967 if (!NT_SUCCESS(Status))
2968 {
2969 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
2970 ApiStatus = NetpNtStatusToApiStatus(Status);
2971 goto done;
2972 }
2973
2974 /* Get the Account Domain SID */
2975 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
2976 &AccountDomainSid);
2977 if (!NT_SUCCESS(Status))
2978 {
2979 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
2980 ApiStatus = NetpNtStatusToApiStatus(Status);
2981 goto done;
2982 }
2983
2984 /* Open the Account Domain */
2985 Status = SamOpenDomain(ServerHandle,
2986 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
2987 AccountDomainSid,
2988 &AccountDomainHandle);
2989 if (!NT_SUCCESS(Status))
2990 {
2991 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
2992 ApiStatus = NetpNtStatusToApiStatus(Status);
2993 goto done;
2994 }
2995
2996 /* Get the RID for the given user name */
2997 Status = SamLookupNamesInDomain(AccountDomainHandle,
2998 1,
2999 &UserName,
3000 &RelativeIds,
3001 &Use);
3002 if (!NT_SUCCESS(Status))
3003 {
3004 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
3005 if (Status == STATUS_NONE_MAPPED)
3006 ApiStatus = NERR_UserNotFound;
3007 else
3008 ApiStatus = NetpNtStatusToApiStatus(Status);
3009 goto done;
3010 }
3011
3012 /* Fail, if it is not a user account */
3013 if (Use[0] != SidTypeUser)
3014 {
3015 ERR("Account is not a User!\n");
3016 ApiStatus = NERR_UserNotFound;
3017 goto done;
3018 }
3019
3020 /* Build the User SID from the Account Domain SID and the users RID */
3021 ApiStatus = BuildSidFromSidAndRid(AccountDomainSid,
3022 RelativeIds[0],
3023 &UserSid);
3024 if (ApiStatus != NERR_Success)
3025 {
3026 ERR("BuildSidFromSidAndRid failed!\n");
3027 goto done;
3028 }
3029
3030 /* Get alias memberships in the Builtin Domain */
3031 Status = SamGetAliasMembership(BuiltinDomainHandle,
3032 1,
3033 &UserSid,
3034 &BuiltinMemberCount,
3035 &BuiltinAliases);
3036 if (!NT_SUCCESS(Status))
3037 {
3038 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3039 ApiStatus = NetpNtStatusToApiStatus(Status);
3040 goto done;
3041 }
3042
3043 if (BuiltinMemberCount > 0)
3044 {
3045 /* Get the Names of the builtin alias members */
3046 Status = SamLookupIdsInDomain(BuiltinDomainHandle,
3047 BuiltinMemberCount,
3048 BuiltinAliases,
3049 &BuiltinNames,
3050 NULL);
3051 if (!NT_SUCCESS(Status))
3052 {
3053 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3054 ApiStatus = NetpNtStatusToApiStatus(Status);
3055 goto done;
3056 }
3057 }
3058
3059 /* Get alias memberships in the Account Domain */
3060 Status = SamGetAliasMembership(AccountDomainHandle,
3061 1,
3062 &UserSid,
3063 &AccountMemberCount,
3064 &AccountAliases);
3065 if (!NT_SUCCESS(Status))
3066 {
3067 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
3068 ApiStatus = NetpNtStatusToApiStatus(Status);
3069 goto done;
3070 }
3071
3072 if (AccountMemberCount > 0)
3073 {
3074 /* Get the Names of the builtin alias members */
3075 Status = SamLookupIdsInDomain(AccountDomainHandle,
3076 AccountMemberCount,
3077 AccountAliases,
3078 &AccountNames,
3079 NULL);
3080 if (!NT_SUCCESS(Status))
3081 {
3082 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
3083 ApiStatus = NetpNtStatusToApiStatus(Status);
3084 goto done;
3085 }
3086 }
3087
3088 /* Calculate the required buffer size */
3089 Size = 0;
3090
3091 for (i = 0; i < BuiltinMemberCount; i++)
3092 {
3093 if (BuiltinNames[i].Length > 0)
3094 {
3095 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3096 Count++;
3097 }
3098 }
3099
3100 for (i = 0; i < AccountMemberCount; i++)
3101 {
3102 if (AccountNames[i].Length > 0)
3103 {
3104 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length + sizeof(UNICODE_NULL));
3105 Count++;
3106 }
3107 }
3108
3109 if (Size == 0)
3110 {
3111 ApiStatus = NERR_Success;
3112 goto done;
3113 }
3114
3115 /* Allocate buffer */
3116 ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
3117 if (ApiStatus != NERR_Success)
3118 goto done;
3119
3120 ZeroMemory(Buffer, Size);
3121
3122 StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
3123
3124 /* Copy data to the allocated buffer */
3125 Index = 0;
3126 for (i = 0; i < BuiltinMemberCount; i++)
3127 {
3128 if (BuiltinNames[i].Length > 0)
3129 {
3130 CopyMemory(StrPtr,
3131 BuiltinNames[i].Buffer,
3132 BuiltinNames[i].Length);
3133 Buffer[Index].lgrui0_name = StrPtr;
3134
3135 StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
3136 Index++;
3137 }
3138 }
3139
3140 for (i = 0; i < AccountMemberCount; i++)
3141 {
3142 if (AccountNames[i].Length > 0)
3143 {
3144 CopyMemory(StrPtr,
3145 AccountNames[i].Buffer,
3146 AccountNames[i].Length);
3147 Buffer[Index].lgrui0_name = StrPtr;
3148
3149 StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length + sizeof(UNICODE_NULL));
3150 Index++;
3151 }
3152 }
3153
3154 done:
3155 if (AccountNames != NULL)
3156 SamFreeMemory(AccountNames);
3157
3158 if (BuiltinNames != NULL)
3159 SamFreeMemory(BuiltinNames);
3160
3161 if (AccountAliases != NULL)
3162 SamFreeMemory(AccountAliases);
3163
3164 if (BuiltinAliases != NULL)
3165 SamFreeMemory(BuiltinAliases);
3166
3167 if (RelativeIds != NULL)
3168 SamFreeMemory(RelativeIds);
3169
3170 if (Use != NULL)
3171 SamFreeMemory(Use);
3172
3173 if (UserSid != NULL)
3174 NetApiBufferFree(UserSid);
3175
3176 if (AccountDomainSid != NULL)
3177 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
3178
3179 if (AccountDomainHandle != NULL)
3180 SamCloseHandle(AccountDomainHandle);
3181
3182 if (BuiltinDomainHandle != NULL)
3183 SamCloseHandle(BuiltinDomainHandle);
3184
3185 if (ServerHandle != NULL)
3186 SamCloseHandle(ServerHandle);
3187
3188 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
3189 {
3190 *entriesread = 0;
3191 *totalentries = 0;
3192 }
3193 else
3194 {