[WKSSVC][NETAPI32][IDL] Implement NetWkstaUserGetInfo using the workstation service

This commit is contained in:
Eric Kohl 2024-12-28 21:14:38 +01:00
parent 0bb830022c
commit 45b008dd23
5 changed files with 209 additions and 159 deletions

View file

@ -17,7 +17,10 @@
#include <ntsecapi.h>
#include <ntmsv1_0.h>
//#include <ntstatus.h>
#include <ndk/obfuncs.h>
#include <ndk/psfuncs.h>
#include <ndk/rtlfuncs.h>
#include <ndk/sefuncs.h>
#include <wkssvc_s.h>

View file

@ -77,6 +77,55 @@ void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
}
static
NET_API_STATUS
NetpGetClientLogonId(
_Out_ PLUID LogonId)
{
HANDLE ThreadToken = NULL;
TOKEN_STATISTICS Statistics;
ULONG Length;
NTSTATUS NtStatus;
NET_API_STATUS ApiStatus = NERR_Success;
ApiStatus = RpcImpersonateClient(NULL);
if (ApiStatus != NERR_Success)
return ApiStatus;
NtStatus = NtOpenThreadToken(NtCurrentThread(),
TOKEN_QUERY,
TRUE,
&ThreadToken);
if (!NT_SUCCESS(NtStatus))
{
ApiStatus = RtlNtStatusToDosError(NtStatus);
goto done;
}
NtStatus = NtQueryInformationToken(ThreadToken,
TokenStatistics,
(PVOID)&Statistics,
sizeof(Statistics),
&Length);
if (!NT_SUCCESS(NtStatus))
{
ApiStatus = RtlNtStatusToDosError(NtStatus);
goto done;
}
FIXME("Client LUID: %lx\n", Statistics.AuthenticationId.LowPart);
RtlCopyLuid(LogonId, &Statistics.AuthenticationId);
done:
if (ThreadToken != NULL)
NtClose(ThreadToken);
RpcRevertToSelf();
return ApiStatus;
}
/* Function 0 */
unsigned long
__stdcall
@ -384,12 +433,149 @@ __stdcall
NetrWkstaUserGetInfo(
WKSSVC_IDENTIFY_HANDLE Unused,
unsigned long Level,
LPWKSTA_USER_INFO UserInfo)
LPWKSTA_USER_INFO *UserInfo)
{
FIXME("(%s, %d, %p)\n", debugstr_w(Unused), Level, UserInfo);
MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;
PMSV1_0_GETUSERINFO_RESPONSE UserInfoResponseBuffer = NULL;
DWORD UserInfoResponseBufferSize = 0;
NTSTATUS Status, ProtocolStatus;
LUID LogonId;
PWKSTA_USER_INFO pUserInfo;
DWORD dwResult = NERR_Success;
UNIMPLEMENTED;
return 0;
TRACE("NetrWkstaUserGetInfo(%s, %d, %p)\n", debugstr_w(Unused), Level, UserInfo);
if (Unused != NULL)
return ERROR_INVALID_PARAMETER;
if (Level > 1 && Level != 1101)
return ERROR_INVALID_LEVEL;
if (Level != 1101)
{
dwResult = NetpGetClientLogonId(&LogonId);
if (dwResult != NERR_Success)
{
ERR("NetpGetClientLogonId() failed (%u)\n", dwResult);
return dwResult;
}
TRACE("LogonId: 0x%08lx\n", LogonId.LowPart);
UserInfoRequest.MessageType = MsV1_0GetUserInfo;
UserInfoRequest.LogonId = LogonId;
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))
{
ERR("\n");
return RtlNtStatusToDosError(Status);
}
TRACE("UserName: %wZ\n", &UserInfoResponseBuffer->UserName);
TRACE("LogonDomain: %wZ\n", &UserInfoResponseBuffer->LogonDomainName);
TRACE("LogonServer: %wZ\n", &UserInfoResponseBuffer->LogonServer);
}
switch (Level)
{
case 0:
pUserInfo = midl_user_allocate(sizeof(WKSTA_USER_INFO_0));
if (pUserInfo == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo, sizeof(WKSTA_USER_INFO_0));
/* User Name */
pUserInfo->UserInfo0.wkui0_username = midl_user_allocate(UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
if (pUserInfo->UserInfo0.wkui0_username == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo->UserInfo0.wkui0_username, UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
CopyMemory(pUserInfo->UserInfo0.wkui0_username, UserInfoResponseBuffer->UserName.Buffer, UserInfoResponseBuffer->UserName.Length);
*UserInfo = pUserInfo;
break;
case 1:
pUserInfo = midl_user_allocate(sizeof(WKSTA_USER_INFO_1));
if (pUserInfo == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo, sizeof(WKSTA_USER_INFO_1));
/* User Name */
pUserInfo->UserInfo1.wkui1_username = midl_user_allocate(UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
if (pUserInfo->UserInfo1.wkui1_username == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo->UserInfo1.wkui1_username, UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
CopyMemory(pUserInfo->UserInfo1.wkui1_username, UserInfoResponseBuffer->UserName.Buffer, UserInfoResponseBuffer->UserName.Length);
/* Logon Domain Name */
pUserInfo->UserInfo1.wkui1_logon_domain = midl_user_allocate(UserInfoResponseBuffer->LogonDomainName.Length + sizeof(WCHAR));
if (pUserInfo->UserInfo1.wkui1_logon_domain == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo->UserInfo1.wkui1_logon_domain, UserInfoResponseBuffer->LogonDomainName.Length + sizeof(WCHAR));
CopyMemory(pUserInfo->UserInfo1.wkui1_logon_domain, UserInfoResponseBuffer->LogonDomainName.Buffer, UserInfoResponseBuffer->LogonDomainName.Length);
/* FIXME: wkui1_oth_domains */
/* Logon Server */
pUserInfo->UserInfo1.wkui1_logon_server = midl_user_allocate(UserInfoResponseBuffer->LogonServer.Length + sizeof(WCHAR));
if (pUserInfo->UserInfo1.wkui1_logon_server == NULL)
{
ERR("\n");
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
ZeroMemory(pUserInfo->UserInfo1.wkui1_logon_server, UserInfoResponseBuffer->LogonServer.Length + sizeof(WCHAR));
CopyMemory(pUserInfo->UserInfo1.wkui1_logon_server, UserInfoResponseBuffer->LogonServer.Buffer, UserInfoResponseBuffer->LogonServer.Length);
*UserInfo = pUserInfo;
break;
case 1101:
/* FIXME: wkui1101_oth_domains */
break;
default:
ERR("\n");
break;
}
if (UserInfoResponseBuffer)
LsaFreeReturnBuffer(UserInfoResponseBuffer);
return dwResult;
}

View file

@ -273,152 +273,6 @@ NetWkstaTransportEnum(LMSTR ServerName, DWORD level, PBYTE* pbuf,
}
/************************************************************
* NetWkstaUserGetInfo (NETAPI32.@)
*/
NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level,
PBYTE* bufptr)
{
NET_API_STATUS nastatus;
TRACE("(%s, %d, %p)\n", debugstr_w(reserved), level, bufptr);
switch (level)
{
case 0:
{
PWKSTA_USER_INFO_0 ui;
DWORD dwSize = UNLEN + 1;
/* set up buffer */
nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
(LPVOID *) bufptr);
if (nastatus != NERR_Success)
return ERROR_NOT_ENOUGH_MEMORY;
ui = (PWKSTA_USER_INFO_0) *bufptr;
ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
/* get data */
if (!GetUserNameW(ui->wkui0_username, &dwSize))
{
NetApiBufferFree(ui);
return ERROR_NOT_ENOUGH_MEMORY;
}
else {
nastatus = NetApiBufferReallocate(
*bufptr, sizeof(WKSTA_USER_INFO_0) +
(lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
(LPVOID *) bufptr);
if (nastatus != NERR_Success)
{
NetApiBufferFree(ui);
return nastatus;
}
ui = (PWKSTA_USER_INFO_0) *bufptr;
ui->wkui0_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
}
break;
}
case 1:
{
PWKSTA_USER_INFO_1 ui;
PWKSTA_USER_INFO_0 ui0;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_HANDLE PolicyHandle;
PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
NTSTATUS NtStatus;
/* sizes of the field buffers in WCHARS */
int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
FIXME("Level 1 processing is partially implemented\n");
oth_domains_sz = 1;
logon_server_sz = 1;
/* get some information first to estimate size of the buffer */
ui0 = NULL;
nastatus = NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
if (nastatus != NERR_Success)
return nastatus;
username_sz = lstrlenW(ui0->wkui0_username) + 1;
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
POLICY_VIEW_LOCAL_INFORMATION,
&PolicyHandle);
if (NtStatus != STATUS_SUCCESS)
{
TRACE("LsaOpenPolicyFailed with NT status %x\n",
LsaNtStatusToWinError(NtStatus));
NetApiBufferFree(ui0);
return ERROR_NOT_ENOUGH_MEMORY;
}
LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
(PVOID*) &DomainInfo);
logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
LsaClose(PolicyHandle);
/* set up buffer */
nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
(username_sz + logon_domain_sz +
oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
(LPVOID *) bufptr);
if (nastatus != NERR_Success) {
NetApiBufferFree(ui0);
return nastatus;
}
ui = (WKSTA_USER_INFO_1 *) *bufptr;
ui->wkui1_username = (LMSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
ui->wkui1_logon_domain = (LMSTR) (
((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
ui->wkui1_oth_domains = (LMSTR) (
((PBYTE) ui->wkui1_logon_domain) +
logon_domain_sz * sizeof(WCHAR));
ui->wkui1_logon_server = (LMSTR) (
((PBYTE) ui->wkui1_oth_domains) +
oth_domains_sz * sizeof(WCHAR));
/* get data */
lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
NetApiBufferFree(ui0);
lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
logon_domain_sz);
LsaFreeMemory(DomainInfo);
/* FIXME. Not implemented. Populated with empty strings */
ui->wkui1_oth_domains[0] = 0;
ui->wkui1_logon_server[0] = 0;
break;
}
case 1101:
{
PWKSTA_USER_INFO_1101 ui;
DWORD dwSize = 1;
FIXME("Stub. Level 1101 processing is not implemented\n");
/* FIXME see also wkui1_oth_domains for level 1 */
/* set up buffer */
nastatus = NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
(LPVOID *) bufptr);
if (nastatus != NERR_Success)
return nastatus;
ui = (PWKSTA_USER_INFO_1101) *bufptr;
ui->wkui1101_oth_domains = (LMSTR)(ui + 1);
/* get data */
ui->wkui1101_oth_domains[0] = 0;
break;
}
default:
TRACE("Invalid level %d is specified\n", level);
return ERROR_INVALID_LEVEL;
}
return NERR_Success;
}
/************************************************************
* NetpGetComputerName (NETAPI32.@)
*/

View file

@ -1116,20 +1116,19 @@ NetWkstaUserEnum(
}
#if 0
NET_API_STATUS
WINAPI
NetWkstaUserGetInfo(
LPWSTR reserved,
_In_ LPWSTR reserved,
_In_ DWORD level,
_Out_ PBYTE *bufptr)
_Out_ LPBYTE *bufptr)
{
NET_API_STATUS status;
TRACE("NetWkstaUserGetInfo(%s, %d, %p)\n",
debugstr_w(reserved), level, bufptr);
if (reserved != NULL)
if (reserved != NULL || bufptr == NULL)
return ERROR_INVALID_PARAMETER;
*bufptr = NULL;
@ -1138,7 +1137,7 @@ NetWkstaUserGetInfo(
{
status = NetrWkstaUserGetInfo(NULL,
level,
(LPWKSTA_USER_INFO)bufptr);
(LPWKSTA_USER_INFO*)bufptr);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -1148,13 +1147,12 @@ NetWkstaUserGetInfo(
return status;
}
#endif
NET_API_STATUS
WINAPI
NetWkstaUserSetInfo(
LPWSTR reserved,
_In_ LPWSTR reserved,
_In_ DWORD level,
_In_ LPBYTE buf,
_Out_ LPDWORD parm_err)

View file

@ -180,7 +180,7 @@ typedef struct _WKSTA_USER_INFO_1101
{
[string] wchar_t *wkui1101_oth_domains;
} WKSTA_USER_INFO_1101, *PWKSTA_USER_INFO_1101, *LPWKSTA_USER_INFO_1101;
/*
typedef [switch_type(unsigned long)] union _WKSTA_USER_INFO
{
[case(0)] LPWKSTA_USER_INFO_0 UserInfo0;
@ -188,6 +188,14 @@ typedef [switch_type(unsigned long)] union _WKSTA_USER_INFO
[case(1101)] LPWKSTA_USER_INFO_1101 UserInfo1101;
[default] ;
} WKSTA_USER_INFO, *PWKSTA_USER_INFO, *LPWKSTA_USER_INFO;
*/
typedef [switch_type(unsigned long)] union _WKSTA_USER_INFO
{
[case(0)] WKSTA_USER_INFO_0 UserInfo0;
[case(1)] WKSTA_USER_INFO_1 UserInfo1;
[case(1101)] WKSTA_USER_INFO_1101 UserInfo1101;
[default] ;
} WKSTA_USER_INFO, *PWKSTA_USER_INFO, *LPWKSTA_USER_INFO;
typedef struct _WKSTA_TRANSPORT_INFO_0
{
@ -407,7 +415,8 @@ interface wkssvc
NetrWkstaUserGetInfo(
[in, string, unique] WKSSVC_IDENTIFY_HANDLE Unused,
[in] unsigned long Level,
[out, switch_is(Level)] LPWKSTA_USER_INFO UserInfo);
[out, switch_is(Level)] LPWKSTA_USER_INFO *UserInfo);
// [out, switch_is(Level)] LPWKSTA_USER_INFO UserInfo);
/* Function 4 */
unsigned long