526 lines
13 KiB
C
526 lines
13 KiB
C
|
/*************************************************************************
|
||
|
* T1.C
|
||
|
*
|
||
|
* Test program for ICA DLL Interface to ICA Device Driver
|
||
|
*
|
||
|
* copyright notice: Copyright 1996, Citrix Systems Inc.
|
||
|
* Copyright (C) 1997-1999 Microsoft Corp.
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
#include <stdio.h>
|
||
|
|
||
|
|
||
|
#define MAX_READ 2
|
||
|
|
||
|
/*
|
||
|
* Data types and definitions
|
||
|
*/
|
||
|
#define KEYBOARD_THREAD_STACKSIZE 1024 * 4
|
||
|
typedef struct _THREADDATA {
|
||
|
HANDLE handle;
|
||
|
} THREADDATA, * PTHREADDATA;
|
||
|
|
||
|
/*
|
||
|
* Global variables
|
||
|
*/
|
||
|
static HANDLE ghIca = NULL;
|
||
|
static HANDLE ghStack = NULL;
|
||
|
static HANDLE ghKeyboard = NULL;
|
||
|
static HANDLE ghMouse = NULL;
|
||
|
static HANDLE ghVideo = NULL;
|
||
|
static HANDLE ghBeep = NULL;
|
||
|
static HANDLE ghCommand = NULL;
|
||
|
static HANDLE ghCdm = NULL;
|
||
|
static HANDLE ghThreadKeyboardRead = NULL;
|
||
|
static HANDLE ghStopEvent = NULL;
|
||
|
|
||
|
/*
|
||
|
* Private procedures
|
||
|
*/
|
||
|
LONG OpenStacks( void );
|
||
|
LONG ConnectStacks( void );
|
||
|
LONG CloseStacks( void );
|
||
|
LONG Initialize( void );
|
||
|
VOID KeyboardReadThread( PTHREADDATA pThreadData );
|
||
|
LONG KeyboardTest( void );
|
||
|
|
||
|
/****************************************************************************
|
||
|
*
|
||
|
* main
|
||
|
*
|
||
|
* Main process entry point
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* argc (input)
|
||
|
* Number of parameters
|
||
|
*
|
||
|
* argv (input)
|
||
|
* Array of argument strings
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - Success
|
||
|
* other - Error return code
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
int _cdecl
|
||
|
main (int argc, char *argv[])
|
||
|
{
|
||
|
BOOL fSuccess = TRUE;
|
||
|
LONG rc;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Open the ICA driver, an ICA stack, and some channels
|
||
|
*/
|
||
|
if ( rc = OpenStacks() ) {
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Do some initialization
|
||
|
*/
|
||
|
if ( rc = Initialize() ) {
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "Sleeping...\n" );
|
||
|
Sleep(3000); // Give thread some time
|
||
|
|
||
|
if ( rc = KeyboardTest() ) {
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Wait for stop event to be triggered.
|
||
|
*/
|
||
|
printf( "ICAKEY main: Waiting for stop event...\n" );
|
||
|
WaitForSingleObject( ghStopEvent, (DWORD)30000 );
|
||
|
printf( "ICAKEY main: ...Stop event triggered\n" );
|
||
|
|
||
|
done:
|
||
|
fSuccess = !rc;
|
||
|
|
||
|
if ( rc = CloseStacks() ) {
|
||
|
fSuccess = FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
printf( "ICAKEY main: Test %s!\n", fSuccess ? "successful" : "failed" );
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
*
|
||
|
* OpenStacks
|
||
|
*
|
||
|
* Open ICA device driver, ICA stack, and ICA channels
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* void
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - Success
|
||
|
* other - Error return code
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
LONG
|
||
|
OpenStacks( void )
|
||
|
{
|
||
|
NTSTATUS rc;
|
||
|
|
||
|
/*
|
||
|
* Open an instance of the ICA device driver
|
||
|
*/
|
||
|
if ( rc = IcaOpen( &ghIca ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaOpen\n",
|
||
|
rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to ICA device driver: %08lX\n", ghIca );
|
||
|
|
||
|
/*
|
||
|
* Open an ICA stack instance
|
||
|
*/
|
||
|
if ( rc = IcaStackOpen( ghIca, Stack_Primary, &ghStack ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaStackOpen\n", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to ICA stack: %08lX\n", ghStack );
|
||
|
|
||
|
/*
|
||
|
* Open the keyboard channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Keyboard, NULL, &ghKeyboard ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( keyboard )\n", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to keyboard channel: %08lX\n", ghKeyboard );
|
||
|
|
||
|
/*
|
||
|
* Open the mouse channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Mouse, NULL, &ghMouse ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( mouse )", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to mouse channel: %08lX\n", ghMouse );
|
||
|
|
||
|
/*
|
||
|
* Open the video channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Video, NULL, &ghVideo ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( video )", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to video channel: %08lX\n", ghVideo );
|
||
|
|
||
|
/*
|
||
|
* Open the beep channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Beep, NULL, &ghBeep ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( beep )", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to beep channel: %08lX\n", ghBeep );
|
||
|
|
||
|
/*
|
||
|
* Open the command channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Command, NULL, &ghCommand ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( command )", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to command channel: %08lX\n", ghCommand );
|
||
|
|
||
|
/*
|
||
|
* Open the cdm channel
|
||
|
*/
|
||
|
if ( rc = IcaChannelOpen( ghIca, Channel_Virtual, VIRTUAL_CDM, &ghCdm ) ) {
|
||
|
printf( "ICAKEY OpenStacks: Error 0x%x from IcaChannelOpen( VIRTUAL_CDM )", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
printf( "ICAKEY OpenStacks: Handle to cdm channel: %08lX\n", ghCdm );
|
||
|
|
||
|
done:
|
||
|
return( rc );
|
||
|
}
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
*
|
||
|
* CloseStacks
|
||
|
*
|
||
|
* Close the ICA device driver, ICA stack, and ICA channels
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* void
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - Success
|
||
|
* other - Error return code
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
LONG
|
||
|
CloseStacks( void )
|
||
|
{
|
||
|
LONG rc = STATUS_SUCCESS;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Close the stop event handle
|
||
|
*/
|
||
|
if ( ghStopEvent ) {
|
||
|
CloseHandle( ghStopEvent );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Kill the keyboard read thread
|
||
|
*/
|
||
|
if ( ghThreadKeyboardRead ) {
|
||
|
TerminateThread( ghThreadKeyboardRead, 0 );
|
||
|
CloseHandle( ghThreadKeyboardRead );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the keyboard channel
|
||
|
*/
|
||
|
if ( ghKeyboard ) {
|
||
|
if ( rc = IcaChannelClose( ghKeyboard ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Keyboard )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the mouse channel
|
||
|
*/
|
||
|
if ( ghMouse ) {
|
||
|
if ( rc = IcaChannelClose( ghMouse ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Mouse )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the video channel
|
||
|
*/
|
||
|
if ( ghVideo ) {
|
||
|
if ( rc = IcaChannelClose( ghVideo ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Video )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the beep channel
|
||
|
*/
|
||
|
if ( ghBeep ) {
|
||
|
if ( rc = IcaChannelClose( ghBeep ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Beep )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the command channel
|
||
|
*/
|
||
|
if ( ghCommand ) {
|
||
|
if ( rc = IcaChannelClose( ghCommand ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Command )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Close the cdm channel
|
||
|
*/
|
||
|
if ( ghCdm ) {
|
||
|
if ( rc = IcaChannelClose( ghCdm ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaChannelClose( Cdm )\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Close the ICA stack instance
|
||
|
*/
|
||
|
if ( ghStack ) {
|
||
|
if ( rc = IcaStackClose( ghStack ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaStackClose\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Close the ICA device driver instance
|
||
|
*/
|
||
|
if ( ghIca ) {
|
||
|
if ( rc = IcaClose( ghIca ) ) {
|
||
|
printf( "ICAKEY CloseStacks: Error 0x%x from IcaClose\n", rc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( rc );
|
||
|
}
|
||
|
|
||
|
/****************************************************************************
|
||
|
*
|
||
|
* Initialize
|
||
|
*
|
||
|
* Do some initialization
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* void
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - Success
|
||
|
* other - Error return code
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
LONG
|
||
|
Initialize( void )
|
||
|
{
|
||
|
LONG rc = STATUS_SUCCESS;
|
||
|
DWORD tidKeyboardReadThread;
|
||
|
THREADDATA ThreadData;
|
||
|
|
||
|
/*
|
||
|
* Create stop event to wait on later.
|
||
|
*/
|
||
|
if ( !(ghStopEvent = CreateEvent( NULL, TRUE, FALSE, NULL )) ) {
|
||
|
printf( "ICAKEY Initialize: Error 0x%x in CreateEvent\n", GetLastError() );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
ThreadData.handle = ghKeyboard;
|
||
|
|
||
|
/*
|
||
|
* Startup the virtual channel read thread
|
||
|
*/
|
||
|
if ( !(ghThreadKeyboardRead = CreateThread( NULL,
|
||
|
KEYBOARD_THREAD_STACKSIZE,
|
||
|
(LPTHREAD_START_ROUTINE)KeyboardReadThread,
|
||
|
(LPVOID)&ThreadData, 0,
|
||
|
(LPDWORD)&tidKeyboardReadThread )) ) {
|
||
|
rc = GetLastError();
|
||
|
printf( "ICAKEY Initialize: Error 0x%x creating keyboard read thread\n", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
return( rc );
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Function: KeyboardReadThread
|
||
|
*
|
||
|
* Purpose: Keyboard read thread
|
||
|
*
|
||
|
* Entry:
|
||
|
* pThreadData
|
||
|
* Pointer to thread creation data
|
||
|
*
|
||
|
* Exit:
|
||
|
* void
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
VOID KeyboardReadThread( PTHREADDATA pThreadData )
|
||
|
{
|
||
|
int rc;
|
||
|
HANDLE handle = pThreadData->handle;
|
||
|
KEYBOARD_INPUT_DATA KeyboardInputData;
|
||
|
DWORD cbRead;
|
||
|
OVERLAPPED Overlapped;
|
||
|
DWORD dwError;
|
||
|
int NumberRead = 0;
|
||
|
|
||
|
Overlapped.Offset = 0;
|
||
|
Overlapped.OffsetHigh = 0;
|
||
|
Overlapped.hEvent = NULL;
|
||
|
|
||
|
printf( "Keyboard read thread starting...\n" );
|
||
|
|
||
|
/*
|
||
|
* Now dedicate this thread to monitor the keyboard
|
||
|
*/
|
||
|
do {
|
||
|
cbRead = 0;
|
||
|
|
||
|
if ( !ReadFile( ghKeyboard,
|
||
|
&KeyboardInputData,
|
||
|
sizeof( KeyboardInputData ),
|
||
|
&cbRead, &Overlapped ) ) {
|
||
|
|
||
|
dwError = GetLastError();
|
||
|
|
||
|
if ( dwError == ERROR_IO_PENDING ) {
|
||
|
// check on the results of the asynchronous read
|
||
|
if ( !GetOverlappedResult( ghKeyboard, &Overlapped,
|
||
|
&cbRead, TRUE) ) { // wait for result
|
||
|
printf( "ICAKEY KeyboardReadThread: Error 0x%x from GetOverlappedResult( Channel_Keyboard )\n",
|
||
|
GetLastError() );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
printf( "ICAKEY KeyboardReadThread: Error 0x%x from ReadFile( Channel_Keyboard )\n",
|
||
|
dwError );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf( "Unit number: 0x%x\nScan code: %02X\nFlags: %04X\nExtra info: %08X\n",
|
||
|
KeyboardInputData.UnitId,
|
||
|
KeyboardInputData.MakeCode,
|
||
|
KeyboardInputData.Flags,
|
||
|
KeyboardInputData.ExtraInformation );
|
||
|
NumberRead++;
|
||
|
|
||
|
if ( NumberRead == MAX_READ )
|
||
|
break;
|
||
|
|
||
|
} while ( 1 );
|
||
|
|
||
|
printf( "Keyboard read thread exiting...\n" );
|
||
|
SetEvent( ghStopEvent );
|
||
|
ExitThread( 0 );
|
||
|
}
|
||
|
|
||
|
/****************************************************************************
|
||
|
*
|
||
|
* KeyboardTest
|
||
|
*
|
||
|
* Stuff some data into the keyboard channel for testing purposes
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* void
|
||
|
*
|
||
|
* EXIT:
|
||
|
* STATUS_SUCCESS - Success
|
||
|
* other - Error return code
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
LONG
|
||
|
KeyboardTest( void )
|
||
|
{
|
||
|
LONG rc = STATUS_SUCCESS;
|
||
|
KEYBOARD_INPUT_DATA KeyboardInputData;
|
||
|
ULONG cbReturned;
|
||
|
|
||
|
/*
|
||
|
* Initialize the keystroke to fabricate
|
||
|
*/
|
||
|
KeyboardInputData.UnitId = 0;
|
||
|
KeyboardInputData.MakeCode = 0x32; // Capital 'M'
|
||
|
KeyboardInputData.Flags = KEY_MAKE;
|
||
|
KeyboardInputData.Reserved = 0;
|
||
|
KeyboardInputData.ExtraInformation = 0;
|
||
|
|
||
|
/*
|
||
|
* First stuff the make
|
||
|
*/
|
||
|
if ( rc = IcaChannelIoControl( ghKeyboard,
|
||
|
IOCTL_KEYBOARD_ICA_INPUT,
|
||
|
&KeyboardInputData,
|
||
|
sizeof( KeyboardInputData ),
|
||
|
NULL,
|
||
|
0,
|
||
|
&cbReturned ) ) {
|
||
|
printf( "ICAKEY KeyboardTest: Error 0x%x in IcaChannelIoControl\n", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
KeyboardInputData.Flags = KEY_BREAK;
|
||
|
|
||
|
/*
|
||
|
* Now stuff the break
|
||
|
*/
|
||
|
if ( rc = IcaChannelIoControl( ghKeyboard,
|
||
|
IOCTL_KEYBOARD_ICA_INPUT,
|
||
|
&KeyboardInputData,
|
||
|
sizeof( KeyboardInputData ),
|
||
|
NULL,
|
||
|
0,
|
||
|
&cbReturned ) ) {
|
||
|
printf( "ICAKEY KeyboardTest: Error 0x%x in IcaChannelIoControl\n", rc );
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
return( rc );
|
||
|
}
|