From 45b008dd2318b1d3d5b8dfbe3be35a5c0425fbd6 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 28 Dec 2024 21:14:38 +0100 Subject: [PATCH] [WKSSVC][NETAPI32][IDL] Implement NetWkstaUserGetInfo using the workstation service --- base/services/wkssvc/precomp.h | 3 + base/services/wkssvc/rpcserver.c | 194 ++++++++++++++++++++++++++++- dll/win32/netapi32/wksta.c | 146 ---------------------- dll/win32/netapi32/wksta_new.c | 12 +- sdk/include/reactos/idl/wkssvc.idl | 13 +- 5 files changed, 209 insertions(+), 159 deletions(-) diff --git a/base/services/wkssvc/precomp.h b/base/services/wkssvc/precomp.h index f2fbde4e433..71a60f4ea50 100644 --- a/base/services/wkssvc/precomp.h +++ b/base/services/wkssvc/precomp.h @@ -17,7 +17,10 @@ #include #include //#include +#include +#include #include +#include #include diff --git a/base/services/wkssvc/rpcserver.c b/base/services/wkssvc/rpcserver.c index 5088b48f6e9..0c50e494f33 100644 --- a/base/services/wkssvc/rpcserver.c +++ b/base/services/wkssvc/rpcserver.c @@ -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; } diff --git a/dll/win32/netapi32/wksta.c b/dll/win32/netapi32/wksta.c index 8890d7ce7e5..d09c5cb201c 100644 --- a/dll/win32/netapi32/wksta.c +++ b/dll/win32/netapi32/wksta.c @@ -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.@) */ diff --git a/dll/win32/netapi32/wksta_new.c b/dll/win32/netapi32/wksta_new.c index 2739a6c86e0..f427f3cd35f 100644 --- a/dll/win32/netapi32/wksta_new.c +++ b/dll/win32/netapi32/wksta_new.c @@ -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) diff --git a/sdk/include/reactos/idl/wkssvc.idl b/sdk/include/reactos/idl/wkssvc.idl index b4cac96edd3..88cf97f6057 100644 --- a/sdk/include/reactos/idl/wkssvc.idl +++ b/sdk/include/reactos/idl/wkssvc.idl @@ -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