summaryrefslogtreecommitdiffstats
path: root/private/os2/os2ses/monrqust.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/os2/os2ses/monrqust.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/os2/os2ses/monrqust.c')
-rw-r--r--private/os2/os2ses/monrqust.c793
1 files changed, 793 insertions, 0 deletions
diff --git a/private/os2/os2ses/monrqust.c b/private/os2/os2ses/monrqust.c
new file mode 100644
index 000000000..08c260829
--- /dev/null
+++ b/private/os2/os2ses/monrqust.c
@@ -0,0 +1,793 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ monrqust.c
+
+Abstract:
+
+ This module contains the Mon requests thread and
+ the handler for Mon requests.
+
+Author:
+
+ Michael Jarus (mjarus) 21-Jan-1992
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#define WIN32_ONLY
+#include "os2ses.h"
+#include "event.h"
+#include "trans.h"
+#include "monitor.h"
+#include "mon.h"
+#include <stdio.h>
+
+
+USHORT RegSize[] = { MIN_KBD_MON_BUFFER, 127 };
+USHORT RWSize[] = { sizeof(KBD_MON_PACKAGE),
+ sizeof(MOU_MON_PACKAGE) };
+
+extern CRITICAL_SECTION QueueInputCriticalSection;
+
+DWORD
+MonQueueClose(IN HANDLE hMon);
+
+DWORD
+InitMonitor()
+{
+ RtlZeroMemory(&MonBuffTable[0].MonHeader, sizeof(MonBuffTable));
+ MonQueue = NULL;
+
+ MonitorEvent = CreateEventW(
+ NULL,
+ FALSE, /* auto reset */
+ TRUE,
+ NULL);
+
+ if (MonitorEvent == NULL)
+ {
+#if DBG
+ DbgPrint("OS2SES(InitMonitor): unable to create event for Monitor\n");
+#endif
+ return 1L;
+ }
+
+ KbdLastKeyDown = FALSE;
+
+ LastKbdMon = NULL;
+ LastMouMon = NULL;
+
+ return(0L);
+}
+
+
+BOOL
+ServeMonRequest(IN PMONREQUEST PReq,
+ OUT PVOID PStatus,
+ IN PVOID pMsg,
+ OUT PULONG pReply)
+{
+ DWORD Rc;
+
+ Rc = *(PDWORD) PStatus = 0;
+
+ switch (PReq->Request)
+ {
+ case MONOpen:
+ Rc = *(PDWORD) PStatus = MonOpen(PReq->d.OpenClose.MonDevice,
+ &(PReq->d.OpenClose.hMON));
+ break;
+
+ case MONReg:
+ Rc = *(PDWORD) PStatus = MonReg(&(PReq->d.Reg));
+ break;
+
+ case MONRead:
+ Rc = *(PDWORD) PStatus = MonRead(&(PReq->d.rwParms),
+ pReply,
+ pMsg);
+ break;
+
+ case MONWrite:
+ Rc = *(PDWORD) PStatus = MonWrite(&(PReq->d.rwParms),
+ pReply,
+ pMsg);
+ break;
+
+ case MONClose:
+ Rc = *(PDWORD) PStatus = MonClose(PReq->d.OpenClose.hMON);
+ break;
+
+ default:
+ Rc = *(PDWORD) PStatus = ERROR_MON_INVALID_PARMS;
+#if DBG
+ IF_OD2_DEBUG( OS2_EXE )
+ {
+ DbgPrint("OS2SES(MonRequest): Unknown Mon request = %X\n",
+ PReq->Request);
+ }
+#endif
+ }
+
+ return(TRUE); // Continue
+}
+
+
+DWORD
+MonOpen(IN MONDEVNUMBER DevType,
+ OUT PHANDLE hMon)
+{
+ DWORD Rc;
+
+ /*
+ * allocate buffer for header & queue
+ */
+
+ if (DevType == KbdDevice)
+ {
+ Rc = InitQueue((PKEY_EVENT_QUEUE *)hMon);
+ } else if (DevType == MouseDevice)
+ {
+ Rc = InitMouQueue((PMOU_EVENT_QUEUE *)hMon);
+ } else /* if (DevType == Lpt1Device) */
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ IF_OD2_DEBUG( OS2_EXE )
+ DbgPrint("OS2SES(MonOpen): illegal device\n");
+#endif
+
+ return(ERROR_MONITOR_NOT_SUPPORTED);
+ }
+
+ if (Rc)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonOpen): unable to allocate handle\n");
+#endif
+
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ ((PKEY_EVENT_QUEUE)*hMon)->MonHdr.DevType = DevType;
+ ((PKEY_EVENT_QUEUE)*hMon)->MonHdr.MonStat = MON_STAT_OPEN; // Mon-Open
+ ((PKEY_EVENT_QUEUE)*hMon)->MonHdr.NextMon = NULL;
+
+#if DBG
+ IF_OD2_DEBUG( MON )
+ {
+ DbgPrint("OS2SES(MonOpen): return address %lx\n", *hMon);
+ }
+#endif
+
+ return(0L);
+}
+
+
+DWORD
+MonReg(IN PMON_REG MonReg)
+{
+ DWORD Rc;
+ BOOL NewReg = FALSE;
+ PMON_HEADER NextMon, NewMonHeader;
+ PKEY_EVENT_QUEUE hMon;
+
+ /*
+ * make sure buffer are not used for other monitor
+ */
+
+ if ((FindMonitorBuffer(MonReg->In, MonReg->ProcessId)) ||
+ (FindMonitorBuffer(MonReg->Out, MonReg->ProcessId)))
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonReg): buffer already reg\n");
+#endif
+
+ return ERROR_MON_INVALID_PARMS;
+ }
+
+ hMon = (PKEY_EVENT_QUEUE)MonReg->hMON;
+
+#if DBG
+ IF_OD2_DEBUG( MON )
+ {
+ DbgPrint("OS2SES(MonReg): hMon address %lx\n", hMon);
+ }
+#endif
+
+ if ((MonReg->InSize < RegSize[hMon->MonHdr.DevType]) ||
+ (MonReg->OutSize < RegSize[hMon->MonHdr.DevType]))
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonReg): buffer too small\n");
+#endif
+
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ if (hMon->MonHdr.MonStat != MON_STAT_OPEN)
+ {
+ /*
+ * queue in use, allocate new one
+ */
+
+#if DBG
+ IF_OD2_DEBUG( MON )
+ {
+ DbgPrint("OS2SES(MonReg): allocate new queue\n");
+ }
+#endif
+
+ NewReg = TRUE;
+
+ if ((Rc = MonOpen(hMon->MonHdr.DevType,
+ (PHANDLE)&NewMonHeader)))
+ {
+#if DBG
+ DbgPrint("OS2SES(MonReg): unable to allocate handle\n");
+#endif
+ return Rc;
+ }
+
+ NextMon = (PMON_HEADER)hMon;
+
+ while (NextMon->NextMon != NULL)
+ {
+ NextMon = NextMon->NextMon;
+ }
+
+#if DBG
+ IF_OD2_DEBUG( MON )
+ {
+ DbgPrint("OS2SES(MonReg): find place\n");
+ }
+#endif
+
+ } else
+ NewMonHeader = (PMON_HEADER)hMon;
+
+ NewMonHeader->MonReg = *MonReg;
+
+ /*
+ * add monitor to the device-queue
+ */
+
+ Rc = AddMonitor(NewMonHeader, (PMON_HEADER *)
+ ((NewMonHeader->DevType == KbdDevice) ?
+ (PMON_HEADER *) &KbdMonQueue : (PMON_HEADER *) &MouMonQueue));
+
+ if (Rc)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonReg): unable to register\n");
+#endif
+
+ if (NewReg)
+ {
+ HeapFree(HandleHeap, 0,
+ (LPSTR) NewMonHeader->MemoryStartAddress);
+ }
+
+ return(Rc);
+ }
+
+ /*
+ * add buffer to table of monitor-buffer
+ */
+
+ AddMonitorBuffer(MonReg->In, NewMonHeader, MonReg->ProcessId);
+ AddMonitorBuffer(MonReg->Out, NewMonHeader, MonReg->ProcessId);
+
+ NewMonHeader->MonStat = MON_STAT_REG; // Mon-Open-And-Reg
+
+ if (NewReg)
+ {
+ NextMon->NextMon = NewMonHeader;
+ }
+
+ MonReg->InSize = RWSize[NewMonHeader->DevType];
+ MonReg->OutSize = RWSize[NewMonHeader->DevType];
+
+ return(0L);
+}
+
+
+DWORD
+MonRead(IN OUT PMON_RW rwParms,
+ OUT PULONG pReply,
+ IN PVOID pMsg)
+{
+ PMON_HEADER MonHeader;
+ USHORT Length = 0;
+ DWORD MonBuf, Rc;
+
+ /*
+ * check legalty of BUFFER-In, Size of DataBuffer and Monitor state
+ */
+
+ if (!(MonBuf = FindMonitorBuffer(rwParms->MonBuffer, rwParms->ProcessId)) ||
+ (MonBuf == -1L))
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonRead): unable to find buffer\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ MonHeader = (PMON_HEADER)MonBuf;
+
+ if (MonHeader->MonReg.In != rwParms->MonBuffer)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonRead): illegal monitor buffer\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ if (rwParms->Length < RWSize[MonHeader->DevType])
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonRead): buffer too small\n");
+#endif
+
+ return(ERROR_MON_BUFFER_TOO_SMALL);
+ }
+
+ if (MonHeader->MonStat != MON_STAT_REG)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonRead): state not ok\n");
+#endif
+
+ //ASSERT(FALSE);
+
+// return(ERROR_MON_INVALID_PARMS);
+ }
+
+ /*
+ * read event if available
+ */
+
+ MonHeader->MonStat = MON_STAT_READ;
+
+ Rc = GetMonInput(
+ RWSize[MonHeader->DevType],
+ (PKEY_EVENT_QUEUE)MonHeader,
+ rwParms,
+ pMsg,
+ pReply
+ );
+
+ if ( *pReply != 0 )
+ {
+ MonHeader->MonStat = MON_STAT_REG;
+ }
+
+ return (Rc);
+}
+
+
+DWORD
+MonWrite(IN PMON_RW rwParms,
+ OUT PULONG pReply,
+ IN PVOID pMsg)
+{
+ PMON_HEADER MonHeader;
+ USHORT Length = 0;
+ DWORD MonBuf, Rc;
+
+ UNREFERENCED_PARAMETER(pMsg);
+ UNREFERENCED_PARAMETER(pReply);
+
+ /*
+ * check legalty of BUFFER-Out, Size of DataBuffer and Monitor state
+ */
+
+ if (!(MonBuf = FindMonitorBuffer(rwParms->MonBuffer, rwParms->ProcessId)) ||
+ (MonBuf == -1L))
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonWrite): unable to find buffer\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ MonHeader = (PMON_HEADER)MonBuf;
+
+ if (MonHeader->MonReg.Out != rwParms->MonBuffer)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonWrite): illegal monitor buffer\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ if (rwParms->Length < RWSize[MonHeader->DevType])
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonWrite): buffer too small\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ if (rwParms->Length > RWSize[MonHeader->DevType]) // BUGBUG
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonWrite): buffer too big\n");
+#endif
+
+ return(ERROR_MON_DATA_TOO_LARGE);
+ }
+
+ if (MonHeader->MonStat == MON_STAT_OPEN)
+ {
+#if DBG
+ IF_OD2_DEBUG( MON )
+ DbgPrint("OS2SES(MonWrite): state not ok\n");
+#endif
+
+ return(ERROR_MON_INVALID_PARMS);
+ }
+
+ /*
+ * write event
+ */
+
+#if DBG
+ IF_OD2_DEBUG( MON )
+ {
+ DbgPrint("OS2SES(MonWrite): (before) from queue %lx, to queue %lx\n",
+ MonHeader, MonHeader->NextQueue );
+ }
+#endif
+
+ Rc = PutMonInput(
+ RWSize[MonHeader->DevType],
+ (PKEY_EVENT_QUEUE)MonHeader->NextQueue,
+ 1,
+ //rwParms,
+ (PKBD_MON_PACKAGE)&(rwParms->ioBuff[0]),
+ pMsg,
+ pReply);
+
+ // BUGBUG if not enough place
+
+ return( Rc );
+}
+
+
+DWORD
+MonClose(IN HANDLE hMon)
+{
+ PMON_HEADER NextMon, MonHeader = (PMON_HEADER)hMon;
+
+ while (MonHeader)
+ {
+ NextMon = MonHeader->NextMon;
+ MonQueueClose((HANDLE)MonHeader);
+ MonHeader = NextMon;
+ }
+
+ return(0L);
+}
+
+
+DWORD
+MonQueueClose(IN HANDLE hMon)
+{
+ PMON_HEADER MonHeader = (PMON_HEADER)hMon;
+
+ if (MonHeader->MonStat >= MON_STAT_REG)
+ {
+ /*
+ * Monitor are reg - DeReg :
+ * remove monitor & delete entried in table
+ */
+
+ RemoveMonitor(MonHeader, (PMON_HEADER *)
+ ((MonHeader->DevType == KbdDevice) ?
+ (PMON_HEADER *) &KbdMonQueue :
+ (PMON_HEADER *) &MouMonQueue));
+
+ DelMonitorBuffer(MonHeader);
+ }
+
+ /*
+ * Free header from heap
+ */
+
+ HeapFree(HandleHeap, 0,
+ (LPSTR) MonHeader->MemoryStartAddress);
+
+ return(0L);
+}
+
+
+DWORD
+FindMonitorBuffer(IN PVOID Buffer,
+ IN ULONG ProcessId)
+{
+ ULONG i, FreeCount = 0;
+
+ for ( i = 0 ; i < MON_BUFFER_TABLE_SIZE ; i++ )
+ {
+ if ((MonBuffTable[i].Buffer == Buffer) &&
+ (MonBuffTable[i].ProcessId == ProcessId))
+ {
+ return((DWORD)MonBuffTable[i].MonHeader);
+ } else if (!MonBuffTable[i].Buffer)
+ {
+ FreeCount++;
+ }
+
+ }
+
+ if (FreeCount < 2)
+ {
+ return((DWORD)-1L); // no place for new 2 buffers
+ }
+
+ return(0L);
+}
+
+
+DWORD
+AddMonitorBuffer(IN PVOID Buffer,
+ IN PMON_HEADER MonHeader,
+ IN ULONG ProcessId)
+{
+ ULONG i, FindCount = 0;
+
+ for ( i = 0 ; i < MON_BUFFER_TABLE_SIZE ; i++ )
+ {
+ if (!MonBuffTable[i].Buffer)
+ {
+ MonBuffTable[i].Buffer = Buffer;
+ MonBuffTable[i].MonHeader = MonHeader;
+ MonBuffTable[i].ProcessId = ProcessId;
+
+ return((DWORD)MonBuffTable[i].MonHeader);
+ }
+ }
+
+ ASSERT( FALSE );
+
+ return(0L);
+}
+
+
+DWORD
+DelMonitorBuffer(IN PMON_HEADER MonHeader)
+{
+ ULONG i, FindCount = 0;
+
+ for ( i = 0 ; i < MON_BUFFER_TABLE_SIZE ; i++ )
+ {
+ if (MonBuffTable[i].MonHeader == MonHeader)
+ {
+ RtlZeroMemory(&(MonBuffTable[i]), sizeof(MON_BUFFER_TABLE));
+ FindCount++;
+ }
+ }
+
+ ASSERT( FindCount == 2 );
+
+ return(0L);
+}
+
+
+DWORD
+NewKbdQueue(IN PKEY_EVENT_QUEUE NewKbdQueue)
+{
+
+ if (WaitForSingleObject( MonitorEvent, INFINITE ))
+ {
+ return(ERROR_MONITOR_NOT_SUPPORTED);
+ }
+
+ if (LastKbdMon != NULL)
+ {
+ LastKbdMon->MonHdr.NextQueue = (PMON_HEADER)NewKbdQueue;
+ } else
+ KbdMonQueue = NewKbdQueue;
+
+ SetEvent( MonitorEvent );
+
+ return(0L);
+}
+
+
+DWORD AddMonitor(IN PMON_HEADER NewMonHeader,
+ IN PMON_HEADER *pMonQueue)
+{
+ PMON_HEADER MonHeader, LastMonHeader = NULL;
+ USHORT Index;
+#if DBG
+ PMON_HEADER DbgMonHeader;
+#endif
+
+ /*
+ * Positioning in chain
+ * --------------------
+ * 1st registered as FIRST
+ * ...
+ * last registered as FIRST
+ * last registered as DEFAULT
+ * ...
+ * 1st registered as DEFAULT
+ * last registered as END
+ * ...
+ * 1st registered as END
+ */
+
+ if (NewMonHeader->MonReg.Pos > MONITOR_END)
+ {
+ /*
+ * ignore MONITOR_SPECIAL
+ */
+
+ NewMonHeader->MonReg.Pos -= 3;
+ NewMonHeader->Flag = 1;
+ }
+
+ /*
+ * Translate Position:
+ * FIRST = 0
+ * DEFAULT = 1
+ * END = 2
+ * device (kbd/mouse) = 3
+ *
+ * when looking for the place, DEFAULT is assign also to FIRST
+ */
+
+ if (NewMonHeader->MonReg.Pos < MONITOR_END)
+ {
+ /*
+ * XOR MONITOR_FIRST & MONITOR_DEFAULT
+ */
+
+ NewMonHeader->MonReg.Pos = 1 - NewMonHeader->MonReg.Pos;
+ }
+
+ Index = (USHORT)NewMonHeader->MonReg.Pos;
+
+ if (Index == 0)
+ {
+ Index = 1; // last FIRST is equivalent to 1st DEFAULT
+ }
+
+ if (WaitForSingleObject( MonitorEvent, INFINITE ))
+ {
+ return(ERROR_MONITOR_NOT_SUPPORTED);
+ }
+
+ MonHeader = *pMonQueue;
+
+ /*
+ * find the place in chain
+ */
+
+ while (MonHeader->MonReg.Pos < (ULONG)Index)
+ {
+ LastMonHeader = MonHeader;
+ MonHeader = MonHeader->NextQueue;
+
+ }
+
+ NewMonHeader->NextQueue = MonHeader;
+
+ if (LastMonHeader == NULL)
+ {
+ NewMonHeader->NextQueue = *pMonQueue;
+ *pMonQueue = NewMonHeader;
+ } else
+ {
+ NewMonHeader->NextQueue = LastMonHeader->NextQueue;
+ LastMonHeader->NextQueue = NewMonHeader;
+ }
+
+ if ((MonHeader->MonReg.Pos == 3) && // we add the last queue in chain for Kbd
+ (*pMonQueue == (PMON_HEADER)KbdMonQueue ))
+ {
+ LastKbdMon = (PKEY_EVENT_QUEUE)NewMonHeader;
+ }
+
+ SetEvent( MonitorEvent );
+
+#if DBG
+ DbgMonHeader = *pMonQueue;
+
+ IF_OD2_DEBUG( MON )
+ {
+ while (DbgMonHeader->NextQueue)
+ {
+ DbgPrint("OS2SES(AddMonitor): Current %lx, next %lx\n", DbgMonHeader, DbgMonHeader->NextQueue);
+
+ DbgMonHeader = DbgMonHeader->NextQueue;
+ }
+
+ DbgPrint("OS2SES(MonReg): %lx ... %lx, (%lx) %lx, %lx (%lx) ... %lx, %lx\n",
+ KbdMonQueue, LastMonHeader,
+ (LastMonHeader) ? LastMonHeader->NextQueue : NULL,
+ NewMonHeader, NewMonHeader->NextQueue, MonHeader, LastKbdMon, KbdQueue);
+ }
+#endif
+
+ return(0L);
+}
+
+
+DWORD
+RemoveMonitor(IN PMON_HEADER OldMonHeader,
+ IN PMON_HEADER *pMonQueue)
+{
+ PMON_HEADER MonHeader, LastMonHeader = NULL;
+
+ if (WaitForSingleObject( MonitorEvent, INFINITE ))
+ {
+ return(ERROR_MONITOR_NOT_SUPPORTED);
+ }
+
+ MonHeader = *pMonQueue;
+
+ /*
+ * find the place in chain
+ */
+
+ while (MonHeader != NULL && MonHeader != OldMonHeader)
+ {
+ LastMonHeader = MonHeader;
+ MonHeader = MonHeader->NextQueue;
+ }
+
+ if (MonHeader == NULL)
+ {
+ return(0);
+ }
+
+ if (LastMonHeader == NULL)
+ {
+ *pMonQueue = MonHeader->NextQueue;
+ } else
+ LastMonHeader->NextQueue = MonHeader->NextQueue;
+
+ if ((OldMonHeader->NextQueue->MonReg.Index == 3) && // we remove the last queue in chain for Kbd
+ (*pMonQueue == (PMON_HEADER)KbdMonQueue ))
+ {
+ if (LastMonHeader == NULL)
+ {
+ LastKbdMon = NULL;
+ } else
+ LastKbdMon = (PKEY_EVENT_QUEUE)LastMonHeader;
+ }
+
+ SetEvent( MonitorEvent );
+
+ return(0L);
+}