WINPR_API BOOL WTSRegisterWtsApiFunctionTable(PWtsApiFunctionTable table);
WINPR_API const CHAR* WTSErrorToString(UINT error);
+WINPR_API const CHAR* WTSSessionStateToString(WTS_CONNECTSTATE_CLASS state);
#ifdef __cplusplus
}
# See the License for the specific language governing permissions and
# limitations under the License.
-winpr_module_add(wtsapi.c
- wtsapi.h)
+winpr_module_add(wtsapi.c)
if(WIN32)
winpr_module_add(wtsapi_win32.c wtsapi_win32.h)
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiEnumerateProcesses(int argc, char* argv[])
{
DWORD count;
BOOL bSuccess;
HANDLE hServer;
- PWTS_PROCESS_INFO pProcessInfo;
+ PWTS_PROCESS_INFOA pProcessInfo;
+
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#endif
hServer = WTS_CURRENT_SERVER_HANDLE;
count = 0;
pProcessInfo = NULL;
- bSuccess = WTSEnumerateProcesses(hServer, 0, 1, &pProcessInfo, &count);
+ bSuccess = WTSEnumerateProcessesA(hServer, 0, 1, &pProcessInfo, &count);
if (!bSuccess)
{
- printf("WTSEnumerateProcesses failed: %d\n", (int) GetLastError());
- //return -1;
+ printf("WTSEnumerateProcesses failed: %u\n", GetLastError());
+ return -1;
+ }
+
+#if 0
+ {
+ DWORD i;
+ printf("WTSEnumerateProcesses enumerated %u processs:\n", count);
+ for (i = 0; i < count; i++)
+ printf("\t[%u]: %s (%lu)\n", i, pProcessInfo[i].pProcessName, pProcessInfo[i].ProcessId);
}
+#endif
WTSFreeMemory(pProcessInfo);
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiEnumerateSessions(int argc, char* argv[])
{
DWORD count;
BOOL bSuccess;
HANDLE hServer;
- PWTS_SESSION_INFO pSessionInfo;
+ PWTS_SESSION_INFOA pSessionInfo;
+
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#endif
hServer = WTS_CURRENT_SERVER_HANDLE;
count = 0;
pSessionInfo = NULL;
- bSuccess = WTSEnumerateSessions(hServer, 0, 1, &pSessionInfo, &count);
+ bSuccess = WTSEnumerateSessionsA(hServer, 0, 1, &pSessionInfo, &count);
if (!bSuccess)
{
for (index = 0; index < count; index++)
{
- printf("[%d] SessionId: %d State: %d\n", (int) index,
- (int) pSessionInfo[index].SessionId,
- (int) pSessionInfo[index].State);
+ printf("[%u] SessionId: %u WinstationName: '%s' State: %s (%u)\n", index,
+ pSessionInfo[index].SessionId,
+ pSessionInfo[index].pWinStationName,
+ WTSSessionStateToString(pSessionInfo[index].State),
+ pSessionInfo[index].State);
}
WTSFreeMemory(pSessionInfo);
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiQuerySessionInformation(int argc, char* argv[])
{
- DWORD index;
+ DWORD index, i;
DWORD count;
BOOL bSuccess;
HANDLE hServer;
LPSTR pBuffer;
DWORD sessionId;
DWORD bytesReturned;
- PWTS_SESSION_INFO pSessionInfo;
+ PWTS_SESSION_INFOA pSessionInfo;
+
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#endif
hServer = WTS_CURRENT_SERVER_HANDLE;
count = 0;
pSessionInfo = NULL;
- bSuccess = WTSEnumerateSessions(hServer, 0, 1, &pSessionInfo, &count);
+ bSuccess = WTSEnumerateSessionsA(hServer, 0, 1, &pSessionInfo, &count);
if (!bSuccess)
{
sessionId = pSessionInfo[index].SessionId;
- printf("[%d] SessionId: %d State: %d\n", (int) index,
- (int) pSessionInfo[index].SessionId,
- (int) pSessionInfo[index].State);
+ printf("[%u] SessionId: %u State: %s (%u) WinstationName: '%s'\n",
+ index,
+ pSessionInfo[index].SessionId,
+ WTSSessionStateToString(pSessionInfo[index].State),
+ pSessionInfo[index].State,
+ pSessionInfo[index].pWinStationName);
/* WTSUserName */
}
Username = (char*) pBuffer;
- printf("\tWTSUserName: %s\n", Username);
+ printf("\tWTSUserName: '%s'\n", Username);
/* WTSDomainName */
}
Domain = (char*) pBuffer;
- printf("\tWTSDomainName: %s\n", Domain);
+ printf("\tWTSDomainName: '%s'\n", Domain);
/* WTSConnectState */
}
ConnectState = *((WTS_CONNECTSTATE_CLASS*) pBuffer);
- printf("\tWTSConnectState: %d\n", (int) ConnectState);
+ printf("\tWTSConnectState: %u (%s)\n", ConnectState, WTSSessionStateToString(ConnectState));
/* WTSClientBuildNumber */
}
ClientBuildNumber = *((ULONG*) pBuffer);
- printf("\tWTSClientBuildNumber: %d\n", (int) ClientBuildNumber);
+ printf("\tWTSClientBuildNumber: %u\n", ClientBuildNumber);
/* WTSClientName */
}
ClientName = (char*) pBuffer;
- printf("\tWTSClientName: %s\n", ClientName);
+ printf("\tWTSClientName: '%s'\n", ClientName);
/* WTSClientProductId */
}
ClientProductId = *((USHORT*) pBuffer);
- printf("\tWTSClientProductId: %d\n", (int) ClientProductId);
+ printf("\tWTSClientProductId: %u\n", ClientProductId);
/* WTSClientHardwareId */
}
ClientHardwareId = *((ULONG*) pBuffer);
- printf("\tWTSClientHardwareId: %d\n", (int) ClientHardwareId);
+ printf("\tWTSClientHardwareId: %u\n", ClientHardwareId);
/* WTSClientAddress */
}
ClientAddress = (PWTS_CLIENT_ADDRESS) pBuffer;
- printf("\tWTSClientAddress: AddressFamily: %d\n",
- (int) ClientAddress->AddressFamily);
+ printf("\tWTSClientAddress: AddressFamily: %u Address: ",
+ ClientAddress->AddressFamily);
+ for (i = 0; i < sizeof(ClientAddress->Address); i++)
+ printf("%02X", ClientAddress->Address[i]);
+ printf("\n");
+
/* WTSClientDisplay */
}
ClientDisplay = (PWTS_CLIENT_DISPLAY) pBuffer;
- printf("\tWTSClientDisplay: HorizontalResolution: %d VerticalResolution: %d ColorDepth: %d\n",
- (int) ClientDisplay->HorizontalResolution, (int) ClientDisplay->VerticalResolution,
- (int) ClientDisplay->ColorDepth);
+ printf("\tWTSClientDisplay: HorizontalResolution: %u VerticalResolution: %u ColorDepth: %u\n",
+ ClientDisplay->HorizontalResolution, ClientDisplay->VerticalResolution,
+ ClientDisplay->ColorDepth);
/* WTSClientProtocolType */
}
ClientProtocolType = *((USHORT*) pBuffer);
- printf("\tWTSClientProtocolType: %d\n", (int) ClientProtocolType);
+ printf("\tWTSClientProtocolType: %u\n", ClientProtocolType);
}
WTSFreeMemory(pSessionInfo);
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiSessionNotification(int argc, char* argv[])
{
- HWND hWnd;
+ HWND hWnd = NULL;
BOOL bSuccess;
DWORD dwFlags;
- hWnd = NULL;
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#else
+ /* We create a message-only window and use the predefined class name "STATIC" for simplicity */
+ hWnd = CreateWindowA("STATIC", "TestWtsApiSessionNotification", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
+ if (!hWnd)
+ {
+ printf("%s: error creating message-only window: %u\n", __FUNCTION__, GetLastError());
+ return -1;
+ }
+#endif
+
dwFlags = NOTIFY_FOR_ALL_SESSIONS;
bSuccess = WTSRegisterSessionNotification(hWnd, dwFlags);
if (!bSuccess)
{
- printf("WTSRegisterSessionNotification failed: %d\n", (int) GetLastError());
- //return -1;
+ printf("%s: WTSRegisterSessionNotification failed: %u\n", __FUNCTION__, GetLastError());
+ return -1;
}
bSuccess = WTSUnRegisterSessionNotification(hWnd);
+#ifdef _WIN32
+ if (hWnd)
+ {
+ DestroyWindow(hWnd);
+ hWnd = NULL;
+ }
+#endif
+
if (!bSuccess)
{
- printf("WTSUnRegisterSessionNotification failed: %d\n", (int) GetLastError());
- //return -1;
+ printf("%s: WTSUnRegisterSessionNotification failed: %u\n", __FUNCTION__, GetLastError());
+ return -1;
}
return 0;
-
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiShutdownSystem(int argc, char* argv[])
{
HANDLE hServer;
DWORD ShutdownFlag;
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#endif
+
hServer = WTS_CURRENT_SERVER_HANDLE;
ShutdownFlag = WTS_WSD_SHUTDOWN;
if (!bSuccess)
{
printf("WTSShutdownSystem failed: %d\n", (int) GetLastError());
- //return -1;
+ return -1;
}
return 0;
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/wtsapi.h>
+#include <winpr/environment.h>
int TestWtsApiWaitSystemEvent(int argc, char* argv[])
{
DWORD eventMask;
DWORD eventFlags;
+#ifndef _WIN32
+ if (!GetEnvironmentVariableA("WTSAPI_LIBRARY", NULL, 0))
+ {
+ printf("%s: No RDS environment detected, skipping test\n", __FUNCTION__);
+ return 0;
+ }
+#endif
+
hServer = WTS_CURRENT_SERVER_HANDLE;
eventMask = WTS_EVENT_ALL;
if (!bSuccess)
{
printf("WTSWaitSystemEvent failed: %d\n", (int) GetLastError());
- //return -1;
+ return -1;
}
return 0;
#include <winpr/wtsapi.h>
-#include "wtsapi.h"
-
#ifdef _WIN32
#include "wtsapi_win32.h"
#endif
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464/
*/
-void InitializeWtsApiStubs(void);
-
-static BOOL g_Initialized = FALSE;
static HMODULE g_WtsApiModule = NULL;
static PWtsApiFunctionTable g_WtsApi = NULL;
#define WTSAPI32_LOAD_PROC(_name, _type) \
WtsApi32_WtsApiFunctionTable.p ## _name = (## _type) GetProcAddress(g_WtsApi32Module, "WTS" #_name);
-int WtsApi32_InitializeWtsApi(void)
+BOOL WtsApi32_InitializeWtsApi(void)
{
g_WtsApi32Module = LoadLibraryA("wtsapi32.dll");
if (!g_WtsApi32Module)
- return -1;
+ return FALSE;
#ifdef _WIN32
WTSAPI32_LOAD_PROC(StopRemoteControlSession, WTS_STOP_REMOTE_CONTROL_SESSION_FN);
g_WtsApi = &WtsApi32_WtsApiFunctionTable;
- return 1;
+ return TRUE;
}
/* WtsApi Functions */
+static BOOL CALLBACK InitializeWtsApiStubs(PINIT_ONCE once, PVOID param, PVOID *context);
+static INIT_ONCE wtsapiInitOnce = INIT_ONCE_STATIC_INIT;
+
+#define WTSAPI_STUB_CALL_VOID(_name, ...) \
+ InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, NULL, NULL); \
+ if (!g_WtsApi || !g_WtsApi->p ## _name) \
+ return; \
+ g_WtsApi->p ## _name ( __VA_ARGS__ )
+
+#define WTSAPI_STUB_CALL_BOOL(_name, ...) \
+ InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, NULL, NULL); \
+ if (!g_WtsApi || !g_WtsApi->p ## _name) \
+ return FALSE; \
+ return g_WtsApi->p ## _name ( __VA_ARGS__ )
+
+#define WTSAPI_STUB_CALL_HANDLE(_name, ...) \
+ InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, NULL, NULL); \
+ if (!g_WtsApi || !g_WtsApi->p ## _name) \
+ return NULL; \
+ return g_WtsApi->p ## _name ( __VA_ARGS__ )
+
+
BOOL WINAPI WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
{
WTSAPI_STUB_CALL_BOOL(StartRemoteControlSessionW, pTargetServerName, TargetLogonId, HotkeyVk, HotkeyModifiers);
DWORD WINAPI WTSGetActiveConsoleSessionId(void)
{
- if (!g_Initialized)
- InitializeWtsApiStubs();
+ InitOnceExecuteOnce(&wtsapiInitOnce, InitializeWtsApiStubs, NULL, NULL);
if (!g_WtsApi || !g_WtsApi->pGetActiveConsoleSessionId)
return 0xFFFFFFFF;
}
}
+const CHAR* WTSSessionStateToString(WTS_CONNECTSTATE_CLASS state)
+{
+ switch (state)
+ {
+ case WTSActive:
+ return "WTSActive";
+ case WTSConnected:
+ return "WTSConnected";
+ case WTSConnectQuery:
+ return "WTSConnectQuery";
+ case WTSShadow:
+ return "WTSShadow";
+ case WTSDisconnected:
+ return "WTSDisconnected";
+ case WTSIdle:
+ return "WTSIdle";
+ case WTSListen:
+ return "WTSListen";
+ case WTSReset:
+ return "WTSReset";
+ case WTSDown:
+ return "WTSDown";
+ case WTSInit:
+ return "WTSInit";
+ }
+ return "INVALID_STATE";
+}
+
BOOL WTSRegisterWtsApiFunctionTable(PWtsApiFunctionTable table)
{
g_WtsApi = table;
- g_Initialized = TRUE;
return TRUE;
}
return TRUE;
}
-void InitializeWtsApiStubs_Env()
+static void InitializeWtsApiStubs_Env()
{
DWORD nSize;
char *env = NULL;
#define FREERDS_LIBRARY_NAME "libfreerds-fdsapi.so"
-void InitializeWtsApiStubs_FreeRDS()
+static void InitializeWtsApiStubs_FreeRDS()
{
wIniFile* ini;
const char* prefix;
IniFile_Free(ini);
}
-void InitializeWtsApiStubs(void)
-{
- if (g_Initialized)
- return;
- g_Initialized = TRUE;
+static BOOL CALLBACK InitializeWtsApiStubs(PINIT_ONCE once, PVOID param, PVOID *context)
+{
InitializeWtsApiStubs_Env();
#ifdef _WIN32
if (!g_WtsApi)
InitializeWtsApiStubs_FreeRDS();
- return;
+ return TRUE;
}
+++ /dev/null
-/**
- * WinPR: Windows Portable Runtime
- * Windows Terminal Services API
- *
- * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
- *
- * 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.
- */
-
-#ifndef WINPR_WTSAPI_PRIVATE_H
-#define WINPR_WTSAPI_PRIVATE_H
-
-#define WTSAPI_STUB_CALL_VOID(_name, ...) \
- if (!g_Initialized) \
- InitializeWtsApiStubs(); \
- if (!g_WtsApi || !g_WtsApi->p ## _name) \
- return; \
- g_WtsApi->p ## _name ( __VA_ARGS__ )
-
-#define WTSAPI_STUB_CALL_BOOL(_name, ...) \
- if (!g_Initialized) \
- InitializeWtsApiStubs(); \
- if (!g_WtsApi || !g_WtsApi->p ## _name) \
- return FALSE; \
- return g_WtsApi->p ## _name ( __VA_ARGS__ )
-
-#define WTSAPI_STUB_CALL_HANDLE(_name, ...) \
- if (!g_Initialized) \
- InitializeWtsApiStubs(); \
- if (!g_WtsApi || !g_WtsApi->p ## _name) \
- return NULL; \
- return g_WtsApi->p ## _name ( __VA_ARGS__ )
-
-#endif /* WINPR_WTSAPI_PRIVATE_H */
#include "wtsapi_win32.h"
-#include "wtsapi.h"
#include "../log.h"
#define WTSAPI_CHANNEL_MAGIC 0x44484356
BOOL WINAPI Win32_WTSVirtualChannelClose(HANDLE hChannel);
+
+/**
+ * NOTE !!
+ * An application using the WinPR wtsapi frees memory via WTSFreeMemory, which
+ * might be mapped to Win32_WTSFreeMemory. Latter does not know if the passed
+ * pointer was allocated by a function in wtsapi32.dll or in some internal
+ * code below. The WTSFreeMemory implementation in all Windows wtsapi32.dll
+ * versions up to Windows 10 uses LocalFree since all its allocating functions
+ * use LocalAlloc() internally.
+ * For that reason we also have to use LocalAlloc() for any memory returned by
+ * our WinPR wtsapi functions.
+ *
+ * To be safe we only use the _wts_malloc, _wts_calloc, _wts_free wrappers
+ * for memory managment the code below.
+ */
+
+static void *_wts_malloc(size_t size)
+{
+ return (PVOID)LocalAlloc(LMEM_FIXED, size);
+}
+
+static void *_wts_calloc(size_t nmemb, size_t size)
+{
+ return (PVOID)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, nmemb * size);
+}
+
+static void _wts_free(void* ptr)
+{
+ LocalFree((HLOCAL)ptr);
+}
+
BOOL Win32_WTSVirtualChannelReadAsync(WTSAPI_CHANNEL* pChannel)
{
BOOL status = TRUE;
HANDLE hFile;
HANDLE hChannel;
WTSAPI_CHANNEL* pChannel;
+ size_t virtualNameLen;
+
+ virtualNameLen = pVirtualName ? strlen(pVirtualName) : 0;
- if (!pVirtualName)
+ if (!virtualNameLen)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
+ if (!pfnWinStationVirtualOpenEx)
+ {
+ SetLastError(ERROR_INVALID_FUNCTION);
+ return NULL;
+ }
+
hFile = pfnWinStationVirtualOpenEx(hServer, SessionId, pVirtualName, flags);
if (!hFile)
return NULL;
- pChannel = (WTSAPI_CHANNEL*) calloc(1, sizeof(WTSAPI_CHANNEL));
+ pChannel = (WTSAPI_CHANNEL*) _wts_calloc(1, sizeof(WTSAPI_CHANNEL));
if (!pChannel)
{
pChannel->hServer = hServer;
pChannel->SessionId = SessionId;
pChannel->hFile = hFile;
- pChannel->VirtualName = _strdup(pVirtualName);
+ pChannel->VirtualName = _wts_calloc(1, virtualNameLen + 1);
if (!pChannel->VirtualName)
{
CloseHandle(hFile);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- free(pChannel);
+ _wts_free(pChannel);
return NULL;
}
+ memcpy(pChannel->VirtualName, pVirtualName, virtualNameLen);
pChannel->flags = flags;
pChannel->dynamic = (flags & WTS_CHANNEL_OPTION_DYNAMIC) ? TRUE : FALSE;
pChannel->showProtocol = pChannel->dynamic;
pChannel->readSize = CHANNEL_PDU_LENGTH;
- pChannel->readBuffer = (BYTE*) malloc(pChannel->readSize);
+ pChannel->readBuffer = (BYTE*) _wts_malloc(pChannel->readSize);
pChannel->header = (CHANNEL_PDU_HEADER*) pChannel->readBuffer;
pChannel->chunk = &(pChannel->readBuffer[sizeof(CHANNEL_PDU_HEADER)]);
if (pChannel->VirtualName)
{
- free(pChannel->VirtualName);
+ _wts_free(pChannel->VirtualName);
pChannel->VirtualName = NULL;
}
if (pChannel->readBuffer)
{
- free(pChannel->readBuffer);
+ _wts_free(pChannel->readBuffer);
pChannel->readBuffer = NULL;
}
pChannel->magic = 0;
- free(pChannel);
+ _wts_free(pChannel);
return status;
}
else if (WtsVirtualClass == WTSVirtualFileHandle)
{
*pBytesReturned = sizeof(HANDLE);
- *ppBuffer = calloc(1, *pBytesReturned);
+ *ppBuffer = _wts_calloc(1, *pBytesReturned);
if (*ppBuffer == NULL)
{
else if (WtsVirtualClass == WTSVirtualEventHandle)
{
*pBytesReturned = sizeof(HANDLE);
- *ppBuffer = calloc(1, *pBytesReturned);
+ *ppBuffer = _wts_calloc(1, *pBytesReturned);
if (*ppBuffer == NULL)
{
VOID WINAPI Win32_WTSFreeMemory(PVOID pMemory)
{
- free(pMemory);
+ _wts_free(pMemory);
}
BOOL WINAPI Win32_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
{
- return TRUE;
+ return FALSE;
}
BOOL WINAPI Win32_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
return WTSFreeMemoryExW(WTSTypeClass, pMemory, NumberOfEntries);
}
-int Win32_InitializeWinSta(PWtsApiFunctionTable pWtsApi)
+BOOL Win32_InitializeWinSta(PWtsApiFunctionTable pWtsApi)
{
g_WinStaModule = LoadLibraryA("winsta.dll");
if (!g_WinStaModule)
- return -1;
+ return FALSE;
pfnWinStationVirtualOpen = (fnWinStationVirtualOpen) GetProcAddress(g_WinStaModule, "WinStationVirtualOpen");
pfnWinStationVirtualOpenEx = (fnWinStationVirtualOpenEx) GetProcAddress(g_WinStaModule, "WinStationVirtualOpenEx");
- if (!pfnWinStationVirtualOpenEx)
- return -1;
+ if (!pfnWinStationVirtualOpen | !pfnWinStationVirtualOpenEx)
+ return FALSE;
pWtsApi->pVirtualChannelOpen = Win32_WTSVirtualChannelOpen;
pWtsApi->pVirtualChannelOpenEx = Win32_WTSVirtualChannelOpenEx;
//pWtsApi->pFreeMemoryExW = Win32_WTSFreeMemoryExW;
//pWtsApi->pFreeMemoryExA = Win32_WTSFreeMemoryExA;
- return 1;
+ return TRUE;
}
#include <winpr/wtsapi.h>
-int Win32_InitializeWinSta(PWtsApiFunctionTable pWtsApi);
+BOOL Win32_InitializeWinSta(PWtsApiFunctionTable pWtsApi);
#endif /* WINPR_WTSAPI_WIN32_PRIVATE_H */