|
|
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.2 2001/05/02 01:58:31 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: DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle()); ! 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()); ! 703: DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle()); ! 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); ! 812: ! 813: // Wake up the VDM (improves keyboard response - dramatically!) ! 814: Wake_Up_VM(vm->handle); ! 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.