source: trunk/src/kernel32/console/vio32Client.cpp

Last change on this file was 5024, checked in by sandervl, 25 years ago

added preliminary console code

File size: 33.6 KB
RevLine 
[5024]1#define INCL_WIN
2#define INCL_DOS
3#define INCL_VIO
4#define INCL_SUB
5#define INCL_DOSERRORS
6#define INCL_WINSWITCHLIST
7#include <os2.h>
8#include "DosQuerySysState2.h"
9#include <stdio.h>
10#include <stdlib.h>
11
12#include "vio32Client.h"
13#include "vio32Private.h"
14#include "vio32Utils.h"
15#include "vio32SharedData.h"
16#include "vio32Errors.h"
17
18extern "C" {
19void __cdecl _ctordtorInit();
20}
21
22kbd32Client kbd32ClientInstance;
23
24#define USE_EXCEPT 0
25
26#if (USE_EXCEPT==1)
27//*****************************************************************************
28//
29// Event handler to act on ctrl-c ctrl-break or any other kill message
30//
31//*****************************************************************************
32
33EXCEPTIONREGISTRATIONRECORD RegRec;
34
35ULONG _System MyTermHandler( PEXCEPTIONREPORTRECORD p1,
36 PEXCEPTIONREGISTRATIONRECORD p2,
37 PCONTEXTRECORD p3,
38 PVOID pv ){
39 switch( p1->ExceptionNum) {
40 case XCPT_PROCESS_TERMINATE:
41 case XCPT_ASYNC_PROCESS_TERMINATE: {
42 kbd32Close();
43 }
44 default:;
45 }
46
47 return XCPT_CONTINUE_SEARCH; /* Exception not resolved... */
48}
49
50#else
51static void APIENTRY vio32Cleanup(ULONG ulReason)
52{
53 DosBeep(200,100);
54 vio32Close();
55 DosExitList(EXLST_EXIT, vio32Cleanup);
56}
57
58#endif
59//*****************************************************************************
60//
61// Threads
62//
63//*****************************************************************************
64
65VOID _Optlink kbdThread(PVOID pParameters){
66 kbd32ClientInstance.kbdThread();
67}
68
69VOID _Optlink mouThread(PVOID pParameters){
70 kbd32ClientInstance.mouThread();
71}
72
73VOID _Optlink kbdMonitorThread(void * pParameters){
74 kbd32ClientInstance.kbdMonitorThread();
75}
76
77VOID _Optlink dataProcessingThread(void * pParameters){
78 kbd32ClientInstance.dataProcessingThread();
79}
80
81//*****************************************************************************
82//
83// kbd32Client::kbd32Client()
84//
85//*****************************************************************************
86
87kbd32Client::kbd32Client(){
88 SharedData = NULL;
89 patched = FALSE;
90 mux = (HMTX)0;
91 accessSemaphore = (HMTX)0;
92 primaryQ = (HQUEUE)0;
93 secondaryQ = (HQUEUE)0;
94 primaryQSem = (HEV)0;
95 secondaryQSem = (HEV)0;
96 mon = (HMONITOR)0;
97 mou = (HMOU)0;
98 kbdThreadId = (TID)0;
99 mouThreadId = (TID)0;
100 kbdMonitorThreadId = (TID)0;
101 dataProcessingThreadId = (TID)0;
102 threadsMustContinue = TRUE;
103 applicationType = 0;
104 applicationPid = 0;
105 hwndFrame = 0;
106 hwndClient = 0;
107 pos = &events[0];
108 inputFilters = NULL;
109 outputFilters = NULL;
110
111 DosCreateMutexSem(NULL,&mux,0,0);
112
113}
114
115
116//*****************************************************************************
117//
118// kbd32Client::~kbd32Client()
119//
120//*****************************************************************************
121
122kbd32Client::~kbd32Client(){
123 Close();
124 if (mux != 0) DosCloseMutexSem(mux);
125
126 // deallocate input filters
127 while(inputFilters != NULL){
128 vio32Filter *f = inputFilters;
129 inputFilters = (vio32Filter *)inputFilters->next;
130 free(f);
131 }
132
133 // deallocate output filters
134 while(outputFilters != NULL){
135 vio32Filter *f = outputFilters;
136 outputFilters = (vio32Filter *)outputFilters->next;
137 free(f);
138 }
139}
140
141//*****************************************************************************
142//
143// kbd32Client::init()
144//
145//*****************************************************************************
146
147APIRET kbd32Client::init(){
148 // get application pid and type
149 PPIB pib;
150 PTIB tib;
151 APIRET ret;
152
153 KBDINFO kInfo;
154 KbdGetStatus(&kInfo,0);
155 kInfo.fsMask |= (KEYBOARD_BINARY_MODE | KEYBOARD_ASCII_MODE);
156 kInfo.fsMask -= ( KEYBOARD_ASCII_MODE);
157 KbdSetStatus(&kInfo,0);
158
159 // GET APPLICATION TYPE AND MORPH THREAD
160 ret = DosGetInfoBlocks(&tib, &pib);
161 if (ret != 0) return VIO32_GETAPPINFO | ret;
162 applicationType = pib->pib_ultype;
163 applicationPid = pib->pib_ulpid;
164
165 // check valid application type
166 if ((applicationType != 2) && (applicationType != 3) && (applicationType != 0)) return VIO32_WRONGAPPTYPE;
167
168 // allow PM calls
169 if (pib->pib_ultype == 2) pib->pib_ultype = 3;
170
171 // get window information
172 if ((applicationType == 2) || (applicationType == 3)){
173 hwndClient = VIOWindowClient();
174 hwndFrame = VIOWindowFrame();
175 }
176
177#if (USE_EXCEPT==1)
178 // SETUP EXCEPTION HANDLER STRUCTURES
179 RegRec.prev_structure = NULL;
180 RegRec.ExceptionHandler = (ERR)MyTermHandler;
181#endif
182
183 // PREPARE PRIMARY QUEUE
184 char qName[64];
185 sprintf(qName,PRIMARY_QUEUE_NAME,applicationPid);
186 ret = DosCreateQueue(&primaryQ,0,qName);
187 if (ret != 0) return VIO32_CREATEQUEUE | ret;
188
189 // PREPARE SECONDARY QUEUE
190 sprintf(qName,SECONDARY_QUEUE_NAME,applicationPid);
191 ret = DosCreateQueue(&secondaryQ,0,qName);
192 if (ret != 0) return VIO32_CREATEQUEUE | ret;
193
194 // PRIMARY EVENTS SEM CREATION: to wait for data
195 ret = DosCreateEventSem(NULL,&primaryQSem,DC_SEM_SHARED,0);
196 if (ret != 0) return VIO32_CREATEHEV | ret;
197
198 // SECONDARY EVENTS SEM CREATION: to wait for data
199 ret = DosCreateEventSem(NULL,&secondaryQSem,DC_SEM_SHARED,0);
200 if (ret != 0) return VIO32_CREATEHEV | ret;
201
202 // MUTEX SEM CREATION: protect shared mem
203 char * mxName = MUTEX_NAME;
204 accessSemaphore = 0;
205 ret = DosCreateMutexSem((PSZ)mxName,&accessSemaphore,DC_SEM_SHARED,1);
206 if ((ret != 0) && (ret != ERROR_DUPLICATE_NAME)) return VIO32_CREATESHMUX | ret;
207
208 // if it already existed let's get hold of it
209 if (ret == ERROR_DUPLICATE_NAME){
210 accessSemaphore = 0;
211 ret = DosOpenMutexSem((PSZ)mxName,&accessSemaphore);
212 if (ret != 0) return VIO32_OPENSHMUX | ret;
213
214 ret = DosRequestMutexSem(accessSemaphore,SEM_INDEFINITE_WAIT);
215 if (ret != 0) return VIO32_REQUESTSHMUX | ret;
216 }
217
218 // SHARED MEMORY: comunicate from PM
219 // at this stage we have the semaphore and it is locked
220 // now do the same with the shared memory
221 PPVOID pmem = (void **)&SharedData;
222 char * shName = SHMEM_NAME;
223 BOOL creator = FALSE;
224 ret = DosAllocSharedMem(pmem,(PSZ)shName,(sizeof(kbd32SharedData)+4096)&0xFFFFF000,PAG_COMMIT | PAG_WRITE | PAG_READ );
225 if ((ret != 0) && (ret != ERROR_ALREADY_EXISTS)){
226 SharedUnlock();
227 return VIO32_ALLOCSHMEM | ret;
228 }
229
230 // if it is already there then lets' simply attach to it
231 if (ret == ERROR_ALREADY_EXISTS){
232 ret = DosGetNamedSharedMem(pmem,(PSZ)shName,PAG_READ | PAG_WRITE);
233 if (ret != 0){
234 SharedUnlock();
235 return VIO32_GETSHMEM | ret;
236 }
237 } else creator = TRUE;
238
239 // FUNNY FAILURE
240 if (SharedData == NULL){
241 SharedUnlock();
242 return VIO32_SHMEMNOTALLOCATED;
243 }
244
245 // now I have to initialize the memory: I get here only if I created it
246 if (creator) SharedData->Init();
247
248 SharedUnlock();
249
250 // start KBD thread
251 if (kbdThreadId == 0) kbdThreadId = _beginthread(::kbdThread,NULL,32768,NULL);
252
253 // start KBD thread
254 if (dataProcessingThreadId == 0) dataProcessingThreadId = _beginthread(::dataProcessingThread,NULL,32768,NULL);
255
256 // now do application type specifics
257 if (applicationType == 0){
258
259 // PREPARE MONITOR
260 ret = DosMonOpen("KBD$",&mon);
261 if (ret != 0) return VIO32_MONOPEN | ret;
262
263 monin.cb = sizeof(monin);
264 monout.cb = sizeof(monout);
265 ret = DosMonReg(mon,(BYTE *)&monin,(BYTE *)&monout,0,-1);
266 if (ret != 0) return VIO32_MONREG | ret;
267
268 // now start mon thread
269 if (kbdMonitorThreadId == 0) kbdMonitorThreadId = _beginthread(::kbdMonitorThread,NULL,32768,NULL);
270 }
271
272 // reset keyboard status
273 KBD32_RESETKEYS(keyStatus);
274
275 // add default filters
276 ULONG where = VIO32_PRE_FIRST;
277 AddFilter(&kbdMapper,where);
278
279 // prepare mouse support
280 // Get mouse handle
281 ret = MouOpen(NULL, &mou);
282 if (ret != 0) return VIO32_MOUOPEN | ret;
283
284 // Enable mouse
285 ret = MouDrawPtr(mou);
286 if (ret != 0) return VIO32_MOUDRAWPTR | ret;
287
288 // Enable all events fails on WSEB ??
289// USHORT mask = 0x7F;
290// ret = MouSetEventMask(&mask,mou);
291// if (ret != 0) return VIO32_MOUSETEVENTMASK | ret;
292
293 // now start mon thread
294 if (mouThreadId == 0) mouThreadId = _beginthread(::mouThread,NULL,32768,NULL);
295
296 // success
297 return 0;
298}
299
300//*****************************************************************************
301//
302// kbd32Client::finish()
303//
304//*****************************************************************************
305
306VOID kbd32Client::finish(){
307 threadsMustContinue = FALSE;
308 if (primaryQSem != 0) DosCloseEventSem(primaryQSem);
309 if (secondaryQSem != 0) DosCloseEventSem(secondaryQSem);
310 if (primaryQ != 0) DosCloseQueue(primaryQ);
311 if (secondaryQ != 0) DosCloseQueue(secondaryQ);
312 if (accessSemaphore != 0) DosCloseMutexSem(accessSemaphore);
313 if (mon != 0) DosMonClose(mon);
314 if (SharedData != NULL) DosFreeMem(SharedData);
315 if (mou != 0) MouClose(mou);
316#if (USE_EXCEPT==1)
317 DosUnsetExceptionHandler(&RegRec);
318#endif
319}
320
321//*****************************************************************************
322//
323// kbd32Client::Open()
324//
325//*****************************************************************************
326
327APIRET kbd32Client::Open(){
328 if (patched) return VIO32_ALREADYOPENED;
329
330 // serialize
331 LocalLock();
332
333 APIRET ret;
334
335#if (USE_EXCEPT==1)
336 // ACTIVATE EXCEPTION HANDLER
337 ret = DosSetExceptionHandler(&RegRec);
338 if (ret != 0){
339 LocalUnlock();
340 return ret | VIO32_SETEXCHANDLER;
341 }
342#else
343 APIRET rc = DosExitList(0x00008000|EXLST_ADD, vio32Cleanup);
344
345#endif
346
347 // INITIALIZE THE SYSTEM
348 ret = init();
349 if (ret != 0){
350 finish();
351 LocalUnlock();
352 return ret;
353 }
354
355 // INSTALL APPLICATION
356 ULONG nesting;
357 DosEnterMustComplete(&nesting);
358 SharedLock();
359 ret = SharedData->InstallApplication(applicationPid,((applicationType == 2) || (applicationType == 3)));
360 SharedUnlock();
361 DosExitMustComplete(&nesting);
362
363 if (ret != 0){
364 finish();
365 LocalUnlock();
366 return ret;
367 }
368
369 patched = TRUE;
370
371 LocalUnlock();
372 return 0;
373}
374
375
376//*****************************************************************************
377//
378// kbd32Client::Close()
379//
380//*****************************************************************************
381
382APIRET kbd32Client::Close(){
383 if (patched == FALSE) return VIO32_NOTOPENED;
384 if (SharedData == NULL) return VIO32_SHMEMNOTALLOCATED;
385
386 // remove settings on memory
387 ULONG nesting;
388 DosEnterMustComplete(&nesting);
389 LocalLock();
390 SharedLock();
391 SharedData->UninstallApplication(applicationPid);
392 SharedUnlock();
393 LocalLock();
394 DosExitMustComplete(&nesting);
395
396 finish();
397 patched = FALSE;
398
399 return 0;
400}
401
402//*****************************************************************************
403//
404// kbd32Client::AddFilter()
405//
406//*****************************************************************************
407
408APIRET kbd32Client::AddFilter(vio32Filter *filter,ULONG &where){
409 if (filter == NULL) return VIO32_INVALIDPARAM;
410
411 LocalLock();
412
413 // MAKE A COPY
414 vio32Filter *f = (vio32Filter *)malloc(sizeof(vio32Filter));
415 *f = *filter;
416 f->next = NULL;
417
418 vio32Filter **list = &inputFilters;
419 // select list
420 if (where & VIO32_POST_FIRST){
421 list = &outputFilters;
422 }
423
424 // now look only at the position
425 ULONG pos = where & 0x0000FFFF;
426
427 if (((*list) == NULL)||(pos==0)) {
428 pos = 0;
429 f->next = (*list);
430 (*list) = f;
431 } else {
432 ULONG index = 1;
433 vio32Filter *q = (*list);
434 while((pos > index)&&(q->next != NULL)){
435 index++;
436 q=(vio32Filter *)q->next;
437 }
438 f->next = q->next;
439 q->next = f;
440 pos = index;
441 }
442
443 where &= 0xFFFF0000;
444 where += pos;
445
446 LocalUnlock();
447 return 0;
448}
449
450APIRET kbd32Client::_removeFilter(VOID *filterData,vio32Filter *&list){
451 BOOL found = FALSE;
452
453 if (list != NULL){
454 vio32Filter *pf = list;
455 if (list->filterData == filterData){
456 list = (vio32Filter *)list->next;
457 free(pf);
458 found = TRUE;
459 } else {
460 while ((pf->next != NULL)&&(((vio32Filter *)pf->next)->filterData != filterData)) pf = (vio32Filter *)pf->next;
461 if (pf->next != NULL){
462 vio32Filter *pf2 = (vio32Filter *)pf->next;
463 pf->next = pf2->next;
464 free(pf2);
465 found = TRUE;
466 }
467 }
468 }
469
470 if (!found) return VIO32_NOTFOUND;
471 return 0;
472}
473
474//*****************************************************************************
475//
476// kbd32Client::RemoveFilter()
477//
478//*****************************************************************************
479
480APIRET kbd32Client::RemoveFilter(VOID *filterData){
481 if (filterData == NULL) return VIO32_INVALIDPARAM;
482
483 LocalLock();
484
485 APIRET found = _removeFilter(filterData,inputFilters);
486 if (found == VIO32_NOTFOUND)
487 found = _removeFilter(filterData,outputFilters);
488
489 LocalUnlock();
490
491 return found;
492}
493
494//*****************************************************************************
495//
496// kbd32Client::GetEvent()
497//
498//*****************************************************************************
499
500APIRET kbd32Client::GetEvent(VIO32EVENTINFO *event,ULONG *eventType,ULONG msecTimeout){
501
502 if (event == NULL) return VIO32_INVALIDPARAM;
503 if (eventType == NULL) return VIO32_INVALIDPARAM;
504
505 BOOL dataUsed = TRUE;
506 REQUESTDATA request;
507 ULONG dataSize;
508 VIO32EVENTINFO *data;
509 BYTE priority;
510 while(dataUsed == TRUE){
511 // exclusive access
512 LocalLock();
513
514 APIRET rc = DosReadQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,secondaryQSem);
515
516 if ((rc != 0)&&(rc != ERROR_QUE_EMPTY)){
517 LocalUnlock();
518 return rc | VIO32_READQUEUE;
519 }
520
521 if (rc == ERROR_QUE_EMPTY){
522 LocalUnlock();
523 rc= DosWaitEventSem(secondaryQSem,msecTimeout);
524 if (rc == ERROR_TIMEOUT) return rc;
525 if (rc != 0) return rc | VIO32_WAITHEV;
526
527 LocalLock();
528 rc = DosReadQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,secondaryQSem);
529 if (rc != 0){
530 LocalUnlock();
531 return rc | VIO32_READQUEUE;
532 }
533 }
534
535 // PROCESS THE DATA here!
536 vio32Filter *f = outputFilters;
537 dataUsed = FALSE;
538 while ((f != NULL)&&(!dataUsed)){
539//FISA
540//printf("output processing using %s\n",f->filterData);
541 dataUsed = f->filter(&request.ulData,data,f->filterData);
542 f = (vio32Filter *)f->next;
543 }
544
545 // if we are about to exit copy data
546 if (!dataUsed){
547 *eventType = request.ulData;
548 *event = *data;
549 }
550
551 LocalUnlock();
552 }
553
554 return 0;
555}
556
557//*****************************************************************************
558//
559// kbd32Client::PeekEvent()
560//
561//*****************************************************************************
562
563APIRET kbd32Client::PeekEvent(VIO32EVENTINFO *event,ULONG *eventType,ULONG position){
564
565 if (event == NULL) return VIO32_INVALIDPARAM;
566 if (eventType == NULL) return VIO32_INVALIDPARAM;
567
568 REQUESTDATA request;
569 ULONG dataSize;
570 VIO32EVENTINFO *data;
571 BYTE priority;
572 // exclusive access
573 LocalLock();
574
575 ULONG pos = 0;
576 // start from the top
577 APIRET rc = DosPeekQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,&pos,DCWW_NOWAIT, &priority,0);
578
579 // move on if necessary
580 while((rc==0)&&(pos != position)){
581 pos = 1;
582 rc = DosPeekQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,&pos,DCWW_NOWAIT, &priority,0);
583 }
584
585 if (rc != 0){
586 LocalUnlock();
587 return rc | VIO32_READQUEUE;
588 }
589
590 *eventType = request.ulData;
591 *event = *data;
592 LocalUnlock();
593
594 return 0;
595}
596
597//*****************************************************************************
598//
599// kbd32Client::FlushEventQ()
600//
601//*****************************************************************************
602
603APIRET kbd32Client::FlushEventQ(){
604
605 REQUESTDATA request;
606 ULONG dataSize;
607 VIO32EVENTINFO *data;
608 BYTE priority;
609 // exclusive access
610 LocalLock();
611
612 ULONG pos = 0;
613 // start from the top
614 APIRET rc = DosReadQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,0);
615 // move on if necessary
616 while(rc==0) rc = DosReadQueue(secondaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,0);
617
618 LocalUnlock();
619
620 return 0;
621}
622
623//*****************************************************************************
624//
625// kbd32Client::GetEventQSize()
626//
627//*****************************************************************************
628
629APIRET kbd32Client::GetEventQSize(ULONG *size,ULONG msecTimeout){
630
631 if (size == NULL) return VIO32_INVALIDPARAM;
632
633 // exclusive access
634 LocalLock();
635
636 APIRET rc = DosQueryQueue(secondaryQ,size);
637
638 LocalUnlock();
639
640 return rc;
641}
642
643//*****************************************************************************
644//
645// kbd32Client::GetKeyStroke()
646//
647//*****************************************************************************
648
649APIRET kbd32Client::GetKeyStroke(KBD32KEYINFO *key,ULONG msecTimeout){
650
651 if (key == NULL) return VIO32_INVALIDPARAM;
652
653 VIO32EVENTINFO event;
654 ULONG eventType;
655 APIRET ret;
656
657 // flush all events until a key event is reached
658 while(1){
659 ret = GetEvent(&event,&eventType,0);
660 // no more events in Q, wait for next event
661 if (ret == ERROR_TIMEOUT) {
662 ret = GetEvent(&event,&eventType,msecTimeout);
663 if (ret != 0 ) return ret;
664 // not a key event, must abort otw I will loop forever
665 if (eventType != KBD32_CHAR) return VIO32_WRONGEVENTTYPE;
666 // success!
667 *key = event.vio32Kbd;
668 return 0;
669 }
670 // some error, not a timeout
671 if (ret != 0 ) return ret;
672 if (eventType == KBD32_CHAR){
673 *key = event.vio32Kbd;
674 return 0;
675 }
676 }
677
678 // will never each this code
679 return 0;
680}
681
682//*****************************************************************************
683//
684// kbd32Client::GetMouse()
685//
686//*****************************************************************************
687
688APIRET kbd32Client::GetMouse(VIO32MOUINFO *mou,ULONG msecTimeout){
689
690 if (mou == NULL) return VIO32_INVALIDPARAM;
691
692 VIO32EVENTINFO event;
693 ULONG eventType;
694 APIRET ret;
695
696 // flush all events until a key event is reached
697 while(1){
698 ret = GetEvent(&event,&eventType,0);
699 // no more events in Q, wait for next event
700 if (ret == ERROR_TIMEOUT) {
701 ret = GetEvent(&event,&eventType,msecTimeout);
702 if (ret != 0 ) return ret;
703 // not a key event, must abort otw I will loop forever
704 if (eventType != VIO32_MOU) return VIO32_WRONGEVENTTYPE;
705 // success!
706 *mou = event.vio32Mou;
707 return 0;
708 }
709 // some error, not a timeout
710 if (ret != 0 ) return ret;
711 if (eventType == VIO32_MOU){
712 *mou = event.vio32Mou;
713 return 0;
714 }
715 }
716
717 // will never each this code
718 return 0;
719}
720
721//*****************************************************************************
722//
723// kbd32Client::WriteEvent()
724//
725//*****************************************************************************
726
727APIRET kbd32Client::WriteEvent(VIO32EVENTINFO *event, ULONG *eventType){
728
729 if (event == NULL) return VIO32_INVALIDPARAM;
730 if (eventType == NULL) return VIO32_INVALIDPARAM;
731
732 ULONG nesting;
733 DosEnterMustComplete(&nesting);
734 SharedLock();
735
736 HWND hwndClient;
737 HWND hwndFrame;
738 int index;
739 APIRET ret = 0;
740 if (SharedData->searchByPid(applicationPid,hwndClient,hwndFrame,index)){
741
742 // now check how many entries are busy
743 ULONG entries = 0;
744 ret = DosQueryQueue(primaryQ, &entries);
745
746 // if too many are used bleep
747 if ((ret == 0) && (entries >= MAX_PRIMARY_Q_LEN)){
748 ret = VIO32_QUEUEFULL;
749 DosBeep(1000,20);
750 }
751 // if all is good send data
752 if (ret == 0){
753 // allocate a Q object.
754 VIO32EVENTINFO *ev = SharedData->getBuffer(index);
755 *ev = *event;
756 // send the data
757 ret = DosWriteQueue(primaryQ,*eventType,sizeof(VIO32EVENTINFO),ev,0);
758 if (ret != 0) ret |= VIO32_WRITEQUEUE;
759 }
760 // now mark the buffer as used
761 if (ret == 0){
762 SharedData->advanceBuffer(index);
763 }
764 } else ret = VIO32_UNREGISTERED;
765
766 SharedUnlock();
767 DosExitMustComplete(&nesting);
768
769 return ret;
770};
771
772//*****************************************************************************
773//
774// kbd32Client::kbdThread()
775//
776//*****************************************************************************
777
778APIRET kbd32Client::GetKeyStatus(VIO32STATUSINFO *status){
779 if (status == NULL) return VIO32_INVALIDPARAM;
780 APIRET ret = 0;
781 VIO32EVENTINFO event;
782 ULONG eventType;
783 while(ret == 0) ret = GetEvent(&event,&eventType,0);
784 if (ret == ERROR_TIMEOUT) ret = 0;
785 LocalLock();
786 *status = keyStatus;
787 LocalUnlock();
788 return ret;
789}
790
791//*****************************************************************************
792//
793// kbd32Client::kbdThread()
794//
795//*****************************************************************************
796
797VOID kbd32Client::kbdThread(){
798 DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,10,0);
799
800 // finish together with the kbd monitor
801 while(threadsMustContinue){
802 KBDKEYINFO charData;
803 APIRET ret = KbdCharIn(&charData,0,0);
804 if (!threadsMustContinue) break;
805 if (ret != 0) return;
806 if (ret == 0){
807 ULONG nesting;
808 DosEnterMustComplete(&nesting);
809 SharedLock();
810
811 HWND hwndClient;
812 HWND hwndFrame;
813 int index;
814 if (SharedData->searchByPid(applicationPid,hwndClient,hwndFrame,index)){
815
816 // now check how many entries are busy
817 ULONG entries = 0;
818 ret = DosQueryQueue(primaryQ, &entries);
819
820 // if too many are used bleep
821 if ((ret == 0) && (entries >= MAX_PRIMARY_Q_LEN)){
822 ret = 1;
823 DosBeep(1000,20);
824 }
825 // if all is good send data
826 if (ret == 0){
827 // allocate a Q object.
828 VIO32EVENTINFO *key = SharedData->getBuffer(index);
829 key->vioKbd = charData;
830 // send the data
831 ret = DosWriteQueue(primaryQ,VIO_CHAR,sizeof(VIO32EVENTINFO),key,0);
832 }
833 // now mark the buffer as used
834 if (ret == 0){
835 SharedData->advanceBuffer(index);
836 }
837 }
838
839 SharedUnlock();
840 DosExitMustComplete(&nesting);
841 }
842 }
843}
844
845//*****************************************************************************
846//
847// kbd32Client::mouThread()
848//
849//*****************************************************************************
850
851VOID kbd32Client::mouThread(){
852 DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,10,0);
853
854 MOUEVENTINFO newMouEvent;
855 MOUEVENTINFO outStandingMouEvent;
856 BOOL hasOutStanding = FALSE;
857 USHORT wait = 1;
858 USHORT noWait = 0;
859 // finish together with the kbd monitor
860 while(threadsMustContinue){
861 APIRET ret = 0;
862 // check if there is a pending mouse event
863 if (hasOutStanding == FALSE){
864 // if not read a new and wait if it is not available
865 ret = MouReadEventQue(&newMouEvent,&wait,mou);
866 if (!threadsMustContinue) break;
867 } else {
868 // if an event was waiting use it as a new event
869 newMouEvent = outStandingMouEvent;
870 }
871 hasOutStanding = FALSE;
872 // now collapse all movements into a single event
873 if (ret == 0){
874 // stop on error or if a different event was encountered and stored
875 while((ret == 0) && (hasOutStanding == FALSE)){
876 // empty the Q
877 ret = MouReadEventQue(&outStandingMouEvent,&noWait,mou);
878 // an empty event does not produce error, so I generate one myself
879 if (outStandingMouEvent.time == 0) ret = 1;
880 if (ret == 0){
881//printf("@%i %i %i %i\n",newMouEvent.time,newMouEvent.fs,newMouEvent.col,newMouEvent.row);
882//printf("@%i %i %i %i\n",outStandingMouEvent.time,outStandingMouEvent.fs,outStandingMouEvent.col,outStandingMouEvent.row);
883 // bug fix for VIO window and spurius mouse move messages
884 if (((outStandingMouEvent.fs & 0x1)!= 0) &&
885 (newMouEvent.col == outStandingMouEvent.col) &&
886 (newMouEvent.row == outStandingMouEvent.row)) outStandingMouEvent.fs -= 0x1;
887//printf("@%i %i %i %i\n",outStandingMouEvent.time,outStandingMouEvent.fs,outStandingMouEvent.col,outStandingMouEvent.row);
888
889 // if the status is different remember the event for later
890 if (outStandingMouEvent.fs != newMouEvent.fs) hasOutStanding = TRUE;
891 // just keep the last event
892 else newMouEvent = outStandingMouEvent;
893 }
894 }
895 ret = 0;
896 }
897
898
899 // now Q the new event
900 if (ret == 0){
901 ULONG nesting;
902 DosEnterMustComplete(&nesting);
903 SharedLock();
904
905 HWND hwndClient;
906 HWND hwndFrame;
907 int index;
908 if (SharedData->searchByPid(applicationPid,hwndClient,hwndFrame,index)){
909
910 // get mode of operation of given app
911 ULONG mode = SharedData->getMode(index);
912
913//printf("@%i %i %i %i\n",newMouEvent.time,newMouEvent.fs,newMouEvent.col,newMouEvent.row);
914 // see whether to filter out messages
915 static ULONG lastMouseStatus = 0;
916 if ((mode & KBD32MODE_ENABLEMOUSE)==0) ret = 1;
917 ULONG newMouseStatus = (newMouEvent.fs & 0x54) | ((newMouEvent.fs & 0x2A)<<1);
918 if ((mode & KBD32MODE_ENABLEMMOVE)==0){
919 newMouEvent.fs = newMouseStatus;
920 if (newMouEvent.fs == lastMouseStatus) ret = 1;
921 }
922 lastMouseStatus = newMouseStatus;
923
924 // now check how many entries are busy
925 ULONG entries = 0;
926 if (ret == 0)
927 ret = DosQueryQueue(primaryQ, &entries);
928
929 // if too many are used bleep
930 if ((ret == 0) && (entries >= MAX_PRIMARY_Q_LEN)){
931 ret = 1;
932 DosBeep(1000,20);
933 }
934
935 // if all is good send data
936 if (ret == 0){
937 // allocate a Q object.
938 VIO32EVENTINFO *key = SharedData->getBuffer(index);
939 key->vioMou = newMouEvent;
940 // send the data
941 ret = DosWriteQueue(primaryQ,VIO_MOU,sizeof(VIO32EVENTINFO),key,0);
942 }
943 // now mark the buffer as used
944 if (ret == 0){
945 SharedData->advanceBuffer(index);
946 }
947 }
948
949 SharedUnlock();
950 DosExitMustComplete(&nesting);
951 }
952 }
953}
954
955//*****************************************************************************
956//
957// kbd32Client::kbdMonitorThread()
958//
959//*****************************************************************************
960
961
962void kbd32Client::kbdMonitorThread(){
963 DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,10,0);
964 //
965 while(threadsMustContinue){
966 MonRecord monData;
967 USHORT bufSize = sizeof(monData);
968 APIRET ret = DosMonRead((PBYTE)&monin,DCWW_WAIT,(PBYTE)&monData,&bufSize);
969 if (!threadsMustContinue) break;
970
971 BOOL dataUsed = (ret != 0);
972 if (ret == 0){
973 ULONG nesting;
974 DosEnterMustComplete(&nesting);
975 SharedLock();
976
977 HWND hwndClient;
978 HWND hwndFrame;
979 int index;
980 if (SharedData->searchByPid(applicationPid,hwndClient,hwndFrame,index)){
981
982 // get mode of operation of given app
983 ULONG mode = SharedData->getMode(index);
984
985 // bypass certain keys
986 ULONG specialKeys = monData.KbdDDFlagWord & 0x003F;
987 if (specialKeys != 0){
988 ret = 1;
989 // pass all the CTRL/SHIFT/ALT/N-LOCK... events
990 if (specialKeys == 0x7) ret = 0;
991 if ((mode & KBD32MODE_DISABLEBREAK) && (specialKeys == 0x11)) ret = 0;
992 }
993
994 // now check how many entries are busy
995 ULONG entries = 0;
996 if (ret == 0){
997 ret = DosQueryQueue(primaryQ, &entries);
998 }
999
1000 // if too many are used bleep
1001 if ((ret == 0) && (entries >= MAX_PRIMARY_Q_LEN)){
1002 ret = 1;
1003 DosBeep(1000,20);
1004 }
1005
1006 // if all is good send data
1007 if (ret == 0){
1008 // allocate a Q object.
1009 VIO32EVENTINFO *key = SharedData->getBuffer(index);
1010 key->monKbd = monData;
1011 // send the data
1012 ret = DosWriteQueue(primaryQ,MON_CHAR,sizeof(VIO32EVENTINFO),key,0);
1013 }
1014 // now mark the buffer as used
1015 if (ret == 0){
1016 SharedData->advanceBuffer(index);
1017 dataUsed = TRUE;
1018 }
1019 }
1020 SharedUnlock();
1021 DosExitMustComplete(&nesting);
1022 }
1023 if (dataUsed == FALSE){
1024/*
1025 if ((monData.KbdDDFlagWord & 0x7) == 0x7){
1026 monData.KbdDDFlagWord &= 0xFFF8;
1027 monData.Shift_State |= 0x2000; // means special char remapped -64
1028 }
1029 if (monData.KbdDDFlagWord & 0x0040){
1030 monData.KbdDDFlagWord &= 0xFFBF;
1031 monData.Shift_State |= 0x1000; // use KBDSTF_SCROLLLOCK to say KEY-UP
1032 }
1033 CHAR scanCode = monData.MonFlagWord >> 8;
1034 monData.XlatedScan = scanCode;
1035printf(">>%c %i 0x%x 0x%x 0x%x\n",monData.XlatedChar,monData.XlatedScan,
1036 monData.MonFlagWord,monData.Shift_State,monData.KbdDDFlagWord);
1037*/
1038 DosMonWrite((PBYTE)&monout,(PBYTE)&monData,14);
1039 }
1040 }
1041}
1042
1043//*****************************************************************************
1044//
1045// kbd32Client::dataProcessingThread()
1046//
1047//*****************************************************************************
1048
1049
1050VOID kbd32Client::dataProcessingThread(){
1051 DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,10,0);
1052
1053 // the message read
1054 VIO32EVENTINFO queuedData;
1055
1056 //
1057 while(threadsMustContinue){
1058 // exclusive access to primary Q
1059 SharedLock();
1060
1061 // READ DATA OFF the primary Q
1062 REQUESTDATA request;
1063 ULONG dataSize;
1064 VIO32EVENTINFO *data;
1065 BYTE priority;
1066 APIRET rc = DosReadQueue(primaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,primaryQSem);
1067 if (!threadsMustContinue) break;
1068 if (rc == ERROR_QUE_EMPTY){
1069 SharedUnlock();
1070 rc= DosWaitEventSem(primaryQSem,-1);
1071 SharedLock();
1072
1073 if (rc == 0)
1074 rc = DosReadQueue(primaryQ,&request,&dataSize,(PPVOID)&data,0,DCWW_NOWAIT, &priority,primaryQSem);
1075 }
1076
1077 // copy data before releasing the semaphore
1078 if (rc == 0) queuedData = *data;
1079
1080 // relinquish primary Q
1081 SharedUnlock();
1082
1083
1084 // exclusive access to secondary Q
1085 LocalLock();
1086
1087 // now check how many entries are busy
1088 ULONG entries = 0;
1089 if (rc == 0) rc = DosQueryQueue(secondaryQ, &entries);
1090
1091 // if too many are used bleep
1092 if ((rc == 0) && (entries >= MAX_SECONDARY_Q_LEN)){
1093 rc = 1;
1094 DosBeep(2000,20);
1095 }
1096
1097 // now allocate a space in the secondary Q
1098 VIO32EVENTINFO *key;
1099 if (rc == 0){
1100 // allocate a Q object.
1101 key = getBuffer();
1102 //
1103 if (key == NULL) rc = 1;
1104 }
1105
1106 // PROCESS THE DATA here!
1107 vio32Filter *f = inputFilters;
1108 BOOL dataUsed = FALSE;
1109 if (rc==0)
1110 while ((f != NULL)&&(!dataUsed)){
1111//FISA
1112//printf("INPUT processing with %s\n",f->filterData);
1113 dataUsed = f->filter(&request.ulData,&queuedData,f->filterData);
1114 f = (vio32Filter *)f->next;
1115 }
1116
1117 // if all is right and the data was not consumed send it forward
1118 if ((rc == 0) && (!dataUsed)){
1119 // copy content
1120 *key = queuedData;
1121 // send the data
1122 rc = DosWriteQueue(secondaryQ,request.ulData,sizeof(VIO32EVENTINFO),key,0);
1123
1124 // now mark the buffer as used
1125 if (rc == 0) advanceBuffer();
1126 }
1127
1128 // free secondary system
1129 LocalUnlock();
1130
1131 if ((rc != 0) && (rc != ERROR_TIMEOUT)) return;
1132 }
1133}
1134
1135
Note: See TracBrowser for help on using the repository browser.