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_g…
==============================================================================
--- 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.@)