mirror of
https://github.com/reactos/reactos.git
synced 2024-10-06 01:13:38 +00:00
[NETAPI32]
NetUserGetLocalGroups: Replace the simulation by a working implementation. svn path=/trunk/; revision=58095
This commit is contained in:
parent
cb52c27133
commit
0fea31f7a2
|
@ -18,6 +18,18 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* 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"
|
#include "netapi32.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
|
WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
|
||||||
|
@ -107,6 +119,46 @@ static struct sam_user* NETAPI_FindUser(LPCWSTR UserName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
NET_API_STATUS
|
NET_API_STATUS
|
||||||
BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo,
|
BuildUserInfoBuffer(PUSER_ACCOUNT_INFORMATION UserInfo,
|
||||||
|
@ -544,7 +596,7 @@ NetUserAdd(LPCWSTR servername,
|
||||||
NET_API_STATUS ApiStatus = NERR_Success;
|
NET_API_STATUS ApiStatus = NERR_Success;
|
||||||
NTSTATUS Status = STATUS_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 */
|
/* Check the info level */
|
||||||
if (level < 1 || level > 4)
|
if (level < 1 || level > 4)
|
||||||
|
@ -1097,53 +1149,298 @@ NetUserGetLocalGroups(LPCWSTR servername,
|
||||||
LPDWORD entriesread,
|
LPDWORD entriesread,
|
||||||
LPDWORD totalentries)
|
LPDWORD totalentries)
|
||||||
{
|
{
|
||||||
NET_API_STATUS status;
|
UNICODE_STRING ServerName;
|
||||||
const WCHAR admins[] = {'A','d','m','i','n','i','s','t','r','a','t','o','r','s',0};
|
UNICODE_STRING UserName;
|
||||||
LPWSTR currentuser;
|
SAM_HANDLE ServerHandle = NULL;
|
||||||
LOCALGROUP_USERS_INFO_0* info;
|
SAM_HANDLE BuiltinDomainHandle = NULL;
|
||||||
DWORD size;
|
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;
|
||||||
|
|
||||||
FIXME("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
|
TRACE("(%s, %s, %d, %08x, %p %d, %p, %p) stub!\n",
|
||||||
debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
|
debugstr_w(servername), debugstr_w(username), level, flags, bufptr,
|
||||||
prefmaxlen, entriesread, totalentries);
|
prefmaxlen, entriesread, totalentries);
|
||||||
|
|
||||||
status = NETAPI_ValidateServername(servername);
|
if (level != 0)
|
||||||
if (status != NERR_Success)
|
return ERROR_INVALID_LEVEL;
|
||||||
return status;
|
|
||||||
|
|
||||||
size = UNLEN + 1;
|
if (flags & ~LG_INCLUDE_INDIRECT)
|
||||||
NetApiBufferAllocate(size * sizeof(WCHAR), (LPVOID*)¤tuser);
|
return ERROR_INVALID_PARAMETER;
|
||||||
GetUserNameW(currentuser, &size);
|
|
||||||
|
|
||||||
if (lstrcmpiW(username, currentuser) && NETAPI_FindUser(username))
|
if (flags & LG_INCLUDE_INDIRECT)
|
||||||
{
|
{
|
||||||
NetApiBufferFree(currentuser);
|
WARN("The flag LG_INCLUDE_INDIRECT is not supported yet!\n");
|
||||||
return NERR_UserNotFound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetApiBufferFree(currentuser);
|
if (servername != NULL)
|
||||||
*totalentries = 1;
|
RtlInitUnicodeString(&ServerName, servername);
|
||||||
size = sizeof(*info) + sizeof(admins);
|
|
||||||
|
|
||||||
if(prefmaxlen < size)
|
RtlInitUnicodeString(&UserName, username);
|
||||||
status = ERROR_MORE_DATA;
|
|
||||||
else
|
|
||||||
status = NetApiBufferAllocate(size, (LPVOID*)&info);
|
|
||||||
|
|
||||||
if(status != NERR_Success)
|
/* 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)
|
||||||
{
|
{
|
||||||
*bufptr = NULL;
|
|
||||||
*entriesread = 0;
|
*entriesread = 0;
|
||||||
return status;
|
*totalentries = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*entriesread = Count;
|
||||||
|
*totalentries = Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->lgrui0_name = (LPWSTR)((LPBYTE)info + sizeof(*info));
|
*bufptr = (LPBYTE)Buffer;
|
||||||
lstrcpyW(info->lgrui0_name, admins);
|
|
||||||
|
|
||||||
*bufptr = (LPBYTE)info;
|
return ApiStatus;
|
||||||
*entriesread = 1;
|
|
||||||
|
|
||||||
return NERR_Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue