www.pudn.com > fxvmm210.zip > _FXAPI.C


/* 
     API functions used by the FXúVM Manager version 2.10 
*/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "..\source.c\_fxapi.h" 
 
/* 
      Externally avalaible variables 
*/ 
 
unsigned char   fxvmm_fxapi_active        = FALSE; 
unsigned char   fxvmm_ems_api_installed   = FALSE; 
unsigned char   fxvmm_ems_api_name[]      = "EMMXXXX0"; 
unsigned int    fxvmm_ems_api_frame       = 0; 
unsigned char   fxvmm_ems_api_vermajor    = 0; 
unsigned char   fxvmm_ems_api_verminor    = 0; 
unsigned long   fxvmm_ems_api_size        = 0L; 
unsigned long   fxvmm_ems_api_free        = 0L; 
unsigned int    fxvmm_ems_api_totalhandle = 0; 
unsigned int    fxvmm_ems_api_freehandle  = 0; 
unsigned int    fxvmm_ems_api_usehandle   = 0; 
unsigned char   fxvmm_xms_api_installed   = FALSE; 
unsigned long   fxvmm_xms_api_free        = 0L; 
unsigned long   fxvmm_xms_api_largest     = 0L; 
unsigned char   fxvmm_xms_api_vermajor    = 0; 
unsigned char   fxvmm_xms_api_verminor    = 0; 
unsigned char   fxvmm_xms_api_hma         = 0; 
unsigned char   fxvmm_xms_api_a20         = 0; 
unsigned int    fxvmm_xms_api_usehandle   = 0; 
unsigned int    fxvmm_xms_api_freehandle  = 0; 
unsigned char   fxvmm_umb_api_installed   = FALSE; 
unsigned long   fxvmm_umb_api_free        = 0L; 
unsigned long   fxvmm_umb_api_large       = 0L; 
unsigned int    fxvmm_umb_api_index       = 0; 
unsigned long   fxvmm_vrt_api_free        = 0L; 
unsigned long   fxvmm_dos_api_free        = 0L; 
unsigned char   fxvmm_dosextender         = FXVMM_DOS_REALMODE ; 
unsigned char   fxvmm_protmode            = FXVMM_DOSV86       ; 
unsigned char   fxvmm_windows             = FXVMM_WINDOWS_NONE ; 
 
/* 
   Static/Local Variables 
*/ 
 
static unsigned char far *fxvmm_stack_st_top  = NULL    ; 
static unsigned char far *fxvmm_stack_st_bot  = NULL    ; 
static unsigned char far *fxvmm_stack_prt     = NULL    ; 
static unsigned int       fxvmm_stack_segment = 0x0000U ; 
static unsigned int       fxvmm_stack_st_ptr  = 0x0000U ; 
static unsigned char      fxvmm_stack_mark    = 0xFFU   ; 
static unsigned int       fxvmm_stack_unused  = 0x0000U ; 
 
static FXVMM_EMSHANDLE fxvmm_ems_api_handles[FXVMM_MAXHANDLES]; 
static FXVMM_XMSHANDLE fxvmm_xms_api_handles[FXVMM_MAXHANDLES]; 
 
static void far        (*fxvmm_xmsdrv_apicall)(void); 
 
static FXVMM_MCBHEAD        *fxvmm_firstmcb=NULL; 
static FXVMM_MEMINFO         fxvmm_mlist[FXVMM_MAXITEM]; 
static unsigned int          fxvmm_mlistnum=0; 
 
static unsigned char *fxvmm_system_typenames[]= 
{ 
    "             ", 
    "System code  ", 
    "System data  ", 
    "Program      ", 
    "Device driver", 
    "Environment  ", 
    "Data area    ", 
    "Free         ", 
}; 
 
