Annotation of sbbs/src/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.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: }

unix.superglobalmegacorp.com

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