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