You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
549 lines
16 KiB
549 lines
16 KiB
|
|
/*************************************************************************
|
|
*
|
|
* wsxmgr.c
|
|
*
|
|
* Routines to manage Window Station extensions.
|
|
*
|
|
* Copyright Microsoft Corporation, 1998
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/*=============================================================================
|
|
== Macros
|
|
=============================================================================*/
|
|
|
|
|
|
/*=============================================================================
|
|
== External procedures defined
|
|
=============================================================================*/
|
|
|
|
PWSEXTENSION FindWinStationExtensionDll( PWSTR pszWsxDll, ULONG WdFlag );
|
|
|
|
|
|
/*=============================================================================
|
|
== Local Data
|
|
=============================================================================*/
|
|
|
|
RTL_CRITICAL_SECTION WsxListLock;
|
|
RTL_CRITICAL_SECTION WsxLoadLock;
|
|
LIST_ENTRY WsxListHead;
|
|
|
|
|
|
/*=============================================================================
|
|
== External Data
|
|
=============================================================================*/
|
|
|
|
extern LIST_ENTRY WinStationListHead; // protected by WinStationListLock
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* WsxInit
|
|
*
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* STATUS_SUCCESS on success, the return value of InitCritSec on failure.
|
|
*
|
|
******************************************************************************/
|
|
|
|
NTSTATUS
|
|
WsxInit( VOID )
|
|
{
|
|
NTSTATUS Status;
|
|
InitializeListHead( &WsxListHead );
|
|
Status = RtlInitializeCriticalSection( &WsxLoadLock );
|
|
if (Status == STATUS_SUCCESS) {
|
|
Status = RtlInitializeCriticalSection( &WsxListLock );
|
|
if (Status != STATUS_SUCCESS) {
|
|
RtlDeleteCriticalSection(&WsxLoadLock);
|
|
}
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* _WinStationEnumCallback
|
|
*
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
VOID
|
|
_WinStationEnumCallback(PCALLBACK_PRIMARY pPrimaryCallback,
|
|
PCALLBACK_COMPLETION pCompletionCallback,
|
|
PVOID pWsxEnum
|
|
)
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PWINSTATION pWinStation;
|
|
|
|
RtlEnterCriticalSection( &WinStationListLock );
|
|
|
|
// call primary if valid
|
|
if ( pPrimaryCallback ) {
|
|
|
|
Head = &WinStationListHead;
|
|
for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
|
|
pWinStation = CONTAINING_RECORD( Next, WINSTATION, Links );
|
|
if ( pWinStation->pWsx ) {
|
|
pPrimaryCallback( pWinStation->pWsx->hInstance, pWinStation->pWsxContext, pWsxEnum );
|
|
} else {
|
|
pPrimaryCallback( NULL, pWinStation->pWsxContext, pWsxEnum );
|
|
}
|
|
}
|
|
}
|
|
|
|
// call completion if valid
|
|
if ( pCompletionCallback ) {
|
|
pCompletionCallback( pWsxEnum );
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WinStationListLock );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* _SendWinStationMessage
|
|
*
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
NTSTATUS
|
|
_SendWinStationMessage(
|
|
ULONG LogonId,
|
|
PWCHAR pTitle,
|
|
PWCHAR pMessage,
|
|
ULONG MessageTimeout )
|
|
{
|
|
PWINSTATION pWinStation;
|
|
WINSTATION_APIMSG msg;
|
|
NTSTATUS Status;
|
|
|
|
/*
|
|
* Find and lock the WinStation struct for the specified LogonId
|
|
*/
|
|
pWinStation = FindWinStationById( LogonId, FALSE );
|
|
if ( pWinStation == NULL ) {
|
|
return( STATUS_CTX_WINSTATION_NOT_FOUND );
|
|
}
|
|
|
|
/*
|
|
* Build message
|
|
*/
|
|
msg.u.SendMessage.pTitle = pTitle;
|
|
msg.u.SendMessage.TitleLength = wcslen( pTitle ) * sizeof(WCHAR);
|
|
msg.u.SendMessage.pMessage = pMessage;
|
|
msg.u.SendMessage.MessageLength = wcslen( pMessage ) * sizeof(WCHAR);
|
|
msg.u.SendMessage.Style = MB_OK | MB_ICONSTOP;
|
|
msg.u.SendMessage.Timeout = MessageTimeout;
|
|
msg.u.SendMessage.Response = 0;
|
|
msg.u.SendMessage.DoNotWait = TRUE;
|
|
msg.u.SendMessage.DoNotWaitForCorrectDesktop = FALSE;
|
|
msg.ApiNumber = SMWinStationDoMessage;
|
|
|
|
// since we not going to wait for the message delievary, we dont care for status.
|
|
msg.u.SendMessage.pStatus = NULL;
|
|
msg.u.SendMessage.pResponse = NULL;
|
|
msg.u.SendMessage.hEvent = NULL;
|
|
|
|
/*
|
|
* Send message
|
|
*/
|
|
Status = SendWinStationCommand( pWinStation, &msg, 0 );
|
|
|
|
/*
|
|
* Done with winstation
|
|
*/
|
|
ReleaseWinStation( pWinStation );
|
|
|
|
return( Status );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* _GetContextForLogonId
|
|
*
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
NTSTATUS
|
|
_GetContextForLogonId(
|
|
ULONG LogonId,
|
|
PVOID * ppWsxContext
|
|
)
|
|
{
|
|
PWINSTATION pWinStation;
|
|
WINSTATION_APIMSG msg;
|
|
|
|
/*
|
|
* Find and lock the WinStation struct for the specified LogonId
|
|
*/
|
|
pWinStation = FindWinStationById( LogonId, FALSE );
|
|
if ( pWinStation == NULL ) {
|
|
*ppWsxContext = NULL;
|
|
return( STATUS_CTX_WINSTATION_NOT_FOUND );
|
|
}
|
|
|
|
/*
|
|
* Return context
|
|
*/
|
|
*ppWsxContext = pWinStation->pWsxContext;
|
|
|
|
/*
|
|
* Done with winstation
|
|
*/
|
|
ReleaseWinStation( pWinStation );
|
|
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* _LoadWsxDll
|
|
*
|
|
* Load and Initialize Window Station Extension DLL.
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
PWSEXTENSION
|
|
_LoadWsxDll( PWSTR pszWsxDll )
|
|
{
|
|
PWSEXTENSION pWsx;
|
|
HINSTANCE hDllInstance;
|
|
|
|
if ( pszWsxDll == NULL || *pszWsxDll == UNICODE_NULL )
|
|
return( NULL );
|
|
|
|
hDllInstance = LoadLibrary(pszWsxDll);
|
|
|
|
if (!hDllInstance) {
|
|
TRACE((hTrace,TC_ICASRV,TT_ERROR,"TERMSRV: Error %d, _LoadWsxDll(%s) failed\n",
|
|
GetLastError(), pszWsxDll));
|
|
return(NULL);
|
|
}
|
|
|
|
pWsx = MemAlloc( sizeof(WSEXTENSION) );
|
|
if ( !pWsx ) {
|
|
return(NULL);
|
|
}
|
|
RtlZeroMemory( pWsx, sizeof(WSEXTENSION) );
|
|
|
|
RtlCopyMemory( pWsx->WsxDLL, pszWsxDll, sizeof(pWsx->WsxDLL) );
|
|
pWsx->hInstance = hDllInstance;
|
|
|
|
/*
|
|
* Initialize Dll support functions
|
|
*/
|
|
pWsx->pWsxInitialize = (PWSX_INITIALIZE) GetProcAddress(hDllInstance, WSX_INITIALIZE);
|
|
if (!pWsx->pWsxInitialize) {
|
|
TRACE((hTrace,TC_ICASRV,TT_ERROR,"TERMSRV: Could not find pWsxInitialize entry point\n"));
|
|
goto LoadWsx_ErrorReturn;
|
|
}
|
|
|
|
/*
|
|
* Client Drive Mapping Extensions
|
|
*/
|
|
pWsx->pWsxCdmConnect = (PWSX_CDMCONNECT)
|
|
GetProcAddress(hDllInstance, WSX_CDMCONNECT);
|
|
|
|
pWsx->pWsxCdmDisconnect = (PWSX_CDMDISCONNECT)
|
|
GetProcAddress(hDllInstance, WSX_CDMDISCONNECT);
|
|
|
|
pWsx->pWsxVerifyClientLicense = (PWSX_VERIFYCLIENTLICENSE)
|
|
GetProcAddress(hDllInstance, WSX_VERIFYCLIENTLICENSE);
|
|
|
|
pWsx->pWsxQueryLicense = (PWSX_QUERYLICENSE)
|
|
GetProcAddress(hDllInstance, WSX_QUERYLICENSE);
|
|
|
|
pWsx->pWsxGetLicense = (PWSX_GETLICENSE)
|
|
GetProcAddress(hDllInstance, WSX_GETLICENSE);
|
|
|
|
pWsx->pWsxWinStationLogonAnnoyance = (PWSX_WINSTATIONLOGONANNOYANCE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONLOGONANNOYANCE);
|
|
|
|
pWsx->pWsxWinStationGenerateLicense = (PWSX_WINSTATIONGENERATELICENSE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONGENERATELICENSE);
|
|
|
|
pWsx->pWsxWinStationInstallLicense = (PWSX_WINSTATIONINSTALLLICENSE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONINSTALLLICENSE);
|
|
|
|
pWsx->pWsxWinStationEnumerateLicenses = (PWSX_WINSTATIONENUMERATELICENSES)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONENUMERATELICENSES);
|
|
|
|
pWsx->pWsxWinStationActivateLicense = (PWSX_WINSTATIONACTIVATELICENSE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONACTIVATELICENSE);
|
|
|
|
pWsx->pWsxWinStationRemoveLicense = (PWSX_WINSTATIONREMOVELICENSE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONREMOVELICENSE);
|
|
|
|
pWsx->pWsxWinStationSetPoolCount = (PWSX_WINSTATIONSETPOOLCOUNT)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONSETPOOLCOUNT);
|
|
|
|
pWsx->pWsxWinStationQueryUpdateRequired = (PWSX_WINSTATIONQUERYUPDATEREQUIRED)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONQUERYUPDATEREQUIRED);
|
|
|
|
pWsx->pWsxWinStationAnnoyanceThread = (PWSX_WINSTATIONANNOYANCETHREAD)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONANNOYANCETHREAD);
|
|
|
|
pWsx->pWsxInitializeClientData = (PWSX_INITIALIZECLIENTDATA)
|
|
GetProcAddress(hDllInstance, WSX_INITIALIZECLIENTDATA);
|
|
|
|
pWsx->pWsxInitializeUserConfig = (PWSX_INITIALIZEUSERCONFIG)
|
|
GetProcAddress(hDllInstance, WSX_INITIALIZEUSERCONFIG);
|
|
|
|
pWsx->pWsxConvertPublishedApp = (PWSX_CONVERTPUBLISHEDAPP)
|
|
GetProcAddress(hDllInstance, WSX_CONVERTPUBLISHEDAPP);
|
|
|
|
pWsx->pWsxWinStationInitialize = (PWSX_WINSTATIONINITIALIZE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONINITIALIZE);
|
|
|
|
pWsx->pWsxWinStationReInitialize = (PWSX_WINSTATIONREINITIALIZE)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONREINITIALIZE);
|
|
|
|
pWsx->pWsxWinStationRundown = (PWSX_WINSTATIONRUNDOWN)
|
|
GetProcAddress(hDllInstance, WSX_WINSTATIONRUNDOWN);
|
|
|
|
pWsx->pWsxDuplicateContext = (PWSX_DUPLICATECONTEXT)
|
|
GetProcAddress(hDllInstance, WSX_DUPLICATECONTEXT);
|
|
|
|
pWsx->pWsxCopyContext = (PWSX_COPYCONTEXT)
|
|
GetProcAddress(hDllInstance, WSX_COPYCONTEXT);
|
|
|
|
pWsx->pWsxClearContext = (PWSX_CLEARCONTEXT)
|
|
GetProcAddress(hDllInstance, WSX_CLEARCONTEXT);
|
|
|
|
pWsx->pWsxVirtualChannelSecurity = (PWSX_VIRTUALCHANNELSECURITY)
|
|
GetProcAddress(hDllInstance, WSX_VIRTUALCHANNELSECURITY);
|
|
|
|
pWsx->pWsxIcaStackIoControl = (PWSX_ICASTACKIOCONTROL)
|
|
GetProcAddress(hDllInstance, WSX_ICASTACKIOCONTROL);
|
|
|
|
pWsx->pWsxBrokenConnection = (PWSX_BROKENCONNECTION)
|
|
GetProcAddress(hDllInstance, WSX_BROKENCONNECTION);
|
|
|
|
pWsx->pWsxLogonNotify = (PWSX_LOGONNOTIFY)
|
|
GetProcAddress(hDllInstance, WSX_LOGONNOTIFY);
|
|
|
|
pWsx->pWsxSetErrorInfo = (PWSX_SETERRORINFO)
|
|
GetProcAddress(hDllInstance, WSX_SETERRORINFO);
|
|
|
|
pWsx->pWsxSendAutoReconnectStatus = (PWSX_SENDAUTORECONNECTSTATUS)
|
|
GetProcAddress(hDllInstance, WSX_SENDAUTORECONNECTSTATUS);
|
|
|
|
pWsx->pWsxEscape = (PWSX_ESCAPE)
|
|
GetProcAddress(hDllInstance, WSX_ESCAPE);
|
|
|
|
return(pWsx);
|
|
|
|
LoadWsx_ErrorReturn:
|
|
|
|
LocalFree(pWsx);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FindWinStationExtensionDll
|
|
*
|
|
* Perform initialization of Window Station Extensions
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
PWSEXTENSION
|
|
FindWinStationExtensionDll( PWSTR pszWsxDll, ULONG WdFlag )
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PWSEXTENSION pWsx = NULL;
|
|
ICASRVPROCADDR IcaSrvProcAddr;
|
|
|
|
RtlEnterCriticalSection( &WsxLoadLock );
|
|
RtlEnterCriticalSection( &WsxListLock );
|
|
|
|
Head = &WsxListHead;
|
|
for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
|
|
pWsx = CONTAINING_RECORD( Next, WSEXTENSION, Links );
|
|
if ( !_wcsicmp( pszWsxDll, pWsx->WsxDLL ) ){
|
|
break;
|
|
}
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WsxListLock );
|
|
if ( Next != Head ) {
|
|
RtlLeaveCriticalSection( &WsxLoadLock );
|
|
return( pWsx );
|
|
}
|
|
|
|
/*
|
|
* Load winstation extensions dll
|
|
*/
|
|
if ( (pWsx = _LoadWsxDll( pszWsxDll )) != NULL ) {
|
|
|
|
KdPrintEx((DPFLTR_TERMSRV_ID, DPFLTR_TRACE_LEVEL, "TERMSRV: FindWinStationExtensionDll(%S) succeeded\n", pszWsxDll ));
|
|
|
|
IcaSrvProcAddr.cbProcAddr =
|
|
(ULONG) sizeof(ICASRVPROCADDR);
|
|
|
|
IcaSrvProcAddr.pNotifySystemEvent =
|
|
(PICASRV_NOTIFYSYSTEMEVENT) NotifySystemEvent;
|
|
|
|
IcaSrvProcAddr.pSendWinStationMessage =
|
|
(PICASRV_SENDWINSTATIONMESSAGE) _SendWinStationMessage;
|
|
|
|
IcaSrvProcAddr.pGetContextForLogonId =
|
|
(PICASRV_GETCONTEXTFORLOGONID) _GetContextForLogonId;
|
|
|
|
IcaSrvProcAddr.pWinStationEnumCallBack =
|
|
(PICASRV_WINSTATIONENUMCALLBACK) _WinStationEnumCallback;
|
|
|
|
// initialize dll support procs
|
|
if ( pWsx->pWsxInitialize( &IcaSrvProcAddr ) ) {
|
|
RtlEnterCriticalSection( &WsxListLock );
|
|
InsertHeadList( &WsxListHead, &pWsx->Links );
|
|
RtlLeaveCriticalSection( &WsxListLock );
|
|
} else {
|
|
LocalFree( pWsx );
|
|
pWsx = NULL;
|
|
KdPrintEx((DPFLTR_TERMSRV_ID, DPFLTR_ERROR_LEVEL, "TERMSRV: FindWinStationExtensionDll(%S) failed\n", pszWsxDll ));
|
|
}
|
|
}
|
|
else {
|
|
KdPrintEx(( DPFLTR_TERMSRV_ID, DPFLTR_ERROR_LEVEL, "TERMSRV: FindWinStationExtensionDll(%S) failed\n", pszWsxDll ));
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WsxLoadLock );
|
|
|
|
|
|
/*
|
|
* Create the thread which will monitor the condition of the
|
|
* WinFrame Licenses and if necessary send Annoyance Messages.
|
|
*/
|
|
if ( pWsx && pWsx->pWsxWinStationAnnoyanceThread ) {
|
|
DWORD ThreadId;
|
|
HANDLE ThreadHandle;
|
|
|
|
ThreadHandle = CreateThread( NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)pWsx->pWsxWinStationAnnoyanceThread,
|
|
NULL,
|
|
THREAD_SET_INFORMATION,
|
|
&ThreadId );
|
|
|
|
if(ThreadHandle )
|
|
NtClose( ThreadHandle );
|
|
}
|
|
|
|
|
|
return( pWsx );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* WsxStackIoControl
|
|
*
|
|
* Callback routine called from ICAAPI.DLL to issue StackIoControl calls.
|
|
*
|
|
* ENTRY:
|
|
* nothing
|
|
*
|
|
* EXIT:
|
|
* nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
NTSTATUS
|
|
WsxStackIoControl(
|
|
IN PVOID pContext,
|
|
IN HANDLE pStack,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID pInBuffer,
|
|
IN ULONG InBufferSize,
|
|
OUT PVOID pOutBuffer,
|
|
IN ULONG OutBufferSize,
|
|
OUT PULONG pBytesReturned )
|
|
{
|
|
PWINSTATION pWinStation = (PWINSTATION)pContext;
|
|
NTSTATUS Status;
|
|
|
|
TRACE((hTrace, TC_ICASRV, TT_API1,
|
|
"TERMSRV: Enter WsxIcaIoControl, IoControlCode=%d\n",
|
|
(IoControlCode >> 2) & 0xfff));
|
|
|
|
if ( pWinStation &&
|
|
pWinStation->pWsx &&
|
|
pWinStation->pWsx->pWsxIcaStackIoControl ) {
|
|
|
|
Status = pWinStation->pWsx->pWsxIcaStackIoControl(
|
|
pWinStation->pWsxContext,
|
|
pWinStation->hIca,
|
|
pStack,
|
|
IoControlCode,
|
|
pInBuffer,
|
|
InBufferSize,
|
|
pOutBuffer,
|
|
OutBufferSize,
|
|
pBytesReturned );
|
|
} else {
|
|
Status = IcaStackIoControl(
|
|
pStack,
|
|
IoControlCode,
|
|
pInBuffer,
|
|
InBufferSize,
|
|
pOutBuffer,
|
|
OutBufferSize,
|
|
pBytesReturned );
|
|
}
|
|
|
|
return( Status );
|
|
}
|
|
|
|
|