/*@P************************************************************************
 * File           : TSTMOV.C
 * Project        : EVERLOCK EVMOV.OBJ BCEXT16 Test Application
 * Author         : M. Brendan Van Horn
 * Compiler       : Borland C++ v4.02
 * Description    :
 *
 * Copyright (c) 1994-95 Az-Tech Software, Inc.
 * ALL RIGHTS RESERVED
 ************************************************************************P@*/

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <dos.h>
#include <conio.h>
#include "sb.h"

/***************************************************************************
 * DPMI Registers
 ***************************************************************************/
typedef struct tagDPMI_REGS
{
   unsigned long  edi, esi, ebp, reserved, ebx, edx, ecx, eax;
   unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss;
} DPMI_REGS;

DPMI_REGS dpmiRegs;

SCB_TYPE far *dsSCB;


/***************************************************************************
 * Function Prototypes.
 ***************************************************************************/
int do_evmov3(void);
int NormalizeStatus( int status );


//@PB
#pragma argsused
int main( int argc, char **argv )
{
   int comp_status;
   unsigned selCS, selDS;

   // announce our presence to the users
   printf( "\nEVERLOCK EVMOV3.OBJ BCEXT16 Test Application\n\n" );

   // get the address of the Real-Mode SB structure
   selCS = FP_SEG(&SCB);
   selDS = AllocSelector(0);
   selDS = PrestoChangoSelector(selCS, selDS);
   dsSCB = MK_FP(selDS, FP_OFF(&SCB));

   // zero out the contents of the SB structure
   memset( dsSCB, 0, sizeof( SCB_TYPE ) );

   // initialize the contents of the SB buffer
   strncpy( dsSCB->id, "AZSB", 4 );

   // parse out the command line parameters
   strncpy( dsSCB->source, argv[1], 63 );
   strncpy( dsSCB->target, argv[2], 63 );

   // get the initial information about the move operation
   dsSCB->func = 0;
   comp_status = do_evmov3();

   // display the results of the check
   if ( comp_status )
   {
      // display the error message
      printf( "EVMOV3.OBJ Error %04X!\n", comp_status );

      // return to the OS
      return NormalizeStatus( comp_status );

   } else if ( dsSCB->stat1 ) {

      // display the error message
      printf( "Security Error %04X-%04X-%04X!\n", dsSCB->stat1,
               dsSCB->stat2, dsSCB->stat3 );

      // return to the OS
      return NormalizeStatus( dsSCB->stat1 );

   }

   // get rid of any extra keystrokes
   while ( kbhit() )
      getch();

   // display the confirmation message
   printf( "%s authorization from %s to %s...\n",
           dsSCB->uninst ? "Uninstalling" : "Installing", dsSCB->source,
           dsSCB->target );

   printf( "Do you wish to continue? " );

   // ask the user if they would like to move
   comp_status = getch();
   printf( "%c\n\n", comp_status );

   // check the user's response
   if ( 'Y' != comp_status && 'y' != comp_status )
   {
      // let the user know that they cancelled
      printf( "Ending EVMOVE at user's request.\n" );

      // return to the operating system
      return 1;
   }

   // do we need to get the non-verified registration info?
   if ( dsSCB->reg && !dsSCB->uninst )
   {
      // yep, so get the registration name
      printf( "Registration Name: " );
      gets( dsSCB->rname );

      // get the registration company
      printf( "          Company: " );
      gets( dsSCB->rcomp );

      // get the registration location
      printf( "         Location: " );
      gets( dsSCB->rloc );

      printf( "\n" );
   }

   // perform the actual move operation
   dsSCB->func = 1;
   comp_status = do_evmov3();

   // display the results of the check
   if ( comp_status )
   {
      // display the error message
      printf( "EVMOV3.OBJ Error %04X!\n", comp_status );

      // return to the OS
      return NormalizeStatus( comp_status );

   } else if ( dsSCB->stat1 ) {

      // display the error message
      printf( "Security Error %04X-%04X-%04X!\n", dsSCB->stat1,
               dsSCB->stat2, dsSCB->stat3 );

      // return to the OS
      return NormalizeStatus( dsSCB->stat1 );
   }

   // let the user know we were successful
   printf( "Authorization Move Successful!\n" );

   // return to the OS
   return 0;
}

//@PB
int do_evmov3(void)
{
   unsigned short segSB;
   unsigned short offSB;
   int comp_status;
   unsigned selCS, selDS;

   DPMI_REGS __far *lpdpmiRegs;

   // clear out the DPMI register block
   _fmemset( &dpmiRegs, 0, sizeof( DPMI_REGS ) );

   // CS:IP of call is SEG:0 of DOS memory
   dpmiRegs.cs = FP_SEG(rmEVMovePtr);

   // setup pointer to DPMI registers
   lpdpmiRegs = (DPMI_REGS __far *) &dpmiRegs;

   // get the segment of the SB buffer
   segSB = FP_SEG(rmSCBPtr);
   offSB = FP_OFF(rmSCBPtr);

   // default to no error conditions
   comp_status = 0;

   __asm mov   bh,0             /* flags = 0                               */
   __asm mov   cx,2             /* two words to copy to real mode stack    */
   __asm les   di,lpdpmiRegs    /* pointer to regs struct                  */
   __asm mov   ax,0301h         /* call real mode procedure                */
   __asm push  segSB            /* SEGMENT of the Real SB                  */
   __asm push  offSB            /* OFFSET of the Real SB                   */
                                /* DPMI will xfer this to real mode stack  */
   __asm int   31h
   __asm add   sp,4             /* clean up what we pushed                 */
   __asm jnc   NOERROR          /* if no error code, skip getting status   */
   __asm mov   comp_status,ax   /* get error code from DPMI server         */
   __asm jmp   CONT             /* skip getting error code from the module */

NOERROR:

   // get any error codes from the module
   comp_status = (unsigned short)dpmiRegs.eax;

CONT:

   // return our results
   return comp_status;
}

//@PB
int NormalizeStatus( int status )
{
   int temp;

   // get the hundreds digit from the error code
   temp = ( ( status & 0x0F00 ) >> 8 ) * 100;

   // add in the tens digit from the error code
   temp += ( ( status & 0x00F0 ) >> 4 ) * 10;

   // finally, add in the ones digit
   temp += status & 0x000F;

   // return the normalized status value to our caller
   return temp;
}