int _fxvmm_vrt_handle_swapwipe( const char *filename ) 
{ 
   FILE          *stream   ; 
   struct   ftime ft       ; 
   unsigned long  loop     ; 
   unsigned char  name[13] ; 
   unsigned char  dod_loop ; 
 
/* 
 Steps to wipe a file 
 
 (1) Change attributes to Archive-bit only 
 (2) open file and set date and time to 00/00/00 00:00:12a 
 (3) Wipe file according to DoD 5220.22-M specs 
     i.e.  Overwrite file with 0xFF 
           Overwrite file with 0x00 
           Do this 3 times, and then Overwrite file with 246 (0xf6) 
 (4) Truncanate it to 0 bytes 
 (5) Create temp name and rename it to that name 
 (6) Delete that file 
*/ 
 
   _chmod( filename , 1 , !FA_RDONLY ); 
   _chmod( filename , 1 , !FA_HIDDEN ); 
   _chmod( filename , 1 , !FA_SYSTEM ); 
   _chmod( filename , 1 ,  FA_ARCH   ); 
 
   /* Note we're resetting the filedate's year to 0 by setting it to 
      -108 ... confused ? ... well DOS doesn't have a year '0', in fact 
      the lowest it can reach is 1980, this is just a little trick to 
      make it '0' ... note that some anti-virus programs tell the user 
      that the program might be infected with a virus if the date of the 
      file is invalid (and this one is...) - shame on those av's ! */ 
 
   ft.ft_year  = -108  ;                         /* make it 0 */ 
   ft.ft_month =   0U  ;                         /* make it 0 */ 
   ft.ft_day   =   0U  ;                         /* make it 0 */ 
   ft.ft_hour  =   0U  ;                         /* make it 0 */ 
   ft.ft_min   =   0U  ;                         /* make it 0 */ 
   ft.ft_tsec  =   0U  ;                         /* make it 0 */ 
 
  if( ( stream = fopen( filename , "r+b" ) ) == NULL ) 
    return( FALSE );                                  /* open for readin' & writin' */ 
 
  for( dod_loop = 0U ; dod_loop < 3U ; dod_loop++ ) /* start wiping */ 
   { 
     rewind( stream ); 
 
      for( loop = 0LU ; loop < fxvmm_vrt_swapsize ; loop ++ ) 
	   putc( dod_loop == 0 || dod_loop == 2 ? 0xff : 0x00 , stream ); 
   } 
 
  for( loop = 0LU ; loop < fxvmm_vrt_swapsize ; loop ++ ) /* Wipe for the last time */ 
	   putc( 0xf6 , stream ); 
 
  fclose( stream  );                                     /* close file */ 
 
  if( ( stream = fopen( filename , "wb" ) ) == NULL )    /* kill to 0 bytes */ 
    return( FALSE ); 
 
  setftime( fileno( stream ), &ft );                     /*  reset time & date */ 
 
  fclose( stream );                                      /*  re-close file */ 
 
  randomize(); 
 
  for( loop = 0U ; loop < 8U ; loop ++ )                  /* make up a name */ 
      name[ loop ] = (random(9) + '0'); 
 
  name[8] = '.';                                         /* add a extension marker */ 
 
  for( loop = 9U ; loop < 12U ; loop ++ )                  /* add extension */ 
      name[ loop ] = (random(9) + '0'); 
 
  name[ loop ] = '\0';                                   /* Terminate string */ 
 
  rename( filename , name );                             /* rename file */ 
 
  unlink( name );                                        /* And finally, remove it */ 
 
 return( TRUE ); 
 
} 
 
char *_fxvmm_vrt_handle_buildswap( void ) 
{ 
  char *ptr = NULL ; /* pointer to the environment */ 
 
  /* first check the DOS environment for the 'TEMP' or 'TMP' setting, 
     if there isn't any setting in the environment, call the mktemp() 
     function wich will create a temporary name for us */ 
 
  if( (ptr = getenv("TEMP")) == NULL && (ptr = getenv("TMP")) == NULL ) 
      return( mktemp("VMXXXXXX") ); 
  else 
   { 
     char *path ; 
 
     /* Allocate some memory for the swapname, if there's not enough 
        memory we could either exit and tell the user, since this is 
        a pretty stupid thing ... like imagine this error message : 
 
        Error: The virtual memory manager just ran out of memory ... ehmm 
 
        Yeah, get my point ?, so if there isn't enough memory (wich would 
        be wierd in the first place, but anyway, if there isn't any we 
        just return the mktemp() function wich will do it for us */ 
 
     if( ( path = malloc(80)) == NULL ) 
        return( mktemp("VMXXXXXX") ); 
 
     strcpy( path , ptr ); 
 
     /* Now check if there's a trailing slash, if not append one */ 
 
     if( path[ strlen(path) - 1 ] != '\\' ) 
         strcat( path , "\\" ); 
 
    /* Append a swapname to the tempoary path */ 
 
     strcat( path , mktemp("VMXXXXXX") ); 
 
     return( path ); 
   } 
} 
 
int _fxvmm_vrt_handle_swapunlink( const char *swapname ) 
{ 
   if( swapname != NULL && fxvmm_vrt_swapsize != 0 ) 
    { 
#ifdef FXVMM_WIPESWAP 
     return( _wipe_file( swapname ) ); 
#else 
     return( unlink( swapname ) ); 
#endif 
    } 
 
  return( TRUE ); 
} 
 
char _fxvmm_open_api( void ) 
{ 
   if( _osmajor == 3 ) /* We require a DOS version above 3.1 */ 
    { 
      if( _osminor < 1 ) 
        return( FALSE ); 
    } 
   else 
   if( _osmajor < 3 )  /* We require a DOS version above 3.1 */ 
        return( FALSE ); 
 
   /* Call the CPU identification routine */ 
 
   _fxvmm_cpuid(); 
 
   if( fxvmm_cputype < 3U )             /* Only 386's and above */ 
        return( FALSE ); 
 
   /* Check wich DOS extender we're running on */ 
 
   _fxvmm_getdosextender(); 
 
   /* Are we in protected mode (of so wich one), or in real mode ? */ 
 
   fxvmm_protmode = _fxvmm_detprotmode(); 
 
   /* Are we running under windows (if so wich one), or DOS */ 
 
   fxvmm_windows  = _fxvmm_detwin(); 
 
   if( _fxvmm_check_ems() == ERROR )   /* check to see if EMS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_xms() == ERROR )   /* check to see if XMS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_umb() == ERROR ) /* check to see if UMB's are okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_dos() == ERROR ) /* check to see if DOS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_vrt() == ERROR ) /* check to see if VRT is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   fxvmm_fxapi_active = TRUE ;  /* The API is active now ! */ 
 
   return( _fxvmm_initialize() ); 
} 
 
