Annotation of sbbs/src/sbbs3/sbbsexec.c, revision 1.1

1.1     ! root        1: /* sbbsexec.c */
        !             2: 
        !             3: /* Synchronet Windows NT/2000 VDD for FOSSIL and DOS I/O Interrupts */
        !             4: 
        !             5: /* $Id: sbbsexec.c,v 1.38 2006/10/28 03:56:36 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 2006 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: #include <windows.h> 
        !            39: #include <stdio.h>
        !            40: #include <vddsvc.h>
        !            41: #include "uartdefs.h"
        !            42: #include "vdd_func.h"
        !            43: #include "ringbuf.h"
        !            44: #include "genwrap.h"
        !            45: #include "dirwrap.h"
        !            46: #include "threadwrap.h"
        !            47: #include "ini_file.h"
        !            48: 
        !            49: #define INI_FILENAME                   "sbbsexec.ini"
        !            50: #define RINGBUF_SIZE_IN                        10000
        !            51: #define DEFAULT_MAX_MSG_SIZE   4000
        !            52: #define LINEAR_RX_BUFLEN               5000
        !            53: 
        !            54: /* UART Parameters and virtual registers */
        !            55: WORD uart_io_base                              = UART_COM1_IO_BASE;    /* COM1 */
        !            56: BYTE uart_irq                                  = UART_COM1_IRQ;
        !            57: BYTE uart_ier_reg                              = 0;
        !            58: BYTE uart_lcr_reg                              = UART_LCR_8_DATA_BITS;
        !            59: BYTE uart_mcr_reg                              = UART_MCR_RTS | UART_MCR_DTR;
        !            60: BYTE uart_lsr_reg                              = UART_LSR_EMPTY_DATA | UART_LSR_EMPTY_XMIT;
        !            61: BYTE uart_msr_reg                              = UART_MSR_CTS | UART_MSR_DSR;
        !            62: BYTE uart_scratch_reg                  = 0;
        !            63: BYTE uart_divisor_latch_lsb            = 0x03; /* 38400 */
        !            64: BYTE uart_divisor_latch_msb            = 0x00;
        !            65: 
        !            66: #if defined (_DEBUG)
        !            67:        int log_level = LOG_DEBUG;
        !            68: #else
        !            69:        int log_level = LOG_WARNING;
        !            70: #endif
        !            71: 
        !            72: BOOL           virtualize_uart=TRUE;
        !            73: double         yield_interval=1.0;
        !            74: BOOL           hangup_supported=TRUE;
        !            75: HANDLE         hangup_event=NULL;
        !            76: HANDLE         hungup_event=NULL;
        !            77: HANDLE         interrupt_event=NULL;
        !            78: HANDLE         rdslot=INVALID_HANDLE_VALUE;
        !            79: HANDLE         wrslot=INVALID_HANDLE_VALUE;
        !            80: RingBuf                rdbuf;
        !            81: str_list_t     ini;
        !            82: char           ini_fname[MAX_PATH+1];
        !            83: char           revision[16];
        !            84: 
        !            85: void lputs(int level, char* msg)
        !            86: {      
        !            87:        char buf[1024];
        !            88:        if(level > log_level)
        !            89:                return;
        !            90: 
        !            91:        SAFEPRINTF(buf,"SBBS: %s\r\n", msg);
        !            92:        OutputDebugString(buf);
        !            93: }
        !            94: 
        !            95: static void lprintf(int level, const char *fmt, ...)
        !            96: {
        !            97:        char sbuf[1024];
        !            98:        va_list argptr;
        !            99: 
        !           100:        if(level > log_level)
        !           101:                return;
        !           102: 
        !           103:     va_start(argptr,fmt);
        !           104:     _vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
        !           105:        sbuf[sizeof(sbuf)-1]=0;
        !           106:     va_end(argptr);
        !           107:     lputs(level,sbuf);
        !           108: }
        !           109: 
        !           110: void hangup()
        !           111: {
        !           112:        if(hangup_supported && hangup_event!=NULL) {
        !           113:                lprintf(LOG_DEBUG,"Hanging-up at application request");
        !           114:                SetEvent(hangup_event);
        !           115:        }
        !           116: }
        !           117: 
        !           118: void parse_ini(char* program)
        !           119: {
        !           120:        char section[MAX_PATH+1];
        !           121: 
        !           122:        if(ini==NULL)   /* no initialization file */
        !           123:                return;
        !           124: 
        !           125:        /* Read the root section of the sbbsexec.ini file */
        !           126:        log_level=iniGetLogLevel(ini,program,"LogLevel",log_level);
        !           127:        if(iniGetBool(ini,program,"Debug",FALSE))
        !           128:                log_level=LOG_DEBUG;
        !           129:        yield_interval=iniGetFloat(ini,program,"YieldInterval",yield_interval);
        !           130:        hangup_supported=iniGetBool(ini,program,"CanDisconnect",hangup_supported);
        !           131: 
        !           132:        lprintf(LOG_INFO,"Parsed %s section of %s"
        !           133:                ,program==ROOT_SECTION ? "root" : program
        !           134:                ,ini_fname);
        !           135: 
        !           136:        /* [UART] section */
        !           137:        if(program==ROOT_SECTION)
        !           138:                SAFECOPY(section,"UART");
        !           139:        else
        !           140:                SAFEPRINTF(section,"%s.UART",program);
        !           141: 
        !           142:        virtualize_uart=iniGetBool(ini,section,"Virtualize",virtualize_uart);
        !           143:        switch(iniGetInteger(ini,section,"ComPort",0)) {
        !           144:                case 1: /* COM1 */
        !           145:                        uart_irq                =UART_COM1_IRQ;
        !           146:                        uart_io_base    =UART_COM1_IO_BASE;
        !           147:                        break;
        !           148:                case 2: /* COM2 */
        !           149:                        uart_irq                =UART_COM2_IRQ;
        !           150:                        uart_io_base    =UART_COM2_IO_BASE;
        !           151:                        break;
        !           152:                case 3: /* COM3 */
        !           153:                        uart_irq                =UART_COM3_IRQ;
        !           154:                        uart_io_base    =UART_COM3_IO_BASE;
        !           155:                        break;
        !           156:                case 4: /* COM4 */
        !           157:                        uart_irq                =UART_COM4_IRQ;
        !           158:                        uart_io_base    =UART_COM4_IO_BASE;
        !           159:                        break;
        !           160:        }
        !           161:        uart_irq=(BYTE)iniGetShortInt(ini,section,"IRQ",uart_irq);
        !           162:        uart_io_base=iniGetShortInt(ini,section,"Address",uart_io_base);
        !           163: 
        !           164:        lprintf(LOG_INFO,"Parsed %s section of %s"
        !           165:                ,section
        !           166:                ,ini_fname);
        !           167: }
        !           168: 
        !           169: 
        !           170: /* Mutex-protected pending interrupt "queue" */
        !           171: int pending_interrupts = 0;
        !           172: CRITICAL_SECTION interrupt_mutex;
        !           173: 
        !           174: void set_interrupt_pending(BYTE intr, BOOL assert)
        !           175: {
        !           176:        EnterCriticalSection(&interrupt_mutex);
        !           177:        lprintf(LOG_DEBUG,"%sasserting interrupt %02X (pending: %02X, IER: %02X)"
        !           178:                ,assert ? "" : "de-", intr
        !           179:                ,pending_interrupts
        !           180:                ,uart_ier_reg);
        !           181:        if(assert) {
        !           182:                if(uart_ier_reg&intr) {                                 /* is interrupt enabled? */
        !           183:                        pending_interrupts |= intr;                     /* flag as pending */
        !           184:                        SetEvent(interrupt_event);
        !           185:                }
        !           186:        } else /* de-assert */
        !           187:                pending_interrupts &= ~intr;            /* remove as pending */
        !           188: 
        !           189:        LeaveCriticalSection(&interrupt_mutex);
        !           190: }
        !           191: 
        !           192: #define assert_interrupt(i)            set_interrupt_pending(i, TRUE)
        !           193: #define deassert_interrupt(i)  set_interrupt_pending(i, FALSE)
        !           194: 
        !           195: void _cdecl interrupt_thread(void *arg)
        !           196: {
        !           197:        while(1) {
        !           198:                if(WaitForSingleObject(interrupt_event,INFINITE)!=WAIT_OBJECT_0)
        !           199:                        break;
        !           200:                if((uart_ier_reg&pending_interrupts) != 0) {
        !           201:                        lprintf(LOG_DEBUG,"VDDSimulateInterrupt (pending: %02X) - IER: %02X"
        !           202:                                ,pending_interrupts, uart_ier_reg);
        !           203:                        VDDSimulateInterrupt(ICA_MASTER, uart_irq, /* count: */1);
        !           204:                }
        !           205: #if 0
        !           206:                /* "Real 16550s should always reassert
        !           207:                 *  this interrupt whenever the transmitter is idle and
        !           208:                 *  the interrupt is enabled."
        !           209:                 */
        !           210:                if(pending_interrupts==0 && uart_ier_reg&UART_IER_TX_EMPTY)
        !           211:                        pending_interrupts|=UART_IER_TX_EMPTY;
        !           212: #endif
        !           213:        }
        !           214: }
        !           215: 
        !           216: void _cdecl input_thread(void* arg)
        !           217: {
        !           218:        char    buf[LINEAR_RX_BUFLEN];
        !           219:        int             count;
        !           220: 
        !           221:        while(1) {
        !           222:                count=0;
        !           223:                if(!ReadFile(rdslot,buf,sizeof(buf),&count,NULL)) {
        !           224:                        if(GetLastError()==ERROR_HANDLE_EOF)    /* closed by VDD_CLOSE */
        !           225:                                break;
        !           226:                        lprintf(LOG_ERR,"!input_thread: ReadFile Error %d (size=%d)"
        !           227:                                ,GetLastError(),count);
        !           228:                        continue;
        !           229:                }
        !           230:                if(count==0) {
        !           231:                        lprintf(LOG_ERR,"!input_thread: ReadFile read 0");
        !           232:                        continue;
        !           233:                }
        !           234:                RingBufWrite(&rdbuf,buf,count);
        !           235:                /* Set the "Data ready" bit in the LSR */
        !           236:                uart_lsr_reg |= UART_LSR_DATA_READY;
        !           237: 
        !           238:                assert_interrupt(UART_IER_RX_DATA); /* assert rx data interrupt */
        !           239:        }
        !           240: }
        !           241: 
        !           242: unsigned vdd_read(BYTE* p, unsigned count)
        !           243: {
        !           244:        sem_wait(rdbuf.sem);
        !           245:        count=RingBufRead(&rdbuf,p,count);
        !           246:        if(count==0)
        !           247:                lprintf(LOG_ERR,"!VDD_READ: RingBufRead read 0");
        !           248: 
        !           249:        return(count);
        !           250: }
        !           251: 
        !           252: unsigned yields=0;
        !           253: 
        !           254: void yield()
        !           255: {
        !           256:        yields++;
        !           257:        lprintf(LOG_DEBUG,"Yielding (yields=%u)", yields);
        !           258:        Sleep(1);
        !           259: }
        !           260: 
        !           261: long double last_yield=0;
        !           262: 
        !           263: void maybe_yield()
        !           264: {
        !           265:        long double t;
        !           266: 
        !           267:        t=xp_timer();
        !           268: 
        !           269:        if(yield_interval && (t-last_yield)*1000.0 >= yield_interval) {
        !           270:                yield();
        !           271:                last_yield=t;
        !           272:        }
        !           273: }
        !           274: 
        !           275: void reset_yield()
        !           276: {
        !           277:        last_yield=xp_timer();
        !           278: }
        !           279: 
        !           280: /***********************/
        !           281: /* UART Virtualization */
        !           282: /***********************/
        !           283: 
        !           284: static char *chr(uchar ch)
        !           285: {
        !           286:        static char str[25];
        !           287: 
        !           288:        if(ch>=' ' && ch<='~')
        !           289:                sprintf(str,"'%c' (%02Xh)",ch,ch);
        !           290:        else if(ch<' ')
        !           291:                sprintf(str,"^%c  (%02Xh)",'@'+ch,ch);
        !           292:        else
        !           293:                sprintf(str,"%u (%02Xh)",ch,ch);
        !           294:        return(str); 
        !           295: }
        !           296: 
        !           297: VOID uart_wrport(WORD port, BYTE data)
        !           298: {
        !           299:        int reg = port - uart_io_base;
        !           300:        int retval;
        !           301: 
        !           302:        lprintf(LOG_DEBUG,"write of port: %x (%s) <- %02X", port, uart_reg_desc[reg], data);
        !           303: 
        !           304:        switch(reg) {
        !           305:                case UART_BASE:
        !           306:                        if(uart_lcr_reg&UART_LCR_DLAB) {
        !           307:                                uart_divisor_latch_lsb = data;
        !           308:                                lprintf(LOG_DEBUG,"set divisor latch low byte: %02X", data);
        !           309:                        } else {
        !           310:                                lprintf(LOG_DEBUG,"WRITE DATA: %s", chr(data));
        !           311:                                if(!WriteFile(wrslot,&data,sizeof(BYTE),&retval,NULL)) {
        !           312:                                        lprintf(LOG_ERR,"!VDD_WRITE: WriteFile Error %d (size=%d)"
        !           313:                                                ,GetLastError(),retval);
        !           314:                                } else {
        !           315:                                        assert_interrupt(UART_IER_TX_EMPTY);
        !           316:                                        reset_yield();
        !           317:                                }
        !           318:                        }
        !           319:                        break;
        !           320:                case UART_IER:
        !           321:                        if(uart_lcr_reg&UART_LCR_DLAB) {
        !           322:                                uart_divisor_latch_msb = data;
        !           323:                                lprintf(LOG_DEBUG,"set divisor latch high byte: %02X", data);
        !           324:                        } else
        !           325:                                uart_ier_reg = data;
        !           326:                        assert_interrupt(UART_IER_TX_EMPTY);    /* should this be re-asserted for all writes? */
        !           327:                        break;
        !           328:                case UART_IIR: /* FCR not supported */
        !           329:                        break;
        !           330:                case UART_LCR:
        !           331:                        uart_lcr_reg = data;
        !           332:                        break;
        !           333:                case UART_MCR:
        !           334:                        uart_mcr_reg = data;
        !           335:                        if((uart_mcr_reg&UART_MCR_DTR) == 0)    /* Dropping DTR (i.e. "hangup") */
        !           336:                                hangup();
        !           337:                        break;
        !           338:                case UART_SCRATCH:
        !           339:                        uart_scratch_reg = data;
        !           340:                        break;
        !           341:                default:
        !           342:                        lprintf(LOG_ERR,"UNSUPPORTED register: %u", reg);
        !           343:                        break;
        !           344:                        
        !           345:        }
        !           346: }
        !           347: 
        !           348: VOID uart_rdport(WORD port, PBYTE data)
        !           349: {
        !           350:        int reg = port - uart_io_base;
        !           351:        DWORD avail;
        !           352: 
        !           353:        lprintf(LOG_DEBUG,"read of port: %x (%s)", port, uart_reg_desc[reg]);
        !           354: 
        !           355:        switch(reg) {
        !           356:                case UART_BASE:
        !           357:                        if(uart_lcr_reg&UART_LCR_DLAB) {
        !           358:                                lprintf(LOG_DEBUG,"reading divisor latch LSB");
        !           359:                                *data = uart_divisor_latch_lsb;
        !           360:                                break;
        !           361:                        }
        !           362:                        if((avail=RingBufFull(&rdbuf))!=0) {
        !           363:                                vdd_read(data,sizeof(BYTE));
        !           364:                                lprintf(LOG_DEBUG,"READ DATA: %s", chr(*data));
        !           365:                                avail--;
        !           366:                                reset_yield();
        !           367:                        } else
        !           368:                                *data=0;
        !           369:                        if(avail==0) {
        !           370:                                lprintf(LOG_DEBUG,"No more data");
        !           371:                                /* Clear the data ready bit in the LSR */
        !           372:                                uart_lsr_reg &= ~UART_LSR_DATA_READY;
        !           373: 
        !           374:                                /* Clear data ready interrupt identification in IIR */
        !           375:                                deassert_interrupt(UART_IER_RX_DATA);
        !           376:                        } else  /* re-assert RX data (increment the semaphore) */
        !           377:                                assert_interrupt(UART_IER_RX_DATA);
        !           378:                        break;
        !           379:                case UART_IER:
        !           380:                        if(uart_lcr_reg&UART_LCR_DLAB) {
        !           381:                                lprintf(LOG_DEBUG,"reading divisor latch MSB");
        !           382:                                *data = uart_divisor_latch_msb;
        !           383:                        } else
        !           384:                                *data = uart_ier_reg;
        !           385:                        break;
        !           386:                case UART_IIR:
        !           387:                        /* Report IIR based on *priority* of pending interrupts */
        !           388:                        if(pending_interrupts & UART_IER_LINE_STATUS)
        !           389:                                *data = UART_IIR_LINE_STATUS;
        !           390:                        else if(pending_interrupts & UART_IER_RX_DATA)
        !           391:                                *data = UART_IIR_RX_DATA;
        !           392:                        else if(pending_interrupts & UART_IER_TX_EMPTY) {
        !           393:                                *data = UART_IIR_TX_EMPTY;
        !           394:                                /* "Transmit Holding Register Empty" interrupt */
        !           395:                                /*  is reset on read of IIR */
        !           396:                                deassert_interrupt(UART_IER_TX_EMPTY);
        !           397:                        }
        !           398:                        else if(pending_interrupts & UART_IER_MODEM_STATUS)
        !           399:                                *data = UART_IIR_MODEM_STATUS;
        !           400:                        else
        !           401:                                *data = UART_IIR_NONE;
        !           402:                        break;
        !           403:                case UART_LCR:
        !           404:                        *data = uart_lcr_reg;
        !           405:                        break;
        !           406:                case UART_MCR:
        !           407:                        *data = uart_mcr_reg;
        !           408:                        break;
        !           409:                case UART_LSR:
        !           410:                        *data = uart_lsr_reg;
        !           411:                        maybe_yield();
        !           412:                        /* Clear line status interrupt pending */
        !           413:                        deassert_interrupt(UART_IER_LINE_STATUS);
        !           414:                        break;
        !           415:                case UART_MSR:
        !           416:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
        !           417:                                uart_msr_reg &=~ UART_MSR_DCD;
        !           418:                        else
        !           419:                                uart_msr_reg |= UART_MSR_DCD;
        !           420:                        *data = uart_msr_reg;
        !           421:                        maybe_yield();
        !           422:                        /* Clear modem status interrupt pending */
        !           423:                        deassert_interrupt(UART_IER_MODEM_STATUS);
        !           424:                        break;
        !           425:                case UART_SCRATCH:
        !           426:                        *data = uart_scratch_reg;
        !           427:                        break;
        !           428:                default:
        !           429:                        lprintf(LOG_ERR,"UNSUPPORTED register: %u", reg);
        !           430:                        break;
        !           431:        }
        !           432: 
        !           433:        if(reg!=UART_BASE)
        !           434:                lprintf(LOG_DEBUG, "returning 0x%02X", *data);
        !           435: }
        !           436: 
        !           437: /* VDD DOS Interface (mainly for FOSSIL driver in dosxtrn.exe) */
        !           438: 
        !           439: __declspec(dllexport) void __cdecl VDDDispatch(void) 
        !           440: {
        !           441:        char                    str[512];
        !           442:        DWORD                   count;
        !           443:        DWORD                   msgs;
        !           444:        int                             retval;
        !           445:        int                             node_num;
        !           446:        BYTE*                   p;
        !           447:        vdd_status_t*   status;
        !           448:        static  DWORD   writes;
        !           449:        static  DWORD   bytes_written;
        !           450:        static  DWORD   reads;
        !           451:        static  DWORD   bytes_read;
        !           452:        static  DWORD   inbuf_poll;
        !           453:        static  DWORD   online_poll;
        !           454:        static  DWORD   status_poll;
        !           455:        static  DWORD   vdd_yields;
        !           456:        static  DWORD   vdd_calls;
        !           457:        VDD_IO_HANDLERS  IOHandlers = { NULL };
        !           458:        static VDD_IO_PORTRANGE PortRange;
        !           459: 
        !           460:        retval=0;
        !           461:        node_num=getBH();
        !           462: 
        !           463:        lprintf(LOG_DEBUG,"VDD_OP: (handle=%d) %d (arg=%X)", getAX(),getBL(),getCX());
        !           464:        vdd_calls++;
        !           465: 
        !           466:        switch(getBL()) {
        !           467: 
        !           468:                case VDD_OPEN:
        !           469: 
        !           470:                        sscanf("$Revision: 1.38 $", "%*s %s", revision);
        !           471: 
        !           472:                        lprintf(LOG_INFO,"Synchronet Virtual Device Driver, rev %s %s %s"
        !           473:                                ,revision, __DATE__, __TIME__);
        !           474: #if 0
        !           475:                        sprintf(str,"sbbsexec%d.log",node_num);
        !           476:                        fp=fopen(str,"wb");
        !           477: #endif
        !           478: 
        !           479:                        sprintf(str,"\\\\.\\mailslot\\sbbsexec\\wr%d",node_num);
        !           480:                        rdslot=CreateMailslot(str
        !           481:                                ,LINEAR_RX_BUFLEN               /* Max message size (0=any) */
        !           482:                                ,MAILSLOT_WAIT_FOREVER  /* Read timeout */
        !           483:                                ,NULL);
        !           484:                        if(rdslot==INVALID_HANDLE_VALUE) {
        !           485:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
        !           486:                                        ,GetLastError(),str);
        !           487:                                retval=1;
        !           488:                                break;
        !           489:                        }
        !           490: 
        !           491:                        sprintf(str,"\\\\.\\mailslot\\sbbsexec\\rd%d",node_num);
        !           492:                        wrslot=CreateFile(str
        !           493:                                ,GENERIC_WRITE
        !           494:                                ,FILE_SHARE_READ
        !           495:                                ,NULL
        !           496:                                ,OPEN_EXISTING
        !           497:                                ,FILE_ATTRIBUTE_NORMAL
        !           498:                                ,(HANDLE) NULL);
        !           499:                        if(wrslot==INVALID_HANDLE_VALUE) {
        !           500:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
        !           501:                                        ,GetLastError(),str);
        !           502:                                retval=2;
        !           503:                                break;
        !           504:                        }
        !           505: 
        !           506:                        if(RingBufInit(&rdbuf, RINGBUF_SIZE_IN)!=0) {
        !           507:                                retval=3;
        !           508:                                break;
        !           509:                        }
        !           510: 
        !           511:                        sprintf(str,"sbbsexec_hungup%d",node_num);
        !           512:                        hungup_event=OpenEvent(
        !           513:                                EVENT_ALL_ACCESS,       /* access flag  */
        !           514:                                FALSE,                          /* inherit flag  */
        !           515:                                str);                           /* pointer to event-object name  */
        !           516:                        if(hungup_event==NULL) {
        !           517:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
        !           518:                                        ,GetLastError(),str);
        !           519:                                retval=4;
        !           520:                                break;
        !           521:                        }
        !           522: 
        !           523:                        sprintf(str,"sbbsexec_hangup%d",node_num);
        !           524:                        hangup_event=OpenEvent(
        !           525:                                EVENT_ALL_ACCESS,       /* access flag  */
        !           526:                                FALSE,                          /* inherit flag  */
        !           527:                                str);                           /* pointer to event-object name  */
        !           528:                        if(hangup_event==NULL) {
        !           529:                                lprintf(LOG_WARNING,"!VDD_OPEN: Error %d opening %s"
        !           530:                                        ,GetLastError(),str);
        !           531:                        }
        !           532: 
        !           533:                        status_poll=0;
        !           534:                        inbuf_poll=0;
        !           535:                        online_poll=0;
        !           536:                        yields=0;
        !           537: 
        !           538:                        lprintf(LOG_INFO,"Yield interval: %f milliseconds", yield_interval);
        !           539: 
        !           540:                        if(virtualize_uart) {
        !           541:                                lprintf(LOG_INFO,"Virtualizing UART (0x%x, IRQ %u)"
        !           542:                                        ,uart_io_base, uart_irq);
        !           543: 
        !           544:                                IOHandlers.inb_handler = uart_rdport;
        !           545:                                IOHandlers.outb_handler = uart_wrport;
        !           546:                                PortRange.First=uart_io_base;
        !           547:                                PortRange.Last=uart_io_base + UART_IO_RANGE;
        !           548: 
        !           549:                                VDDInstallIOHook((HANDLE)getAX(), 1, &PortRange, &IOHandlers);
        !           550: 
        !           551:                                interrupt_event=CreateEvent(NULL,FALSE,FALSE,NULL);
        !           552:                                InitializeCriticalSection(&interrupt_mutex);
        !           553: 
        !           554:                                _beginthread(interrupt_thread, 0, NULL);
        !           555:                        }
        !           556: 
        !           557:                        lprintf(LOG_DEBUG,"VDD_OPEN: Opened successfully");
        !           558: 
        !           559:                        _beginthread(input_thread, 0, NULL);
        !           560: 
        !           561:                        retval=0;
        !           562:                        break;
        !           563: 
        !           564:                case VDD_CLOSE:
        !           565:                        lprintf(LOG_INFO,"VDD_CLOSE: rdbuf=%u "
        !           566:                                "status_poll=%u inbuf_poll=%u online_poll=%u yields=%u vdd_yields=%u vdd_calls=%u"
        !           567:                                ,RingBufFull(&rdbuf),status_poll,inbuf_poll,online_poll
        !           568:                                ,yields,vdd_yields,vdd_calls);
        !           569:                        lprintf(LOG_INFO,"           read=%u bytes (in %u calls)",bytes_read,reads);
        !           570:                        lprintf(LOG_INFO,"           wrote=%u bytes (in %u calls)",bytes_written,writes);
        !           571: 
        !           572:                        if(virtualize_uart) {
        !           573:                                lprintf(LOG_INFO,"Uninstalling Virtualizaed UART IO Hook");
        !           574:                                VDDDeInstallIOHook((HANDLE)getAX(), 1, &PortRange);
        !           575:                        }
        !           576: 
        !           577:                        CloseHandle(rdslot);
        !           578:                        CloseHandle(wrslot);
        !           579:                        if(hungup_event!=NULL)
        !           580:                                CloseHandle(hungup_event);
        !           581:                        if(hangup_event!=NULL)
        !           582:                                CloseHandle(hangup_event);
        !           583: 
        !           584: #if 0  /* This isn't strictly necessary... 
        !           585:                   and possibly the cause of a NULL dereference in the input_thread */
        !           586:                        RingBufDispose(&rdbuf);
        !           587: #endif
        !           588:                        status_poll=0;
        !           589:                        retval=0;
        !           590: 
        !           591:                        break;
        !           592: 
        !           593:                case VDD_READ:
        !           594:                        count = getCX();
        !           595:                        if(count != 1)
        !           596:                                lprintf(LOG_DEBUG,"VDD_READ of %d",count);
        !           597:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           598:                                ,count,FALSE); 
        !           599:                        retval=vdd_read(p, count);
        !           600:                        reads++;
        !           601:                        bytes_read+=retval;
        !           602:                        reset_yield();
        !           603:                        break;
        !           604: 
        !           605:                case VDD_PEEK:
        !           606:                        count = getCX();
        !           607:                        if(count != 1)
        !           608:                                lprintf(LOG_DEBUG,"VDD_PEEK of %d",count);
        !           609: 
        !           610:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           611:                                ,count,FALSE); 
        !           612:                        retval=RingBufPeek(&rdbuf,p,count);
        !           613:                        reset_yield();
        !           614:                        break;
        !           615: 
        !           616:                case VDD_WRITE:
        !           617:                        count = getCX();
        !           618:                        if(count != 1)
        !           619:                                lprintf(LOG_DEBUG,"VDD_WRITE of %d",count);
        !           620:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           621:                                ,count,FALSE); 
        !           622:                        if(!WriteFile(wrslot,p,count,&retval,NULL)) {
        !           623:                                lprintf(LOG_ERR,"!VDD_WRITE: WriteFile Error %d (size=%d)"
        !           624:                                        ,GetLastError(),retval);
        !           625:                                retval=0;
        !           626:                        } else {
        !           627:                                writes++;
        !           628:                                bytes_written+=retval;
        !           629:                                reset_yield();
        !           630:                        }
        !           631:                        break;
        !           632: 
        !           633:                case VDD_STATUS:
        !           634: 
        !           635:                        status_poll++;
        !           636:                        count = getCX();
        !           637:                        if(count != sizeof(vdd_status_t)) {
        !           638:                                lprintf(LOG_DEBUG,"!VDD_STATUS: wrong size (%d!=%d)",count,sizeof(vdd_status_t));
        !           639:                                retval=sizeof(vdd_status_t);
        !           640:                                break;
        !           641:                        }
        !           642:                        status = (vdd_status_t*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           643:                                ,count,FALSE); 
        !           644: 
        !           645:                        status->inbuf_full=RingBufFull(&rdbuf);
        !           646: 
        !           647:                        /* OUTBUF FULL/SIZE */
        !           648:                        if(!GetMailslotInfo(
        !           649:                                wrslot,                                 /* mailslot handle  */
        !           650:                                &status->outbuf_size,   /* address of maximum message size  */
        !           651:                                &status->outbuf_full,   /* address of size of next message  */
        !           652:                                &msgs,                                  /* address of number of messages  */
        !           653:                                NULL                                    /* address of read time-out  */
        !           654:                                )) {
        !           655:                                status->outbuf_full=0;
        !           656:                                status->outbuf_size=DEFAULT_MAX_MSG_SIZE;
        !           657:                        }
        !           658:                        if(status->outbuf_full==MAILSLOT_NO_MESSAGE)
        !           659:                                status->outbuf_full=0;
        !           660:                        status->outbuf_full*=msgs;
        !           661:                        
        !           662:                        /* ONLINE */
        !           663:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
        !           664:                                status->online=0;
        !           665:                        else
        !           666:                                status->online=1;
        !           667: 
        !           668:                        retval=0;       /* success */
        !           669:                        break;
        !           670: 
        !           671:                case VDD_INBUF_PURGE:
        !           672:                        RingBufReInit(&rdbuf);
        !           673:                        retval=0;
        !           674:                        break;
        !           675: 
        !           676:                case VDD_OUTBUF_PURGE:
        !           677:                        lprintf(LOG_WARNING,"!VDD_OUTBUF_PURGE: NOT IMPLEMENTED");
        !           678:                        retval=0;
        !           679:                        break;
        !           680: 
        !           681:                case VDD_INBUF_FULL:
        !           682:                        retval=RingBufFull(&rdbuf);
        !           683:                        inbuf_poll++;
        !           684:                        break;
        !           685: 
        !           686:                case VDD_INBUF_SIZE:
        !           687:                        retval=RINGBUF_SIZE_IN;
        !           688:                        break;
        !           689: 
        !           690:                case VDD_OUTBUF_FULL:
        !           691:                        if(!GetMailslotInfo(
        !           692:                                wrslot,         /* mailslot handle  */
        !           693:                                NULL,           /* address of maximum message size  */
        !           694:                                &retval,        /* address of size of next message  */
        !           695:                                &msgs,          /* address of number of messages  */
        !           696:                                NULL            /* address of read time-out  */
        !           697:                                ))
        !           698:                                retval=0;
        !           699:                        if(retval==MAILSLOT_NO_MESSAGE)
        !           700:                                retval=0;
        !           701:                        retval*=msgs;
        !           702:                        break;
        !           703: 
        !           704:                case VDD_OUTBUF_SIZE:
        !           705:                        if(!GetMailslotInfo(
        !           706:                                wrslot,         /* mailslot handle  */
        !           707:                                &retval,        /* address of maximum message size  */
        !           708:                                NULL,           /* address of size of next message  */
        !           709:                                NULL,           /* address of number of messages  */
        !           710:                                NULL            /* address of read time-out  */
        !           711:                                )) 
        !           712:                                retval=DEFAULT_MAX_MSG_SIZE;
        !           713:                        break;
        !           714: 
        !           715:                case VDD_ONLINE:
        !           716:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
        !           717:                                retval=0;
        !           718:                        else
        !           719:                                retval=1;
        !           720:                        online_poll++;
        !           721:                        break;
        !           722: 
        !           723:                case VDD_YIELD:                 /* forced yield */
        !           724:                        vdd_yields++;
        !           725:                        yield();
        !           726:                        break;
        !           727: 
        !           728:                case VDD_MAYBE_YIELD:   /* yield if YieldInterval is enabled and expired */
        !           729:                        maybe_yield();
        !           730:                        break;
        !           731: 
        !           732:                case VDD_LOAD_INI_FILE: /* Load and parse settings file */
        !           733:                        {
        !           734:                                FILE*   fp;
        !           735:                                char    cwd[MAX_PATH+1];
        !           736: 
        !           737:                                /* Load exec/sbbsexec.ini first (setting default values) */
        !           738:                                count = getCX();
        !           739:                                p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           740:                                        ,count,FALSE); 
        !           741:                                iniFileName(ini_fname, sizeof(ini_fname), p, INI_FILENAME);
        !           742:                                if((fp=fopen(ini_fname,"r"))!=NULL) {
        !           743:                                        ini=iniReadFile(fp);
        !           744:                                        fclose(fp);
        !           745:                                        parse_ini(ROOT_SECTION);
        !           746:                                }
        !           747: 
        !           748:                                /* Load cwd/sbbsexec.ini second (over-riding default values) */
        !           749:                                GetCurrentDirectory(sizeof(cwd),cwd);
        !           750:                                iniFileName(ini_fname, sizeof(ini_fname), cwd, INI_FILENAME);
        !           751:                                if((fp=fopen(ini_fname,"r"))!=NULL) {
        !           752:                                        ini=iniReadFile(fp);
        !           753:                                        fclose(fp);
        !           754:                                        parse_ini(ROOT_SECTION);
        !           755:                                }
        !           756:                        }
        !           757:                        break;
        !           758: 
        !           759:                case VDD_LOAD_INI_SECTION:      /* Parse (program-specific) sub-section of settings file */
        !           760:                        count = getCX();
        !           761:                        p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           762:                                ,count,FALSE); 
        !           763:                        parse_ini(p);
        !           764:                        break;
        !           765: 
        !           766:                case VDD_DEBUG_OUTPUT:  /* Send string to debug output */
        !           767:                        count = getCX();
        !           768:                        p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
        !           769:                                ,count,FALSE); 
        !           770:                        lputs(LOG_INFO, p);
        !           771:                        break;
        !           772: 
        !           773:                case VDD_HANGUP:
        !           774:                        hangup();
        !           775:                        break;
        !           776: 
        !           777:                default:
        !           778:                        lprintf(LOG_ERR,"!UNKNOWN VDD_OP: %d",getBL());
        !           779:                        break;
        !           780:        }
        !           781:        setAX((WORD)retval);
        !           782: }

unix.superglobalmegacorp.com

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