|
|
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.