char _fxvmm_close_api( void ) 
{ 
   _fxvmm_deinitialize(); 
 
   fxvmm_fxapi_active = FALSE ;  /* API not active anymore */ 
 
   if( _fxvmm_check_ems() == ERROR )   /* check to see if EMS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_xms() == ERROR )   /* check to see if XMS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_umb() == ERROR ) /* check to see if UMB's are okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_dos() == ERROR ) /* check to see if DOS is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   if( _fxvmm_check_vrt() == ERROR ) /* check to see if VRT is okay (i.e. not corrupted) */ 
        return( FALSE ); 
 
   return( TRUE ); 
} 
 
/* 
   Returns wich DOS extender is active 
*/ 
 
void _fxvmm_getdosextender( void ) 
{ 
   union  REGS  regs; 
   struct SREGS segregs; 
 
   regs.x.ax = 0x2B00; 
   regs.x.cx = 0x4149; /* "AI" */ 
   regs.x.dx = 0x413F; /* "A?" */ 
 
   int86(0x21, ®s, ®s); 
 
   if( regs.x.ax == 0x4149 ) 
    { 
      if( regs.x.cx == 0x0202 ) 
         fxvmm_dosextender = FXVMM_ERGO_OS286; 
      else 
      if( regs.x.cx == 0x0203 ) 
       { 
	 segread(&segregs); 
 
         if( segregs.cs == 0x0F ) 
            fxvmm_dosextender = FXVMM_ERGO_OS386; 
         else 
            fxvmm_dosextender = FXVMM_ERGO_OS286; 
       } 
    } 
   else 
    { 
 
      regs.x.ax = 0x3000; 
      regs.x.bx = 0x50484152;       /* "PHAR" */ 
 
      int86( 0x21, ®s, ®s ); 
 
      regs.x.ax &= 0xFFFF0000; 
#pragma warn -rng 
 
      if( regs.x.ax == 0x44580000 )   /* "DX00" */ 
	 fxvmm_dosextender = FXVMM_PHARLAP_386; 
#pragma warn +rng 
   } 
 
} 
 
/* 
   Check wether EMS exists, and wether it's corrupted or not 
*/ 
 
char _fxvmm_check_ems( void ) 
{ 
   void far *int67 ; 
 
   int67 = (void *)getvect(0x67); 
 
   if( int67 == NULL ) 
      return( ERROR ); 
 
   asm   push  ds 
   asm   push  si 
   asm   push  di 
   asm   les   di,int67 
   asm   mov   di,10 
   asm   lea   si,fxvmm_ems_api_name 
   asm   mov   cx,8 
   asm   cld 
   asm   repe  cmpsb 
   asm   pop   di 
   asm   pop   si 
   asm   pop   ds 
   asm   jz    _found 
 
   return( FALSE ); 
 
   _found: 
 
   fxvmm_ems_api_installed = TRUE; 
 
   asm   mov   ah,41h 
   asm   int   67h 
   asm   or    ah,ah 
   asm   jnz   _error 
   asm   mov   fxvmm_ems_api_frame,bx 
 
   asm   mov   ah,46h 
   asm   int   67h 
   asm   or    ah,ah 
   asm   jnz   _error 
   asm   mov   bl,al 
   asm   and   al,0fh 
   asm   and   bl,0f0h 
   asm   mov   cl,4 
   asm   shr   bl,cl 
   asm   mov   fxvmm_ems_api_vermajor,bl 
   asm   mov   fxvmm_ems_api_verminor,al 
 
   asm   mov   ah,42h 
   asm   int   67h 
   asm   or    ah,ah 
   asm   jnz   _error 
   asm   mov   word ptr fxvmm_ems_api_size,dx 
   asm   mov   word ptr fxvmm_ems_api_size[2],0 
   asm   mov   word ptr fxvmm_ems_api_free,bx 
   asm   mov   word ptr fxvmm_ems_api_free[2],0 
 
   fxvmm_ems_api_size *= 16384L; 
   fxvmm_ems_api_free *= 16384L; 
 
   asm   push  di 
 
   _ES=FP_SEG( &fxvmm_ems_api_handles ); 
   _DI=FP_OFF( &fxvmm_ems_api_handles ); 
 
   asm   mov   ah,4Dh 
   asm   int   67h 
   asm   pop   di 
   asm   or    ah,ah 
   asm   jnz   _error 
   asm   mov   fxvmm_ems_api_usehandle,bx 
 
   if( fxvmm_ems_api_vermajor >= 4 ) 
    { 
      asm   mov   ax,5402h 
      asm   int   67h 
      asm   or    ah,ah 
      asm   jnz   _error 
      asm   mov   fxvmm_ems_api_totalhandle,bx 
    } 
   else 
      fxvmm_ems_api_totalhandle = fxvmm_ems_api_usehandle; 
 
   fxvmm_ems_api_freehandle = (fxvmm_ems_api_totalhandle - fxvmm_ems_api_usehandle); 
 
   return( TRUE ); 
 
   _error: return( ERROR ); 
} 
 
/* 
   Check wether XMS exists, and wether it's corrupted or not 
*/ 
 
