|
|
1.1 root 1: // SBBSEXEC.cpp - SBBSEXEC.VXD main module
2:
3: /* Synchronet Windows 9X FOSSIL driver (requires VtoolsD C++ framework) */
4:
5: /* $Id: sbbsexec.cpp,v 1.1.1.1 2000/10/10 11:27:21 rswindell Exp $ */
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());
238:
239: if(start.event) {
240: new_vm=find_vm(NULL);
241: if(new_vm==NULL) {
242: DBTRACE(0,"!NO AVAILABLE VM structures");
243: return(FALSE);
244: }
245: new_vm->handle=hVM;
246: new_vm->mode=start.mode;
247: new_vm->online = true;
248: new_vm->overrun = false;
249: new_vm->input_sem = NULL;
250: new_vm->output_sem = NULL;
251:
252: if(RingBufInit(&new_vm->in, RINGBUF_SIZE_IN)!=0
253: || RingBufInit(&new_vm->out, RINGBUF_SIZE_OUT)!=0) {
254: DBTRACE(0,"!FAILED to create I/O buffers");
255: return(FALSE);
256: }
257: if(!VWIN32_SetWin32Event(start.event)) {
258: DBTRACEx(0,"!FAILED TO SET EVENT handle", start.event);
259: return(FALSE);
260: }
261: if(!VWIN32_CloseVxDHandle(start.event)) {
262: DBTRACEx(0,"!FAILED TO CLOSE EVENT handle", start.event);
263: return(FALSE);
264: }
265: start.event=0;
266: }
267: return(TRUE);
268: }
269:
270:
271: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
272: SBBSExecInt29::SBBSExecInt29() : VPreChainV86Int(0x29)
273: {
274: DBTRACE(0,"SBBSExecInt29 constructor");
275: }
276:
277: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
278: BOOL SBBSExecInt29::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
279: {
280: vm_t* vm = find_vm(hVM);
281:
282: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
283: return(FALSE); // Tells VMM that interrupt was not handled
284: }
285:
286: if(!RingBufFree(&vm->out)) {
287: DBTRACEx(0,"!Int29 OUTPUT BUFFER OVERFLOW, hVM", hVM);
288: vm->overrun=true;
289: return(FALSE);
290: }
291: DBTRACEx(1,"Int29 OUTPUT", _clientAL);
292:
293: BYTE ch=_clientAL;
294: RingBufWrite(&vm->out,&ch,1);
295: vm->overrun=false;
296:
297: return(FALSE);
298: }
299:
300:
301: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302: SBBSExecInt21::SBBSExecInt21() : VPreChainV86Int(0x21)
303: {
304: DBTRACE(0,"SBBSExecInt21 constructor");
305: }
306:
307: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
308: BOOL SBBSExecInt21::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
309: {
310: BYTE ch;
311: BYTE* buffer;
312: WORD buflen;
313: vm_t* vm = find_vm(hVM);
314:
315: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
316: #if 0
317: if(vm && !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
318: DBTRACEx(0,"Int21 on unsupported VM", hVM);
319: }
320: #endif
321: return(FALSE); // Tells VMM that interrupt was not handled
322: }
323: DBTRACEx(1,"Int21 function", _clientAH);
324:
325: DWORD avail = RingBufFree(&vm->out);
326:
327: switch(_clientAH) {
328: case 0x01:
329: DBTRACE(0,"!Int21 Char input WITH echo");
330: break;
331: case 0x06: // Direct console I/O
332: DBTRACEx(0,"DOS DIRECT CONSOLE IO, DL", _clientDL);
333: if(_clientDL==0xff) {
334: avail=RingBufFull(&vm->in);
335: if(avail) {
336: DBTRACEd(0,"avail",avail);
337: RingBufRead(&vm->in, &ch, 1);
338: _clientFlags&=~(1<<6); // clear zero flag
339: _clientAX=ch;
340: return(TRUE);
341: }
342: break;
343: }
344: // fall-through
345: case 0x02: // Character output
346: DBTRACEx(1,"Int21 function", _clientAH);
347: if(!avail) {
348: DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
349: vm->overrun=true;
350: break;
351: }
352: ch=_clientDL;
353: RingBufWrite(&vm->out,&ch,1);
354: vm->overrun=false;
355: break;
356: case 0x09: // Display string
357: DBTRACE(0,"!Int21 func 09 - DISPLAY STRING");
358: break;
359: case 0x0A: // Buffered keyboard input
360: DBTRACE(0,"Int21 Func 0A - Buffered Keyboard Input");
361: /* Need to get a string from the user, echo, and copy to DS:DX */
362: /* byte 0 = max length, byte 1 = actual read (minus CR) */
363: break;
364: case 0x40: // Write file or device
365: if(_clientBX!=1 && _clientBX!=2) { // !stdout and !stderr
366: DBTRACEd(1,"!Int21 write to unsupported device", _clientBX);
367: break;
368: }
369: DBTRACEdd(1,"Int21 write file", _clientBX, _clientCX);
370: buffer = (BYTE*)MAPFLAT(CRS.Client_DS, CWRS.Client_DX);
371: buflen = _clientCX;
372: if(avail<buflen) {
373: DBTRACEd(0,"!OUTPUT BUFFER OVERFLOW, avail", avail);
374: vm->overrun=true;
375: if(!avail)
376: break;
377: buflen=avail;
378: }
379: RingBufWrite(&vm->out,buffer,buflen);
380: vm->overrun=false;
381: break;
382: }
383:
384: return(FALSE); // Tells VMM that interrupt was not handled
385: }
386:
387: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
388: SBBSExecInt16::SBBSExecInt16() : VPreChainV86Int(0x16)
389: {
390: DBTRACE(0,"SBBSExecInt16 constructor");
391: }
392:
393: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
394: BOOL SBBSExecInt16::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
395: {
396: BYTE ch;
397: DWORD avail;
398: vm_t* vm = find_vm(hVM);
399:
400: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_IN)) {
401: return(FALSE); // Tells VMM that interrupt was not handled
402: }
403:
404: // DBTRACExx(0,"Int16 (hVM, AX)", hVM, _clientAX);
405:
406: avail=RingBufFull(&vm->in);
407: switch(_clientAH) {
408: case 0x00: // Read char from keyboard
409: case 0x10: // Read char from enhanced keyboard
410: if(avail) {
411: RingBufRead(&vm->in, &ch, 1);
412: _clientAX=ch;
413: return(TRUE);
414: }
415: break;
416: case 0x01: // Get keyboard status
417: case 0x11: // Get enhanced keyboard status
418: if(avail) {
419: RingBufPeek(&vm->in, &ch, 1);
420: _clientFlags&=~(1<<6); // clear zero flag
421: _clientAX=ch;
422: return(TRUE);
423: }
424: break;
425: default:
426: DBTRACEx(0,"!UNHANDLED INT16 function", _clientAH);
427: break;
428: }
429:
430: return(FALSE);
431: }
432:
433: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
434: SBBSExecInt14::SBBSExecInt14() : VPreChainV86Int(0x14)
435: {
436: DBTRACE(0,"SBBSExecInt14 constructor");
437: }
438:
439: WORD PortStatus(vm_t* vm)
440: {
441: WORD status=0x0008; // AL bit 3 (change in DCD) always set
442:
443: if(vm->online) // carrier detect
444: status|=0x0080; // DCD
445:
446: if(RingBufFull(&vm->in)) // receive data ready
447: status|=0x0100; // RDA
448:
449: if(vm->overrun) // overrun error detected
450: status|=0x0200; // OVRN
451:
452: if(RingBufFree(&vm->out)> // room available in output buffer
453: RINGBUF_SIZE_OUT/2)
454: status|=0x2000; // THRE
455:
456: if(!RingBufFull(&vm->out)) // output buffer is empty
457: status|=0x4000; // TSRE
458:
459: return(status);
460: }
461: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
462: const char* fossil_id="Synchronet SBBSEXEC.VXD Fossil";
463: BOOL SBBSExecInt14::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
464: {
465: BYTE* buffer;
466: BYTE ch;
467: WORD buflen;
468: WORD rd,wr;
469: WORD avail;
470: vm_t* vm = find_vm(hVM);
471:
472: if(vm==NULL || vm->mode!=SBBSEXEC_MODE_FOSSIL) {
473: return(FALSE); // Tells VMM that interrupt was not handled
474: }
475:
476:
477: DBTRACEx(4,"Int14 func",_clientAH);
478:
479: switch(_clientAH) {
480: case 0x00: /* Initialize/Set baud rate */
481: DBTRACE(0,"Int14 init");
482: _clientAX=PortStatus(vm);
483: break;
484: case 0x01: /* write char to com port */
485: if(RingBufFree(&vm->out)<2) {
486: DBTRACEx(1,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
487: vm->output_sem=Create_Semaphore(0);
488: Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
489: Destroy_Semaphore(vm->output_sem);
490: vm->output_sem=NULL;
491: if(!vm->online) {
492: DBTRACE(0,"!USER HUNG UP");
493: return(true);
494: }
495: }
496: ch=_clientAL;
497: RingBufWrite(&vm->out,&ch,1);
498: #if 0 /* Now done in SBBS.DLL/XTRN.CPP */
499: if(ch==0xff) { /* escape TELNET IAC */
500: RingBufWrite(&vm->out,&ch,1);
501: DBTRACE(1,"Escaped IAC in output stream");
502: }
503: #endif
504: vm->overrun=false;
505: _clientAX=PortStatus(vm);
506: break;
507: case 0x02: /* read char from com port */
508: if(!RingBufFull(&vm->in)) {
509: DBTRACEx(0,"Waiting on input semaphore, hVM", hVM);
510: vm->input_sem=Create_Semaphore(0);
511: Wait_Semaphore(vm->input_sem,BLOCK_THREAD_IDLE);
512: Destroy_Semaphore(vm->input_sem);
513: vm->input_sem=NULL;
514: #if 0
515: _clientAH=0x80; /* timed-out */
516: return(TRUE);
517: #endif
518: }
519: RingBufRead(&vm->in,&ch,1);
520: _clientAH=0;
521: _clientAL=ch;
522: break;
523: case 0x03: /* request status */
524: _clientAX=PortStatus(vm);
525: break;
526: case 0x04: /* initialize */
527: DBTRACE(0,"Int14 func 4 init");
528: _clientAX=0x1954; /* magic number = success */
529: _clientBH=5; /* FOSSIL rev */
530: _clientBL=0x1B; /* maximum FOSSIL func supported */
531: break;
532: case 0x08: // flush output buffer
533: DBTRACE(0,"Int14 FLUSH OUTPUT BUFFER");
534: vm->output_sem=Create_Semaphore(0);
535: Wait_Semaphore(vm->output_sem,BLOCK_THREAD_IDLE);
536: Destroy_Semaphore(vm->output_sem);
537: vm->output_sem=NULL;
538: break;
539: case 0x09: // purge output buffer
540: DBTRACE(0,"Int14 PURGE OUTPUT BUFFER");
541: RingBufReInit(&vm->out);
542: break;
543: case 0x0A: // purge input buffer
544: DBTRACE(0,"Int14 PURGE INPUT BUFFER");
545: RingBufReInit(&vm->in);
546: break;
547: case 0x0B: /* write char to com port, no wait */
548: if(RingBufFree(&vm->out)<2) {
549: _clientAX=0; // char was not accepted
550: break;
551: }
552: ch=_clientAL;
553: RingBufWrite(&vm->out,&ch,1);
554: #if 0 /* Now done in SBBS.DLL/XTRN.CPP */
555: if(ch==0xff) { /* escape TELNET IAC */
556: RingBufWrite(&vm->out,&ch,1);
557: DBTRACE(1,"Escaped IAC in output stream");
558: }
559: #endif
560: _clientAX=1; // char was accepted
561: break;
562: case 0x0C: // non-destructive read-ahead
563: if(!RingBufFull(&vm->in)) {
564: _clientAX=0xffff; // no char available
565: break;
566: }
567: RingBufPeek(&vm->in,&ch,1);
568: _clientAH=0;
569: _clientAL=ch;
570: break;
571: case 0x13: /* write to display */
572: dprintf("%c",_clientAL);
573: break;
574: case 0x18: /* read bock */
575: rd=_clientCX;
576: avail=RingBufFull(&vm->in);
577: if(rd>avail)
578: rd=avail;
579: if(rd) {
580: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
581: rd = RingBufRead(&vm->in, buffer, rd);
582: }
583: _clientAX = rd;
584: break;
585: case 0x19: /* write block */
586: wr=_clientCX;
587: avail=RingBufFree(&vm->out);
588: if(wr>avail)
589: wr=avail;
590: if(wr) {
591: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
592: wr = RingBufWrite(&vm->out, buffer, wr);
593: }
594: _clientAX = wr;
595: break;
596: #if 1
597: case 0x1B: // driver info
598: {
599: DBTRACE(1,"Int14 driver info");
600: struct {
601: WORD info_size;
602: BYTE curr_fossil;
603: BYTE curr_rev;
604: DWORD id_string;
605: WORD inbuf_size;
606: WORD inbuf_free;
607: WORD outbuf_size;
608: WORD outbuf_free;
609: BYTE screen_width;
610: BYTE screen_height;
611: BYTE baud_rate;
612: } info={ sizeof(info), 5, 1, 0
613: ,RINGBUF_SIZE_IN-1, RingBufFree(&vm->in)
614: ,RINGBUF_SIZE_OUT-1, RingBufFree(&vm->out)
615: ,80,25
616: ,1 // 38400
617: };
618: // Map_Lin_To_VM_Addr
619: buffer = (BYTE*)MAPFLAT(CRS.Client_ES, CWRS.Client_DI);
620: wr=sizeof(info);
621: if(wr>_clientCX)
622: wr=_clientCX;
623: memcpy(buffer, &info, wr);
624: _clientAX=wr;
625: break;
626: }
627: #endif
628: default:
629: DBTRACEx(0,"!UNHANDLED INTERRUPT 14h function",_clientAH);
630: break;
631: }
632: return(TRUE); // Tells VMM that interrupt was handled
633: }
634:
635: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
636: SBBSExecInt10::SBBSExecInt10() : VPreChainV86Int(0x10)
637: {
638: DBTRACE(0,"SBBSExecInt10 constructor");
639: }
640:
641: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
642: BOOL SBBSExecInt10::handler(VMHANDLE hVM, CLIENT_STRUCT* pRegs, DWORD intno)
643: {
644: BYTE ch;
645: DWORD avail;
646: vm_t* vm = find_vm(hVM);
647:
648: if(vm==NULL || !(vm->mode&SBBSEXEC_MODE_DOS_OUT)) {
649: return(FALSE); // Tells VMM that interrupt was not handled
650: }
651:
652: avail=RingBufFree(&vm->out);
653:
654: switch(_clientAH) {
655: case 0x02: // Set Cursor Position
656: DBTRACE(1,"Int10 func 2 - Set cursor position");
657: break;
658: case 0x09: // Write char and attr at cursor
659: DBTRACE(1,"Int10 func 9 - Write char and attr at curosr");
660: case 0x10: // Write char at cursor
661: #if 0
662: DBTRACE(1,"Int10 func 9 - Write char at curosr");
663: if(!avail) {
664: DBTRACEx(0,"!OUTPUT BUFFER OVERFLOW, hVM", hVM);
665: vm->overrun=true;
666: break;
667: }
668: ch=_clientAL;
669: RingBufWrite(&vm->out,&ch,1);
670: vm->overrun=false;
671:
672: #endif
673: break;
674: }
675:
676: return(FALSE);
677: }
678:
679:
680:
681: DWORD SBBSExec::OnW32DeviceIoControl(PIOCTLPARAMS pIOCTL)
682: {
683: DWORD rd;
684: DWORD wr;
685: DWORD avail;
686: vm_t* vm;
687:
688: // DBTRACEd(0,"SBBSEXEC ioctl"
689: //,pIOCTL->dioc_IOCtlCode);
690:
691: switch(pIOCTL->dioc_IOCtlCode) {
692: case DIOC_OPEN:
693: DBTRACEd(0,"IOCTL: OPEN",Get_System_Time());
694: break;
695:
696: case DIOC_CLOSEHANDLE:
697: DBTRACEd(0,"IOCTL: CLOSE",Get_System_Time());
698: break;
699:
700: case SBBSEXEC_IOCTL_START:
701: DBTRACEd(0,"IOCTL: START",Get_System_Time());
702: if(start.event) {
703: DBTRACE(0,"Exec already started!");
704: return(SBBSEXEC_ERROR_INUSE);
705: }
706: if (pIOCTL->dioc_InBuf==NULL
707: || pIOCTL->dioc_cbInBuf!=sizeof(start)) {
708: return(SBBSEXEC_ERROR_INBUF);
709: }
710: start=*(sbbsexec_start_t*)pIOCTL->dioc_InBuf;
711: break;
712:
713: case SBBSEXEC_IOCTL_COMPLETE:
714: DBTRACEd(0,"IOCTL: COMPLETE",Get_System_Time());
715: if(start.event || new_vm==NULL) {
716: DBTRACE(0,"!VM never created");
717: start.event=0;
718: return(SBBSEXEC_ERROR_INUSE);
719: }
720: if(pIOCTL->dioc_OutBuf==NULL
721: || pIOCTL->dioc_cbOutBuf<sizeof(VMHANDLE)) {
722: DBTRACE(0,"!Invalid OUTBUF");
723: return(SBBSEXEC_ERROR_OUTBUF);
724: }
725: *(VMHANDLE*)pIOCTL->dioc_OutBuf=new_vm->handle;
726: DBTRACEx(0,"CREATED VM HANDLE", new_vm->handle);
727: new_vm=NULL;
728:
729: if(pIOCTL->dioc_bytesret!=NULL)
730: *pIOCTL->dioc_bytesret = sizeof(VMHANDLE);
731: break;
732: case SBBSEXEC_IOCTL_READ:
733:
734: if (pIOCTL->dioc_InBuf==NULL
735: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
736: DBTRACE(0,"!INVALID INBUF");
737: return(SBBSEXEC_ERROR_INBUF);
738: }
739:
740: if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf==0) {
741: DBTRACE(0,"!INVALID OUTBUF");
742: return(SBBSEXEC_ERROR_OUTBUF);
743: }
744:
745: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
746: if(vm==NULL) {
747: DBTRACE(0,"!NO VM LIST");
748: return(SBBSEXEC_ERROR_INDATA);
749: }
750:
751: rd = RingBufFull(&vm->out);
752:
753: if(rd>pIOCTL->dioc_cbOutBuf) {
754: DBTRACEdd(0,"Reducing read size"
755: ,rd, pIOCTL->dioc_cbOutBuf);
756: rd=pIOCTL->dioc_cbOutBuf;
757: }
758:
759: RingBufRead(&vm->out, (BYTE*)pIOCTL->dioc_OutBuf, rd);
760:
761: if(pIOCTL->dioc_bytesret!=NULL)
762: *pIOCTL->dioc_bytesret = rd;
763:
764: if(vm->output_sem!=NULL) // Wake up int14 handler
765: Signal_Semaphore(vm->output_sem);
766:
767: if(rd>1) {
768: DBTRACEd(1,"IOCTL_READ bytes", rd);
769: }
770: break;
771:
772: case SBBSEXEC_IOCTL_WRITE:
773:
774: if (pIOCTL->dioc_InBuf==NULL
775: || pIOCTL->dioc_cbInBuf<sizeof(VMHANDLE)+1) {
776: DBTRACE(0,"!INVALID INBUF");
777: return(SBBSEXEC_ERROR_INBUF);
778: }
779:
780: if (pIOCTL->dioc_OutBuf==NULL
781: || pIOCTL->dioc_cbOutBuf!=sizeof(DWORD)) {
782: DBTRACE(0,"!INVALID OUTBUF");
783: return(SBBSEXEC_ERROR_OUTBUF);
784: }
785:
786: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
787: if(vm==NULL) {
788: DBTRACE(0,"!NO VM LIST");
789: return(SBBSEXEC_ERROR_INDATA);
790: }
791:
792: wr = pIOCTL->dioc_cbInBuf-sizeof(VMHANDLE);
793:
794: avail = RingBufFree(&vm->in);
795:
796: if(wr>avail) {
797: DBTRACEdd(0,"Reducing write size", wr, avail);
798: wr=avail;
799: }
800:
801: RingBufWrite(&vm->in, (BYTE*)pIOCTL->dioc_InBuf+sizeof(VMHANDLE), wr);
802:
803: *(DWORD *)pIOCTL->dioc_OutBuf = wr;
804:
805: if(pIOCTL->dioc_bytesret!=NULL)
806: *pIOCTL->dioc_bytesret = sizeof(DWORD);
807:
808: if(vm->input_sem!=NULL) // Wake up int14 handler
809: Signal_Semaphore(vm->input_sem);
810: break;
811:
812: case SBBSEXEC_IOCTL_DISCONNECT:
813: DBTRACEd(0,"IOCTL: DISCONNECT",Get_System_Time());
814:
815: if (pIOCTL->dioc_InBuf==NULL
816: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
817: DBTRACE(0,"!INVALID INBUF");
818: return(SBBSEXEC_ERROR_INBUF);
819: }
820:
821: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
822: if(vm==NULL) {
823: DBTRACE(0,"!NO VM LIST");
824: return(SBBSEXEC_ERROR_INDATA);
825: }
826:
827: vm->online=false;
828:
829: if(vm->input_sem!=NULL) // Wake up int14 handler
830: Signal_Semaphore(vm->input_sem);
831: if(vm->output_sem!=NULL) // Wake up int14 handler
832: Signal_Semaphore(vm->output_sem);
833: break;
834:
835: case SBBSEXEC_IOCTL_STOP:
836: DBTRACEd(0,"IOCTL: STOP",Get_System_Time());
837:
838: if (pIOCTL->dioc_InBuf==NULL
839: || pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
840: DBTRACE(0,"!INVALID INBUF");
841: return(SBBSEXEC_ERROR_INBUF);
842: }
843:
844: vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
845: if(vm==NULL) {
846: DBTRACE(0,"!NO VM LIST");
847: return(SBBSEXEC_ERROR_INDATA);
848: }
849:
850: DBTRACEx(0,"CLOSING VM HANDLE", vm->handle);
851: vm->handle=NULL; // Mark as available
852: RingBufDispose(&vm->in);
853: RingBufDispose(&vm->out);
854: if(vm->input_sem!=NULL) // Wake up int14 handler
855: Signal_Semaphore(vm->input_sem);
856: if(vm->output_sem!=NULL) // Wake up int14 handler
857: Signal_Semaphore(vm->output_sem);
858:
859: vm->input_sem=NULL;
860: vm->output_sem=NULL;
861:
862: break;
863:
864: default:
865: DBTRACEdx(0,"!UNKNOWN IOCTL"
866: ,pIOCTL->dioc_IOCtlCode,pIOCTL->dioc_IOCtlCode);
867: return(SBBSEXEC_ERROR_IOCTL);
868:
869: }
870: return (0); // DEVIOCTL_NOERROR);
871: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.