From a37d2347c39833a6de365f79d1c2c77995b66cce Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Fri, 7 Jun 2013 22:36:49 +0000 Subject: [PATCH] [NETAPI32] Fix NetLocalGroupGetMembers and implement level 1. The netapi32:access winetest does not crash any more and group members appear in the user manager control panel. svn path=/trunk/; revision=59186 --- reactos/dll/win32/netapi32/local_group.c | 205 +++++++++++++++-------- 1 file changed, 133 insertions(+), 72 deletions(-) diff --git a/reactos/dll/win32/netapi32/local_group.c b/reactos/dll/win32/netapi32/local_group.c index 72ab5cc495d..8f40d3ed068 100644 --- a/reactos/dll/win32/netapi32/local_group.c +++ b/reactos/dll/win32/netapi32/local_group.c @@ -50,10 +50,13 @@ typedef struct _MEMBER_ENUM_CONTEXT SAM_HANDLE ServerHandle; SAM_HANDLE DomainHandle; SAM_HANDLE AliasHandle; + LSA_HANDLE LsaHandle; PSID *Sids; ULONG Count; - ULONG Index; + PLSA_REFERENCED_DOMAIN_LIST Domains; + PLSA_TRANSLATED_NAME Names; + } MEMBER_ENUM_CONTEXT, *PMEMBER_ENUM_CONTEXT; @@ -160,66 +163,6 @@ FreeAliasInfo(PALIAS_GENERAL_INFORMATION AliasInfo) } -static -NET_API_STATUS -BuildAliasMemberBuffer(PSID MemberSid, - DWORD level, - LPVOID *Buffer) -{ - LPVOID LocalBuffer = NULL; - PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0; - PVOID Ptr; - ULONG Size = 0; - NET_API_STATUS ApiStatus = NERR_Success; - - switch (level) - { - case 0: - Size = sizeof(LOCALGROUP_MEMBERS_INFO_0) + - RtlLengthSid(MemberSid); - break; - - default: - ApiStatus = ERROR_INVALID_LEVEL; - goto done; - } - - - ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer); - if (ApiStatus != NERR_Success) - goto done; - - ZeroMemory(LocalBuffer, Size); - - switch (level) - { - case 0: - MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)LocalBuffer; - - Ptr = (PVOID)MembersInfo0++; - MembersInfo0->lgrmi0_sid = (PSID)Ptr; - - memcpy(MembersInfo0->lgrmi0_sid, - MemberSid, - RtlLengthSid(MemberSid)); - break; - } - -done: - if (ApiStatus == NERR_Success) - { - *Buffer = LocalBuffer; - } - else - { - if (LocalBuffer != NULL) - NetApiBufferFree(LocalBuffer); - } - - return ApiStatus; -} - - static NET_API_STATUS OpenAliasByName(SAM_HANDLE DomainHandle, @@ -996,14 +939,21 @@ NetLocalGroupGetMembers( LPDWORD totalentries, PDWORD_PTR resumehandle) { + OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING ServerName; UNICODE_STRING AliasName; PMEMBER_ENUM_CONTEXT EnumContext = NULL; LPVOID Buffer = NULL; + PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0; + PLOCALGROUP_MEMBERS_INFO_1 MembersInfo1; + LPWSTR Ptr; + ULONG Size = 0; + ULONG SidLength; + ULONG i; NET_API_STATUS ApiStatus = NERR_Success; NTSTATUS Status = STATUS_SUCCESS; - TRACE("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername), + TRACE("(%s %s %d %p %d, %p %p %p)\n", debugstr_w(servername), debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle); @@ -1109,30 +1059,135 @@ NetLocalGroupGetMembers( ApiStatus = NERR_Success; goto done; } + + + if (level != 0) + { + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + 0, + NULL); + + Status = LsaOpenPolicy((servername != NULL) ? &ServerName : NULL, + (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes, + POLICY_EXECUTE, + &EnumContext->LsaHandle); + if (!NT_SUCCESS(Status)) + { + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + Status = LsaLookupSids(EnumContext->LsaHandle, + EnumContext->Count, + EnumContext->Sids, + &EnumContext->Domains, + &EnumContext->Names); + if (!NT_SUCCESS(Status)) + { + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + } } - /* Build the member information buffer */ - ApiStatus = BuildAliasMemberBuffer(EnumContext->Sids[EnumContext->Index], - level, - &Buffer); + /* Calculate the required buffer size */ + for (i = 0; i < EnumContext->Count; i++) + { + switch (level) + { + case 0: + Size = sizeof(LOCALGROUP_MEMBERS_INFO_0) + + RtlLengthSid(EnumContext->Sids[i]); + break; + + case 1: + Size = sizeof(LOCALGROUP_MEMBERS_INFO_1) + + RtlLengthSid(EnumContext->Sids[i]) + + EnumContext->Names[i].Name.Length + sizeof(WCHAR); + break; + + default: + ApiStatus = ERROR_INVALID_LEVEL; + goto done; + } + } + + /* Allocate the member buffer */ + ApiStatus = NetApiBufferAllocate(Size, &Buffer); if (ApiStatus != NERR_Success) goto done; - EnumContext->Index++; - (*entriesread)++; + ZeroMemory(Buffer, Size); + + /* Fill the member buffer */ + switch (level) + { + case 0: + MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)Buffer; + Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_0) * EnumContext->Count); + break; + + case 1: + MembersInfo1 = (PLOCALGROUP_MEMBERS_INFO_1)Buffer; + Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_1) * EnumContext->Count); + break; + } + + for (i = 0; i < EnumContext->Count; i++) + { + switch (level) + { + case 0: + MembersInfo0->lgrmi0_sid = (PSID)Ptr; + + SidLength = RtlLengthSid(EnumContext->Sids[i]); + memcpy(MembersInfo0->lgrmi0_sid, + EnumContext->Sids[i], + SidLength); + Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); + break; + + case 1: + MembersInfo1->lgrmi1_sid = (PSID)Ptr; + + SidLength = RtlLengthSid(EnumContext->Sids[i]); + memcpy(MembersInfo1->lgrmi1_sid, + EnumContext->Sids[i], + SidLength); + + Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); + + MembersInfo1->lgrmi1_sidusage = EnumContext->Names[i].Use; + + TRACE("Name: %S\n", EnumContext->Names[i].Name.Buffer); + + MembersInfo1->lgrmi1_name = (LPWSTR)Ptr; + + memcpy(MembersInfo1->lgrmi1_name, + EnumContext->Names[i].Name.Buffer, + EnumContext->Names[i].Name.Length); + break; + } + } + + *entriesread = EnumContext->Count; + + *bufptr = (LPBYTE)Buffer; done: - if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count) - ApiStatus = ERROR_MORE_DATA; - if (EnumContext != NULL) - *totalentries = EnumContext->Count - EnumContext->Index; + *totalentries = EnumContext->Count; if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) { /* Release the enumeration context */ if (EnumContext != NULL) { + if (EnumContext->LsaHandle != NULL) + LsaClose(EnumContext->LsaHandle); + if (EnumContext->AliasHandle != NULL) SamCloseHandle(EnumContext->AliasHandle); @@ -1145,6 +1200,12 @@ done: if (EnumContext->Sids != NULL) SamFreeMemory(EnumContext->Sids); + if (EnumContext->Domains != NULL) + LsaFreeMemory(EnumContext->Domains); + + if (EnumContext->Names != NULL) + LsaFreeMemory(EnumContext->Names); + NetApiBufferFree(EnumContext); EnumContext = NULL; }