char _fxvmm_check_xms( void ) 
{ 
   asm   mov   ax,4300h 
   asm   int   2fh 
   asm   cmp   al,80h 
   asm   je    _found 
 
   return( FALSE ); 
 
   _found: 
 
   fxvmm_xms_api_installed = TRUE; 
 
   asm   mov   ax,4310h 
   asm   int   2fh 
   asm   mov   word ptr fxvmm_xmsdrv_apicall,bx 
   asm   mov   word ptr fxvmm_xmsdrv_apicall[2],es 
 
   asm   mov   ah,0 
 
   (*fxvmm_xmsdrv_apicall)(); 
 
   asm   mov   fxvmm_xms_api_vermajor,ah 
   asm   mov   fxvmm_xms_api_verminor,al 
   asm   mov   fxvmm_xms_api_hma,dl 
 
   asm   mov   ah,8 
 
   (*fxvmm_xmsdrv_apicall)(); 
 
   asm   mov   word ptr fxvmm_xms_api_free,ax 
   asm   mov   word ptr fxvmm_xms_api_free[2],0 
   asm   mov   word ptr fxvmm_xms_api_largest,dx 
   asm   mov   word ptr fxvmm_xms_api_largest[2],0 
 
   fxvmm_xms_api_free    *= 1024L; 
   fxvmm_xms_api_largest *= 1024L; 
 
   asm   mov   ah,7 
 
   (*fxvmm_xmsdrv_apicall)(); 
 
   asm   or    bl,bl 
   asm   jnz   _error 
   asm   mov   fxvmm_xms_api_a20,al 
 
   return( TRUE ); 
 
   _error: return( ERROR ); 
} 
 
/* 
   Check wether DOS is corrupted or not 
*/ 
 
char _fxvmm_check_dos( void ) 
{ 
   if( heapcheck() == -1 ) 
       return( ERROR ); 
 
   (size_t)fxvmm_dos_api_free = coreleft(); 
 
   return( TRUE ); 
} 
 
/* 
   Check wether DOS is corrupted or not 
*/ 
 
char _fxvmm_check_vrt( void ) 
{ 
  struct   dfree free  ; 
  unsigned int   drive ; 
 
  if( fxvmm_fxapi_active ) 
   { 
     if( fxvmm_vrt_swaphandle == 0x0000 ) 
         drive = getdisk(); 
      else 
         drive = fxvmm_vrt_swaphandle ; 
   } 
  else 
      drive = getdisk(); 
 
  getdfree( drive + 1 , &free ); 
 
  if ( free.df_sclus == 0xFFFF ) 
     return( ERROR ); 
  else 
  if( ( fxvmm_vrt_api_free = (unsigned long)free.df_avail * (unsigned long)free.df_bsec * (unsigned long)free.df_sclus ) == 0LU ) 
     return( FALSE ); 
 
  return( TRUE ); 
} 
 
/* 
   Check wether an upper-memory block link is established 
*/ 
 
unsigned char _fxvmm_get_umblink( void ) 
{ 
   asm   mov   ax,5802h 
   asm   int   21h 
   return( _AL ); 
} 
 
/* 
   Establish an upper-memory block link 
*/ 
 
int _fxvmm_set_umblink( unsigned char link ) 
{ 
   asm   mov   ax,5803h 
   asm   xor   bh,bh 
   asm   mov   bl,link 
   asm   int   21h 
   asm   jc    _noumb 
 
   return( TRUE ); 
 
   _noumb: 
   asm   cmp   ax,1 
   asm   jne   _trash 
 
   return( FALSE ); 
 
   _trash: return( ERROR ); 
} 
 
/* 
   Check wether UMB is present, and not corrupted 
*/ 
 
char _fxvmm_check_umb( void ) 
{ 
   unsigned char origlink; 
 
   origlink = _fxvmm_get_umblink(); 
 
   switch( _fxvmm_set_umblink(1) ) 
     { 
      case TRUE   : fxvmm_umb_api_installed = TRUE ; 
                    break; 
      case FALSE  : fxvmm_umb_api_installed = FALSE; 
                    break; 
      case ERROR :  return( ERROR ); 
     } 
 
   _fxvmm_set_umblink( origlink ); 
 
   return( TRUE ); 
} 
 
/* 
   Check if the MCB contains an _psp 
*/ 
 
int _fxvmm_ispsp( FXVMM_MCBHEAD *mcb ) 
{ 
   asm   les   bx,mcb 
   asm   mov   ax,es 
   asm   inc   ax 
   asm   mov   es,ax 
   asm   mov   ax, TRUE 
   asm   cmp   word ptr es:[bx],20CDh 
   asm   je    __exit 
   asm   mov   ax,FALSE 
 
   __exit: 
 
   return( _AX ); 
} 
 
/* 
   Return the segment of the environment from the given MCB 
*/ 
 
unsigned int _fxvmm_envseg( FXVMM_MCBHEAD *mcb ) 
{ 
   FXVMM_MCBHEAD *env; 
 
   asm   les   bx,mcb 
   asm   mov   ax,es 
   asm   inc   ax 
   asm   mov   es,ax 
   asm   mov   bx,ax 
   asm   mov   ax,es:[2Ch] 
   asm   dec   ax 
   asm   mov   es,ax 
   asm   inc   ax 
   asm   cmp   es:[1],bx 
   asm   je    __exit 
   asm   mov   ax,0 
 
   __exit: 
 
   return( _AX ); 
} 
 
