/** * WinPR: Windows Portable Runtime * Windows Terminal Services API * * Copyright 2013 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include /** * Remote Desktop Services API Functions: * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464/ */ #ifndef _WIN32 #include "wtsrpc_c.h" BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) { return RpcStartRemoteControlSession(NULL, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers); } BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers) { return TRUE; } BOOL WTSStopRemoteControlSession(ULONG LogonId) { return RpcStopRemoteControlSession(NULL, LogonId); } BOOL WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword, BOOL bWait) { return RpcConnectSession(NULL, LogonId, TargetLogonId, pPassword, bWait); } BOOL WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait) { return TRUE; } BOOL WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount) { return RpcEnumerateServers(NULL, pDomainName, Reserved, Version, ppServerInfo, pCount); } BOOL WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount) { return TRUE; } HANDLE WTSOpenServerW(LPWSTR pServerName) { return RpcOpenServer(NULL, pServerName); } HANDLE WTSOpenServerA(LPSTR pServerName) { return NULL; } HANDLE WTSOpenServerExW(LPWSTR pServerName) { return RpcOpenServerEx(NULL, pServerName); } HANDLE WTSOpenServerExA(LPSTR pServerName) { return NULL; } VOID WTSCloseServer(HANDLE hServer) { RpcCloseServer(NULL, hServer); } BOOL WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount) { return RpcEnumerateSessions(NULL, hServer, Reserved, Version, ppSessionInfo, pCount); } BOOL WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount) { return TRUE; } BOOL WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount) { return RpcEnumerateSessionsEx(NULL, hServer, pLevel, Filter, ppSessionInfo, pCount); } BOOL WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter, PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount) { return TRUE; } BOOL WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount) { return RpcEnumerateProcesses(NULL, hServer, Reserved, Version, ppProcessInfo, pCount); } BOOL WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount) { return TRUE; } BOOL WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode) { return RpcTerminateProcess(NULL, hServer, ProcessId, ExitCode); } BOOL WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) { return RpcQuerySessionInformation(NULL, hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned); } BOOL WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned) { return TRUE; } BOOL WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned) { return RpcQueryUserConfig(NULL, pServerName, pUserName, WTSConfigClass, ppBuffer, pBytesReturned); } BOOL WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned) { return TRUE; } BOOL WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength) { return RpcSetUserConfig(NULL, pServerName, pUserName, WTSConfigClass, pBuffer, DataLength); } BOOL WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength) { return TRUE; } BOOL WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) { return RpcSendMessage(NULL, hServer, SessionId, pTitle, TitleLength, pMessage, MessageLength, Style, Timeout, pResponse, bWait); } BOOL WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait) { return TRUE; } BOOL WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait) { return RpcDisconnectSession(NULL, hServer, SessionId, bWait); } BOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait) { return RpcLogoffSession(NULL, hServer, SessionId, bWait); } BOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag) { return RpcShutdownSystem(NULL, hServer, ShutdownFlag); } BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags) { return TRUE; } HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName) { HANDLE handle = NULL; if (hServer != WTS_CURRENT_SERVER_HANDLE) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } return handle; } HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) { HANDLE handle = NULL; if (!flags) handle = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, SessionId, pVirtualName); return handle; } BOOL WTSVirtualChannelClose(HANDLE hChannelHandle) { if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* TODO: properly close handle */ return TRUE; } BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) { OVERLAPPED overlapped; if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } overlapped.hEvent = 0; overlapped.Offset = 0; overlapped.OffsetHigh = 0; if (ReadFile(hChannelHandle, Buffer, BufferSize, pBytesRead, &overlapped)) return TRUE; if (GetLastError() != ERROR_IO_PENDING) return FALSE; if (!TimeOut) { CancelIo(hChannelHandle); *pBytesRead = 0; return TRUE; } if (WaitForSingleObject(hChannelHandle, TimeOut) == WAIT_TIMEOUT) { CancelIo(hChannelHandle); SetLastError(ERROR_IO_INCOMPLETE); return FALSE; } return GetOverlappedResult(hChannelHandle, &overlapped, pBytesRead, 0); } BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten) { OVERLAPPED overlapped; if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } overlapped.hEvent = 0; overlapped.Offset = 0; overlapped.OffsetHigh = 0; if (WriteFile(hChannelHandle, Buffer, Length, pBytesWritten, &overlapped)) return TRUE; if (GetLastError() == ERROR_IO_PENDING) return GetOverlappedResult(hChannelHandle, &overlapped, pBytesWritten, 1); return FALSE; } BOOL VirtualChannelIoctl(HANDLE hChannelHandle, ULONG IoControlCode) { DWORD error; NTSTATUS ntstatus; IO_STATUS_BLOCK ioStatusBlock; if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } ntstatus = NtDeviceIoControlFile(hChannelHandle, 0, 0, 0, &ioStatusBlock, IoControlCode, 0, 0, 0, 0); if (ntstatus == STATUS_PENDING) { ntstatus = NtWaitForSingleObject(hChannelHandle, 0, 0); if (ntstatus >= 0) ntstatus = ioStatusBlock.status; } if (ntstatus == STATUS_BUFFER_OVERFLOW) { ntstatus = STATUS_BUFFER_TOO_SMALL; error = RtlNtStatusToDosError(ntstatus); SetLastError(error); return FALSE; } if (ntstatus < 0) { error = RtlNtStatusToDosError(ntstatus); SetLastError(error); return FALSE; } return TRUE; } #define FILE_DEVICE_TERMSRV 0x00000038 BOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle) { return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x0107); } BOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle) { return VirtualChannelIoctl(hChannelHandle, (FILE_DEVICE_TERMSRV << 16) | 0x010B); } BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) { if (!hChannelHandle || (hChannelHandle == INVALID_HANDLE_VALUE)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (WtsVirtualClass == WTSVirtualFileHandle) { *ppBuffer = malloc(sizeof(void*)); CopyMemory(*ppBuffer, &hChannelHandle, sizeof(void*)); *pBytesReturned = sizeof(void*); return TRUE; } return FALSE; } VOID WTSFreeMemory(PVOID pMemory) { free(pMemory); } BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) { BOOL status = TRUE; switch (WTSTypeClass) { case WTSTypeProcessInfoLevel0: break; case WTSTypeProcessInfoLevel1: break; case WTSTypeSessionInfoLevel1: break; default: status = FALSE; break; } return status; } BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) { BOOL status = TRUE; switch (WTSTypeClass) { case WTSTypeProcessInfoLevel0: break; case WTSTypeProcessInfoLevel1: break; case WTSTypeSessionInfoLevel1: break; default: status = FALSE; break; } return status; } BOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) { return RpcRegisterSessionNotification(NULL, hWnd, dwFlags); } BOOL WTSUnRegisterSessionNotification(HWND hWnd) { return RpcUnRegisterSessionNotification(NULL, hWnd); } BOOL WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags) { return RpcRegisterSessionNotificationEx(NULL, hServer, hWnd, dwFlags); } BOOL WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd) { return RpcUnRegisterSessionNotificationEx(NULL, hServer, hWnd); } BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken) { return TRUE; } BOOL WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount) { return TRUE; } BOOL WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPSTR* ppProcessInfo, DWORD* pCount) { return TRUE; } BOOL WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEW pListeners, DWORD* pCount) { return TRUE; } BOOL WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD* pCount) { return TRUE; } BOOL WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer) { return TRUE; } BOOL WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer) { return TRUE; } BOOL WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer, DWORD flag) { return TRUE; } BOOL WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag) { return TRUE; } BOOL WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { return TRUE; } BOOL WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { return TRUE; } BOOL WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPWSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) { return TRUE; } BOOL WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) { return TRUE; } BOOL WTSEnableChildSessions(BOOL bEnable) { return RpcEnableChildSessions(NULL, bEnable); } BOOL WTSIsChildSessionsEnabled(PBOOL pbEnabled) { return RpcIsChildSessionsEnabled(NULL, pbEnabled); } BOOL WTSGetChildSessionId(PULONG pSessionId) { return RpcGetChildSessionId(NULL, pSessionId); } #endif