WindowsXP-SP1/termsrv/wtsapi/server.c

403 lines
10 KiB
C

/*******************************************************************************
* server.c
*
* Published Terminal Server APIs
*
* - server 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 <stdio.h>
#include <stdarg.h>
#include <wtsapi32.h>
/*=============================================================================
== External procedures defined
=============================================================================*/
BOOL WINAPI WTSEnumerateServersW( LPWSTR, DWORD, DWORD, PWTS_SERVER_INFOW *, DWORD * );
BOOL WINAPI WTSEnumerateServersA( LPSTR, DWORD, DWORD, PWTS_SERVER_INFOA *, DWORD * );
HANDLE WINAPI WTSOpenServerW( LPWSTR );
HANDLE WINAPI WTSOpenServerA( LPSTR );
VOID WINAPI WTSCloseServer( HANDLE );
/*=============================================================================
== Procedures used
=============================================================================*/
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
/****************************************************************************
*
* WTSEnumerateServersW (UNICODE)
*
* Returns a list of Terminal servers within the specified NT domain
*
* ENTRY:
* pDomainName (input)
* Pointer to NT domain name (or NULL for current domain)
* Reserved (input)
* Must be zero
* Version (input)
* Version of the enumeration request (must be 1)
* ppServerInfo (output)
* Points to the address of a variable to receive the enumeration results,
* which are returned as an array of WTS_SERVER_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_SERVER_INFO structures returned
*
* EXIT:
*
* TRUE -- The enumerate operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSEnumerateServersW(
IN LPWSTR pDomainName,
IN DWORD Reserved,
IN DWORD Version,
OUT PWTS_SERVER_INFOW * ppServerInfo,
OUT DWORD * pCount
)
{
LPWSTR pServerList;
LPWSTR pData;
PBYTE pNameData;
ULONG Length;
ULONG NameCount; // number of names
ULONG NameLength; // number of bytes of name data
PWTS_SERVER_INFOW pServerW;
/*
* Validate parameters
*/
if ( Reserved != 0 || Version != 1 ) {
SetLastError( ERROR_INVALID_PARAMETER );
goto badparam;
}
if ( !ppServerInfo || !pCount) {
SetLastError( ERROR_INVALID_USER_BUFFER);
goto badparam;
}
/*
* Enumerate servers and check for an error
*/
pServerList = EnumerateMultiUserServers( pDomainName );
if ( pServerList == NULL ) {
SetLastError(ERROR_INVALID_DOMAINNAME);
goto badenum;
}
/*
* Count the number of Terminal servers
*/
NameCount = 0;
NameLength = 0;
pData = pServerList;
while ( *pData ) {
Length = (wcslen(pData) + 1) * sizeof(WCHAR); // number of bytes
NameCount++;
NameLength += Length;
(PBYTE)pData += Length;
}
/*
* Allocate user buffer
*/
pServerW = LocalAlloc( LPTR, (NameCount * sizeof(WTS_SERVER_INFOW)) + NameLength );
if ( pServerW == NULL )
goto badalloc;
/*
* Update user parameters
*/
*ppServerInfo = pServerW;
*pCount = NameCount;
/*
* Copy data to new buffer
*/
pData = pServerList;
pNameData = (PBYTE)pServerW + (NameCount * sizeof(WTS_SERVER_INFOW));
while ( *pData ) {
Length = (wcslen(pData) + 1) * sizeof(WCHAR); // number of bytes
memcpy( pNameData, pData, Length );
pServerW->pServerName = (LPWSTR) pNameData;
pServerW++;
pNameData += Length;
(PBYTE)pData += Length;
}
/*
* Free original server list buffer
*/
LocalFree( pServerList );
return( TRUE );
/*=============================================================================
== Error return
=============================================================================*/
badalloc:
badenum:
badparam:
if (ppServerInfo) *ppServerInfo = NULL;
if (pCount) *pCount = 0;
return( FALSE );
}
/****************************************************************************
*
* WTSEnumerateServersA (ANSI stub)
*
* Returns a list of Terminal servers within the specified NT domain
*
* ENTRY:
*
* see WTSEnumerateServersW
*
* EXIT:
*
* TRUE -- The enumerate operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
****************************************************************************/
BOOL
WINAPI
WTSEnumerateServersA(
IN LPSTR pDomainName,
IN DWORD Reserved,
IN DWORD Version,
OUT PWTS_SERVER_INFOA * ppServerInfo,
OUT DWORD * pCount
)
{
LPWSTR pDomainNameW = NULL;
ULONG DomainNameWLength;
PWTS_SERVER_INFOW pServerW;
PWTS_SERVER_INFOA pServerA;
PBYTE pNameData;
ULONG Length;
ULONG NameLength; // number of bytes of name data
ULONG NameCount;
ULONG i;
if ( !ppServerInfo || !pCount) {
SetLastError( ERROR_INVALID_USER_BUFFER);
return FALSE;
}
/*
* Convert ansi domain name to unicode
*/
if ( pDomainName ) {
DomainNameWLength = (strlen(pDomainName) + 1) * sizeof(WCHAR);
if ( (pDomainNameW = LocalAlloc( LPTR, DomainNameWLength )) == NULL )
goto badalloc1;
AnsiToUnicode( pDomainNameW, DomainNameWLength, pDomainName );
}
/*
* Enumerate servers (UNICODE)
*/
if ( !WTSEnumerateServersW( pDomainNameW,
Reserved,
Version,
&pServerW,
&NameCount ) ) {
goto badenum;
}
/*
* Calculate the length of the name data
*/
for ( i=0, NameLength=0; i < NameCount; i++ ) {
NameLength += (wcslen(pServerW[i].pServerName) + 1);
}
/*
* Allocate user buffer
*/
pServerA = LocalAlloc( LPTR, (NameCount * sizeof(WTS_SERVER_INFOA)) + NameLength );
if ( pServerA == NULL )
goto badalloc2;
/*
* Convert unicode server list to ansi
*/
pNameData = (PBYTE)pServerA + (NameCount * sizeof(WTS_SERVER_INFOA));
for ( i=0; i < NameCount; i++ ) {
Length = wcslen(pServerW[i].pServerName) + 1;
pServerA[i].pServerName = pNameData;
UnicodeToAnsi( pNameData, NameLength, pServerW[i].pServerName );
NameLength -= Length;
pNameData += Length;
}
/*
* Free unicode server list buffer
*/
LocalFree( pServerW );
/*
* Free domain name buffer
*/
if ( pDomainNameW )
LocalFree( pDomainNameW );
/*
* Update user parameters
*/
*ppServerInfo = pServerA;
*pCount = NameCount;
return( TRUE );
/*=============================================================================
== Error return
=============================================================================*/
badalloc2:
LocalFree( pServerW );
badenum:
if ( pDomainNameW )
LocalFree( pDomainNameW );
badalloc1:
*ppServerInfo = NULL;
*pCount = 0;
return( FALSE );
}
/****************************************************************************
*
* WTSOpenServerW (UNICODE)
*
* Opens a handle to the specified server
*
* NOTE: WTS_SERVER_CURRENT can be used as a handle to the current server
*
* ENTRY:
* pServerName (input)
* Pointer to Terminal server name
*
* EXIT:
*
* Handle to specified server (NULL on error)
*
*
****************************************************************************/
HANDLE
WINAPI
WTSOpenServerW(
IN LPWSTR pServerName
)
{
return( WinStationOpenServerW( pServerName ) );
}
/****************************************************************************
*
* WTSOpenServerA (ANSI)
*
* Opens a handle to the specified server
*
* NOTE: WTS_SERVER_CURRENT can be used as a handle to the current server
*
* ENTRY:
* pServerName (input)
* Pointer to Terminal server name
*
* EXIT:
*
* Handle to specified server
*
*
****************************************************************************/
HANDLE
WINAPI
WTSOpenServerA(
IN LPSTR pServerName
)
{
return( WinStationOpenServerA( pServerName ) );
}
/****************************************************************************
*
* WTSCloseServer
*
* Close server handle
*
* ENTRY:
* hServer (input)
* handle to server
*
* EXIT:
* nothing
*
****************************************************************************/
VOID
WINAPI
WTSCloseServer(
IN HANDLE hServer
)
{
(void) WinStationCloseServer( hServer );
}