📄 dos2udip.c
字号:
return NULL; }static RealUDIVecRecPtr IPCFar * FindIntVect(){ RealUDIVecRecPtr IPCFar * VecP; union rec recognizer; InitRecognizer( &recognizer ); /* Try and find a vector that matches the passed in recognizer */ for (VecP = (RealUDIVecRecPtr IPCFar *)(REALPTR_TO_FARCPTR(0x60*4)); VecP <= (RealUDIVecRecPtr IPCFar *)(REALPTR_TO_FARCPTR(0x66*4)); VecP++) { if ((*VecP != REALNULL) && ((struct UDIVecRec IPCFar *) REALPTR_TO_FARCPTR(*VecP))->recognizer.l == recognizer.l) return VecP; } return NULL;}static void SetupEnvironment(void){#ifndef DOS386 /* if not DOS386, nothing to do except set up the pointer to TIPVecRec */ pTIPVecRec = &TIPVecRec;#else /* setup code for DOS386 */FARPTR dummyfp;REALPTR dummyrp;ULONG dummyint;REALPTR IPCFar *p;REALPTR ptr_dos_ext_psp;int err;int i; /************************************************************** * There are some initialization things that we might as well do before * we do the realcopy down below. Here we do some initialization * of TIPVecRec and the code_selector and data_selector and call_prot * routine address that are then used by the real mode code. ****************************************************************/ _dx_rmlink_get(&call_prot, &dummyrp, &dummyint, &dummyfp); code_selector = GetCS(); data_selector = GetDS(); for (i=0; i<4; i++) segregblock[i] = data_selector; /****************************************************** * Map first 1 meg of physical memory into our ds: address space * This is 256 4K pages starting at physical address 0. * The pointer conventional_memory is its mapped offset in our data space * If this mapping cannot be done (because we are running under DPMI 0.90) * then we will have to access dos memory using far pointers and do some * copies of data down in the d386 routines. ********************************************************/ err = _dx_map_phys(data_selector, (ULONG) 0, (ULONG) 256, (ULONG *)&conventional_memory); if (err) conventional_memory = NULL;#ifdef DEBUG if (err) printf("TIP: Unable to map conventional memory %d\n", err); else printf("TIP: Successfully mapped conventional memory\n");#endif if (!conventional_memory) { /* mapping conventional memory did not work */ /* need to set up stacks to switch to at UDI call time */ create_stack(0, 64000); create_stack(1, 10000); stack_table[2] = 0; /* end of list */ } /* do a realcopy to copy all the things that must be reachable * from real mode into a real mode segment. For simplicity, * we just always assume that REALBREAK might not work. * This is only used at TIP INIT time and the performance impact is negligent. */ err = realcopy(0, /* real mode stuff was linked first */ end_real, /* where the real mode stuff ends */ &real_basep, &prot_basep, &rmem_adrp); if (err) { printf("\nTIP: realcopy call failed;\n"); printf( " Probable cause: insufficient free conventional memory.\n"); do_exit(1); } /* The prot_basep that was returned above must now be used to access from protected mode the data elements that were copied above. In particular, we create a pointer to the copied TIPVecRec and use that. */ pTIPVecRec = (struct UDIVecRec IPCFar *) (prot_basep + (ULONG) &TIPVecRec); /************************************************************** * The real_basep that was returned from realcopy must be used as * the code segment pointer of all the real mode routines. * and so must be patched into TIPVecRec. * real_basep is returned by realcopy such that the offset parts * (as assembled in in the module dostip.asm) can remain unchanged. * So we just need to patch the real_basep seg into each of those pointers ***************************************************************/ for (p = (REALPTR IPCFar *)&pTIPVecRec->exeName; p<= (REALPTR IPCFar *)&pTIPVecRec->UDITransMode; p++) { RP_SET(*p, RP_OFF(*p), RP_SEG(real_basep)); } /***************************************************** Store our PSP (real segment) away for later termination and also the dos extender's PSP (our parent). We get this by building a real pointer with seg = our_tsr_psp, ofst = 0x16, and then derefencing that *****************************************************/ our_tsr_psp = GetPSP(); RP_SET(ptr_dos_ext_psp, 0x16, our_tsr_psp); dos_ext_psp = *((USHORT _far *)(REALPTR_TO_FARCPTR(ptr_dos_ext_psp)));#endif /* end of DOS386 setup code */}static unsigned int ComputeTSRSize(void *topofstack){#ifndef DOS386 /* Real mode program, compute program size */ /* Huge pointers force compiler to do segment arithmetic for us. */static char _huge *tsrstack;static char _huge *tsrbottom; /* Initialize stack and bottom of program. */ tsrstack = (char huge *)topofstack; FP_SEG( tsrbottom ) = _psp; FP_OFF( tsrbottom ) = 0; /* Program size is: * top of stack * - bottom of program (converted to paragraphs) (using huge math) * + one extra paragraph */ return((unsigned int) (((tsrstack - tsrbottom) >> 4) + 1));#else /********************* In DOS386 mode, the TSR size consists of the real memory that is used by the Pharlap DOS extender and the small amount of real memory used by UDI. The number 6400 seems to be a good guess for now. This might have to be adjusted with newer versions of Dos extender, etc. I wonder if there is some way to compute this number accurately. **********************/ return(6400); /* our best guess for now */#endif}main(int argc, char *argv[]){ unsigned tsrsize; get_tip_name(argc, argv); /* get name from argv or whereever */#ifdef TSRDEBUG { int i; printf( "Invoked with %d arguments\n", argc ); for (i = 0; i < argc; i++) printf( "%s ", argv[i] ); printf( "\n" ); }#endif InitRecognizer(&TIPVecRec.recognizer ); SetupEnvironment(); /* do some setup specific to DOS or DOS386 */ /* See if the interrupt vector has already been selected for us */ if ((UDIVecP = FindIntVect()) == NULL) { if ((UDIVecP = AllocateIntVect()) == NULL) return -1; /* No interrupt vectors available */ } else { /* Interrupt vector already allocated */ pTIPVecRec->Next = *UDIVecP; /* always store a real ptr there */ ((struct UDIVecRec IPCFar *) REALPTR_TO_FARCPTR(pTIPVecRec->Next))->Prev = FARCPTR_TO_REALPTR(pTIPVecRec); } *UDIVecP = FARCPTR_TO_REALPTR(pTIPVecRec); tsrsize = ComputeTSRSize(&argv); /* pass it pointer to argv (top of stack) */ /* We are now ready to support DFEs. If we wish to debug back-ends, though, we are probably running CodeView with the TIP right now and don't want to really TSR because CV will shut down at that point. Instead, let's spawn a new DOS shell from which we can start a DFE (after setting a breakpoint in the TIP somewhere). */#ifdef TSRDEBUG system( getenv( "COMSPEC" ) );#else do_dos_keep(0, tsrsize);#endif return 0;}#define GET_PSP_DOS2 0x51#define GET_PSP_DOS3 0x62#define SET_PSP 0x50static unsigned short GetPSP( void ){ union REGS regs; if (_osmajor == 2) return 0;#ifdef DOS386 regs.h.ah = GET_PSP_DOS2; /* Phar Lap requires we use this to get real segment */#else regs.h.ah = GET_PSP_DOS3;#endif intdos( ®s, ®s ); return regs.x.bx;}static void SetPSP( unsigned short PSPSegment ){ union REGS regs; regs.h.ah = SET_PSP; regs.x.bx = PSPSegment; intdos( ®s, ®s );}#ifdef DOS386/*============================ DOS386 glue routines ====================================*//**************************************************************** * In DPMI Compatibility mode, when we get to this point, the only * thing that is on the stack is the saved far stack pointer (which actually * points back to the real mode stack). Remember in pmstub in dostip.asm, * we switched stack pointers so that SS = DS for C level requirements. * * The INCOMING_PARAMS macro defines a packed structure which expresses what the * real mode stack really looks like when we get to each dos386 glue routine. * The STACK_PAD is all the extra stuff that was on the stack because of the switching * from real to protected mode, etc. * The packed structure can be used to express where things really are on the stack * because the DFE's MSC compiler will push things differently from the hc386 compiler. ********************************************************************/typedef _packed struct { FARPTR ret_to_dosext; USHORT zero_word; USHORT saved_di; USHORT saved_si; USHORT saved_bp; USHORT saved_ds; ULONG ret_to_dfe;} STACK_PAD;/* The following macro defines the packed structure for the incoming parameters * including the STACK_PAD stuff noted above. It is used by those few d386_ * routines that do not need converted pointers to avoid non-use warnings */#define INCOMING_PARAMS_NO_PTR(params) \ _packed struct { \ STACK_PAD padding; \ params \ } _far *in = rm_stk_ptr; \/* The following macro defines the packed structure for the incoming parameters * (see above) and also defines a local structure for storing the converted local * pointers. Most d386_ routines use this macro. */#define INCOMING_PARAMS(params) \ INCOMING_PARAMS_NO_PTR(params) \ struct { \ params \ int dummy; /* to avoid warnings and for local count */ \ } local ; /* local structure for holding converted pointers */ \ int stackspace = stacksize; \/************************************************************** * The following macros handle the creation of near C pointers from real pointers * so that the real UDI routines can be called with near C pointers. * Different macros are called for IN pointers vs. OUT pointers and * for PREPROCESSING (before the real UDI call) and POSTPROCESSING (cleanup * after returning from the real UDI call). * * If conventional_memory has been mapped, the following happens * PREPROCESS (IN or OUT ptr) sets local.var pointer to the mapped pointer * nothing to copy so count is ignored * POSTPROCESS nothing to do * * If conventional_memory has not been mapped, then * PREPROCESS (IN ptr) does alloca of count to get local pointer * copies data into local allocated area * PREPROCESS (OUT ptr) does alloca of count to get local pointer * no copy of data yet. * POSTPROCESS (OUT ptr) copies data from local allocated area back to real mem * * Note that a few UDI routines have pointers that are both IN and OUT */ /* the following is used in a couple of places in the macros */#define ALLOC_LOCAL(var, count) \ if ((stackspace -= count) <= 500) return(UDIErrorIPCLimitation); \ local.var = alloca(count); #define INPTR_PREPROCESS_COUNT(var,count) \ if (conventional_memory) { \ local.var = REALPTR_TO_NEARCPTR(in->var); \ } \ else { \ local.dummy = count; /* avoid double evaluation if count is expression */ \ ALLOC_LOCAL(var, local.dummy); \ movedata(SS_DOSMEM, LINEARIZE(in->var), data_selector, (unsigned int) local.var, local.dummy); \ } #define INPTR_PREPROCESS(var) INPTR_PREPROCESS_COUNT(var, sizeof(*(in->var)))#define OUTPTR_PREPROCESS_COUNT(var,count) \ if (conventional_memory) \ local.var = REALPTR_TO_NEARCPTR(in->var); \ else { \ ALLOC_LOCAL(var,count); \ }#define OUTPTR_PREPROCESS(var) OUTPTR_PREPROCESS_COUNT(var, sizeof(*(in->var)))#define OUTPTR_POSTPROCESS_COUNT(var,count) \ if (!conventional_memory) {\ movedata(data_selector, (unsigned int)local.var, SS_DOSMEM, LINEARIZE(in->var), count); \ }#define OUTPTR_POSTPROCESS(var) OUTPTR_POSTPROCESS_COUNT(var, sizeof(*(in->var)))/* The following routine computes the length of a string that * is pointed to by a real pointer. This is only needed when * we cannot map real mode memory at the end of the DS. */int realptr_strlen(REALPTR rp) {char _far *farp;char _far *start; farp = (char _far *) REALPTR_TO_FARCPTR(rp); /* need to use a far c ptr */ start = farp; while (*farp++); /* advance until a 0 located */ return(FP_OFF(farp) - FP_OFF(start));}/*======================== Glue Routines ============================================*/UDIError d386_UDIConnect (void _far * rm_stk_ptr, int stacksize){ INCOMING_PARAMS( char *Configuration; /* In */ UDISessionId *Session; /* Out */ DOSTerm *TermStruct; /* In - not seen in UDIP */)UDIError err; INPTR_PREPROCESS_COUNT(Configuration, realptr_strlen((REALPTR)(in->Configuration))+1); OUTPTR_PREPROCESS(Session); err = UDICConnect( /* for UDIConnect, special case, call UDICConnect in dos2udip.c */ local.Configuration, local.Session, REALPTR_TO_FARCPTR((REALPTR)in->TermStruct) ); OUTPTR_POSTPROCESS(Session); return(err);}UDIError d386_UDIDisconnect (void _far * rm_stk_ptr, int stacksize){INCOMING_PARAMS( UDISessionId Session; /* In */ UDIBool Terminate; DOSTerm *TermStruct; /* In - not seen in UDIP */)UDIError err; local.dummy = 0; /* avoids warning */ err = UDICDisconnect( /* need to call UDICDisconnect */ in->Session, in->Terminate, REALPTR_TO_FARCPTR((REALPTR)in->TermStruct) ); return(err); }UDIError d386_UDISetCurrentConnection (void _far * rm_stk_ptr, int stacksize){INCOMING_PARAMS_NO_PTR( UDISessionId Session; /* In */) return(UDISetCurrentConnection(in->Session));}UDIError d386_UDICapabilities (void _far * rm_stk_ptr, int stacksize){INCOMING_PARAMS( UDIUInt32 *TIPId; /* Out */ UDIUInt32 *TargetId; /* Out */ UDIUInt32 DFEId; /* In */ UDIUInt32 DFE; /* In */ UDIUInt32 *TIP; /* Out */ UDIUInt32 *DFEIPCId; /* Out */ UDIUInt32 *TIPIPCId; /* Out */ char *TIPString; /* Out */)UDIError err; OUTPTR_PREPROCESS(TIPId); OUTPTR_PREPROCESS(TargetId); OUTPTR_PREPROCESS(TIP); OUTPTR_PREPROCESS(DFEIPCId); OUTPTR_PREPROCESS(TIPIPCId); OUTPTR_PREPROCESS_COUNT(TIPString, 100); /* max TIP string? */ err = UDICCapabilities( /* another special case call UDICapabilities */ local.TIPId, local.TargetId, in->DFEId, in->DFE, local.TIP, local.DFEIPCId, local.TIPIPCId, local.TIPString ); OUTPTR_POSTPROCESS(TIPId); OUTPTR_POSTPROCESS(TargetId); OUTPTR_POSTPROCESS(TIP); OUTPTR_POSTPROCESS(DFEIPCId); OUTPTR_POSTPROCESS(TIPIPCId); OUTPTR_POSTPROCESS_COUNT(TIPString, strlen(local.TIPString)+1); return(err);}UDIError d386_UDIGetErrorMsg (void _far * rm_stk_ptr, int stacksize){INCOMING_PARAMS( UDIError ErrorCode; /* In */ UDISizeT MsgSize; /* In */ char *Msg; /* Out */ UDISizeT *CountDone; /* Out */)UDIError err; OUTPTR_PREPROCESS_COUNT(Msg, in->MsgSize); OUTPTR_PREPROCESS(CountDone); err = UDIGetErrorMsg( in->ErrorCode, in->MsgSize, local.Msg, /* pointers made local */ local.CountDone ); OUTPTR_POSTPROCESS_COUNT(Msg, *(local.CountDone)+1); OUTPTR_POSTPROCESS(CountDone); return(err);}UDIError d386_UDIGetTargetConfig (void _far * rm_stk_ptr, int stacksize)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -