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 _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 } ENUM_CONTEXT
, *PENUM_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 failed (Status %08lx)\n", 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 /* Initialize the Server name*/
310 if (servername
!= NULL
)
311 RtlInitUnicodeString(&ServerName
, servername
);
313 /* Initialize the Alias name*/
317 Name
= ((PGROUP_INFO_0
)buf
)->grpi0_name
;
323 Name
= ((PGROUP_INFO_1
)buf
)->grpi1_name
;
324 Comment
= ((PGROUP_INFO_1
)buf
)->grpi1_comment
;
329 Name
= ((PGROUP_INFO_2
)buf
)->grpi2_name
;
330 Comment
= ((PGROUP_INFO_2
)buf
)->grpi2_comment
;
331 Attributes
= ((PGROUP_INFO_2
)buf
)->grpi2_attributes
;
335 Name
= ((PGROUP_INFO_3
)buf
)->grpi3_name
;
336 Comment
= ((PGROUP_INFO_3
)buf
)->grpi3_comment
;
337 Attributes
= ((PGROUP_INFO_3
)buf
)->grpi3_attributes
;
341 return ERROR_INVALID_LEVEL
;
344 RtlInitUnicodeString(&GroupName
, Name
);
346 /* Connect to the SAM Server */
347 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
349 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
351 if (!NT_SUCCESS(Status
))
353 ERR("SamConnect failed (Status %08lx)\n", Status
);
354 ApiStatus
= NetpNtStatusToApiStatus(Status
);
358 /* Open the account domain */
359 Status
= OpenAccountDomain(ServerHandle
,
360 (servername
!= NULL
) ? &ServerName
: NULL
,
361 DOMAIN_CREATE_GROUP
| DOMAIN_LOOKUP
,
363 if (!NT_SUCCESS(Status
))
365 ERR("SamOpenDomain failed (Status %08lx)\n", Status
);
366 ApiStatus
= NetpNtStatusToApiStatus(Status
);
370 /* Try to open the group account */
371 ApiStatus
= OpenGroupByName(DomainHandle
,
373 GROUP_READ_INFORMATION
,
376 if (ApiStatus
== NERR_Success
)
378 ERR("OpenGroupByName: Group %wZ already exists!\n", &GroupName
);
380 SamCloseHandle(GroupHandle
);
381 ApiStatus
= ERROR_GROUP_EXISTS
;
385 ApiStatus
= NERR_Success
;
387 /* Create the group */
388 Status
= SamCreateGroupInDomain(DomainHandle
,
390 DELETE
| GROUP_WRITE_ACCOUNT
,
393 if (!NT_SUCCESS(Status
))
395 ERR("SamCreateGroupInDomain failed (Status %08lx)\n", Status
);
396 ApiStatus
= NetpNtStatusToApiStatus(Status
);
400 TRACE("Created group \"%wZ\" (RID: %lu)\n", &GroupName
, RelativeId
);
402 /* Set the admin comment */
403 if (level
== 1 || level
== 2 || level
== 3)
405 RtlInitUnicodeString(&AdminComment
.AdminComment
, Comment
);
407 Status
= SamSetInformationGroup(GroupHandle
,
408 GroupAdminCommentInformation
,
410 if (!NT_SUCCESS(Status
))
412 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status
);
413 ApiStatus
= NetpNtStatusToApiStatus(Status
);
415 /* Delete the Alias if the Comment could not be set */
416 SamDeleteGroup(GroupHandle
);
422 /* Set the attributes */
423 if (level
== 2 || level
== 3)
425 AttributeInfo
.Attributes
= Attributes
;
427 Status
= SamSetInformationGroup(GroupHandle
,
428 GroupAttributeInformation
,
430 if (!NT_SUCCESS(Status
))
432 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status
);
433 ApiStatus
= NetpNtStatusToApiStatus(Status
);
435 /* Delete the Alias if the Attributes could not be set */
436 SamDeleteGroup(GroupHandle
);
443 if (GroupHandle
!= NULL
)
445 if (ApiStatus
!= NERR_Success
)
446 SamDeleteGroup(GroupHandle
);
448 SamCloseHandle(GroupHandle
);
451 if (DomainHandle
!= NULL
)
452 SamCloseHandle(DomainHandle
);
454 if (ServerHandle
!= NULL
)
455 SamCloseHandle(ServerHandle
);
464 _In_opt_ LPCWSTR servername
,
465 _In_ LPCWSTR groupname
,
466 _In_ LPCWSTR username
)
468 UNICODE_STRING ServerName
;
469 UNICODE_STRING GroupName
;
470 UNICODE_STRING UserName
;
471 SAM_HANDLE ServerHandle
= NULL
;
472 SAM_HANDLE DomainHandle
= NULL
;
473 SAM_HANDLE GroupHandle
= NULL
;
474 PULONG RelativeIds
= NULL
;
475 PSID_NAME_USE Use
= NULL
;
476 NET_API_STATUS ApiStatus
= NERR_Success
;
477 NTSTATUS Status
= STATUS_SUCCESS
;
479 TRACE("NetGroupAddUser(%s, %s, %s)\n",
480 debugstr_w(servername
), debugstr_w(groupname
), debugstr_w(username
));
482 if (servername
!= NULL
)
483 RtlInitUnicodeString(&ServerName
, servername
);
485 RtlInitUnicodeString(&GroupName
, groupname
);
487 RtlInitUnicodeString(&UserName
, username
);
489 /* Connect to the SAM Server */
490 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
492 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
494 if (!NT_SUCCESS(Status
))
496 ERR("SamConnect failed (Status %08lx)\n", Status
);
497 ApiStatus
= NetpNtStatusToApiStatus(Status
);
501 /* Open the Acount Domain */
502 Status
= OpenAccountDomain(ServerHandle
,
503 (servername
!= NULL
) ? &ServerName
: NULL
,
506 if (!NT_SUCCESS(Status
))
508 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
509 ApiStatus
= NetpNtStatusToApiStatus(Status
);
513 /* Open the group account */
514 ApiStatus
= OpenGroupByName(DomainHandle
,
519 if (ApiStatus
!= NERR_Success
)
521 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
522 if (ApiStatus
== ERROR_NONE_MAPPED
)
523 ApiStatus
= NERR_GroupNotFound
;
527 Status
= SamLookupNamesInDomain(DomainHandle
,
532 if (!NT_SUCCESS(Status
))
534 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status
);
535 ApiStatus
= NetpNtStatusToApiStatus(Status
);
539 /* Fail, if it is not a user account */
540 if (Use
[0] != SidTypeUser
)
542 ERR("Object is not a user!\n");
543 ApiStatus
= NERR_GroupNotFound
;
547 Status
= SamAddMemberToGroup(GroupHandle
,
550 if (!NT_SUCCESS(Status
))
552 ERR("SamAddMemberToGroup failed (Status %lu)\n", Status
);
553 ApiStatus
= NetpNtStatusToApiStatus(Status
);
558 if (RelativeIds
!= NULL
)
559 SamFreeMemory(RelativeIds
);
564 if (GroupHandle
!= NULL
)
565 SamCloseHandle(GroupHandle
);
567 if (DomainHandle
!= NULL
)
568 SamCloseHandle(DomainHandle
);
570 if (ServerHandle
!= NULL
)
571 SamCloseHandle(ServerHandle
);
580 _In_opt_ LPCWSTR servername
,
581 _In_ IN LPCWSTR groupname
)
583 UNICODE_STRING ServerName
;
584 UNICODE_STRING GroupName
;
585 SAM_HANDLE ServerHandle
= NULL
;
586 SAM_HANDLE DomainHandle
= NULL
;
587 SAM_HANDLE GroupHandle
= NULL
;
588 NET_API_STATUS ApiStatus
= NERR_Success
;
589 NTSTATUS Status
= STATUS_SUCCESS
;
591 TRACE("NetGroupDel(%s, %s)\n",
592 debugstr_w(servername
), debugstr_w(groupname
));
594 if (servername
!= NULL
)
595 RtlInitUnicodeString(&ServerName
, servername
);
597 RtlInitUnicodeString(&GroupName
, groupname
);
599 /* Connect to the SAM Server */
600 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
602 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
604 if (!NT_SUCCESS(Status
))
606 ERR("SamConnect failed (Status %08lx)\n", Status
);
607 ApiStatus
= NetpNtStatusToApiStatus(Status
);
611 /* Open the Acount Domain */
612 Status
= OpenAccountDomain(ServerHandle
,
613 (servername
!= NULL
) ? &ServerName
: NULL
,
616 if (!NT_SUCCESS(Status
))
618 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
619 ApiStatus
= NetpNtStatusToApiStatus(Status
);
624 ApiStatus
= OpenGroupByName(DomainHandle
,
629 if (ApiStatus
!= NERR_Success
)
631 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
632 if (ApiStatus
== ERROR_NONE_MAPPED
)
633 ApiStatus
= NERR_GroupNotFound
;
637 /* Delete the group */
638 Status
= SamDeleteGroup(GroupHandle
);
639 if (!NT_SUCCESS(Status
))
641 ERR("SamDeleteGroup failed (Status %08lx)\n", Status
);
642 ApiStatus
= NetpNtStatusToApiStatus(Status
);
647 if (GroupHandle
!= NULL
)
648 SamCloseHandle(GroupHandle
);
650 if (DomainHandle
!= NULL
)
651 SamCloseHandle(DomainHandle
);
653 if (ServerHandle
!= NULL
)
654 SamCloseHandle(ServerHandle
);
663 _In_opt_ LPCWSTR servername
,
664 _In_ LPCWSTR groupname
,
665 _In_ LPCWSTR username
)
667 UNICODE_STRING ServerName
;
668 UNICODE_STRING GroupName
;
669 UNICODE_STRING UserName
;
670 SAM_HANDLE ServerHandle
= NULL
;
671 SAM_HANDLE DomainHandle
= NULL
;
672 SAM_HANDLE GroupHandle
= NULL
;
673 PULONG RelativeIds
= NULL
;
674 PSID_NAME_USE Use
= NULL
;
675 NET_API_STATUS ApiStatus
= NERR_Success
;
676 NTSTATUS Status
= STATUS_SUCCESS
;
678 TRACE("NetGroupDelUser(%s, %s, %s)\n",
679 debugstr_w(servername
), debugstr_w(groupname
), debugstr_w(username
));
681 if (servername
!= NULL
)
682 RtlInitUnicodeString(&ServerName
, servername
);
684 RtlInitUnicodeString(&GroupName
, groupname
);
686 RtlInitUnicodeString(&UserName
, username
);
688 /* Connect to the SAM Server */
689 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
691 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
693 if (!NT_SUCCESS(Status
))
695 ERR("SamConnect failed (Status %08lx)\n", Status
);
696 ApiStatus
= NetpNtStatusToApiStatus(Status
);
700 /* Open the Acount Domain */
701 Status
= OpenAccountDomain(ServerHandle
,
702 (servername
!= NULL
) ? &ServerName
: NULL
,
705 if (!NT_SUCCESS(Status
))
707 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
708 ApiStatus
= NetpNtStatusToApiStatus(Status
);
712 /* Open the group account */
713 ApiStatus
= OpenGroupByName(DomainHandle
,
718 if (ApiStatus
!= NERR_Success
)
720 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
721 if (ApiStatus
== ERROR_NONE_MAPPED
)
722 ApiStatus
= NERR_GroupNotFound
;
726 Status
= SamLookupNamesInDomain(DomainHandle
,
731 if (!NT_SUCCESS(Status
))
733 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status
);
734 ApiStatus
= NetpNtStatusToApiStatus(Status
);
738 /* Fail, if it is not a user account */
739 if (Use
[0] != SidTypeUser
)
741 ERR("Object is not a user!\n");
742 ApiStatus
= NERR_GroupNotFound
;
746 Status
= SamRemoveMemberFromGroup(GroupHandle
,
748 if (!NT_SUCCESS(Status
))
750 ERR("SamRemoveMemberFromGroup failed (Status %lu)\n", Status
);
751 ApiStatus
= NetpNtStatusToApiStatus(Status
);
756 if (RelativeIds
!= NULL
)
757 SamFreeMemory(RelativeIds
);
762 if (GroupHandle
!= NULL
)
763 SamCloseHandle(GroupHandle
);
765 if (DomainHandle
!= NULL
)
766 SamCloseHandle(DomainHandle
);
768 if (ServerHandle
!= NULL
)
769 SamCloseHandle(ServerHandle
);
778 _In_opt_ LPCWSTR servername
,
780 _Out_ LPBYTE
*bufptr
,
781 _In_ DWORD prefmaxlen
,
782 _Out_ LPDWORD entriesread
,
783 _Out_ LPDWORD totalentries
,
784 _Inout_opt_ PDWORD_PTR resume_handle
)
786 UNICODE_STRING ServerName
;
787 PSAM_RID_ENUMERATION CurrentGroup
;
788 PENUM_CONTEXT EnumContext
= NULL
;
790 SAM_HANDLE GroupHandle
= NULL
;
791 PGROUP_GENERAL_INFORMATION GroupInfo
= NULL
;
793 NET_API_STATUS ApiStatus
= NERR_Success
;
794 NTSTATUS Status
= STATUS_SUCCESS
;
796 TRACE("NetGroupEnum(%s, %d, %p, %d, %p, %p, %p)\n", debugstr_w(servername
),
797 level
, bufptr
, prefmaxlen
, entriesread
, totalentries
, resume_handle
);
803 if (servername
!= NULL
)
804 RtlInitUnicodeString(&ServerName
, servername
);
806 if (resume_handle
!= NULL
&& *resume_handle
!= 0)
808 EnumContext
= (PENUM_CONTEXT
)*resume_handle
;
812 ApiStatus
= NetApiBufferAllocate(sizeof(ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
813 if (ApiStatus
!= NERR_Success
)
816 EnumContext
->EnumerationContext
= 0;
817 EnumContext
->Buffer
= NULL
;
818 EnumContext
->Returned
= 0;
819 EnumContext
->Index
= 0;
821 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
822 &EnumContext
->ServerHandle
,
823 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
825 if (!NT_SUCCESS(Status
))
827 ERR("SamConnect failed (Status %08lx)\n", Status
);
828 ApiStatus
= NetpNtStatusToApiStatus(Status
);
832 Status
= OpenAccountDomain(EnumContext
->ServerHandle
,
833 (servername
!= NULL
) ? &ServerName
: NULL
,
834 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
835 &EnumContext
->AccountDomainHandle
);
836 if (!NT_SUCCESS(Status
))
838 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
839 ApiStatus
= NetpNtStatusToApiStatus(Status
);
843 Status
= OpenBuiltinDomain(EnumContext
->ServerHandle
,
844 DOMAIN_LIST_ACCOUNTS
| DOMAIN_LOOKUP
,
845 &EnumContext
->BuiltinDomainHandle
);
846 if (!NT_SUCCESS(Status
))
848 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status
);
849 ApiStatus
= NetpNtStatusToApiStatus(Status
);
853 EnumContext
->Phase
= AccountPhase
; //BuiltinPhase;
854 EnumContext
->DomainHandle
= EnumContext
->AccountDomainHandle
; //BuiltinDomainHandle;
860 TRACE("EnumContext->Index: %lu\n", EnumContext
->Index
);
861 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
863 if (EnumContext
->Index
>= EnumContext
->Returned
)
865 TRACE("Calling SamEnumerateGroupsInDomain\n");
867 Status
= SamEnumerateGroupsInDomain(EnumContext
->DomainHandle
,
868 &EnumContext
->EnumerationContext
,
869 (PVOID
*)&EnumContext
->Buffer
,
871 &EnumContext
->Returned
);
873 TRACE("SamEnumerateGroupsInDomain returned (Status %08lx)\n", Status
);
874 if (!NT_SUCCESS(Status
))
876 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status
);
877 ApiStatus
= NetpNtStatusToApiStatus(Status
);
881 if (Status
== STATUS_MORE_ENTRIES
)
883 ApiStatus
= NERR_BufTooSmall
;
888 TRACE("EnumContext: %lu\n", EnumContext
);
889 TRACE("EnumContext->Returned: %lu\n", EnumContext
->Returned
);
890 TRACE("EnumContext->Buffer: %p\n", EnumContext
->Buffer
);
892 /* Get a pointer to the current group */
893 CurrentGroup
= &EnumContext
->Buffer
[EnumContext
->Index
];
895 TRACE("RID: %lu\n", CurrentGroup
->RelativeId
);
897 Status
= SamOpenGroup(EnumContext
->DomainHandle
,
898 GROUP_READ_INFORMATION
,
899 CurrentGroup
->RelativeId
,
901 if (!NT_SUCCESS(Status
))
903 ERR("SamOpenGroup failed (Status %08lx)\n", Status
);
904 ApiStatus
= NetpNtStatusToApiStatus(Status
);
908 Status
= SamQueryInformationGroup(GroupHandle
,
909 GroupGeneralInformation
,
910 (PVOID
*)&GroupInfo
);
911 if (!NT_SUCCESS(Status
))
913 ERR("SamQueryInformationGroup failed (Status %08lx)\n", Status
);
914 ApiStatus
= NetpNtStatusToApiStatus(Status
);
918 SamCloseHandle(GroupHandle
);
921 TRACE("Name: %S\n", GroupInfo
->Name
.Buffer
);
922 TRACE("Comment: %S\n", GroupInfo
->AdminComment
.Buffer
);
924 ApiStatus
= BuildGroupInfoBuffer(GroupInfo
,
926 CurrentGroup
->RelativeId
,
928 if (ApiStatus
!= NERR_Success
)
931 if (GroupInfo
!= NULL
)
933 FreeGroupInfo(GroupInfo
);
937 EnumContext
->Index
++;
941 if (EnumContext
->Index
== EnumContext
->Returned
)
943 switch (EnumContext
->Phase
)
946 EnumContext
->Phase
= AccountPhase
;
947 EnumContext
->DomainHandle
= EnumContext
->AccountDomainHandle
;
948 EnumContext
->EnumerationContext
= 0;
949 EnumContext
->Index
= 0;
950 EnumContext
->Returned
= 0;
952 if (EnumContext
->Buffer
!= NULL
)
954 for (i
= 0; i
< EnumContext
->Returned
; i
++)
956 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
959 SamFreeMemory(EnumContext
->Buffer
);
960 EnumContext
->Buffer
= NULL
;
966 EnumContext
->Phase
= DonePhase
;
973 if (ApiStatus
== NERR_Success
&& EnumContext
!= NULL
&& EnumContext
->Phase
!= DonePhase
)
974 ApiStatus
= ERROR_MORE_DATA
;
976 if (EnumContext
!= NULL
)
977 *totalentries
= EnumContext
->Returned
;
979 if (resume_handle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
981 if (EnumContext
!= NULL
)
983 if (EnumContext
->BuiltinDomainHandle
!= NULL
)
984 SamCloseHandle(EnumContext
->BuiltinDomainHandle
);
986 if (EnumContext
->AccountDomainHandle
!= NULL
)
987 SamCloseHandle(EnumContext
->AccountDomainHandle
);
989 if (EnumContext
->ServerHandle
!= NULL
)
990 SamCloseHandle(EnumContext
->ServerHandle
);
992 if (EnumContext
->Buffer
!= NULL
)
994 for (i
= 0; i
< EnumContext
->Returned
; i
++)
996 SamFreeMemory(EnumContext
->Buffer
[i
].Name
.Buffer
);
999 SamFreeMemory(EnumContext
->Buffer
);
1002 NetApiBufferFree(EnumContext
);
1007 if (GroupHandle
!= NULL
)
1008 SamCloseHandle(GroupHandle
);
1010 if (GroupInfo
!= NULL
)
1011 FreeGroupInfo(GroupInfo
);
1013 if (resume_handle
!= NULL
)
1014 *resume_handle
= (DWORD_PTR
)EnumContext
;
1016 *bufptr
= (LPBYTE
)Buffer
;
1018 TRACE("return %lu\n", ApiStatus
);
1027 _In_opt_ LPCWSTR servername
,
1028 _In_ LPCWSTR groupname
,
1030 _Out_ LPBYTE
*bufptr
)
1032 UNICODE_STRING ServerName
;
1033 UNICODE_STRING GroupName
;
1034 SAM_HANDLE ServerHandle
= NULL
;
1035 SAM_HANDLE DomainHandle
= NULL
;
1036 SAM_HANDLE GroupHandle
= NULL
;
1037 PGROUP_GENERAL_INFORMATION GroupInfo
= NULL
;
1038 PVOID Buffer
= NULL
;
1040 NET_API_STATUS ApiStatus
= NERR_Success
;
1041 NTSTATUS Status
= STATUS_SUCCESS
;
1043 TRACE("NetGroupGetInfo(%s, %s, %d, %p)\n",
1044 debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
);
1046 if (servername
!= NULL
)
1047 RtlInitUnicodeString(&ServerName
, servername
);
1049 RtlInitUnicodeString(&GroupName
, groupname
);
1051 /* Connect to the SAM Server */
1052 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1054 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1056 if (!NT_SUCCESS(Status
))
1058 ERR("SamConnect failed (Status %08lx)\n", Status
);
1059 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1063 /* Open the Acount Domain */
1064 Status
= OpenAccountDomain(ServerHandle
,
1065 (servername
!= NULL
) ? &ServerName
: NULL
,
1068 if (!NT_SUCCESS(Status
))
1070 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1071 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1075 /* Open the group account in the account domain */
1076 ApiStatus
= OpenGroupByName(DomainHandle
,
1078 GROUP_READ_INFORMATION
,
1081 if (ApiStatus
!= NERR_Success
)
1083 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
1084 if (ApiStatus
== ERROR_NONE_MAPPED
)
1085 ApiStatus
= NERR_GroupNotFound
;
1089 Status
= SamQueryInformationGroup(GroupHandle
,
1090 GroupGeneralInformation
,
1091 (PVOID
*)&GroupInfo
);
1092 if (!NT_SUCCESS(Status
))
1094 ERR("SamQueryInformationGroup failed (Status %08lx)\n", Status
);
1095 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1099 ApiStatus
= BuildGroupInfoBuffer(GroupInfo
,
1103 if (ApiStatus
!= NERR_Success
)
1107 if (GroupInfo
!= NULL
)
1108 FreeGroupInfo(GroupInfo
);
1110 if (GroupHandle
!= NULL
)
1111 SamCloseHandle(GroupHandle
);
1113 if (DomainHandle
!= NULL
)
1114 SamCloseHandle(DomainHandle
);
1116 if (ServerHandle
!= NULL
)
1117 SamCloseHandle(ServerHandle
);
1119 *bufptr
= (LPBYTE
)Buffer
;
1128 _In_opt_ LPCWSTR servername
,
1129 _In_ LPCWSTR groupname
,
1131 _Out_ LPBYTE
*bufptr
,
1132 _In_ DWORD prefmaxlen
,
1133 _Out_ LPDWORD entriesread
,
1134 _Out_ LPDWORD totalentries
,
1135 _Inout_ PDWORD_PTR resume_handle
)
1137 UNICODE_STRING ServerName
;
1138 UNICODE_STRING GroupName
;
1139 PGROUP_USERS_INFO_0 UserInfo0
;
1140 PGROUP_USERS_INFO_1 UserInfo1
;
1141 PUSER_ENUM_CONTEXT EnumContext
= NULL
;
1142 PVOID Buffer
= NULL
;
1145 NET_API_STATUS ApiStatus
= NERR_Success
;
1146 NTSTATUS Status
= STATUS_SUCCESS
;
1148 TRACE("NetGroupGetUsers(%s, %s, %d, %p, %d, %p, %p, %p)\n",
1149 debugstr_w(servername
), debugstr_w(groupname
), level
, bufptr
,
1150 prefmaxlen
, entriesread
, totalentries
, resume_handle
);
1156 if (servername
!= NULL
)
1157 RtlInitUnicodeString(&ServerName
, servername
);
1159 RtlInitUnicodeString(&GroupName
, groupname
);
1161 if (resume_handle
!= NULL
&& *resume_handle
!= 0)
1163 EnumContext
= (PUSER_ENUM_CONTEXT
)*resume_handle
;
1167 ApiStatus
= NetApiBufferAllocate(sizeof(ENUM_CONTEXT
), (PVOID
*)&EnumContext
);
1168 if (ApiStatus
!= NERR_Success
)
1171 EnumContext
->MemberCount
= 0;
1172 EnumContext
->MemberIds
= NULL
;
1173 EnumContext
->Attributes
= NULL
;
1174 EnumContext
->Names
= NULL
;
1175 EnumContext
->Start
= 0;
1176 EnumContext
->Count
= 0;
1178 /* Connect to the SAM Server */
1179 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1180 &EnumContext
->ServerHandle
,
1181 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1183 if (!NT_SUCCESS(Status
))
1185 ERR("SamConnect failed (Status %08lx)\n", Status
);
1186 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1190 /* Open the Acount Domain */
1191 Status
= OpenAccountDomain(EnumContext
->ServerHandle
,
1192 (servername
!= NULL
) ? &ServerName
: NULL
,
1194 &EnumContext
->DomainHandle
);
1195 if (!NT_SUCCESS(Status
))
1197 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1198 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1202 /* Open the group account */
1203 ApiStatus
= OpenGroupByName(EnumContext
->DomainHandle
,
1206 &EnumContext
->GroupHandle
,
1208 if (ApiStatus
!= NERR_Success
)
1210 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
1211 if (ApiStatus
== ERROR_NONE_MAPPED
)
1212 ApiStatus
= NERR_GroupNotFound
;
1216 /* Get the group members */
1217 Status
= SamGetMembersInGroup(EnumContext
->GroupHandle
,
1218 &EnumContext
->MemberIds
,
1219 &EnumContext
->Attributes
,
1220 &EnumContext
->MemberCount
);
1221 if (!NT_SUCCESS(Status
))
1223 ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status
);
1224 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1228 if (EnumContext
->MemberCount
> 0)
1230 /* Get all member names */
1231 Status
= SamLookupIdsInDomain(EnumContext
->DomainHandle
,
1232 EnumContext
->MemberCount
,
1233 EnumContext
->MemberIds
,
1234 &EnumContext
->Names
,
1236 if (!NT_SUCCESS(Status
))
1238 ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status
);
1239 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1245 /* Calculate the required buffer size */
1247 if (prefmaxlen
== -1)
1249 Size
= EnumContext
->MemberCount
*
1250 ((level
== 0) ? sizeof(GROUP_USERS_INFO_0
) : sizeof(GROUP_USERS_INFO_1
));
1251 for (i
= EnumContext
->Start
; i
< EnumContext
->MemberCount
; i
++)
1252 Size
+= EnumContext
->Names
[i
].Length
+ sizeof(WCHAR
);
1254 EnumContext
->Count
= EnumContext
->MemberCount
;
1258 for (i
= EnumContext
->Start
; i
< EnumContext
->MemberCount
; i
++)
1260 Size
+= (level
== 0) ? sizeof(GROUP_USERS_INFO_0
) : sizeof(GROUP_USERS_INFO_1
);
1261 Size
+= EnumContext
->Names
[i
].Length
+ sizeof(WCHAR
);
1263 EnumContext
->Count
++;
1265 if (Size
>= prefmaxlen
)
1270 TRACE("Buffer size: %lu\n", Size
);
1272 /* Allocate and clear the buffer */
1273 ApiStatus
= NetApiBufferAllocate(Size
, &Buffer
);
1274 if (ApiStatus
!= NERR_Success
)
1277 ZeroMemory(Buffer
, Size
);
1279 /* Fill the buffer */
1281 Ptr
= (PWCHAR
)((LONG_PTR
)Buffer
+ EnumContext
->Count
* sizeof(GROUP_USERS_INFO_0
));
1283 Ptr
= (PWCHAR
)((LONG_PTR
)Buffer
+ EnumContext
->Count
* sizeof(GROUP_USERS_INFO_1
));
1285 for (i
= 0; i
< EnumContext
->Count
; i
++)
1287 idx
= EnumContext
->Start
+ i
;
1291 UserInfo0
= (PGROUP_USERS_INFO_0
)Buffer
;
1293 UserInfo0
[i
].grui0_name
= Ptr
;
1295 memcpy(UserInfo0
[i
].grui0_name
,
1296 EnumContext
->Names
[idx
].Buffer
,
1297 EnumContext
->Names
[idx
].Length
);
1298 UserInfo0
[i
].grui0_name
[EnumContext
->Names
[idx
].Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1300 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ EnumContext
->Names
[idx
].Length
+ sizeof(WCHAR
));
1304 UserInfo1
= (PGROUP_USERS_INFO_1
)Buffer
;
1306 UserInfo1
[i
].grui1_name
= Ptr
;
1308 memcpy(UserInfo1
[i
].grui1_name
,
1309 EnumContext
->Names
[idx
].Buffer
,
1310 EnumContext
->Names
[idx
].Length
);
1311 UserInfo1
[i
].grui1_name
[EnumContext
->Names
[idx
].Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1313 UserInfo1
[i
].grui1_attributes
= EnumContext
->Attributes
[idx
];
1315 Ptr
= (PWSTR
)((ULONG_PTR
)Ptr
+ EnumContext
->Names
[idx
].Length
+ sizeof(WCHAR
));
1319 /* Set the new start index */
1320 EnumContext
->Start
+= EnumContext
->Count
;
1322 /* Only return ERROR_MORE_DATA if we are not done yet */
1323 if (EnumContext
->MemberCount
> EnumContext
->Start
)
1324 ApiStatus
= ERROR_MORE_DATA
;
1326 ApiStatus
= NERR_Success
;
1329 if (EnumContext
!= NULL
)
1331 *entriesread
= EnumContext
->Count
;
1332 *totalentries
= EnumContext
->MemberCount
;
1335 if (resume_handle
== NULL
|| ApiStatus
!= ERROR_MORE_DATA
)
1337 if (EnumContext
!= NULL
)
1339 if (EnumContext
->Names
!= NULL
)
1341 for (i
= 0; i
< EnumContext
->MemberCount
; i
++)
1342 SamFreeMemory(EnumContext
->Names
[i
].Buffer
);
1344 SamFreeMemory(EnumContext
->Names
);
1347 if (EnumContext
->Attributes
!= NULL
)
1348 SamFreeMemory(EnumContext
->Attributes
);
1350 if (EnumContext
->MemberIds
!= NULL
)
1351 SamFreeMemory(EnumContext
->MemberIds
);
1354 if (EnumContext
->GroupHandle
!= NULL
)
1355 SamCloseHandle(EnumContext
->GroupHandle
);
1357 if (EnumContext
->DomainHandle
!= NULL
)
1358 SamCloseHandle(EnumContext
->DomainHandle
);
1360 if (EnumContext
->ServerHandle
!= NULL
)
1361 SamCloseHandle(EnumContext
->ServerHandle
);
1363 NetApiBufferFree(EnumContext
);
1368 *bufptr
= (LPBYTE
)Buffer
;
1370 if (resume_handle
!= NULL
)
1371 *resume_handle
= (DWORD_PTR
)EnumContext
;
1380 _In_opt_ LPCWSTR servername
,
1381 _In_ LPCWSTR groupname
,
1384 _Out_opt_ LPDWORD parm_err
)
1386 UNICODE_STRING ServerName
;
1387 UNICODE_STRING GroupName
;
1388 SAM_HANDLE ServerHandle
= NULL
;
1389 SAM_HANDLE DomainHandle
= NULL
;
1390 SAM_HANDLE GroupHandle
= NULL
;
1391 GROUP_NAME_INFORMATION GroupNameInfo
;
1392 GROUP_ADM_COMMENT_INFORMATION AdminCommentInfo
;
1393 GROUP_ATTRIBUTE_INFORMATION AttributeInfo
;
1394 NET_API_STATUS ApiStatus
= NERR_Success
;
1395 NTSTATUS Status
= STATUS_SUCCESS
;
1397 TRACE("NetGroupSetInfo(%s, %s, %d, %p, %p)\n",
1398 debugstr_w(servername
), debugstr_w(groupname
), level
, buf
, parm_err
);
1400 if (parm_err
!= NULL
)
1401 *parm_err
= PARM_ERROR_NONE
;
1403 if (servername
!= NULL
)
1404 RtlInitUnicodeString(&ServerName
, servername
);
1406 RtlInitUnicodeString(&GroupName
, groupname
);
1408 /* Connect to the SAM Server */
1409 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1411 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1413 if (!NT_SUCCESS(Status
))
1415 ERR("SamConnect failed (Status %08lx)\n", Status
);
1416 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1420 /* Open the Acount Domain */
1421 Status
= OpenAccountDomain(ServerHandle
,
1422 (servername
!= NULL
) ? &ServerName
: NULL
,
1425 if (!NT_SUCCESS(Status
))
1427 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1428 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1432 /* Open the group */
1433 ApiStatus
= OpenGroupByName(DomainHandle
,
1435 GROUP_WRITE_ACCOUNT
,
1438 if (ApiStatus
!= NERR_Success
)
1440 WARN("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
1441 if (ApiStatus
== ERROR_NONE_MAPPED
)
1442 ApiStatus
= NERR_GroupNotFound
;
1449 /* Set the group name */
1450 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1451 ((PGROUP_INFO_0
)buf
)->grpi0_name
);
1453 Status
= SamSetInformationGroup(GroupHandle
,
1454 GroupNameInformation
,
1456 if (!NT_SUCCESS(Status
))
1458 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1459 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1465 /* Set the group name */
1466 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1467 ((PGROUP_INFO_1
)buf
)->grpi1_name
);
1469 Status
= SamSetInformationGroup(GroupHandle
,
1470 GroupNameInformation
,
1472 if (!NT_SUCCESS(Status
))
1474 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1475 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1479 /* Set the admin comment */
1480 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1481 ((PGROUP_INFO_1
)buf
)->grpi1_comment
);
1483 Status
= SamSetInformationGroup(GroupHandle
,
1484 GroupAdminCommentInformation
,
1486 if (!NT_SUCCESS(Status
))
1488 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1489 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1495 /* Set the group name */
1496 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1497 ((PGROUP_INFO_2
)buf
)->grpi2_name
);
1499 Status
= SamSetInformationGroup(GroupHandle
,
1500 GroupNameInformation
,
1502 if (!NT_SUCCESS(Status
))
1504 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1505 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1509 /* Set the admin comment */
1510 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1511 ((PGROUP_INFO_2
)buf
)->grpi2_comment
);
1513 Status
= SamSetInformationGroup(GroupHandle
,
1514 GroupAdminCommentInformation
,
1516 if (!NT_SUCCESS(Status
))
1518 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1519 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1523 /* Set the attributes */
1524 AttributeInfo
.Attributes
= ((PGROUP_INFO_2
)buf
)->grpi2_attributes
;
1526 Status
= SamSetInformationGroup(GroupHandle
,
1527 GroupAttributeInformation
,
1529 if (!NT_SUCCESS(Status
))
1531 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1532 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1538 /* Set the group name */
1539 RtlInitUnicodeString(&GroupNameInfo
.Name
,
1540 ((PGROUP_INFO_3
)buf
)->grpi3_name
);
1542 Status
= SamSetInformationGroup(GroupHandle
,
1543 GroupNameInformation
,
1545 if (!NT_SUCCESS(Status
))
1547 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1548 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1552 /* Set the admin comment */
1553 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1554 ((PGROUP_INFO_3
)buf
)->grpi3_comment
);
1556 Status
= SamSetInformationGroup(GroupHandle
,
1557 GroupAdminCommentInformation
,
1559 if (!NT_SUCCESS(Status
))
1561 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1562 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1566 /* Set the attributes */
1567 AttributeInfo
.Attributes
= ((PGROUP_INFO_3
)buf
)->grpi3_attributes
;
1569 Status
= SamSetInformationGroup(GroupHandle
,
1570 GroupAttributeInformation
,
1572 if (!NT_SUCCESS(Status
))
1574 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1575 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1581 /* Set the admin comment */
1582 RtlInitUnicodeString(&AdminCommentInfo
.AdminComment
,
1583 ((PGROUP_INFO_1002
)buf
)->grpi1002_comment
);
1585 Status
= SamSetInformationGroup(GroupHandle
,
1586 GroupAdminCommentInformation
,
1588 if (!NT_SUCCESS(Status
))
1590 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1591 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1597 /* Set the attributes */
1598 AttributeInfo
.Attributes
= ((PGROUP_INFO_1005
)buf
)->grpi1005_attributes
;
1600 Status
= SamSetInformationGroup(GroupHandle
,
1601 GroupAttributeInformation
,
1603 if (!NT_SUCCESS(Status
))
1605 ERR("SamSetInformationGroup failed (ApiStatus %lu)\n", ApiStatus
);
1606 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1612 ApiStatus
= ERROR_INVALID_LEVEL
;
1617 if (GroupHandle
!= NULL
)
1618 SamCloseHandle(GroupHandle
);
1620 if (DomainHandle
!= NULL
)
1621 SamCloseHandle(DomainHandle
);
1623 if (ServerHandle
!= NULL
)
1624 SamCloseHandle(ServerHandle
);
1633 _In_opt_ LPCWSTR servername
,
1634 _In_ LPCWSTR groupname
,
1637 _In_ DWORD totalentries
)
1639 UNICODE_STRING ServerName
;
1640 UNICODE_STRING GroupName
;
1641 SAM_HANDLE ServerHandle
= NULL
;
1642 SAM_HANDLE DomainHandle
= NULL
;
1643 SAM_HANDLE GroupHandle
= NULL
;
1644 ULONG OldMemberCount
= 0;
1645 PULONG OldMemberIDs
= NULL
;
1646 PULONG OldAttributes
= NULL
;
1647 PUNICODE_STRING NamesArray
= NULL
;
1648 PGROUP_USERS_INFO_0 UserInfo0
;
1649 PGROUP_USERS_INFO_1 UserInfo1
;
1650 PULONG NewMemberIDs
= NULL
;
1651 PSID_NAME_USE NewMemberUse
= NULL
;
1654 NET_API_STATUS ApiStatus
= NERR_Success
;
1655 NTSTATUS Status
= STATUS_SUCCESS
;
1657 TRACE("NetGroupSetUsers(%s, %s, %d, %p, %d) stub!\n",
1658 debugstr_w(servername
), debugstr_w(groupname
), level
, buf
, totalentries
);
1660 if (servername
!= NULL
)
1661 RtlInitUnicodeString(&ServerName
, servername
);
1663 RtlInitUnicodeString(&GroupName
, groupname
);
1665 /* Connect to the SAM Server */
1666 Status
= SamConnect((servername
!= NULL
) ? &ServerName
: NULL
,
1668 SAM_SERVER_CONNECT
| SAM_SERVER_LOOKUP_DOMAIN
,
1670 if (!NT_SUCCESS(Status
))
1672 ERR("SamConnect failed (Status %08lx)\n", Status
);
1673 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1677 /* Open the Acount Domain */
1678 Status
= OpenAccountDomain(ServerHandle
,
1679 (servername
!= NULL
) ? &ServerName
: NULL
,
1682 if (!NT_SUCCESS(Status
))
1684 ERR("OpenAccountDomain failed (Status %08lx)\n", Status
);
1685 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1689 /* Open the group account in the account domain */
1690 ApiStatus
= OpenGroupByName(DomainHandle
,
1692 GROUP_LIST_MEMBERS
| GROUP_ADD_MEMBER
| GROUP_REMOVE_MEMBER
,
1695 if (ApiStatus
!= NERR_Success
)
1697 ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus
);
1698 if (ApiStatus
== ERROR_NONE_MAPPED
)
1699 ApiStatus
= NERR_GroupNotFound
;
1703 /* Get the group members */
1704 Status
= SamGetMembersInGroup(GroupHandle
,
1708 if (!NT_SUCCESS(Status
))
1710 ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status
);
1711 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1715 NamesArray
= RtlAllocateHeap(RtlGetProcessHeap(),
1717 totalentries
* sizeof(UNICODE_STRING
));
1718 if (NamesArray
== NULL
)
1720 ERR("RtlAllocateHeap failed\n");
1721 ApiStatus
= ERROR_OUTOFMEMORY
;
1725 UserInfo0
= (PGROUP_USERS_INFO_0
)buf
;
1726 UserInfo1
= (PGROUP_USERS_INFO_1
)buf
;
1727 for (i
= 0; i
< totalentries
; i
++)
1730 RtlInitUnicodeString(&NamesArray
[i
], UserInfo0
[i
].grui0_name
);
1732 RtlInitUnicodeString(&NamesArray
[i
], UserInfo1
[i
].grui1_name
);
1735 Status
= SamLookupNamesInDomain(DomainHandle
,
1740 if (!NT_SUCCESS(Status
))
1742 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status
);
1744 if (Status
== STATUS_NONE_MAPPED
)
1746 ApiStatus
= NERR_UserNotFound
;
1750 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1754 /* Add members and set attributes for existing members */
1755 for (i
= 0; i
< totalentries
; i
++)
1758 for (j
= 0; j
< OldMemberCount
; j
++)
1760 if (NewMemberIDs
[i
] == OldMemberIDs
[j
])
1764 Status
= SamSetMemberAttributesOfGroup(GroupHandle
,
1766 UserInfo1
[i
].grui1_attributes
);
1767 if (!NT_SUCCESS(Status
))
1769 ERR("SamSetMemberAttributesOfGroup failed (Status %lu)\n", Status
);
1770 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1782 TRACE("Add member %lx\n", NewMemberIDs
[i
]);
1784 if (NewMemberUse
[i
] != SidTypeUser
)
1786 ERR("New member is not a user!\n");
1787 ApiStatus
= NERR_GroupNotFound
;
1791 Status
= SamAddMemberToGroup(GroupHandle
,
1793 (level
== 0) ? 0 : UserInfo1
[i
].grui1_attributes
);
1794 if (!NT_SUCCESS(Status
))
1796 ERR("SamAddMemberToGroup failed (Status %lu)\n", Status
);
1797 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1803 /* Remove members */
1804 for (i
= 0; i
< OldMemberCount
; i
++)
1807 for (j
= 0; j
< totalentries
; j
++)
1809 if (OldMemberIDs
[i
] == NewMemberIDs
[j
])
1818 TRACE("Delete member %lx\n", OldMemberIDs
[i
]);
1820 Status
= SamRemoveMemberFromGroup(GroupHandle
,
1822 if (!NT_SUCCESS(Status
))
1824 ERR("SamRemoveMemberFromGroup failed (Status %lu)\n", Status
);
1825 ApiStatus
= NetpNtStatusToApiStatus(Status
);
1832 if (NewMemberUse
!= NULL
)
1833 SamFreeMemory(NewMemberUse
);
1835 if (NewMemberIDs
!= NULL
)
1836 SamFreeMemory(NewMemberIDs
);
1838 if (NamesArray
!= NULL
)
1839 RtlFreeHeap(RtlGetProcessHeap(), 0, NamesArray
);
1841 if (OldMemberIDs
!= NULL
)
1842 SamFreeMemory(OldMemberIDs
);
1844 if (GroupHandle
!= NULL
)
1845 SamCloseHandle(GroupHandle
);
1847 if (DomainHandle
!= NULL
)
1848 SamCloseHandle(DomainHandle
);
1850 if (ServerHandle
!= NULL
)
1851 SamCloseHandle(ServerHandle
);