[NETAPI32]
[reactos.git] / reactos / dll / win32 / netapi32 / local_group.c
1 /*
2 * Copyright 2006 Robert Reif
3 *
4 * netapi32 local group 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 #include "netapi32.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
24
25 typedef enum _ENUM_PHASE
26 {
27 BuiltinPhase,
28 AccountPhase,
29 DonePhase
30 } ENUM_PHASE;
31
32 typedef struct _ENUM_CONTEXT
33 {
34 SAM_HANDLE ServerHandle;
35 SAM_HANDLE DomainHandle;
36 SAM_HANDLE BuiltinDomainHandle;
37 SAM_HANDLE AccountDomainHandle;
38
39 SAM_ENUMERATE_HANDLE EnumerationContext;
40 PSAM_RID_ENUMERATION Buffer;
41 ULONG Returned;
42 ULONG Index;
43 ENUM_PHASE Phase;
44
45 } ENUM_CONTEXT, *PENUM_CONTEXT;
46
47 typedef struct _MEMBER_ENUM_CONTEXT
48 {
49 SAM_HANDLE ServerHandle;
50 SAM_HANDLE DomainHandle;
51 SAM_HANDLE AliasHandle;
52 LSA_HANDLE LsaHandle;
53
54 PSID *Sids;
55 ULONG Count;
56 PLSA_REFERENCED_DOMAIN_LIST Domains;
57 PLSA_TRANSLATED_NAME Names;
58
59 } MEMBER_ENUM_CONTEXT, *PMEMBER_ENUM_CONTEXT;
60
61
62 static
63 NET_API_STATUS
64 BuildAliasInfoBuffer(PALIAS_GENERAL_INFORMATION AliasInfo,
65 DWORD level,
66 LPVOID *Buffer)
67 {
68 LPVOID LocalBuffer = NULL;
69 PLOCALGROUP_INFO_0 LocalInfo0;
70 PLOCALGROUP_INFO_1 LocalInfo1;
71 LPWSTR Ptr;
72 ULONG Size = 0;
73 NET_API_STATUS ApiStatus = NERR_Success;
74
75 *Buffer = NULL;
76
77 switch (level)
78 {
79 case 0:
80 Size = sizeof(LOCALGROUP_INFO_0) +
81 AliasInfo->Name.Length + sizeof(WCHAR);
82 break;
83
84 case 1:
85 Size = sizeof(LOCALGROUP_INFO_1) +
86 AliasInfo->Name.Length + sizeof(WCHAR) +
87 AliasInfo->AdminComment.Length + sizeof(WCHAR);
88 break;
89
90 default:
91 ApiStatus = ERROR_INVALID_LEVEL;
92 goto done;
93 }
94
95 ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer);
96 if (ApiStatus != NERR_Success)
97 goto done;
98
99 ZeroMemory(LocalBuffer, Size);
100
101 switch (level)
102 {
103 case 0:
104 LocalInfo0 = (PLOCALGROUP_INFO_0)LocalBuffer;
105
106 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo0 + sizeof(LOCALGROUP_INFO_0));
107 LocalInfo0->lgrpi0_name = Ptr;
108
109 memcpy(LocalInfo0->lgrpi0_name,
110 AliasInfo->Name.Buffer,
111 AliasInfo->Name.Length);
112 LocalInfo0->lgrpi0_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
113 break;
114
115 case 1:
116 LocalInfo1 = (PLOCALGROUP_INFO_1)LocalBuffer;
117
118 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo1 + sizeof(LOCALGROUP_INFO_1));
119 LocalInfo1->lgrpi1_name = Ptr;
120
121 memcpy(LocalInfo1->lgrpi1_name,
122 AliasInfo->Name.Buffer,
123 AliasInfo->Name.Length);
124 LocalInfo1->lgrpi1_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
125
126 Ptr = (LPWSTR)((ULONG_PTR)Ptr + AliasInfo->Name.Length + sizeof(WCHAR));
127 LocalInfo1->lgrpi1_comment = Ptr;
128
129 memcpy(LocalInfo1->lgrpi1_comment,
130 AliasInfo->AdminComment.Buffer,
131 AliasInfo->AdminComment.Length);
132 LocalInfo1->lgrpi1_comment[AliasInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
133 break;
134 }
135
136 done:
137 if (ApiStatus == NERR_Success)
138 {
139 *Buffer = LocalBuffer;
140 }
141 else
142 {
143 if (LocalBuffer != NULL)
144 NetApiBufferFree(LocalBuffer);
145 }
146
147 return ApiStatus;
148 }
149
150
151 static
152 VOID
153 FreeAliasInfo(PALIAS_GENERAL_INFORMATION AliasInfo)
154 {
155 if (AliasInfo->Name.Buffer != NULL)
156 SamFreeMemory(AliasInfo->Name.Buffer);
157
158 if (AliasInfo->AdminComment.Buffer != NULL)
159 SamFreeMemory(AliasInfo->AdminComment.Buffer);
160
161 SamFreeMemory(AliasInfo);
162 }
163
164
165 static
166 NET_API_STATUS
167 OpenAliasByName(SAM_HANDLE DomainHandle,
168 PUNICODE_STRING AliasName,
169 ULONG DesiredAccess,
170 PSAM_HANDLE AliasHandle)
171 {
172 PULONG RelativeIds = NULL;
173 PSID_NAME_USE Use = NULL;
174 NET_API_STATUS ApiStatus = NERR_Success;
175 NTSTATUS Status = STATUS_SUCCESS;
176
177 /* Get the RID for the given user name */
178 Status = SamLookupNamesInDomain(DomainHandle,
179 1,
180 AliasName,
181 &RelativeIds,
182 &Use);
183 if (!NT_SUCCESS(Status))
184 {
185 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
186 return NetpNtStatusToApiStatus(Status);
187 }
188
189 /* Fail, if it is not an alias account */
190 if (Use[0] != SidTypeAlias)
191 {
192 ERR("Object is not an Alias!\n");
193 ApiStatus = NERR_GroupNotFound;
194 goto done;
195 }
196
197 /* Open the alias account */
198 Status = SamOpenAlias(DomainHandle,
199 DesiredAccess,
200 RelativeIds[0],
201 AliasHandle);
202 if (!NT_SUCCESS(Status))
203 {
204 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
205 ApiStatus = NetpNtStatusToApiStatus(Status);
206 goto done;
207 }
208
209 done:
210 if (RelativeIds != NULL)
211 SamFreeMemory(RelativeIds);
212
213 if (Use != NULL)
214 SamFreeMemory(Use);
215
216 return ApiStatus;
217 }
218
219
220 static
221 NET_API_STATUS
222 BuildSidListFromDomainAndName(IN PUNICODE_STRING ServerName,
223 IN PLOCALGROUP_MEMBERS_INFO_3 buf,
224 IN ULONG EntryCount,
225 OUT PLOCALGROUP_MEMBERS_INFO_0 *MemberList)
226 {
227 OBJECT_ATTRIBUTES ObjectAttributes;
228 LSA_HANDLE LsaHandle = NULL;
229 PUNICODE_STRING NamesArray = NULL;
230 ULONG i;
231 PLSA_REFERENCED_DOMAIN_LIST Domains = NULL;
232 PLSA_TRANSLATED_SID Sids = NULL;
233 PLOCALGROUP_MEMBERS_INFO_0 MemberBuffer = NULL;
234 NET_API_STATUS ApiStatus = NERR_Success;
235 NTSTATUS Status = STATUS_SUCCESS;
236
237 ApiStatus = NetApiBufferAllocate(sizeof(UNICODE_STRING) * EntryCount,
238 (LPVOID*)&NamesArray);
239 if (ApiStatus != NERR_Success)
240 {
241 goto done;
242 }
243
244 for (i = 0; i < EntryCount; i++)
245 {
246 RtlInitUnicodeString(&NamesArray[i],
247 buf[i].lgrmi3_domainandname);
248 }
249
250 InitializeObjectAttributes(&ObjectAttributes,
251 NULL,
252 0,
253 0,
254 NULL);
255
256 Status = LsaOpenPolicy(ServerName,
257 (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes,
258 POLICY_EXECUTE,
259 &LsaHandle);
260 if (!NT_SUCCESS(Status))
261 {
262 ApiStatus = NetpNtStatusToApiStatus(Status);
263 goto done;
264 }
265
266 Status = LsaLookupNames(LsaHandle,
267 EntryCount,
268 NamesArray,
269 &Domains,
270 &Sids);
271 if (!NT_SUCCESS(Status))
272 {
273 ApiStatus = NetpNtStatusToApiStatus(Status);
274 goto done;
275 }
276
277 ApiStatus = NetApiBufferAllocate(sizeof(LOCALGROUP_MEMBERS_INFO_0) * EntryCount,
278 (LPVOID*)&MemberBuffer);
279 if (ApiStatus != NERR_Success)
280 {
281 goto done;
282 }
283
284 for (i = 0; i < EntryCount; i++)
285 {
286 ApiStatus = BuildSidFromSidAndRid(Domains->Domains[Sids[i].DomainIndex].Sid,
287 Sids[i].RelativeId,
288 &MemberBuffer[i].lgrmi0_sid);
289 if (ApiStatus != NERR_Success)
290 {
291 goto done;
292 }
293 }
294
295 done:
296 if (ApiStatus != NERR_Success)
297 {
298 if (MemberBuffer != NULL)
299 {
300 for (i = 0; i < EntryCount; i++)
301 {
302 if (MemberBuffer[i].lgrmi0_sid != NULL)
303 NetApiBufferFree(MemberBuffer[i].lgrmi0_sid);
304 }
305
306 NetApiBufferFree(MemberBuffer);
307 MemberBuffer = NULL;
308 }
309 }
310
311 if (Sids != NULL)
312 LsaFreeMemory(Sids);
313
314 if (Domains != NULL)
315 LsaFreeMemory(Domains);
316
317 if (LsaHandle != NULL)
318 LsaClose(LsaHandle);
319
320 if (NamesArray != NULL)
321 NetApiBufferFree(NamesArray);
322
323 *MemberList = MemberBuffer;
324
325 return ApiStatus;
326 }
327
328
329 /************************************************************
330 * NetLocalGroupAdd (NETAPI32.@)
331 */
332 NET_API_STATUS
333 WINAPI
334 NetLocalGroupAdd(
335 LPCWSTR servername,
336 DWORD level,
337 LPBYTE buf,
338 LPDWORD parm_err)
339 {
340 ALIAS_ADM_COMMENT_INFORMATION AdminComment;
341 UNICODE_STRING ServerName;
342 UNICODE_STRING AliasName;
343 SAM_HANDLE ServerHandle = NULL;
344 SAM_HANDLE DomainHandle = NULL;
345 SAM_HANDLE AliasHandle = NULL;
346 LPWSTR aliasname = NULL;
347 LPWSTR aliascomment = NULL;
348 ULONG RelativeId;
349 NET_API_STATUS ApiStatus = NERR_Success;
350 NTSTATUS Status = STATUS_SUCCESS;
351
352 TRACE("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf,
353 parm_err);
354
355 /* Initialize the Server name*/
356 if (servername != NULL)
357 RtlInitUnicodeString(&ServerName, servername);
358
359 /* Initialize the Alias name*/
360 switch (level)
361 {
362 case 0:
363 aliasname = ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name;
364 aliascomment = NULL;
365 break;
366
367 case 1:
368 aliasname = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_name;
369 aliascomment = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment;
370 break;
371
372 default:
373 return ERROR_INVALID_LEVEL;
374 }
375
376 RtlInitUnicodeString(&AliasName, aliasname);
377
378 /* Connect to the SAM Server */
379 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
380 &ServerHandle,
381 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
382 NULL);
383 if (!NT_SUCCESS(Status))
384 {
385 ERR("SamConnect failed (Status %08lx)\n", Status);
386 ApiStatus = NetpNtStatusToApiStatus(Status);
387 goto done;
388 }
389
390 /* Open the Builtin Domain */
391 Status = OpenBuiltinDomain(ServerHandle,
392 DOMAIN_LOOKUP,
393 &DomainHandle);
394 if (!NT_SUCCESS(Status))
395 {
396 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
397 ApiStatus = NetpNtStatusToApiStatus(Status);
398 goto done;
399 }
400
401 /* Try to open the Alias Account in the Builtin Domain */
402 ApiStatus = OpenAliasByName(DomainHandle,
403 &AliasName,
404 ALIAS_READ_INFORMATION,
405 &AliasHandle);
406 if (ApiStatus == NERR_Success)
407 {
408 ERR("OpenAliasByName: alias %wZ already exists!\n", &AliasName);
409
410 SamCloseHandle(AliasHandle);
411 ApiStatus = ERROR_ALIAS_EXISTS;
412 goto done;
413 }
414
415 ApiStatus = NERR_Success;
416
417 /* Close the Builtin Domain */
418 SamCloseHandle(DomainHandle);
419 DomainHandle = NULL;
420
421 /* Open the account domain */
422 Status = OpenAccountDomain(ServerHandle,
423 (servername != NULL) ? &ServerName : NULL,
424 DOMAIN_CREATE_ALIAS | DOMAIN_LOOKUP,
425 &DomainHandle);
426 if (!NT_SUCCESS(Status))
427 {
428 ERR("SamOpenDomain failed (Status %08lx)\n", Status);
429 ApiStatus = NetpNtStatusToApiStatus(Status);
430 goto done;
431 }
432
433 /* Create the alias */
434 Status = SamCreateAliasInDomain(DomainHandle,
435 &AliasName,
436 DELETE | ALIAS_WRITE_ACCOUNT,
437 &AliasHandle,
438 &RelativeId);
439 if (!NT_SUCCESS(Status))
440 {
441 ERR("SamCreateAliasInDomain failed (Status %08lx)\n", Status);
442 ApiStatus = NetpNtStatusToApiStatus(Status);
443 goto done;
444 }
445
446 TRACE("Created alias \"%wZ\" (RID: %lu)\n", &AliasName, RelativeId);
447
448 /* Set the admin comment */
449 if (level == 1)
450 {
451 RtlInitUnicodeString(&AdminComment.AdminComment, aliascomment);
452
453 Status = SamSetInformationAlias(AliasHandle,
454 AliasAdminCommentInformation,
455 &AdminComment);
456 if (!NT_SUCCESS(Status))
457 {
458 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status);
459 ApiStatus = NetpNtStatusToApiStatus(Status);
460
461 /* Delete the Alias if the Comment could not be set */
462 SamDeleteAlias(AliasHandle);
463
464 goto done;
465 }
466 }
467
468 done:
469 if (AliasHandle != NULL)
470 {
471 if (ApiStatus != NERR_Success)
472 SamDeleteAlias(AliasHandle);
473 else
474 SamCloseHandle(AliasHandle);
475 }
476
477 if (DomainHandle != NULL)
478 SamCloseHandle(DomainHandle);
479
480 if (ServerHandle != NULL)
481 SamCloseHandle(ServerHandle);
482
483 return ApiStatus;
484 }
485
486
487 /************************************************************
488 * NetLocalGroupAddMember (NETAPI32.@)
489 */
490 NET_API_STATUS
491 WINAPI
492 NetLocalGroupAddMember(
493 LPCWSTR servername,
494 LPCWSTR groupname,
495 PSID membersid)
496 {
497 LOCALGROUP_MEMBERS_INFO_0 Member;
498
499 TRACE("(%s %s %p)\n", debugstr_w(servername),
500 debugstr_w(groupname), membersid);
501
502 Member.lgrmi0_sid = membersid;
503
504 return NetLocalGroupAddMembers(servername,
505 groupname,
506 0,
507 (LPBYTE)&Member,
508 1);
509 }
510
511
512 /************************************************************
513 * NetLocalGroupAddMembers (NETAPI32.@)
514 */
515 NET_API_STATUS
516 WINAPI
517 NetLocalGroupAddMembers(
518 LPCWSTR servername,
519 LPCWSTR groupname,
520 DWORD level,
521 LPBYTE buf,
522 DWORD totalentries)
523 {
524 UNICODE_STRING ServerName;
525 UNICODE_STRING AliasName;
526 SAM_HANDLE ServerHandle = NULL;
527 SAM_HANDLE DomainHandle = NULL;
528 SAM_HANDLE AliasHandle = NULL;
529 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL;
530 ULONG i;
531 NET_API_STATUS ApiStatus = NERR_Success;
532 NTSTATUS Status = STATUS_SUCCESS;
533
534 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername),
535 debugstr_w(groupname), level, buf, totalentries);
536
537 if (servername != NULL)
538 RtlInitUnicodeString(&ServerName, servername);
539
540 RtlInitUnicodeString(&AliasName, groupname);
541
542 switch (level)
543 {
544 case 0:
545 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf;
546 break;
547
548 case 3:
549 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL,
550 (PLOCALGROUP_MEMBERS_INFO_3)buf,
551 totalentries,
552 &MemberList);
553 if (!NT_SUCCESS(Status))
554 {
555 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status);
556 ApiStatus = NetpNtStatusToApiStatus(Status);
557 goto done;
558 }
559 break;
560
561 default:
562 ApiStatus = ERROR_INVALID_LEVEL;
563 goto done;
564 }
565
566 /* Connect to the SAM Server */
567 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
568 &ServerHandle,
569 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
570 NULL);
571 if (!NT_SUCCESS(Status))
572 {
573 ERR("SamConnect failed (Status %08lx)\n", Status);
574 ApiStatus = NetpNtStatusToApiStatus(Status);
575 goto done;
576 }
577
578 /* Open the Builtin Domain */
579 Status = OpenBuiltinDomain(ServerHandle,
580 DOMAIN_LOOKUP,
581 &DomainHandle);
582 if (!NT_SUCCESS(Status))
583 {
584 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
585 ApiStatus = NetpNtStatusToApiStatus(Status);
586 goto done;
587 }
588
589 /* Open the alias account in the builtin domain */
590 ApiStatus = OpenAliasByName(DomainHandle,
591 &AliasName,
592 ALIAS_ADD_MEMBER,
593 &AliasHandle);
594 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
595 {
596 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
597 goto done;
598 }
599
600 if (AliasHandle == NULL)
601 {
602 if (DomainHandle != NULL)
603 SamCloseHandle(DomainHandle);
604
605 /* Open the Acount Domain */
606 Status = OpenAccountDomain(ServerHandle,
607 (servername != NULL) ? &ServerName : NULL,
608 DOMAIN_LOOKUP,
609 &DomainHandle);
610 if (!NT_SUCCESS(Status))
611 {
612 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
613 ApiStatus = NetpNtStatusToApiStatus(Status);
614 goto done;
615 }
616
617 /* Open the alias account in the account domain */
618 ApiStatus = OpenAliasByName(DomainHandle,
619 &AliasName,
620 ALIAS_ADD_MEMBER,
621 &AliasHandle);
622 if (ApiStatus != NERR_Success)
623 {
624 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
625 if (ApiStatus == ERROR_NONE_MAPPED)
626 ApiStatus = NERR_GroupNotFound;
627 goto done;
628 }
629 }
630
631 /* Add new members to the alias */
632 for (i = 0; i < totalentries; i++)
633 {
634 Status = SamAddMemberToAlias(AliasHandle,
635 MemberList[i].lgrmi0_sid);
636 if (!NT_SUCCESS(Status))
637 {
638 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status);
639 ApiStatus = NetpNtStatusToApiStatus(Status);
640 goto done;
641 }
642 }
643
644 done:
645 if (level == 3 && MemberList != NULL)
646 {
647 for (i = 0; i < totalentries; i++)
648 {
649 if (MemberList[i].lgrmi0_sid != NULL)
650 NetApiBufferFree(MemberList[i].lgrmi0_sid);
651 }
652
653 NetApiBufferFree(MemberList);
654 }
655
656 if (AliasHandle != NULL)
657 SamCloseHandle(AliasHandle);
658
659 if (DomainHandle != NULL)
660 SamCloseHandle(DomainHandle);
661
662 if (ServerHandle != NULL)
663 SamCloseHandle(ServerHandle);
664
665 return ApiStatus;
666 }
667
668
669 /************************************************************
670 * NetLocalGroupDel (NETAPI32.@)
671 */
672 NET_API_STATUS
673 WINAPI
674 NetLocalGroupDel(
675 LPCWSTR servername,
676 LPCWSTR groupname)
677 {
678 UNICODE_STRING ServerName;
679 UNICODE_STRING GroupName;
680 SAM_HANDLE ServerHandle = NULL;
681 SAM_HANDLE DomainHandle = NULL;
682 SAM_HANDLE AliasHandle = NULL;
683 NET_API_STATUS ApiStatus = NERR_Success;
684 NTSTATUS Status = STATUS_SUCCESS;
685
686 TRACE("(%s %s)\n", debugstr_w(servername), debugstr_w(groupname));
687
688 if (servername != NULL)
689 RtlInitUnicodeString(&ServerName, servername);
690
691 RtlInitUnicodeString(&GroupName, groupname);
692
693 /* Connect to the SAM Server */
694 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
695 &ServerHandle,
696 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
697 NULL);
698 if (!NT_SUCCESS(Status))
699 {
700 ERR("SamConnect failed (Status %08lx)\n", Status);
701 ApiStatus = NetpNtStatusToApiStatus(Status);
702 goto done;
703 }
704
705 /* Open the Builtin Domain */
706 Status = OpenBuiltinDomain(ServerHandle,
707 DOMAIN_LOOKUP,
708 &DomainHandle);
709 if (!NT_SUCCESS(Status))
710 {
711 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
712 ApiStatus = NetpNtStatusToApiStatus(Status);
713 goto done;
714 }
715
716 /* Open the alias account in the builtin domain */
717 ApiStatus = OpenAliasByName(DomainHandle,
718 &GroupName,
719 DELETE,
720 &AliasHandle);
721 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
722 {
723 TRACE("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
724 goto done;
725 }
726
727 if (AliasHandle == NULL)
728 {
729 if (DomainHandle != NULL)
730 {
731 SamCloseHandle(DomainHandle);
732 DomainHandle = NULL;
733 }
734
735 /* Open the Acount Domain */
736 Status = OpenAccountDomain(ServerHandle,
737 (servername != NULL) ? &ServerName : NULL,
738 DOMAIN_LOOKUP,
739 &DomainHandle);
740 if (!NT_SUCCESS(Status))
741 {
742 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
743 ApiStatus = NetpNtStatusToApiStatus(Status);
744 goto done;
745 }
746
747 /* Open the alias account in the account domain */
748 ApiStatus = OpenAliasByName(DomainHandle,
749 &GroupName,
750 DELETE,
751 &AliasHandle);
752 if (ApiStatus != NERR_Success)
753 {
754 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
755 if (ApiStatus == ERROR_NONE_MAPPED)
756 ApiStatus = NERR_GroupNotFound;
757 goto done;
758 }
759 }
760
761 /* Delete the alias */
762 Status = SamDeleteAlias(AliasHandle);
763 if (!NT_SUCCESS(Status))
764 {
765 ERR("SamDeleteAlias failed (Status %08lx)\n", Status);
766 ApiStatus = NetpNtStatusToApiStatus(Status);
767 goto done;
768 }
769
770 done:
771 if (AliasHandle != NULL)
772 SamCloseHandle(AliasHandle);
773
774 if (DomainHandle != NULL)
775 SamCloseHandle(DomainHandle);
776
777 if (ServerHandle != NULL)
778 SamCloseHandle(ServerHandle);
779
780 return ApiStatus;
781 }
782
783
784 /************************************************************
785 * NetLocalGroupDelMember (NETAPI32.@)
786 */
787 NET_API_STATUS
788 WINAPI
789 NetLocalGroupDelMember(
790 LPCWSTR servername,
791 LPCWSTR groupname,
792 PSID membersid)
793 {
794 LOCALGROUP_MEMBERS_INFO_0 Member;
795
796 TRACE("(%s %s %p)\n", debugstr_w(servername),
797 debugstr_w(groupname), membersid);
798
799 Member.lgrmi0_sid = membersid;
800
801 return NetLocalGroupDelMembers(servername,
802 groupname,
803 0,
804 (LPBYTE)&Member,
805 1);
806 }
807
808
809 /************************************************************
810 * NetLocalGroupDelMembers (NETAPI32.@)
811 */
812 NET_API_STATUS
813 WINAPI
814 NetLocalGroupDelMembers(
815 LPCWSTR servername,
816 LPCWSTR groupname,
817 DWORD level,
818 LPBYTE buf,
819 DWORD totalentries)
820 {
821 UNICODE_STRING ServerName;
822 UNICODE_STRING AliasName;
823 SAM_HANDLE ServerHandle = NULL;
824 SAM_HANDLE DomainHandle = NULL;
825 SAM_HANDLE AliasHandle = NULL;
826 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL;
827 ULONG i;
828 NET_API_STATUS ApiStatus = NERR_Success;
829 NTSTATUS Status = STATUS_SUCCESS;
830
831 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername),
832 debugstr_w(groupname), level, buf, totalentries);
833
834 if (servername != NULL)
835 RtlInitUnicodeString(&ServerName, servername);
836
837 RtlInitUnicodeString(&AliasName, groupname);
838
839 switch (level)
840 {
841 case 0:
842 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf;
843 break;
844
845 case 3:
846 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL,
847 (PLOCALGROUP_MEMBERS_INFO_3)buf,
848 totalentries,
849 &MemberList);
850 if (!NT_SUCCESS(Status))
851 {
852 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status);
853 ApiStatus = NetpNtStatusToApiStatus(Status);
854 goto done;
855 }
856 break;
857
858 default:
859 ApiStatus = ERROR_INVALID_LEVEL;
860 goto done;
861 }
862
863 /* Connect to the SAM Server */
864 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
865 &ServerHandle,
866 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
867 NULL);
868 if (!NT_SUCCESS(Status))
869 {
870 ERR("SamConnect failed (Status %08lx)\n", Status);
871 ApiStatus = NetpNtStatusToApiStatus(Status);
872 goto done;
873 }
874
875 /* Open the Builtin Domain */
876 Status = OpenBuiltinDomain(ServerHandle,
877 DOMAIN_LOOKUP,
878 &DomainHandle);
879 if (!NT_SUCCESS(Status))
880 {
881 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
882 ApiStatus = NetpNtStatusToApiStatus(Status);
883 goto done;
884 }
885
886 /* Open the alias account in the builtin domain */
887 ApiStatus = OpenAliasByName(DomainHandle,
888 &AliasName,
889 ALIAS_REMOVE_MEMBER,
890 &AliasHandle);
891 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
892 {
893 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
894 goto done;
895 }
896
897 if (AliasHandle == NULL)
898 {
899 if (DomainHandle != NULL)
900 SamCloseHandle(DomainHandle);
901
902 /* Open the Acount Domain */
903 Status = OpenAccountDomain(ServerHandle,
904 (servername != NULL) ? &ServerName : NULL,
905 DOMAIN_LOOKUP,
906 &DomainHandle);
907 if (!NT_SUCCESS(Status))
908 {
909 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
910 ApiStatus = NetpNtStatusToApiStatus(Status);
911 goto done;
912 }
913
914 /* Open the alias account in the account domain */
915 ApiStatus = OpenAliasByName(DomainHandle,
916 &AliasName,
917 ALIAS_REMOVE_MEMBER,
918 &AliasHandle);
919 if (ApiStatus != NERR_Success)
920 {
921 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
922 if (ApiStatus == ERROR_NONE_MAPPED)
923 ApiStatus = NERR_GroupNotFound;
924 goto done;
925 }
926 }
927
928 /* Remove members from the alias */
929 for (i = 0; i < totalentries; i++)
930 {
931 Status = SamRemoveMemberFromAlias(AliasHandle,
932 MemberList[i].lgrmi0_sid);
933 if (!NT_SUCCESS(Status))
934 {
935 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status);
936 ApiStatus = NetpNtStatusToApiStatus(Status);
937 goto done;
938 }
939 }
940
941 done:
942 if (level == 3 && MemberList != NULL)
943 {
944 for (i = 0; i < totalentries; i++)
945 {
946 if (MemberList[i].lgrmi0_sid != NULL)
947 NetApiBufferFree(MemberList[i].lgrmi0_sid);
948 }
949
950 NetApiBufferFree(MemberList);
951 }
952
953 if (AliasHandle != NULL)
954 SamCloseHandle(AliasHandle);
955
956 if (DomainHandle != NULL)
957 SamCloseHandle(DomainHandle);
958
959 if (ServerHandle != NULL)
960 SamCloseHandle(ServerHandle);
961
962 return ApiStatus;
963 }
964
965
966 /************************************************************
967 * NetLocalGroupEnum (NETAPI32.@)
968 */
969 NET_API_STATUS
970 WINAPI
971 NetLocalGroupEnum(
972 LPCWSTR servername,
973 DWORD level,
974 LPBYTE* bufptr,
975 DWORD prefmaxlen,
976 LPDWORD entriesread,
977 LPDWORD totalentries,
978 PDWORD_PTR resumehandle)
979 {
980 UNICODE_STRING ServerName;
981 PSAM_RID_ENUMERATION CurrentAlias;
982 PENUM_CONTEXT EnumContext = NULL;
983 ULONG i;
984 SAM_HANDLE AliasHandle = NULL;
985 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
986 LPVOID Buffer = NULL;
987 NET_API_STATUS ApiStatus = NERR_Success;
988 NTSTATUS Status = STATUS_SUCCESS;
989
990 TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
991 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
992
993 *entriesread = 0;
994 *totalentries = 0;
995 *bufptr = NULL;
996
997 if (servername != NULL)
998 RtlInitUnicodeString(&ServerName, servername);
999
1000 if (resumehandle != NULL && *resumehandle != 0)
1001 {
1002 EnumContext = (PENUM_CONTEXT)*resumehandle;
1003 }
1004 else
1005 {
1006 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
1007 if (ApiStatus != NERR_Success)
1008 goto done;
1009
1010 EnumContext->EnumerationContext = 0;
1011 EnumContext->Buffer = NULL;
1012 EnumContext->Returned = 0;
1013 EnumContext->Index = 0;
1014
1015 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1016 &EnumContext->ServerHandle,
1017 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1018 NULL);
1019 if (!NT_SUCCESS(Status))
1020 {
1021 ERR("SamConnect failed (Status %08lx)\n", Status);
1022 ApiStatus = NetpNtStatusToApiStatus(Status);
1023 goto done;
1024 }
1025
1026 Status = OpenAccountDomain(EnumContext->ServerHandle,
1027 (servername != NULL) ? &ServerName : NULL,
1028 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
1029 &EnumContext->AccountDomainHandle);
1030 if (!NT_SUCCESS(Status))
1031 {
1032 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1033 ApiStatus = NetpNtStatusToApiStatus(Status);
1034 goto done;
1035 }
1036
1037 Status = OpenBuiltinDomain(EnumContext->ServerHandle,
1038 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
1039 &EnumContext->BuiltinDomainHandle);
1040 if (!NT_SUCCESS(Status))
1041 {
1042 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
1043 ApiStatus = NetpNtStatusToApiStatus(Status);
1044 goto done;
1045 }
1046
1047 EnumContext->Phase = BuiltinPhase;
1048 EnumContext->DomainHandle = EnumContext->BuiltinDomainHandle;
1049 }
1050
1051
1052 // while (TRUE)
1053 // {
1054 TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
1055 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
1056
1057 if (EnumContext->Index >= EnumContext->Returned)
1058 {
1059 TRACE("Calling SamEnumerateAliasesInDomain\n");
1060
1061 Status = SamEnumerateAliasesInDomain(EnumContext->DomainHandle,
1062 &EnumContext->EnumerationContext,
1063 (PVOID *)&EnumContext->Buffer,
1064 prefmaxlen,
1065 &EnumContext->Returned);
1066
1067 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
1068 if (!NT_SUCCESS(Status))
1069 {
1070 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
1071 ApiStatus = NetpNtStatusToApiStatus(Status);
1072 goto done;
1073 }
1074
1075 if (Status == STATUS_MORE_ENTRIES)
1076 {
1077 ApiStatus = NERR_BufTooSmall;
1078 goto done;
1079 }
1080 }
1081
1082 TRACE("EnumContext: %lu\n", EnumContext);
1083 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
1084 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
1085
1086 /* Get a pointer to the current alias */
1087 CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
1088
1089 TRACE("RID: %lu\n", CurrentAlias->RelativeId);
1090
1091 Status = SamOpenAlias(EnumContext->DomainHandle,
1092 ALIAS_READ_INFORMATION,
1093 CurrentAlias->RelativeId,
1094 &AliasHandle);
1095 if (!NT_SUCCESS(Status))
1096 {
1097 ERR("SamOpenAlias failed (Status %08lx)\n", Status);
1098 ApiStatus = NetpNtStatusToApiStatus(Status);
1099 goto done;
1100 }
1101
1102 Status = SamQueryInformationAlias(AliasHandle,
1103 AliasGeneralInformation,
1104 (PVOID *)&AliasInfo);
1105 if (!NT_SUCCESS(Status))
1106 {
1107 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
1108 ApiStatus = NetpNtStatusToApiStatus(Status);
1109 goto done;
1110 }
1111
1112 SamCloseHandle(AliasHandle);
1113 AliasHandle = NULL;
1114
1115 TRACE("Name: %S\n", AliasInfo->Name.Buffer);
1116 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
1117
1118 ApiStatus = BuildAliasInfoBuffer(AliasInfo,
1119 level,
1120 &Buffer);
1121 if (ApiStatus != NERR_Success)
1122 goto done;
1123
1124 if (AliasInfo != NULL)
1125 {
1126 FreeAliasInfo(AliasInfo);
1127 AliasInfo = NULL;
1128 }
1129
1130 EnumContext->Index++;
1131
1132 (*entriesread)++;
1133
1134 if (EnumContext->Index == EnumContext->Returned)
1135 {
1136 switch (EnumContext->Phase)
1137 {
1138 case BuiltinPhase:
1139 EnumContext->Phase = AccountPhase;
1140 EnumContext->DomainHandle = EnumContext->AccountDomainHandle;
1141 EnumContext->EnumerationContext = 0;
1142 EnumContext->Index = 0;
1143 EnumContext->Returned = 0;
1144
1145 if (EnumContext->Buffer != NULL)
1146 {
1147 for (i = 0; i < EnumContext->Returned; i++)
1148 {
1149 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
1150 }
1151
1152 SamFreeMemory(EnumContext->Buffer);
1153 EnumContext->Buffer = NULL;
1154 }
1155 break;
1156
1157 case AccountPhase:
1158 case DonePhase:
1159 EnumContext->Phase = DonePhase;
1160 break;
1161 }
1162 }
1163 // }
1164
1165 done:
1166 if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Phase != DonePhase)
1167 ApiStatus = ERROR_MORE_DATA;
1168
1169 if (EnumContext != NULL)
1170 *totalentries = EnumContext->Returned;
1171
1172 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
1173 {
1174 if (EnumContext != NULL)
1175 {
1176 if (EnumContext->BuiltinDomainHandle != NULL)
1177 SamCloseHandle(EnumContext->BuiltinDomainHandle);
1178
1179 if (EnumContext->AccountDomainHandle != NULL)
1180 SamCloseHandle(EnumContext->AccountDomainHandle);
1181
1182 if (EnumContext->ServerHandle != NULL)
1183 SamCloseHandle(EnumContext->ServerHandle);
1184
1185 if (EnumContext->Buffer != NULL)
1186 {
1187 for (i = 0; i < EnumContext->Returned; i++)
1188 {
1189 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
1190 }
1191
1192 SamFreeMemory(EnumContext->Buffer);
1193 }
1194
1195 NetApiBufferFree(EnumContext);
1196 EnumContext = NULL;
1197 }
1198 }
1199
1200 if (AliasHandle != NULL)
1201 SamCloseHandle(AliasHandle);
1202
1203 if (AliasInfo != NULL)
1204 FreeAliasInfo(AliasInfo);
1205
1206 if (resumehandle != NULL)
1207 *resumehandle = (DWORD_PTR)EnumContext;
1208
1209 *bufptr = (LPBYTE)Buffer;
1210
1211 TRACE ("return %lu\n", ApiStatus);
1212
1213 return ApiStatus;
1214 }
1215
1216
1217 /************************************************************
1218 * NetLocalGroupGetInfo (NETAPI32.@)
1219 */
1220 NET_API_STATUS
1221 WINAPI
1222 NetLocalGroupGetInfo(
1223 LPCWSTR servername,
1224 LPCWSTR groupname,
1225 DWORD level,
1226 LPBYTE* bufptr)
1227 {
1228 UNICODE_STRING ServerName;
1229 UNICODE_STRING GroupName;
1230 SAM_HANDLE ServerHandle = NULL;
1231 SAM_HANDLE DomainHandle = NULL;
1232 SAM_HANDLE AliasHandle = NULL;
1233 PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
1234 LPVOID Buffer = NULL;
1235 NET_API_STATUS ApiStatus = NERR_Success;
1236 NTSTATUS Status = STATUS_SUCCESS;
1237
1238 TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername),
1239 debugstr_w(groupname), level, bufptr);
1240
1241 if (servername != NULL)
1242 RtlInitUnicodeString(&ServerName, servername);
1243
1244 RtlInitUnicodeString(&GroupName, groupname);
1245
1246 /* Connect to the SAM Server */
1247 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1248 &ServerHandle,
1249 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1250 NULL);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 ERR("SamConnect failed (Status %08lx)\n", Status);
1254 ApiStatus = NetpNtStatusToApiStatus(Status);
1255 goto done;
1256 }
1257
1258 /* Open the Builtin Domain */
1259 Status = OpenBuiltinDomain(ServerHandle,
1260 DOMAIN_LOOKUP,
1261 &DomainHandle);
1262 if (!NT_SUCCESS(Status))
1263 {
1264 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
1265 ApiStatus = NetpNtStatusToApiStatus(Status);
1266 goto done;
1267 }
1268
1269 /* Open the alias account in the builtin domain */
1270 ApiStatus = OpenAliasByName(DomainHandle,
1271 &GroupName,
1272 ALIAS_READ_INFORMATION,
1273 &AliasHandle);
1274 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
1275 {
1276 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1277 goto done;
1278 }
1279
1280 if (AliasHandle == NULL)
1281 {
1282 if (DomainHandle != NULL)
1283 SamCloseHandle(DomainHandle);
1284
1285 /* Open the Acount Domain */
1286 Status = OpenAccountDomain(ServerHandle,
1287 (servername != NULL) ? &ServerName : NULL,
1288 DOMAIN_LOOKUP,
1289 &DomainHandle);
1290 if (!NT_SUCCESS(Status))
1291 {
1292 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1293 ApiStatus = NetpNtStatusToApiStatus(Status);
1294 goto done;
1295 }
1296
1297 /* Open the alias account in the account domain */
1298 ApiStatus = OpenAliasByName(DomainHandle,
1299 &GroupName,
1300 ALIAS_READ_INFORMATION,
1301 &AliasHandle);
1302 if (ApiStatus != NERR_Success)
1303 {
1304 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1305 if (ApiStatus == ERROR_NONE_MAPPED)
1306 ApiStatus = NERR_GroupNotFound;
1307 goto done;
1308 }
1309 }
1310
1311 Status = SamQueryInformationAlias(AliasHandle,
1312 AliasGeneralInformation,
1313 (PVOID *)&AliasInfo);
1314 if (!NT_SUCCESS(Status))
1315 {
1316 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
1317 ApiStatus = NetpNtStatusToApiStatus(Status);
1318 goto done;
1319 }
1320
1321 ApiStatus = BuildAliasInfoBuffer(AliasInfo,
1322 level,
1323 &Buffer);
1324 if (ApiStatus != NERR_Success)
1325 goto done;
1326
1327 done:
1328 if (AliasInfo != NULL)
1329 FreeAliasInfo(AliasInfo);
1330
1331 if (AliasHandle != NULL)
1332 SamCloseHandle(AliasHandle);
1333
1334 if (DomainHandle != NULL)
1335 SamCloseHandle(DomainHandle);
1336
1337 if (ServerHandle != NULL)
1338 SamCloseHandle(ServerHandle);
1339
1340 *bufptr = (LPBYTE)Buffer;
1341
1342 return ApiStatus;
1343 }
1344
1345
1346 /************************************************************
1347 * NetLocalGroupGetMembers (NETAPI32.@)
1348 */
1349 NET_API_STATUS
1350 WINAPI
1351 NetLocalGroupGetMembers(
1352 LPCWSTR servername,
1353 LPCWSTR localgroupname,
1354 DWORD level,
1355 LPBYTE* bufptr,
1356 DWORD prefmaxlen,
1357 LPDWORD entriesread,
1358 LPDWORD totalentries,
1359 PDWORD_PTR resumehandle)
1360 {
1361 OBJECT_ATTRIBUTES ObjectAttributes;
1362 UNICODE_STRING ServerName;
1363 UNICODE_STRING AliasName;
1364 PMEMBER_ENUM_CONTEXT EnumContext = NULL;
1365 LPVOID Buffer = NULL;
1366 PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0;
1367 PLOCALGROUP_MEMBERS_INFO_1 MembersInfo1;
1368 PLOCALGROUP_MEMBERS_INFO_2 MembersInfo2;
1369 PLOCALGROUP_MEMBERS_INFO_3 MembersInfo3;
1370 LPWSTR Ptr;
1371 ULONG Size = 0;
1372 ULONG SidLength;
1373 ULONG i;
1374 NET_API_STATUS ApiStatus = NERR_Success;
1375 NTSTATUS Status = STATUS_SUCCESS;
1376
1377 TRACE("(%s %s %d %p %d %p %p %p)\n", debugstr_w(servername),
1378 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
1379 totalentries, resumehandle);
1380
1381 *entriesread = 0;
1382 *totalentries = 0;
1383 *bufptr = NULL;
1384
1385 if (servername != NULL)
1386 RtlInitUnicodeString(&ServerName, servername);
1387
1388 RtlInitUnicodeString(&AliasName, localgroupname);
1389
1390 if (resumehandle != NULL && *resumehandle != 0)
1391 {
1392 EnumContext = (PMEMBER_ENUM_CONTEXT)*resumehandle;
1393 }
1394 else
1395 {
1396 /* Allocate the enumeration context */
1397 ApiStatus = NetApiBufferAllocate(sizeof(MEMBER_ENUM_CONTEXT), (PVOID*)&EnumContext);
1398 if (ApiStatus != NERR_Success)
1399 goto done;
1400
1401 /* Connect to the SAM Server */
1402 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1403 &EnumContext->ServerHandle,
1404 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1405 NULL);
1406 if (!NT_SUCCESS(Status))
1407 {
1408 ERR("SamConnect failed (Status %08lx)\n", Status);
1409 ApiStatus = NetpNtStatusToApiStatus(Status);
1410 goto done;
1411 }
1412
1413 /* Open the Builtin Domain */
1414 Status = OpenBuiltinDomain(EnumContext->ServerHandle,
1415 DOMAIN_LOOKUP,
1416 &EnumContext->DomainHandle);
1417 if (!NT_SUCCESS(Status))
1418 {
1419 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
1420 ApiStatus = NetpNtStatusToApiStatus(Status);
1421 goto done;
1422 }
1423
1424 /* Open the alias account in the builtin domain */
1425 ApiStatus = OpenAliasByName(EnumContext->DomainHandle,
1426 &AliasName,
1427 ALIAS_LIST_MEMBERS,
1428 &EnumContext->AliasHandle);
1429 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
1430 {
1431 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1432 goto done;
1433 }
1434
1435 if (EnumContext->AliasHandle == NULL)
1436 {
1437 if (EnumContext->DomainHandle != NULL)
1438 SamCloseHandle(EnumContext->DomainHandle);
1439
1440 /* Open the Acount Domain */
1441 Status = OpenAccountDomain(EnumContext->ServerHandle,
1442 (servername != NULL) ? &ServerName : NULL,
1443 DOMAIN_LOOKUP,
1444 &EnumContext->DomainHandle);
1445 if (!NT_SUCCESS(Status))
1446 {
1447 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1448 ApiStatus = NetpNtStatusToApiStatus(Status);
1449 goto done;
1450 }
1451
1452 /* Open the alias account in the account domain */
1453 ApiStatus = OpenAliasByName(EnumContext->DomainHandle,
1454 &AliasName,
1455 ALIAS_LIST_MEMBERS,
1456 &EnumContext->AliasHandle);
1457 if (ApiStatus != NERR_Success)
1458 {
1459 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1460 if (ApiStatus == ERROR_NONE_MAPPED)
1461 ApiStatus = NERR_GroupNotFound;
1462 goto done;
1463 }
1464 }
1465
1466 /* Get the member list */
1467 Status = SamGetMembersInAlias(EnumContext->AliasHandle,
1468 &EnumContext->Sids,
1469 &EnumContext->Count);
1470 if (!NT_SUCCESS(Status))
1471 {
1472 ERR("SamGetMemberInAlias failed (Status %08lx)\n", Status);
1473 ApiStatus = NetpNtStatusToApiStatus(Status);
1474 goto done;
1475 }
1476
1477 if (EnumContext->Count == 0)
1478 {
1479 TRACE("No member found. We're done.\n");
1480 ApiStatus = NERR_Success;
1481 goto done;
1482 }
1483
1484 /* Get name and domain information for all members */
1485 if (level != 0)
1486 {
1487 InitializeObjectAttributes(&ObjectAttributes,
1488 NULL,
1489 0,
1490 0,
1491 NULL);
1492
1493 Status = LsaOpenPolicy((servername != NULL) ? &ServerName : NULL,
1494 (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes,
1495 POLICY_EXECUTE,
1496 &EnumContext->LsaHandle);
1497 if (!NT_SUCCESS(Status))
1498 {
1499 ApiStatus = NetpNtStatusToApiStatus(Status);
1500 goto done;
1501 }
1502
1503 Status = LsaLookupSids(EnumContext->LsaHandle,
1504 EnumContext->Count,
1505 EnumContext->Sids,
1506 &EnumContext->Domains,
1507 &EnumContext->Names);
1508 if (!NT_SUCCESS(Status))
1509 {
1510 ApiStatus = NetpNtStatusToApiStatus(Status);
1511 goto done;
1512 }
1513 }
1514 }
1515
1516 /* Calculate the required buffer size */
1517 for (i = 0; i < EnumContext->Count; i++)
1518 {
1519 switch (level)
1520 {
1521 case 0:
1522 Size += sizeof(LOCALGROUP_MEMBERS_INFO_0) +
1523 RtlLengthSid(EnumContext->Sids[i]);
1524 break;
1525
1526 case 1:
1527 Size += sizeof(LOCALGROUP_MEMBERS_INFO_1) +
1528 RtlLengthSid(EnumContext->Sids[i]) +
1529 EnumContext->Names[i].Name.Length + sizeof(WCHAR);
1530 break;
1531
1532 case 2:
1533 Size += sizeof(LOCALGROUP_MEMBERS_INFO_2) +
1534 RtlLengthSid(EnumContext->Sids[i]) +
1535 EnumContext->Names[i].Name.Length + sizeof(WCHAR);
1536 if (EnumContext->Names[i].DomainIndex >= 0)
1537 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR);
1538 break;
1539
1540 case 3:
1541 Size += sizeof(LOCALGROUP_MEMBERS_INFO_3) +
1542 EnumContext->Names[i].Name.Length + sizeof(WCHAR);
1543 if (EnumContext->Names[i].DomainIndex >= 0)
1544 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR);
1545 break;
1546
1547 default:
1548 ApiStatus = ERROR_INVALID_LEVEL;
1549 goto done;
1550 }
1551 }
1552
1553 /* Allocate the member buffer */
1554 ApiStatus = NetApiBufferAllocate(Size, &Buffer);
1555 if (ApiStatus != NERR_Success)
1556 goto done;
1557
1558 ZeroMemory(Buffer, Size);
1559
1560 /* Fill the member buffer */
1561 switch (level)
1562 {
1563 case 0:
1564 MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)Buffer;
1565 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_0) * EnumContext->Count);
1566 break;
1567
1568 case 1:
1569 MembersInfo1 = (PLOCALGROUP_MEMBERS_INFO_1)Buffer;
1570 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_1) * EnumContext->Count);
1571 break;
1572
1573 case 2:
1574 MembersInfo2 = (PLOCALGROUP_MEMBERS_INFO_2)Buffer;
1575 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_2) * EnumContext->Count);
1576 break;
1577
1578 case 3:
1579 MembersInfo3 = (PLOCALGROUP_MEMBERS_INFO_3)Buffer;
1580 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_3) * EnumContext->Count);
1581 break;
1582 }
1583
1584 for (i = 0; i < EnumContext->Count; i++)
1585 {
1586 switch (level)
1587 {
1588 case 0:
1589 MembersInfo0->lgrmi0_sid = (PSID)Ptr;
1590
1591 SidLength = RtlLengthSid(EnumContext->Sids[i]);
1592 memcpy(MembersInfo0->lgrmi0_sid,
1593 EnumContext->Sids[i],
1594 SidLength);
1595 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
1596 MembersInfo0++;
1597 break;
1598
1599 case 1:
1600 MembersInfo1->lgrmi1_sid = (PSID)Ptr;
1601
1602 SidLength = RtlLengthSid(EnumContext->Sids[i]);
1603 memcpy(MembersInfo1->lgrmi1_sid,
1604 EnumContext->Sids[i],
1605 SidLength);
1606
1607 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
1608
1609 MembersInfo1->lgrmi1_sidusage = EnumContext->Names[i].Use;
1610
1611 TRACE("Name: %S\n", EnumContext->Names[i].Name.Buffer);
1612
1613 MembersInfo1->lgrmi1_name = Ptr;
1614
1615 memcpy(MembersInfo1->lgrmi1_name,
1616 EnumContext->Names[i].Name.Buffer,
1617 EnumContext->Names[i].Name.Length);
1618 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
1619 MembersInfo1++;
1620 break;
1621
1622 case 2:
1623 MembersInfo2->lgrmi2_sid = (PSID)Ptr;
1624
1625 SidLength = RtlLengthSid(EnumContext->Sids[i]);
1626 memcpy(MembersInfo2->lgrmi2_sid,
1627 EnumContext->Sids[i],
1628 SidLength);
1629
1630 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
1631
1632 MembersInfo2->lgrmi2_sidusage = EnumContext->Names[i].Use;
1633
1634 MembersInfo2->lgrmi2_domainandname = Ptr;
1635
1636 if (EnumContext->Names[i].DomainIndex >= 0)
1637 {
1638 memcpy(MembersInfo2->lgrmi2_domainandname,
1639 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer,
1640 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
1641
1642 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
1643
1644 *((LPWSTR)Ptr) = L'\\';
1645
1646 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR));
1647 }
1648
1649 memcpy(Ptr,
1650 EnumContext->Names[i].Name.Buffer,
1651 EnumContext->Names[i].Name.Length);
1652 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
1653 MembersInfo2++;
1654 break;
1655
1656 case 3:
1657 MembersInfo3->lgrmi3_domainandname = Ptr;
1658
1659 if (EnumContext->Names[i].DomainIndex >= 0)
1660 {
1661 memcpy(MembersInfo3->lgrmi3_domainandname,
1662 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer,
1663 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
1664
1665 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
1666
1667 *((LPWSTR)Ptr) = L'\\';
1668
1669 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR));
1670 }
1671
1672 memcpy(Ptr,
1673 EnumContext->Names[i].Name.Buffer,
1674 EnumContext->Names[i].Name.Length);
1675 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
1676 MembersInfo3++;
1677 break;
1678 }
1679 }
1680
1681 *entriesread = EnumContext->Count;
1682
1683 *bufptr = (LPBYTE)Buffer;
1684
1685 done:
1686 if (EnumContext != NULL)
1687 *totalentries = EnumContext->Count;
1688
1689 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
1690 {
1691 /* Release the enumeration context */
1692 if (EnumContext != NULL)
1693 {
1694 if (EnumContext->LsaHandle != NULL)
1695 LsaClose(EnumContext->LsaHandle);
1696
1697 if (EnumContext->AliasHandle != NULL)
1698 SamCloseHandle(EnumContext->AliasHandle);
1699
1700 if (EnumContext->DomainHandle != NULL)
1701 SamCloseHandle(EnumContext->DomainHandle);
1702
1703 if (EnumContext->ServerHandle != NULL)
1704 SamCloseHandle(EnumContext->ServerHandle);
1705
1706 if (EnumContext->Sids != NULL)
1707 SamFreeMemory(EnumContext->Sids);
1708
1709 if (EnumContext->Domains != NULL)
1710 LsaFreeMemory(EnumContext->Domains);
1711
1712 if (EnumContext->Names != NULL)
1713 LsaFreeMemory(EnumContext->Names);
1714
1715 NetApiBufferFree(EnumContext);
1716 EnumContext = NULL;
1717 }
1718 }
1719
1720 return ApiStatus;
1721 }
1722
1723
1724 /************************************************************
1725 * NetLocalGroupSetInfo (NETAPI32.@)
1726 */
1727 NET_API_STATUS
1728 WINAPI
1729 NetLocalGroupSetInfo(
1730 LPCWSTR servername,
1731 LPCWSTR groupname,
1732 DWORD level,
1733 LPBYTE buf,
1734 LPDWORD parm_err)
1735 {
1736 UNICODE_STRING ServerName;
1737 UNICODE_STRING AliasName;
1738 SAM_HANDLE ServerHandle = NULL;
1739 SAM_HANDLE DomainHandle = NULL;
1740 SAM_HANDLE AliasHandle = NULL;
1741 ALIAS_NAME_INFORMATION AliasNameInfo;
1742 ALIAS_ADM_COMMENT_INFORMATION AdminCommentInfo;
1743 NET_API_STATUS ApiStatus = NERR_Success;
1744 NTSTATUS Status = STATUS_SUCCESS;
1745
1746 TRACE("(%s %s %d %p %p)\n", debugstr_w(servername),
1747 debugstr_w(groupname), level, buf, parm_err);
1748
1749 if (parm_err != NULL)
1750 *parm_err = PARM_ERROR_NONE;
1751
1752 if (servername != NULL)
1753 RtlInitUnicodeString(&ServerName, servername);
1754
1755 RtlInitUnicodeString(&AliasName, groupname);
1756
1757 /* Connect to the SAM Server */
1758 Status = SamConnect((servername != NULL) ? &ServerName : NULL,
1759 &ServerHandle,
1760 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1761 NULL);
1762 if (!NT_SUCCESS(Status))
1763 {
1764 ERR("SamConnect failed (Status %08lx)\n", Status);
1765 ApiStatus = NetpNtStatusToApiStatus(Status);
1766 goto done;
1767 }
1768
1769 /* Open the Builtin Domain */
1770 Status = OpenBuiltinDomain(ServerHandle,
1771 DOMAIN_LOOKUP,
1772 &DomainHandle);
1773 if (!NT_SUCCESS(Status))
1774 {
1775 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
1776 ApiStatus = NetpNtStatusToApiStatus(Status);
1777 goto done;
1778 }
1779
1780 /* Open the alias account in the builtin domain */
1781 ApiStatus = OpenAliasByName(DomainHandle,
1782 &AliasName,
1783 ALIAS_WRITE_ACCOUNT,
1784 &AliasHandle);
1785 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
1786 {
1787 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1788 goto done;
1789 }
1790
1791 if (AliasHandle == NULL)
1792 {
1793 if (DomainHandle != NULL)
1794 SamCloseHandle(DomainHandle);
1795
1796 /* Open the Acount Domain */
1797 Status = OpenAccountDomain(ServerHandle,
1798 (servername != NULL) ? &ServerName : NULL,
1799 DOMAIN_LOOKUP,
1800 &DomainHandle);
1801 if (!NT_SUCCESS(Status))
1802 {
1803 ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
1804 ApiStatus = NetpNtStatusToApiStatus(Status);
1805 goto done;
1806 }
1807
1808 /* Open the alias account in the account domain */
1809 ApiStatus = OpenAliasByName(DomainHandle,
1810 &AliasName,
1811 ALIAS_WRITE_ACCOUNT,
1812 &AliasHandle);
1813 if (ApiStatus != NERR_Success)
1814 {
1815 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
1816 if (ApiStatus == ERROR_NONE_MAPPED)
1817 ApiStatus = NERR_GroupNotFound;
1818 goto done;
1819 }
1820 }
1821
1822 switch (level)
1823 {
1824 case 0:
1825 /* Set the alias name */
1826 RtlInitUnicodeString(&AliasNameInfo.Name,
1827 ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name);
1828
1829 Status = SamSetInformationAlias(AliasHandle,
1830 AliasNameInformation,
1831 &AliasNameInfo);
1832 if (!NT_SUCCESS(Status))
1833 {
1834 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus);
1835 ApiStatus = NetpNtStatusToApiStatus(Status);
1836 goto done;
1837 }
1838 break;
1839
1840 case 1:
1841 case 1002:
1842 /* Set the alias admin comment */
1843 if (level == 1)
1844 RtlInitUnicodeString(&AdminCommentInfo.AdminComment,
1845 ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment);
1846 else
1847 RtlInitUnicodeString(&AdminCommentInfo.AdminComment,
1848 ((PLOCALGROUP_INFO_1002)buf)->lgrpi1002_comment);
1849
1850 Status = SamSetInformationAlias(AliasHandle,
1851 AliasAdminCommentInformation,
1852 &AdminCommentInfo);
1853 if (!NT_SUCCESS(Status))
1854 {
1855 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus);
1856 ApiStatus = NetpNtStatusToApiStatus(Status);
1857 goto done;
1858 }
1859 break;
1860
1861 default:
1862 ApiStatus = ERROR_INVALID_LEVEL;
1863 goto done;
1864 }
1865
1866 done:
1867 if (AliasHandle != NULL)
1868 SamCloseHandle(AliasHandle);
1869
1870 if (DomainHandle != NULL)
1871 SamCloseHandle(DomainHandle);
1872
1873 if (ServerHandle != NULL)
1874 SamCloseHandle(ServerHandle);
1875
1876 return ApiStatus;
1877 }
1878
1879
1880 /************************************************************
1881 * NetLocalGroupSetMember (NETAPI32.@)
1882 */
1883 NET_API_STATUS
1884 WINAPI
1885 NetLocalGroupSetMembers(
1886 LPCWSTR servername,
1887 LPCWSTR groupname,
1888 DWORD level,
1889 LPBYTE buf,
1890 DWORD totalentries)
1891 {
1892 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
1893 debugstr_w(groupname), level, buf, totalentries);
1894 return NERR_Success;
1895 }
1896
1897 /* EOF */