Annotation of sbbs/sbbs3/execvxd/sbbsexec.cpp, revision 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.