Sync with trunk r58113.
[reactos.git] / dll / win32 / netapi32 / user.c
1 /*
2 * Copyright 2002 Andriy Palamarchuk
3 *
4 * netapi32 user functions
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 /*
22 * TODO:
23 * Implement NetUserChangePassword
24 * Implement NetUserDel
25 * Implement NetUserGetGroups
26 * Implement NetUserSetGroups
27 * Implement NetUserSetInfo
28 * NetUserGetLocalGroups does not support LG_INCLUDE_INDIRECT yet.
29 * Add missing information levels.
30 * ...
31 */
32
33 #include "netapi32.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
36
37
38 typedef struct _ENUM_CONTEXT
39 {
40 SAM_HANDLE ServerHandle;
41 SAM_HANDLE BuiltinDomainHandle;
42 SAM_HANDLE AccountDomainHandle;
43
44 SAM_ENUMERATE_HANDLE EnumerationContext;
45 PSAM_RID_ENUMERATION Buffer;
46 ULONG Count;
47 ULONG Index;
48 BOOLEAN BuiltinDone;
49
50 } ENUM_CONTEXT, *PENUM_CONTEXT;
51
52
53 /* NOTE: So far, this is implemented to support tests that require user logins,
54 * but not designed to handle real user databases. Those should probably
55 * be synced with either the host's user database or with Samba.
56 *
57 * FIXME: The user database should hold all the information the USER_INFO_4 struct
58 * needs, but for the first try, I will just implement the USER_INFO_1 fields.
59 */
60
61 struct sam_user
62 {
63 struct list entry;
64 WCHAR user_name[LM20_UNLEN+1];
65 WCHAR user_password[PWLEN + 1];
66 DWORD sec_since_passwd_change;
67 DWORD user_priv;
68 LPWSTR home_dir;
69 LPWSTR user_comment;
70 DWORD user_flags;
71 LPWSTR user_logon_script_path;
72 };
73
74 static struct list user_list = LIST_INIT( user_list );
75
76 BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName);
77
78 /************************************************************
79 * NETAPI_ValidateServername
80 *
81 * Validates server name
82 */
83 static NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
84 {
85 if (ServerName)
86 {
87 if (ServerName[0] == 0)
88 return ERROR_BAD_NETPATH;
89 else if (
90 ((ServerName[0] == '\\') &&
91 (ServerName[1] != '\\'))
92 ||
93 ((ServerName[0] == '\\') &&
94 (ServerName[1] == '\\') &&
95 (ServerName[2] == 0))
96 )
97 return ERROR_INVALID_NAME;
98 }
99 return NERR_Success;
100 }
101
102 /************************************************************
103 * NETAPI_FindUser
104 *
105 * Looks for a user in the user database.
106 * Returns a pointer to the entry in the user list when the user
107 * is found, NULL otherwise.
108 */
109 static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
110 {
111 struct sam_user *user;
112
113 LIST_FOR_EACH_ENTRY(user, &user_list, struct sam_user, entry)
114 {
115 if(lstrcmpW(user->user_name, UserName) == 0)
116 return user;
117 }
118 return NULL;
119 }
120
121
122 static PSID
123 CreateSidFromSidAndRid(PSID SrcSid,
124 ULONG RelativeId)
125 {
126 UCHAR RidCount;
127 PSID DstSid;
128 ULONG i;
129 ULONG DstSidSize;
130 PULONG p, q;
131
132 RidCount = *RtlSubAuthorityCountSid(SrcSid);
133 if (RidCount >= 8)
134 return NULL;
135
136 DstSidSize = RtlLengthRequiredSid(RidCount + 1);
137
138 DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
139 0,
140 DstSidSize);
141 if (DstSid == NULL)
142 return NULL;
143
144 RtlInitializeSid(DstSid,
145 RtlIdentifierAuthoritySid(SrcSid),
146 RidCount + 1);
147
148 for (i = 0; i < (ULONG)RidCount; i++)
149 {
150 p = RtlSubAuthoritySid(SrcSid, i);
151 q = RtlSubAuthoritySid(DstSid, i);
152 *q = *p;
153 }
154
155 q = RtlSubAuthoritySid(DstSid, (ULONG)RidCount);
156 *q = RelativeId;
157
158 return DstSid;
159 }
160
161
162 static
163 NET_API_STATUS
164 BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo,
165 DWORD level,
166 ULONG RelativeId,
167 LPVOID *Buffer)
168 {
169 LPVOID LocalBuffer = NULL;
170 PUSER_INFO_0 UserInfo0;
171 PUSER_INFO_1 UserInfo1;
172 PUSER_INFO_10 UserInfo10;
173 PUSER_INFO_20 UserInfo20;
174 LPWSTR Ptr;
175 ULONG Size = 0;
176 NET_API_STATUS ApiStatus = NERR_Success;
177
178 *Buffer = NULL;
179
180 switch (level)
181 {
182 case 0:
183 Size = sizeof(USER_INFO_0) +
184 UserInfo->UserName.Length + sizeof(WCHAR);
185 break;
186
187 case 1:
188 Size = sizeof(USER_INFO_1) +
189 UserInfo->UserName.Length + sizeof(WCHAR);
190
191 if (UserInfo->HomeDirectory.Length > 0)
192 Size += UserInfo->HomeDirectory.Length + sizeof(WCHAR);
193
194 if (UserInfo->AdminComment.Length > 0)
195 Size += UserInfo->AdminComment.Length + sizeof(WCHAR);
196
197 if (UserInfo->ScriptPath.Length > 0)
198 Size = UserInfo->ScriptPath.Length + sizeof(WCHAR);
199 break;
200
201 // case 2:
202 // case 3:
203 // case 4:
204
205 case 10:
206 Size = sizeof(USER_INFO_10) +
207 UserInfo->UserName.Length + sizeof(WCHAR);
208
209 if (UserInfo->AdminComment.Length > 0)
210 Size += UserInfo->AdminComment.Length + sizeof(WCHAR);
211
212 /* FIXME: usri10_usr_comment */
213
214 if (UserInfo->FullName.Length > 0)
215 Size += UserInfo->FullName.Length + sizeof(WCHAR);
216 break;
217
218 // case 11:
219
220 case 20:
221 Size = sizeof(USER_INFO_20) +
222 UserInfo->UserName.Length + sizeof(WCHAR);
223
224 if (UserInfo->FullName.Length > 0)
225 Size += UserInfo->FullName.Length + sizeof(WCHAR);
226
227 if (UserInfo->AdminComment.Length > 0)
228 Size += UserInfo->AdminComment.Length + sizeof(WCHAR);
229 break;
230
231 // case 23:
232
233 default:
234 ApiStatus = ERROR_INVALID_LEVEL;
235 goto done;
236 }
237
238 ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer);
239 if (ApiStatus != NERR_Success)
240 goto done;
241
242 ZeroMemory(LocalBuffer, Size);
243
244 switch (level)
245 {
246 case 0:
247 UserInfo0 = (PUSER_INFO_0)LocalBuffer;
248
249 Ptr = (LPWSTR)((ULONG_PTR)UserInfo0 + sizeof(USER_INFO_0));
250 UserInfo0->usri0_name = Ptr;
251
252 memcpy(UserInfo0->usri0_name,
253 UserInfo->UserName.Buffer,
254 UserInfo->UserName.Length);
255 UserInfo0->usri0_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
256 break;
257
258 case 1:
259 UserInfo1 = (PUSER_INFO_1)LocalBuffer;
260
261 Ptr = (LPWSTR)((ULONG_PTR)UserInfo1 + sizeof(USER_INFO_1));
262
263 UserInfo1->usri1_name = Ptr;
264
265 memcpy(UserInfo1->usri1_name,
266 UserInfo->UserName.Buffer,
267 UserInfo->UserName.Length);
268 UserInfo1->usri1_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
269
270 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
271
272 UserInfo1->usri1_password = NULL;
273
274 /* FIXME: UserInfo1->usri1_password_age */
275 /* FIXME: UserInfo1->usri1_priv */
276
277 if (UserInfo->HomeDirectory.Length > 0)
278 {
279 UserInfo1->usri1_home_dir = Ptr;
280
281 memcpy(UserInfo1->usri1_home_dir,
282 UserInfo->HomeDirectory.Buffer,
283 UserInfo->HomeDirectory.Length);
284 UserInfo1->usri1_home_dir[UserInfo->HomeDirectory.Length / sizeof(WCHAR)] = UNICODE_NULL;
285
286 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->HomeDirectory.Length + sizeof(WCHAR));
287 }
288
289 if (UserInfo->AdminComment.Length > 0)
290 {
291 UserInfo1->usri1_comment = Ptr;
292
293 memcpy(UserInfo1->usri1_comment,
294 UserInfo->AdminComment.Buffer,
295 UserInfo->AdminComment.Length);
296 UserInfo1->usri1_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
297
298 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
299 }
300
301 // UserInfo1->usri1_flags = UserInfo->UserAccountControl;
302
303 if (UserInfo->ScriptPath.Length > 0)
304 {
305 UserInfo1->usri1_script_path = Ptr;
306
307 memcpy(UserInfo1->usri1_script_path,
308 UserInfo->ScriptPath.Buffer,
309 UserInfo->ScriptPath.Length);
310 UserInfo1->usri1_script_path[UserInfo->ScriptPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
311 }
312 break;
313
314 // case 2:
315 // case 3:
316 // case 4:
317
318 case 10:
319 UserInfo10 = (PUSER_INFO_10)LocalBuffer;
320
321 Ptr = (LPWSTR)((ULONG_PTR)UserInfo10 + sizeof(USER_INFO_10));
322
323 UserInfo10->usri10_name = Ptr;
324
325 memcpy(UserInfo10->usri10_name,
326 UserInfo->UserName.Buffer,
327 UserInfo->UserName.Length);
328 UserInfo10->usri10_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
329
330 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
331
332 if (UserInfo->AdminComment.Length > 0)
333 {
334 UserInfo10->usri10_comment = Ptr;
335
336 memcpy(UserInfo10->usri10_comment,
337 UserInfo->AdminComment.Buffer,
338 UserInfo->AdminComment.Length);
339 UserInfo10->usri10_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
340
341 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
342 }
343
344 /* FIXME: UserInfo10->usri10_usr_comment */
345
346 if (UserInfo->FullName.Length > 0)
347 {
348 UserInfo10->usri10_full_name = Ptr;
349
350 memcpy(UserInfo10->usri10_full_name,
351 UserInfo->FullName.Buffer,
352 UserInfo->FullName.Length);
353 UserInfo10->usri10_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
354 }
355 break;
356
357 // case 11:
358
359 case 20:
360 UserInfo20 = (PUSER_INFO_20)LocalBuffer;
361
362 Ptr = (LPWSTR)((ULONG_PTR)UserInfo20 + sizeof(USER_INFO_20));
363
364 UserInfo20->usri20_name = Ptr;
365
366 memcpy(UserInfo20->usri20_name,
367 UserInfo->UserName.Buffer,
368 UserInfo->UserName.Length);
369 UserInfo20->usri20_name[UserInfo->UserName.Length / sizeof(WCHAR)] = UNICODE_NULL;
370
371 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->UserName.Length + sizeof(WCHAR));
372
373 if (UserInfo->FullName.Length > 0)
374 {
375 UserInfo20->usri20_full_name = Ptr;
376
377 memcpy(UserInfo20->usri20_full_name,
378 UserInfo->FullName.Buffer,
379 UserInfo->FullName.Length);
380 UserInfo20->usri20_full_name[UserInfo->FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
381
382 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->FullName.Length + sizeof(WCHAR));
383 }
384
385 if (UserInfo->AdminComment.Length > 0)
386 {
387 UserInfo20->usri20_comment = Ptr;
388
389 memcpy(UserInfo20->usri20_comment,
390 UserInfo->AdminComment.Buffer,
391 UserInfo->AdminComment.Length);
392 UserInfo20->usri20_comment[UserInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
393
394 Ptr = (LPWSTR)((ULONG_PTR)Ptr + UserInfo->AdminComment.Length + sizeof(WCHAR));
395 }
396
397 // UserInfo20->usri20_flags = UserInfo->UserAccountControl;
398 UserInfo20->usri20_user_id = RelativeId;
399 break;
400
401 // case 23:
402 }
403
404 done:
405 if (ApiStatus == NERR_Success)
406 {
407 *Buffer = LocalBuffer;
408 }
409 else
410 {
411 if (LocalBuffer != NULL)
412 NetApiBufferFree(LocalBuffer);
413 }
414
415 return ApiStatus;
416 }
417
418
419 static
420 VOID
421 FreeUserInfo(PUSER_ACCOUNT_INFORMATION UserInfo)
422 {
423 if (UserInfo->UserName.Buffer != NULL)
424 SamFreeMemory(UserInfo->UserName.Buffer);
425
426 if (UserInfo->FullName.Buffer != NULL)
427 SamFreeMemory(UserInfo->FullName.Buffer);
428
429 if (UserInfo->HomeDirectory.Buffer != NULL)
430 SamFreeMemory(UserInfo->HomeDirectory.Buffer);
431
432 if (UserInfo->HomeDirectoryDrive.Buffer != NULL)
433 SamFreeMemory(UserInfo->HomeDirectoryDrive.Buffer);
434
435 if (UserInfo->ScriptPath.Buffer != NULL)
436 SamFreeMemory(UserInfo->ScriptPath.Buffer);
437
438 if (UserInfo->ProfilePath.Buffer != NULL)
439 SamFreeMemory(UserInfo->ProfilePath.Buffer);
440
441 if (UserInfo->AdminComment.Buffer != NULL)
442 SamFreeMemory(UserInfo->AdminComment.Buffer);
443
444 if (UserInfo->WorkStations.Buffer != NULL)
445 SamFreeMemory(UserInfo->WorkStations.Buffer);
446
447 if (UserInfo->LogonHours.LogonHours != NULL)
448 SamFreeMemory(UserInfo->LogonHours.LogonHours);
449
450 SamFreeMemory(UserInfo);
451 }
452
453
454 static
455 NET_API_STATUS
456 SetUserInfo(SAM_HANDLE UserHandle,
457 LPBYTE UserInfo,
458 DWORD Level)
459 {
460 USER_ALL_INFORMATION UserAllInfo;
461 PUSER_INFO_1 UserInfo1;
462 PUSER_INFO_3 UserInfo3;
463 NET_API_STATUS ApiStatus = NERR_Success;
464 NTSTATUS Status = STATUS_SUCCESS;
465
466 ZeroMemory(&UserAllInfo, sizeof(USER_ALL_INFORMATION));
467
468 switch (Level)
469 {
470 case 1:
471 UserInfo1 = (PUSER_INFO_1)UserInfo;
472 // RtlInitUnicodeString(&UserAllInfo.UserName,
473 // UserInfo1->usri1_name);
474
475 RtlInitUnicodeString(&UserAllInfo.AdminComment,
476 UserInfo1->usri1_comment);
477
478 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
479 UserInfo1->usri1_home_dir);
480
481 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
482 UserInfo1->usri1_script_path);
483
484 RtlInitUnicodeString(&UserAllInfo.NtPassword,
485 UserInfo1->usri1_password);
486 UserAllInfo.NtPasswordPresent = TRUE;
487
488 // UserInfo1->usri1_flags
489 // UserInfo1->usri1_priv
490
491 UserAllInfo.WhichFields =
492 USER_ALL_ADMINCOMMENT |
493 USER_ALL_HOMEDIRECTORY |
494 USER_ALL_SCRIPTPATH |
495 USER_ALL_NTPASSWORDPRESENT
496 // USER_ALL_USERACCOUNTCONTROL
497 ;
498 break;
499
500
501 case 3:
502 UserInfo3 = (PUSER_INFO_3)UserInfo;
503
504 // LPWSTR usri3_name;
505
506 RtlInitUnicodeString(&UserAllInfo.NtPassword,
507 UserInfo3->usri3_password);
508 UserAllInfo.NtPasswordPresent = TRUE;
509
510 // DWORD usri3_password_age; // ignored
511 // DWORD usri3_priv;
512
513 RtlInitUnicodeString(&UserAllInfo.HomeDirectory,
514 UserInfo3->usri3_home_dir);
515
516 RtlInitUnicodeString(&UserAllInfo.AdminComment,
517 UserInfo3->usri3_comment);
518
519 // DWORD usri3_flags;
520
521 RtlInitUnicodeString(&UserAllInfo.ScriptPath,
522 UserInfo3->usri3_script_path);
523
524 // DWORD usri3_auth_flags;
525
526 RtlInitUnicodeString(&UserAllInfo.FullName,
527 UserInfo3->usri3_full_name);
528
529 // LPWSTR usri3_usr_comment;
530 // LPWSTR usri3_parms;
531 // LPWSTR usri3_workstations;
532 // DWORD usri3_last_logon;
533 // DWORD usri3_last_logoff;
534 // DWORD usri3_acct_expires;
535 // DWORD usri3_max_storage;
536 // DWORD usri3_units_per_week;
537 // PBYTE usri3_logon_hours;
538 // DWORD usri3_bad_pw_count;
539 // DWORD usri3_num_logons;
540 // LPWSTR usri3_logon_server;
541 // DWORD usri3_country_code;
542 // DWORD usri3_code_page;
543 // DWORD usri3_user_id; // ignored
544 // DWORD usri3_primary_group_id;
545 // LPWSTR usri3_profile;
546 // LPWSTR usri3_home_dir_drive;
547 // DWORD usri3_password_expired;
548
549 UserAllInfo.WhichFields =
550 USER_ALL_NTPASSWORDPRESENT |
551 USER_ALL_HOMEDIRECTORY |
552 USER_ALL_ADMINCOMMENT |
553 USER_ALL_SCRIPTPATH |
554 USER_ALL_FULLNAME
555 // USER_ALL_USERACCOUNTCONTROL
556 ;
557 break;
558
559 default:
560 ERR("Unsupported level %lu!\n", Level);
561 return ERROR_INVALID_PARAMETER;
562 }
563
564 Status = SamSetInformationUser(UserHandle,
565 UserAllInformation,
566 &UserAllInfo);
567 if (!NT_SUCCESS(Status))
568 {
569 ERR("SamSetInformationUser failed (Status %08lx)\n", Status);
570 ApiStatus = NetpNtStatusToApiStatus(Status);
571 goto done;
572 }
573
574 done:
575 return ApiStatus;
576 }
577
578
579 /************************************************************
580 * NetUserAdd (NETAPI32.@)
581 */
582 NET_API_STATUS
583 WINAPI
584 NetUserAdd(LPCWSTR servername,
585 DWORD level,
586 LPBYTE bufptr,
587 LPDWORD parm_err)
588 {
589 UNICODE_STRING ServerName;
590 UNICODE_STRING UserName;
591 SAM_HANDLE ServerHandle = NULL;
592 SAM_HANDLE DomainHandle = NULL;
593 SAM_HANDLE UserHandle = NULL;
594 ULONG GrantedAccess;
595 ULONG RelativeId;
596 NET_API_STATUS ApiStatus = NERR_Success;
597 NTSTATUS Status = STATUS_SUCCESS;
598
599 TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr, parm_err);
600
601 /* Check the info level */
602 if (level < 1 || level > 4)
603 return ERROR_INVALID_LEVEL;
604
605 if (servername != NULL)
606 RtlInitUnicodeString(&ServerName, servername);
607
608 /* Connect to the SAM Server */
609 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
610 &ServerHandle,
611 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
612 NULL);
613 if (!NT_SUCCESS(Status))
614 {
615 ERR("SamConnect failed (Status %08lx)\n", Status);
616 ApiStatus = NetpNtStatusToApiStatus(Status);
617 goto done;
618 }
619
620 /* Open the Account Domain */
621 Status = OpenAccountDomain(ServerHandle,
622 (servername != NULL) ? &ServerName : NULL,
623 DOMAIN_CREATE_USER | DOMAIN_LOOKUP,
624 &DomainHandle);
625 if (!NT_SUCCESS(Status))
626 {
627 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
628 ApiStatus = NetpNtStatusToApiStatus(Status);
629 goto done;
630 }
631
632 /* Initialize the user name string */
633 RtlInitUnicodeString(&UserName,
634 ((PUSER_INFO_1)bufptr)->usri1_name);
635
636 /* Create the user account */
637 Status = SamCreateUser2InDomain(DomainHandle,
638 &UserName,
639 USER_NORMAL_ACCOUNT,
640 USER_ALL_ACCESS | DELETE | WRITE_DAC,
641 &UserHandle,
642 &GrantedAccess,
643 &RelativeId);
644 if (!NT_SUCCESS(Status))
645 {
646 ERR("SamCreateUser2InDomain failed (Status %08lx)\n", Status);
647 ApiStatus = NetpNtStatusToApiStatus(Status);
648 goto done;
649 }
650
651 /* Set user information */
652 ApiStatus = SetUserInfo(UserHandle,
653 bufptr,
654 level);
655 if (ApiStatus != NERR_Success)
656 {
657 ERR("SetUserInfo failed (Status %lu)\n", ApiStatus);
658 goto done;
659 }
660
661 done:
662 if (UserHandle != NULL)
663 SamCloseHandle(UserHandle);
664
665 if (DomainHandle != NULL)
666 SamCloseHandle(DomainHandle);
667
668 if (ServerHandle != NULL)
669 SamCloseHandle(ServerHandle);
670
671 return ApiStatus;
672 }
673
674
675 /******************************************************************************
676 * NetUserChangePassword (NETAPI32.@)
677 * PARAMS
678 * domainname [I] Optional. Domain on which the user resides or the logon
679 * domain of the current user if NULL.
680 * username [I] Optional. Username to change the password for or the name
681 * of the current user if NULL.
682 * oldpassword [I] The user's current password.
683 * newpassword [I] The password that the user will be changed to using.
684 *
685 * RETURNS
686 * Success: NERR_Success.
687 * Failure: NERR_* failure code or win error code.
688 *
689 */
690 NET_API_STATUS
691 WINAPI
692 NetUserChangePassword(LPCWSTR domainname,
693 LPCWSTR username,
694 LPCWSTR oldpassword,
695 LPCWSTR newpassword)
696 {
697 struct sam_user *user;
698
699 TRACE("(%s, %s, ..., ...)\n", debugstr_w(domainname), debugstr_w(username));
700
701 if(domainname)
702 FIXME("Ignoring domainname %s.\n", debugstr_w(domainname));
703
704 if((user = NETAPI_FindUser(username)) == NULL)
705 return NERR_UserNotFound;
706
707 if(lstrcmpW(user->user_password, oldpassword) != 0)
708 return ERROR_INVALID_PASSWORD;
709
710 if(lstrlenW(newpassword) > PWLEN)
711 return ERROR_PASSWORD_RESTRICTION;
712
713 lstrcpyW(user->user_password, newpassword);
714
715 return NERR_Success;
716 }
717
718
719 /************************************************************
720 * NetUserDel (NETAPI32.@)
721 */
722 NET_API_STATUS
723 WINAPI
724 NetUserDel(LPCWSTR servername,
725 LPCWSTR username)
726 {
727 NET_API_STATUS status;
728 struct sam_user *user;
729
730 TRACE("(%s, %s)\n", debugstr_w(servername), debugstr_w(username));
731
732 if((status = NETAPI_ValidateServername(servername))!= NERR_Success)
733 return status;
734
735 if ((user = NETAPI_FindUser(username)) == NULL)
736 return NERR_UserNotFound;
737
738 list_remove(&user->entry);
739
740 HeapFree(GetProcessHeap(), 0, user->home_dir);
741 HeapFree(GetProcessHeap(), 0, user->user_comment);
742 HeapFree(GetProcessHeap(), 0, user->user_logon_script_path);
743 HeapFree(GetProcessHeap(), 0, user);
744
745 return NERR_Success;
746 }
747
748
749 /************************************************************
750 * NetUserEnum (NETAPI32.@)
751 */
752 NET_API_STATUS
753 WINAPI
754 NetUserEnum(LPCWSTR servername,
755 DWORD level,
756 DWORD filter,
757 LPBYTE* bufptr,
758 DWORD prefmaxlen,
759 LPDWORD entriesread,
760 LPDWORD totalentries,
761 LPDWORD resume_handle)
762 {
763 UNICODE_STRING ServerName;
764 PSAM_RID_ENUMERATION CurrentUser;
765 PENUM_CONTEXT EnumContext = NULL;
766 LPVOID Buffer = NULL;
767 ULONG i;
768 SAM_HANDLE UserHandle = NULL;
769 PUSER_ACCOUNT_INFORMATION UserInfo = NULL;
770
771 NET_API_STATUS ApiStatus = NERR_Success;
772 NTSTATUS Status = STATUS_SUCCESS;
773
774 FIXME("(%s %d 0x%d %p %d %p %p %p) stub!\n", debugstr_w(servername), level,
775 filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
776
777 *entriesread = 0;
778 *totalentries = 0;
779 *bufptr = NULL;
780
781 if (servername != NULL)
782 RtlInitUnicodeString(&ServerName, servername);
783
784 if (resume_handle != NULL && *resume_handle != 0)
785 {
786 EnumContext = (PENUM_CONTEXT)*resume_handle;
787 }
788 else
789 {
790 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
791 if (ApiStatus != NERR_Success)
792 goto done;
793
794 EnumContext->EnumerationContext = 0;
795 EnumContext->Buffer = NULL;
796 EnumContext->Count = 0;
797 EnumContext->Index = 0;
798 EnumContext->BuiltinDone = FALSE;
799
800 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
801 &EnumContext->ServerHandle,
802 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
803 NULL);
804 if (!NT_SUCCESS(Status))
805 {
806 ERR("SamConnect failed (Status %08lx)\n", Status);
807 ApiStatus = NetpNtStatusToApiStatus(Status);
808 goto done;
809 }
810
811 Status = OpenAccountDomain(EnumContext->ServerHandle,
812 (servername != NULL) ? &ServerName : NULL,
813 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
814 &EnumContext->AccountDomainHandle);
815 if (!NT_SUCCESS(Status))
816 {
817 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
818 ApiStatus = NetpNtStatusToApiStatus(Status);
819 goto done;
820 }
821
822 Status = OpenBuiltinDomain(EnumContext->ServerHandle,
823 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
824 &EnumContext->BuiltinDomainHandle);
825 if (!NT_SUCCESS(Status))
826 {
827 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
828 ApiStatus = NetpNtStatusToApiStatus(Status);
829 goto done;
830 }
831 }
832
833 // while (TRUE)
834 // {
835 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
836 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
837
838 if (EnumContext->Index >= EnumContext->Count)
839 {
840 // if (EnumContext->BuiltinDone == TRUE)
841 // {
842 // ApiStatus = NERR_Success;
843 // goto done;
844 // }
845
846 TRACE("Calling SamEnumerateUsersInDomain\n");
847 Status = SamEnumerateUsersInDomain(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
848 &EnumContext->EnumerationContext,
849 0,
850 (PVOID *)&EnumContext->Buffer,
851 prefmaxlen,
852 &EnumContext->Count);
853
854 TRACE("SamEnumerateUsersInDomain returned (Status %08lx)\n", Status);
855 if (!NT_SUCCESS(Status))
856 {
857 ERR("SamEnumerateUsersInDomain failed (Status %08lx)\n", Status);
858 ApiStatus = NetpNtStatusToApiStatus(Status);
859 goto done;
860 }
861
862 if (Status == STATUS_MORE_ENTRIES)
863 {
864 ApiStatus = NERR_BufTooSmall;
865 goto done;
866 }
867 else
868 {
869 EnumContext->BuiltinDone = TRUE;
870 }
871 }
872
873 TRACE("EnumContext: %lu\n", EnumContext);
874 TRACE("EnumContext->Count: %lu\n", EnumContext->Count);
875 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
876
877 /* Get a pointer to the current user */
878 CurrentUser = &EnumContext->Buffer[EnumContext->Index];
879
880 TRACE("RID: %lu\n", CurrentUser->RelativeId);
881
882 Status = SamOpenUser(EnumContext->AccountDomainHandle, //BuiltinDomainHandle,
883 USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
884 CurrentUser->RelativeId,
885 &UserHandle);
886 if (!NT_SUCCESS(Status))
887 {
888 ERR("SamOpenUser failed (Status %08lx)\n", Status);
889 ApiStatus = NetpNtStatusToApiStatus(Status);
890 goto done;
891 }
892
893 Status = SamQueryInformationUser(UserHandle,
894 UserAccountInformation,
895 (PVOID *)&UserInfo);
896 if (!NT_SUCCESS(Status))
897 {
898 ERR("SamQueryInformationUser failed (Status %08lx)\n", Status);
899 ApiStatus = NetpNtStatusToApiStatus(Status);
900 goto done;
901 }
902
903 SamCloseHandle(UserHandle);
904 UserHandle = NULL;
905
906 ApiStatus = BuildUserInfoBuffer(UserInfo,
907 level,
908 CurrentUser->RelativeId,
909 &Buffer);
910 if (ApiStatus != NERR_Success)
911 {
912 ERR("BuildUserInfoBuffer failed (ApiStatus %lu)\n", ApiStatus);
913 goto done;
914 }
915
916 if (UserInfo != NULL)
917 {
918 FreeUserInfo(UserInfo);
919 UserInfo = NULL;
920 }
921
922 EnumContext->Index++;
923
924 (*entriesread)++;
925 // }
926
927 done:
928 if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count)
929 ApiStatus = ERROR_MORE_DATA;
930
931 if (EnumContext != NULL)
932 *totalentries = EnumContext->Count;
933
934 if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
935 {
936 if (EnumContext != NULL)
937 {
938 if (EnumContext->BuiltinDomainHandle != NULL)
939 SamCloseHandle(EnumContext->BuiltinDomainHandle);
940
941 if (EnumContext->AccountDomainHandle != NULL)
942 SamCloseHandle(EnumContext->AccountDomainHandle);
943
944 if (EnumContext->ServerHandle != NULL)
945 SamCloseHandle(EnumContext->ServerHandle);
946
947 if (EnumContext->Buffer != NULL)
948 {
949 for (i = 0; i < EnumContext->Count; i++)
950 {
951 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
952 }
953
954 SamFreeMemory(EnumContext->Buffer);
955 }
956
957 NetApiBufferFree(EnumContext);
958 EnumContext = NULL;
959 }
960 }
961
962 if (UserHandle != NULL)
963 SamCloseHandle(UserHandle);
964
965 if (UserInfo != NULL)
966 FreeUserInfo(UserInfo);
967
968 if (resume_handle != NULL)
969 *resume_handle = (DWORD_PTR)EnumContext;
970
971 *bufptr = (LPBYTE)Buffer;
972
973 TRACE("return %lu\n", ApiStatus);
974
975 return ApiStatus;
976 }
977
978
979 /************************************************************
980 * NetUserGetGroups (NETAPI32.@)
981 */
982 NET_API_STATUS
983 WINAPI
984 NetUserGetGroups(LPCWSTR servername,
985 LPCWSTR username,
986 DWORD level,
987 LPBYTE *bufptr,
988 DWORD prefixmaxlen,
989 LPDWORD entriesread,
990 LPDWORD totalentries)
991 {
992 FIXME("%s %s %d %p %d %p %p stub\n", debugstr_w(servername),
993 debugstr_w(username), level, bufptr, prefixmaxlen, entriesread,
994 totalentries);
995
996 *bufptr = NULL;
997 *entriesread = 0;
998 *totalentries = 0;
999
1000 return ERROR_INVALID_LEVEL;
1001 }
1002
1003
1004 /************************************************************
1005 * NetUserGetInfo (NETAPI32.@)
1006 */
1007 NET_API_STATUS
1008 WINAPI
1009 NetUserGetInfo(LPCWSTR servername,
1010 LPCWSTR username,
1011 DWORD level,
1012 LPBYTE* bufptr)
1013 {
1014 UNICODE_STRING ServerName;
1015 UNICODE_STRING UserName;
1016 SAM_HANDLE ServerHandle = NULL;
1017 SAM_HANDLE AccountDomainHandle = NULL;
1018 SAM_HANDLE UserHandle = NULL;
1019 PULONG RelativeIds = NULL;
1020 PSID_NAME_USE Use = NULL;
1021 PUSER_ACCOUNT_INFORMATION UserInfo = NULL;
1022 LPVOID Buffer = NULL;
1023 NET_API_STATUS ApiStatus = NERR_Success;
1024 NTSTATUS Status = STATUS_SUCCESS;
1025
1026 TRACE("(%s, %s, %d, %p)\n", debugstr_w(servername),
1027 debugstr_w(username), level, bufptr);
1028
1029 if (servername != NULL)
1030 RtlInitUnicodeString(&ServerName, servername);
1031
1032 RtlInitUnicodeString(&UserName, username);
1033
1034 /* Connect to the SAM Server */
1035 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1036 &ServerHandle,
1037 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1038 NULL);
1039 if (!NT_SUCCESS(Status))
1040 {
1041 ERR("SamConnect failed (Status %08lx)\n", Status);
1042 ApiStatus = NetpNtStatusToApiStatus(Status);
1043 goto done;
1044 }
1045
1046 /* Open the Account Domain */
1047 Status = OpenAccountDomain(ServerHandle,
1048 (servername != NULL) ? &ServerName : NULL,
1049 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
1050 &AccountDomainHandle);
1051 if (!NT_SUCCESS(Status))
1052 {
1053 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1054 ApiStatus = NetpNtStatusToApiStatus(Status);
1055 goto done;
1056 }
1057
1058 /* Get the RID for the given user name */
1059 Status = SamLookupNamesInDomain(AccountDomainHandle,
1060 1,
1061 &UserName,
1062 &RelativeIds,
1063 &Use);
1064 if (!NT_SUCCESS(Status))
1065 {
1066 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
1067 ApiStatus = NetpNtStatusToApiStatus(Status);
1068 goto done;
1069 }
1070
1071 /* Check if the account is a user account */
1072 if (Use[0] != SidTypeUser)
1073 {
1074 ERR("No user found!\n");
1075 ApiStatus = NERR_UserNotFound;
1076 goto done;
1077 }
1078
1079 TRACE("RID: %lu\n", RelativeIds[0]);
1080
1081 /* Open the user object */
1082 Status = SamOpenUser(AccountDomainHandle,
1083 USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT,
1084 RelativeIds[0],
1085 &UserHandle);
1086 if (!NT_SUCCESS(Status))
1087 {
1088 ERR("SamOpenUser failed (Status %08lx)\n", Status);
1089 ApiStatus = NetpNtStatusToApiStatus(Status);
1090 goto done;
1091 }
1092
1093 Status = SamQueryInformationUser(UserHandle,
1094 UserAccountInformation,
1095 (PVOID *)&UserInfo);
1096 if (!NT_SUCCESS(Status))
1097 {
1098 ERR("SamQueryInformationUser failed (Status %08lx)\n", Status);
1099 ApiStatus = NetpNtStatusToApiStatus(Status);
1100 goto done;
1101 }
1102
1103 ApiStatus = BuildUserInfoBuffer(UserInfo,
1104 level,
1105 RelativeIds[0],
1106 &Buffer);
1107 if (ApiStatus != NERR_Success)
1108 {
1109 ERR("BuildUserInfoBuffer failed (ApiStatus %08lu)\n", ApiStatus);
1110 goto done;
1111 }
1112
1113 done:
1114 if (UserInfo != NULL)
1115 FreeUserInfo(UserInfo);
1116
1117 if (UserHandle != NULL)
1118 SamCloseHandle(UserHandle);
1119
1120 if (RelativeIds != NULL)
1121 SamFreeMemory(RelativeIds);
1122
1123 if (Use != NULL)
1124 SamFreeMemory(Use);
1125
1126 if (AccountDomainHandle != NULL)
1127 SamCloseHandle(AccountDomainHandle);
1128
1129 if (ServerHandle != NULL)
1130 SamCloseHandle(ServerHandle);
1131
1132 *bufptr = (LPBYTE)Buffer;
1133
1134 return ApiStatus;
1135 }
1136
1137
1138 /************************************************************
1139 * NetUserGetLocalGroups (NETAPI32.@)
1140 */
1141 NET_API_STATUS
1142 WINAPI
1143 NetUserGetLocalGroups(LPCWSTR servername,
1144 LPCWSTR username,
1145 DWORD level,
1146 DWORD flags,
1147 LPBYTE* bufptr,
1148 DWORD prefmaxlen,
1149 LPDWORD entriesread,
1150 LPDWORD totalentries)
1151 {
1152 UNICODE_STRING ServerName;
1153 UNICODE_STRING UserName;
1154 SAM_HANDLE ServerHandle = NULL;
1155 SAM_HANDLE BuiltinDomainHandle = NULL;
1156 SAM_HANDLE AccountDomainHandle = NULL;
1157 PSID AccountDomainSid = NULL;
1158 PSID UserSid = NULL;
1159 PULONG RelativeIds = NULL;
1160 PSID_NAME_USE Use = NULL;
1161 ULONG BuiltinMemberCount = 0;
1162 ULONG AccountMemberCount = 0;
1163 PULONG BuiltinAliases = NULL;
1164 PULONG AccountAliases = NULL;
1165 PUNICODE_STRING BuiltinNames = NULL;
1166 PUNICODE_STRING AccountNames = NULL;
1167 PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
1168 ULONG Size;
1169 ULONG Count = 0;
1170 ULONG Index;
1171 ULONG i;
1172 LPWSTR StrPtr;
1173 NET_API_STATUS ApiStatus = NERR_Success;
1174 NTSTATUS Status = STATUS_SUCCESS;
1175
1176 TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
1177 debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
1178 prefmaxlen, entriesread, totalentries);
1179
1180 if (level != 0)
1181 return ERROR_INVALID_LEVEL;
1182
1183 if (flags & ~LG_INCLUDE_INDIRECT)
1184 return ERROR_INVALID_PARAMETER;
1185
1186 if (flags & LG_INCLUDE_INDIRECT)
1187 {
1188 WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
1189 }
1190
1191 if (servername != NULL)
1192 RtlInitUnicodeString(&ServerName, servername);
1193
1194 RtlInitUnicodeString(&UserName, username);
1195
1196 /* Connect to the SAM Server */
1197 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1198 &ServerHandle,
1199 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1200 NULL);
1201 if (!NT_SUCCESS(Status))
1202 {
1203 ERR("SamConnect failed (Status %08lx)\n", Status);
1204 ApiStatus = NetpNtStatusToApiStatus(Status);
1205 goto done;
1206 }
1207
1208 /* Open the Builtin Domain */
1209 Status = OpenBuiltinDomain(ServerHandle,
1210 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
1211 &BuiltinDomainHandle);
1212 if (!NT_SUCCESS(Status))
1213 {
1214 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
1215 ApiStatus = NetpNtStatusToApiStatus(Status);
1216 goto done;
1217 }
1218
1219 /* Get the Account Domain SID */
1220 Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
1221 &AccountDomainSid);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
1225 ApiStatus = NetpNtStatusToApiStatus(Status);
1226 goto done;
1227 }
1228
1229 /* Open the Account Domain */
1230 Status = SamOpenDomain(ServerHandle,
1231 DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
1232 AccountDomainSid,
1233 &AccountDomainHandle);
1234 if (!NT_SUCCESS(Status))
1235 {
1236 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1237 ApiStatus = NetpNtStatusToApiStatus(Status);
1238 goto done;
1239 }
1240
1241 /* Get the RID for the given user name */
1242 Status = SamLookupNamesInDomain(AccountDomainHandle,
1243 1,
1244 &UserName,
1245 &RelativeIds,
1246 &Use);
1247 if (!NT_SUCCESS(Status))
1248 {
1249 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
1250 ApiStatus = NetpNtStatusToApiStatus(Status);
1251 goto done;
1252 }
1253
1254 /* Fail, if it is not a user account */
1255 if (Use[0] != SidTypeUser)
1256 {
1257 ERR("Account is not a User!\n");
1258 ApiStatus = NERR_UserNotFound;
1259 goto done;
1260 }
1261
1262 /* Build the User SID from the Account Domain SID and the users RID */
1263 UserSid = CreateSidFromSidAndRid(AccountDomainSid,
1264 RelativeIds[0]);
1265 if (UserSid == NULL)
1266 {
1267 ERR("CreateSidFromSidAndRid failed!\n");
1268 ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
1269 goto done;
1270 }
1271
1272 /* Get alias memberships in the Builtin Domain */
1273 Status = SamGetAliasMembership(BuiltinDomainHandle,
1274 1,
1275 &UserSid,
1276 &BuiltinMemberCount,
1277 &BuiltinAliases);
1278 if (!NT_SUCCESS(Status))
1279 {
1280 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
1281 ApiStatus = NetpNtStatusToApiStatus(Status);
1282 goto done;
1283 }
1284
1285 if (BuiltinMemberCount > 0)
1286 {
1287 /* Get the Names of the builtin alias members */
1288 Status = SamLookupIdsInDomain(BuiltinDomainHandle,
1289 BuiltinMemberCount,
1290 BuiltinAliases,
1291 &BuiltinNames,
1292 NULL);
1293 if (!NT_SUCCESS(Status))
1294 {
1295 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
1296 ApiStatus = NetpNtStatusToApiStatus(Status);
1297 goto done;
1298 }
1299 }
1300
1301 /* Get alias memberships in the Account Domain */
1302 Status = SamGetAliasMembership(AccountDomainHandle,
1303 1,
1304 &UserSid,
1305 &AccountMemberCount,
1306 &AccountAliases);
1307 if (!NT_SUCCESS(Status))
1308 {
1309 ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
1310 ApiStatus = NetpNtStatusToApiStatus(Status);
1311 goto done;
1312 }
1313
1314 if (AccountMemberCount > 0)
1315 {
1316 /* Get the Names of the builtin alias members */
1317 Status = SamLookupIdsInDomain(AccountDomainHandle,
1318 AccountMemberCount,
1319 AccountAliases,
1320 &AccountNames,
1321 NULL);
1322 if (!NT_SUCCESS(Status))
1323 {
1324 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
1325 ApiStatus = NetpNtStatusToApiStatus(Status);
1326 goto done;
1327 }
1328 }
1329
1330 /* Calculate the required buffer size */
1331 Size = 0;
1332
1333 for (i = 0; i < BuiltinMemberCount; i++)
1334 {
1335 if (BuiltinNames[i].Length > 0)
1336 {
1337 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
1338 Count++;
1339 }
1340 }
1341
1342 for (i = 0; i < AccountMemberCount; i++)
1343 {
1344 if (BuiltinNames[i].Length > 0)
1345 {
1346 Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length + sizeof(UNICODE_NULL));
1347 Count++;
1348 }
1349 }
1350
1351 if (Size == 0)
1352 {
1353 ApiStatus = NERR_Success;
1354 goto done;
1355 }
1356
1357 /* Allocate buffer */
1358 ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
1359 if (ApiStatus != NERR_Success)
1360 goto done;
1361
1362 ZeroMemory(Buffer, Size);
1363
1364 StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
1365
1366 /* Copy data to the allocated buffer */
1367 Index = 0;
1368 for (i = 0; i < BuiltinMemberCount; i++)
1369 {
1370 if (BuiltinNames[i].Length > 0)
1371 {
1372 CopyMemory(StrPtr,
1373 BuiltinNames[i].Buffer,
1374 BuiltinNames[i].Length);
1375 Buffer[Index].lgrui0_name = StrPtr;
1376
1377 StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length + sizeof(UNICODE_NULL));
1378 Index++;
1379 }
1380 }
1381
1382 for (i = 0; i < AccountMemberCount; i++)
1383 {
1384 if (AccountNames[i].Length > 0)
1385 {
1386 CopyMemory(StrPtr,
1387 AccountNames[i].Buffer,
1388 AccountNames[i].Length);
1389 Buffer[Index].lgrui0_name = StrPtr;
1390
1391 StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length + sizeof(UNICODE_NULL));
1392 Index++;
1393 }
1394 }
1395
1396 done:
1397 if (AccountNames != NULL)
1398 SamFreeMemory(AccountNames);
1399
1400 if (BuiltinNames != NULL)
1401 SamFreeMemory(BuiltinNames);
1402
1403 if (AccountAliases != NULL)
1404 SamFreeMemory(AccountAliases);
1405
1406 if (BuiltinAliases != NULL)
1407 SamFreeMemory(BuiltinAliases);
1408
1409 if (RelativeIds != NULL)
1410 SamFreeMemory(RelativeIds);
1411
1412 if (Use != NULL)
1413 SamFreeMemory(Use);
1414
1415 if (UserSid != NULL)
1416 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
1417
1418 if (AccountDomainSid != NULL)
1419 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1420
1421 if (AccountDomainHandle != NULL)
1422 SamCloseHandle(AccountDomainHandle);
1423
1424 if (BuiltinDomainHandle != NULL)
1425 SamCloseHandle(BuiltinDomainHandle);
1426
1427 if (ServerHandle != NULL)
1428 SamCloseHandle(ServerHandle);
1429
1430 if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
1431 {
1432 *entriesread = 0;
1433 *totalentries = 0;
1434 }
1435 else
1436 {
1437 *entriesread = Count;
1438 *totalentries = Count;
1439 }
1440
1441 *bufptr = (LPBYTE)Buffer;
1442
1443 return ApiStatus;
1444 }
1445
1446
1447 /******************************************************************************
1448 * NetUserSetGroups (NETAPI32.@)
1449 */
1450 NET_API_STATUS
1451 WINAPI
1452 NetUserSetGroups(LPCWSTR servername,
1453 LPCWSTR username,
1454 DWORD level,
1455 LPBYTE buf,
1456 DWORD num_entries)
1457 {
1458 FIXME("(%s %s %lu %p %lu)\n",
1459 debugstr_w(servername), debugstr_w(username), level, buf, num_entries);
1460 return ERROR_ACCESS_DENIED;
1461 }
1462
1463
1464 /******************************************************************************
1465 * NetUserSetInfo (NETAPI32.@)
1466 */
1467 NET_API_STATUS
1468 WINAPI
1469 NetUserSetInfo(LPCWSTR servername,
1470 LPCWSTR username,
1471 DWORD level,
1472 LPBYTE buf,
1473 LPDWORD parm_err)
1474 {
1475 FIXME("(%s %s %lu %p %p)\n",
1476 debugstr_w(servername), debugstr_w(username), level, buf, parm_err);
1477 return ERROR_ACCESS_DENIED;
1478 }
1479
1480 /* EOF */