2 * PROJECT: ReactOS NetAPI DLL
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: SAM service group interface code
5 * COPYRIGHT: Copyright 2018 Eric Kohl (eric.kohl@reactos.org)
8 /* INCLUDES ******************************************************************/
12 WINE_DEFAULT_DEBUG_CHANNEL(netapi32
);
14 typedef enum _ENUM_PHASE
21 typedef struct _GROUP_ENUM_CONTEXT
23 SAM_HANDLE ServerHandle
;
24 SAM_HANDLE DomainHandle
;
25 SAM_HANDLE BuiltinDomainHandle
;
26 SAM_HANDLE AccountDomainHandle
;
28 SAM_ENUMERATE_HANDLE EnumerationContext
;
29 PSAM_RID_ENUMERATION Buffer
;
33 } GROUP_ENUM_CONTEXT
, *PGROUP_ENUM_CONTEXT
;
35 typedef struct _USER_ENUM_CONTEXT
37 SAM_HANDLE ServerHandle
;
38 SAM_HANDLE DomainHandle
;
39 SAM_HANDLE GroupHandle
;
44 PUNICODE_STRING Names
;
48 } USER_ENUM_CONTEXT
, *PUSER_ENUM_CONTEXT
;
51 /* FUNCTIONS *****************************************************************/
56 _In_ PGROUP_GENERAL_INFORMATION GroupInfo
,
61 PVOID GroupBuffer
= NULL
;
62 PGROUP_INFO_0 GroupInfo0
;
63 PGROUP_INFO_1 GroupInfo1
;
64 PGROUP_INFO_2 GroupInfo2
;
65 PGROUP_INFO_3 GroupInfo3
;
68 NET_API_STATUS ApiStatus
= NERR_Success
;
75 Size
= sizeof(GROUP_INFO_0
) +
76 GroupInfo
->Name
.Length
+ sizeof(WCHAR
);
80 Size
= sizeof(GROUP_INFO_1
) +
81 GroupInfo
->Name
.Length
+ sizeof(WCHAR
) +
82 GroupInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
86 Size
= sizeof(GROUP_INFO_2
) +
87 GroupInfo
->Name
.Length
+ sizeof(WCHAR
) +
88 GroupInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
92 Size
= sizeof(GROUP_INFO_3
) +
93 GroupInfo
->Name
.Length
+ sizeof(WCHAR
) +
94 GroupInfo
->AdminComment
.Length
+ sizeof(WCHAR
);
99 ApiStatus
= ERROR_INVALID_LEVEL
;
103 ApiStatus
= NetApiBufferAllocate(Size
, &GroupBuffer
);
104 if (ApiStatus
!= NERR_Success
)
107 ZeroMemory(GroupBuffer
, Size
);
112 GroupInfo0
= (PGROUP_INFO_0
)GroupBuffer
;
114 Ptr
= (PWSTR
)((ULONG_PTR
)GroupInfo0
+ sizeof(LOCALGROUP_INFO_0
));
115 GroupInfo0
->grpi0_name
= Ptr
;
117 memcpy(GroupInfo0
->grpi0_name
,
118 GroupInfo
->Name
.Buffer
,
119 GroupInfo
->Name
.Length
);
120 GroupInfo0
->grpi0_name
[GroupInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
124 GroupInfo1
= (PGROUP_INFO_1
)GroupBuffer
;
126 Ptr
= (PWSTR
)((ULONG_PTR
)GroupInfo1
+ sizeof(GROUP_INFO_1
));
127 GroupInfo1
->grpi1_name
= Ptr
;
129 memcpy(GroupInfo1
->grpi1_name
,
130 GroupInfo
->Name
.Buffer
,
131 GroupInfo
->Name
.Length
);
132 GroupInfo1
->grpi1_name
[GroupInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
134 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ GroupInfo
->Name
.Length
+ sizeof(WCHAR
));
135 GroupInfo1
->grpi1_comment
= Ptr
;
137 memcpy(GroupInfo1
->grpi1_comment
,
138 GroupInfo
->AdminComment
.Buffer
,
139 GroupInfo
->AdminComment
.Length
);
140 GroupInfo1
->grpi1_comment
[GroupInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
144 GroupInfo2
= (PGROUP_INFO_2
)GroupBuffer
;
146 Ptr
= (PWSTR
)((ULONG_PTR
)GroupInfo2
+ sizeof(GROUP_INFO_2
));
147 GroupInfo2
->grpi2_name
= Ptr
;
149 memcpy(GroupInfo2
->grpi2_name
,
150 GroupInfo
->Name
.Buffer
,
151 GroupInfo
->Name
.Length
);
152 GroupInfo2
->grpi2_name
[GroupInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
154 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ GroupInfo
->Name
.Length
+ sizeof(WCHAR
));
155 GroupInfo2
->grpi2_comment
= Ptr
;
157 memcpy(GroupInfo2
->grpi2_comment
,
158 GroupInfo
->AdminComment
.Buffer
,
159 GroupInfo
->AdminComment
.Length
);
160 GroupInfo2
->grpi2_comment
[GroupInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
162 GroupInfo2
->grpi2_group_id
= GroupId
;
164 GroupInfo2
->grpi2_attributes
= GroupInfo
->Attributes
;
168 GroupInfo3
= (PGROUP_INFO_3
)GroupBuffer
;
170 Ptr
= (PWSTR
)((ULONG_PTR
)GroupInfo3
+ sizeof(GROUP_INFO_3
));
171 GroupInfo3
->grpi3_name
= Ptr
;
173 memcpy(GroupInfo3
->grpi3_name
,
174 GroupInfo
->Name
.Buffer
,
175 GroupInfo
->Name
.Length
);
176 GroupInfo3
->grpi3_name
[GroupInfo
->Name
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
178 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ GroupInfo
->Name
.Length
+ sizeof(WCHAR
));
179 GroupInfo3
->grpi3_comment
= Ptr
;
181 memcpy(GroupInfo3
->grpi3_comment
,
182 GroupInfo
->AdminComment
.Buffer
,
183 GroupInfo
->AdminComment
.Length
);
184 GroupInfo3
->grpi3_comment
[GroupInfo
->AdminComment
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
186 GroupInfo3
->grpi3_group_sid
= NULL
; /* FIXME */
188 GroupInfo3
->grpi3_attributes
= GroupInfo
->Attributes
;
193 if (ApiStatus
== NERR_Success
)
195 *Buffer
= GroupBuffer
;
199 if (GroupBuffer
!= NULL
)
200 NetApiBufferFree(GroupBuffer
);
210 _In_ PGROUP_GENERAL_INFORMATION GroupInfo
)
212 if (GroupInfo
->Name
.Buffer
!= NULL
)
213 SamFreeMemory(GroupInfo
->Name
.Buffer
);
215 if (GroupInfo
->AdminComment
.Buffer
!= NULL
)
216 SamFreeMemory(GroupInfo
->AdminComment
.Buffer
);
218 SamFreeMemory(GroupInfo
);
225 _In_ SAM_HANDLE DomainHandle
,
226 _In_ PUNICODE_STRING GroupName
,
227 _In_ ULONG DesiredAccess
,
228 _Out_ PSAM_HANDLE GroupHandle
,
229 _Out_ PULONG RelativeId
)
231 PULONG RelativeIds
= NULL
;
232 PSID_NAME_USE Use
= NULL
;
233 NET_API_STATUS ApiStatus
= NERR_Success
;
234 NTSTATUS Status
= STATUS_SUCCESS
;
236 /* Get the RID for the given user name */
237 Status
= SamLookupNamesInDomain(DomainHandle
,
242 if (!NT_SUCCESS(Status
))
244 WARN("SamLookupNamesInDomain(%wZ) failed (Status %08lx)\n", GroupName
, Status
);
245 return NetpNtStatusToApiStatus(Status
);
248 /* Fail, if it is not an alias account */
249 if (Use
[0] != SidTypeGroup
)
251 ERR("Object is not a group!\n");
252 ApiStatus
= NERR_GroupNotFound
;
256 /* Open the alias account */
257 Status
= SamOpenGroup(DomainHandle
,
261 if (!NT_SUCCESS(Status
))
263 ERR("SamOpenGroup failed (Status %08lx)\n", Status
);
264 ApiStatus
= NetpNtStatusToApiStatus(Status
);
268 if (RelativeId
!= NULL
)
269 *RelativeId
= RelativeIds
[0];
272 if (RelativeIds
!= NULL
)
273 SamFreeMemory(RelativeIds
);
282 /* PUBLIC FUNCTIONS **********************************************************/
287 _In_opt_ LPCWSTR servername
,
290 _Out_opt_ LPDWORD parm_err
)
292 GROUP_ADM_COMMENT_INFORMATION AdminComment
;
293 GROUP_ATTRIBUTE_INFORMATION AttributeInfo
;
294 UNICODE_STRING ServerName
;
295 UNICODE_STRING GroupName
;
296 SAM_HANDLE ServerHandle
= NULL
;
297 SAM_HANDLE DomainHandle
= NULL
;
298 SAM_HANDLE GroupHandle
= NULL
;
300 PWSTR Comment
= NULL
;
301 ULONG Attributes
= 0;
303 NET_API_STATUS ApiStatus
= NERR_Success
;
304 NTSTATUS Status
= STATUS_SUCCESS
;
306 TRACE("NetGroupAdd(%s, %d, %p, %p)\n",
307 debugstr_w(servername
), level
, buf
, parm_err
);
309 if (parm_err
!= NULL
)
310 *parm_err
= PARM_ERROR_NONE
;
312 /* Initialize the Server name*/
313 if (servername
!= NULL
)
314 RtlInitUnicodeString(&ServerName
, servername
);
316 /* Initialize the Alias name*/
320 Name
= ((PGROUP_INFO_0
)buf
)->grpi0_name
;
326 Name
= ((PGROUP_INFO_1
)buf
)->grpi1_name
;
327 Comment
= ((PGROUP_INFO_1
)buf
)->grpi1_comment
;
332 Name
= ((PGROUP_INFO_2
)buf
)->grpi2_name
;
333 Comment
= ((PGROUP_INFO_2
)buf
)->grpi2_comment
;
334 Attributes
= ((PGROUP_INFO_2
)buf
)->grpi2_attributes
;
338 Name
= ((PGROUP_INFO_3
)buf
)->grpi3_name
;
339 Comment
= ((PGROUP_INFO_3
)buf
)->grpi3_comment
;
340 Attributes
= ((PGROUP_INFO_3
)buf
)->grpi3_attributes
;
344 return ERROR_INVALID_LEVEL
;
347 RtlInitUnicodeString(&GroupName
, Name
);
349 /* Connect to the SAM Server */
350 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
352 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
354 if (!NT_SUCCESS(Status
))
356 ERR("SamConnect failed (Status %08lx)\n", Status
);
357 ApiStatus
= NetpNtStatusToApiStatus(Status
);
361 /* Open the account domain */
362 Status
= OpenAccountDomain(ServerHandle
,
363 (servername
!= NULL
) ? &ServerName
: NULL
,
364 DOMAIN_CREATE_GROUP
| DOMAIN_LOOKUP
,
366 if (!NT_SUCCESS(Status
))
368 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
369 ApiStatus
= NetpNtStatusToApiStatus(Status
);
373 /* Try to open the group account */
374 ApiStatus
= OpenGroupByName(DomainHandle
,
376 GROUP_READ_INFORMATION
,
379 if (ApiStatus
== NERR_Success
)
381 ERR("OpenGroupByName: Group %wZ already exists!\n", &GroupName
);
383 SamCloseHandle(GroupHandle
);
384 ApiStatus
= ERROR_GROUP_EXISTS
;
388 ApiStatus
= NERR_Success
;
390 /* Create the group */
391 Status
= SamCreateGroupInDomain(DomainHandle
,
393 DELETE
| GROUP_WRITE_ACCOUNT
,
396 if (!NT_SUCCESS(Status
))
398 ERR("SamCreateGroupInDomain failed (Status %08lx)\n", Status
);
399 ApiStatus
= NetpNtStatusToApiStatus(Status
);
403 TRACE("Created group \"%wZ\" (RID: %lu)\n", &GroupName
, RelativeId
);
405 /* Set the admin comment */
406 if (level
== 1 || level
== 2 || level
== 3)
408 RtlInitUnicodeString(&AdminComment
.AdminComment
, Comment
);
410 Status
= SamSetInformationGroup(GroupHandle
,
411 GroupAdminCommentInformation
,
413 if (!NT_SUCCESS(Status
))
415 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status
);
416 ApiStatus
= NetpNtStatusToApiStatus(Status
);
418 /* Delete the Alias if the Comment could not be set */
419 SamDeleteGroup(GroupHandle
);
425 /* Set the attributes */
426 if (level
== 2 || level
== 3)
428 AttributeInfo
.Attributes
= Attributes
;
430 Status
= SamSetInformationGroup(GroupHandle
,
431 GroupAttributeInformation
,
433 if (!NT_SUCCESS(Status
))
435 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status
);
436 ApiStatus
= NetpNtStatusToApiStatus(Status
);
438 /* Delete the Alias if the Attributes could not be set */
439 SamDeleteGroup(GroupHandle
);
446 if (GroupHandle
!= NULL
)
448 if (ApiStatus
!= NERR_Success
)
449 SamDeleteGroup(GroupHandle
);
451 SamCloseHandle(GroupHandle
);
454 if (DomainHandle
!= NULL
)
455 SamCloseHandle(DomainHandle
);
457 if (ServerHandle
!= NULL
)
458 SamCloseHandle(ServerHandle
);
467 _In_opt_ LPCWSTR servername
,
468 _In_ LPCWSTR groupname
,
469 _In_ LPCWSTR username
)
471 UNICODE_STRING ServerName
;
472 UNICODE_STRING GroupName
;
473 UNICODE_STRING UserName
;
474 SAM_HANDLE ServerHandle
= NULL
;
475 SAM_HANDLE DomainHandle
= NULL
;
476 SAM_HANDLE GroupHandle
= NULL
;
477 PULONG RelativeIds
= NULL
;
478 PSID_NAME_USE Use
= NULL
;
479 NET_API_STATUS ApiStatus
= NERR_Success
;
480 NTSTATUS Status
= STATUS_SUCCESS
;
482 TRACE("NetGroupAddUser(%s, %s, %s)\n",
483 debugstr_w(servername
), debugstr_w(groupname
), debugstr_w(username
));
485 if (servername
!= NULL
)
486 RtlInitUnicodeString(&ServerName
, servername
);
488 RtlInitUnicodeString(&GroupName
, groupname
);
490 RtlInitUnicodeString(&UserName
, username
);
492 /* Connect to the SAM Server */
493 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
495 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
497 if (!NT_SUCCESS(Status
))
499 ERR("SamConnect failed (Status %08lx)\n", Status
);
500 ApiStatus
= NetpNtStatusToApiStatus(Status
);
504 /* Open the Acount Domain */
505 Status
= OpenAccountDomain(ServerHandle
,
506 (servername
!= NULL
) ? &ServerName
: NULL
,
509 if (!NT_SUCCESS(Status
))
511 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
512 ApiStatus
= NetpNtStatusToApiStatus(Status
);
516 /* Open the group account */
517 ApiStatus
= OpenGroupByName(DomainHandle
,
522 if (ApiStatus
!= NERR_Success
)
524 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
525 if (ApiStatus
== ERROR_NONE_MAPPED
)
526 ApiStatus
= NERR_GroupNotFound
;
530 Status
= SamLookupNamesInDomain(DomainHandle
,
535 if (!NT_SUCCESS(Status
))
537 ERR("SamLookupNamesInDomain(%wZ) failed (Status %08lx)\n", &UserName
, Status
);
538 ApiStatus
= NetpNtStatusToApiStatus(Status
);
542 /* Fail, if it is not a user account */
543 if (Use
[0] != SidTypeUser
)
545 ERR("Object is not a user!\n");
546 ApiStatus
= NERR_GroupNotFound
;
550 Status
= SamAddMemberToGroup(GroupHandle
,
553 if (!NT_SUCCESS(Status
))
555 ERR("SamAddMemberToGroup failed (Status %lu)\n", Status
);
556 ApiStatus
= NetpNtStatusToApiStatus(Status
);
561 if (RelativeIds
!= NULL
)
562 SamFreeMemory(RelativeIds
);
567 if (GroupHandle
!= NULL
)
568 SamCloseHandle(GroupHandle
);
570 if (DomainHandle
!= NULL
)
571 SamCloseHandle(DomainHandle
);
573 if (ServerHandle
!= NULL
)
574 SamCloseHandle(ServerHandle
);
583 _In_opt_ LPCWSTR servername
,
584 _In_ IN LPCWSTR groupname
)
586 UNICODE_STRING ServerName
;
587 UNICODE_STRING GroupName
;
588 SAM_HANDLE ServerHandle
= NULL
;
589 SAM_HANDLE DomainHandle
= NULL
;
590 SAM_HANDLE GroupHandle
= NULL
;
591 NET_API_STATUS ApiStatus
= NERR_Success
;
592 NTSTATUS Status
= STATUS_SUCCESS
;
594 TRACE("NetGroupDel(%s, %s)\n",
595 debugstr_w(servername
), debugstr_w(groupname
));
597 if (servername
!= NULL
)
598 RtlInitUnicodeString(&ServerName
, servername
);
600 RtlInitUnicodeString(&GroupName
, groupname
);
602 /* Connect to the SAM Server */
603 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
605 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
607 if (!NT_SUCCESS(Status
))
609 ERR("SamConnect failed (Status %08lx)\n", Status
);
610 ApiStatus
= NetpNtStatusToApiStatus(Status
);
614 /* Open the Acount Domain */
615 Status
= OpenAccountDomain(ServerHandle
,
616 (servername
!= NULL
) ? &ServerName
: NULL
,
619 if (!NT_SUCCESS(Status
))
621 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
622 ApiStatus
= NetpNtStatusToApiStatus(Status
);
627 ApiStatus
= OpenGroupByName(DomainHandle
,
632 if (ApiStatus
!= NERR_Success
)
634 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
635 if (ApiStatus
== ERROR_NONE_MAPPED
)
636 ApiStatus
= NERR_GroupNotFound
;
640 /* Delete the group */
641 Status
= SamDeleteGroup(GroupHandle
);
642 if (!NT_SUCCESS(Status
))
644 ERR("SamDeleteGroup failed (Status %08lx)\n", Status
);
645 ApiStatus
= NetpNtStatusToApiStatus(Status
);
650 if (GroupHandle
!= NULL
)
651 SamCloseHandle(GroupHandle
);
653 if (DomainHandle
!= NULL
)
654 SamCloseHandle(DomainHandle
);
656 if (ServerHandle
!= NULL
)
657 SamCloseHandle(ServerHandle
);
666 _In_opt_ LPCWSTR servername
,
667 _In_ LPCWSTR groupname
,
668 _In_ LPCWSTR username
)
670 UNICODE_STRING ServerName
;
671 UNICODE_STRING GroupName
;
672 UNICODE_STRING UserName
;
673 SAM_HANDLE ServerHandle
= NULL
;
674 SAM_HANDLE DomainHandle
= NULL
;
675 SAM_HANDLE GroupHandle
= NULL
;
676 PULONG RelativeIds
= NULL
;
677 PSID_NAME_USE Use
= NULL
;
678 NET_API_STATUS ApiStatus
= NERR_Success
;
679 NTSTATUS Status
= STATUS_SUCCESS
;
681 TRACE("NetGroupDelUser(%s, %s, %s)\n",
682 debugstr_w(servername
), debugstr_w(groupname
), debugstr_w(username
));
684 if (servername
!= NULL
)
685 RtlInitUnicodeString(&ServerName
, servername
);
687 RtlInitUnicodeString(&GroupName
, groupname
);
689 RtlInitUnicodeString(&UserName
, username
);
691 /* Connect to the SAM Server */
692 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
694 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
696 if (!NT_SUCCESS(Status
))
698 ERR("SamConnect failed (Status %08lx)\n", Status
);
699 ApiStatus
= NetpNtStatusToApiStatus(Status
);
703 /* Open the Acount Domain */
704 Status
= OpenAccountDomain(ServerHandle
,
705 (servername
!= NULL
) ? &ServerName
: NULL
,
708 if (!NT_SUCCESS(Status
))
710 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
711 ApiStatus
= NetpNtStatusToApiStatus(Status
);
715 /* Open the group account */
716 ApiStatus
= OpenGroupByName(DomainHandle
,
721 if (ApiStatus
!= NERR_Success
)
723 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
724 if (ApiStatus
== ERROR_NONE_MAPPED
)
725 ApiStatus
= NERR_GroupNotFound
;
729 Status
= SamLookupNamesInDomain(DomainHandle
,
734 if (!NT_SUCCESS(Status
))
736 ERR("SamLookupNamesInDomain(%wZ) failed (Status %08lx)\n", &UserName
, Status
);
737 ApiStatus
= NetpNtStatusToApiStatus(Status
);
741 /* Fail, if it is not a user account */
742 if (Use
[0] != SidTypeUser
)
744 ERR("Object is not a user!\n");
745 ApiStatus
= NERR_GroupNotFound
;
749 Status
= SamRemoveMemberFromGroup(GroupHandle
,
751 if (!NT_SUCCESS(Status
))
753 ERR("SamRemoveMemberFromGroup failed (Status %lu)\n", Status
);
754 ApiStatus
= NetpNtStatusToApiStatus(Status
);
759 if (RelativeIds
!= NULL
)
760 SamFreeMemory(RelativeIds
);
765 if (GroupHandle
!= NULL
)
766 SamCloseHandle(GroupHandle
);
768 if (DomainHandle
!= NULL
)
769 SamCloseHandle(DomainHandle
);
771 if (ServerHandle
!= NULL
)
772 SamCloseHandle(ServerHandle
);
781 _In_opt_ LPCWSTR servername
,
783 _Out_ LPBYTE
*bufptr
,
784 _In_ DWORD prefmaxlen
,
785 _Out_ LPDWORD entriesread
,
786 _Out_ LPDWORD totalentries
,
787 _Inout_opt_ PDWORD_PTR resume_handle
)
789 UNICODE_STRING ServerName
;
790 PSAM_RID_ENUMERATION CurrentGroup
;
791 PGROUP_ENUM_CONTEXT EnumContext
= NULL
;
793 SAM_HANDLE GroupHandle
= NULL
;
794 PGROUP_GENERAL_INFORMATION GroupInfo
= NULL
;
796 NET_API_STATUS ApiStatus
= NERR_Success
;
797 NTSTATUS Status
= STATUS_SUCCESS
;
799 TRACE("NetGroupEnum(%s, %d, %p, %d, %p, %p, %p)\n", debugstr_w(servername
),
800 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
806 if (servername
!= NULL
)
807 RtlInitUnicodeString(&ServerName
, servername
);
809 if (resume_handle
!= NULL
&& *resume_handle
!= 0)
811 EnumContext
= (PGROUP_ENUM_CONTEXT
)*resume_handle
;
815 ApiStatus
= NetApiBufferAllocate(sizeof(GROUP_ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
816 if (ApiStatus
!= NERR_Success
)
819 EnumContext
->EnumerationContext
= 0;
820 EnumContext
->Buffer
= NULL
;
821 EnumContext
->Returned
= 0;
822 EnumContext
->Index
= 0;
824 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
825 &EnumContext
->ServerHandle
,
826 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
828 if (!NT_SUCCESS(Status
))
830 ERR("SamConnect failed (Status %08lx)\n", Status
);
831 ApiStatus
= NetpNtStatusToApiStatus(Status
);
835 Status
= OpenAccountDomain(EnumContext
->ServerHandle
,
836 (servername
!= NULL
) ? &ServerName
: NULL
,
837 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
838 &EnumContext
->AccountDomainHandle
);
839 if (!NT_SUCCESS(Status
))
841 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
842 ApiStatus
= NetpNtStatusToApiStatus(Status
);
846 Status
= OpenBuiltinDomain(EnumContext
->ServerHandle
,
847 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
848 &EnumContext
->BuiltinDomainHandle
);
849 if (!NT_SUCCESS(Status
))
851 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status
);
852 ApiStatus
= NetpNtStatusToApiStatus(Status
);
856 EnumContext
->Phase
= AccountPhase
; //BuiltinPhase;
857 EnumContext
->DomainHandle
= EnumContext
->AccountDomainHandle
; //BuiltinDomainHandle;
863 TRACE("EnumContext->Index: %lu\n", EnumContext
->Index
);
864 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
866 if (EnumContext
->Index
>= EnumContext
->Returned
)
868 TRACE("Calling SamEnumerateGroupsInDomain\n");
870 Status
= SamEnumerateGroupsInDomain(EnumContext
->DomainHandle
,
871 &EnumContext
->EnumerationContext
,
872 (PVOID
*)&EnumContext
->Buffer
,
874 &EnumContext
->Returned
);
876 TRACE("SamEnumerateGroupsInDomain returned (Status %08lx)\n", Status
);
877 if (!NT_SUCCESS(Status
))
879 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status
);
880 ApiStatus
= NetpNtStatusToApiStatus(Status
);
884 if (Status
== STATUS_MORE_ENTRIES
)
886 ApiStatus
= NERR_BufTooSmall
;
891 TRACE("EnumContext: %lu\n", EnumContext
);
892 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
893 TRACE("EnumContext->Buffer: %p\n", EnumContext
->Buffer
);
895 /* Get a pointer to the current group */
896 CurrentGroup
= &EnumContext
->Buffer
[EnumContext
->Index
];
898 TRACE("RID: %lu\n", CurrentGroup
->RelativeId
);
900 Status
= SamOpenGroup(EnumContext
->DomainHandle
,
901 GROUP_READ_INFORMATION
,
902 CurrentGroup
->RelativeId
,
904 if (!NT_SUCCESS(Status
))
906 ERR("SamOpenGroup failed (Status %08lx)\n", Status
);
907 ApiStatus
= NetpNtStatusToApiStatus(Status
);
911 Status
= SamQueryInformationGroup(GroupHandle
,
912 GroupGeneralInformation
,
913 (PVOID
*)&GroupInfo
);
914 if (!NT_SUCCESS(Status
))
916 ERR("SamQueryInformationGroup failed (Status %08lx)\n", Status
);
917 ApiStatus
= NetpNtStatusToApiStatus(Status
);
921 SamCloseHandle(GroupHandle
);
924 TRACE("Name: %S\n", GroupInfo
->Name
.Buffer
);
925 TRACE("Comment: %S\n", GroupInfo
->AdminComment
.Buffer
);
927 ApiStatus
= BuildGroupInfoBuffer(GroupInfo
,
929 CurrentGroup
->RelativeId
,
931 if (ApiStatus
!= NERR_Success
)
934 if (GroupInfo
!= NULL
)
936 FreeGroupInfo(GroupInfo
);
940 EnumContext
->Index
++;
944 if (EnumContext
->Index
== EnumContext
->Returned
)
946 switch (EnumContext
->Phase
)
949 EnumContext
->Phase
= AccountPhase
;
950 EnumContext
->DomainHandle
= EnumContext
->AccountDomainHandle
;
951 EnumContext
->EnumerationContext
= 0;
952 EnumContext
->Index
= 0;
953 EnumContext
->Returned
= 0;
955 if (EnumContext
->Buffer
!= NULL
)
957 for (i
= 0; i
< EnumContext
->Returned
; i
++)
959 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
962 SamFreeMemory(EnumContext
->Buffer
);
963 EnumContext
->Buffer
= NULL
;
969 EnumContext
->Phase
= DonePhase
;
976 if (ApiStatus
== NERR_Success
&& EnumContext
!= NULL
&& EnumContext
->Phase
!= DonePhase
)
977 ApiStatus
= ERROR_MORE_DATA
;
979 if (EnumContext
!= NULL
)
980 *totalentries
= EnumContext
->Returned
;
982 if (resume_handle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
984 if (EnumContext
!= NULL
)
986 if (EnumContext
->BuiltinDomainHandle
!= NULL
)
987 SamCloseHandle(EnumContext
->BuiltinDomainHandle
);
989 if (EnumContext
->AccountDomainHandle
!= NULL
)
990 SamCloseHandle(EnumContext
->AccountDomainHandle
);
992 if (EnumContext
->ServerHandle
!= NULL
)
993 SamCloseHandle(EnumContext
->ServerHandle
);
995 if (EnumContext
->Buffer
!= NULL
)
997 for (i
= 0; i
< EnumContext
->Returned
; i
++)
999 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
1002 SamFreeMemory(EnumContext
->Buffer
);
1005 NetApiBufferFree(EnumContext
);
1010 if (GroupHandle
!= NULL
)
1011 SamCloseHandle(GroupHandle
);
1013 if (GroupInfo
!= NULL
)
1014 FreeGroupInfo(GroupInfo
);
1016 if (resume_handle
!= NULL
)
1017 *resume_handle
= (DWORD_PTR
)EnumContext
;
1019 *bufptr
= (LPBYTE
)Buffer
;
1021 TRACE("return %lu\n", ApiStatus
);
1030 _In_opt_ LPCWSTR servername
,
1031 _In_ LPCWSTR groupname
,
1033 _Out_ LPBYTE
*bufptr
)
1035 UNICODE_STRING ServerName
;
1036 UNICODE_STRING GroupName
;
1037 SAM_HANDLE ServerHandle
= NULL
;
1038 SAM_HANDLE DomainHandle
= NULL
;
1039 SAM_HANDLE GroupHandle
= NULL
;
1040 PGROUP_GENERAL_INFORMATION GroupInfo
= NULL
;
1041 PVOID Buffer
= NULL
;
1043 NET_API_STATUS ApiStatus
= NERR_Success
;
1044 NTSTATUS Status
= STATUS_SUCCESS
;
1046 TRACE("NetGroupGetInfo(%s, %s, %d, %p)\n",
1047 debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
);
1049 if (servername
!= NULL
)
1050 RtlInitUnicodeString(&ServerName
, servername
);
1052 RtlInitUnicodeString(&GroupName
, groupname
);
1054 /* Connect to the SAM Server */
1055 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1057 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1059 if (!NT_SUCCESS(Status
))
1061 ERR("SamConnect failed (Status %08lx)\n", Status
);
1062 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1066 /* Open the Acount Domain */
1067 Status
= OpenAccountDomain(ServerHandle
,
1068 (servername
!= NULL
) ? &ServerName
: NULL
,
1071 if (!NT_SUCCESS(Status
))
1073 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1074 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1078 /* Open the group account in the account domain */
1079 ApiStatus
= OpenGroupByName(DomainHandle
,
1081 GROUP_READ_INFORMATION
,
1084 if (ApiStatus
!= NERR_Success
)
1086 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
1087 if (ApiStatus
== ERROR_NONE_MAPPED
)
1088 ApiStatus
= NERR_GroupNotFound
;
1092 Status
= SamQueryInformationGroup(GroupHandle
,
1093 GroupGeneralInformation
,
1094 (PVOID
*)&GroupInfo
);
1095 if (!NT_SUCCESS(Status
))
1097 ERR("SamQueryInformationGroup failed (Status %08lx)\n", Status
);
1098 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1102 ApiStatus
= BuildGroupInfoBuffer(GroupInfo
,
1106 if (ApiStatus
!= NERR_Success
)
1110 if (GroupInfo
!= NULL
)
1111 FreeGroupInfo(GroupInfo
);
1113 if (GroupHandle
!= NULL
)
1114 SamCloseHandle(GroupHandle
);
1116 if (DomainHandle
!= NULL
)
1117 SamCloseHandle(DomainHandle
);
1119 if (ServerHandle
!= NULL
)
1120 SamCloseHandle(ServerHandle
);
1122 *bufptr
= (LPBYTE
)Buffer
;
1131 _In_opt_ LPCWSTR servername
,
1132 _In_ LPCWSTR groupname
,
1134 _Out_ LPBYTE
*bufptr
,
1135 _In_ DWORD prefmaxlen
,
1136 _Out_ LPDWORD entriesread
,
1137 _Out_ LPDWORD totalentries
,
1138 _Inout_ PDWORD_PTR resume_handle
)
1140 UNICODE_STRING ServerName
;
1141 UNICODE_STRING GroupName
;
1142 PGROUP_USERS_INFO_0 UserInfo0
;
1143 PGROUP_USERS_INFO_1 UserInfo1
;
1144 PUSER_ENUM_CONTEXT EnumContext
= NULL
;
1145 PVOID Buffer
= NULL
;
1148 NET_API_STATUS ApiStatus
= NERR_Success
;
1149 NTSTATUS Status
= STATUS_SUCCESS
;
1151 TRACE("NetGroupGetUsers(%s, %s, %d, %p, %d, %p, %p, %p)\n",
1152 debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
,
1153 prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1159 if (servername
!= NULL
)
1160 RtlInitUnicodeString(&ServerName
, servername
);
1162 RtlInitUnicodeString(&GroupName
, groupname
);
1164 if (resume_handle
!= NULL
&& *resume_handle
!= 0)
1166 EnumContext
= (PUSER_ENUM_CONTEXT
)*resume_handle
;
1170 ApiStatus
= NetApiBufferAllocate(sizeof(USER_ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
1171 if (ApiStatus
!= NERR_Success
)
1174 EnumContext
->MemberCount
= 0;
1175 EnumContext
->MemberIds
= NULL
;
1176 EnumContext
->Attributes
= NULL
;
1177 EnumContext
->Names
= NULL
;
1178 EnumContext
->Start
= 0;
1179 EnumContext
->Count
= 0;
1181 /* Connect to the SAM Server */
1182 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1183 &EnumContext
->ServerHandle
,
1184 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1186 if (!NT_SUCCESS(Status
))
1188 ERR("SamConnect failed (Status %08lx)\n", Status
);
1189 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1193 /* Open the Acount Domain */
1194 Status
= OpenAccountDomain(EnumContext
->ServerHandle
,
1195 (servername
!= NULL
) ? &ServerName
: NULL
,
1197 &EnumContext
->DomainHandle
);
1198 if (!NT_SUCCESS(Status
))
1200 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1201 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1205 /* Open the group account */
1206 ApiStatus
= OpenGroupByName(EnumContext
->DomainHandle
,
1209 &EnumContext
->GroupHandle
,
1211 if (ApiStatus
!= NERR_Success
)
1213 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
1214 if (ApiStatus
== ERROR_NONE_MAPPED
)
1215 ApiStatus
= NERR_GroupNotFound
;
1219 /* Get the group members */
1220 Status
= SamGetMembersInGroup(EnumContext
->GroupHandle
,
1221 &EnumContext
->MemberIds
,
1222 &EnumContext
->Attributes
,
1223 &EnumContext
->MemberCount
);
1224 if (!NT_SUCCESS(Status
))
1226 ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status
);
1227 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1231 if (EnumContext
->MemberCount
> 0)
1233 /* Get all member names */
1234 Status
= SamLookupIdsInDomain(EnumContext
->DomainHandle
,
1235 EnumContext
->MemberCount
,
1236 EnumContext
->MemberIds
,
1237 &EnumContext
->Names
,
1239 if (!NT_SUCCESS(Status
))
1241 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status
);
1242 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1248 /* Calculate the required buffer size */
1250 if (prefmaxlen
== -1)
1252 Size
= EnumContext
->MemberCount
*
1253 ((level
== 0) ? sizeof(GROUP_USERS_INFO_0
) : sizeof(GROUP_USERS_INFO_1
));
1254 for (i
= EnumContext
->Start
; i
< EnumContext
->MemberCount
; i
++)
1255 Size
+= EnumContext
->Names
[i
].Length
+ sizeof(WCHAR
);
1257 EnumContext
->Count
= EnumContext
->MemberCount
;
1261 for (i
= EnumContext
->Start
; i
< EnumContext
->MemberCount
; i
++)
1263 Size
+= (level
== 0) ? sizeof(GROUP_USERS_INFO_0
) : sizeof(GROUP_USERS_INFO_1
);
1264 Size
+= EnumContext
->Names
[i
].Length
+ sizeof(WCHAR
);
1266 EnumContext
->Count
++;
1268 if (Size
>= prefmaxlen
)
1273 TRACE("Buffer size: %lu\n", Size
);
1275 /* Allocate and clear the buffer */
1276 ApiStatus
= NetApiBufferAllocate(Size
, &Buffer
);
1277 if (ApiStatus
!= NERR_Success
)
1280 ZeroMemory(Buffer
, Size
);
1282 /* Fill the buffer */
1284 Ptr
= (PWCHAR
)((LONG_PTR
)Buffer
+ EnumContext
->Count
* sizeof(GROUP_USERS_INFO_0
));
1286 Ptr
= (PWCHAR
)((LONG_PTR
)Buffer
+ EnumContext
->Count
* sizeof(GROUP_USERS_INFO_1
));
1288 for (i
= 0; i
< EnumContext
->Count
; i
++)
1290 idx
= EnumContext
->Start
+ i
;
1294 UserInfo0
= (PGROUP_USERS_INFO_0
)Buffer
;
1296 UserInfo0
[i
].grui0_name
= Ptr
;
1298 memcpy(UserInfo0
[i
].grui0_name
,
1299 EnumContext
->Names
[idx
].Buffer
,
1300 EnumContext
->Names
[idx
].Length
);
1301 UserInfo0
[i
].grui0_name
[EnumContext
->Names
[idx
].Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1303 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ EnumContext
->Names
[idx
].Length
+ sizeof(WCHAR
));
1307 UserInfo1
= (PGROUP_USERS_INFO_1
)Buffer
;
1309 UserInfo1
[i
].grui1_name
= Ptr
;
1311 memcpy(UserInfo1
[i
].grui1_name
,
1312 EnumContext
->Names
[idx
].Buffer
,
1313 EnumContext
->Names
[idx
].Length
);
1314 UserInfo1
[i
].grui1_name
[EnumContext
->Names
[idx
].Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1316 UserInfo1
[i
].grui1_attributes
= EnumContext
->Attributes
[idx
];
1318 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ EnumContext
->Names
[idx
].Length
+ sizeof(WCHAR
));
1322 /* Set the new start index */
1323 EnumContext
->Start
+= EnumContext
->Count
;
1325 /* Only return ERROR_MORE_DATA if we are not done yet */
1326 if (EnumContext
->MemberCount
> EnumContext
->Start
)
1327 ApiStatus
= ERROR_MORE_DATA
;
1329 ApiStatus
= NERR_Success
;
1332 if (EnumContext
!= NULL
)
1334 *entriesread
= EnumContext
->Count
;
1335 *totalentries
= EnumContext
->MemberCount
;
1338 if (resume_handle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
1340 if (EnumContext
!= NULL
)
1342 if (EnumContext
->Names
!= NULL
)
1344 for (i
= 0; i
< EnumContext
->MemberCount
; i
++)
1345 SamFreeMemory(EnumContext
->Names
[i
].Buffer
);
1347 SamFreeMemory(EnumContext
->Names
);
1350 if (EnumContext
->Attributes
!= NULL
)
1351 SamFreeMemory(EnumContext
->Attributes
);
1353 if (EnumContext
->MemberIds
!= NULL
)
1354 SamFreeMemory(EnumContext
->MemberIds
);
1357 if (EnumContext
->GroupHandle
!= NULL
)
1358 SamCloseHandle(EnumContext
->GroupHandle
);
1360 if (EnumContext
->DomainHandle
!= NULL
)
1361 SamCloseHandle(EnumContext
->DomainHandle
);
1363 if (EnumContext
->ServerHandle
!= NULL
)
1364 SamCloseHandle(EnumContext
->ServerHandle
);
1366 NetApiBufferFree(EnumContext
);
1371 *bufptr
= (LPBYTE
)Buffer
;
1373 if (resume_handle
!= NULL
)
1374 *resume_handle
= (DWORD_PTR
)EnumContext
;
1383 _In_opt_ LPCWSTR servername
,
1384 _In_ LPCWSTR groupname
,
1387 _Out_opt_ LPDWORD parm_err
)
1389 UNICODE_STRING ServerName
;
1390 UNICODE_STRING GroupName
;
1391 SAM_HANDLE ServerHandle
= NULL
;
1392 SAM_HANDLE DomainHandle
= NULL
;
1393 SAM_HANDLE GroupHandle
= NULL
;
1394 GROUP_NAME_INFORMATION GroupNameInfo
;
1395 GROUP_ADM_COMMENT_INFORMATION AdminCommentInfo
;
1396 GROUP_ATTRIBUTE_INFORMATION AttributeInfo
;
1397 NET_API_STATUS ApiStatus
= NERR_Success
;
1398 NTSTATUS Status
= STATUS_SUCCESS
;
1400 TRACE("NetGroupSetInfo(%s, %s, %d, %p, %p)\n",
1401 debugstr_w(servername
), debugstr_w(groupname
), level
, buf
, parm_err
);
1403 if (parm_err
!= NULL
)
1404 *parm_err
= PARM_ERROR_NONE
;
1406 if (servername
!= NULL
)
1407 RtlInitUnicodeString(&ServerName
, servername
);
1409 RtlInitUnicodeString(&GroupName
, groupname
);
1411 /* Connect to the SAM Server */
1412 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1414 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1416 if (!NT_SUCCESS(Status
))
1418 ERR("SamConnect failed (Status %08lx)\n", Status
);
1419 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1423 /* Open the Acount Domain */
1424 Status
= OpenAccountDomain(ServerHandle
,
1425 (servername
!= NULL
) ? &ServerName
: NULL
,
1428 if (!NT_SUCCESS(Status
))
1430 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1431 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1435 /* Open the group */
1436 ApiStatus
= OpenGroupByName(DomainHandle
,
1438 GROUP_WRITE_ACCOUNT
,
1441 if (ApiStatus
!= NERR_Success
)
1443 WARN("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
1444 if (ApiStatus
== ERROR_NONE_MAPPED
)
1445 ApiStatus
= NERR_GroupNotFound
;
1452 /* Set the group name */
1453 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1454 ((PGROUP_INFO_0
)buf
)->grpi0_name
);
1456 Status
= SamSetInformationGroup(GroupHandle
,
1457 GroupNameInformation
,
1459 if (!NT_SUCCESS(Status
))
1461 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1462 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1468 /* Set the group name */
1469 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1470 ((PGROUP_INFO_1
)buf
)->grpi1_name
);
1472 Status
= SamSetInformationGroup(GroupHandle
,
1473 GroupNameInformation
,
1475 if (!NT_SUCCESS(Status
))
1477 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1478 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1482 /* Set the admin comment */
1483 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1484 ((PGROUP_INFO_1
)buf
)->grpi1_comment
);
1486 Status
= SamSetInformationGroup(GroupHandle
,
1487 GroupAdminCommentInformation
,
1489 if (!NT_SUCCESS(Status
))
1491 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1492 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1498 /* Set the group name */
1499 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1500 ((PGROUP_INFO_2
)buf
)->grpi2_name
);
1502 Status
= SamSetInformationGroup(GroupHandle
,
1503 GroupNameInformation
,
1505 if (!NT_SUCCESS(Status
))
1507 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1508 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1512 /* Set the admin comment */
1513 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1514 ((PGROUP_INFO_2
)buf
)->grpi2_comment
);
1516 Status
= SamSetInformationGroup(GroupHandle
,
1517 GroupAdminCommentInformation
,
1519 if (!NT_SUCCESS(Status
))
1521 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1522 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1526 /* Set the attributes */
1527 AttributeInfo
.Attributes
= ((PGROUP_INFO_2
)buf
)->grpi2_attributes
;
1529 Status
= SamSetInformationGroup(GroupHandle
,
1530 GroupAttributeInformation
,
1532 if (!NT_SUCCESS(Status
))
1534 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1535 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1541 /* Set the group name */
1542 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1543 ((PGROUP_INFO_3
)buf
)->grpi3_name
);
1545 Status
= SamSetInformationGroup(GroupHandle
,
1546 GroupNameInformation
,
1548 if (!NT_SUCCESS(Status
))
1550 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1551 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1555 /* Set the admin comment */
1556 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1557 ((PGROUP_INFO_3
)buf
)->grpi3_comment
);
1559 Status
= SamSetInformationGroup(GroupHandle
,
1560 GroupAdminCommentInformation
,
1562 if (!NT_SUCCESS(Status
))
1564 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1565 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1569 /* Set the attributes */
1570 AttributeInfo
.Attributes
= ((PGROUP_INFO_3
)buf
)->grpi3_attributes
;
1572 Status
= SamSetInformationGroup(GroupHandle
,
1573 GroupAttributeInformation
,
1575 if (!NT_SUCCESS(Status
))
1577 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1578 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1584 /* Set the admin comment */
1585 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1586 ((PGROUP_INFO_1002
)buf
)->grpi1002_comment
);
1588 Status
= SamSetInformationGroup(GroupHandle
,
1589 GroupAdminCommentInformation
,
1591 if (!NT_SUCCESS(Status
))
1593 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1594 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1600 /* Set the attributes */
1601 AttributeInfo
.Attributes
= ((PGROUP_INFO_1005
)buf
)->grpi1005_attributes
;
1603 Status
= SamSetInformationGroup(GroupHandle
,
1604 GroupAttributeInformation
,
1606 if (!NT_SUCCESS(Status
))
1608 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1609 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1615 ApiStatus
= ERROR_INVALID_LEVEL
;
1620 if (GroupHandle
!= NULL
)
1621 SamCloseHandle(GroupHandle
);
1623 if (DomainHandle
!= NULL
)
1624 SamCloseHandle(DomainHandle
);
1626 if (ServerHandle
!= NULL
)
1627 SamCloseHandle(ServerHandle
);
1636 _In_opt_ LPCWSTR servername
,
1637 _In_ LPCWSTR groupname
,
1640 _In_ DWORD totalentries
)
1642 UNICODE_STRING ServerName
;
1643 UNICODE_STRING GroupName
;
1644 SAM_HANDLE ServerHandle
= NULL
;
1645 SAM_HANDLE DomainHandle
= NULL
;
1646 SAM_HANDLE GroupHandle
= NULL
;
1647 ULONG OldMemberCount
= 0;
1648 PULONG OldMemberIDs
= NULL
;
1649 PULONG OldAttributes
= NULL
;
1650 PUNICODE_STRING NamesArray
= NULL
;
1651 PGROUP_USERS_INFO_0 UserInfo0
;
1652 PGROUP_USERS_INFO_1 UserInfo1
;
1653 PULONG NewMemberIDs
= NULL
;
1654 PSID_NAME_USE NewMemberUse
= NULL
;
1657 NET_API_STATUS ApiStatus
= NERR_Success
;
1658 NTSTATUS Status
= STATUS_SUCCESS
;
1660 TRACE("NetGroupSetUsers(%s, %s, %d, %p, %d) stub!\n",
1661 debugstr_w(servername
), debugstr_w(groupname
), level
, buf
, totalentries
);
1663 if (servername
!= NULL
)
1664 RtlInitUnicodeString(&ServerName
, servername
);
1666 RtlInitUnicodeString(&GroupName
, groupname
);
1668 /* Connect to the SAM Server */
1669 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1671 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1673 if (!NT_SUCCESS(Status
))
1675 ERR("SamConnect failed (Status %08lx)\n", Status
);
1676 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1680 /* Open the Acount Domain */
1681 Status
= OpenAccountDomain(ServerHandle
,
1682 (servername
!= NULL
) ? &ServerName
: NULL
,
1685 if (!NT_SUCCESS(Status
))
1687 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1688 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1692 /* Open the group account in the account domain */
1693 ApiStatus
= OpenGroupByName(DomainHandle
,
1695 GROUP_LIST_MEMBERS
| GROUP_ADD_MEMBER
| GROUP_REMOVE_MEMBER
,
1698 if (ApiStatus
!= NERR_Success
)
1700 ERR("OpenGroupByName(%wZ) failed (ApiStatus %lu)\n", &GroupName
, ApiStatus
);
1701 if (ApiStatus
== ERROR_NONE_MAPPED
)
1702 ApiStatus
= NERR_GroupNotFound
;
1706 /* Get the group members */
1707 Status
= SamGetMembersInGroup(GroupHandle
,
1711 if (!NT_SUCCESS(Status
))
1713 ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status
);
1714 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1718 NamesArray
= RtlAllocateHeap(RtlGetProcessHeap(),
1720 totalentries
* sizeof(UNICODE_STRING
));
1721 if (NamesArray
== NULL
)
1723 ERR("RtlAllocateHeap failed\n");
1724 ApiStatus
= ERROR_OUTOFMEMORY
;
1728 UserInfo0
= (PGROUP_USERS_INFO_0
)buf
;
1729 UserInfo1
= (PGROUP_USERS_INFO_1
)buf
;
1730 for (i
= 0; i
< totalentries
; i
++)
1733 RtlInitUnicodeString(&NamesArray
[i
], UserInfo0
[i
].grui0_name
);
1735 RtlInitUnicodeString(&NamesArray
[i
], UserInfo1
[i
].grui1_name
);
1738 Status
= SamLookupNamesInDomain(DomainHandle
,
1743 if (!NT_SUCCESS(Status
))
1745 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status
);
1747 if (Status
== STATUS_NONE_MAPPED
)
1749 ApiStatus
= NERR_UserNotFound
;
1753 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1757 /* Add members and set attributes for existing members */
1758 for (i
= 0; i
< totalentries
; i
++)
1761 for (j
= 0; j
< OldMemberCount
; j
++)
1763 if (NewMemberIDs
[i
] == OldMemberIDs
[j
])
1767 Status
= SamSetMemberAttributesOfGroup(GroupHandle
,
1769 UserInfo1
[i
].grui1_attributes
);
1770 if (!NT_SUCCESS(Status
))
1772 ERR("SamSetMemberAttributesOfGroup failed (Status %lu)\n", Status
);
1773 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1785 TRACE("Add member %lx\n", NewMemberIDs
[i
]);
1787 if (NewMemberUse
[i
] != SidTypeUser
)
1789 ERR("New member is not a user!\n");
1790 ApiStatus
= NERR_GroupNotFound
;
1794 Status
= SamAddMemberToGroup(GroupHandle
,
1796 (level
== 0) ? 0 : UserInfo1
[i
].grui1_attributes
);
1797 if (!NT_SUCCESS(Status
))
1799 ERR("SamAddMemberToGroup failed (Status %lu)\n", Status
);
1800 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1806 /* Remove members */
1807 for (i
= 0; i
< OldMemberCount
; i
++)
1810 for (j
= 0; j
< totalentries
; j
++)
1812 if (OldMemberIDs
[i
] == NewMemberIDs
[j
])
1821 TRACE("Delete member %lx\n", OldMemberIDs
[i
]);
1823 Status
= SamRemoveMemberFromGroup(GroupHandle
,
1825 if (!NT_SUCCESS(Status
))
1827 ERR("SamRemoveMemberFromGroup failed (Status %lu)\n", Status
);
1828 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1835 if (NewMemberUse
!= NULL
)
1836 SamFreeMemory(NewMemberUse
);
1838 if (NewMemberIDs
!= NULL
)
1839 SamFreeMemory(NewMemberIDs
);
1841 if (NamesArray
!= NULL
)
1842 RtlFreeHeap(RtlGetProcessHeap(), 0, NamesArray
);
1844 if (OldMemberIDs
!= NULL
)
1845 SamFreeMemory(OldMemberIDs
);
1847 if (GroupHandle
!= NULL
)
1848 SamCloseHandle(GroupHandle
);
1850 if (DomainHandle
!= NULL
)
1851 SamCloseHandle(DomainHandle
);
1853 if (ServerHandle
!= NULL
)
1854 SamCloseHandle(ServerHandle
);