/* 
   Seach the vector table 
*/ 
 
void _fxvmm_search_vectors( FXVMM_MEMINFO *m ) 
{ 
   unsigned int  i; 
   unsigned long begin, end, iv; 
   unsigned char far *ivp; 
 
   begin = (unsigned long)( (m -> seg) + 1) << 4; 
 
   end = begin + (m -> size) ; 
 
   for( i = 0 ; i < 256 ; i++ ) 
       { 
         memcpy(&ivp, MK_FP(0, i*4), 4); 
 
         iv = ((unsigned long)(FP_SEG(ivp) + 1) << 4) + (unsigned long)FP_OFF(ivp); 
 
         if( ( iv > begin ) && ( iv < end ) && ( (m -> vecnum) < FXVMM_MAXVECTOR ) ) 
              (m -> vectors[ (m -> vecnum++) ]) = (unsigned char)i; 
       } 
} 
 
/* 
   Seach the sd 
*/ 
 
void _fxvmm_searchsd( FXVMM_MCBHEAD *mcb ) 
{ 
   unsigned int begin, end; 
   FXVMM_SDHEAD *sd; 
 
   sd = MK_FP(FP_SEG(mcb) + 1, 0); 
 
   begin = FP_SEG(mcb); 
   end   = FP_SEG(mcb) + mcb->size; 
 
   while((FP_SEG(sd) > begin) && (FP_SEG(sd) < end) && (fxvmm_mlistnum < FXVMM_MAXITEM)) 
     { 
      fxvmm_mlistnum++; 
 
      fxvmm_mlist[fxvmm_mlistnum].seg  = (sd -> start); 
      fxvmm_mlist[fxvmm_mlistnum].size = (unsigned long)(sd -> size) << 4; 
 
      switch( (sd -> type) ) 
        { 
         case 'D': 
         case 'I': fxvmm_mlist[fxvmm_mlistnum].name[0]=' '; 
 
                   strncpy(&fxvmm_mlist[fxvmm_mlistnum].name[1], sd->name, 8); 
                   strupr(fxvmm_mlist[fxvmm_mlistnum].name); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDEV; 
                   break; 
 
         case 'F': strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " FILES"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
 
         case 'X': strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " FCBS"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
 
         case 'C': 
         case 'B': strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " BUFFERS"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
 
         case 'L': strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " LASTDRV"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
 
         case 'S': strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " STACKS"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
 
         default:  strcpy(fxvmm_mlist[fxvmm_mlistnum].name, " UNKNOWN"); 
                   fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTDATA; 
                   break; 
         } 
 
      sd = MK_FP( (sd -> start) + (sd -> size), 0); 
 
      } 
} 
 
/* 
   Check name for valid ASCII characters 
*/ 
 
void check_name( unsigned char *name ) 
{ 
   unsigned int i; 
 
   for( i = 0 ; name[i] ; i++ ) 
 
      if( name[i] < 0x20 ) 
        { 
          name[i] = '\0'; 
          break; 
         } 
} 
 
/* 
   Register an MCB 
*/ 
 
void _fxvmm_regmcb( FXVMM_MCBHEAD *mcb ) 
{ 
   fxvmm_mlist[fxvmm_mlistnum].seg   = FP_SEG(mcb); 
   fxvmm_mlist[fxvmm_mlistnum].owner = mcb->owner; 
   fxvmm_mlist[fxvmm_mlistnum].size  = (unsigned long)mcb->size << 4; 
 
   if( fxvmm_mlist[fxvmm_mlistnum].seg <= 0x9FFF ) 
    { 
      if( _fxvmm_ispsp(mcb) ) 
       { 
         strncpy(fxvmm_mlist[fxvmm_mlistnum].name, mcb->name, 8); 
         check_name(fxvmm_mlist[fxvmm_mlistnum].name); 
         strupr(fxvmm_mlist[fxvmm_mlistnum].name); 
 
         fxvmm_mlist[fxvmm_mlistnum].environment = _fxvmm_envseg(mcb); 
         fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTAPP; 
        } 
 
      if( !(mcb -> owner) ) 
         fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTFREE; 
      else 
      if( (mcb -> owner) <= 0x0008 ) 
        { 
         strcpy(fxvmm_mlist[fxvmm_mlistnum].name, "DOS"); 
 
         if( !strncmp(mcb->name, "SD", 2) ) 
           { 
            fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTSYSDATA; 
            _fxvmm_searchsd(mcb); 
           } 
         else 
         if( !strncmp(mcb->name, "SC", 2) ) 
            fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTSYSCODE; 
         else 
            fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTSYSCODE; 
       } 
    } 
  else 
    { 
      if( !(mcb -> owner) ) 
         fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTFREE; 
      else 
      if( (mcb -> owner) <= 0x0008 ) 
        { 
          strcpy(fxvmm_mlist[fxvmm_mlistnum].name, "DOS"); 
 
          if( !strncmp(mcb->name, "SD", 2) ) 
           { 
            fxvmm_mlist[fxvmm_mlistnum].type = FXVMM_MTSYSDATA; 
            _fxvmm_searchsd(mcb); 
           } 
          else 
          if( !strncmp( (mcb -> name) , "SC", 2 ) ) 
            { 
            fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTSYSCODE; 
            } 
       } 
     else 
     if( (mcb -> owner) > 0x0008 ) 
       { 
         fxvmm_mlist[fxvmm_mlistnum].environment=_fxvmm_envseg(mcb); 
         fxvmm_mlist[fxvmm_mlistnum].type=FXVMM_MTAPP; 
 
         strncpy(fxvmm_mlist[fxvmm_mlistnum].name, mcb->name, 8); 
         strupr(fxvmm_mlist[fxvmm_mlistnum].name); 
       } 
    } 
} 
 
