windows-nt/Source/XPSP1/NT/termsrv/wtsapi/session.c
2020-09-26 16:20:57 +08:00

1508 lines
40 KiB
C

/*******************************************************************************
* session.c
*
* Published Terminal Server APIs
*
* - session routines
*
* Copyright 1998, Citrix Systems Inc.
* Copyright (C) 1997-1999 Microsoft Corp.
/******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddkbd.h>
#include <ntddmou.h>
#include <windows.h>
#include <winbase.h>
#include <winerror.h>
#if(WINVER >= 0x0500)
#include <ntstatus.h>
#include <winsta.h>
#else
#include <citrix\cxstatus.h>
#include <citrix\winsta.h>
#endif
#include <utildll.h>
#include <winsock.h> // for AF_INET, etc.
#include <stdio.h>
#include <stdarg.h>
#include <wtsapi32.h>
/*=============================================================================
== External procedures defined
=============================================================================*/
BOOL WINAPI WTSEnumerateSessionsW( HANDLE, DWORD, DWORD, PWTS_SESSION_INFOW *,
DWORD * );
BOOL WINAPI WTSEnumerateSessionsA( HANDLE, DWORD, DWORD, PWTS_SESSION_INFOA *,
DWORD * );
BOOL WINAPI WTSQuerySessionInformationW( HANDLE, DWORD, WTS_INFO_CLASS,
LPWSTR *, DWORD * );
BOOL WINAPI WTSQuerySessionInformationA( HANDLE, DWORD, WTS_INFO_CLASS,
LPSTR *, DWORD * );
BOOL WINAPI WTSSendMessageW( HANDLE, DWORD, LPWSTR, DWORD, LPWSTR, DWORD,
DWORD, DWORD, DWORD *, BOOL );
BOOL WINAPI WTSSendMessageA( HANDLE, DWORD, LPSTR, DWORD, LPSTR, DWORD,
DWORD, DWORD, DWORD *, BOOL );
BOOL WINAPI WTSDisconnectSession( HANDLE, DWORD, BOOL );
BOOL WINAPI WTSLogoffSession( HANDLE, DWORD, BOOL );
/*=============================================================================
== Internal procedures defined
=============================================================================*/
BOOL _CopyData( PVOID, ULONG, LPWSTR *, DWORD * );
BOOL _CopyStringW( LPWSTR, LPWSTR *, DWORD * );
BOOL _CopyStringA( LPSTR, LPWSTR *, DWORD * );
BOOL _CopyStringWtoA( LPWSTR, LPSTR *, DWORD * );
BOOL ValidateCopyAnsiToUnicode(LPSTR, DWORD, LPWSTR);
BOOL ValidateCopyUnicodeToUnicode(LPWSTR, DWORD, LPWSTR);
/*=============================================================================
== Procedures used
=============================================================================*/
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
/*=============================================================================
== Local Data
=============================================================================*/
/*
* Table to map WINSTATIONSTATECLASS to WTS_CONNECTSTATE_CLASS
*/
WTS_CONNECTSTATE_CLASS WTSStateMapping[] =
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit,
};
/****************************************************************************
*
* WTSEnumerateSessionsW (UNICODE)
*
* Returns a list of Terminal Server Sessions on the specified server
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* Reserved (input)
* Must be zero
* Version (input)
* Version of the enumeration request (must be 1)
* ppSessionInfo (output)
* Points to the address of a variable to receive the enumeration results,
* which are returned as an array of WTS_SESSION_INFO structures. The
* buffer is allocated within this API and is disposed of using
* WTSFreeMemory.
* pCount (output)
* Points to the address of a variable to receive the number of
* WTS_SESSION_INFO structures returned
*
* EXIT:
*
* TRUE -- The enumerate operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSEnumerateSessionsW(
IN HANDLE hServer,
IN DWORD Reserved,
IN DWORD Version,
OUT PWTS_SESSION_INFOW * ppSessionInfo,
OUT DWORD * pCount
)
{
PWTS_SESSION_INFOW pSessionW;
PLOGONIDW pLogonIds;
PLOGONIDW pLogonId;
ULONG SessionCount;
ULONG NameLength;
PBYTE pNameData;
ULONG Length;
ULONG i;
/*
* Validate parameters
*/
if ( Reserved != 0 || Version != 1 ) {
SetLastError( ERROR_INVALID_PARAMETER );
goto badparam;
}
if (!ppSessionInfo || !pCount) {
SetLastError(ERROR_INVALID_USER_BUFFER);
goto badparam;
}
/*
* Enumerate Sessions and check for an error
*/
if ( !WinStationEnumerateW( hServer,
&pLogonIds,
&SessionCount ) ) {
goto badenum;
}
/*
* Total up the size of the session data
*/
NameLength = 0;
for ( i=0; i < SessionCount; i++ ) {
NameLength += ((wcslen(pLogonIds[i].WinStationName) + 1) * sizeof(WCHAR)); // number of bytes
}
/*
* Allocate user buffer
*/
pSessionW = LocalAlloc( LPTR, (SessionCount * sizeof(WTS_SESSION_INFOW)) + NameLength );
if ( pSessionW == NULL )
goto badalloc;
/*
* Update user parameters
*/
*ppSessionInfo = pSessionW;
*pCount = SessionCount;
/*
* Copy data to new buffer
*/
pNameData = (PBYTE)pSessionW + (SessionCount * sizeof(WTS_SESSION_INFOW));
for ( i=0; i < SessionCount; i++ ) {
pLogonId = &pLogonIds[i];
Length = (wcslen(pLogonId->WinStationName) + 1) * sizeof(WCHAR); // number of bytes
memcpy( pNameData, pLogonId->WinStationName, Length );
pSessionW->pWinStationName = (LPWSTR) pNameData;
pSessionW->SessionId = pLogonId->LogonId;
pSessionW->State = WTSStateMapping[ pLogonId->State ];
pSessionW++;
pNameData += Length;
}
/*
* Free original Session list buffer
*/
WinStationFreeMemory( pLogonIds );
return( TRUE );
/*=============================================================================
== Error return
=============================================================================*/
badalloc:
WinStationFreeMemory( pLogonIds );
badenum:
badparam:
if (ppSessionInfo) *ppSessionInfo = NULL;
if (pCount) *pCount = 0;
return( FALSE );
}
/****************************************************************************
*
* WTSEnumerateSessionsA (ANSI stub)
*
* Returns a list of Terminal Server Sessions on the specified server
*
* ENTRY:
*
* see WTSEnumerateSessionsW
*
* EXIT:
*
* TRUE -- The enumerate operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSEnumerateSessionsA(
IN HANDLE hServer,
IN DWORD Reserved,
IN DWORD Version,
OUT PWTS_SESSION_INFOA * ppSessionInfo,
OUT DWORD * pCount
)
{
PWTS_SESSION_INFOA pSessionA;
PLOGONIDA pLogonIds;
PLOGONIDA pLogonId;
ULONG SessionCount;
ULONG NameLength;
PBYTE pNameData;
ULONG Length;
ULONG i;
/*
* Validate parameters
*/
if ( Reserved != 0 || Version != 1 ) {
SetLastError( ERROR_INVALID_PARAMETER );
goto badparam;
}
if (!ppSessionInfo || !pCount) {
SetLastError(ERROR_INVALID_USER_BUFFER);
goto badparam;
}
/*
* Enumerate Sessions and check for an error
*/
if ( !WinStationEnumerateA( hServer,
&pLogonIds,
&SessionCount ) ) {
goto badenum;
}
/*
* Total up the size of the session data
*/
NameLength = 0;
for ( i=0; i < SessionCount; i++ ) {
NameLength += (strlen(pLogonIds[i].WinStationName) + 1); // number of bytes
}
/*
* Allocate user buffer
*/
pSessionA = LocalAlloc( LPTR, (SessionCount * sizeof(WTS_SESSION_INFOA)) + NameLength );
if ( pSessionA == NULL )
goto badalloc;
/*
* Update user parameters
*/
*ppSessionInfo = pSessionA;
*pCount = SessionCount;
/*
* Copy data to new buffer
*/
pNameData = (PBYTE)pSessionA + (SessionCount * sizeof(WTS_SESSION_INFOA));
for ( i=0; i < SessionCount; i++ ) {
pLogonId = &pLogonIds[i];
Length = strlen(pLogonId->WinStationName) + 1; // number of bytes
memcpy( pNameData, pLogonId->WinStationName, Length );
pSessionA->pWinStationName = (LPSTR) pNameData;
pSessionA->SessionId = pLogonId->LogonId;
pSessionA->State = WTSStateMapping[ pLogonId->State ];
pSessionA++;
pNameData += Length;
}
/*
* Free original Session list buffer
*/
WinStationFreeMemory( pLogonIds );
return( TRUE );
/*=============================================================================
== Error return
=============================================================================*/
badalloc:
WinStationFreeMemory( pLogonIds );
badenum:
badparam:
if (ppSessionInfo) *ppSessionInfo = NULL;
if (pCount) *pCount = 0;
return( FALSE );
}
/****************************************************************************
*
* WTSQuerySessionInformationW (UNICODE)
*
* Query information for the specified session and server
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* SessionId (input)
* Server Session Id (or WTS_CURRENT_SESSION)
* WTSInfoClass (input)
* Specifies the type of information to retrieve from the specified
* session
* ppBuffer (output)
* Points to the address of a variable to receive information about
* the specified session. The format and contents of the data
* depend on the specified information class being queried. The
* buffer is allocated within this API and is disposed of using
* WTSFreeMemory.
* pBytesReturned (output)
* An optional parameter that if specified, receives the number of
* bytes returned.
*
* EXIT:
*
* TRUE -- The query operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSQuerySessionInformationW(
IN HANDLE hServer,
IN DWORD SessionId,
IN WTS_INFO_CLASS WTSInfoClass,
OUT LPWSTR * ppBuffer,
OUT DWORD * pBytesReturned
)
{
PWINSTATIONCONFIGW pWSConfig = NULL;
PWINSTATIONINFORMATIONW pWSInfo = NULL;
PWINSTATIONCLIENT pWSClient = NULL;
WTS_CLIENT_DISPLAY ClientDisplay;
WTS_CLIENT_ADDRESS ClientAddress;
ULONG WSModulesLength;
ULONG BytesReturned;
ULONG i;
BYTE Version;
BOOL fSuccess = FALSE;
if (!ppBuffer || !pBytesReturned) {
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
/*
* Query WinStation Data
*/
switch ( WTSInfoClass ) {
case WTSInitialProgram :
case WTSApplicationName :
case WTSWorkingDirectory :
case WTSOEMId :
pWSConfig = LocalAlloc( LPTR, sizeof(WINSTATIONCONFIGW) );
if ( pWSConfig == NULL )
goto no_memory;
if ( !WinStationQueryInformationW( hServer,
SessionId,
WinStationConfiguration,
pWSConfig,
sizeof(WINSTATIONCONFIGW),
&BytesReturned ) ) {
goto badquery;
}
break;
}
switch ( WTSInfoClass ) {
case WTSSessionId :
pWSInfo = LocalAlloc( LPTR, sizeof(WINSTATIONINFORMATIONW) );
if ( pWSInfo == NULL )
goto no_memory;
//
// no need to make a rpc call here
//
if (WTS_CURRENT_SESSION == SessionId)
{
pWSInfo->LogonId = NtCurrentPeb()->SessionId;
}
else
{
//
// why would anybody want to know non current sessionid ?
//
pWSInfo->LogonId = SessionId;
}
BytesReturned = sizeof(pWSInfo->LogonId);
break;
case WTSUserName :
case WTSWinStationName :
case WTSDomainName :
case WTSConnectState :
pWSInfo = LocalAlloc( LPTR, sizeof(WINSTATIONINFORMATIONW) );
if ( pWSInfo == NULL )
goto no_memory;
if ( !WinStationQueryInformationW( hServer,
SessionId,
WinStationInformation,
pWSInfo,
sizeof(WINSTATIONINFORMATIONW),
&BytesReturned ) ) {
goto badquery;
}
break;
}
switch ( WTSInfoClass ) {
case WTSClientBuildNumber :
case WTSClientName :
case WTSClientDirectory :
case WTSClientProductId :
case WTSClientHardwareId :
case WTSClientAddress :
case WTSClientDisplay :
case WTSClientProtocolType :
pWSClient = LocalAlloc( LPTR, sizeof(WINSTATIONCLIENT) );
if ( pWSClient == NULL )
goto no_memory;
if ( !WinStationQueryInformationW( hServer,
SessionId,
WinStationClient,
pWSClient,
sizeof(WINSTATIONCLIENT),
&BytesReturned ) ) {
goto badquery;
}
break;
}
/*
* Copy the data to the users buffer
*/
switch ( WTSInfoClass ) {
case WTSInitialProgram :
if ( SessionId == 0 )
return( FALSE );
fSuccess = _CopyStringW( pWSConfig->User.InitialProgram,
ppBuffer,
pBytesReturned );
break;
case WTSApplicationName :
if ( SessionId == 0 )
return( FALSE );
fSuccess = _CopyStringW( pWSConfig->User.PublishedName,
ppBuffer,
pBytesReturned );
break;
case WTSWorkingDirectory :
fSuccess = _CopyStringW( pWSConfig->User.WorkDirectory,
ppBuffer,
pBytesReturned );
break;
case WTSOEMId :
fSuccess = _CopyStringA( pWSConfig->OEMId,
ppBuffer,
pBytesReturned );
break;
case WTSSessionId :
fSuccess = _CopyData( &(pWSInfo->LogonId),
sizeof(pWSInfo->LogonId),
ppBuffer,
pBytesReturned );
break;
case WTSConnectState :
fSuccess = _CopyData( &(pWSInfo->ConnectState),
sizeof(pWSInfo->ConnectState),
ppBuffer,
pBytesReturned );
break;
case WTSWinStationName :
fSuccess = _CopyStringW( pWSInfo->WinStationName,
ppBuffer,
pBytesReturned );
break;
case WTSUserName :
fSuccess = _CopyStringW( pWSInfo->UserName,
ppBuffer,
pBytesReturned );
break;
case WTSDomainName :
fSuccess = _CopyStringW( pWSInfo->Domain,
ppBuffer,
pBytesReturned );
break;
case WTSClientBuildNumber :
fSuccess = _CopyData( &(pWSClient->ClientBuildNumber),
sizeof(pWSClient->ClientBuildNumber),
ppBuffer,
pBytesReturned );
break;
case WTSClientName :
fSuccess = _CopyStringW( pWSClient->ClientName,
ppBuffer,
pBytesReturned );
break;
case WTSClientDirectory :
fSuccess = _CopyStringW( pWSClient->ClientDirectory,
ppBuffer,
pBytesReturned );
break;
case WTSClientProductId :
fSuccess = _CopyData( &(pWSClient->ClientProductId),
sizeof(pWSClient->ClientProductId),
ppBuffer,
pBytesReturned );
break;
case WTSClientHardwareId :
fSuccess = _CopyData( &(pWSClient->ClientHardwareId),
sizeof(pWSClient->ClientHardwareId),
ppBuffer,
pBytesReturned );
break;
case WTSClientAddress :
ClientAddress.AddressFamily = pWSClient->ClientAddressFamily;
switch ( ClientAddress.AddressFamily ) {
case AF_UNSPEC :
// force null-termination
if ( pWSClient->ClientAddress[CLIENTADDRESS_LENGTH+1] != L'\0' )
pWSClient->ClientAddress[CLIENTADDRESS_LENGTH+1] = L'\0';
// We do this here instead of in the ANSI version of this
// function because we've only got 20 bytes to work with
// (unicode addresses over 10 chars would be truncated).
// The return is the same for both A and W versions.
WideCharToMultiByte( CP_ACP, 0L, pWSClient->ClientAddress,
-1, ClientAddress.Address, 20, NULL, NULL );
break;
case AF_INET :
// convert string to binary format
swscanf( pWSClient->ClientAddress, L"%u.%u.%u.%u",
&ClientAddress.Address[2],
&ClientAddress.Address[3],
&ClientAddress.Address[4],
&ClientAddress.Address[5] );
break;
case AF_IPX :
{
PWCHAR pBuf = pWSClient->ClientAddress;
_wcsupr( pWSClient->ClientAddress );
// convert string to binary format
for ( i=0 ; i<10 ; i++ ) {
if ( *pBuf != L':' ) {
swscanf( pBuf, L"%2X", &ClientAddress.Address[i] );
pBuf += 2;
} else {
// skip the colon
pBuf++;
i--;
continue;
}
}
}
break;
}
fSuccess = _CopyData( &ClientAddress,
sizeof(ClientAddress),
ppBuffer,
pBytesReturned );
break;
case WTSClientDisplay :
ClientDisplay.HorizontalResolution = pWSClient->HRes;
ClientDisplay.VerticalResolution = pWSClient->VRes;
ClientDisplay.ColorDepth = pWSClient->ColorDepth;
fSuccess = _CopyData( &ClientDisplay,
sizeof(ClientDisplay),
ppBuffer,
pBytesReturned );
break;
case WTSClientProtocolType :
fSuccess = _CopyData( &(pWSClient->ProtocolType),
sizeof(pWSClient->ProtocolType),
ppBuffer,
pBytesReturned );
break;
}
if ( pWSConfig )
LocalFree( pWSConfig );
if ( pWSInfo )
LocalFree( pWSInfo );
if ( pWSClient )
LocalFree( pWSClient );
return( fSuccess );
/*=============================================================================
== Error return
=============================================================================*/
badquery:
return( FALSE );
no_memory:
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return( FALSE );
}
/****************************************************************************
*
* WTSQuerySessionInformationA (ANSI)
*
* Query information for the specified session and server
*
* ENTRY:
*
* see WTSQuerySessionInformationW
*
* EXIT:
*
* TRUE -- The query operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSQuerySessionInformationA(
IN HANDLE hServer,
IN DWORD SessionId,
IN WTS_INFO_CLASS WTSInfoClass,
OUT LPSTR * ppBuffer,
OUT DWORD * pBytesReturned
)
{
LPWSTR pBufferW;
DWORD BytesReturned;
DWORD DataLength;
if (!ppBuffer || !pBytesReturned) {
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
/*
* Query the data
*/
if ( !WTSQuerySessionInformationW( hServer,
SessionId,
WTSInfoClass,
&pBufferW,
&BytesReturned ) ) {
return( FALSE );
}
switch ( WTSInfoClass ) {
case WTSSessionId :
case WTSConnectState :
case WTSClientBuildNumber :
case WTSClientProductId :
case WTSClientHardwareId :
case WTSClientAddress :
case WTSClientDisplay :
case WTSClientProtocolType:
/*
* Non-String Data - just return
*/
*ppBuffer = (LPSTR) pBufferW;
if ( pBytesReturned ) {
*pBytesReturned = BytesReturned;
}
break;
case WTSInitialProgram :
case WTSWorkingDirectory :
case WTSOEMId :
case WTSWinStationName :
case WTSUserName :
case WTSDomainName :
case WTSClientName :
case WTSClientDirectory :
case WTSApplicationName :
/*
* String Data - Convert to ANSI
*/
DataLength = wcslen(pBufferW) + 1;
*ppBuffer = LocalAlloc( LPTR, DataLength );
if ( *ppBuffer == NULL ) {
LocalFree( pBufferW );
return( FALSE );
}
UnicodeToAnsi( *ppBuffer, DataLength, pBufferW );
if ( pBytesReturned ) {
*pBytesReturned = DataLength;
}
LocalFree( pBufferW );
break;
}
return( TRUE );
}
/****************************************************************************
*
* WTSSetSessionInformationW (UNICODE)
*
* NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
*
* Modify information for the specified session and server
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* SessionId (input)
* Server Session Id (or WTS_CURRENT_SESSION)
* WTSInfoClass (input)
* Specifies the type of information to modify for the specified
* session
* pData (input)
* Pointer to the data used to modify the specified session information.
* DataLength (output)
* The length of the data provided.
*
* EXIT:
*
* TRUE -- The modify operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSSetSessionInformationW(
IN HANDLE hServer,
IN DWORD SessionId,
IN WTS_INFO_CLASS WTSInfoClass,
IN PVOID pData,
IN DWORD DataLength
)
{
return( TRUE );
}
/****************************************************************************
*
* WTSSetSessionInformationA (ANSI)
*
* NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
*
* Modify information for the specified session and server
*
* ENTRY:
*
* see WTSSetSessionInformationW
*
* EXIT:
*
* TRUE -- The query operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSSetSessionInformationA(
IN HANDLE hServer,
IN DWORD SessionId,
IN WTS_INFO_CLASS WTSInfoClass,
IN PVOID pData,
IN DWORD DataLength
)
{
return( TRUE );
}
/****************************************************************************
*
* WTSSendMessageW (UNICODE)
*
* Send a message box to the specified session
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* SessionId (input)
* Server Session Id (or WTS_CURRENT_SESSION)
* pTitle (input)
* Pointer to title for message box to display.
* TitleLength (input)
* Length of title to display in bytes.
* pMessage (input)
* Pointer to message to display.
* MessageLength (input)
* Length of message in bytes to display at the specified window station.
* Style (input)
* Standard Windows MessageBox() style parameter.
* Timeout (input)
* Response timeout in seconds. If message is not responded to in
* Timeout seconds then a response code of IDTIMEOUT (cwin.h) is
* returned to signify the message timed out.
* pResponse (output)
* Address to return selected response. Valid only when bWait is set.
* bWait (input)
* Wait for the response
*
* EXIT:
*
* TRUE -- The operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSSendMessageW(
IN HANDLE hServer,
IN DWORD SessionId,
IN LPWSTR pTitle,
IN DWORD TitleLength,
IN LPWSTR pMessage,
IN DWORD MessageLength,
IN DWORD Style,
IN DWORD Timeout,
OUT DWORD * pResponse,
IN BOOL bWait
)
{
if (!pTitle ||
!pMessage ||
!pResponse
) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return( WinStationSendMessageW( hServer,
SessionId,
pTitle,
TitleLength,
pMessage,
MessageLength,
Style,
Timeout,
pResponse,
(BOOLEAN) !bWait ) );
}
/****************************************************************************
*
* WTSSendMessageA (ANSI)
*
* Send a message box to the specified session
*
* ENTRY:
*
* see WTSSendMessageW
*
* EXIT:
*
* TRUE -- The operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSSendMessageA(
IN HANDLE hServer,
IN DWORD SessionId,
IN LPSTR pTitle,
IN DWORD TitleLength,
IN LPSTR pMessage,
IN DWORD MessageLength,
IN DWORD Style,
IN DWORD Timeout,
OUT DWORD * pResponse,
IN BOOL bWait
)
{
if (!pTitle ||
!pMessage ||
!pResponse
) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return( WinStationSendMessageA( hServer,
SessionId,
pTitle,
TitleLength,
pMessage,
MessageLength,
Style,
Timeout,
pResponse,
(BOOLEAN) !bWait ) );
}
/****************************************************************************
*
* WTSDisconnectSession
*
* Disconnect the specified session
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* SessionId (input)
* Server Session Id (or WTS_CURRENT_SESSION)
* bWait (input)
* Wait for the operation to complete
*
* EXIT:
*
* TRUE -- The operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSDisconnectSession(
IN HANDLE hServer,
IN DWORD SessionId,
IN BOOL bWait
)
{
return( WinStationDisconnect( hServer, SessionId, (BOOLEAN) bWait ) );
}
/****************************************************************************
*
* WTSLogoffSession
*
* Logoff the specified session
*
* ENTRY:
* hServer (input)
* Terminal Server handle (or WTS_CURRENT_SERVER)
* SessionId (input)
* Server Session Id (or WTS_CURRENT_SESSION)
* bWait (input)
* Wait for the operation to complete
*
* EXIT:
*
* TRUE -- The operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSLogoffSession(
IN HANDLE hServer,
IN DWORD SessionId,
IN BOOL bWait
)
{
return( WinStationReset( hServer, SessionId, (BOOLEAN) bWait ) );
}
/****************************************************************************
*
* _CopyData
*
* Allocate buffer and copy data into it
*
* ENTRY:
* pData (input)
* pointer to data to copy
* DataLength (input)
* length of data to copy
* ppBuffer (output)
* Points to the address of a variable to receive the copied data
* pBytesReturned (output)
* An optional parameter that if specified, receives the number of
* bytes returned.
*
* EXIT:
*
* TRUE -- The copy operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
_CopyData( PVOID pData,
ULONG DataLength,
LPWSTR * ppBuffer,
DWORD * pBytesReturned )
{
*ppBuffer = LocalAlloc( LPTR, DataLength );
if ( *ppBuffer == NULL ) {
return( FALSE );
}
if ( pBytesReturned != NULL ) {
*pBytesReturned = DataLength;
}
memcpy( *ppBuffer, pData, DataLength );
return( TRUE );
}
/****************************************************************************
*
* _CopyStringW
*
* Allocate a buffer for a unicode string and copy unicode string into it
*
* ENTRY:
* pString (input)
* pointer to unicode string to copy
* ppBuffer (output)
* Points to the address of a variable to receive the copied data
* pBytesReturned (output)
* An optional parameter that if specified, receives the number of
* bytes returned.
*
* EXIT:
*
* TRUE -- The copy operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
_CopyStringW( LPWSTR pString,
LPWSTR * ppBuffer,
DWORD * pBytesReturned )
{
ULONG DataLength;
BOOL rc = TRUE;
/*
* If original string is NULL, just make copy NULL. KLB 11-03-97
*/
if ( pString == NULL ) {
*ppBuffer = NULL;
if ( pBytesReturned != NULL ) {
*pBytesReturned = 0;
}
goto done;
}
DataLength = (wcslen( pString ) + 1) * sizeof(WCHAR);
*ppBuffer = LocalAlloc( LPTR, DataLength );
if ( *ppBuffer == NULL ) {
rc = FALSE;
goto done;
}
if ( pBytesReturned != NULL ) {
*pBytesReturned = DataLength;
}
memcpy( *ppBuffer, pString, DataLength );
done:
return( rc );
}
/****************************************************************************
*
* _CopyStringA
*
* Allocate a buffer for a unicode string and copy ansi string into it
*
* ENTRY:
* pString (input)
* pointer to ansi string to copy
* ppBuffer (output)
* Points to the address of a variable to receive the copied data
* pBytesReturned (output)
* An optional parameter that if specified, receives the number of
* bytes returned.
*
* EXIT:
*
* TRUE -- The copy operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
_CopyStringA( LPSTR pString,
LPWSTR * ppBuffer,
DWORD * pBytesReturned )
{
ULONG DataLength;
BOOL rc = TRUE;
/*
* If original string is NULL, just make copy NULL. KLB 11-03-97
*/
if ( pString == NULL ) {
*ppBuffer = NULL;
if ( pBytesReturned != NULL ) {
*pBytesReturned = 0;
}
goto done;
}
DataLength = (strlen( pString ) + 1) * sizeof(WCHAR);
*ppBuffer = LocalAlloc( LPTR, DataLength );
if ( *ppBuffer == NULL ) {
rc = FALSE;
goto done;
}
if ( pBytesReturned != NULL ) {
*pBytesReturned = DataLength;
}
AnsiToUnicode( *ppBuffer, DataLength, pString );
done:
return( rc );
}
/****************************************************************************
*
* _CopyStringWtoA
*
* Allocate a buffer for an ansi string and copy unicode string into it
*
* ENTRY:
* pString (input)
* pointer to unicode string to copy
* ppBuffer (output)
* Points to the address of a variable to receive the copied data
* pBytesReturned (output)
* An optional parameter that if specified, receives the number of
* bytes returned.
*
* EXIT:
*
* TRUE -- The copy operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
_CopyStringWtoA( LPWSTR pString,
LPSTR * ppBuffer,
DWORD * pBytesReturned )
{
ULONG DataLength;
DataLength = (wcslen( pString ) + 1) * sizeof(CHAR);
*ppBuffer = LocalAlloc( LPTR, DataLength );
if ( *ppBuffer == NULL )
return( FALSE );
if ( pBytesReturned != NULL ) {
*pBytesReturned = DataLength;
}
UnicodeToAnsi( *ppBuffer, DataLength, pString );
return( TRUE );
}
/****************************************************************************
*
* ValidateCopyUnicodeToUnicode
*
* Determines if the source unicode character string is valid and if so,
* copies it to the destination.
*
* ENTRY:
* pSourceW (input)
* pointer to a null terminated string.
* MaxLength (input)
* The maximum allowed length (in characters).
* pDestW (input)
* The destination where pSourceW is copied.
* EXIT:
* Returns TRUE if successful, otherwise FALSE.
*
****************************************************************************/
BOOL
ValidateCopyUnicodeToUnicode(LPWSTR pSourceW, DWORD MaxLength, LPWSTR pDestW)
{
DWORD Length;
if ( wcslen(pSourceW) > MaxLength ) {
return(FALSE);
}
wcscpy(pDestW,pSourceW);
return(TRUE);
}
/****************************************************************************
*
* ValidateCopyAnsiToUnicode
*
* Determines if the source ANSI character string is valid and if so,
* converts and copies it to the unicode destination.
*
* ENTRY:
* pSourceA (input)
* pointer to a null terminated ANSI string.
* MaxLength (input)
* The maximum allowed length (in characters).
* pDestW (input)
* The destination where pSourceA is copied.
* EXIT:
* Returns TRUE if successful, otherwise FALSE.
*
****************************************************************************/
BOOL
ValidateCopyAnsiToUnicode(LPSTR pSourceA, DWORD MaxLength, LPWSTR pDestW)
{
UINT Length;
DWORD DataLength;
if ( (Length = strlen(pSourceA)) > MaxLength ) {
return(FALSE);
}
DataLength = (Length+1) * sizeof(WCHAR);
AnsiToUnicode(pDestW,DataLength,pSourceA);
return(TRUE);
}
/****************************************************************************
*
* WTSRegisterSessionNotification
*
* Register a window handle for console notification
* Console notification, are messages sent when console session switch occurs
*
* ENTRY:
* hWnd (input)
* Window handle to be registered.
* dwFlags (input)
* value must be NOTIFY_FOR_THIS_SESSION
* EXIT:
* Returns TRUE if successful, otherwise FALSE. Sets LastError
*
****************************************************************************/
BOOL WINAPI
WTSRegisterSessionNotification (HWND hWnd, DWORD dwFlags)
{
DWORD dwProcId;
HMODULE User32DllHandle = NULL ;
//
// make sure that window handle is valid
//
if (!IsWindow(hWnd))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto error ;
}
GetWindowThreadProcessId(hWnd, &dwProcId);
if (dwProcId != GetCurrentProcessId())
{
SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
goto error ;
}
if (dwFlags != NOTIFY_FOR_THIS_SESSION && dwFlags != NOTIFY_FOR_ALL_SESSIONS)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto error ;
}
return WinStationRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd, dwFlags);
// -------------------------------- Handle Errors and return FALSE -----------------------
error :
return FALSE ;
}
/****************************************************************************
*
* WTSUnRegisterSessionNotification
*
* UnRegister a window handle for console notification
* Console notification, are messages sent when console session switch occurs
*
* ENTRY:
* dwFlags (input)
* NOTIFY_FOR_THIS_SESSION
* EXIT:
* Returns TRUE if successful, otherwise FALSE. Sets LastError
*
****************************************************************************/
BOOL WINAPI
WTSUnRegisterSessionNotification (HWND hWnd)
{
DWORD dwProcId;
HMODULE User32DllHandle = NULL ;
//
// make sure that window handle is valid
//
if (!IsWindow(hWnd))
{
SetLastError(ERROR_INVALID_PARAMETER);
goto error ;
}
GetWindowThreadProcessId(hWnd, &dwProcId);
if (dwProcId != GetCurrentProcessId())
{
SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
goto error ;
}
return WinStationUnRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd);
// -------------------------------- Handle Errors and return FALSE -----------------------
error :
return FALSE ;
}