mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4205 lines
123 KiB
4205 lines
123 KiB
/*++
|
|
|
|
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
|