/* 
   Build a list of MCB's 
*/ 
 
void _fxvmm_make_mcblist( void ) 
{ 
   unsigned int i, j; 
   FXVMM_MCBHEAD *cur_mcb; 
   unsigned char  origlink; 
 
   memset( fxvmm_mlist, 0x00, sizeof(fxvmm_mlist) ); 
 
   if( _fxvmm_check_ems() == ERROR ) 
        return ; 
 
   if( _fxvmm_check_xms() == ERROR ) 
        return ; 
 
   if( _fxvmm_check_umb() == ERROR ) 
        return ; 
 
   asm   mov   ah,52h 
   asm   int   21h 
   asm   mov   ax,es:[bx-2] 
   asm   mov   word ptr fxvmm_firstmcb[2],ax 
   asm   mov   word ptr fxvmm_firstmcb,0 
 
   if( fxvmm_umb_api_installed ) 
    { 
      origlink = _fxvmm_get_umblink(); 
      _fxvmm_set_umblink(1); 
    } 
 
   cur_mcb = (FXVMM_MCBHEAD *)MK_FP(fxvmm_firstmcb, 0); 
 
   (unsigned int)fxvmm_dos_api_free = coreleft(); 
 
   while( ( fxvmm_mlistnum < FXVMM_MAXITEM ) && (cur_mcb->type != 'Z') ) 
    { 
      _fxvmm_regmcb(cur_mcb); 
      cur_mcb=(FXVMM_MCBHEAD *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0); 
      ++fxvmm_mlistnum; 
     } 
 
   _fxvmm_regmcb(cur_mcb); 
 
   cur_mcb=(FXVMM_MCBHEAD *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0); 
 
   ++fxvmm_mlistnum; 
 
   if( fxvmm_umb_api_installed ) 
      _fxvmm_set_umblink( origlink ); 
 
   for( i = 0 ; i < fxvmm_mlistnum ; i++ ) 
      if( (fxvmm_mlist[i].seg >= 0x9000) && (fxvmm_mlist[i].seg <= 0xB000) && (fxvmm_mlist[i].type == FXVMM_MTSYSCODE) ) 
       { 
         fxvmm_umb_api_index=i; 
         break; 
       } 
 
   for( i = fxvmm_umb_api_index ; i < fxvmm_mlistnum ; i++ ) 
      if( fxvmm_mlist[i].type == FXVMM_MTFREE ) 
        { 
           fxvmm_umb_api_free+=fxvmm_mlist[i].size; 
 
           if( fxvmm_mlist[i].size > fxvmm_umb_api_large ) 
              fxvmm_umb_api_large=fxvmm_mlist[i].size; 
         } 
 
   for( i = 0 ; i < fxvmm_mlistnum ; i++ ) 
     { 
      if( fxvmm_mlist[i].type == FXVMM_MTAPP ) 
         for( j = 0 ; j < fxvmm_mlistnum ; j++ ) 
            if( ( fxvmm_mlist[i].seg != fxvmm_mlist[j].seg ) && (fxvmm_mlist[j].owner == fxvmm_mlist[i].seg+1)) 
              { 
               strcpy(fxvmm_mlist[j].name, fxvmm_mlist[i].name); 
 
               fxvmm_mlist[j].type = (fxvmm_mlist[i].environment == fxvmm_mlist[j].seg+1) ? FXVMM_MTENV : FXVMM_MTDATA; 
              } 
 
      if( fxvmm_mlist[i].type != FXVMM_MTSYSDATA ) 
         _fxvmm_search_vectors(&fxvmm_mlist[i]); 
      } 
 
   for( i = 0 ; i < fxvmm_mlistnum; i++ ) 
      if( fxvmm_mlist[i].seg+1 == _psp ) 
        { 
         fxvmm_mlist[i+1].size+= fxvmm_mlist[i].size + 16; 
         fxvmm_mlist[i].type   = FXVMM_MTMAP; 
 
         for( j = 0 ; j < fxvmm_mlistnum; j++ ) 
            if( fxvmm_mlist[j].seg+1 == fxvmm_mlist[i].environment ) 
             { 
               if( j == (i-1) ) 
                { 
                  fxvmm_mlist[j].type = FXVMM_MTMAP; 
                } 
              else 
               { 
                  fxvmm_mlist[j].type    = FXVMM_MTFREE; 
                  fxvmm_mlist[j].name[0] = '\0'; 
               } 
 
              break; 
             } 
 
         break; 
      } 
} 
 
