https://git.reactos.org/?p=reactos.git;a=commitdiff;h=74620c94d33e51c2e0249…
commit 74620c94d33e51c2e02496ed70143a373fc82f8f
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Mon Sep 10 22:04:53 2018 +0200
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Mon Sep 10 22:05:49 2018 +0200
[NETAPI32] Implement NetGroupGetUsers
---
dll/win32/netapi32/group.c | 22 ----
dll/win32/netapi32/group_new.c | 267 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 267 insertions(+), 22 deletions(-)
diff --git a/dll/win32/netapi32/group.c b/dll/win32/netapi32/group.c
index efb46e86c1..b252111b3c 100644
--- a/dll/win32/netapi32/group.c
+++ b/dll/win32/netapi32/group.c
@@ -23,28 +23,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
-/************************************************************
- * NetGroupGetUsers (NETAPI32.@)
- *
- */
-NET_API_STATUS
-WINAPI
-NetGroupGetUsers(IN LPCWSTR servername,
- IN LPCWSTR groupname,
- IN DWORD level,
- OUT LPBYTE *bufptr,
- IN DWORD prefmaxlen,
- OUT LPDWORD entriesread,
- OUT LPDWORD totalentries,
- IN OUT PDWORD_PTR resume_handle)
-{
- FIXME("(%s, %s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, bufptr, prefmaxlen, entriesread,
- totalentries, resume_handle);
- return ERROR_ACCESS_DENIED;
-}
-
-
/************************************************************
* NetGroupSetUsers (NETAPI32.@)
*
diff --git a/dll/win32/netapi32/group_new.c b/dll/win32/netapi32/group_new.c
index 743e685c94..dbf5a3bdf6 100644
--- a/dll/win32/netapi32/group_new.c
+++ b/dll/win32/netapi32/group_new.c
@@ -32,6 +32,21 @@ typedef struct _ENUM_CONTEXT
ENUM_PHASE Phase;
} ENUM_CONTEXT, *PENUM_CONTEXT;
+typedef struct _USER_ENUM_CONTEXT
+{
+ SAM_HANDLE ServerHandle;
+ SAM_HANDLE DomainHandle;
+ SAM_HANDLE GroupHandle;
+
+ ULONG MemberCount;
+ PULONG MemberIds;
+ PULONG Attributes;
+ PUNICODE_STRING Names;
+
+ ULONG Start;
+ ULONG Count;
+} USER_ENUM_CONTEXT, *PUSER_ENUM_CONTEXT;
+
/* FUNCTIONS *****************************************************************/
@@ -1107,6 +1122,258 @@ done:
}
+NET_API_STATUS
+WINAPI
+NetGroupGetUsers(
+ _In_opt_ LPCWSTR servername,
+ _In_ LPCWSTR groupname,
+ _In_ DWORD level,
+ _Out_ LPBYTE *bufptr,
+ _In_ DWORD prefmaxlen,
+ _Out_ LPDWORD entriesread,
+ _Out_ LPDWORD totalentries,
+ _Inout_ PDWORD_PTR resume_handle)
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING GroupName;
+ PGROUP_USERS_INFO_0 UserInfo0;
+ PGROUP_USERS_INFO_1 UserInfo1;
+ PUSER_ENUM_CONTEXT EnumContext = NULL;
+ PVOID Buffer = NULL;
+ ULONG i, idx, Size;
+ PWSTR Ptr;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("NetGroupGetUsers(%s, %s, %d, %p, %d, %p, %p, %p)\n",
+ debugstr_w(servername), debugstr_w(groupname), level, bufptr,
+ prefmaxlen, entriesread, totalentries, resume_handle);
+
+ *entriesread = 0;
+ *totalentries = 0;
+ *bufptr = NULL;
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&GroupName, groupname);
+
+ if (resume_handle != NULL && *resume_handle != 0)
+ {
+ EnumContext = (PUSER_ENUM_CONTEXT)*resume_handle;
+ }
+ else
+ {
+ ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT),
(PVOID*)&EnumContext);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ EnumContext->MemberCount = 0;
+ EnumContext->MemberIds = NULL;
+ EnumContext->Attributes = NULL;
+ EnumContext->Names = NULL;
+ EnumContext->Start = 0;
+ EnumContext->Count = 0;
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &EnumContext->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(EnumContext->ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &EnumContext->DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the group account */
+ ApiStatus = OpenGroupByName(EnumContext->DomainHandle,
+ &GroupName,
+ GROUP_LIST_MEMBERS,
+ &EnumContext->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(EnumContext->GroupHandle,
+ &EnumContext->MemberIds,
+ &EnumContext->Attributes,
+ &EnumContext->MemberCount);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetMembersInGroup failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ if (EnumContext->MemberCount > 0)
+ {
+ /* Get all member names */
+ Status = SamLookupIdsInDomain(EnumContext->DomainHandle,
+ EnumContext->MemberCount,
+ EnumContext->MemberIds,
+ &EnumContext->Names,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+ }
+
+ /* Calculate the required buffer size */
+ Size = 0;
+ if (prefmaxlen == -1)
+ {
+ Size = EnumContext->MemberCount *
+ ((level == 0) ? sizeof(GROUP_USERS_INFO_0) : sizeof(GROUP_USERS_INFO_1));
+ for (i = EnumContext->Start; i < EnumContext->MemberCount; i++)
+ Size += EnumContext->Names[i].Length + sizeof(WCHAR);
+
+ EnumContext->Count = EnumContext->MemberCount;
+ }
+ else
+ {
+ for (i = EnumContext->Start; i < EnumContext->MemberCount; i++)
+ {
+ Size += (level == 0) ? sizeof(GROUP_USERS_INFO_0) :
sizeof(GROUP_USERS_INFO_1);
+ Size += EnumContext->Names[i].Length + sizeof(WCHAR);
+
+ EnumContext->Count++;
+
+ if (Size >= prefmaxlen)
+ break;
+ }
+ }
+
+ TRACE("Buffer size: %lu\n", Size);
+
+ /* Allocate and clear the buffer */
+ ApiStatus = NetApiBufferAllocate(Size, &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ ZeroMemory(Buffer, Size);
+
+ /* Fill the buffer */
+ if (level == 0)
+ Ptr = (PWCHAR)((LONG_PTR)Buffer + EnumContext->Count *
sizeof(GROUP_USERS_INFO_0));
+ else
+ Ptr = (PWCHAR)((LONG_PTR)Buffer + EnumContext->Count *
sizeof(GROUP_USERS_INFO_1));
+
+ for (i = 0; i < EnumContext->Count; i++)
+ {
+ idx = EnumContext->Start + i;
+
+ if (level == 0)
+ {
+ UserInfo0 = (PGROUP_USERS_INFO_0)Buffer;
+
+ UserInfo0[i].grui0_name = Ptr;
+
+ memcpy(UserInfo0[i].grui0_name,
+ EnumContext->Names[idx].Buffer,
+ EnumContext->Names[idx].Length);
+ UserInfo0[i].grui0_name[EnumContext->Names[idx].Length / sizeof(WCHAR)] =
UNICODE_NULL;
+
+ Ptr = (PWSTR)((ULONG_PTR)Ptr + EnumContext->Names[idx].Length +
sizeof(WCHAR));
+ }
+ else
+ {
+ UserInfo1 = (PGROUP_USERS_INFO_1)Buffer;
+
+ UserInfo1[i].grui1_name = Ptr;
+
+ memcpy(UserInfo1[i].grui1_name,
+ EnumContext->Names[idx].Buffer,
+ EnumContext->Names[idx].Length);
+ UserInfo1[i].grui1_name[EnumContext->Names[idx].Length / sizeof(WCHAR)] =
UNICODE_NULL;
+
+ UserInfo1[i].grui1_attributes = EnumContext->Attributes[idx];
+
+ Ptr = (PWSTR)((ULONG_PTR)Ptr + EnumContext->Names[idx].Length +
sizeof(WCHAR));
+ }
+ }
+
+ /* Set the new start index */
+ EnumContext->Start += EnumContext->Count;
+
+ /* Only return ERROR_MORE_DATA if we are not done yet */
+ if (EnumContext->MemberCount > EnumContext->Start)
+ ApiStatus = ERROR_MORE_DATA;
+ else
+ ApiStatus = NERR_Success;
+
+done:
+ if (EnumContext != NULL)
+ {
+ *entriesread = EnumContext->Count;
+ *totalentries = EnumContext->MemberCount;
+ }
+
+ if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
+ {
+ if (EnumContext != NULL)
+ {
+ if (EnumContext->Names != NULL)
+ {
+ for (i = 0; i < EnumContext->MemberCount; i++)
+ SamFreeMemory(EnumContext->Names[i].Buffer);
+
+ SamFreeMemory(EnumContext->Names);
+ }
+
+ if (EnumContext->Attributes != NULL)
+ SamFreeMemory(EnumContext->Attributes);
+
+ if (EnumContext->MemberIds != NULL)
+ SamFreeMemory(EnumContext->MemberIds);
+
+
+ if (EnumContext->GroupHandle != NULL)
+ SamCloseHandle(EnumContext->GroupHandle);
+
+ if (EnumContext->DomainHandle != NULL)
+ SamCloseHandle(EnumContext->DomainHandle);
+
+ if (EnumContext->ServerHandle != NULL)
+ SamCloseHandle(EnumContext->ServerHandle);
+
+ NetApiBufferFree(EnumContext);
+ EnumContext = NULL;
+ }
+ }
+
+ *bufptr = (LPBYTE)Buffer;
+
+ if (resume_handle != NULL)
+ *resume_handle = (DWORD_PTR)EnumContext;
+
+ return ApiStatus;
+}
+
+
NET_API_STATUS
WINAPI
NetGroupSetInfo(