/******************************************************************************* * session.c * * Published Terminal Server APIs * * - session routines * * Copyright 1998, Citrix Systems Inc. * Copyright (C) 1997-1999 Microsoft Corp. /******************************************************************************/ #include #include #include #include #include #include #include #include #if(WINVER >= 0x0500) #include #include #else #include #include #endif #include #include // for AF_INET, etc. #include #include #include /*============================================================================= == 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; } badquery: if ( pWSConfig ) LocalFree( pWSConfig ); if ( pWSInfo ) LocalFree( pWSInfo ); if ( pWSClient ) LocalFree( pWSClient ); return( fSuccess ); /*============================================================================= == Error return =============================================================================*/ 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 * lets allocate the maximum possible MultiByte length. */ DataLength = (wcslen(pBufferW) + 1) * sizeof(WCHAR); *ppBuffer = LocalAlloc( LPTR, DataLength ); if ( *ppBuffer == NULL ) { LocalFree( pBufferW ); return( FALSE ); } RtlUnicodeToMultiByteN( *ppBuffer, DataLength, pBytesReturned, pBufferW, 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 ); } /**************************************************************************** * * 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 ; }