|
|
1.1 root 1: // SBBSEXEC.cpp - SBBSEXEC.VXD main module
2:
3: /* Synchronet Windows 9X FOSSIL driver (requires VtoolsD C++ framework) */
4:
1.1.1.2 ! root 5: /* $Id: sbbsexec.cpp,v 1.2 2001/05/02 01:58:31 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38:
39: #define DEVICE_MAIN
40: #include "sbbsexec.h"
41: #include "debugout.h"
42: #include "..\ringbuf.h"
43:
44: #define RINGBUF_SIZE_IN 10000
45: #define RINGBUF_SIZE_OUT 10000
46:
47: #undef DEVICENAME
48: #define DEVICENAME "SBBSEXEC" // For debug output
49:
50: #include LOCKED_CODE_SEGMENT
51: #include LOCKED_DATA_SEGMENT
52:
53: #define MAX_VM 250
54:
55: typedef struct {
56: VMHANDLE handle;
57: SEMHANDLE input_sem;
58: SEMHANDLE output_sem;
59: DWORD mode;
60: BOOL online;
61: BOOL overrun;
62: RingBuf in;
63: RingBuf out;
64: } vm_t;
65:
66: vm_t vm[MAX_VM];
67:
68: Declare_Virtual_Device(SBBSExec)
69:
70: //////////////////////////////////////////////////////////////////////////
71: #include LOCKED_CODE_SEGMENT
72: #include LOCKED_DATA_SEGMENT
73:
74: vm_t* new_vm;
75: sbbsexec_start_t start;
76:
77: vm_t* find_vm(VMHANDLE hVM)
78: {
79: int i;
80:
81: for(i=0;i<MAX_VM;i++)
82: if(vm[i].handle==hVM)
83: return(&vm[i]);
84: #if 0
85: if(hVM!=Get_Sys_VM_Handle()) {
86: DBTRACEx(0,"!VM NOT FOUND",hVM);
87: }
88: #endif
89: return(NULL);
90: }
91:
92: BOOL SBBSExec::OnSysDynamicDeviceInit()
93: {
94: DBTRACE(0,"OnSysDynamicDeviceInit");
95:
96: return(OnDeviceInit(NULL,NULL));
97: }
98:
99:
100: BOOL SBBSExec::OnDeviceInit(VMHANDLE hSysVM, PCHAR pszCmdTail)
101: {
102: DBTRACE(0,"SBBSExec::OnDeviceInit");
103:
104: pInt10 = NULL; // BIOS I/O
105: pInt14 = NULL; // FOSSIL
106: pInt16 = NULL; // Keyboard input
107: pInt21 = NULL; // DOS I/O
108: pInt29 = NULL; // Direct console I/O (PKZIP/UNZIP)
109:
110: memset(&start,0,sizeof(start));
111: #if 1
112:
113:
114: if ( (pInt21 = new SBBSExecInt21()) == NULL) {
115: DBTRACE(0,"!Failed to create int 21 handler");
116: UnhookInts();
117: return(FALSE);
118: }
119:
120: if ( !pInt21->hook()) {
121: DBTRACE(0,"!Failed to hook int 21");
122: UnhookInts();
123: return(FALSE);
124: }
125:
126: if ( (pInt29 = new SBBSExecInt29()) == NULL) {
127: DBTRACE(0,"!Failed to create int 29 handler");
128: UnhookInts();
129: return(FALSE);
130: }
131:
132: if ( !pInt29->hook()) {
133: DBTRACE(0,"!Failed to hook int 29");
134: UnhookInts();
135: return(FALSE);
136: }
137:
138: if ( (pInt16 = new SBBSExecInt16()) == NULL) {
139: DBTRACE(0,"!Failed to create int 16 handler");
140: UnhookInts();
141: return(FALSE);
142: }
143:
144: if ( !pInt16->hook()) {
145: DBTRACE(0,"!Failed to hook int 16");
146: UnhookInts();
147: return(FALSE);
148: }
149:
150: if ( (pInt14 = new SBBSExecInt14()) == NULL) {
151: DBTRACE(0,"!Failed to create int 14 handler");
152: UnhookInts();
153: return(FALSE);
154: }
155:
156: if ( !pInt14->hook()) {
157: DBTRACE(0,"!Failed to hook int 14");
158: UnhookInts();
159: return(FALSE);
160: }
161:
162: if ( (pInt10 = new SBBSExecInt10()) == NULL) {
163: DBTRACE(0,"!Failed to create int 10 handler");
164: UnhookInts();
165: return(FALSE);
166: }
167:
168: if ( !pInt10->hook()) {
169: DBTRACE(0,"!Failed to hook int 10");
170: UnhookInts();
171: return(FALSE);
172: }
173:
174: #endif
175:
176: return TRUE;
177: }
178:
179: //****************************************************************************
180: //****************************************************************************
181: VOID SBBSExec::OnSystemExit(VMHANDLE hSysVM)
182: {
183: DBTRACE(0,"OnSystemExit");
184: OnSysDynamicDeviceExit();
185: }
186:
187: void SBBSExec::UnhookInts()
188: {
189:
190: if(pInt10!=NULL) {
191: pInt10->unhook();
192: delete pInt10;
193: pInt10=NULL;
194: }
195:
196: if(pInt14!=NULL) {
197: pInt14->unhook();
198: delete pInt14;
199: pInt14=NULL;
200: }
201:
202: if(pInt16!=NULL) {
203: pInt16->unhook();
204: delete pInt16;
205: pInt16=NULL;
206: }
207:
208: if(pInt21!=NULL) {
209: pInt21->unhook();
210: delete pInt21;
211: pInt21=NULL;
212: }
213:
214: if(pInt29!=NULL) {
215: pInt29->unhook();
216: delete pInt29;
217: pInt29=NULL;
218: }
219: }
220:
221: //****************************************************************************
222: // Handle control message SYS_DYNAMIC_DEVICE_EXIT
223: //****************************************************************************
224: BOOL SBBSExec::OnSysDynamicDeviceExit()
225: {
226: DBTRACE(0,"OnSysDynamicDeviceExit");
227:
228: UnhookInts();
229:
230: return(TRUE);
231: }
232:
233: //////////////////////////////////////////////////////////////////////////
234: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235: BOOL SBBSExec::OnCreateVM(VMHANDLE hVM)
236: {
237: DBTRACExd(0,"CreateVM, handle, time",hVM,Get_System_Time());
1.1.1.2 ! root 238: DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle());
1.1 root 239:
240: if(start.event) {
241: new_vm=find_vm(NULL);
242: if(new_vm==NULL) {
243: DBTRACE(0,"!NO AVAILABLE VM structures");
244: return(FALSE);
245: }
246: new_vm->handle=hVM;
247: new_vm->mode=start.mode;
248: new_vm->online = true;
249: new_vm->overrun = false;
250: new_vm->input_sem = NULL;
251: new_vm->output_sem = NULL;
252:
253: if(RingBufInit(&new_vm->in, RINGBUF_SIZE_IN)!=0
254: || RingBufInit(&new_vm->out, RINGBUF_SIZE_OUT)!=0) {
255: DBTRACE(0,"!FAILED to create I/O buffers");
256: return(FALSE);
257: }
258: if(!VWIN32_SetWin32Event(start.event)) {
259: DBTRACEx(0,"!FAILED TO SET EVENT handle", start.event);
260: return(FALSE);
261: }
262: if(!VWIN32_CloseVxDHandle(start.event)) {
263: DBTRACEx(0,"!FAILED TO CLOSE EVENT handle", start.event);
264: return(FALSE);
265: }
266: start.event=0;
267: }
268: return(TRUE);
269: }
270:
271:
272: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
273: SBBSExecInt29::SBBSExecInt29() : VPreChainV86Int(0x29)
274: {
275: DBTRACE(0,"SBBSExecInt29 constructor");
276: }
277:
278: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
279: BOOL SBBSExecInt29::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
280: {
281: vm_t* vm = find_vm(hVM);
282:
283: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
284: return(FALSE); // Tells VMM that interrupt was not handled
285: }
286:
287: if(!RingBufFree(&vm->out)) {
288: DBTRACEx(0,"!Int29 OUTPUT BUFFER OVERFLOW, hVM", hVM);
289: vm->overrun=true;
290: return(FALSE);
291: }
292: DBTRACEx(1,"Int29 OUTPUT", _clientAL);
293:
294: BYTE ch=_clientAL;
295: RingBufWrite(&vm->out,&ch,1);
296: vm->overrun=false;
297:
298: return(FALSE);
299: }
300:
301:
302: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
303: SBBSExecInt21::SBBSExecInt21() : VPreChainV86Int(0x21)
304: {
305: DBTRACE(0,"SBBSExecInt21 constructor");
306: }
307:
308: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309: BOOL SBBSExecInt21::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
310: {
311: BYTE ch;
312: BYTE* buffer;
313: WORD buflen;
314: vm_t* vm = find_vm(hVM);
315:
316: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
317: #if 0
318: if(vm && !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
319: DBTRACEx(0,"Int21 on unsupported VM", hVM);
320: }
321: #endif
322: return(FALSE); // Tells VMM that interrupt was not handled
323: }
324: DBTRACEx(1,"Int21 function", _clientAH);
325:
326: DWORD avail = RingBufFree(&vm->out);
327:
328: switch(_clientAH) {
329: case 0x01:
330: DBTRACE(0,"!Int21 Char input WITH echo");
331: break;
332: case 0x06: // Direct console I/O
333: DBTRACEx(0,"DOS DIRECT CONSOLE IO, DL", _clientDL);
334: if(_clientDL==0xff) {
335: avail=RingBufFull(&vm->in);
336: if(avail) {
337: DBTRACEd(0,"avail",avail);
338: RingBufRead(&vm->in, &ch, 1);
339: _clientFlags&=~(1<<6); // clear zero flag
340: _clientAX=ch;
341: return(TRUE);
342: }
343: break;
344: }
345: // fall-through
346: case 0x02: // Character output
347: DBTRACEx(1,"Int21 function", _clientAH);
348: if(!avail) {
349: DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
350: vm->overrun=true;
351: break;
352: }
353: ch=_clientDL;
354: RingBufWrite(&vm->out,&ch,1);
355: vm->overrun=false;
356: break;
357: case 0x09: // Display string
358: DBTRACE(0,"!Int21 func 09 - DISPLAY STRING");
359: break;
360: case 0x0A: // Buffered keyboard input
361: DBTRACE(0,"Int21 Func 0A - Buffered Keyboard Input");
362: /* Need to get a string from the user, echo, and copy to DS:DX */
363: /* byte 0 = max length, byte 1 = actual read (minus CR) */
364: break;
365: case 0x40: // Write file or device
366: if(_clientBX!=1 && _clientBX!=2) { // !stdout and !stderr
367: DBTRACEd(1,"!Int21 write to unsupported device", _clientBX);
368: break;
369: }
370: DBTRACEdd(1,"Int21 write file", _clientBX, _clientCX);
371: buffer = (BYTE*)MAPFLAT(CRS.Client_DS, CWRS.Client_DX);
372: buflen = _clientCX;
373: if(avail<buflen) {
374: DBTRACEd(0,"!OUTPUT BUFFER OVERFLOW, avail", avail);
375: vm->overrun=true;
376: if(!avail)
377: break;
378: buflen=avail;
379: }
380: RingBufWrite(&vm->out,buffer,buflen);
381: vm->overrun=false;
382: break;
383: }
384:
385: return(FALSE); // Tells VMM that interrupt was not handled
386: }
387:
388: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
389: SBBSExecInt16::SBBSExecInt16() : VPreChainV86Int(0x16)
390: {
391: DBTRACE(0,"SBBSExecInt16 constructor");
392: }
393:
394: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
395: BOOL SBBSExecInt16::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
396: {
397: BYTE ch;
398: DWORD avail;
399: vm_t* vm = find_vm(hVM);
400:
401: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_IN)) {
402: return(FALSE); // Tells VMM that interrupt was not handled
403: }
404:
405: // DBTRACExx(0,"Int16 (hVM, AX)", hVM, _clientAX);
406:
407: avail=RingBufFull(&vm->in);
408: switch(_clientAH) {
409: case 0x00: // Read char from keyboard
410: case 0x10: // Read char from enhanced keyboard
411: if(avail) {
412: RingBufRead(&vm->in, &ch, 1);
413: _clientAX=ch;
414: return(TRUE);
415: }
416: break;
417: case 0x01: // Get keyboard status
418: case 0x11: // Get enhanced keyboard status
419: if(avail) {
420: RingBufPeek(&vm->in, &ch, 1);
421: _clientFlags&=~(1<<6); // clear zero flag
422: _clientAX=ch;
423: return(TRUE);
424: }
425: break;
426: default:
427: DBTRACEx(0,"!UNHANDLED INT16 function", _clientAH);
428: break;
429: }
430:
431: return(FALSE);
432: }
433:
434: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
435: SBBSExecInt14::SBBSExecInt14() : VPreChainV86Int(0x14)
436: {
437: DBTRACE(0,"SBBSExecInt14 constructor");
438: }
439:
440: WORD PortStatus(vm_t* vm)
441: {
442: WORD status=0x0008; // AL bit 3 (change in DCD) always set
443:
444: if(vm->online) // carrier detect
445: status|=0x0080; // DCD
446:
447: if(RingBufFull(&vm->in)) // receive data ready
448: status|=0x0100; // RDA
449:
450: if(vm->overrun) // overrun error detected
451: status|=0x0200; // OVRN
452:
453: if(RingBufFree(&vm->out)> // room available in output buffer
454: RINGBUF_SIZE_OUT/2)
455: status|=0x2000; // THRE
456:
457: if(!RingBufFull(&vm->out)) // output buffer is empty
458: status|=0x4000; // TSRE
459:
460: return(status);
461: }
462: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
463: const char* fossil_id="Synchronet SBBSEXEC.VXD Fossil";
464: BOOL SBBSExecInt14::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
465: {
466: BYTE* buffer;
467: BYTE ch;
468: WORD buflen;
469: WORD rd,wr;
470: WORD avail;
471: vm_t* vm = find_vm(hVM);
472:
473: if(vm==NULL || vm->mode!=SBBSEXEC_MODE_FOSSIL) {
474: return(FALSE); // Tells VMM that interrupt was not handled
475: }
476:
477:
478: DBTRACEx(4,"Int14 func",_clientAH);
479:
480: switch(_clientAH) {
481: case 0x00: /* Initialize/Set baud rate */
482: DBTRACE(0,"Int14 init");
483: _clientAX=PortStatus(vm);
484: break;
485: case 0x01: /* write char to com port */
486: if(RingBufFree(&vm->out)<2) {
487: DBTRACEx(1,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
488: vm->output_sem=Create_Semaphore(0);
489: Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
490: Destroy_Semaphore(vm->output_sem);
491: vm->output_sem=NULL;
492: if(!vm->online) {
493: DBTRACE(0,"!USER HUNG UP");
494: return(true);
495: }
496: }
497: ch=_clientAL;
498: RingBufWrite(&vm->out,&ch,1);
499: #if 0 /* Now done in SBBS.DLL/XTRN.CPP */
500: if(ch==0xff) { /* escape TELNET IAC */
501: RingBufWrite(&vm->out,&ch,1);
502: DBTRACE(1,"Escaped IAC in output stream");
503: }
504: #endif
505: vm->overrun=false;
506: _clientAX=PortStatus(vm);
507: break;
508: case 0x02: /* read char from com port */
509: if(!RingBufFull(&vm->in)) {
510: DBTRACEx(0,"Waiting on input semaphore, hVM", hVM);
511: vm->input_sem=Create_Semaphore(0);
512: Wait_Semaphore(vm->input_sem,BLOCK_THREAD_IDLE);
513: Destroy_Semaphore(vm->input_sem);
514: vm->input_sem=NULL;
515: #if 0
516: _clientAH=0x80; /* timed-out */
517: return(TRUE);
518: #endif
519: }
520: RingBufRead(&vm->in,&ch,1);
521: _clientAH=0;
522: _clientAL=ch;
523: break;
524: case 0x03: /* request status */
525: _clientAX=PortStatus(vm);
526: break;
527: case 0x04: /* initialize */
528: DBTRACE(0,"Int14 func 4 init");
529: _clientAX=0x1954; /* magic number = success */
530: _clientBH=5; /* FOSSIL rev */
531: _clientBL=0x1B; /* maximum FOSSIL func supported */
532: break;
533: case 0x08: // flush output buffer
534: DBTRACE(0,"Int14 FLUSH OUTPUT BUFFER");
535: vm->output_sem=Create_Semaphore(0);
536: Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
537: Destroy_Semaphore(vm->output_sem);
538: vm->output_sem=NULL;
539: break;
540: case 0x09: // purge output buffer
541: DBTRACE(0,"Int14 PURGE OUTPUT BUFFER");
542: RingBufReInit(&vm->out);
543: break;
544: case 0x0A: // purge input buffer
545: DBTRACE(0,"Int14 PURGE INPUT BUFFER");
546: RingBufReInit(&vm->in);
547: break;
548: case 0x0B: /* write char to com port, no wait */
549: if(RingBufFree(&vm->out)<2) {
550: _clientAX=0; // char was not accepted
551: break;
552: }
553: ch=_clientAL;
554: RingBufWrite(&vm->out,&ch,1);
555: #if 0 /* Now done in SBBS.DLL/XTRN.CPP */
556: if(ch==0xff) { /* escape TELNET IAC */
557: RingBufWrite(&vm->out,&ch,1);
558: DBTRACE(1,"Escaped IAC in output stream");
559: }
560: #endif
561: _clientAX=1; // char was accepted
562: break;
563: case 0x0C: // non-destructive read-ahead
564: if(!RingBufFull(&vm->in)) {
565: _clientAX=0xffff; // no char available
566: break;
567: }
568: RingBufPeek(&vm->in,&ch,1);
569: _clientAH=0;
570: _clientAL=ch;
571: break;
572: case 0x13: /* write to display */
573: dprintf("%c",_clientAL);
574: break;
575: case 0x18: /* read bock */
576: rd=_clientCX;
577: avail=RingBufFull(&vm->in);
578: if(rd>avail)
579: rd=avail;
580: if(rd) {
581: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
582: rd = RingBufRead(&vm->in, buffer, rd);
583: }
584: _clientAX = rd;
585: break;
586: case 0x19: /* write block */
587: wr=_clientCX;
588: avail=RingBufFree(&vm->out);
589: if(wr>avail)
590: wr=avail;
591: if(wr) {
592: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
593: wr = RingBufWrite(&vm->out, buffer, wr);
594: }
595: _clientAX = wr;
596: break;
597: #if 1
598: case 0x1B: // driver info
599: {
600: DBTRACE(1,"Int14 driver info");
601: struct {
602: WORD info_size;
603: BYTE curr_fossil;
604: BYTE curr_rev;
605: DWORD id_string;
606: WORD inbuf_size;
607: WORD inbuf_free;
608: WORD outbuf_size;
609: WORD outbuf_free;
610: BYTE screen_width;
611: BYTE screen_height;
612: BYTE baud_rate;
613: } info={ sizeof(info), 5, 1, 0
614: ,RINGBUF_SIZE_IN-1, RingBufFree(&vm->in)
615: ,RINGBUF_SIZE_OUT-1, RingBufFree(&vm->out)
616: ,80,25
617: ,1 // 38400
618: };
619: // Map_Lin_To_VM_Addr
620: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
621: wr=sizeof(info);
622: if(wr>_clientCX)
623: wr=_clientCX;
624: memcpy(buffer, &info, wr);
625: _clientAX=wr;
626: break;
627: }
628: #endif
629: default:
630: DBTRACEx(0,"!UNHANDLED INTERRUPT 14h function",_clientAH);
631: break;
632: }
633: return(TRUE); // Tells VMM that interrupt was handled
634: }
635:
636: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
637: SBBSExecInt10::SBBSExecInt10() : VPreChainV86Int(0x10)
638: {
639: DBTRACE(0,"SBBSExecInt10 constructor");
640: }
641:
642: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
643: BOOL SBBSExecInt10::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
644: {
645: BYTE ch;
646: DWORD avail;
647: vm_t* vm = find_vm(hVM);
648:
649: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
650: return(FALSE); // Tells VMM that interrupt was not handled
651: }
652:
653: avail=RingBufFree(&vm->out);
654:
655: switch(_clientAH) {
656: case 0x02: // Set Cursor Position
657: DBTRACE(1,"Int10 func 2 - Set cursor position");
658: break;
659: case 0x09: // Write char and attr at cursor
660: DBTRACE(1,"Int10 func 9 - Write char and attr at curosr");
661: case 0x10: // Write char at cursor
662: #if 0
663: DBTRACE(1,"Int10 func 9 - Write char at curosr");
664: if(!avail) {
665: DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
666: vm->overrun=true;
667: break;
668: }
669: ch=_clientAL;
670: RingBufWrite(&vm->out,&ch,1);
671: vm->overrun=false;
672:
673: #endif
674: break;
675: }
676:
677: return(FALSE);
678: }
679:
680:
681:
682: DWORD SBBSExec::OnW32DeviceIoControl(PIOCTLPARAMS pIOCTL)
683: {
684: DWORD rd;
685: DWORD wr;
686: DWORD avail;
687: vm_t* vm;
688:
689: // DBTRACEd(0,"SBBSEXEC ioctl"
690: //,pIOCTL->dioc_IOCtlCode);
691:
692: switch(pIOCTL->dioc_IOCtlCode) {
693: case DIOC_OPEN:
694: DBTRACEd(0,"IOCTL: OPEN",Get_System_Time());
695: break;
696:
697: case DIOC_CLOSEHANDLE:
698: DBTRACEd(0,"IOCTL: CLOSE",Get_System_Time());
699: break;
700:
701: case SBBSEXEC_IOCTL_START:
702: DBTRACEd(0,"IOCTL: START",Get_System_Time());
1.1.1.2 ! root 703: DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle());
1.1 root 704: if(start.event) {
705: DBTRACE(0,"Exec already started!");
706: return(SBBSEXEC_ERROR_INUSE);
707: }
708: if (pIOCTL->dioc_InBuf==NULL
709: || pIOCTL->dioc_cbInBuf!=sizeof(start)) {
710: return(SBBSEXEC_ERROR_INBUF);
711: }
712: start=*(sbbsexec_start_t*)pIOCTL->dioc_InBuf;
713: break;
714:
715: case SBBSEXEC_IOCTL_COMPLETE:
716: DBTRACEd(0,"IOCTL: COMPLETE",Get_System_Time());
717: if(start.event || new_vm==NULL) {
718: DBTRACE(0,"!VM never created");
719: start.event=0;
720: return(SBBSEXEC_ERROR_INUSE);
721: }
722: if(pIOCTL->dioc_OutBuf==NULL
723: || pIOCTL->dioc_cbOutBuf<sizeof(VMHANDLE)) {
724: DBTRACE(0,"!Invalid OUTBUF");
725: return(SBBSEXEC_ERROR_OUTBUF);
726: }
727: *(VMHANDLE*)pIOCTL->dioc_OutBuf=new_vm->handle;
728: DBTRACEx(0,"CREATED VM HANDLE", new_vm->handle);
729: new_vm=NULL;
730:
731: if(pIOCTL->dioc_bytesret!=NULL)
732: *pIOCTL->dioc_bytesret = sizeof(VMHANDLE);
733: break;
734: case SBBSEXEC_IOCTL_READ:
735:
736: if (pIOCTL->dioc_InBuf==NULL
737: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
738: DBTRACE(0,"!INVALID INBUF");
739: return(SBBSEXEC_ERROR_INBUF);
740: }
741:
742: if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf==0) {
743: DBTRACE(0,"!INVALID OUTBUF");
744: return(SBBSEXEC_ERROR_OUTBUF);
745: }
746:
747: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
748: if(vm==NULL) {
749: DBTRACE(0,"!NO VM LIST");
750: return(SBBSEXEC_ERROR_INDATA);
751: }
752:
753: rd = RingBufFull(&vm->out);
754:
755: if(rd>pIOCTL->dioc_cbOutBuf) {
756: DBTRACEdd(0,"Reducing read size"
757: ,rd, pIOCTL->dioc_cbOutBuf);
758: rd=pIOCTL->dioc_cbOutBuf;
759: }
760:
761: RingBufRead(&vm->out, (BYTE*)pIOCTL->dioc_OutBuf, rd);
762:
763: if(pIOCTL->dioc_bytesret!=NULL)
764: *pIOCTL->dioc_bytesret = rd;
765:
766: if(vm->output_sem!=NULL) // Wake up int14 handler
767: Signal_Semaphore(vm->output_sem);
768:
769: if(rd>1) {
770: DBTRACEd(1,"IOCTL_READ bytes", rd);
771: }
772: break;
773:
774: case SBBSEXEC_IOCTL_WRITE:
775:
776: if (pIOCTL->dioc_InBuf==NULL
777: || pIOCTL->dioc_cbInBuf<sizeof(VMHANDLE)+1) {
778: DBTRACE(0,"!INVALID INBUF");
779: return(SBBSEXEC_ERROR_INBUF);
780: }
781:
782: if (pIOCTL->dioc_OutBuf==NULL
783: || pIOCTL->dioc_cbOutBuf!=sizeof(DWORD)) {
784: DBTRACE(0,"!INVALID OUTBUF");
785: return(SBBSEXEC_ERROR_OUTBUF);
786: }
787:
788: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
789: if(vm==NULL) {
790: DBTRACE(0,"!NO VM LIST");
791: return(SBBSEXEC_ERROR_INDATA);
792: }
793:
794: wr = pIOCTL->dioc_cbInBuf-sizeof(VMHANDLE);
795:
796: avail = RingBufFree(&vm->in);
797:
798: if(wr>avail) {
799: DBTRACEdd(0,"Reducing write size", wr, avail);
800: wr=avail;
801: }
802:
803: RingBufWrite(&vm->in, (BYTE*)pIOCTL->dioc_InBuf+sizeof(VMHANDLE), wr);
804:
805: *(DWORD *)pIOCTL->dioc_OutBuf = wr;
806:
807: if(pIOCTL->dioc_bytesret!=NULL)
808: *pIOCTL->dioc_bytesret = sizeof(DWORD);
809:
810: if(vm->input_sem!=NULL) // Wake up int14 handler
811: Signal_Semaphore(vm->input_sem);
1.1.1.2 ! root 812:
! 813: // Wake up the VDM (improves keyboard response - dramatically!)
! 814: Wake_Up_VM(vm->handle);
1.1 root 815: break;
816:
817: case SBBSEXEC_IOCTL_DISCONNECT:
818: DBTRACEd(0,"IOCTL: DISCONNECT",Get_System_Time());
819:
820: if (pIOCTL->dioc_InBuf==NULL
821: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
822: DBTRACE(0,"!INVALID INBUF");
823: return(SBBSEXEC_ERROR_INBUF);
824: }
825:
826: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
827: if(vm==NULL) {
828: DBTRACE(0,"!NO VM LIST");
829: return(SBBSEXEC_ERROR_INDATA);
830: }
831:
832: vm->online=false;
833:
834: if(vm->input_sem!=NULL) // Wake up int14 handler
835: Signal_Semaphore(vm->input_sem);
836: if(vm->output_sem!=NULL) // Wake up int14 handler
837: Signal_Semaphore(vm->output_sem);
838: break;
839:
840: case SBBSEXEC_IOCTL_STOP:
841: DBTRACEd(0,"IOCTL: STOP",Get_System_Time());
842:
843: if (pIOCTL->dioc_InBuf==NULL
844: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
845: DBTRACE(0,"!INVALID INBUF");
846: return(SBBSEXEC_ERROR_INBUF);
847: }
848:
849: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
850: if(vm==NULL) {
851: DBTRACE(0,"!NO VM LIST");
852: return(SBBSEXEC_ERROR_INDATA);
853: }
854:
855: DBTRACEx(0,"CLOSING VM HANDLE", vm->handle);
856: vm->handle=NULL; // Mark as available
857: RingBufDispose(&vm->in);
858: RingBufDispose(&vm->out);
859: if(vm->input_sem!=NULL) // Wake up int14 handler
860: Signal_Semaphore(vm->input_sem);
861: if(vm->output_sem!=NULL) // Wake up int14 handler
862: Signal_Semaphore(vm->output_sem);
863:
864: vm->input_sem=NULL;
865: vm->output_sem=NULL;
866:
867: break;
868:
869: default:
870: DBTRACEdx(0,"!UNKNOWN IOCTL"
871: ,pIOCTL->dioc_IOCtlCode,pIOCTL->dioc_IOCtlCode);
872: return(SBBSEXEC_ERROR_IOCTL);
873:
874: }
875: return (0); // DEVIOCTL_NOERROR);
876: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.