|
|
1.1 ! root 1: /* dosxtrn.c */ ! 2: ! 3: /* Synchronet External DOS Program Launcher (16-bit MSVC 1.52c project) */ ! 4: ! 5: /* $Id: dosxtrn.c,v 1.23 2006/10/28 03:54:09 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 <stdio.h> ! 39: #include <stdlib.h> ! 40: #include <string.h> ! 41: #include <process.h> ! 42: #include <dos.h> /* _dos_set/getvect() */ ! 43: #include <windows.h> /* BOOL, etc. */ ! 44: #include "vdd_func.h" ! 45: #include "execvxd.h" ! 46: #include "isvbop.h" /* ddk\inc */ ! 47: #include "fossdefs.h" ! 48: ! 49: #define VDD_FILENAME "sbbsexec.dll" ! 50: ! 51: /****************************************************************************/ ! 52: /* Truncates white-space chars off end of 'str' and terminates at first tab */ ! 53: /****************************************************************************/ ! 54: static void truncsp(char *str) ! 55: { ! 56: size_t c; ! 57: ! 58: str[strcspn(str,"\t")]=0; ! 59: c=strlen(str); ! 60: while(c && (unsigned char)str[c-1]<=' ') c--; ! 61: str[c]=0; ! 62: } ! 63: short vdd=0; ! 64: BYTE node_num=0; ! 65: int mode=0; ! 66: int revision; ! 67: char id_string[128]; ! 68: #ifdef DEBUG_INT_CALLS ! 69: ulong int14calls=0; ! 70: ulong int16calls=0; ! 71: ulong int21calls=0; ! 72: ulong int29calls=0; ! 73: #endif ! 74: ! 75: void (interrupt *oldint14)(); ! 76: void (interrupt *oldint16)(); ! 77: void (interrupt *oldint21)(); ! 78: void (interrupt *oldint29)(); ! 79: ! 80: ! 81: static int vdd_buf(BYTE op, int count, WORD buf_seg, WORD buf_off) ! 82: { ! 83: int retval; ! 84: ! 85: _asm { ! 86: push bx ! 87: push cx ! 88: push es ! 89: push di ! 90: mov ax, vdd ! 91: mov bh, node_num ! 92: mov bl, op ! 93: mov cx, count ! 94: mov es, buf_seg ! 95: mov di, buf_off ! 96: } ! 97: DispatchCall(); ! 98: _asm { ! 99: mov retval, ax ! 100: pop di ! 101: pop es ! 102: pop cx ! 103: pop bx ! 104: } ! 105: return(retval); ! 106: } ! 107: ! 108: static int vdd_str(BYTE op, char* str) ! 109: { ! 110: WORD buf_seg; ! 111: ! 112: _asm mov buf_seg, ss; ! 113: return vdd_buf(op, strlen(str), buf_seg, (WORD)str); ! 114: } ! 115: ! 116: static int vdd_op(BYTE op) ! 117: { ! 118: int retval; ! 119: ! 120: #if FALSE /* disable yield? */ ! 121: if(op==VDD_YIELD) ! 122: return(0); ! 123: #endif ! 124: _asm { ! 125: push bx ! 126: mov ax, vdd ! 127: mov bh, node_num ! 128: mov bl, op ! 129: } ! 130: DispatchCall(); ! 131: _asm { ! 132: mov retval, ax ! 133: pop bx ! 134: } ! 135: return(retval); ! 136: } ! 137: ! 138: union REGS inregs; ! 139: struct SREGS sregs; ! 140: BOOL inside_int14=FALSE; ! 141: ! 142: /* This function is only necessary for naughty programs that call the vector ! 143: directly instead of issuing an interrupt ! 144: */ ! 145: void interrupt win95int14( ! 146: unsigned _es, unsigned _ds, ! 147: unsigned _di, unsigned _si, ! 148: unsigned _bp, unsigned _sp, ! 149: unsigned _bx, unsigned _dx, ! 150: unsigned _cx, unsigned _ax, ! 151: unsigned flags ) ! 152: { ! 153: union REGS outregs; ! 154: ! 155: /* prevent recursion, just incase the VXD isn't handling int14h */ ! 156: if(inside_int14) ! 157: return; ! 158: ! 159: inside_int14=TRUE; ! 160: ! 161: inregs.x.ax=_ax; ! 162: inregs.x.bx=_bx; ! 163: inregs.x.cx=_cx; ! 164: inregs.x.dx=_dx; ! 165: inregs.x.si=_si; ! 166: inregs.x.di=_di; ! 167: inregs.x.cflag=flags; ! 168: ! 169: sregs.es=_es; ! 170: sregs.ds=_ds; ! 171: ! 172: int86x(0x14,&inregs,&outregs,&sregs); ! 173: ! 174: /* FOSSIL driver only touches these AX and BX */ ! 175: _ax= outregs.x.ax; ! 176: _bx= outregs.x.bx; ! 177: ! 178: inside_int14=FALSE; ! 179: } ! 180: ! 181: void vdd_getstatus(vdd_status_t* status) ! 182: { ! 183: WORD buf_seg; ! 184: ! 185: _asm mov buf_seg, ss; ! 186: if(vdd_buf(VDD_STATUS, sizeof(vdd_status_t), buf_seg, (WORD)status)!=0) ! 187: memset(status,0,sizeof(vdd_status_t)); ! 188: } ! 189: ! 190: WORD PortStatus() ! 191: { ! 192: WORD status=0x0008; /* AL bit 3 (change in DCD) always set */ ! 193: vdd_status_t vdd_status; ! 194: ! 195: vdd_getstatus(&vdd_status); ! 196: ! 197: if(vdd_status.online) /* carrier detect */ ! 198: status|=0x0080; /* DCD */ ! 199: ! 200: if(vdd_status.inbuf_full) /* receive data ready */ ! 201: status|=0x0100; /* RDA */ ! 202: ! 203: /* if(vm->overrun) /* overrun error detected */ ! 204: /* status|=0x0200; /* OVRN */ ! 205: ! 206: if(vdd_status.outbuf_full ! 207: <vdd_status.outbuf_size/2) /* room available in output buffer */ ! 208: status|=0x2000; /* THRE */ ! 209: ! 210: if(!vdd_status.outbuf_full) /* output buffer is empty */ ! 211: status|=0x4000; /* TSRE */ ! 212: ! 213: return(status); ! 214: } ! 215: ! 216: #ifdef DEBUG_FOSSIL_CALLS ! 217: DWORD fossil_calls[0x100]; ! 218: #endif ! 219: ! 220: void interrupt winNTint14( ! 221: unsigned _es, unsigned _ds, ! 222: unsigned _di, unsigned _si, ! 223: unsigned _bp, unsigned _sp, ! 224: unsigned _bx, unsigned _dx, ! 225: unsigned _cx, unsigned _ax, ! 226: ) ! 227: { ! 228: BYTE ch; ! 229: BYTE far* p; ! 230: WORD buf_seg; ! 231: int wr; ! 232: vdd_status_t vdd_status; ! 233: fossil_info_t info = { ! 234: sizeof(info) ! 235: ,FOSSIL_REVISION ! 236: ,revision /* driver revision */ ! 237: ,0 /* ID string pointer */ ! 238: ,0,0 /* receive buffer size/free (overwritten later) */ ! 239: ,0,0 /* transmit buffer size/free (overwritten later) */ ! 240: ,80,25 /* screen dimensions (cols, rows) */ ! 241: /* port settings (i.e. 38400 N-8-1): */ ! 242: ,FOSSIL_BAUD_RATE_38400 ! 243: |FOSSIL_PARITY_NONE ! 244: |FOSSIL_DATA_BITS_8 ! 245: |FOSSIL_STOP_BITS_1 ! 246: }; ! 247: ! 248: #ifdef DEBUG_INT_CALLS ! 249: int14calls++; ! 250: #endif ! 251: ! 252: #ifdef DEBUG_FOSSIL_CALLS ! 253: fossil_calls[_ax>>8]++; ! 254: #endif ! 255: ! 256: switch(_ax>>8) { ! 257: case FOSSIL_FUNC_SET_RATE: /* Initialize/Set baud rate */ ! 258: _ax = PortStatus(); ! 259: break; ! 260: case FOSSIL_FUNC_PUT_CHAR: /* write char to com port, with wait */ ! 261: ch=_ax&0xff; ! 262: _asm mov buf_seg, ss; ! 263: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch); ! 264: _ax = PortStatus(); ! 265: break; ! 266: case FOSSIL_FUNC_GET_CHAR: /* read char from com port, with wait */ ! 267: _asm mov buf_seg, ss; ! 268: _ax = vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch); ! 269: if(!_ax) { ! 270: _ax = 0x8000; /* timed-out */ ! 271: vdd_op(VDD_YIELD); ! 272: } else { ! 273: _ax = ch; ! 274: } ! 275: break; ! 276: case FOSSIL_FUNC_GET_STATUS: /* request status */ ! 277: _ax=PortStatus(); ! 278: if(_ax==0x6088) ! 279: vdd_op(VDD_MAYBE_YIELD); ! 280: break; ! 281: case FOSSIL_FUNC_INIT: /* initialize */ ! 282: _ax=FOSSIL_SIGNATURE; /* magic number = success */ ! 283: _bx=FOSSIL_REVISION<<8 | FOSSIL_FUNC_HIGHEST; /* FOSSIL rev/maximum FOSSIL func supported */ ! 284: break; ! 285: case FOSSIL_FUNC_DTR: ! 286: if((_ax&0xff)==0) /* Lower DTR */ ! 287: vdd_op(VDD_HANGUP); ! 288: break; ! 289: case FOSSIL_FUNC_FLUSH_OUT: /* flush output buffer */ ! 290: break; ! 291: case FOSSIL_FUNC_PURGE_OUT: /* purge output buffer */ ! 292: vdd_op(VDD_OUTBUF_PURGE); ! 293: break; ! 294: case FOSSIL_FUNC_PURGE_IN: /* purge input buffer */ ! 295: vdd_op(VDD_INBUF_PURGE); ! 296: break; ! 297: case FOSSIL_FUNC_WRITE_CHAR: /* write char to com port, no wait */ ! 298: if(0 /*RingBufFree(&vm->out)<2 */) { ! 299: _ax=0; /* char was not accepted */ ! 300: break; ! 301: } ! 302: ch=_ax&0xff; ! 303: _asm mov buf_seg, ss; ! 304: _ax = vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch); ! 305: break; ! 306: case FOSSIL_FUNC_PEEK: /* non-destructive read-ahead */ ! 307: vdd_getstatus(&vdd_status); ! 308: if(!vdd_status.inbuf_full) { ! 309: _ax=0xffff; /* no char available */ ! 310: vdd_op(VDD_YIELD); ! 311: break; ! 312: } ! 313: _asm mov buf_seg, ss; ! 314: _ax = vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch); ! 315: if(_ax == 0) ! 316: vdd_op(VDD_YIELD); ! 317: break; ! 318: case FOSSIL_FUNC_READ_BLOCK: /* read block, no wait */ ! 319: vdd_getstatus(&vdd_status); ! 320: if(!vdd_status.inbuf_full) ! 321: _ax = 0; /* no data available */ ! 322: else ! 323: _ax = vdd_buf(VDD_READ, _cx, _es, _di); ! 324: if(_ax == 0) ! 325: vdd_op(VDD_YIELD); ! 326: break; ! 327: case FOSSIL_FUNC_WRITE_BLOCK: /* write block, no wait */ ! 328: _ax = vdd_buf(VDD_WRITE, _cx, _es, _di); ! 329: break; ! 330: case FOSSIL_FUNC_GET_INFO: /* driver info */ ! 331: vdd_getstatus(&vdd_status); ! 332: info.inbuf_size=vdd_status.inbuf_size; ! 333: info.inbuf_free=info.inbuf_size-vdd_status.inbuf_full; ! 334: info.outbuf_size=vdd_status.outbuf_size; ! 335: info.outbuf_free=info.outbuf_size-vdd_status.outbuf_full; ! 336: info.id_string = id_string; ! 337: ! 338: if(vdd_status.inbuf_full==vdd_status.outbuf_full==0) ! 339: vdd_op(VDD_MAYBE_YIELD); ! 340: ! 341: p = _MK_FP(_es,_di); ! 342: wr=sizeof(info); ! 343: if(wr>_cx) ! 344: wr=_cx; ! 345: _fmemcpy(p, &info, wr); ! 346: _ax=wr; ! 347: break; ! 348: } ! 349: } ! 350: ! 351: void int14stub(void) ! 352: { ! 353: /* This function will be overwritten later (during runtime) with FOSSIL signature */ ! 354: } ! 355: ! 356: void interrupt winNTint16( ! 357: unsigned _es, unsigned _ds, ! 358: unsigned _di, unsigned _si, ! 359: unsigned _bp, unsigned _sp, ! 360: unsigned _bx, unsigned _dx, ! 361: unsigned _cx, unsigned _ax, ! 362: unsigned _ip, unsigned _cs, ! 363: unsigned flags ) ! 364: { ! 365: BYTE ch; ! 366: WORD buf_seg; ! 367: vdd_status_t status; ! 368: ! 369: #ifdef DEBUG_INT_CALLS ! 370: int16calls++; ! 371: #endif ! 372: ! 373: vdd_getstatus(&status); ! 374: switch(_ax>>8) { ! 375: case 0x00: /* Read char from keyboard */ ! 376: case 0x10: /* Read char from enhanced keyboard */ ! 377: if(status.inbuf_full) { ! 378: _asm mov buf_seg, ss; ! 379: vdd_buf(VDD_READ, 1, buf_seg, (WORD)&ch); ! 380: _ax=ch; ! 381: return; ! 382: } ! 383: vdd_op(VDD_MAYBE_YIELD); ! 384: break; ! 385: case 0x01: /* Get keyboard status */ ! 386: case 0x11: /* Get enhanced keyboard status */ ! 387: if(status.inbuf_full) { ! 388: _asm mov buf_seg, ss; ! 389: vdd_buf(VDD_PEEK, 1, buf_seg, (WORD)&ch); ! 390: flags&=~(1<<6); /* clear zero flag */ ! 391: _ax=ch; ! 392: return; ! 393: } ! 394: vdd_op(VDD_MAYBE_YIELD); ! 395: break; ! 396: } ! 397: ! 398: _chain_intr(oldint16); ! 399: } ! 400: ! 401: #ifdef DEBUG_DOS_CALLS ! 402: DWORD dos_calls[0x100]; ! 403: #endif ! 404: ! 405: void interrupt winNTint21( ! 406: unsigned _es, unsigned _ds, ! 407: unsigned _di, unsigned _si, ! 408: unsigned _bp, unsigned _sp, ! 409: unsigned _bx, unsigned _dx, ! 410: unsigned _cx, unsigned _ax, ! 411: ) ! 412: { ! 413: #ifdef DEBUG_INT_CALLS ! 414: int21calls++; ! 415: #endif ! 416: if(_ax>>8 == 0x2c) /* GET_SYSTEM_TIME */ ! 417: vdd_op(VDD_MAYBE_YIELD); ! 418: #ifdef DEBUG_DOS_CALLS ! 419: dos_calls[_ax>>8]++; ! 420: #endif ! 421: _chain_intr(oldint21); ! 422: } ! 423: ! 424: void interrupt winNTint29( ! 425: unsigned _es, unsigned _ds, ! 426: unsigned _di, unsigned _si, ! 427: unsigned _bp, unsigned _sp, ! 428: unsigned _bx, unsigned _dx, ! 429: unsigned _cx, unsigned _ax, ! 430: ) ! 431: { ! 432: char ch; ! 433: WORD buf_seg; ! 434: #ifdef DEBUG_INT_CALLS ! 435: int29calls++; ! 436: #endif ! 437: ! 438: ch=_ax&0xff; ! 439: _asm mov buf_seg, ss ! 440: vdd_buf(VDD_WRITE, 1, buf_seg, (WORD)&ch); ! 441: ! 442: _chain_intr(oldint29); ! 443: } ! 444: ! 445: /****************************************************************************/ ! 446: /* Return the filename portion of a full pathname */ ! 447: /****************************************************************************/ ! 448: char* getfname(const char* path) ! 449: { ! 450: const char* fname; ! 451: const char* bslash; ! 452: ! 453: fname=strrchr(path,'/'); ! 454: bslash=strrchr(path,'\\'); ! 455: if(bslash>fname) ! 456: fname=bslash; ! 457: if(fname!=NULL) ! 458: fname++; ! 459: else ! 460: fname=(char*)path; ! 461: return((char*)fname); ! 462: } ! 463: ! 464: char * DllName =VDD_FILENAME; ! 465: char * InitFunc ="VDDInitialize"; ! 466: char * DispFunc ="VDDDispatch"; ! 467: ! 468: int main(int argc, char **argv) ! 469: { ! 470: char str[128]; ! 471: char cmdline[128],*p; ! 472: char dll[256]; ! 473: char exec_dir[128]; ! 474: char* envvar[10]; ! 475: char* arg[16]; ! 476: int i,c,d,envnum=0; ! 477: FILE* fp; ! 478: BOOL NT=FALSE; ! 479: BOOL success=FALSE; ! 480: WORD buf_seg; ! 481: WORD w; ! 482: ! 483: sscanf("$Revision: 1.23 $", "%*s 1.%u", &revision); ! 484: ! 485: sprintf(id_string,"Synchronet FOSSIL Driver (DOSXTRN) revision %u", revision); ! 486: if(argc<2) { ! 487: fprintf(stderr ! 488: ,"%s - Copyright %s Rob Swindell\n" ! 489: ,id_string, __DATE__+7); ! 490: fprintf(stderr ! 491: ,"usage: dosxtrn <path/dosxtrn.env> [NT|95] [node_num] [mode]\n"); ! 492: return(1); ! 493: } ! 494: ! 495: sprintf(exec_dir,"%.*s",sizeof(exec_dir)-1,argv[0]); ! 496: p=getfname(exec_dir); ! 497: *p=0; ! 498: sprintf(dll,"%s%s",exec_dir,VDD_FILENAME); ! 499: DllName=dll; ! 500: ! 501: if(argc>2 && !strcmp(argv[2],"NT")) ! 502: NT=TRUE; ! 503: if(argc>3) ! 504: node_num=atoi(argv[3]); ! 505: if(argc>4) ! 506: mode=atoi(argv[4]); ! 507: ! 508: if((fp=fopen(argv[1],"r"))==NULL) { ! 509: fprintf(stderr,"!Error opening %s\n",argv[1]); ! 510: return(2); ! 511: } ! 512: ! 513: fgets(cmdline, sizeof(cmdline), fp); ! 514: truncsp(cmdline); ! 515: ! 516: arg[0]=cmdline; /* point to the beginning of the string */ ! 517: for(c=0,d=1;cmdline[c];c++) /* Break up command line */ ! 518: if(cmdline[c]==' ') { ! 519: cmdline[c]=0; /* insert nulls */ ! 520: arg[d++]=cmdline+c+1; /* point to the beginning of the next arg */ ! 521: } ! 522: arg[d]=0; ! 523: ! 524: while(!feof(fp)) { ! 525: if(!fgets(str, sizeof(str), fp)) ! 526: break; ! 527: truncsp(str); ! 528: if((envvar[envnum]=strdup(str))==NULL) { ! 529: fprintf(stderr,"!MALLOC ERROR\n"); ! 530: return(4); ! 531: } ! 532: _putenv(envvar[envnum++]); ! 533: } ! 534: fclose(fp); ! 535: ! 536: /* Save int14 handler */ ! 537: oldint14=_dos_getvect(0x14); ! 538: ! 539: /* Overwrite stub function */ ! 540: ((BYTE*)int14stub)[0] = 0xe9; /* jump (relative) */ ! 541: ((BYTE*)int14stub)[3] = 0x90; /* NOP */ ! 542: ((BYTE*)int14stub)[4] = 0x90; /* NOP */ ! 543: ((BYTE*)int14stub)[5] = 0x90; /* NOP */ ! 544: ((BYTE*)int14stub)[6] = FOSSIL_SIGNATURE&0xff; /* FOSSIL sig (LSB) */ ! 545: ((BYTE*)int14stub)[7] = FOSSIL_SIGNATURE>>8; /* FOSSIL sig (MSB) */ ! 546: ((BYTE*)int14stub)[8] = FOSSIL_FUNC_HIGHEST; /* FOSSIL highest func supported */ ! 547: ! 548: if(NT) { /* Windows NT/2000 */ ! 549: ! 550: for(i=0;i<2;i++) { ! 551: ! 552: /* Register VDD */ ! 553: _asm { ! 554: push es ! 555: push ds ! 556: pop es ! 557: mov si, DllName ; ds:si = dll name ! 558: mov di, InitFunc ; es:di = init routine ! 559: mov bx, DispFunc ; ds:bx = dispatch routine ! 560: #if 1 /* Vista work-around, apparently doesn't support an InitFunc (RegisterModule fails with AX=1) */ ! 561: xor di,di ! 562: mov es,di ! 563: #endif ! 564: ! 565: }; ! 566: RegisterModule(); ! 567: _asm { ! 568: mov vdd, ax ! 569: jc err ! 570: mov success, TRUE ! 571: err: ! 572: pop es ! 573: } ! 574: if(success) ! 575: break; ! 576: DllName=VDD_FILENAME; /* try again with no path (for Windows Vista) */ ! 577: } ! 578: if(!success) { ! 579: fprintf(stderr,"Error %d loading %s\n",vdd,DllName); ! 580: return(-1); ! 581: } ! 582: ! 583: #if 0 ! 584: fprintf(stderr,"vdd handle=%d\n",vdd); ! 585: fprintf(stderr,"mode=%d\n",mode); ! 586: #endif ! 587: vdd_str(VDD_LOAD_INI_FILE, exec_dir); ! 588: ! 589: vdd_str(VDD_LOAD_INI_SECTION, getfname(arg[0])); ! 590: ! 591: sprintf(str,"%s, rev %u, %s %s", __FILE__, revision, __DATE__, __TIME__); ! 592: vdd_str(VDD_DEBUG_OUTPUT, str); ! 593: ! 594: i=vdd_op(VDD_OPEN); ! 595: if(i) { ! 596: fprintf(stderr,"!VDD_OPEN ERROR: %d\n",i); ! 597: UnRegisterModule(); ! 598: return(-1); ! 599: } ! 600: oldint16=_dos_getvect(0x16); ! 601: oldint21=_dos_getvect(0x21); ! 602: oldint29=_dos_getvect(0x29); ! 603: if(mode==SBBSEXEC_MODE_FOSSIL) { ! 604: *(WORD*)((BYTE*)int14stub+1) = (WORD)winNTint14 - (WORD)&int14stub - 3; /* jmp offset */ ! 605: _dos_setvect(0x14,(void(interrupt *)())int14stub); ! 606: } ! 607: _dos_setvect(0x21,winNTint21); ! 608: if(mode&SBBSEXEC_MODE_DOS_IN) ! 609: _dos_setvect(0x16,winNTint16); ! 610: if(mode&SBBSEXEC_MODE_DOS_OUT) ! 611: _dos_setvect(0x29,winNTint29); ! 612: } ! 613: else if(mode==SBBSEXEC_MODE_FOSSIL) { /* Windows 95/98/Millennium */ ! 614: *(WORD*)((BYTE*)int14stub+1) = (WORD)win95int14 - (WORD)&int14stub - 3; /* jmp offset */ ! 615: _dos_setvect(0x14,(void(interrupt *)())int14stub); ! 616: } ! 617: ! 618: _heapmin(); ! 619: i=_spawnvp(_P_WAIT, arg[0], arg); ! 620: ! 621: p=argv[1]+(strlen(argv[1])-3); ! 622: strcpy(p,"RET"); ! 623: if((fp=fopen(argv[1],"w+"))==NULL) { ! 624: fprintf(stderr,"!Error opening %s\n",argv[1]); ! 625: return(3); ! 626: } ! 627: fprintf(fp,"%d",i); ! 628: ! 629: /* Restore original ISRs */ ! 630: _dos_setvect(0x14,oldint14); ! 631: ! 632: if(NT) { ! 633: vdd_op(VDD_CLOSE); ! 634: ! 635: _dos_setvect(0x16,oldint16); ! 636: _dos_setvect(0x21,oldint21); ! 637: _dos_setvect(0x29,oldint29); ! 638: ! 639: sprintf(str,"%s returned %d", arg[0], i); ! 640: vdd_str(VDD_DEBUG_OUTPUT, str); ! 641: ! 642: #ifdef DEBUG_INT_CALLS ! 643: sprintf(str,"int14h calls: %u", int14calls); vdd_str(VDD_DEBUG_OUTPUT, str); ! 644: sprintf(str,"int16h calls: %u", int16calls); vdd_str(VDD_DEBUG_OUTPUT, str); ! 645: sprintf(str,"int21h calls: %u", int21calls); vdd_str(VDD_DEBUG_OUTPUT, str); ! 646: sprintf(str,"int29h calls: %u", int29calls); vdd_str(VDD_DEBUG_OUTPUT, str); ! 647: #endif ! 648: #ifdef DEBUG_DOS_CALLS ! 649: for(i=0;i<0x100;i++) { ! 650: if(dos_calls[i]>100) { ! 651: sprintf(str,"int21h function %02X calls: %u\n" ! 652: ,i, dos_calls[i]); ! 653: vdd_str(VDD_DEBUG_OUTPUT, str); ! 654: } ! 655: } ! 656: #endif ! 657: #ifdef DEBUG_FOSSIL_CALLS ! 658: for(i=0;i<0x100;i++) { ! 659: if(fossil_calls[i]>0) { ! 660: sprintf(str,"int14h function %02X calls: %u" ! 661: ,i, fossil_calls[i]); ! 662: vdd_str(VDD_DEBUG_OUTPUT, str); } ! 663: } ! 664: #endif ! 665: ! 666: /* Unregister VDD */ ! 667: _asm mov ax, vdd; ! 668: UnRegisterModule(); ! 669: ! 670: } ! 671: ! 672: return(i); ! 673: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.