Author: ekohl
Date: Tue Jan 1 22:54:39 2013
New Revision: 58095
URL:
http://svn.reactos.org/svn/reactos?rev=58095&view=rev
Log:
[NETAPI32]
NetUserGetLocalGroups: Replace the simulation by a working implementation.
Modified:
trunk/reactos/dll/win32/netapi32/user.c
Modified: trunk/reactos/dll/win32/netapi32/user.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/netapi32/user.c?…
==============================================================================
--- trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/netapi32/user.c [iso-8859-1] Tue Jan 1 22:54:39 2013
@@ -18,6 +18,18 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+/*
+ * TODO:
+ * Implement NetUserChangePassword
+ * Implement NetUserDel
+ * Implement NetUserGetGroups
+ * Implement NetUserSetGroups
+ * Implement NetUserSetInfo
+ * NetUserGetLocalGroups does not support LG_INCLUDE_INDIRECT yet.
+ * Add missing information levels.
+ * ...
+ */
+
#include "netapi32.h"
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
@@ -104,6 +116,46 @@
return user;
}
return NULL;
+}
+
+
+static PSID
+CreateSidFromSidAndRid(PSID SrcSid,
+ ULONG RelativeId)
+{
+ UCHAR RidCount;
+ PSID DstSid;
+ ULONG i;
+ ULONG DstSidSize;
+ PULONG p, q;
+
+ RidCount = *RtlSubAuthorityCountSid(SrcSid);
+ if (RidCount >= 8)
+ return NULL;
+
+ DstSidSize = RtlLengthRequiredSid(RidCount + 1);
+
+ DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ DstSidSize);
+ if (DstSid == NULL)
+ return NULL;
+
+ RtlInitializeSid(DstSid,
+ RtlIdentifierAuthoritySid(SrcSid),
+ RidCount + 1);
+
+ for (i = 0; i < (ULONG)RidCount; i++)
+ {
+ p = RtlSubAuthoritySid(SrcSid, i);
+ q = RtlSubAuthoritySid(DstSid, i);
+ *q = *p;
+ }
+
+ q = RtlSubAuthoritySid(DstSid, (ULONG)RidCount);
+ *q = RelativeId;
+
+ return DstSid;
}
@@ -544,7 +596,7 @@
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
- FIXME("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr,
parm_err);
+ TRACE("(%s, %d, %p, %p)\n", debugstr_w(servername), level, bufptr,
parm_err);
/* Check the info level */
if (level < 1 || level > 4)
@@ -1097,53 +1149,298 @@
LPDWORD entriesread,
LPDWORD totalentries)
{
- NET_API_STATUS status;
- const WCHAR admins[] =
{'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
- LPWSTR currentuser;
- LOCALGROUP_USERS_INFO_0* info;
- DWORD size;
-
- FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
+ UNICODE_STRING ServerName;
+ UNICODE_STRING UserName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE BuiltinDomainHandle = NULL;
+ SAM_HANDLE AccountDomainHandle = NULL;
+ PSID AccountDomainSid = NULL;
+ PSID UserSid = NULL;
+ PULONG RelativeIds = NULL;
+ PSID_NAME_USE Use = NULL;
+ ULONG BuiltinMemberCount = 0;
+ ULONG AccountMemberCount = 0;
+ PULONG BuiltinAliases = NULL;
+ PULONG AccountAliases = NULL;
+ PUNICODE_STRING BuiltinNames = NULL;
+ PUNICODE_STRING AccountNames = NULL;
+ PLOCALGROUP_USERS_INFO_0 Buffer = NULL;
+ ULONG Size;
+ ULONG Count = 0;
+ ULONG Index;
+ ULONG i;
+ LPWSTR StrPtr;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
prefmaxlen, entriesread, totalentries);
- status = NETAPI_ValidateServername(servername);
- if (status != NERR_Success)
- return status;
-
- size = UNLEN + 1;
- NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)¤tuser);
- GetUserNameW(currentuser, &size);
-
- if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
- {
- NetApiBufferFree(currentuser);
- return NERR_UserNotFound;
- }
-
- NetApiBufferFree(currentuser);
- *totalentries = 1;
- size = sizeof(*info) + sizeof(admins);
-
- if(prefmaxlen < size)
- status = ERROR_MORE_DATA;
+ if (level != 0)
+ return ERROR_INVALID_LEVEL;
+
+ if (flags & ~LG_INCLUDE_INDIRECT)
+ return ERROR_INVALID_PARAMETER;
+
+ if (flags & LG_INCLUDE_INDIRECT)
+ {
+ WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
+ }
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&UserName, username);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &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(ServerHandle,
+ DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
+ &BuiltinDomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Get the Account Domain SID */
+ Status = GetAccountDomainSid((servername != NULL) ? &ServerName : NULL,
+ &AccountDomainSid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetAccountDomainSid failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Account Domain */
+ Status = SamOpenDomain(ServerHandle,
+ DOMAIN_LOOKUP | DOMAIN_GET_ALIAS_MEMBERSHIP,
+ AccountDomainSid,
+ &AccountDomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Get the RID for the given user name */
+ Status = SamLookupNamesInDomain(AccountDomainHandle,
+ 1,
+ &UserName,
+ &RelativeIds,
+ &Use);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Fail, if it is not a user account */
+ if (Use[0] != SidTypeUser)
+ {
+ ERR("Account is not a User!\n");
+ ApiStatus = NERR_UserNotFound;
+ goto done;
+ }
+
+ /* Build the User SID from the Account Domain SID and the users RID */
+ UserSid = CreateSidFromSidAndRid(AccountDomainSid,
+ RelativeIds[0]);
+ if (UserSid == NULL)
+ {
+ ERR("CreateSidFromSidAndRid failed!\n");
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ /* Get alias memberships in the Builtin Domain */
+ Status = SamGetAliasMembership(BuiltinDomainHandle,
+ 1,
+ &UserSid,
+ &BuiltinMemberCount,
+ &BuiltinAliases);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ if (BuiltinMemberCount > 0)
+ {
+ /* Get the Names of the builtin alias members */
+ Status = SamLookupIdsInDomain(BuiltinDomainHandle,
+ BuiltinMemberCount,
+ BuiltinAliases,
+ &BuiltinNames,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+
+ /* Get alias memberships in the Account Domain */
+ Status = SamGetAliasMembership(AccountDomainHandle,
+ 1,
+ &UserSid,
+ &AccountMemberCount,
+ &AccountAliases);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamGetAliasMembership failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ if (AccountMemberCount > 0)
+ {
+ /* Get the Names of the builtin alias members */
+ Status = SamLookupIdsInDomain(AccountDomainHandle,
+ AccountMemberCount,
+ AccountAliases,
+ &AccountNames,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamLookupIdsInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+
+ /* Calculate the required buffer size */
+ Size = 0;
+
+ for (i = 0; i < BuiltinMemberCount; i++)
+ {
+ if (BuiltinNames[i].Length > 0)
+ {
+ Size += (sizeof(LOCALGROUP_USERS_INFO_0) + BuiltinNames[i].Length +
sizeof(UNICODE_NULL));
+ Count++;
+ }
+ }
+
+ for (i = 0; i < AccountMemberCount; i++)
+ {
+ if (BuiltinNames[i].Length > 0)
+ {
+ Size += (sizeof(LOCALGROUP_USERS_INFO_0) + AccountNames[i].Length +
sizeof(UNICODE_NULL));
+ Count++;
+ }
+ }
+
+ if (Size == 0)
+ {
+ ApiStatus = NERR_Success;
+ goto done;
+ }
+
+ /* Allocate buffer */
+ ApiStatus = NetApiBufferAllocate(Size, (LPVOID*)&Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ ZeroMemory(Buffer, Size);
+
+ StrPtr = (LPWSTR)((INT_PTR)Buffer + Count * sizeof(LOCALGROUP_USERS_INFO_0));
+
+ /* Copy data to the allocated buffer */
+ Index = 0;
+ for (i = 0; i < BuiltinMemberCount; i++)
+ {
+ if (BuiltinNames[i].Length > 0)
+ {
+ CopyMemory(StrPtr,
+ BuiltinNames[i].Buffer,
+ BuiltinNames[i].Length);
+ Buffer[Index].lgrui0_name = StrPtr;
+
+ StrPtr = (LPWSTR)((INT_PTR)StrPtr + BuiltinNames[i].Length +
sizeof(UNICODE_NULL));
+ Index++;
+ }
+ }
+
+ for (i = 0; i < AccountMemberCount; i++)
+ {
+ if (AccountNames[i].Length > 0)
+ {
+ CopyMemory(StrPtr,
+ AccountNames[i].Buffer,
+ AccountNames[i].Length);
+ Buffer[Index].lgrui0_name = StrPtr;
+
+ StrPtr = (LPWSTR)((INT_PTR)StrPtr + AccountNames[i].Length +
sizeof(UNICODE_NULL));
+ Index++;
+ }
+ }
+
+done:
+ if (AccountNames != NULL)
+ SamFreeMemory(AccountNames);
+
+ if (BuiltinNames != NULL)
+ SamFreeMemory(BuiltinNames);
+
+ if (AccountAliases != NULL)
+ SamFreeMemory(AccountAliases);
+
+ if (BuiltinAliases != NULL)
+ SamFreeMemory(BuiltinAliases);
+
+ if (RelativeIds != NULL)
+ SamFreeMemory(RelativeIds);
+
+ if (Use != NULL)
+ SamFreeMemory(Use);
+
+ if (UserSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
+
+ if (AccountDomainSid != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
+
+ if (AccountDomainHandle != NULL)
+ SamCloseHandle(AccountDomainHandle);
+
+ if (BuiltinDomainHandle != NULL)
+ SamCloseHandle(BuiltinDomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_MORE_DATA)
+ {
+ *entriesread = 0;
+ *totalentries = 0;
+ }
else
- status = NetApiBufferAllocate(size, (LPVOID*)&info);
-
- if(status != NERR_Success)
- {
- *bufptr = NULL;
- *entriesread = 0;
- return status;
- }
-
- info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
- lstrcpyW(info->lgrui0_name, admins);
-
- *bufptr = (LPBYTE)info;
- *entriesread = 1;
-
- return NERR_Success;
+ {
+ *entriesread = Count;
+ *totalentries = Count;
+ }
+
+ *bufptr = (LPBYTE)Buffer;
+
+ return ApiStatus;
}