diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/os2/os2ses/monrqust.c | |
download | NT4.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.c | 793 |
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); +} |