/* 
   Display DOS memory 
*/ 
 
void _fxvmm_display_dosmem( void ) 
{ 
   unsigned int i, j, pos; 
   unsigned char  line[81]; 
 
   _fxvmm_make_mcblist(); 
 
   fprintf( stderr, "\n\rMCB        Size  Name        Type"); 
   fprintf( stderr, "\n\rÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"); 
 
   for( i = 0 ; i < fxvmm_mlistnum ; i++ ) 
      if( fxvmm_mlist[i].type != FXVMM_MTMAP ) 
          fprintf( stderr, "\n\r%04Xh   %6lu   %-9s   %-4s", fxvmm_mlist[i].seg, fxvmm_mlist[i].size, fxvmm_mlist[i].name, fxvmm_system_typenames[fxvmm_mlist[i].type]); 
 
} 
 
/* 
   Display EMS memory 
*/ 
 
void _fxvmm_display_emsmem( void ) 
{ 
   unsigned int i; 
   unsigned char *line, numstr[20]; 
   unsigned char  handlename[9]; 
 
   if( _fxvmm_check_ems() == ERROR ) 
        return ; 
 
   if( !fxvmm_ems_api_installed ) 
      fprintf( stderr, "\n\rNo EMS driver installed on this system"); 
  else 
    { 
      fprintf( stderr, "\n\rEMS driver version : %1i.%1i"   , fxvmm_ems_api_vermajor, fxvmm_ems_api_verminor ); 
      fprintf( stderr, "\n\rEMS page frame     : %s"        , fxvmm_ems_api_frame ); 
      fprintf( stderr, "\n\rTotal EMS memory   : %lu bytes" , fxvmm_ems_api_size ); 
      fprintf( stderr, "\n\rFree  EMS memory   : %lu"       , fxvmm_ems_api_free ); 
      fprintf( stderr, "\n\rTotal EMS handles  : %u"        , fxvmm_ems_api_totalhandle ); 
      fprintf( stderr, "\n\rFree  EMS handles  : %u"        , fxvmm_ems_api_freehandle ); 
 
      fprintf( stderr, "\n\rHandle  Pages  Size      Name   "); 
      fprintf( stderr, "\n\rÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"); 
 
      for( i = 0 ; i < fxvmm_ems_api_usehandle ; i++ ) 
        { 
         memset(handlename, 0, sizeof(handlename)); 
 
         if( fxvmm_ems_api_vermajor >= 4 ) 
           { 
            if( fxvmm_ems_api_handles[i].handle == 0 ) 
               strcpy(handlename, "SYSTEM"); 
            else 
             { 
               asm   push  di 
 
               _DX = fxvmm_ems_api_handles[i].handle; 
 
               _ES = FP_SEG( &handlename ); 
               _DI = FP_OFF( &handlename ); 
 
               asm   mov   ax,5300h 
               asm   int   67h 
               asm   pop   di 
              } 
 
             strupr(handlename); 
 
            } 
 
           fprintf( stderr , "\n\r%-7u %-6u %-9lu %-9s",fxvmm_ems_api_handles[i].handle, fxvmm_ems_api_handles[i].pages,(unsigned long)fxvmm_ems_api_handles[i].pages * 16384L, handlename); 
         } 
 
      } 
 
} 
 
/* 
   Display XMS memory 
*/ 
 
