diff options
Diffstat (limited to 'private/os2/os2ses/event.c')
-rw-r--r-- | private/os2/os2ses/event.c | 4205 |
1 files changed, 4205 insertions, 0 deletions
diff --git a/private/os2/os2ses/event.c b/private/os2/os2ses/event.c new file mode 100644 index 000000000..0095988c8 --- /dev/null +++ b/private/os2/os2ses/event.c @@ -0,0 +1,4205 @@ +/*++ + +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 |