Annotation of sbbs/sbbs3/execvxd/sbbsexec.cpp, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.