Author: ekohl Date: Wed Jun 5 22:08:53 2013 New Revision: 59176
URL: http://svn.reactos.org/svn/reactos?rev=59176&view=rev Log: [NETAPI32] Implement NetLocalGroupGetMembers. Level 0 support only. Will be tested and fixed when level 1 support will be added.
Modified: trunk/reactos/dll/win32/netapi32/local_group.c
Modified: trunk/reactos/dll/win32/netapi32/local_group.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netapi32/local_gr... ============================================================================== --- trunk/reactos/dll/win32/netapi32/local_group.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/netapi32/local_group.c [iso-8859-1] Wed Jun 5 22:08:53 2013 @@ -45,6 +45,17 @@
} ENUM_CONTEXT, *PENUM_CONTEXT;
+typedef struct _MEMBER_ENUM_CONTEXT +{ + SAM_HANDLE ServerHandle; + SAM_HANDLE DomainHandle; + SAM_HANDLE AliasHandle; + + PSID *Sids; + ULONG Count; + ULONG Index; +} MEMBER_ENUM_CONTEXT, *PMEMBER_ENUM_CONTEXT; +
static NET_API_STATUS @@ -146,6 +157,66 @@ SamFreeMemory(AliasInfo->AdminComment.Buffer);
SamFreeMemory(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; }
@@ -913,7 +984,9 @@ /************************************************************ * NetLocalGroupGetMembers (NETAPI32.@) */ -NET_API_STATUS WINAPI NetLocalGroupGetMembers( +NET_API_STATUS +WINAPI +NetLocalGroupGetMembers( LPCWSTR servername, LPCWSTR localgroupname, DWORD level, @@ -923,44 +996,163 @@ LPDWORD totalentries, PDWORD_PTR resumehandle) { - FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername), + UNICODE_STRING ServerName; + UNICODE_STRING AliasName; + PMEMBER_ENUM_CONTEXT EnumContext = NULL; + LPVOID Buffer = NULL; + NET_API_STATUS ApiStatus = NERR_Success; + NTSTATUS Status = STATUS_SUCCESS; + + TRACE("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername), debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
- if (level == 3) - { - WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD userNameLen; - DWORD len,needlen; - PLOCALGROUP_MEMBERS_INFO_3 ptr; - - /* still a stub, current user is belonging to all groups */ - - *totalentries = 1; - *entriesread = 0; - - userNameLen = MAX_COMPUTERNAME_LENGTH + 1; - GetUserNameW(userName,&userNameLen); - needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) + - (userNameLen+2) * sizeof(WCHAR); - if (prefmaxlen != MAX_PREFERRED_LENGTH) - len = min(prefmaxlen,needlen); - else - len = needlen; - - NetApiBufferAllocate(len, (LPVOID *) bufptr); - if (len < needlen) - return ERROR_MORE_DATA; - - ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr; - ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3)); - lstrcpyW(ptr->lgrmi3_domainandname,userName); - - *entriesread = 1; - } - - return NERR_Success; -} + *entriesread = 0; + *totalentries = 0; + *bufptr = NULL; + + if (servername != NULL) + RtlInitUnicodeString(&ServerName, servername); + + RtlInitUnicodeString(&AliasName, localgroupname); + + if (resumehandle != NULL && *resumehandle != 0) + { + EnumContext = (PMEMBER_ENUM_CONTEXT)*resumehandle; + } + else + { + /* Allocate the enumeration context */ + ApiStatus = NetApiBufferAllocate(sizeof(MEMBER_ENUM_CONTEXT), (PVOID*)&EnumContext); + if (ApiStatus != NERR_Success) + goto done; + + /* 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 Builtin Domain */ + Status = OpenBuiltinDomain(EnumContext->ServerHandle, + DOMAIN_LOOKUP, + &EnumContext->DomainHandle); + if (!NT_SUCCESS(Status)) + { + ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + /* Open the alias account in the builtin domain */ + ApiStatus = OpenAliasByName(EnumContext->DomainHandle, + &AliasName, + ALIAS_LIST_MEMBERS, + &EnumContext->AliasHandle); + if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) + { + ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); + goto done; + } + + if (EnumContext->AliasHandle == NULL) + { + if (EnumContext->DomainHandle != NULL) + SamCloseHandle(EnumContext->DomainHandle); + + /* 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 alias account in the account domain */ + ApiStatus = OpenAliasByName(EnumContext->DomainHandle, + &AliasName, + ALIAS_LIST_MEMBERS, + &EnumContext->AliasHandle); + if (ApiStatus != NERR_Success) + { + ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); + if (ApiStatus == ERROR_NONE_MAPPED) + ApiStatus = NERR_GroupNotFound; + goto done; + } + } + + /* Get the member list */ + Status = SamGetMembersInAlias(EnumContext->AliasHandle, + &EnumContext->Sids, + &EnumContext->Count); + if (!NT_SUCCESS(Status)) + { + ERR("SamGetMemberInAlias failed (Status %08lx)\n", Status); + ApiStatus = NetpNtStatusToApiStatus(Status); + goto done; + } + + if (EnumContext->Count == 0) + { + TRACE("No member found. We're done.\n"); + ApiStatus = NERR_Success; + goto done; + } + } + + /* Build the member information buffer */ + ApiStatus = BuildAliasMemberBuffer(EnumContext->Sids[EnumContext->Index], + level, + &Buffer); + if (ApiStatus != NERR_Success) + goto done; + + EnumContext->Index++; + (*entriesread)++; + +done: + if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Count) + ApiStatus = ERROR_MORE_DATA; + + if (EnumContext != NULL) + *totalentries = EnumContext->Count - EnumContext->Index; + + if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) + { + /* Release the enumeration context */ + if (EnumContext != NULL) + { + if (EnumContext->AliasHandle != NULL) + SamCloseHandle(EnumContext->AliasHandle); + + if (EnumContext->DomainHandle != NULL) + SamCloseHandle(EnumContext->DomainHandle); + + if (EnumContext->ServerHandle != NULL) + SamCloseHandle(EnumContext->ServerHandle); + + if (EnumContext->Sids != NULL) + SamFreeMemory(EnumContext->Sids); + + NetApiBufferFree(EnumContext); + EnumContext = NULL; + } + } + + return ApiStatus; +} +
/************************************************************ * NetLocalGroupSetInfo (NETAPI32.@)