/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
Event.c
Abstract:
This module contains the code of the input event handler. It
read input from the input buffer queue and divide the event to 2
different queues: Kbd & Mou.
It also contains the code of the Kbd & Mou routines of reading
events from their queues.
Author:
Michael Jarus (mjarus) 3-Nov-1991
Environment:
User Mode Only
Revision History:
--*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#if PMNT
#include <windows.h>
#include <wincon.h>
#include <ntddvdeo.h>
#include "conapi.h"
#define PMNT_CONSOLE_INCLUDED // to fix a redefinition in "os2nt.h"
#endif // PMNT
#define WIN32_ONLY
#include "os2ses.h"
#include "event.h"
#include "trans.h"
#if PMNT
#ifndef FIELD_OFFSET
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
#endif
#define INCL_32BIT
#include "pmnt.h"
#endif
#define AccentedKey 0x0200 // Key was translated using previous accent.
#define KeyTypeMask 0x003F // Isolates the Key Type field of DDFlags.
#define AccentKey 0x0010 // @@ This packet is an accent key
#if PMNT
/* Hand-shaking events */
HANDLE hStartHardwareEvent;
HANDLE hEndHardwareEvent;
LONG ScreenX = 640L;
LONG ScreenY = 480L;
extern PSZ Od2PgmFilePath;
#endif // PMNT
VOID
ExitThread(
ULONG dwExitCode
);
#if PMNT
DWORD
NtClose(
IN HANDLE Handle
);
#endif // PMNT
VOID Od2ExitGP();
DWORD MonQueueClose(IN HANDLE hMon);
DWORD
ReadInputEvent(IN ULONG PeekFlag);
BOOLEAN
Ow2WriteBackDummyEvent(VOID);
BOOLEAN
Ow2ClearupDummyEvent(VOID);
DWORD
Ow2FaultFilter(
IN DWORD uFaultFilter,
IN PEXCEPTION_POINTERS lpExP);
VOID Ow2DisplayExceptionInfo( VOID );
DWORD
Ow2GetInputConsoleMode(
#if DBG
PSZ FuncName,
#endif
LPDWORD lpMode
);
DWORD
Ow2SetInputConsoleMode(
#if DBG
PSZ FuncName,
#endif
DWORD dwMode
);
CRITICAL_SECTION QueueInputCriticalSection;
ULONG EventServerThreadSuspend = TRUE;
ULONG NextEventServerThreadSuspend;
HANDLE SuspendEvent;
HANDLE HandsOffEvent;
HANDLE HandsOnEvent;
BOOL IgnoreNextMouseEventDueToFocus = FALSE;
BOOL EventThreadHandsOff = FALSE;
DWORD Ow2dwInputMode; /* Console Current Input Mode */
DWORD Ow2dwWinInputMode; /* The desired mode (DefaultWinInputMode | ENABLE_MOUSE_INPUT) */
#if DBG
BYTE GetOs2MouEventIntoQueueStr[] = "GetOs2MouEventIntoQueue";
BYTE Ow2GetOs2KbdEventIntoQueueStr[] = "Ow2GetOs2KbdEventIntoQueue";
BYTE StartEventHandlerForSessionStr[] = "StartEventHandlerForSession";
BYTE AddConAfterWinProcessStr[] = "AddConAfterWinProcess";
BYTE RemoveConForWinProcessStr[] = "RemoveConForWinProcess";
BYTE ReadInputEventStr[] = "ReadInputEvent";
BYTE StartEventHandlerStr[] = "StartEventHandler";
BYTE InitQueueStr[] = "InitQueue";
BYTE InitMouQueueStr[] = "InitMouQueue";
BYTE EventServerThreadStr[] = "EventServerThread";
BYTE Ow2MouOnStr[] = "Ow2MouOn";
BYTE Ow2MouOffStr[] = "Ow2MouOff";
#endif
#if DBG
ULONG InternalDebug = 0;
#define InputModeDebug 0001
#define InputEventDebug 0002
#endif
PVOID
StartEventHandlerForSession(VOID)
{
DWORD NewInput = (OS2_DEFAULT_INPUT_MODE /*| ENABLE_MOUSE_INPUT*/);
EventLoop = TRUE;
InitializeCriticalSection(&QueueInputCriticalSection);
if (hStdInConsoleType)
{
hConsoleInput = hConsoleStdIn;
} else
{
hConsoleInput = Or2WinCreateFileW(
#if DBG
StartEventHandlerForSessionStr,
#endif
L"CONIN$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, /* &SecurityAttributes */
OPEN_EXISTING,
0,
NULL
);
if (hConsoleInput == INVALID_HANDLE_VALUE)
{
#if DBG
ASSERT1( "StartEvent: unable to create CONIN$", FALSE );
#endif
// return(NULL);
}
}
if (!Or2WinGetConsoleMode(
#if DBG
StartEventHandlerForSessionStr,
#endif
hConsoleInput,
&DefaultWinInputMode
))
{
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "StartEvent: Can not get CONIN Mode", FALSE );
}
#endif
DefaultWinInputMode = WINDOW_DEFAULT_INPUT_MODE;
}
Ow2dwWinInputMode = DefaultWinInputMode /*| ENABLE_MOUSE_INPUT*/;
Ow2dwInputMode = DefaultWinInputMode;
InputModeFlags = WINDOW_DEFAULT_INPUT_MODE;
if (Ow2SetInputConsoleMode(
#if DBG
StartEventHandlerForSessionStr,
#endif
Ow2dwWinInputMode
))
{
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "StartEvent: Can not set CONIN Mode", FALSE );
} else
KdPrint(("OS2SES(StartEvent): Can not set CONIN Mode\n"));
#endif
} else
{
Ow2dwInputMode = Ow2dwWinInputMode;
}
InputModeFlags = NewInput;
HandleHeap = Or2WinHeapCreate(
#if DBG
StartEventHandlerForSessionStr,
#endif
0, // Serialize the heap
HANDLE_HEAP_SIZE, // Init size = 64K
0 // Max size is unlimited
);
if (HandleHeap == NULL)
{
#if DBG
ASSERT1( "StartEvent: unable to create heap for event-queue", FALSE );
#endif
return(NULL);
}
KbdEventQueueSize = PortMessageHeaderSize + KEYBOARD_QUEUE_SIZE;
MouEventQueueSize = PortMessageHeaderSize + MOUSE_QUEUE_SIZE;
//
// Complete window initialization and set SesGrp parameters
//
if( SesGrpInit() || KbdInit() || MouInit() || InitMonitor() || VioInitForSession() ||
AnsiInitForSession())
{
return(NULL);
}
SuspendEvent = Or2WinCreateEventW(
#if DBG
StartEventHandlerForSessionStr,
#endif
NULL,
FALSE, /* auto reset */
FALSE, // not set at creation
NULL
);
if (SuspendEvent == NULL)
{
#if DBG
ASSERT1( "StartEvent: unable to create event", FALSE );
#endif
return (NULL);
}
HandsOffEvent = Or2WinCreateEventW(
#if DBG
StartEventHandlerForSessionStr,
#endif
NULL,
FALSE, // auto reset
FALSE, // Clear at creation
NULL
);
if (HandsOffEvent == NULL)
{
#if DBG
ASSERT1( "StartEvent: unable to create HandsOff event", FALSE );
#endif
return (NULL);
}
HandsOnEvent = Or2WinCreateEventW(
#if DBG
StartEventHandlerForSessionStr,
#endif
NULL,
FALSE, // auto reset
TRUE, // Set at creation
NULL
);
if (HandsOnEvent == NULL)
{
#if DBG
ASSERT1( "StartEvent: unable to create HandsOn event", FALSE );
#endif
return (NULL);
}
Os2WindowFocus = (ULONG)-1;
return ((PVOID)KbdQueue);
}
PVOID
StartEventHandler(VOID)
{
HandleHeap = Or2WinHeapCreate(
#if DBG
StartEventHandlerStr,
#endif
0, // Serialize the heap
HANDLE_HEAP_SIZE, // Init size = 64K
0 // Max size is unlimited
);
if (HandleHeap == NULL)
{
#if DBG
ASSERT1( "StartEvent(non root): unable to create heap for event-queue", FALSE );
#endif
return(NULL);
}
if (VioInit() || AnsiInit())
{
return(NULL);
}
return ((PVOID)-1L);
}
DWORD
InitQueue(IN PKEY_EVENT_QUEUE *ppKbdQueue)
{
PKEY_EVENT_QUEUE pKbdQueue;
PBYTE Ptr;
*ppKbdQueue == NULL;
Ptr = Or2WinHeapAlloc(
#if DBG
InitQueueStr,
#endif
HandleHeap,
0,
KbdEventQueueSize
);
if ( Ptr == NULL )
{
#if DBG
KdPrint(("OS2SES(Event-InitKbdQueue): unable to allocate handle\n"));
#endif
return ERROR_KBD_NO_MORE_HANDLE;
}
pKbdQueue = (PKEY_EVENT_QUEUE) ( Ptr + PortMessageHeaderSize );
RtlZeroMemory(pKbdQueue, sizeof(MON_HEADER));
pKbdQueue->MonHdr.MemoryStartAddress = Ptr;
pKbdQueue->In = pKbdQueue->Out = pKbdQueue->Event;
pKbdQueue->End = pKbdQueue->Event + (KEYBOARD_QUEUE_LENGTH-1);
if (KbdQueue != NULL)
{
pKbdQueue->Setup = KbdQueue->Setup;
pKbdQueue->Cp = KbdQueue->Cp;
pKbdQueue->bNlsShift = KbdQueue->bNlsShift;
}
pKbdQueue->Count = 1;
// add initialization for MON_HDR ( & to sign queue-end)
InitializeCriticalSection(&pKbdQueue->MonHdr.SyncCriticalSection);
pKbdQueue->MonHdr.MonReg.Pos = 3;
pKbdQueue->MonHdr.DevType = KbdDevice;
*ppKbdQueue = pKbdQueue;
return(FALSE);
}
DWORD
InitMouQueue(IN PMOU_EVENT_QUEUE *ppMouQueue)
{
PMOU_EVENT_QUEUE pMouQueue;
PBYTE Ptr;
*ppMouQueue = NULL;
Ptr = Or2WinHeapAlloc(
#if DBG
InitMouQueueStr,
#endif
HandleHeap,
0,
MouEventQueueSize
);
if ( Ptr == NULL )
{
#if DBG
KdPrint(("OS2SES(Event-InitMouQueue): unable to allocate handle\n"));
#endif
return TRUE;
}
pMouQueue = (PMOU_EVENT_QUEUE) ( Ptr + PortMessageHeaderSize );
RtlZeroMemory(pMouQueue, sizeof(MON_HEADER));
pMouQueue->MonHdr.MemoryStartAddress = Ptr;
pMouQueue->In = pMouQueue->Out = pMouQueue->Event;
pMouQueue->End = pMouQueue->Event + (MOUSE_QUEUE_LENGTH-1);
// add initialization for MON_HDR ( & to sign queue-end)
InitializeCriticalSection(&pMouQueue->MonHdr.SyncCriticalSection);
pMouQueue->MonHdr.MonReg.Pos = 3;
pMouQueue->MonHdr.DevType = MouseDevice;
*ppMouQueue = pMouQueue;
return(FALSE);
}
DWORD
AddConAfterWinProcess()
{
DWORD Rc;
Or2WinEnterCriticalSection(
#if DBG
AddConAfterWinProcessStr,
#endif
&QueueInputCriticalSection
);
EventServerThreadSuspend = NextEventServerThreadSuspend;
if(EventServerThreadSuspend)
{
if(KbdMonQueue->MonHdr.WaitForEvent || MouMonQueue->MonHdr.WaitForEvent)
{
Or2WinSetEvent(
#if DBG
AddConAfterWinProcessStr,
#endif
SuspendEvent
);
EventServerThreadSuspend = FALSE;
}
}
Or2WinLeaveCriticalSection(
#if DBG
AddConAfterWinProcessStr,
#endif
&QueueInputCriticalSection
);
if (!Or2WinSetConsoleMode(
#if DBG
AddConAfterWinProcessStr,
#endif
hConsoleOutput,
SesGrp->OutputModeFlags
))
{
Rc = GetLastError();
#if DBG
KdPrint(("ServeWinWaitThread: SetConsoleMode failed\n",
Rc));
#endif
}
if (Ow2SetInputConsoleMode(
#if DBG
AddConAfterWinProcessStr,
#endif
Ow2dwWinInputMode
))
{
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "AddConAfterWinProcess: Can not set CONIN Mode", FALSE );
} else
KdPrint(("OS2SES(AddConAfterWinProcess): Can not set CONIN Mode\n"));
#endif
} else
{
Ow2dwInputMode = Ow2dwWinInputMode;
}
//
// Put EventServerThread back to work
//
Or2WinSetEvent(
#if DBG
AddConAfterWinProcessStr,
#endif
HandsOnEvent
);
return (NO_ERROR);
}
DWORD
RemoveConForWinProcess()
{
DWORD Rc;
EventThreadHandsOff = TRUE;
Or2WinEnterCriticalSection(
#if DBG
RemoveConForWinProcessStr,
#endif
&QueueInputCriticalSection
);
NextEventServerThreadSuspend = TRUE;
if(KbdMonQueue->MonHdr.WaitForEvent || MouMonQueue->MonHdr.WaitForEvent)
{
NextEventServerThreadSuspend = FALSE;
}
EventServerThreadSuspend = FALSE;
//
// Set the suspend event, to release EventServerThread, to
// will take hands off the console
//
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("RemoveConForWinProcess: SetEvent\n"));
}
#endif
Or2WinSetEvent(
#if DBG
RemoveConForWinProcessStr,
#endif
SuspendEvent
);
//
// Write Back to console in case EventThread is in ReadInput()
//
Ow2WriteBackDummyEvent();
Or2WinLeaveCriticalSection(
#if DBG
RemoveConForWinProcessStr,
#endif
&QueueInputCriticalSection
);
//
// Wait to synchronize with EventServerThread
//
WaitForSingleObject(HandsOffEvent, INFINITE);
//
// Set default console mode here. We can be sure that EventServerThread will
// not change these settings, because it has set HandsOffEvent and going to
// wait on HandsOnEvent.
//
if (Rc = Ow2SetInputConsoleMode(
#if DBG
RemoveConForWinProcessStr,
#endif
DefaultWinInputMode
))
{
#if DBG
KdPrint(("OS2SES(RemoveConForWinProcess): SetConsoleMode(Input) failed \n"));
#endif
}
if (!Or2WinSetConsoleMode(
#if DBG
RemoveConForWinProcessStr,
#endif
hConsoleOutput,
SesGrp->DefaultWinOutputMode
))
{
#if DBG
KdPrint(("OS2SES(event-RemoveConForWinProcess): SetConsoleMode(Output) failed \n"));
#endif
}
return (0L);
}
DWORD
EventServerThread(IN PVOID Parameter)
{
UNREFERENCED_PARAMETER(Parameter);
try {
restart:
WaitForSingleObject( HandsOnEvent, INFINITE );
if (SesGrp->Os2ssLCID != SesGrp->Win32LCID)
{
if(!Or2WinSetThreadLocale(
#if DBG
EventServerThreadStr,
#endif
SesGrp->Os2ssLCID
))
{
ASSERT1("OS2SS(event): cannot set Thread Locale", FALSE);
}
}
EventServerThreadSuspend = TRUE;
for ( ; ; )
{
//SuspendEvent
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("EventServerThread: WaitEvent\n"));
}
#endif
//
// Wait for an application to ask for Keyboard/Monitor/Mouse
//
while (WaitForSingleObject( SuspendEvent, INFINITE ));
#if PMNT
/*
* Terminate EventServerThread for PMNT processes.
*/
if (ProcessIsPMProcess()) {
NtClose(EventServerThreadHandle);
ExitThread(0L);
}
#endif
if (EventThreadHandsOff) {
EventThreadHandsOff = FALSE;
//
// RemoveConForWinProcess puts a dummy event to wake this
// thread from ReadInputEvent, clear it is there
//
Ow2ClearupDummyEvent();
SetEvent( HandsOffEvent );
goto restart;
}
EventServerThreadSuspend = FALSE;
ReadInputEvent(0L); // read next event
if (EventThreadHandsOff) {
EventThreadHandsOff = FALSE;
//
// RemoveConForWinProcess puts a dummy event to wake this
// thread from ReadInputEvent, clear it is there
//
Ow2ClearupDummyEvent();
SetEvent( HandsOffEvent );
goto restart;
}
EnterCriticalSection(&QueueInputCriticalSection);
if (EventThreadHandsOff) {
EventThreadHandsOff = FALSE;
//
// RemoveConForWinProcess puts a dummy event to wake this
// thread from ReadInputEvent, clear it is there
//
Ow2ClearupDummyEvent();
SetEvent( HandsOffEvent );
LeaveCriticalSection(&QueueInputCriticalSection);
goto restart;
}
if(KbdMonQueue->MonHdr.WaitForEvent || MouMonQueue->MonHdr.WaitForEvent ||
SesGrp->PauseScreenUpdate )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("EventServerThread: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
} else
{
EventServerThreadSuspend = TRUE;
}
LeaveCriticalSection(&QueueInputCriticalSection);
}
}
//
// if Os2Debug is on, and ntsd is attached, it will get the second chance
//
#if DBG
except( (Os2Debug ? Ow2FaultFilter(EXCEPTION_CONTINUE_SEARCH, GetExceptionInformation()):
Ow2FaultFilter(EXCEPTION_EXECUTE_HANDLER, GetExceptionInformation())) ) {
#else
except( Ow2FaultFilter(EXCEPTION_EXECUTE_HANDLER, GetExceptionInformation()) ) {
#endif
#if DBG
KdPrint(("OS2SES: Internal error - Exception occured in EventServerThread\n"));
#endif
Ow2DisplayExceptionInfo();
ExitThread(1);
}
ExitThread(0L);
return(0L);
}
DWORD
ReadInputEvent(IN ULONG PeekFlag)
/*++
Routine Description:
This routine get next Input Event from queue and handle it
according to the EventType.
Arguments:
PeekFlag - indicate if should try to peek before read (1)
or to wait till next event(0).
Return Value:
0 - no event
-1 - try again (event was ignore or was illegal)
other (KEY_EVENT, MOUSE_EVENT) - type of the event read and handled
(WINDOW_BUFFER_SIZE_EVENT, MENU_EVENT, FOCUS_EVENT)
Note:
--*/
{
INPUT_RECORD In;
KEYEVENTINFO KbdEvent[3];
MOU_MON_PACKAGE MouEvent;
DWORD cEvents, Rc, RetCode = 0, i, j, NumKbd;
DWORD InConMode;
BOOL ReadInputFail = FALSE;
/*
* 1. Set ConsoleInputMode
*
* This is done if there is other proess performing ReadConsoleInput
* from the same win-session (who might change the input mode).
* Another reason: when KbdRead(or KbdCharIn) is stopped for a long
* period for another processing, the OS2SS won't detect ^C (like
* ISQL, bug# 1341, 3/31/93 MJarus).
*/
InConMode = WINDOW_DEFAULT_INPUT_MODE;
if (Ow2GetInputConsoleMode(
#if DBG
ReadInputEventStr,
#endif
&InConMode
))
{
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "ReadInputEvent: Can not get CONIN Mode", FALSE );
}
#endif
}
Ow2SetInputConsoleMode(
#if DBG
ReadInputEventStr,
#endif
InputModeFlags
);
/*
* 2. Peek ConsoleInput
*
* In case ReadInputEvent is called from KbdXxxx, MouXxxx or DosMonXxx
* API and there is no data in buffer.
* PeekConsoleInput is called before ReadConsoleInput to check if there
* is data in the input queue. If no data (and wait is ON) -
* EventServerThread will resume to wait for the data and will send reply
* to client.
*/
if (PeekFlag)
{
if (!PeekConsoleInputW(
hConsoleInput,
&In,
1L,
&cEvents
))
{ /* check why, should not happend */
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1("EventServer: unable to peek from CONIN$", FALSE);
} else
{
KdPrint(("OS2SES(EventSever): unable to peek from CONIN$\n"));
}
#endif
ReadInputFail = TRUE;
RetCode = (DWORD)-1;
} else if (cEvents != 1L)
{
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
//KdPrint(("OS2SES(EventSever): no data peeked from CONIN$\n"));
}
#endif
ReadInputFail = TRUE;
//RetCode = 0;
}
if ( ReadInputFail )
{
Ow2SetInputConsoleMode(
#if DBG
ReadInputEventStr,
#endif
InConMode
);
return(RetCode);
}
}
/*
* 3. Read ConsoleInput
*
* Wait for InputEvent
*/
if (!ReadConsoleInputW(
hConsoleInput,
&In,
1L,
&cEvents
))
{ /* check why, should not happend */
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1("EventServer: unable to read from CONIN$", FALSE);
} else
KdPrint(("OS2SES(EventSever): unable to read from CONIN$\n"));
#endif
ReadInputFail = TRUE;
RetCode = (DWORD)-1L;
} else if (cEvents != 1L)
{ /* check why, should not happend */
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "EventServer: no data read from CONIN$", FALSE );
} else
KdPrint(("OS2SES(EventSever): no data read from CONIN$\n"));
#endif
ReadInputFail = TRUE;
RetCode = (DWORD)-1L;
}
Ow2SetInputConsoleMode(
#if DBG
ReadInputEventStr,
#endif
InConMode
);
if ( ReadInputFail )
{
return(RetCode);
}
/*
* 4. Get Time Stamp (needed for KBD and MOUSE events)
*
* Set RetCode to be the EventType (in case the event
* will be handled)
*
* Handle the Event according its type
*/
RetCode = (DWORD)In.EventType;
if (In.EventType != MOUSE_EVENT)
{
IgnoreNextMouseEventDueToFocus = FALSE;
}
switch (In.EventType)
{
case KEY_EVENT :
RetCode = (DWORD)-1L;
for ( i = In.Event.KeyEvent.wRepeatCount,
In.Event.KeyEvent.wRepeatCount = 1 ; i ; i-- )
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("EventServer(KBD): queue %lx, char %x\n",
KbdMonQueue, In.Event.KeyEvent.uChar.AsciiChar));
}
#endif
/*
* update KbdInfo: Kbd-data & time
*/
if (!(NumKbd = MapWin2Os2KbdInfo(&(In.Event.KeyEvent),
&KbdEvent[0])))
{
continue;
}
KbdEvent[0].KeyInfo[0].KeyInfo.time = GetTickCount();
/*
* ^Break
* ^C for ASCII mode only
*
*/
if (Rc = CheckForBreakEvent(&KbdEvent[0]))
{
#if DBG
IF_OD2_DEBUG( KBD )
{
KdPrint(("Event: CheckForBreakEvent %u, ignore char\n", Rc));
}
#endif
if (Rc == 1) // not PopUp
{
//BUGBUG release Waiting threads
}
continue;
}
/*
* write event
*/
for ( j = 0 ; j < NumKbd ; j++ )
{
Rc = (USHORT)PutMonInput(
sizeof(KBD_MON_PACKAGE),
KbdMonQueue,
KbdEvent[0].wRepeatCount,
&KbdEvent[j].KeyInfo[0],
NULL,
NULL);
if (Rc)
{
/* BUGBUG=> ? beep */
i = 1;
break;
}
RetCode = KEY_EVENT;
//RetCode = 0;
}
}
break;
case MOUSE_EVENT :
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("EventServer(MOU): State %x, Flag %x, Pos %u-%u, queue %lx\n",
In.Event.MouseEvent.dwButtonState,
In.Event.MouseEvent.dwEventFlags,
In.Event.MouseEvent.dwMousePosition.Y,
In.Event.MouseEvent.dwMousePosition.X,
MouMonQueue));
} else IF_OD2_DEBUG( MOU )
{
KdPrint(("EventServer: State %x, Flag %x, Pos %u-%u\n",
In.Event.MouseEvent.dwButtonState,
In.Event.MouseEvent.dwEventFlags,
In.Event.MouseEvent.dwMousePosition.Y,
In.Event.MouseEvent.dwMousePosition.X));
}
#endif
//
// YS - 6.8.93 overcome the case where the console position is negative
//
if ( (LONG)(In.Event.MouseEvent.dwMousePosition.X) < 0)
{
In.Event.MouseEvent.dwMousePosition.X = 0;
}
if ( (LONG)(In.Event.MouseEvent.dwMousePosition.Y) < 0)
{
In.Event.MouseEvent.dwMousePosition.Y = 0;
}
MouPtrLoc.row = In.Event.MouseEvent.dwMousePosition.Y;
MouPtrLoc.col = In.Event.MouseEvent.dwMousePosition.X;
if(IgnoreNextMouseEventDueToFocus &&
In.Event.MouseEvent.dwButtonState &&
(In.Event.MouseEvent.dwEventFlags == MOUSE_MOVED))
{
In.Event.MouseEvent.dwButtonState = 0;
}
IgnoreNextMouseEventDueToFocus = FALSE;
/*
* update MouInfo: Mou-data & time
*/
if (!MouNumber ||
(MouDevStatus & MOUSE_DISABLED) ||
!MapWin2Os2MouEvent(&MouEvent.MouInfo,
&In.Event.MouseEvent))
{
RetCode = (DWORD)-1L;
break;
}
MouEvent.MouInfo.time = GetTickCount();
/*
* write mouse event to queue
*/
Rc = (USHORT)PutMonInput(
sizeof(MOU_MON_PACKAGE),
(PKEY_EVENT_QUEUE)MouMonQueue,
1,
(PKBD_MON_PACKAGE)&MouEvent,
NULL,
NULL);
if (!Rc && !MouEvent.MouInfo.fs)
{
/*
* Release of last button - add OS2_MOUSE_MOTION
*/
MouEvent.MouInfo.fs = OS2_MOUSE_MOTION;
Rc = (USHORT)PutMonInput(
sizeof(MOU_MON_PACKAGE),
(PKEY_EVENT_QUEUE)MouMonQueue,
1,
(PKBD_MON_PACKAGE)&MouEvent,
NULL,
NULL);
}
if (Rc)
/* BUGBUG=> ? over-write last event */ ;
break;
case WINDOW_BUFFER_SIZE_EVENT :
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
KdPrint(("EventServer: window event size %x:%x\n",
In.Event.WindowBufferSizeEvent.dwSize.Y,
In.Event.WindowBufferSizeEvent.dwSize.X));
}
#endif
break;
case MENU_EVENT :
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
KdPrint(("EventServer: menu event command %x\n",
In.Event.MenuEvent.dwCommandId));
}
#endif
break;
case FOCUS_EVENT :
if(Os2WindowFocus != (ULONG)In.Event.FocusEvent.bSetFocus)
{
//if(Os2WindowFocus != (ULONG)-1)
{
SendNewFocusSet((ULONG)In.Event.FocusEvent.bSetFocus);
}
Os2WindowFocus = (ULONG)In.Event.FocusEvent.bSetFocus;
IgnoreNextMouseEventDueToFocus = Os2WindowFocus;
}
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
KdPrint(("EventServer: focus event(%u-%s)\n",
In.Event.FocusEvent.bSetFocus,
(In.Event.FocusEvent.bSetFocus) ? "Set" : "Reset"));
}
#endif
break;
default :
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
KdPrint(("OS2SES(Event): unknown event %x\n",
In.EventType));
}
#endif
RetCode = (DWORD)-1L;
break;
}
return(RetCode);
}
DWORD
CheckForBreakEvent(IN PKEYEVENTINFO KbdEvent)
{
DWORD Rc = 0;
UCHAR Os2ScanCode = KbdEvent->KeyInfo[0].KeyInfo.chScan;
BOOL Os2ControlOn = ( KbdEvent->KeyInfo[0].KeyInfo.fsState & OS2_CONTROL );
/*
* 1. ^Break
* ^C for ASCII mode only
* 2. Pause
* ^S - (not paused)
* 3. End-Pause
*
* return: 0 - character
* 1 - ^Break/^C
* 2 - ignore (^Break/^C in PopUp, ^S[pause], end_pause)
*/
if (( KbdEvent->KeyInfo[0].KeyboardFlag & KBD_KEY_BREAK ) ||
( KbdEvent->KeyInfo[0].KeyInfo.fbStatus & 1 ))
{
// ignore:
// break
// shift
return (0);
}
if ( SesGrp->PauseScreenUpdate )
{
// Screen is Paused: release (if no ^C or ^BRK) and ignore key (always)
if ( Os2ScanCode != 0xFF ) // not pause
{
EnableScreenUpdate();
}
Rc = 2;
} else if (( Os2ControlOn && ( Os2ScanCode == 0x1F ) && KbdAsciiMode ) ||
( !Os2ControlOn && ( Os2ScanCode == 0xFF )))
{
// ^S in ASCII or PAUSE (but not ^)
DisableScreenUpdate();
return (2);
}
if ( !Os2ControlOn )
{
return (Rc);
}
if (( Os2ScanCode == 0xFF ) || // ^Brk
(( Os2ScanCode == 0x2E ) && KbdAsciiMode )) // ^C in ACSII mode
{
if (hPopUpOutput != (HANDLE) NULL ) // PopUp - ignore
{
return (2);
}
#if DBG
IF_OD2_DEBUG( CLEANUP )
{
if ( Os2ScanCode == 0x2E )
KdPrint(("Os2: send ^C event to server\n"));
else
KdPrint(("Os2: send ^Break event to server\n"));
}
#endif
//EventLoop = FALSE;
SendSignalToOs2Srv(
( Os2ScanCode == 0x2E) ?
XCPT_SIGNAL_INTR : XCPT_SIGNAL_BREAK);
#if DBG
IF_OD2_DEBUG( CLEANUP )
{
KdPrint(("Os2: event was send\n"));
}
#endif
return (1);
}
if ( Os2ControlOn && KbdAsciiMode && ( Os2ScanCode == 0x19 ) && // ^P in ASCII
!( KbdEvent->KeyInfo[0].KeyInfo.fsState & OS2_ALT ))
{
return (2);
}
return (Rc);
}
DWORD
GetKeyboardInput( IN ULONG Flag,
OUT PKEYEVENTINFO Event,
IN PVOID pMsg,
OUT PULONG pReply)
{
WORD KeyCount = Event->wRepeatCount;
DWORD Rc;
BOOL IgnoreKey;
for ( ; EventLoop ; )
{
if ( KbdQueue->In == KbdQueue->Out )
{
SaveKbdPortMessegeInfo(KbdQueue->MonHdr.MemoryStartAddress,
(PVOID)&KbdRequestSaveArea,
pMsg);
/*
* Enter critical Section
*/
EnterCriticalSection(&QueueInputCriticalSection);
if (KbdQueue->In == KbdQueue->Out)
{
if (!EventServerThreadSuspend)
{
goto NoKbdReturn;
}
if (KbdQueue != KbdMonQueue)
{
goto NoKbdReturn;
}
LeaveCriticalSection(&QueueInputCriticalSection);
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)KEY_EVENT))
{
;
}
EnterCriticalSection(&QueueInputCriticalSection);
if (KbdQueue->In == KbdQueue->Out)
{
if (EventServerThreadSuspend &&
((( Flag & WAIT_MASK) != IO_NOWAIT ) ||
SesGrp->PauseScreenUpdate ))
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetKeyboardInput: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
NoKbdReturn:
if ((Flag & WAIT_MASK) != IO_NOWAIT)
{
#if DBG
IF_OD2_DEBUG( KBD )
{
KdPrint(("GetKeyboardInput: no kbd so wait\n"));
}
#endif
KbdQueue->MonHdr.WaitForEvent = TRUE;
*pReply = 0;
}
LeaveCriticalSection(&QueueInputCriticalSection);
return (NO_ERROR);
} else if ( SesGrp->PauseScreenUpdate && EventServerThreadSuspend )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetKeyboardInput 2: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
}
LeaveCriticalSection(&QueueInputCriticalSection);
} else
{
*Event = *(KbdQueue->Out);
IgnoreKey = (BOOL)KbdCheckPackage(&Event->KeyInfo[0]);
if ( IgnoreKey || ( KbdQueue->Out->wRepeatCount <= KeyCount ))
{
if (KbdQueue->Out == KbdQueue->End)
KbdQueue->Out = KbdQueue->Event;
else
KbdQueue->Out++;
} else
{
KbdQueue->Out->wRepeatCount -= KeyCount;
Event->wRepeatCount = KeyCount;
}
if ( !IgnoreKey )
{
return (1L);
}
}
}
return (0L);
}
DWORD
GetOs2MouEvent( IN USHORT WaitFlag,
OUT PMOUEVENTINFO Event,
IN PVOID pMsg,
OUT PULONG pReply)
{
DWORD Rc;
for ( ; EventLoop ; )
{
if (MouQueue->In == MouQueue->Out)
{
SavePortMessegeInfo(MouQueue->MonHdr.MemoryStartAddress, pMsg);
/*
* Enter critical Section
*/
EnterCriticalSection(&QueueInputCriticalSection);
if (MouQueue->In == MouQueue->Out)
{
if (!EventServerThreadSuspend)
{
goto NoMouReturn;
}
if (MouQueue != MouMonQueue)
{
goto NoMouReturn;
}
LeaveCriticalSection(&QueueInputCriticalSection);
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)MOUSE_EVENT))
{
;
}
EnterCriticalSection(&QueueInputCriticalSection);
if (MouQueue->In == MouQueue->Out)
{
if (EventServerThreadSuspend &&
(( WaitFlag != MOU_NOWAIT ) ||
SesGrp->PauseScreenUpdate ))
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetOs2MouEvent: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
NoMouReturn:
if ( WaitFlag != MOU_NOWAIT)
{
MouQueue->MonHdr.WaitForEvent = TRUE;
*pReply = 0;
}
LeaveCriticalSection(&QueueInputCriticalSection);
return (NO_ERROR);
} else if ( SesGrp->PauseScreenUpdate && EventServerThreadSuspend )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetOs2MouEvent 2: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
}
LeaveCriticalSection(&QueueInputCriticalSection);
} else
{
*Event = MouQueue->Out->MouInfo;
if (MouQueue->Out == MouQueue->End)
MouQueue->Out = MouQueue->Event;
else
MouQueue->Out++;
#if DBG
IF_OD2_DEBUG( MOU )
{
KdPrint(("GetOs2MouEvent: fs %x, Pos %u-%u, Time %u\n",
Event->fs, Event->row, Event->col, Event->time ));
}
#endif
return (0L);
}
}
return (0L);
}
DWORD
Ow2GetOs2KbdEventIntoQueue()
{
DWORD Rc, NumEvent, ReadDone = FALSE;
if (!EventServerThreadSuspend)
{
return (0L);
}
Or2WinGetNumberOfConsoleInputEvents(
#if DBG
Ow2GetOs2KbdEventIntoQueueStr,
#endif
hConsoleInput,
&NumEvent
);
for ( ; NumEvent ; )
{
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)KEY_EVENT));
if (!Rc)
{
// No more events
break;
}
ReadDone = TRUE;
Or2WinGetNumberOfConsoleInputEvents(
#if DBG
Ow2GetOs2KbdEventIntoQueueStr,
#endif
hConsoleInput,
&NumEvent
);
}
if ( ReadDone && EventServerThreadSuspend && SesGrp->PauseScreenUpdate )
{
EnterCriticalSection(&QueueInputCriticalSection);
if ( EventServerThreadSuspend && SesGrp->PauseScreenUpdate )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("Ow2GetOs2KbdEventIntoQueue: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
LeaveCriticalSection(&QueueInputCriticalSection);
}
return (0L);
}
DWORD
GetOs2MouEventIntoQueue()
{
DWORD Rc, NumEvent, ReadDone = FALSE;
PMOU_MON_PACKAGE NextMouIn;
if (!EventServerThreadSuspend)
{
return (0L);
}
Or2WinGetNumberOfConsoleInputEvents(
#if DBG
GetOs2MouEventIntoQueueStr,
#endif
hConsoleInput,
&NumEvent
);
for ( ; NumEvent ; )
{
NextMouIn = (MouMonQueue->In == MouMonQueue->End) ?
MouMonQueue->Event :
(MouMonQueue->In+1);
if (NextMouIn == MouQueue->Out)
{
// QUEUE is full
break;
} else
{
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)MOUSE_EVENT));
if (!Rc)
{
// No more events
break;
}
ReadDone = TRUE;
}
Or2WinGetNumberOfConsoleInputEvents(
#if DBG
GetOs2MouEventIntoQueueStr,
#endif
hConsoleInput,
&NumEvent
);
}
if ( ReadDone && EventServerThreadSuspend && SesGrp->PauseScreenUpdate )
{
EnterCriticalSection(&QueueInputCriticalSection);
if ( EventServerThreadSuspend && SesGrp->PauseScreenUpdate )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetOs2MouEventIntoQueue: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
LeaveCriticalSection(&QueueInputCriticalSection);
}
return (0L);
}
DWORD
GetMonInput(IN USHORT MaxLength, // BUGBUG - not implemented
IN PKEY_EVENT_QUEUE KbdMon,
IN OUT PMON_RW rwParms,
IN PVOID pMsg,
OUT PULONG pReply)
{
PMOU_EVENT_QUEUE MouMon;
PMOU_MON_PACKAGE MouPackage;
PKBD_MON_PACKAGE MonPackage;
DWORD Rc;
UNREFERENCED_PARAMETER(MaxLength);
if (KbdMon->MonHdr.DevType == KbdDevice)
{
MonPackage = (PKBD_MON_PACKAGE) &(rwParms->ioBuff[0]);
for ( ; EventLoop ; )
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): enter, queue %lx\n", KbdMon));
}
#endif
if (KbdMon->LastKeyFlag)
{
*MonPackage = KbdMon->LastKey.KeyInfo[0];
KbdMon->LastKey.wRepeatCount-- ;
if (KbdMon->LastKey.wRepeatCount == 0)
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): no more last\n"));
}
#endif
KbdMon->LastKeyFlag = FALSE;
}
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): return last\n"));
}
#endif
return(NO_ERROR);
}
if (KbdMon->In == KbdMon->Out)
{
SavePortMessegeInfo(KbdMon->MonHdr.MemoryStartAddress, pMsg);
/*
* Enter critical Section
*/
EnterCriticalSection(&QueueInputCriticalSection);
if (KbdMon->In == KbdMon->Out)
{
if (!EventServerThreadSuspend)
{
goto NoMonReturn;
}
if (KbdMon != KbdMonQueue)
{
goto NoMonReturn;
}
LeaveCriticalSection(&QueueInputCriticalSection);
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)KEY_EVENT))
{
;
}
EnterCriticalSection(&QueueInputCriticalSection);
if (KbdMon->In == KbdMon->Out)
{
if (EventServerThreadSuspend &&
( !rwParms->fWait || SesGrp->PauseScreenUpdate ))
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetMonInput: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
NoMonReturn:
if ( !rwParms->fWait )
{
Rc = NO_ERROR;
*pReply = 0;
KbdMon->MonHdr.WaitForEvent = TRUE;
} else
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput-Kbd): no wait\n"));
}
#endif
//Rc = NO_ERROR;
Rc = ERROR_MON_BUFFER_EMPTY;
}
LeaveCriticalSection(&QueueInputCriticalSection);
return (Rc);
} else if ( SesGrp->PauseScreenUpdate && EventServerThreadSuspend )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetMonInput 2: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
}
LeaveCriticalSection(&QueueInputCriticalSection);
} else
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): found package\n"));
}
#endif
*MonPackage = KbdMon->Out->KeyInfo[0];
if (KbdMon->Out->wRepeatCount != 1)
{
/*
* decrement count and keep package
*/
KbdMon->LastKey = *KbdMon->Out;
KbdMon->LastKey.wRepeatCount-- ;
KbdMon->LastKey.KeyInfo[0].KeyboardFlag |= KBD_MULTIMAKE;
KbdMon->LastKeyFlag = TRUE;
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): package saved as last\n"));
}
#endif
}
/*
* update OUT pointer
*/
if (KbdMon->Out == KbdMon->End)
KbdMon->Out = KbdMon->Event;
else
KbdMon->Out++;
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): last repeat of package\n"));
}
#endif
return (NO_ERROR);
}
}
} else
{
MouMon = (PMOU_EVENT_QUEUE) KbdMon;
MouPackage = (PMOU_MON_PACKAGE) &(rwParms->ioBuff[0]);
for ( ; EventLoop ; )
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): enter, queue %lx\n", MouMon));
}
#endif
if (MouMon->LastMouFlag)
{
*MouPackage = MouMon->LastEvent;
MouMon->LastMouFlag = FALSE;
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): return last\n"));
}
#endif
return (NO_ERROR);
}
if (MouMon->In == MouMon->Out)
{
SavePortMessegeInfo(MouMon->MonHdr.MemoryStartAddress, pMsg);
/*
* Enter critical Section
*/
EnterCriticalSection(&QueueInputCriticalSection);
if (MouMon->In == MouMon->Out)
{
if (!EventServerThreadSuspend)
{
goto NoMouseMonReturn;
}
if (MouMon != MouMonQueue)
{
goto NoMouseMonReturn;
}
LeaveCriticalSection(&QueueInputCriticalSection);
while ((Rc = ReadInputEvent(1L)) && (Rc != (DWORD)MOUSE_EVENT))
{
;
}
EnterCriticalSection(&QueueInputCriticalSection);
if (MouMon->In == MouMon->Out)
{
if (EventServerThreadSuspend &&
( !rwParms->fWait || SesGrp->PauseScreenUpdate ))
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetMonInput-Mou: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
NoMouseMonReturn:
if ( !rwParms->fWait )
{
Rc = NO_ERROR;
*pReply = 0;
MouMon->MonHdr.WaitForEvent = TRUE;
} else
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput-Mouse): no wait\n"));
}
#endif
//Rc = NO_ERROR;
Rc = ERROR_MON_BUFFER_EMPTY;
}
LeaveCriticalSection(&QueueInputCriticalSection);
return (Rc);
} else if ( SesGrp->PauseScreenUpdate && EventServerThreadSuspend )
{
#if DBG
if (InternalDebug & InputEventDebug)
{
KdPrint(("GetMonInput-Mou 2: SetEvent\n"));
}
#endif
SetEvent( SuspendEvent );
}
}
LeaveCriticalSection(&QueueInputCriticalSection);
} else
{
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): found package\n"));
}
#endif
*MouPackage = *MouMon->Out;
/*
* update OUT pointer
*/
if (MouMon->Out == MouMon->End)
MouMon->Out = MouMon->Event;
else
MouMon->Out++;
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(GetMonInput): last repeat of package\n"));
}
#endif
return (NO_ERROR);
}
}
}
return(0L);
}
DWORD
PutMonInput(
IN USHORT MaxLength, // BUGBUG - not implemented
IN PKEY_EVENT_QUEUE NextKbdMon,
IN WORD RepeatCount,
IN PKBD_MON_PACKAGE MonPackage,
//IN OUT PMON_RW rwParms,
IN PVOID pMsg,
OUT PULONG pReply)
{
/* return non-zero if no place */
PKEYEVENTINFO NextKbdIn;
BOOL FirstEvent;
PMOU_MON_PACKAGE MouPackage;
//PKBD_MON_PACKAGE MonPackage;
PMOU_MON_PACKAGE NextMouIn;
PMOU_EVENT_QUEUE NextMouMon;
UNREFERENCED_PARAMETER(MaxLength);
UNREFERENCED_PARAMETER(pMsg);
UNREFERENCED_PARAMETER(pReply);
if (NextKbdMon->MonHdr.DevType == KbdDevice)
{
//MonPackage = (PKBD_MON_PACKAGE) &(rwParms->ioBuff[0]);
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(PutMonInput): enter, to queue %lx, char %x\n",
NextKbdMon, MonPackage->KeyInfo.chChar ));
}
#endif
if (( NextKbdMon == KbdQueue ) && /* last monitor in queue */
(( MonPackage->KeyboardFlag & KeyTypeMask ) == AccentKey ) &&
!( MonPackage->KeyboardFlag & AccentedKey ))
{
#if DBG
IF_OD2_DEBUG2( MON, KBD )
{
KdPrint(("OS2SES(PutMonInput): ignore package for DeviceFlag=0x%x\n",
MonPackage->DeviceFlag ));
}
#endif
return (0L);
}
NextKbdMon->In->KeyInfo[0] = *MonPackage;
NextKbdMon->In->wRepeatCount = RepeatCount;
NextKbdIn = (NextKbdMon->In == NextKbdMon->End) ?
NextKbdMon->Event :
(NextKbdMon->In+1);
FirstEvent = (NextKbdMon->In == NextKbdMon->Out);
if ( NextKbdMon->In == NextKbdMon->Out )
{
EnterCriticalSection(&QueueInputCriticalSection);
if ( NextKbdMon->In == NextKbdMon->Out )
{
if ( NextKbdMon->MonHdr.WaitForEvent )
{
if ( NextKbdMon == KbdQueue ) /* last monitor in queue */
{
KbdHandlePackage(NextKbdMon,
MonPackage);
} else
{
NextKbdMon->MonHdr.WaitForEvent = FALSE;
NextKbdMon->MonHdr.MonStat = MON_STAT_REG;
SendMonReply(NextKbdMon->MonHdr.MemoryStartAddress,
MonPackage,
sizeof(KBD_MON_PACKAGE));
}
} else
NextKbdMon->In = NextKbdIn;
LeaveCriticalSection(&QueueInputCriticalSection);
return (0L);
}
LeaveCriticalSection(&QueueInputCriticalSection);
}
if (NextKbdIn != NextKbdMon->Out)
NextKbdMon->In = NextKbdIn;
else
return(1L);
} else
{
NextMouMon = (PMOU_EVENT_QUEUE) NextKbdMon;
MouPackage = (PMOU_MON_PACKAGE) MonPackage;
//MouPackage = (PMOU_MON_PACKAGE) &(rwParms->ioBuff[0]);
#if DBG
IF_OD2_DEBUG( MON )
{
KdPrint(("OS2SES(PutMonInput): enter, to queue %lx, event %x (%x:%x)\n",
NextMouMon, MouPackage->MouInfo.fs,
MouPackage->MouInfo.row, MouPackage->MouInfo.col ));
}
#endif
*NextMouMon->In = *MouPackage;
NextMouIn = (NextMouMon->In == NextMouMon->End) ?
NextMouMon->Event :
(NextMouMon->In+1);
if ( NextMouMon->In == NextMouMon->Out )
{
EnterCriticalSection(&QueueInputCriticalSection);
if ( NextMouMon->In == NextMouMon->Out )
{
if ( NextMouMon->MonHdr.WaitForEvent )
{
NextMouMon->MonHdr.WaitForEvent = FALSE;
if ( NextMouMon == MouQueue ) /* last monitor in queue */
SendMouReply(NextMouMon->MonHdr.MemoryStartAddress,
&MouPackage->MouInfo);
else
{
NextMouMon->MonHdr.MonStat = MON_STAT_REG;
SendMonReply(NextMouMon->MonHdr.MemoryStartAddress,
MouPackage,
sizeof(MOU_MON_PACKAGE));
}
} else
NextMouMon->In = NextMouIn;
LeaveCriticalSection(&QueueInputCriticalSection);
return (0L);
}
LeaveCriticalSection(&QueueInputCriticalSection);
}
if (NextMouIn != NextMouMon->Out)
NextMouMon->In = NextMouIn;
else
{
if ( NextMouMon == MouQueue ) /* last monitor in queue */
{
/* no place - throw the oldest info */
NextMouMon->Out = (NextMouMon->Out == NextMouMon->End) ?
NextMouMon->Event :
(NextMouMon->Out+1);
NextMouMon->In = NextMouIn;
}
return(1L);
}
}
return(0L);
}
VOID
EventReleaseLPC(
IN ULONG ProcessId
)
{
PKEY_EVENT_QUEUE CurrentKbdQueue, LastKbdQueue;
PMOU_EVENT_QUEUE CurrentMouQueue, LastMouQueue;
for ( CurrentKbdQueue = KbdMonQueue, LastKbdQueue = NULL ;
LastKbdQueue != KbdQueue ;
LastKbdQueue = CurrentKbdQueue,
CurrentKbdQueue = (PKEY_EVENT_QUEUE)CurrentKbdQueue->MonHdr.NextQueue)
{
if((CurrentKbdQueue->MonHdr.WaitForEvent) &&
(Ow2GetProcessIdFromLPCMessage(
CurrentKbdQueue->MonHdr.MemoryStartAddress) == ProcessId))
{
if(CurrentKbdQueue != KbdQueue)
{
SendMonReply(CurrentKbdQueue->MonHdr.MemoryStartAddress,
NULL,
sizeof(KBD_MON_PACKAGE));
MonQueueClose((HANDLE)CurrentKbdQueue);
} else
{
RtlZeroMemory(
&KbdRequestSaveArea.d.KeyInfo,
sizeof(KBDKEYINFO));
SendKbdReply(CurrentKbdQueue->MonHdr.MemoryStartAddress,
(PVOID)&KbdRequestSaveArea,
NULL,
0);
}
}
}
for ( CurrentMouQueue = MouMonQueue, LastMouQueue = NULL ;
LastMouQueue != MouQueue ;
LastMouQueue = CurrentMouQueue,
CurrentMouQueue = (PMOU_EVENT_QUEUE)CurrentMouQueue->MonHdr.NextQueue)
{
if((CurrentMouQueue->MonHdr.WaitForEvent) &&
(Ow2GetProcessIdFromLPCMessage(
CurrentMouQueue->MonHdr.MemoryStartAddress) == ProcessId))
{
if(CurrentMouQueue != MouQueue)
{
SendMonReply(CurrentMouQueue->MonHdr.MemoryStartAddress,
NULL,
sizeof(MOU_MON_PACKAGE));
MonQueueClose((HANDLE)CurrentMouQueue);
} else
{
SendMouReply(CurrentMouQueue->MonHdr.MemoryStartAddress,
NULL);
}
}
}
//if ((MouQueue->MonHdr.WaitForEvent) &&
// (MouMonQueue == MouQueue ) && /* last monitor in queue */
// (Ow2GetProcessIdFromLPCMessage(
// MouQueue->MonHdr.MemoryStartAddress) == ProcessId))
//{
// RtlZeroMemory(
// &MouPackage,
// sizeof(MOU_MON_PACKAGE));
//
// SendMouReply(MouQueue->MonHdr.MemoryStartAddress,
// &MouPackage);
//}
}
VOID
Ow2MouOn()
{
Ow2dwWinInputMode |= ENABLE_MOUSE_INPUT;
InputModeFlags |= ENABLE_MOUSE_INPUT;
if (!SesGrp->WinProcessNumberInSession)
{
Ow2SetInputConsoleMode(
#if DBG
Ow2MouOnStr,
#endif
Ow2dwInputMode | ENABLE_MOUSE_INPUT
);
}
}
VOID
Ow2MouOff()
{
Ow2dwWinInputMode &= ~ENABLE_MOUSE_INPUT;
InputModeFlags &= ~ENABLE_MOUSE_INPUT;
if (!SesGrp->WinProcessNumberInSession)
{
Ow2SetInputConsoleMode(
#if DBG
Ow2MouOffStr,
#endif
Ow2dwInputMode & ~ENABLE_MOUSE_INPUT
);
}
}
DWORD
Ow2GetInputConsoleMode(
#if DBG
PSZ FuncName,
#endif
LPDWORD lpMode
)
{
BOOL Rc;
if (SesGrp->WinProcessNumberInSession)
{
Rc = Or2WinGetConsoleMode(
#if DBG
FuncName,
#endif
hConsoleInput,
lpMode
);
#if DBG
ASSERT1( "Ow2GetInputConsoleMode: GetConsoleMode fail", Rc );
#endif
if (Rc)
{
Ow2dwInputMode = *lpMode;
} else
{
return(GetLastError());
}
} else
{
*lpMode = Ow2dwInputMode;
}
#if DBG
if (InternalDebug & InputModeDebug)
{
KdPrint(("Ow2GetInputConsoleMode, Ow2dwInputMode = %x\n",
Ow2dwInputMode));
}
#endif
return (NO_ERROR);
}
DWORD
Ow2SetInputConsoleMode(
#if DBG
PSZ FuncName,
#endif
DWORD dwMode
)
{
BOOL Rc;
#if DBG
if (InternalDebug & InputModeDebug)
{
KdPrint(("Ow2SetInputConsoleMode, Ow2dwInputMode = %x, input argument dwMode = %x\n",
Ow2dwInputMode, dwMode));
}
#endif
if (SesGrp->WinProcessNumberInSession ||
(dwMode != Ow2dwInputMode))
{
Rc = Or2WinSetConsoleMode(
#if DBG
FuncName,
#endif
hConsoleInput,
dwMode
);
#if DBG
ASSERT1( "Ow2SetInputConsoleMode: SetConsoleMode fail", Rc );
#endif
if (Rc)
{
Ow2dwInputMode = dwMode;
}
}
return (NO_ERROR);
}
BOOLEAN
Ow2WriteBackDummyEvent()
{
INPUT_RECORD InputRecord;
INPUT_RECORD In;
BOOLEAN WriteSucceeded;
DWORD RecordsWritten;
DWORD cEvents;
DWORD PeekSuccess;
if ((PeekSuccess = PeekConsoleInputW(
hConsoleInput,
&In,
1L,
&cEvents
)) && cEvents == 0)
{
InputRecord.EventType = MENU_EVENT;
InputRecord.Event.MenuEvent.dwCommandId = WM_USER+1;
WriteSucceeded = WriteConsoleInput(hConsoleInput,
&InputRecord, 1, &RecordsWritten);
if (!WriteSucceeded || (RecordsWritten != 1)) {
#if DBG
DbgPrint("OS2: Ow2WriteBackDummyEvent - failed to write into input queue\n");
#endif // DBG
return(FALSE);
}
}
else if (!PeekSuccess){
#if DBG
DbgPrint("OS2: Ow2WriteBackDummyEvent - failed to peek input queue\n");
#endif // DBG
return(FALSE);
}
return(TRUE);
}
BOOLEAN
Ow2ClearupDummyEvent()
{
INPUT_RECORD In;
DWORD cEvents;
DWORD PeekSuccess;
if ((PeekSuccess = PeekConsoleInputW(
hConsoleInput,
&In,
1L,
&cEvents
)) && cEvents == 1)
{
//
// Check if the event in the queue is the special dummy event
//
if (In.EventType == MENU_EVENT && In.Event.MenuEvent.dwCommandId == (WM_USER+1))
{
if (!ReadConsoleInputW(
hConsoleInput,
&In,
1L,
&cEvents
))
{ // check why, should not happen
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1("Ow2ClearupDummyEvent: unable to read from CONIN$", FALSE);
} else
KdPrint(("OS2SES(Ow2ClearupDummyEvent): unable to read from CONIN$\n"));
#endif
return(FALSE);
} else if (cEvents != 1L)
{ // check why, should not happen
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1( "Ow2ClearupDummyEvent: no data read from CONIN$", FALSE );
} else
KdPrint(("OS2SES(Ow2ClearupDummyEvent): no data read from CONIN$\n"));
#endif
return(FALSE);
}
}
}
else if (!PeekSuccess) {
// Peek Failed, check why, should not happen
#if DBG
IF_OD2_DEBUG( OS2_EXE )
{
ASSERT1("ClearupDummyEvent: unable to peek from CONIN$", FALSE);
} else
{
KdPrint(("OS2SES(ClearupDummyEvent): unable to peek from CONIN$\n"));
}
#endif
return(FALSE);
}
return(TRUE);
}
#if PMNT
APIRET
MouSetPtrPosPM(
PPTRLOC pPtrLoc)
{
if (SetCursorPos(pPtrLoc->col, pPtrLoc->row))
return NO_ERROR;
else
return ERROR_MOUSE_INV_PARMS;
}
APIRET
MouGetPtrPosPM(
PPTRLOC pPtrLoc)
{
POINT pt;
if (GetCursorPos(&pt))
{
pPtrLoc->col = (USHORT)pt.x;
pPtrLoc->row = (USHORT)pt.y;
return NO_ERROR;
}
else
return ERROR_MOUSE_INV_PARMS;
}
COORD LastMousePosition = {-1, -1};
BOOLEAN PMNTInFocus = TRUE;
APIRET
PMNTGetNextEvent(
PMNT_INPUT_RECORD *ppm_input_rec)
{
int count;
INPUT_RECORD input_rec;
static int IgnoreNextMouseEvent = 0;
static BOOLEAN firsttime = TRUE;
if (firsttime)
{
firsttime = FALSE;
// For PM apps, this will cause EventServerThread to actually terminate
SetEvent(SuspendEvent);
}
while (1)
{
int SetNewMousePosition = 0;
if (!Or2WinReadConsoleInputA(
#if DBG
ReadInputEventStr,
#endif
hConsoleInput,
&input_rec,
1,
&count
))
{
#if 0
KdPrint(("PMNTGetNextEvent : Read Console input error = %lx \n",
GetLastError()));
#endif
return ERROR_INVALID_PARAMETER;
}
else
{
try
{
switch (input_rec.EventType)
{
case KEY_EVENT:
ppm_input_rec->EventType = PMNT_KEY_EVENT;
ppm_input_rec->Event.KeyEvent.bKeyDown =
input_rec.Event.KeyEvent.bKeyDown;
ppm_input_rec->Event.KeyEvent.wRepeatCount =
input_rec.Event.KeyEvent.wRepeatCount;
ppm_input_rec->Event.KeyEvent.wVirtualKeyCode =
input_rec.Event.KeyEvent.wVirtualKeyCode;
ppm_input_rec->Event.KeyEvent.wVirtualScanCode =
input_rec.Event.KeyEvent.wVirtualScanCode;
//BUGBUG - when/how should we look at unicode ?
ppm_input_rec->Event.KeyEvent.uChar.AsciiChar =
input_rec.Event.KeyEvent.uChar.AsciiChar;
ppm_input_rec->Event.KeyEvent.dwControlKeyState =
input_rec.Event.KeyEvent.dwControlKeyState;
//#if DBG
// DbgPrint(">>> Key event (%s): Char=%x, Scan=%x, VK=%x\n",
// (input_rec.Event.KeyEvent.bKeyDown ? "DOWN":" UP "),
// input_rec.Event.KeyEvent.uChar.AsciiChar,
// input_rec.Event.KeyEvent.wVirtualScanCode,
// input_rec.Event.KeyEvent.wVirtualKeyCode);
//#endif
return NO_ERROR;
case MOUSE_EVENT:
if (IgnoreNextMouseEvent)
{
IgnoreNextMouseEvent = 0;
break;
}
if (input_rec.Event.MouseEvent.dwMousePosition.X < 0)
{
input_rec.Event.MouseEvent.dwMousePosition.X = 0;
SetNewMousePosition = 1;
}
else if (input_rec.Event.MouseEvent.dwMousePosition.X
>= (ScreenX-1))
{
input_rec.Event.MouseEvent.dwMousePosition.X =
ScreenX - 1;
if (input_rec.Event.MouseEvent.dwMousePosition.Y
>= (ScreenY-1))
input_rec.Event.MouseEvent.dwMousePosition.Y =
ScreenY - 1;
SetCursorPos(input_rec.Event.MouseEvent.dwMousePosition.X,
input_rec.Event.MouseEvent.dwMousePosition.Y);
IgnoreNextMouseEvent = 1;
}
if (input_rec.Event.MouseEvent.dwMousePosition.Y < 0)
{
input_rec.Event.MouseEvent.dwMousePosition.Y = 0;
SetNewMousePosition = 1;
}
else if (input_rec.Event.MouseEvent.dwMousePosition.Y
>= (ScreenY-1))
{
input_rec.Event.MouseEvent.dwMousePosition.Y =
ScreenY - 1;
if (input_rec.Event.MouseEvent.dwMousePosition.X
>= (ScreenX-1))
input_rec.Event.MouseEvent.dwMousePosition.X =
ScreenX - 1;
SetCursorPos(input_rec.Event.MouseEvent.dwMousePosition.X,
input_rec.Event.MouseEvent.dwMousePosition.Y);
IgnoreNextMouseEvent = 1;
}
if (SetNewMousePosition)
{
SetNewMousePosition = 0;
// Reset the mouse position to be within the screen
// boundaries
SetCursorPos(input_rec.Event.MouseEvent.dwMousePosition.X,
input_rec.Event.MouseEvent.dwMousePosition.Y);
break; // No need to generate a mouse event
}
else
{
ppm_input_rec->EventType = PMNT_MOUSE_EVENT;
ppm_input_rec->Event.MouseEvent.dwMousePosition.X =
input_rec.Event.MouseEvent.dwMousePosition.X;
ppm_input_rec->Event.MouseEvent.dwMousePosition.Y =
input_rec.Event.MouseEvent.dwMousePosition.Y;
ppm_input_rec->Event.MouseEvent.dwButtonState =
input_rec.Event.MouseEvent.dwButtonState;
ppm_input_rec->Event.MouseEvent.dwControlKeyState =
input_rec.Event.MouseEvent.dwControlKeyState;
ppm_input_rec->Event.MouseEvent.dwEventFlags =
input_rec.Event.MouseEvent.dwEventFlags;
if (PMNTInFocus)
{
LastMousePosition.X =
input_rec.Event.MouseEvent.dwMousePosition.X;
LastMousePosition.Y =
input_rec.Event.MouseEvent.dwMousePosition.Y;
}
return NO_ERROR;
}
case FOCUS_EVENT:
ppm_input_rec->EventType = PMNT_FOCUS_EVENT;
ppm_input_rec->Event.FocusEvent.bSetFocus =
input_rec.Event.FocusEvent.bSetFocus;
return NO_ERROR;
case WINDOW_BUFFER_SIZE_EVENT:
#if DBG
KdPrint(("PMNTGetNextEvent: WINDOW_BUFFER_SIZE_EVENT\n"));
#endif
break;
case MENU_EVENT:
#if DBG
KdPrint(("PMNTGetNextEvent: MENU_EVENT\n"));
KdPrint((" (command ID=0x%x)\n",
input_rec.Event.MenuEvent.dwCommandId));
#endif
if (input_rec.Event.MenuEvent.dwCommandId == WM_USER)
{
ppm_input_rec->EventType = PMNT_MENU_EVENT;
ppm_input_rec->Event.MenuEvent.dwCommandId = 0xdead;
return(NO_ERROR);
}
else if (input_rec.Event.MenuEvent.dwCommandId == (WM_USER+1))
{
ppm_input_rec->EventType = PMNT_MENU_EVENT;
ppm_input_rec->Event.MenuEvent.dwCommandId = 0x1;
return(NO_ERROR);
}
else if (input_rec.Event.MenuEvent.dwCommandId == (WM_USER+2))
{
ppm_input_rec->EventType = PMNT_MENU_EVENT;
ppm_input_rec->Event.MenuEvent.dwCommandId = 0x2;
return(NO_ERROR);
}
break;
default:
break;
}
}
except( EXCEPTION_EXECUTE_HANDLER )
{
Od2ExitGP();
}
}
} // while(1)
}
#ifndef CONSOLE_FULLSCREEN_MODE
#define CONSOLE_FULLSCREEN_MODE 1
#define CONSOLE_WINDOWED_MODE 2
//BUGBUG !!! Most definitions below are taken from the private API include
// file of the console ('conapi.h') -> needs to be updated from
// time to time.
typedef struct _CONSOLE_GRAPHICS_BUFFER_INFO {
DWORD dwBitMapInfoLength;
LPBITMAPINFO lpBitMapInfo;
DWORD dwUsage;
HANDLE hMutex;
PVOID lpBitMap;
} CONSOLE_GRAPHICS_BUFFER_INFO, *PCONSOLE_GRAPHICS_BUFFER_INFO;
#define CONSOLE_GRAPHICS_BUFFER 2
BOOL
SetConsoleDisplayMode(
HANDLE hConsoleOutput,
DWORD dwFlags,
PCOORD lpNewScreenBufferDimensions
);
#endif
typedef struct _BITMAPINFOPAT
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFOPAT;
BITMAPINFOPAT bmiPat =
{
{
sizeof(BITMAPINFOHEADER),
640,
-480, // For some weird reason, the Console wants a negative value,
// otherwise it prints a: "****** Negating biHeight" message.
1,
1,
BI_RGB,
(640 * 480 / 8),
0,
0,
0,
0
},
{ // B G R
{ 0, 0, 0x0, 0 }
}
};
/******************************************************************************
* PMNTGetWin32Hwnd:
* Returns the WIN32 HWND of our window.
******************************************************************************/
ULONG PMNTGetWin32Hwnd(ULONG *pHwnd)
{
try
{
*pHwnd = (ULONG)Ow2ForegroundWindow;
}
except( EXCEPTION_EXECUTE_HANDLER )
{
return ERROR_INVALID_PARAMETER;
}
return NO_ERROR;
}
static BOOL HWDumpVersion=FALSE;
PVIDEO_HARDWARE_STATE_HEADER videoState;
UCHAR InitStatePortValue[0x30] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x20, 0, 0xe3, 0, 2, 0, 0xff, 0, 0x10, 0, 0, 0, 0, 0, 4, 0,
0, 0, 0, 0, 0x3f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
UCHAR InitStateBasicSequencer[] = {3,1,0xf,0,6};
UCHAR InitStateBasicCrtCont[] = {
0x5f,0x4f,0x50,0x82,0x54,0x80,0xb,0x3e,0,0x40,0,0,0,0,0,0,
0xea,0xac,0xdf,0x28,0,0xe7,4,0xc3,0xff};
UCHAR InitStateBasicGraphCont[] = {0,0,0,0,3,0,5,0xf,0xff};
UCHAR InitStateBasicAttribCont[] = {
0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,
1,0,0xf,0,0};
UCHAR InitStateBasicDac[] = {
0, 0, 0, 0, 0,0x2a, 0,0x2a, 0, 0,0x2a,0x2a,0x2a,0, 0,0x2a,
0,0x2a,0x2a,0x2a, 0,0x28,0x28,0x28,0x36,0x36,0x36, 0, 0,0x3f, 0,0x3f,
0, 0,0x3f,0x3f,0x3f, 0, 0,0x3f, 0,0x3f,0x3f,0x3f, 0, 0x3f, 0x3f, 0x3f,
0, 0x15, 0, 0, 0x15, 0x2a, 0, 0x3f, 0, 0, 0x3f, 0x2a, 0x2a, 0x15, 0, 0x2a,
0x15, 0x2a, 0x2a, 0x3f, 0, 0x2a, 0x3f, 0x2a, 0, 0x15, 0x15, 0, 0x15, 0x3f, 0, 0x3f,
0x15, 0, 0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x2a, 0x15, 0x3f, 0x2a, 0x3f, 0x15, 0x2a, 0x3f, 0x3f,
0x15, 0, 0, 0x15, 0,0x2a, 0x15, 0x2a, 0, 0x15, 0x2a, 0x2a, 0x3f, 0, 0, 0x3f,
0,0x2a, 0x3f, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x15,0x15,0,0x3f,0x15,0x2a,
0x15, 0x15, 0x2a, 0x3f, 0x3f, 0,0x15, 0x3f, 0,0x3f,0x3f,0x2a,0x15,0x3f,0x2a,0x3f,
0x15, 0x15, 0,0x15, 0x15, 0x2a, 0x15, 0x3f, 0,0x15,0x3f,0x2a,0x3f,0x15,0,0x3f,
0x15, 0x2a, 0x3f, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15,0x15,0x15,0x15,0x15,0x3f,0x15,0x3f,
0x15, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x15, 0x3f,0x15,0x3f,0x3f,0x3f,0x15,0x3f,0x3f,0x3f,
0, 0, 0, 0, 0,0x2a, 0,0x2a, 0, 0,0x2a, 0x2a, 0x2a, 0, 0,0x2a,
0,0x2a, 0x2a, 0x2a, 0,0x2a, 0x2a, 0x2a, 0, 0,0x15, 0, 0,0x3f, 0,0x2a,
0x15, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0x2a, 0x2a, 0x3f,
0,0x15, 0, 0,0x15, 0x2a, 0,0x3f, 0, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x2a,
0x15, 0x2a, 0x2a, 0x3f, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x15, 0,0x15, 0x3f, 0,0x3f,
0x15, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x2a, 0x15, 0x3f, 0x2a, 0x3f, 0x15, 0x2a, 0x3f, 0x3f,
0x15, 0, 0,0x15, 0,0x2a, 0x15, 0x2a, 0,0x15, 0x2a, 0x2a, 0x3f, 0, 0,0x3f,
0,0x2a, 0x3f, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x15, 0x15, 0,0x3f, 0x15, 0x2a,
0x15, 0x15, 0x2a, 0x3f, 0x3f, 0,0x15, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x3f, 0x2a, 0x3f,
0x15, 0x15, 0,0x15, 0x15, 0x2a, 0x15, 0x3f, 0,0x15, 0x3f, 0x2a, 0x3f, 0x15, 0,0x3f,
0x15, 0x2a, 0x3f, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x15, 0x3f,
0x15, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x15, 0x3f, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x3f, 0x3f, 0x3f,
0, 0, 0, 0, 0,0x2a, 0,0x2a, 0, 0,0x2a, 0x2a, 0x2a, 0, 0,0x2a,
0,0x2a, 0x2a, 0x2a, 0,0x2a, 0x2a, 0x2a, 0, 0,0x15, 0, 0,0x3f, 0,0x2a,
0x15, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0x2a, 0x2a, 0x3f,
0,0x15, 0, 0,0x15, 0x2a, 0,0x3f, 0, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x2a,
0x15, 0x2a, 0x2a, 0x3f, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x15, 0,0x15, 0x3f, 0,0x3f,
0x15, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x2a, 0x15, 0x3f, 0x2a, 0x3f, 0x15, 0x2a, 0x3f, 0x3f,
0x15, 0, 0,0x15, 0,0x2a, 0x15, 0x2a, 0,0x15, 0x2a, 0x2a, 0x3f, 0, 0,0x3f,
0,0x2a, 0x3f, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x15, 0x15, 0,0x3f, 0x15, 0x2a,
0x15, 0x15, 0x2a, 0x3f, 0x3f, 0,0x15, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x3f, 0x2a, 0x3f,
0x15, 0x15, 0,0x15, 0x15, 0x2a, 0x15, 0x3f, 0,0x15, 0x3f, 0x2a, 0x3f, 0x15, 0,0x3f,
0x15, 0x2a, 0x3f, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x15, 0x3f,
0x15, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x15, 0x3f, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x3f, 0x3f, 0x3f,
0, 0, 0, 0, 0,0x2a, 0,0x2a, 0, 0,0x2a, 0x2a, 0x2a, 0, 0,0x2a,
0,0x2a, 0x2a, 0x2a, 0,0x2a, 0x2a, 0x2a, 0, 0,0x15, 0, 0,0x3f, 0,0x2a,
0x15, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0x2a, 0x2a, 0x3f,
0,0x15, 0, 0,0x15, 0x2a, 0,0x3f, 0, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x2a,
0x15, 0x2a, 0x2a, 0x3f, 0,0x2a, 0x3f, 0x2a, 0,0x15, 0x15, 0,0x15, 0x3f, 0,0x3f,
0x15, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x2a, 0x15, 0x3f, 0x2a, 0x3f, 0x15, 0x2a, 0x3f, 0x3f,
0x15, 0, 0,0x15, 0,0x2a, 0x15, 0x2a, 0,0x15, 0x2a, 0x2a, 0x3f, 0, 0,0x3f,
0,0x2a, 0x3f, 0x2a, 0,0x3f, 0x2a, 0x2a, 0x15, 0,0x15, 0x15, 0,0x3f, 0x15, 0x2a,
0x15, 0x15, 0x2a, 0x3f, 0x3f, 0,0x15, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x3f, 0x2a, 0x3f,
0x15, 0x15, 0,0x15, 0x15, 0x2a, 0x15, 0x3f, 0,0x15, 0x3f, 0x2a, 0x3f, 0x15, 0,0x3f,
0x15, 0x2a, 0x3f, 0x3f, 0,0x3f, 0x3f, 0x2a, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x15, 0x3f,
0x15, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x15, 0x3f, 0x15, 0x3f, 0x3f, 0x3f, 0x15, 0x3f, 0x3f, 0x3f};
UCHAR InitStateBasicLatches[] = {0, 0, 0,0xff};
#if 0
UCHAR InitStateExtendedCrtCont[] = {
0x48,0x93, 0,0x20, 0, 0, 0, 0, 0, 0,0xff, 0xff, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xff, 0xff, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0xf, 0xef, 0, 0, 0, 0,0x2f, 0,0xff,
0xff, 0xff, 0xff, 0,0xff, 0, 0, 0, 0,0xff, 0xff, 0xff, 0xff, 0,0xff, 0,
2, 2, 0,0xff, 0xff, 0, 0, 0, 0,0xff, 0xf, 0xff, 0xf};
UCHAR InitStateExtendedGraphCont[] = {
0x10, 0x31, 0xa5, 0x28, 0, 0, 0,0xfb, 0xdf, 0, 0, 0, 0,0x50, 0,0xd6,
0xa1, 0, 0, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0xf, 0xf, 0xf, 0xf, 0xf};
#endif //0
extern BOOLEAN Os2InitializeVDMEvents(VOID);
extern BOOLEAN Os2WaitForVDMThread(HANDLE hEvent);
extern VOID Os2VDMThread(PVOID Parameter);
#ifndef PMNT_DAYTONA
extern BOOLEAN Os2WaitForVDMThreadReady(VOID);
extern VOID Os2VDMGetStartThread(PVOID Parameter);
#endif // not PMNT_DAYTONA
extern VOID DosExit(ULONG ExitAction,ULONG ExitResult);
ULONG
PMNTSetShutdownPriority(ULONG NewPriority, ULONG DisablePopup)
{
ULONG rc = NO_ERROR;
if (DisablePopup == 1) // i.e. disable
{
if (!SetProcessShutdownParameters(
NewPriority,
1 // Don't give pop-up when 20 sec are exceeded
))
{
#if DBG
DbgPrint("Os2: PMNTSetShutdownPriority(0x%X, %d) failed\n",
NewPriority, DisablePopup);
#endif
rc = ERROR_INVALID_PARAMETER;
}
}
else if (DisablePopup == 0) // i.e. enable
{
if (!SetProcessShutdownParameters(
NewPriority,
0 // Give pop-up when 20 sec are exceeded
))
{
#if DBG
DbgPrint("Os2: PMNTSetShutdownPriority(0x%X, %d) failed\n",
NewPriority, DisablePopup);
#endif
rc = ERROR_INVALID_PARAMETER;
}
}
else // leave unchanged
{
ULONG tmpPriority, tmpDisable;
if (!GetProcessShutdownParameters(
&tmpPriority,
&tmpDisable
))
{
#if DBG
DbgPrint("Os2: PMNTSetShutdownPriority(0x%X, %d) failed because of query\n",
NewPriority, DisablePopup);
#endif
rc = ERROR_INVALID_PARAMETER;
}
else
{
if (!SetProcessShutdownParameters(
NewPriority,
tmpDisable
))
{
#if DBG
DbgPrint("Os2: PMNTSetShutdownPriority(0x%X, %d) failed\n",
NewPriority, DisablePopup);
#endif
rc = ERROR_INVALID_PARAMETER;
}
}
}
return rc;
}
//
//This is a workaround for Unknown Video Adapters
//It is basically the same as PMNTSetFullScreen of event.c@v52
//
void PMNTSetFullScreenDump(void)
{
CONSOLE_GRAPHICS_BUFFER_INFO GraphicsInfo;
HANDLE Handle;
COORD NewCoord;
/* Size of video save block. */
DWORD stateLength;
CHAR_INFO *textBuffer;
COORD textBufferSize; // Dimensions of the shared buffer
DWORD ModeFlags;
DWORD OldPriorityClass;
DWORD OldPriorityThread;
#if DBG
DbgPrint("PMNTSetFullScreenDump was called\n");
#endif
//
// open a new console
//
GraphicsInfo.dwBitMapInfoLength = sizeof(bmiPat);
GraphicsInfo.lpBitMapInfo = (LPBITMAPINFO)&bmiPat;
GraphicsInfo.dwUsage = DIB_RGB_COLORS;
// Set some fields according to the display resolution
GraphicsInfo.lpBitMapInfo->bmiHeader.biWidth = ScreenX;
// For some weird reason, the Console wants a negative value,
// otherwise it prints a: "****** Negating biHeight" message.
GraphicsInfo.lpBitMapInfo->bmiHeader.biHeight = -ScreenY;
GraphicsInfo.lpBitMapInfo->bmiHeader.biSizeImage = ScreenX*ScreenY/8;
Handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_GRAPHICS_BUFFER,
&GraphicsInfo
);
if (Handle == (HANDLE)-1)
{
#if DBG
DbgPrint("CreateConsoleScreenBuffer failed\n");
#endif
return;
}
//
// make it current
//
if (!SetConsoleActiveScreenBuffer(Handle))
{
#if DBG
DbgPrint("SetConsoleActiveScreenBuffer() failed\n");
#endif
}
if (!GetConsoleDisplayMode(&ModeFlags))
{
#if DBG
DbgPrint("GetConsoleDisplayMode() failed, error=%d\n",
GetLastError());
#endif
}
OldPriorityClass = GetPriorityClass(GetCurrentProcess());
OldPriorityThread = GetThreadPriority(GetCurrentThread());
#if DBG
if (!OldPriorityClass)
{
DbgPrint("PMNTSetFullScreen: GetPriorityClass failed, error=%d\n",
GetLastError());
}
if (OldPriorityThread == THREAD_PRIORITY_ERROR_RETURN)
{
DbgPrint("PMNTSetFullScreen: GetThreadPriority failed, error=%d\n",
GetLastError());
}
#endif
if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS))
{
#if DBG
DbgPrint("PMNTSetFullScreen: SetPriorityClass failed, error=%d\n",
GetLastError());
#endif
}
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
{
#if DBG
DbgPrint("PMNTSetFullScreen: SetThreadPriority failed, error=%d\n",
GetLastError());
#endif
}
// Is the Console already full-screen ?
if ((ModeFlags & CONSOLE_FULLSCREEN) == 0)
{
INPUT_RECORD input_rec;
int count;
if (!SetConsoleDisplayMode(
Handle,
CONSOLE_FULLSCREEN_MODE,
&NewCoord
))
{
#if DBG
DbgPrint("SetConsoleDisplayMode() 0x%x %d failed\n", GetLastError(),
GetLastError());
#endif
}
// The 2 loops below are here because of a Console bug: when one windows
// goes full-screen, GDI relinquishes the display and sends a lost focus
// message to all windows on the desktop, incl. to the window going
// full-screen. The Console is not smart enough to filter out this
// spurious event and it passes it on to the Console client in the form
// of a negative Console focus event. Then, the window gets a positive
// focus event.
// There is more: when the full-screen window happens to register itself
// as a VDM, the Console actually goes through the usual handshake
// involved when loosing/gaining focus, with the 2 hardware events !!!
// The PM/NT loop handling these events was created only later. All
// Console APIs (such as SetInputConsoleMode) issued from PMSHELL before
// the creation of the thread handling the dialog with the Console but
// after the spurious focus event resulted in a dead-lock: PMSHELL was
// waiting for some answer from the Console, which was waiting for the VDM
// (i.e. PMSHELL) to perform the handshake !
// Note that the problem didn't appear consistently because it was
// dependent on the timing on the WM_FOCUS message(s).
//
// The 2 loops below wait for these events and discard them.
//
while (1)
{
if (!Or2WinReadConsoleInputA(
#if DBG
ReadInputEventStr,
#endif
hConsoleInput,
&input_rec,
1,
&count
))
{
KdPrint(("PMNTSetFullScreent : Read Console input error = %lx \n",
GetLastError()));
return;
}
if (input_rec.EventType == FOCUS_EVENT)
{
if (input_rec.Event.FocusEvent.bSetFocus)
{
// Expected negative focus at that point but go on
KdPrint(("PMNTSetFullScreen: positive Focus event ?!?\n"));
goto SkipConsoleWait;
}
else
{
// Got the first spurious event (negative focus) - go on
break;
}
}
else
{
KdPrint(("PMNTSetFullScreen: ignoring non-focus event (%d)\n",
input_rec.EventType));
}
}
while (1)
{
if (!Or2WinReadConsoleInputA(
#if DBG
ReadInputEventStr,
#endif
hConsoleInput,
&input_rec,
1,
&count
))
{
KdPrint(("PMNTSetFullScreen : Read Console input error = %lx \n"));
return;
}
if (input_rec.EventType == FOCUS_EVENT)
{
if (!input_rec.Event.FocusEvent.bSetFocus)
{
// Expects positive focus at that point.
KdPrint(("PMNTSetFullScreen: negative Focus event ?!?\n"));
}
else
{
// Got the 2nd spurious event (positive focus) - go on
break;
}
}
}
}
SkipConsoleWait:
// Get rid of any events at that point
FlushConsoleInputBuffer(hConsoleInput);
/*
* Register start and end events with the console. These events are used
* when gaining or losing control of the hardware.
*/
hStartHardwareEvent = CreateEventW((LPSECURITY_ATTRIBUTES) NULL,
FALSE,
FALSE,
NULL);
hEndHardwareEvent = CreateEventW((LPSECURITY_ATTRIBUTES) NULL,
FALSE,
FALSE,
NULL);
if ((hStartHardwareEvent == NULL) || (hEndHardwareEvent == NULL))
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, Cannot create start or end events\n");
#endif
}
/* Poll the event to try and get rid of any console queued sets
* This shouldn't be needed (or shouldn't work) but something along
* those lines seems to be happening at the moment.
*/
WaitForSingleObject(hStartHardwareEvent, 0);
if (!SetConsoleKeyShortcuts(
TRUE,
CONSOLE_ALTENTER,
NULL,
0
)
)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, SetConsoleKetShortcuts() failed\n");
#endif
}
textBufferSize.X = 80;
textBufferSize.Y = 50;
stateLength = sizeof(CHAR_INFO)*80*50;
if (!RegisterConsoleVDM( TRUE,
hStartHardwareEvent,
hEndHardwareEvent,
(LPWSTR) NULL,
(DWORD) 0,
&stateLength,
(PVOID *) &videoState,
(LPWSTR) NULL,
(DWORD) 0,
textBufferSize,
(PVOID *) &textBuffer
)
)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, RegisterConsoleVDM() failed\n");
#endif
}
// Restore process/thread priority class & priority
if (!SetPriorityClass(GetCurrentProcess(), OldPriorityClass))
{
#if DBG
DbgPrint("PMNTSetFullScreen: SetPriorityClass(%d) failed, error=%d\n",
OldPriorityClass,
GetLastError());
#endif
}
if (!SetThreadPriority(GetCurrentThread(), OldPriorityThread))
{
#if DBG
DbgPrint("PMNTSetFullScreen: SetThreadPriority(%d) failed, error=%d\n",
OldPriorityThread,
GetLastError());
#endif
}
}
extern ULONG
Dos16Open(PSZ pszFileName,PUSHORT phf,PUSHORT pusAction,ULONG cbFile,
ULONG ulAttribute,ULONG fsOpenFlags,ULONG fsOpenMode,ULONG ulReserved);
extern ULONG DosClose(IN HFILE FileHandle);
extern ULONG Dos16Write(HFILE FileHandle,PVOID Buffer,ULONG Length,PUSHORT BytesWritten);
extern ULONG Dos16Read(ULONG hFile, PVOID pBuffer, ULONG cbRead, PUSHORT pcbActual);
static BOOL VideoDumped = FALSE;
#define PMNTREGQUERYVALMAX 256
char PMNTDisplayAdapterName[PMNTREGQUERYVALMAX] = {'\0'};
LONG PMNTDisplayAdapterLen = 0;
//
// This routine dumps the videostate buffer into c:\os2\videohw.dmp exists
//
void PMNTVideoDump(void)
{
ULONG rc;
ULONG len;
USHORT hfile,Action,cbWritten;
if (PMNTDisplayAdapterLen == 0)
{
KdPrint(("PMNTVideoDump: couldn't get current display name - returning"));
return;
}
len = sizeof(VIDEO_HARDWARE_STATE_HEADER);
if (len < videoState->BasicSequencerOffset) len = videoState->BasicSequencerOffset;
if (len < videoState->BasicCrtContOffset) len = videoState->BasicCrtContOffset;
if (len < videoState->BasicGraphContOffset) len = videoState->BasicGraphContOffset;
if (len < videoState->BasicAttribContOffset) len = videoState->BasicAttribContOffset;
if (len < videoState->BasicDacOffset) len = videoState->BasicDacOffset;
if (len < videoState->BasicLatchesOffset) len = videoState->BasicLatchesOffset;
if (len < videoState->ExtendedSequencerOffset) len = videoState->ExtendedSequencerOffset;
if (len < videoState->ExtendedCrtContOffset) len = videoState->ExtendedCrtContOffset;
if (len < videoState->ExtendedGraphContOffset) len = videoState->ExtendedGraphContOffset;
if (len < videoState->ExtendedAttribContOffset) len = videoState->ExtendedAttribContOffset;
if (len < videoState->ExtendedDacOffset) len = videoState->ExtendedDacOffset;
if (len < videoState->ExtendedValidatorStateOffset) len = videoState->ExtendedValidatorStateOffset;
if (len < videoState->ExtendedMiscDataOffset) len = videoState->ExtendedMiscDataOffset;
if (len < videoState->Plane1Offset) len = videoState->Plane1Offset;
if (rc=Dos16Open("C:\\OS2\\VIDEOHW.DMP",
&hfile,
&Action,
0L,
0L,
0x00000012, /* FILE_TRUNCATE | FILE_CREATE */
0x00000012, /* OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE */
0L))
{
KdPrint(("PMNTVideoDump: cannot open VIDEOHW.DMP, rc= %d\n",rc));
return;
}
if (rc=Dos16Write((ULONG)hfile,
PMNTDisplayAdapterName,
PMNTDisplayAdapterLen,
&cbWritten))
{
KdPrint(("PMNTVideoDump: cannot write display name to VIDEOHW.DMP, rc= %d\n",rc));
DosClose((ULONG)hfile);
return;
}
if (rc=Dos16Write((ULONG)hfile,videoState,len,&cbWritten))
{
KdPrint(("PMNTVideoDump: cannot write to VIDEOHW.DMP, rc= %d\n",rc));
DosClose((ULONG)hfile);
return;
}
DosClose((ULONG)hfile);
KdPrint(("PMNTVideoDump: C:\\OS2\\VIDEOHW.DMP was created\n"));
return;
}
//
// This routine modifies the videostate buffer in the case that
// c:\os2\videohw.dmp exists
// returns TRUE if and only if the file exists and is readable
//
BOOL PMNTReadVideoDump(void)
{
ULONG rc;
USHORT hfile,Action,cbRead;
CHAR tmp_name_buf[PMNTREGQUERYVALMAX];
if (PMNTDisplayAdapterLen == 0)
return FALSE;
if (Dos16Open("C:\\OS2\\VIDEOHW.DMP",
&hfile,
&Action,
0L,
0L,
0x00000001, /* FILE_OPEN */
0x00000020, /* OPEN_SHARE_DENYWRITE */
0L))
{
// file_not_found is the normal case
return(FALSE);
}
if (rc=Dos16Read((ULONG)hfile,
tmp_name_buf,
PMNTDisplayAdapterLen,
&cbRead))
{
KdPrint(("PMNTReadVideoDump: cannot read VIDEOHW.DMP, rc= %d\n",rc));
DosClose((ULONG)hfile);
return(FALSE);
}
if (cbRead != PMNTDisplayAdapterLen)
{
KdPrint(("PMNTReadVideoDump: cannot read enough from VIDEOHW.DMP, cbRead= %d\n",
cbRead));
DosClose((ULONG)hfile);
return(FALSE);
}
if (memcmp(tmp_name_buf, PMNTDisplayAdapterName, PMNTDisplayAdapterLen))
{
KdPrint(("PMNTReadVideoDump: got name=%s instead of actual name=%s\n",
tmp_name_buf, PMNTDisplayAdapterName));
DosClose((ULONG)hfile);
return(FALSE);
}
if (rc=Dos16Read((ULONG)hfile,videoState,0x0000ffff,&cbRead))
{
KdPrint(("PMNTReadVideoDump: cannot read VIDEOHW.DMP, rc= %d\n",rc));
DosClose((ULONG)hfile);
return(FALSE);
}
KdPrint(("PMNTReadVideoDump() modified videoState from C:\\OS2\\VIDEOHW.DMP\n"));
DosClose((ULONG)hfile);
return(TRUE);
}
//
// This routine modifies the videostate buffer in the case of
// a QVision Adapter
//
void PMNTChkQVision(void)
{
char *ptr,*ptr_base;
if (!(strstr(PMNTDisplayAdapterName,"\\qv\\")))
{
// Not QVision
return;
}
KdPrint(("This machine uses QVision Video Adapter\n"));
videoState->Length = 0x9c;
videoState->PortValue[0x1e] = 0x57;
videoState->BasicSequencerOffset = 0x9c;
videoState->BasicCrtContOffset = 0xa1;
videoState->BasicGraphContOffset = 0xba;
videoState->BasicAttribContOffset= 0xc3;
videoState->BasicDacOffset = 0xd8;
videoState->BasicLatchesOffset = 0x3d8;
#if 0
videoState->ExtendedSequencerOffset = 0x3dc;
videoState->ExtendedCrtContOffset = 0x3dc;
videoState->ExtendedGraphContOffset = 0x429;
videoState->ExtendedAttribContOffset= 0x48a;
videoState->ExtendedDacOffset = 0x48a;
videoState->ExtendedValidatorStateOffset = 0x0;
videoState->ExtendedMiscDataOffset = 0x0;
videoState->PlaneLength = 0x10000;
videoState->Plane1Offset = 0x95a;
videoState->Plane2Offset = 0x1095a;
videoState->Plane3Offset = 0x2095a;
videoState->Plane4Offset = 0x3095a;
videoState->VGAStateFlags = 0x0;
videoState->DIBOffset = 0x0;
videoState->DIBBitsPerPixel = 0x0;
videoState->DIBXResolution = 0x0;
videoState->DIBYResolution = 0x0;
videoState->DIBXlatOffset = 0x0;
videoState->DIBXlatLength = 0x0;
#endif //0
ptr_base = (char *)( videoState);
ptr = ptr_base + videoState->BasicSequencerOffset;
memcpy(ptr,InitStateBasicSequencer,sizeof(InitStateBasicSequencer));
ptr = ptr_base + videoState->BasicCrtContOffset;
memcpy(ptr,InitStateBasicCrtCont,sizeof(InitStateBasicCrtCont));
ptr = ptr_base + videoState->BasicGraphContOffset;
memcpy(ptr,InitStateBasicGraphCont,sizeof(InitStateBasicGraphCont));
ptr = ptr_base + videoState->BasicAttribContOffset;
memcpy(ptr,InitStateBasicAttribCont,sizeof(InitStateBasicAttribCont));
ptr = ptr_base + videoState->BasicDacOffset;
memcpy(ptr,InitStateBasicDac,sizeof(InitStateBasicDac));
ptr = ptr_base + videoState->BasicLatchesOffset;
memcpy(ptr,InitStateBasicLatches,sizeof(InitStateBasicLatches));
#if 0
ptr = ptr_base + videoState->ExtendedCrtContOffset;
memcpy(ptr,InitStateExtendedCrtCont,sizeof(InitStateExtendedCrtCont));
ptr = ptr_base + videoState->ExtendedGraphContOffset;
memcpy(ptr,InitStateExtendedGraphCont,sizeof(InitStateExtendedGraphCont));
#endif //0
return;
}
//
// This routine reads the name of the display driver into a buffer
//
void PMNTReadDisplayAdapterName(void)
{
char VideoKeyName[] = "HARDWARE\\DEVICEMAP\\VIDEO";
char VideoValName[] = "\\Device\\Video0";
LONG ValType,rc;
HKEY hKey;
if (rc = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,VideoKeyName,(DWORD)0,KEY_QUERY_VALUE,&hKey))
{
KdPrint(("PMNTReadDisplayAdapterName: RegOpenKeyEx() failed rc = %d\n",rc));
PMNTDisplayAdapterLen = 0;
return;
}
PMNTDisplayAdapterLen = PMNTREGQUERYVALMAX;
if (rc = RegQueryValueEx(
hKey,VideoValName,NULL,&ValType,
PMNTDisplayAdapterName,
&PMNTDisplayAdapterLen))
{
KdPrint(("PMNTReadDisplayAdapterName: RegQueryValEx() failed rc = %d\n",rc));
PMNTDisplayAdapterLen = 0;
RegCloseKey(hKey);
return;
}
RegCloseKey(hKey);
KdPrint(("This machine uses %s Video Adapter\n",
PMNTDisplayAdapterName));
return;
}
PMNTSetFocus(HWND FocusHwnd)
{
BOOLEAN rc;
// Code below doesn't work when the PM window which has been clicked on (which
// is closing itself) causes PMShell to be selected (next in focus chain)
#if 0
HWND tmp;
tmp = GetForegroundWindow();
// Try to ignore FOCUS event which arrives after we already set the focus
// on PMShell (for example, for the second spurious FOCUS event sent by
// the Console)
if (tmp == FocusHwnd)
{
return NO_ERROR;
}
#endif //0
#if DBG
DbgPrint("PMNTSetFocus: passing handle=%x\n", FocusHwnd);
#endif
rc = SetForegroundWindow(FocusHwnd);
// PatrickQ 4/26/96: CBA fix, don't call OpenIcon if the
// SetForegroundWindow call failed. This prevents the PMShell window from
// being in a restored state when we attempt this code while a screen such
// as CTRL-ALT-DEL is on the desktop
if (!rc)
{
#if DBG
DbgPrint("SetForegroundWindow failed, rc=0\n");
#endif
return ERROR_INVALID_PARAMETER;
}
rc = OpenIcon(FocusHwnd);
// rc = ShowWindow(FocusHwnd, SW_SHOWMAXIMIZED);
if (!rc)
{
#if DBG
DbgPrint("OpenIcon failed, rc=0\n");
#endif
return ERROR_INVALID_PARAMETER;
}
else
return NO_ERROR;
}
void PMNTSetFullScreen(USHORT Register)
{
CONSOLE_GRAPHICS_BUFFER_INFO GraphicsInfo;
HANDLE Handle;
COORD NewCoord;
/* Size of video save block. */
DWORD stateLength;
/* Video save block pointer. */
CHAR_INFO *textBuffer;
COORD textBufferSize; // Dimensions of the shared buffer
DWORD ModeFlags;
int i;
HANDLE ThreadHandle;
ULONG Tid;
#if DBG
DbgPrint("PMNTSetFullScreen was called\n");
#endif
if (Register)
{
// Create PMNTVDMEvent event objects
if (!Os2InitializeVDMEvents())
{
#if DBG
DbgPrint("Os2: PMNTSetFullScreen, ERROR - Os2InitializeVDMEvents() failed\n");
#endif // DBG
printf("Os2: PMNTSetFullScreen, ERROR - Os2InitializeVDMEvents() failed\n");
DosExit(0, 0);
}
PMNTReadDisplayAdapterName();
if (Register == 2)
{
HWDumpVersion = TRUE;
PMNTSetFullScreenDump();
return;
}
}
else // !Register
{
/**********************************************************************
* Un-register VDM: called by PMSHELL as part of its exit-list
**********************************************************************/
textBufferSize.X = 80;
textBufferSize.Y = 50;
stateLength = sizeof(CHAR_INFO)*80*50;
if (!RegisterConsoleVDM( FALSE,
hStartHardwareEvent,
hEndHardwareEvent,
(LPWSTR) NULL,
(DWORD) 0,
&stateLength,
(PVOID *) &videoState,
(LPWSTR) NULL,
(DWORD) 0,
textBufferSize,
(PVOID *) &textBuffer
)
)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, UnRegisterConsoleVDM() failed\n");
#endif
}
return;
}
//
// open a new console
//
GraphicsInfo.dwBitMapInfoLength = sizeof(bmiPat);
GraphicsInfo.lpBitMapInfo = (LPBITMAPINFO)&bmiPat;
GraphicsInfo.dwUsage = DIB_RGB_COLORS;
// Set some fields according to the display resolution
GraphicsInfo.lpBitMapInfo->bmiHeader.biWidth = ScreenX;
// For some weird reason, the Console wants a negative value,
// otherwise it prints a: "****** Negating biHeight" message.
GraphicsInfo.lpBitMapInfo->bmiHeader.biHeight = -ScreenY;
GraphicsInfo.lpBitMapInfo->bmiHeader.biSizeImage = ScreenX*ScreenY/8;
Handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_GRAPHICS_BUFFER,
&GraphicsInfo
);
if (Handle == (HANDLE)-1)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, CreateConsoleScreenBuffer() failed, error=0x%x\n",
GetLastError());
#endif
printf("PMSS: Internal error, CreateConsoleScreenBuffer() failed, error=0x%x\n",
GetLastError());
DosExit(0, 0);
return;
}
//
// make it current
//
if (!SetConsoleActiveScreenBuffer(Handle))
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, SetConsoleActiveScreenBuffer() failed, error=0x%x\n",
GetLastError());
#endif
printf("PMSS: Internal error, SetConsoleActiveScreenBuffer() failed, error=0x%x\n",
GetLastError());
DosExit(0, 0);
return;
}
if (!SetConsoleKeyShortcuts(
TRUE,
CONSOLE_ALTENTER,
NULL,
0
)
)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, SetConsoleKetShortcuts() failed, error=0x%x\n",
GetLastError());
#endif
}
if (!GetConsoleDisplayMode(&ModeFlags))
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, GetConsoleDisplayMode() failed, error=0x%x\n",
GetLastError());
#endif
printf("PMSS: Internal error, GetConsoleDisplayMode() failed, error=0x%x\n",
GetLastError());
DosExit(0, 0);
return;
}
// Is the Console already full-screen ?
if ((ModeFlags & CONSOLE_FULLSCREEN) != 0)
{
#if DBG
DbgPrint("Os2: PMNTSetFullScreen, ERROR - trying to run PMShell from full-screen session !\n");
#endif // DBG
SetConsoleKeyShortcuts(
TRUE,
0,
NULL,
0);
Ow2PMShellErrorPopup(Od2PgmFilePath, ERROR_PMSHELL_FULLSCREEN);
DosExit(0, 0);
return;
}
/*
* Register start and end events with the console. These events are used
* when gaining or losing control of the hardware.
*/
hStartHardwareEvent = CreateEventW((LPSECURITY_ATTRIBUTES) NULL,
FALSE,
FALSE,
NULL);
hEndHardwareEvent = CreateEventW((LPSECURITY_ATTRIBUTES) NULL,
FALSE,
FALSE,
NULL);
if ((hStartHardwareEvent == NULL) || (hEndHardwareEvent == NULL))
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, Cannot create start or end events\n");
#endif
printf("PMSS: Internal error, cannot create start or end events\n");
DosExit(0, 0);
return;
}
/* Poll the event to try and get rid of any console queued sets
* This shouldn't be needed (or shouldn't work) but something along
* those lines seems to be happening at the moment.
*/
WaitForSingleObject(hStartHardwareEvent, 0);
// Get rid of any events at that point
FlushConsoleInputBuffer(hConsoleInput);
textBufferSize.X = 80;
textBufferSize.Y = 50;
stateLength = sizeof(CHAR_INFO)*80*50;
if (!RegisterConsoleVDM( TRUE,
hStartHardwareEvent,
hEndHardwareEvent,
(LPWSTR) NULL,
(DWORD) 0,
&stateLength,
(PVOID *) &videoState,
(LPWSTR) NULL,
(DWORD) 0,
textBufferSize,
(PVOID *) &textBuffer
) ||
(!stateLength)
)
{
#if DBG
DbgPrint("PMNTSetFullScreen: ERROR, RegisterConsoleVDM() failed, error=0x%x\n",
GetLastError());
#endif
printf("PMSS: Internal error, RegisterConsoleVDM() failed\n");
// Restore Console state
SetConsoleKeyShortcuts(
TRUE,
0,
NULL,
0);
DosExit(0, 0);
return;
}
// Set values for PortValue[]
for (i=0; i<0x30; i++)
videoState->PortValue[i] = InitStatePortValue[i];
// Initial value for AttribIndexDataState
videoState->AttribIndexDataState = 1;
if (!PMNTReadVideoDump())
{
PMNTChkQVision();
}
ThreadHandle = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE)Os2VDMThread,
NULL,
0,
&Tid);
if (!ThreadHandle)
{
#if DBG
DbgPrint("OS2: PMNTSetFullScreen, fail to CreateThread, error %d\n",GetLastError());
#endif
}
else
{
DWORD Status;
Status = NtClose(ThreadHandle);
#if DBG
if (!(Status >= 0))
{
DbgPrint("PMNTSetFullScreen: NtClose(%x) failed, status=%x\n",
ThreadHandle, Status);
}
#endif // DBG
}
if (!SetConsoleDisplayMode(
Handle,
CONSOLE_FULLSCREEN_MODE,
&NewCoord
))
{
#if DBG
DbgPrint("SetConsoleDisplayMode() 0x%x %d failed\n", GetLastError(),
GetLastError());
#endif
}
// Work-around for cases where the Console doesn't make us full-screen
PMNTSetFocus(Ow2ForegroundWindow);
// Wait for Os2VDMThread() to get events from the Console signifying we
// went full-screen
Os2WaitForVDMThread(0);
#if DBG
DbgPrint("Os2: PMNTSetFullScreen returning\n");
#endif
}
/******************************************************************************
* PMNTCloseWindow:
*
* Minimize the current window. This function is called when switching from
* one of the CMD windows representing a PM app to the PMShell window.
*
******************************************************************************/
PMNTCloseWindow()
{
if (ProcessIsPMShell())
{
DWORD Dummy;
#if DBG
DbgPrint("PMNTCloseWindow\n");
#endif
// Special case: minimize PMShell window
if (!VDMConsoleOperation(
1, //VDM_HIDE_WINDOW
(LPVOID)&Dummy))
{
#if DBG
DbgPrint("PMNTCloseWindow: VDMConsoleOperation() 1 failed, error=0x%x\n",
GetLastError());
#endif
return ERROR_INVALID_PARAMETER;
}
ShowWindow(Ow2ForegroundWindow, SW_HIDE);
if (!VDMConsoleOperation(
1, //VDM_HIDE_WINDOW
(LPVOID)&Dummy))
{
#if DBG
DbgPrint("PMNTCloseWindow: VDMConsoleOperation() 2 failed, error=0x%x\n",
GetLastError());
#endif
return ERROR_INVALID_PARAMETER;
}
return NO_ERROR;
}
#if 0
The code below results in setting the window size to the size of an icon.
This is done so that double-clicking on such a window next time
produces the smallest possible transient restored window.
Unfortunately, this is not feasible because the current CMD window may be
a CMD window which the user expects to get back unharmed after the PM app
terminates (i.e. we shouldn't change its size) !
static int FirstTime = 0;
if (FirstTime < 2)
{
if (!SetWindowPos(
Ow2ForegroundWindow,
HWND_TOP,
0, // X (ignored)
0, // Y (ignored)
GetSystemMetrics(SM_CXICON), // CX
GetSystemMetrics(SM_CYICON), // CY
SWP_NOMOVE))
{
#if DBG
DbgPrint("SetWindowPos failed, rc=%d\n",
GetLastError());
#endif
}
FirstTime++;
}
#endif //0
#if DBG
DbgPrint("PMNTCloseWindow: passing handle=%x\n", Ow2ForegroundWindow);
#endif
// PatrickQ 4/26/96: Upon closing the current window, take the opportunity
// to correct situations where we remember a 0 Ow2ForeGroundWindow
// because, for example, the PM app was started when a CTRL-ALT-DEL screen
// was active. This change is prompted by the CBA problem when starting
// PM apps while screen is locked
if (Ow2ForegroundWindow == 0)
{
// Re-acquire Ow2ForegroundWindow
Ow2ForegroundWindow = GetForegroundWindow();
}
if (!CloseWindow(Ow2ForegroundWindow))
{
#if DBG
DbgPrint("CloseWindow failed, rc=%d\n",
GetLastError());
#endif
}
return NO_ERROR;
}
VOID
PMNTGetFullScreen(
ULONG Operation
)
{
#ifdef JAPAN
DWORD dwNlsMode;
#endif // JAPAN
#ifndef PMNT_DAYTONA
HANDLE ThreadHandle = NULL;
ULONG Tid;
#endif // PMNT_DAYTONA
ULONG rc;
switch (Operation)
{
case 1: // Wait till we must loose focus
#if DBG
DbgPrint("PMNTGetFullScreen(1): waiting for notification of lost focus\n");
#endif
#ifdef JAPAN // MSKK [ShigeO] Aug 18, 1993
//
// Disable Win32 IME on PM desktop
//
if(!GetConsoleNlsMode(hConsoleInput, &dwNlsMode)) {
#if DBG
DbgPrint("GetConsoleNlsMode() 0x%x %d failed\n", GetLastError(), GetLastError());
#endif
} else {
#if DBG
DbgPrint("PMNTGetFullScreen: We are calling SetConsoleNlsMode\n");
#endif
if(!SetConsoleNlsMode(hConsoleInput, dwNlsMode | NLS_IME_DISABLE)) {
#if DBG
DbgPrint("SetConsoleNlsMode() 0x%x %d failed\n", GetLastError(), GetLastError());
#endif
}
}
#endif // JAPAN
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
{
#if DBG
DbgPrint("PMNTGetFullScreen(1): WaitForSingleObject(hStartHardwareEvent, INFINITE) failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(1): got notification of lost focus, returning\n");
#endif
PMNTInFocus = FALSE;
return;
case 2: // Notify Console it can take the focus away from us
#if DBG
DbgPrint("PMNTGetFullScreen(2): sending event to console\n");
#endif
if (!SetEvent(hEndHardwareEvent))
{
#if DBG
DbgPrint("PMNTGetFullScreen(2): SetEvent(hEndHardwareEvent) #1 failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(2): about to wait#2\n");
#endif
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
{
#if DBG
DbgPrint("PMNTGetFullScreen(2): WaitForSingleObject(hStartHardwareEvent, INFINITE) failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(2): wait#2 succeeded\n");
#endif
if (!SetEvent(hEndHardwareEvent))
{
#if DBG
DbgPrint("PMNTGetFullScreen(2): SetEvent(hEndHardwareEvent) #2 failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(2): SetEvent(hEndHardwareEvent#2) succeeded, returning\n");
#endif
return;
case 3: // Wait till we gain focus
#if DBG
DbgPrint("PMNTGetFullScreen(3): waiting for notification of gain focus\n");
#endif
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): WaitForSingleObject(hStartHardwareEvent, INFINITE) #1 failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(3): wait#1 succeeded (got focus)\n");
#endif
#if 0
{
ULONG offset;
int i;
DbgPrint("------------------------------------------------------\n");
DbgPrint("Hardware state header:\n");
DbgPrint("- Length=%x\n", videoState->Length);
DbgPrint("- PortValues:\n");
for (i=0; i<0x30; i++)
DbgPrint(" %d: %x\n", i, videoState->PortValue[i]);
DbgPrint("- AttribIndexDataState=%x\n", videoState->AttribIndexDataState);
DbgPrint("- BasicSequencerOffset=%x\n", videoState->BasicSequencerOffset);
for (offset = videoState->BasicSequencerOffset, i=0;
offset < videoState->BasicCrtContOffset;
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- BasicCrtContOffset=%x\n", videoState->BasicCrtContOffset);
for (offset = videoState->BasicCrtContOffset, i=0;
offset < videoState->BasicGraphContOffset;
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- BasicGraphContOffset=%x\n", videoState->BasicGraphContOffset);
for (offset = videoState->BasicGraphContOffset, i=0;
offset < videoState->BasicAttribContOffset;
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- BasicAttribContOffset=%x\n", videoState->BasicAttribContOffset);
for (offset = videoState->BasicAttribContOffset, i=0;
offset < videoState->BasicDacOffset;
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- BasicDacOffset=%x\n", videoState->BasicDacOffset);
for (offset = videoState->BasicDacOffset, i=0;
offset < videoState->BasicLatchesOffset;
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- BasicLatchesOffset=%x\n", videoState->BasicLatchesOffset);
for (offset = videoState->BasicLatchesOffset, i=0;
offset < min(videoState->ExtendedSequencerOffset,0);
offset++,i++)
{
if (!(i % 16))
DbgPrint("\n %2x: ", i);
DbgPrint("%2x ", *(BYTE *)((ULONG)videoState + offset));
}
DbgPrint("\n");
DbgPrint("- ExtendedSequencerOffset=%x\n", videoState->ExtendedSequencerOffset);
DbgPrint("- ExtendedCrtContOffset=%x\n", videoState->ExtendedCrtContOffset);
DbgPrint("- ExtendedGraphContOffset=%x\n", videoState->ExtendedGraphContOffset);
DbgPrint("- ExtendedAttribContOffset=%x\n", videoState->ExtendedAttribContOffset);
DbgPrint("- ExtendedDacOffset=%x\n", videoState->ExtendedDacOffset);
DbgPrint("- ExtendedValidatorStateOffset=%x\n", videoState->ExtendedValidatorStateOffset);
DbgPrint("- ExtendedMiscDataOffset=%x\n", videoState->ExtendedMiscDataOffset);
DbgPrint("- PlaneLength=%x\n", videoState->PlaneLength);
DbgPrint("- Plane1Offset=%x\n", videoState->Plane1Offset);
DbgPrint("- Plane2Offset=%x\n", videoState->Plane2Offset);
DbgPrint("- Plane3Offset=%x\n", videoState->Plane3Offset);
DbgPrint("- Plane4Offset=%x\n", videoState->Plane4Offset);
DbgPrint("- VGAStateFlags=%x\n", videoState->VGAStateFlags);
DbgPrint("- DIBOffset=%x\n", videoState->DIBOffset);
DbgPrint("- DIBBitsPerPixel=%x\n", videoState->DIBBitsPerPixel);
DbgPrint("- DIBXResolution=%x\n", videoState->DIBXResolution);
DbgPrint("- DIBYResolution=%x\n", videoState->DIBYResolution);
DbgPrint("- DIBXlatOffset=%x\n", videoState->DIBXlatOffset);
DbgPrint("- DIBXlatLength=%x\n", videoState->DIBXlatLength);
DbgPrint("------------------------------------------------------\n");
}
#endif // 0
if (HWDumpVersion)
{
// Workaround for unknown video adapters
// Dump videoState into c:\os2\videohw.dmp
if (!VideoDumped)
{
VideoDumped=TRUE;
PMNTVideoDump();
}
}
#ifndef PMNT_DAYTONA
// Create a thread that will wait on the StartHardware event before
// we release the Console. This will prevent the Console from
// setting the event twice without letting us sense it twice
ThreadHandle = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE)Os2VDMGetStartThread,
NULL,
0,
&Tid);
#if DBG
DbgPrint("PMNTGetFullScreen(3): Create Os2VDMGetStartThread(), handle = %x\n", ThreadHandle);
#endif
Sleep(50L); // Sleep 50 miliseconds to make sure the above thread is
// waiting on the event
if (ThreadHandle)
{
DWORD Status;
Status = NtClose(ThreadHandle);
#if DBG
if (!(Status >= 0))
{
DbgPrint("PMNTGetFullScreen(3): NtClose(%x) failed, status=%x\n",
ThreadHandle, Status);
}
#endif // DBG
if (!Os2WaitForVDMThreadReady())
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): Os2WaitForVDMThread isn't useful, ThreadHandle = NULL\n");
#endif // DBG
ThreadHandle = NULL;
}
#if DBG
else
DbgPrint("PMNTGetFullScreen(3): Os2VDMGetStartThread is ready\n");
#endif
}
#if DBG
else
{
DbgPrint("PMNTGetFullScreen(3): CreateThread for Os2VDMGetStartThread failed, error=%x\n",
GetLastError());
}
#endif // DBG
#endif // not PMNT_DAYTONA
// Restore PM/NT mouse position
if (LastMousePosition.X != -1)
SetCursorPos(LastMousePosition.X,
LastMousePosition.Y);
if (!SetEvent(hEndHardwareEvent))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): SetEvent(hEndHardwareEvent) #1 failed, error=%x\n",
GetLastError());
#endif
return;
}
#if DBG
DbgPrint("PMNTGetFullScreen(3): about to wait#2\n");
#endif
#ifndef PMNT_DAYTONA
if (ThreadHandle != NULL)
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): waiting for Os2VDMGetStartThread()\n");
#endif
// Wait for Os2VDMGetStartThread() to get events from the
// Console signifying we went full-screen
if (!Os2WaitForVDMThread(0))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): Os2WaitForVDMThread failed, return\n");
#endif
return;
}
}
else
{
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): WaitForSingleObject(hStartHardwareEvent, INFINITE) #2 failed, error=%x\n",
GetLastError());
#endif
return;
}
}
#else // PMNT_DAYTONA
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): WaitForSingleObject(hStartHardwareEvent, INFINITE) #2 failed, error=%x\n",
GetLastError());
#endif
return;
}
if (!SetEvent(hEndHardwareEvent))
{
#if DBG
DbgPrint("PMNTGetFullScreen(3): SetEvent(hEndHardwareEvent) #2 failed, error=%x\n",
GetLastError());
#endif
return;
}
#endif // PMNT_DAYTONA
#if DBG
DbgPrint("PMNTGetFullScreen(3): returning\n");
#endif
PMNTInFocus = TRUE;
return;
default:
#if DBG
DbgPrint("PMNTGetFullScreen: bad command %d\n", Operation);
#endif
return;
}
}
BOOLEAN
Ow2WriteBackCloseEvent()
{
INPUT_RECORD InputRecord;
BOOLEAN WriteSucceeded;
DWORD RecordsWritten;
if (!ProcessIsPMProcess()) {
return(FALSE);
}
InputRecord.EventType = MENU_EVENT;
InputRecord.Event.MenuEvent.dwCommandId = WM_USER;
WriteSucceeded = WriteConsoleInput(hConsoleInput,
&InputRecord, 1, &RecordsWritten);
if (!WriteSucceeded || (RecordsWritten != 1)) {
#if DBG
DbgPrint("OS2: Ow2WriteBackCloseEvent - failed to write into input queue\n");
#endif // DBG
return(FALSE);
}
return(TRUE);
}
#endif // PMNT