void _fxvmm_display_xmsmem( void ) 
{ 
   unsigned int i; 
   unsigned char *line, numstr[20]; 
 
   _fxvmm_make_mcblist(); 
 
   if( fxvmm_xms_api_installed ) 
      { 
        fprintf( stderr, "\n\rPlease wait, testing XMS memory ..."); 
 
        memset(fxvmm_xms_api_handles, 0, sizeof(fxvmm_xms_api_handles)); 
 
        fxvmm_xms_api_usehandle = 0 ; 
 
        for( i = 0 ; i < 65535 ; i++ ) 
         { 
          asm   mov   ah,0Eh 
 
          _DX = i; 
 
          (*fxvmm_xmsdrv_apicall)(); 
 
          asm   or    ax,ax 
          asm   jnz  _found 
          continue; 
 
         _found: 
 
         asm mov byte ptr fxvmm_xms_api_freehandle,bl 
 
         if( fxvmm_xms_api_usehandle < FXVMM_MAXHANDLES ) 
           { 
            asm   push  di 
 
            _ES = FP_SEG( &fxvmm_xms_api_handles ); 
            _DI = FP_OFF( &fxvmm_xms_api_handles ); 
 
            asm   mov   ax,fxvmm_xms_api_usehandle 
            asm   mov   cl,3 
            asm   shl   ax,cl 
            asm   add   di,ax 
            asm   mov   ax,i 
            asm   mov   es:[di],ax 
            asm   mov   es:[di+2],dx 
            asm   mov   es:[di+6],bh 
            asm   pop   di 
 
            fxvmm_xms_api_handles[fxvmm_xms_api_usehandle].size *= 1024L; 
 
            fxvmm_xms_api_usehandle++; 
          } 
        } 
 
     } 
 
   if( !fxvmm_xms_api_installed ) 
      fprintf( stderr, "\n\rNo XMS driver installed on this system"); 
  else 
   { 
      fprintf( stderr, "\n\rXMS driver version     : %u.%u" ,  fxvmm_xms_api_vermajor, fxvmm_xms_api_verminor ); 
      fprintf( stderr, "\n\rHMA state              : %s"    , (fxvmm_xms_api_hma) ? "exists"  : "does not exist" ); 
      fprintf( stderr, "\n\rA20 line state         : %s"    , (fxvmm_xms_api_a20) ? "enabled" : "disabled" ); 
      fprintf( stderr, "\n\rFree XMS memory        : %lu"   ,  fxvmm_xms_api_free ); 
      fprintf( stderr, "\n\rLargest Free XMS block : %lu"   ,  fxvmm_xms_api_largest ); 
      fprintf( stderr, "\n\rFree XMS handles       : %u"    ,  fxvmm_xms_api_freehandle ); 
 
      if( fxvmm_xms_api_usehandle ) 
        { 
         fprintf( stderr, "\n\r"); 
         fprintf( stderr, "\n\rBlock   Handle  Size      Locks"); 
         fprintf( stderr, "\n\rÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"); 
 
         for( i = 0 ; i < fxvmm_xms_api_usehandle ; i++ ) 
            printf("\n\r%-6u  %-7u %-9lu %-12u",i, fxvmm_xms_api_handles[i].handle, fxvmm_xms_api_handles[i].size,fxvmm_xms_api_handles[i].locks); 
 
            fprintf( stderr, "\n\rÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"); 
        } 
 
      if( fxvmm_umb_api_installed ) 
       { 
         fprintf( stderr, "\n\rFree Upper Memory      : %lu"    , fxvmm_umb_api_free ); 
         fprintf( stderr, "\n\rLargest Upper Block    : %lu"    , fxvmm_umb_api_large); 
       } 
     else 
         fprintf( stderr, "\n\rNo Upper Memory avalaible"); 
   } 
 
} 
 
/* 
   Display Virtual memory 
*/ 
 
void _fxvmm_display_vrtmem( void ) 
{ 
 
  if( _fxvmm_check_vrt() == ERROR ) 
        return ; 
 
  fprintf( stderr, "\n\r%lu bytes of Virtual Memory available" , fxvmm_vrt_api_free ); 
 
} 
 
/* 
   Display ALL memory 
*/ 
 
void _fxvmm_display_allmem( void ) 
{ 
 
    fprintf(stderr,"\n\rAvailable DOS memory     : %12lu bytes", fxvmm_dos_api_free ); 
    fprintf(stderr,"\n\rAvailable EMS memory     : %12lu bytes", fxvmm_ems_api_free ); 
    fprintf(stderr,"\n\rAvailable XMS memory     : %12lu bytes", fxvmm_xms_api_free ); 
    fprintf(stderr,"\n\rAvailable Virtual memory : %12lu bytes", fxvmm_vrt_api_free ); 
    fprintf(stderr,"\n\rÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +"); 
 
    if( fxvmm_fxapi_active ) 
        fprintf(stderr,"\n\rAvailable FXVMM memory   : %12lu bytes" , (fxvmm_ems_api_free + fxvmm_xms_api_free + fxvmm_vrt_api_free + fxvmm_dos_api_free) ); 
    else 
        fprintf(stderr,"\n\rAvailable FXVMM memory   : NONE - not initialized"); 
 
} 
 
/* 
   function to mark the applications stack. 
 
   notes: Make sure you use it as the first executable statement ... i.e. 
 
   #include <....> 
   . 
   . 
   . 
   static data 
   . 
   . 
   . 
   _fxvmm_markstack(); 
   . 
   . 
   . 
   rest of program 
   . 
   . 
   . 
 
  note(2): the function will use the atexit() function to 
  hook it's sister-procedure (_fxvmm_exitstack()) to the 
  exit procedure. 
*/ 
 
void _fxvmm_markstack( void ) 
{ 
    fxvmm_stack_segment = _SS ; 
    fxvmm_stack_st_ptr  = _SP ; 
 
    FP_SEG(fxvmm_stack_st_top) = fxvmm_stack_segment ; 
    FP_OFF(fxvmm_stack_st_top) = fxvmm_stack_st_ptr  ; 
 
    FP_SEG(fxvmm_stack_st_bot) = fxvmm_stack_segment; 
    FP_OFF(fxvmm_stack_st_bot) = 0x0000u; 
 
     fxvmm_stack_prt = fxvmm_stack_st_bot; 
 
     while( fxvmm_stack_prt < fxvmm_stack_st_top ) 
           *fxvmm_stack_prt++ = fxvmm_stack_mark; 
 
     atexit( _fxvmm_exitstack ); 
} 
 
 
void _fxvmm_exitstack( void ) 
{ 
   fxvmm_stack_prt = fxvmm_stack_st_bot; 
 
   while( *fxvmm_stack_prt++ == fxvmm_stack_mark ) 
	   fxvmm_stack_unused++; 
 
   fprintf( stderr , "\n\rFXúVM Manager -> %u bytes of unused stack detected\n\r", fxvmm_stack_unused ); 
}