https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4d9425d1234eea68c6411…
commit 4d9425d1234eea68c6411d1ed3eeae1d2297fe38
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Wed Sep 12 17:11:52 2018 +0200
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Wed Sep 12 17:11:52 2018 +0200
[NETAPI32] Implement NetGroupSetUsers
---
dll/win32/netapi32/group.c | 18 ----
dll/win32/netapi32/group_new.c | 227 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 227 insertions(+), 18 deletions(-)
diff --git a/dll/win32/netapi32/group.c b/dll/win32/netapi32/group.c
index b252111b3c..e6300f2bb2 100644
--- a/dll/win32/netapi32/group.c
+++ b/dll/win32/netapi32/group.c
@@ -22,22 +22,4 @@
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-
-/************************************************************
- * NetGroupSetUsers (NETAPI32.@)
- *
- */
-NET_API_STATUS
-WINAPI
-NetGroupSetUsers(IN LPCWSTR servername,
- IN LPCWSTR groupname,
- IN DWORD level,
- IN LPBYTE buf,
- IN DWORD totalentries)
-{
- FIXME("(%s, %s, %d, %p, %d) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, buf, totalentries);
- return ERROR_ACCESS_DENIED;
-}
-
/* EOF */
diff --git a/dll/win32/netapi32/group_new.c b/dll/win32/netapi32/group_new.c
index dbf5a3bdf6..d93589e294 100644
--- a/dll/win32/netapi32/group_new.c
+++ b/dll/win32/netapi32/group_new.c
@@ -1626,4 +1626,231 @@ done:
return ApiStatus;
}
+
+NET_API_STATUS
+WINAPI
+NetGroupSetUsers(
+ _In_opt_ LPCWSTR servername,
+ _In_ LPCWSTR groupname,
+ _In_ DWORD level,
+ _In_ LPBYTE buf,
+ _In_ DWORD totalentries)
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING GroupName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE GroupHandle = NULL;
+ ULONG OldMemberCount = 0;
+ PULONG OldMemberIDs = NULL;
+ PULONG OldAttributes = NULL;
+ PUNICODE_STRING NamesArray = NULL;
+ PGROUP_USERS_INFO_0 UserInfo0;
+ PGROUP_USERS_INFO_1 UserInfo1;
+ PULONG NewMemberIDs = NULL;
+ PSID_NAME_USE NewMemberUse = NULL;
+ ULONG i, j;
+ BOOL Found;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("NetGroupSetUsers(%s, %s, %d, %p, %d) stub!\n",
+ debugstr_w(servername), debugstr_w(groupname), level, buf, totalentries);
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&GroupName, groupname);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the group account in the account domain */
+ ApiStatus = OpenGroupByName(DomainHandle,
+ &GroupName,
+ GROUP_LIST_MEMBERS | GROUP_ADD_MEMBER |
GROUP_REMOVE_MEMBER,
+ &GroupHandle,
+ NULL);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenGroupByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+
+ /* Get the group members */
+ Status = SamGetMembersInGroup(GroupHandle,
+ &OldMemberIDs,
+ &OldAttributes,
+ &OldMemberCount);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ NamesArray = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ totalentries * sizeof(UNICODE_STRING));
+ if (NamesArray == NULL)
+ {
+ ERR("RtlAllocateHeap failed\n");
+ ApiStatus = ERROR_OUTOFMEMORY;
+ goto done;
+ }
+
+ UserInfo0 = (PGROUP_USERS_INFO_0)buf;
+ UserInfo1 = (PGROUP_USERS_INFO_1)buf;
+ for (i = 0; i < totalentries; i++)
+ {
+ if (level == 0)
+ RtlInitUnicodeString(&NamesArray[i], UserInfo0[i].grui0_name);
+ else
+ RtlInitUnicodeString(&NamesArray[i], UserInfo1[i].grui1_name);
+ }
+
+ Status = SamLookupNamesInDomain(DomainHandle,
+ totalentries,
+ NamesArray,
+ &NewMemberIDs,
+ &NewMemberUse);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
+
+ if (Status == STATUS_NONE_MAPPED)
+ {
+ ApiStatus = NERR_UserNotFound;
+ goto done;
+ }
+
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Add members and set attributes for existing members */
+ for (i = 0; i < totalentries; i++)
+ {
+ Found = FALSE;
+ for (j = 0; j < OldMemberCount; j++)
+ {
+ if (NewMemberIDs[i] == OldMemberIDs[j])
+ {
+ if (level == 1)
+ {
+ Status = SamSetMemberAttributesOfGroup(GroupHandle,
+ NewMemberIDs[i],
+
UserInfo1[i].grui1_attributes);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamSetMemberAttributesOfGroup failed (Status
%lu)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found == FALSE)
+ {
+ TRACE("Add member %lx\n", NewMemberIDs[i]);
+
+ if (NewMemberUse[i] != SidTypeUser)
+ {
+ ERR("New member is not a user!\n");
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+
+ Status = SamAddMemberToGroup(GroupHandle,
+ NewMemberIDs[i],
+ (level == 0) ? 0 :
UserInfo1[i].grui1_attributes);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamAddMemberToGroup failed (Status %lu)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+ }
+
+ /* Remove members */
+ for (i = 0; i < OldMemberCount; i++)
+ {
+ Found = FALSE;
+ for (j = 0; j < totalentries; j++)
+ {
+ if (OldMemberIDs[i] == NewMemberIDs[j])
+ {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (Found == FALSE)
+ {
+ TRACE("Delete member %lx\n", OldMemberIDs[i]);
+
+ Status = SamRemoveMemberFromGroup(GroupHandle,
+ OldMemberIDs[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamRemoveMemberFromGroup failed (Status %lu)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (NewMemberUse != NULL)
+ SamFreeMemory(NewMemberUse);
+
+ if (NewMemberIDs != NULL)
+ SamFreeMemory(NewMemberIDs);
+
+ if (NamesArray != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, NamesArray);
+
+ if (OldMemberIDs != NULL)
+ SamFreeMemory(OldMemberIDs);
+
+ if (GroupHandle != NULL)
+ SamCloseHandle(GroupHandle);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ return ApiStatus;
+}
+
/* EOF */