mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 00:31:27 +00:00
[NETAPI32][WKSSVC][IDL] Implement NetrWkstaUserEnum
- TODO: Take PreferredMaximumLength and ResumeHandle into account
This commit is contained in:
parent
4cdcbbd1a9
commit
faf6297972
3 changed files with 267 additions and 17 deletions
|
@ -447,12 +447,243 @@ NetrWkstaUserEnum(
|
||||||
unsigned long *TotalEntries,
|
unsigned long *TotalEntries,
|
||||||
unsigned long *ResumeHandle)
|
unsigned long *ResumeHandle)
|
||||||
{
|
{
|
||||||
ERR("NetrWkstaUserEnum(%p %p 0x%lx %p %p)\n",
|
MSV1_0_ENUMUSERS_REQUEST EnumRequest;
|
||||||
ServerName, UserInfo, PreferredMaximumLength, TotalEntries, ResumeHandle);
|
PMSV1_0_ENUMUSERS_RESPONSE EnumResponseBuffer = NULL;
|
||||||
|
MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;
|
||||||
|
PMSV1_0_GETUSERINFO_RESPONSE UserInfoResponseBuffer = NULL;
|
||||||
|
PMSV1_0_GETUSERINFO_RESPONSE *UserInfoArray = NULL;
|
||||||
|
DWORD EnumResponseBufferSize = 0;
|
||||||
|
DWORD UserInfoResponseBufferSize = 0;
|
||||||
|
NTSTATUS Status, ProtocolStatus;
|
||||||
|
ULONG i, start, count;
|
||||||
|
PLUID pLogonId;
|
||||||
|
PULONG pEnumHandle;
|
||||||
|
DWORD dwResult = NERR_Success;
|
||||||
|
|
||||||
|
PWKSTA_USER_INFO_0 pUserInfo0 = NULL;
|
||||||
|
PWKSTA_USER_INFO_1 pUserInfo1 = NULL;
|
||||||
|
|
||||||
UNIMPLEMENTED;
|
TRACE("NetrWkstaUserEnum(%p %p 0x%lx %p %p)\n",
|
||||||
return 0;
|
ServerName, UserInfo, PreferredMaximumLength, TotalEntries, ResumeHandle);
|
||||||
|
|
||||||
|
if (UserInfo->Level > 1)
|
||||||
|
{
|
||||||
|
ERR("Invalid Level %lu\n", UserInfo->Level);
|
||||||
|
return ERROR_INVALID_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enumerate all currently logged-on users */
|
||||||
|
EnumRequest.MessageType = MsV1_0EnumerateUsers;
|
||||||
|
Status = LsaCallAuthenticationPackage(LsaHandle,
|
||||||
|
LsaAuthenticationPackage,
|
||||||
|
&EnumRequest,
|
||||||
|
sizeof(EnumRequest),
|
||||||
|
(PVOID*)&EnumResponseBuffer,
|
||||||
|
&EnumResponseBufferSize,
|
||||||
|
&ProtocolStatus);
|
||||||
|
|
||||||
|
TRACE("LsaCallAuthenticationPackage Status 0x%08lx ResponseBufferSize %lu\n", Status, EnumResponseBufferSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
dwResult = RtlNtStatusToDosError(Status);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("LoggedOnUsers: %lu\n", EnumResponseBuffer->NumberOfLoggedOnUsers);
|
||||||
|
TRACE("ResponseBuffer: 0x%p\n", EnumResponseBuffer);
|
||||||
|
TRACE("LogonIds: 0x%p\n", EnumResponseBuffer->LogonIds);
|
||||||
|
TRACE("EnumHandles: 0x%p\n", EnumResponseBuffer->EnumHandles);
|
||||||
|
if (EnumResponseBuffer->NumberOfLoggedOnUsers > 0)
|
||||||
|
{
|
||||||
|
pLogonId = EnumResponseBuffer->LogonIds;
|
||||||
|
pEnumHandle = EnumResponseBuffer->EnumHandles;
|
||||||
|
TRACE("pLogonId: 0x%p\n", pLogonId);
|
||||||
|
TRACE("pEnumHandle: 0x%p\n", pEnumHandle);
|
||||||
|
|
||||||
|
UserInfoArray = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
EnumResponseBuffer->NumberOfLoggedOnUsers * sizeof(PMSV1_0_GETUSERINFO_RESPONSE));
|
||||||
|
if (UserInfoArray == NULL)
|
||||||
|
{
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < EnumResponseBuffer->NumberOfLoggedOnUsers; i++)
|
||||||
|
{
|
||||||
|
TRACE("Logon %lu: 0x%08lx %lu\n", i, pLogonId->LowPart, *pEnumHandle);
|
||||||
|
|
||||||
|
UserInfoRequest.MessageType = MsV1_0GetUserInfo;
|
||||||
|
UserInfoRequest.LogonId = *pLogonId;
|
||||||
|
Status = LsaCallAuthenticationPackage(LsaHandle,
|
||||||
|
LsaAuthenticationPackage,
|
||||||
|
&UserInfoRequest,
|
||||||
|
sizeof(UserInfoRequest),
|
||||||
|
(PVOID*)&UserInfoResponseBuffer,
|
||||||
|
&UserInfoResponseBufferSize,
|
||||||
|
&ProtocolStatus);
|
||||||
|
TRACE("LsaCallAuthenticationPackage:MsV1_0GetUserInfo Status 0x%08lx ResponseBufferSize %lu\n", Status, UserInfoResponseBufferSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
dwResult = RtlNtStatusToDosError(Status);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInfoArray[i] = UserInfoResponseBuffer;
|
||||||
|
|
||||||
|
TRACE("UserName: %wZ\n", &UserInfoArray[i]->UserName);
|
||||||
|
TRACE("LogonDomain: %wZ\n", &UserInfoArray[i]->LogonDomainName);
|
||||||
|
TRACE("LogonServer: %wZ\n", &UserInfoArray[i]->LogonServer);
|
||||||
|
|
||||||
|
pLogonId++;
|
||||||
|
pEnumHandle++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PreferredMaximumLength == MAX_PREFERRED_LENGTH)
|
||||||
|
{
|
||||||
|
start = 0;
|
||||||
|
count = EnumResponseBuffer->NumberOfLoggedOnUsers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("Calculate the start index and the number of matching array entries!");
|
||||||
|
dwResult = ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (UserInfo->Level)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
pUserInfo0 = midl_user_allocate(count * sizeof(WKSTA_USER_INFO_0));
|
||||||
|
if (pUserInfo0 == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo0, count * sizeof(WKSTA_USER_INFO_0));
|
||||||
|
|
||||||
|
for (i = 0; i < 0 + count; i++)
|
||||||
|
{
|
||||||
|
pUserInfo0[i].wkui0_username = midl_user_allocate(UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
|
||||||
|
if (pUserInfo0[i].wkui0_username == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo0[i].wkui0_username, UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
|
||||||
|
CopyMemory(pUserInfo0[i].wkui0_username, UserInfoArray[start + i]->UserName.Buffer, UserInfoArray[start + i]->UserName.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInfo->WkstaUserInfo.Level0.EntriesRead = count;
|
||||||
|
UserInfo->WkstaUserInfo.Level0.Buffer = pUserInfo0;
|
||||||
|
*TotalEntries = EnumResponseBuffer->NumberOfLoggedOnUsers;
|
||||||
|
*ResumeHandle = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
pUserInfo1 = midl_user_allocate(count * sizeof(WKSTA_USER_INFO_1));
|
||||||
|
if (pUserInfo1 == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo1, count * sizeof(WKSTA_USER_INFO_1));
|
||||||
|
|
||||||
|
for (i = 0; i < 0 + count; i++)
|
||||||
|
{
|
||||||
|
pUserInfo1[i].wkui1_username = midl_user_allocate(UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
|
||||||
|
if (pUserInfo1[i].wkui1_username == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo1[i].wkui1_username, UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
|
||||||
|
CopyMemory(pUserInfo1[i].wkui1_username, UserInfoArray[start + i]->UserName.Buffer, UserInfoArray[start + i]->UserName.Length);
|
||||||
|
|
||||||
|
pUserInfo1[i].wkui1_logon_domain = midl_user_allocate(UserInfoArray[start + i]->LogonDomainName.Length + sizeof(WCHAR));
|
||||||
|
if (pUserInfo1[i].wkui1_logon_domain == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo1[i].wkui1_logon_domain, UserInfoArray[start + i]->LogonDomainName.Length + sizeof(WCHAR));
|
||||||
|
CopyMemory(pUserInfo1[i].wkui1_logon_domain, UserInfoArray[start + i]->LogonDomainName.Buffer, UserInfoArray[start + i]->LogonDomainName.Length);
|
||||||
|
|
||||||
|
// FIXME: wkui1_oth_domains
|
||||||
|
|
||||||
|
pUserInfo1[i].wkui1_logon_server = midl_user_allocate(UserInfoArray[start + i]->LogonServer.Length + sizeof(WCHAR));
|
||||||
|
if (pUserInfo1[i].wkui1_logon_server == NULL)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
dwResult = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pUserInfo1[i].wkui1_logon_server, UserInfoArray[start + i]->LogonServer.Length + sizeof(WCHAR));
|
||||||
|
CopyMemory(pUserInfo1[i].wkui1_logon_server, UserInfoArray[start + i]->LogonServer.Buffer, UserInfoArray[start + i]->LogonServer.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInfo->WkstaUserInfo.Level1.EntriesRead = count;
|
||||||
|
UserInfo->WkstaUserInfo.Level1.Buffer = pUserInfo1;
|
||||||
|
*TotalEntries = EnumResponseBuffer->NumberOfLoggedOnUsers;
|
||||||
|
*ResumeHandle = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (UserInfo->Level == 0)
|
||||||
|
{
|
||||||
|
UserInfo->WkstaUserInfo.Level0.Buffer = NULL;
|
||||||
|
UserInfo->WkstaUserInfo.Level0.EntriesRead = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UserInfo->WkstaUserInfo.Level1.Buffer = NULL;
|
||||||
|
UserInfo->WkstaUserInfo.Level1.EntriesRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*TotalEntries = 0;
|
||||||
|
dwResult = NERR_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (UserInfoArray !=NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (i = 0; i < EnumResponseBuffer->NumberOfLoggedOnUsers; i++)
|
||||||
|
{
|
||||||
|
if (UserInfoArray[i]->UserName.Buffer != NULL)
|
||||||
|
LsaFreeReturnBuffer(UserInfoArray[i]->UserName.Buffer);
|
||||||
|
|
||||||
|
if (UserInfoArray[i]->LogonDomainName.Buffer != NULL)
|
||||||
|
LsaFreeReturnBuffer(UserInfoArray[i]->LogonDomainName.Buffer);
|
||||||
|
|
||||||
|
if (UserInfoArray[i]->LogonServer.Buffer != NULL)
|
||||||
|
LsaFreeReturnBuffer(UserInfoArray[i]->LogonServer.Buffer);
|
||||||
|
|
||||||
|
LsaFreeReturnBuffer(UserInfoArray[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, UserInfoArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnumResponseBuffer != NULL)
|
||||||
|
LsaFreeReturnBuffer(EnumResponseBuffer);
|
||||||
|
|
||||||
|
return dwResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1057,8 +1057,8 @@ NetWkstaUserEnum(
|
||||||
_Inout_ LPDWORD resumehandle)
|
_Inout_ LPDWORD resumehandle)
|
||||||
{
|
{
|
||||||
WKSTA_USER_ENUM_STRUCT UserEnumInfo;
|
WKSTA_USER_ENUM_STRUCT UserEnumInfo;
|
||||||
WKSTA_USER_INFO_0_CONTAINER Container0;
|
// WKSTA_USER_INFO_0_CONTAINER Container0;
|
||||||
WKSTA_USER_INFO_1_CONTAINER Container1;
|
// WKSTA_USER_INFO_1_CONTAINER Container1;
|
||||||
NET_API_STATUS status;
|
NET_API_STATUS status;
|
||||||
|
|
||||||
TRACE("NetWkstaUserEnum(%s, %d, %p, %d, %p, %p, %p)\n", debugstr_w(servername),
|
TRACE("NetWkstaUserEnum(%s, %d, %p, %d, %p, %p, %p)\n", debugstr_w(servername),
|
||||||
|
@ -1068,15 +1068,19 @@ NetWkstaUserEnum(
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
UserEnumInfo.WkstaUserInfo.Level0 = &Container0;
|
// UserEnumInfo.WkstaUserInfo.Level0 = &Container0;
|
||||||
Container0.EntriesRead = 0;
|
// Container0.EntriesRead = 0;
|
||||||
Container0.Buffer = NULL;
|
// Container0.Buffer = NULL;
|
||||||
|
UserEnumInfo.WkstaUserInfo.Level0.EntriesRead = 0;
|
||||||
|
UserEnumInfo.WkstaUserInfo.Level0.Buffer = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
UserEnumInfo.WkstaUserInfo.Level1 = &Container1;
|
// UserEnumInfo.WkstaUserInfo.Level1 = &Container1;
|
||||||
Container1.EntriesRead = 0;
|
// Container1.EntriesRead = 0;
|
||||||
Container1.Buffer = NULL;
|
// Container1.Buffer = NULL;
|
||||||
|
UserEnumInfo.WkstaUserInfo.Level1.EntriesRead = 0;
|
||||||
|
UserEnumInfo.WkstaUserInfo.Level1.Buffer = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1095,13 +1099,17 @@ NetWkstaUserEnum(
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
*bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level0->Buffer;
|
// *bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level0->Buffer;
|
||||||
*entriesread = UserEnumInfo.WkstaUserInfo.Level0->EntriesRead;
|
// *entriesread = UserEnumInfo.WkstaUserInfo.Level0->EntriesRead;
|
||||||
|
*bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level0.Buffer;
|
||||||
|
*entriesread = UserEnumInfo.WkstaUserInfo.Level0.EntriesRead;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
*bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level1->Buffer;
|
// *bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level1->Buffer;
|
||||||
*entriesread = UserEnumInfo.WkstaUserInfo.Level1->EntriesRead;
|
// *entriesread = UserEnumInfo.WkstaUserInfo.Level1->EntriesRead;
|
||||||
|
*bufptr = (LPBYTE)UserEnumInfo.WkstaUserInfo.Level1.Buffer;
|
||||||
|
*entriesread = UserEnumInfo.WkstaUserInfo.Level1.EntriesRead;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,7 +311,7 @@ typedef struct _WKSTA_USER_INFO_1_CONTAINER
|
||||||
unsigned long EntriesRead;
|
unsigned long EntriesRead;
|
||||||
[size_is(EntriesRead)] LPWKSTA_USER_INFO_1 Buffer;
|
[size_is(EntriesRead)] LPWKSTA_USER_INFO_1 Buffer;
|
||||||
} WKSTA_USER_INFO_1_CONTAINER, *PWKSTA_USER_INFO_1_CONTAINER, *LPWKSTA_USER_INFO_1_CONTAINER;
|
} WKSTA_USER_INFO_1_CONTAINER, *PWKSTA_USER_INFO_1_CONTAINER, *LPWKSTA_USER_INFO_1_CONTAINER;
|
||||||
|
/*
|
||||||
typedef struct _WKSTA_USER_ENUM_STRUCT
|
typedef struct _WKSTA_USER_ENUM_STRUCT
|
||||||
{
|
{
|
||||||
unsigned long Level;
|
unsigned long Level;
|
||||||
|
@ -322,6 +322,17 @@ typedef struct _WKSTA_USER_ENUM_STRUCT
|
||||||
[default] ;
|
[default] ;
|
||||||
} WkstaUserInfo;
|
} WkstaUserInfo;
|
||||||
} WKSTA_USER_ENUM_STRUCT, *PWKSTA_USER_ENUM_STRUCT, *LPWKSTA_USER_ENUM_STRUCT;
|
} WKSTA_USER_ENUM_STRUCT, *PWKSTA_USER_ENUM_STRUCT, *LPWKSTA_USER_ENUM_STRUCT;
|
||||||
|
*/
|
||||||
|
typedef struct _WKSTA_USER_ENUM_STRUCT
|
||||||
|
{
|
||||||
|
unsigned long Level;
|
||||||
|
[switch_is(Level)] union _WKSTA_USER_ENUM_UNION
|
||||||
|
{
|
||||||
|
[case(0)] WKSTA_USER_INFO_0_CONTAINER Level0;
|
||||||
|
[case(1)] WKSTA_USER_INFO_1_CONTAINER Level1;
|
||||||
|
[default] ;
|
||||||
|
} WkstaUserInfo;
|
||||||
|
} WKSTA_USER_ENUM_STRUCT, *PWKSTA_USER_ENUM_STRUCT, *LPWKSTA_USER_ENUM_STRUCT;
|
||||||
|
|
||||||
typedef struct _WKSTA_TRANSPORT_INFO_0_CONTAINER
|
typedef struct _WKSTA_TRANSPORT_INFO_0_CONTAINER
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue