mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NETAPI] Implement NetGroupEnum
This commit is contained in:
parent
0e69bc3bce
commit
033146ca23
3 changed files with 458 additions and 20 deletions
|
@ -21,6 +21,7 @@ list(APPEND SOURCE
|
|||
display.c
|
||||
dssetup.c
|
||||
group.c
|
||||
group_new.c
|
||||
local_group.c
|
||||
misc.c
|
||||
nbcmdqueue.c
|
||||
|
|
|
@ -86,26 +86,6 @@ NetGroupDelUser(IN LPCWSTR servername,
|
|||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* NetGroupEnum (NETAPI32.@)
|
||||
*
|
||||
*/
|
||||
NET_API_STATUS
|
||||
WINAPI
|
||||
NetGroupEnum(IN LPCWSTR servername,
|
||||
IN DWORD level,
|
||||
OUT LPBYTE *bufptr,
|
||||
IN DWORD prefmaxlen,
|
||||
OUT LPDWORD entriesread,
|
||||
OUT LPDWORD totalentries,
|
||||
IN OUT PDWORD_PTR resume_handle)
|
||||
{
|
||||
FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername),
|
||||
level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
|
||||
return ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* NetGroupGetInfo (NETAPI32.@)
|
||||
*
|
||||
|
|
457
dll/win32/netapi32/group_new.c
Normal file
457
dll/win32/netapi32/group_new.c
Normal file
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
* PROJECT: ReactOS NetAPI DLL
|
||||
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
||||
* PURPOSE: SAM service group interface code
|
||||
* COPYRIGHT: Copyright 2018 Eric Kohl (eric.kohl@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "netapi32.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
|
||||
|
||||
typedef enum _ENUM_PHASE
|
||||
{
|
||||
BuiltinPhase,
|
||||
AccountPhase,
|
||||
DonePhase
|
||||
} ENUM_PHASE;
|
||||
|
||||
typedef struct _ENUM_CONTEXT
|
||||
{
|
||||
SAM_HANDLE ServerHandle;
|
||||
SAM_HANDLE DomainHandle;
|
||||
SAM_HANDLE BuiltinDomainHandle;
|
||||
SAM_HANDLE AccountDomainHandle;
|
||||
|
||||
SAM_ENUMERATE_HANDLE EnumerationContext;
|
||||
PSAM_RID_ENUMERATION Buffer;
|
||||
ULONG Returned;
|
||||
ULONG Index;
|
||||
ENUM_PHASE Phase;
|
||||
} ENUM_CONTEXT, *PENUM_CONTEXT;
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static
|
||||
NET_API_STATUS
|
||||
BuildGroupInfoBuffer(
|
||||
_In_ PGROUP_GENERAL_INFORMATION GroupInfo,
|
||||
_In_ DWORD Level,
|
||||
_In_ DWORD GroupId,
|
||||
_Out_ LPVOID *Buffer)
|
||||
{
|
||||
PVOID GroupBuffer = NULL;
|
||||
PGROUP_INFO_0 GroupInfo0;
|
||||
PGROUP_INFO_1 GroupInfo1;
|
||||
PGROUP_INFO_2 GroupInfo2;
|
||||
PGROUP_INFO_3 GroupInfo3;
|
||||
PWSTR Ptr;
|
||||
ULONG Size = 0;
|
||||
NET_API_STATUS ApiStatus = NERR_Success;
|
||||
|
||||
*Buffer = NULL;
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case 0:
|
||||
Size = sizeof(GROUP_INFO_0) +
|
||||
GroupInfo->Name.Length + sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Size = sizeof(GROUP_INFO_1) +
|
||||
GroupInfo->Name.Length + sizeof(WCHAR) +
|
||||
GroupInfo->AdminComment.Length + sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Size = sizeof(GROUP_INFO_2) +
|
||||
GroupInfo->Name.Length + sizeof(WCHAR) +
|
||||
GroupInfo->AdminComment.Length + sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Size = sizeof(GROUP_INFO_3) +
|
||||
GroupInfo->Name.Length + sizeof(WCHAR) +
|
||||
GroupInfo->AdminComment.Length + sizeof(WCHAR);
|
||||
/* FIXME: Sid size */
|
||||
break;
|
||||
|
||||
default:
|
||||
ApiStatus = ERROR_INVALID_LEVEL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ApiStatus = NetApiBufferAllocate(Size, &GroupBuffer);
|
||||
if (ApiStatus != NERR_Success)
|
||||
goto done;
|
||||
|
||||
ZeroMemory(GroupBuffer, Size);
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case 0:
|
||||
GroupInfo0 = (PGROUP_INFO_0)GroupBuffer;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)GroupInfo0 + sizeof(LOCALGROUP_INFO_0));
|
||||
GroupInfo0->grpi0_name = Ptr;
|
||||
|
||||
memcpy(GroupInfo0->grpi0_name,
|
||||
GroupInfo->Name.Buffer,
|
||||
GroupInfo->Name.Length);
|
||||
GroupInfo0->grpi0_name[GroupInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
GroupInfo1 = (PGROUP_INFO_1)GroupBuffer;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)GroupInfo1 + sizeof(GROUP_INFO_1));
|
||||
GroupInfo1->grpi1_name = Ptr;
|
||||
|
||||
memcpy(GroupInfo1->grpi1_name,
|
||||
GroupInfo->Name.Buffer,
|
||||
GroupInfo->Name.Length);
|
||||
GroupInfo1->grpi1_name[GroupInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)Ptr + GroupInfo->Name.Length + sizeof(WCHAR));
|
||||
GroupInfo1->grpi1_comment = Ptr;
|
||||
|
||||
memcpy(GroupInfo1->grpi1_comment,
|
||||
GroupInfo->AdminComment.Buffer,
|
||||
GroupInfo->AdminComment.Length);
|
||||
GroupInfo1->grpi1_comment[GroupInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
GroupInfo2 = (PGROUP_INFO_2)GroupBuffer;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)GroupInfo2 + sizeof(GROUP_INFO_2));
|
||||
GroupInfo2->grpi2_name = Ptr;
|
||||
|
||||
memcpy(GroupInfo2->grpi2_name,
|
||||
GroupInfo->Name.Buffer,
|
||||
GroupInfo->Name.Length);
|
||||
GroupInfo2->grpi2_name[GroupInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)Ptr + GroupInfo->Name.Length + sizeof(WCHAR));
|
||||
GroupInfo2->grpi2_comment = Ptr;
|
||||
|
||||
memcpy(GroupInfo2->grpi2_comment,
|
||||
GroupInfo->AdminComment.Buffer,
|
||||
GroupInfo->AdminComment.Length);
|
||||
GroupInfo2->grpi2_comment[GroupInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
GroupInfo2->grpi2_group_id = GroupId;
|
||||
|
||||
GroupInfo2->grpi2_attributes= GroupInfo->Attributes;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
GroupInfo3 = (PGROUP_INFO_3)GroupBuffer;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)GroupInfo3 + sizeof(GROUP_INFO_3));
|
||||
GroupInfo3->grpi3_name = Ptr;
|
||||
|
||||
memcpy(GroupInfo3->grpi3_name,
|
||||
GroupInfo->Name.Buffer,
|
||||
GroupInfo->Name.Length);
|
||||
GroupInfo3->grpi3_name[GroupInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
Ptr = (PWSTR)((ULONG_PTR)Ptr + GroupInfo->Name.Length + sizeof(WCHAR));
|
||||
GroupInfo3->grpi3_comment = Ptr;
|
||||
|
||||
memcpy(GroupInfo3->grpi3_comment,
|
||||
GroupInfo->AdminComment.Buffer,
|
||||
GroupInfo->AdminComment.Length);
|
||||
GroupInfo3->grpi3_comment[GroupInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
GroupInfo3->grpi3_group_sid = NULL; /* FIXME */
|
||||
|
||||
GroupInfo3->grpi3_attributes= GroupInfo->Attributes;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ApiStatus == NERR_Success)
|
||||
{
|
||||
*Buffer = GroupBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GroupBuffer != NULL)
|
||||
NetApiBufferFree(GroupBuffer);
|
||||
}
|
||||
|
||||
return ApiStatus;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
VOID
|
||||
FreeGroupInfo(
|
||||
PGROUP_GENERAL_INFORMATION GroupInfo)
|
||||
{
|
||||
if (GroupInfo->Name.Buffer != NULL)
|
||||
SamFreeMemory(GroupInfo->Name.Buffer);
|
||||
|
||||
if (GroupInfo->AdminComment.Buffer != NULL)
|
||||
SamFreeMemory(GroupInfo->AdminComment.Buffer);
|
||||
|
||||
SamFreeMemory(GroupInfo);
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
NET_API_STATUS
|
||||
WINAPI
|
||||
NetGroupEnum(
|
||||
_In_opt_ LPCWSTR servername,
|
||||
_In_ DWORD level,
|
||||
_Out_ LPBYTE *bufptr,
|
||||
_In_ DWORD prefmaxlen,
|
||||
_Out_ LPDWORD entriesread,
|
||||
_Out_ LPDWORD totalentries,
|
||||
_Inout_opt_ PDWORD_PTR resume_handle)
|
||||
{
|
||||
UNICODE_STRING ServerName;
|
||||
PSAM_RID_ENUMERATION CurrentGroup;
|
||||
PENUM_CONTEXT EnumContext = NULL;
|
||||
ULONG i;
|
||||
SAM_HANDLE GroupHandle = NULL;
|
||||
PGROUP_GENERAL_INFORMATION GroupInfo = NULL;
|
||||
PVOID Buffer = NULL;
|
||||
NET_API_STATUS ApiStatus = NERR_Success;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
TRACE("NetGroupEnum(%s, %d, %p, %d, %p, %p, %p)\n", debugstr_w(servername),
|
||||
level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle);
|
||||
|
||||
*entriesread = 0;
|
||||
*totalentries = 0;
|
||||
*bufptr = NULL;
|
||||
|
||||
if (servername != NULL)
|
||||
RtlInitUnicodeString(&ServerName, servername);
|
||||
|
||||
if (resume_handle != NULL && *resume_handle != 0)
|
||||
{
|
||||
EnumContext = (PENUM_CONTEXT)*resume_handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
|
||||
if (ApiStatus != NERR_Success)
|
||||
goto done;
|
||||
|
||||
EnumContext->EnumerationContext = 0;
|
||||
EnumContext->Buffer = NULL;
|
||||
EnumContext->Returned = 0;
|
||||
EnumContext->Index = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Status = OpenAccountDomain(EnumContext->ServerHandle,
|
||||
(servername != NULL) ? &ServerName : NULL,
|
||||
DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
|
||||
&EnumContext->AccountDomainHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
|
||||
ApiStatus = NetpNtStatusToApiStatus(Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = OpenBuiltinDomain(EnumContext->ServerHandle,
|
||||
DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
|
||||
&EnumContext->BuiltinDomainHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
|
||||
ApiStatus = NetpNtStatusToApiStatus(Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
EnumContext->Phase = AccountPhase; //BuiltinPhase;
|
||||
EnumContext->DomainHandle = EnumContext->AccountDomainHandle; //BuiltinDomainHandle;
|
||||
}
|
||||
|
||||
|
||||
// while (TRUE)
|
||||
// {
|
||||
TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
|
||||
TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
|
||||
|
||||
if (EnumContext->Index >= EnumContext->Returned)
|
||||
{
|
||||
TRACE("Calling SamEnumerateGroupsInDomain\n");
|
||||
|
||||
Status = SamEnumerateGroupsInDomain(EnumContext->DomainHandle,
|
||||
&EnumContext->EnumerationContext,
|
||||
(PVOID *)&EnumContext->Buffer,
|
||||
prefmaxlen,
|
||||
&EnumContext->Returned);
|
||||
|
||||
TRACE("SamEnumerateGroupsInDomain returned (Status %08lx)\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
|
||||
ApiStatus = NetpNtStatusToApiStatus(Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (Status == STATUS_MORE_ENTRIES)
|
||||
{
|
||||
ApiStatus = NERR_BufTooSmall;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("EnumContext: %lu\n", EnumContext);
|
||||
TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
|
||||
TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
|
||||
|
||||
/* Get a pointer to the current group */
|
||||
CurrentGroup = &EnumContext->Buffer[EnumContext->Index];
|
||||
|
||||
TRACE("RID: %lu\n", CurrentGroup->RelativeId);
|
||||
|
||||
Status = SamOpenGroup(EnumContext->DomainHandle,
|
||||
GROUP_READ_INFORMATION,
|
||||
CurrentGroup->RelativeId,
|
||||
&GroupHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("SamOpenGroup failed (Status %08lx)\n", Status);
|
||||
ApiStatus = NetpNtStatusToApiStatus(Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = SamQueryInformationGroup(GroupHandle,
|
||||
GroupGeneralInformation,
|
||||
(PVOID *)&GroupInfo);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("SamQueryInformationGroup failed (Status %08lx)\n", Status);
|
||||
ApiStatus = NetpNtStatusToApiStatus(Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
SamCloseHandle(GroupHandle);
|
||||
GroupHandle = NULL;
|
||||
|
||||
TRACE("Name: %S\n", GroupInfo->Name.Buffer);
|
||||
TRACE("Comment: %S\n", GroupInfo->AdminComment.Buffer);
|
||||
|
||||
ApiStatus = BuildGroupInfoBuffer(GroupInfo,
|
||||
level,
|
||||
CurrentGroup->RelativeId,
|
||||
&Buffer);
|
||||
if (ApiStatus != NERR_Success)
|
||||
goto done;
|
||||
|
||||
if (GroupInfo != NULL)
|
||||
{
|
||||
FreeGroupInfo(GroupInfo);
|
||||
GroupInfo = NULL;
|
||||
}
|
||||
|
||||
EnumContext->Index++;
|
||||
|
||||
(*entriesread)++;
|
||||
|
||||
if (EnumContext->Index == EnumContext->Returned)
|
||||
{
|
||||
switch (EnumContext->Phase)
|
||||
{
|
||||
case BuiltinPhase:
|
||||
EnumContext->Phase = AccountPhase;
|
||||
EnumContext->DomainHandle = EnumContext->AccountDomainHandle;
|
||||
EnumContext->EnumerationContext = 0;
|
||||
EnumContext->Index = 0;
|
||||
EnumContext->Returned = 0;
|
||||
|
||||
if (EnumContext->Buffer != NULL)
|
||||
{
|
||||
for (i = 0; i < EnumContext->Returned; i++)
|
||||
{
|
||||
SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
|
||||
}
|
||||
|
||||
SamFreeMemory(EnumContext->Buffer);
|
||||
EnumContext->Buffer = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case AccountPhase:
|
||||
case DonePhase:
|
||||
EnumContext->Phase = DonePhase;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
done:
|
||||
if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Phase != DonePhase)
|
||||
ApiStatus = ERROR_MORE_DATA;
|
||||
|
||||
if (EnumContext != NULL)
|
||||
*totalentries = EnumContext->Returned;
|
||||
|
||||
if (resume_handle == NULL || ApiStatus != ERROR_MORE_DATA)
|
||||
{
|
||||
if (EnumContext != NULL)
|
||||
{
|
||||
if (EnumContext->BuiltinDomainHandle != NULL)
|
||||
SamCloseHandle(EnumContext->BuiltinDomainHandle);
|
||||
|
||||
if (EnumContext->AccountDomainHandle != NULL)
|
||||
SamCloseHandle(EnumContext->AccountDomainHandle);
|
||||
|
||||
if (EnumContext->ServerHandle != NULL)
|
||||
SamCloseHandle(EnumContext->ServerHandle);
|
||||
|
||||
if (EnumContext->Buffer != NULL)
|
||||
{
|
||||
for (i = 0; i < EnumContext->Returned; i++)
|
||||
{
|
||||
SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
|
||||
}
|
||||
|
||||
SamFreeMemory(EnumContext->Buffer);
|
||||
}
|
||||
|
||||
NetApiBufferFree(EnumContext);
|
||||
EnumContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (GroupHandle != NULL)
|
||||
SamCloseHandle(GroupHandle);
|
||||
|
||||
if (GroupInfo != NULL)
|
||||
FreeGroupInfo(GroupInfo);
|
||||
|
||||
if (resume_handle != NULL)
|
||||
*resume_handle = (DWORD_PTR)EnumContext;
|
||||
|
||||
*bufptr = (LPBYTE)Buffer;
|
||||
|
||||
TRACE("return %lu\n", ApiStatus);
|
||||
|
||||
return ApiStatus;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue