/*@P************************************************************************
 * File           : TSTCHK.C
 * Project        : EVERLOCK EVCHK.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 "sb.h"

// Get state of access flag x in byte array a.
#define ISFLAGSET(a,x) ((a)[((x)-1)>>3]&(1<<(((x)-1)&7)))

/***************************************************************************
 * 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 NormalizeStatus( int status );
void  do_output(void);
void  show_usrdata(void);
void  show_access_flgs(void);


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

   DPMI_REGS __far *lpdpmiRegs;

   // announce our presence to the user
   printf( "\nEVERLOCK EVCHK3.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 );
   dsSCB->snp = 0;
   dsSCB->pin = 0xCF02E123;         // update with PIN from EV3 file

   // get the filename for this application
   strncpy( dsSCB->source, argv[0], 63 );

   // change from our application name to the dummy application name
   strcpy( strrchr( dsSCB->source, '\\' ) + 1, "PCHECK.EXE" );

   // perform the protection check using EVCHK3.OBJ
   dsSCB->func = 1;

   // 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(rmEVCheckPtr);

   // 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:

   // display the results of the check
   if ( comp_status )
   {
      // display the error message
      printf( "EVCHK3.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 NormalizeStatus( dsSCB->stat1 );

   }

   // display the protection information.
   do_output();

   // return to the OS
   return 0;
}

//@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;
}

/* Output from the EVCHK3 call */
void do_output(void)
{
   /** Print out the Status Codes **/
   printf("\n            Return Code: %04X-%04X-%04X", 
                        dsSCB->stat1, dsSCB->stat2, dsSCB->stat3);

   /** Print out the Function Code used **/
   printf("\n          Function Code: %d", dsSCB->func);

   /** Print out the Drive, Path and Program Name checked **/
   printf("\n Drive and Path Checked: %s", dsSCB->source);

   /** Print out the Protection Type returned **/
   if(dsSCB->ptype == 'P')
      printf("\n        Protection Type:  Original Product");
   else if(dsSCB->ptype == 'C')
      printf("\n        Protection Type:  CPU-Lock Product");
   else if(dsSCB->ptype == 'E')
      printf("\n        Protection Type:  Encrypt Only Product");
   else
      printf("\n        Protection Type:  Installed Copy");

   /** Print Product Name **/
   printf("\n           Product Name: %s", dsSCB->prod);

   /** Print out the Product Serial Number **/
   printf("\n        Product Serial#: %lu",dsSCB->snp);

   /** Print the NUC Handle value **/
   printf("\n       Net-Users Handle:  %u", dsSCB->hnuc);

   /** Print the Authorization Version **/
   printf("\n  Authorization Version:  %u", dsSCB->avers);

   /** Print out the Exec-Counts found **/
   if(dsSCB->ecl == 0xFFFF)
   {
      printf("\n       Exec-Count Limit: ");
      printf("Unlimited");
   }
   else
   {
      printf("\n     Current Exec-Count: ");
      printf("%d", dsSCB->ecl);
   }

   /** Print out the Expire-Days found **/
   if(dsSCB->edl == 0xFFFF)
   {
      printf("\n      Expire-Days Limit: ");
      printf("Unlimited");
   }
   else
   {
      printf("\n      Current Days Left: ");
      printf("%d", dsSCB->edl);
      printf("\n            Expire Date: %s", dsSCB->ed);
   }

   /** Print out the Current Net-Users Count and Limit **/
   if(dsSCB->nul == 0xFFFF)
      printf("\n        Net-Users Limit: Unlimited");
   else
   {
      printf("\nCurrent Net-Users Count: %d",dsSCB->nuc);
      printf("\n        Net-Users Limit: %d",dsSCB->nul);
   }

   /** Print out the Install Counts Available if Original Product **/
   if(dsSCB->ptype == 'P')
      printf("\n         Install Counts: %d",dsSCB->icr);

   /** Print out User-Data **/
   show_usrdata();

   /** Print out the Access Flags **/
   show_access_flgs();

   /** Print out the Registration Info **/
   if(dsSCB->rtype == 'N')
   {
      printf("\n     Registered to Name: %s", dsSCB->rname);
      printf("\n  Registered to Company: %s", dsSCB->rcomp);
      printf("\n Registered to Location: %s", dsSCB->rloc);
      printf("\n        Date Registered: %s", dsSCB->rdate);
   }

   /** Print out the Current Date **/
   printf("\n           Today's Date: %s", dsSCB->cdate);

   /** Print out the Secure String **/
   printf("\n          Secure String: ");
   printf("\n------------------------ ");
   printf("\n%s",dsSCB->secstr);
}

void show_usrdata(void)
{
   char buffer[72];
   char temp[4];
   short i;

   for(i=0; i<72; i++)
      buffer[i] = '\0';

   strcpy(buffer, "              User-Data: ");
                 
   for(i=0; i<8; i++)
   {
      sprintf(temp, "%02X ", dsSCB->usrdat[i]);
      strcat(buffer, temp);
   }

   printf("\n%s", buffer);
}

void show_access_flgs(void)
{
   unsigned char flags[65];
   unsigned char temp[76];
   unsigned char buffer[55];
   unsigned char buf[4];
   short i, j, k;
   unsigned char flg, tmpflg;
   unsigned char *p;

   k=0;

   /* 
      Setup flags[] array to be a list of turned on flags
   */
   for(i=0; i<64; i++)
   {
      if(dsSCB->accflg[i >> 3] & (1 << (i & 7)))
         flags[k++] = i+1;
   }
   flags[k] = '\0';
   
   strcpy(temp, "\n       Access Flags Set: ");
   buffer[0] = '\0';
   p = flags;
   if(*p != '\0')
   {
      for(i=0; i<64; i++)
      {
         if(*p != '\0')
         {
            sprintf(buf, "%2d ", *p);
            p++;
            strcat(buffer, buf);
         }
         else
            break;

         if(strlen(buffer) == 52)
         {
            strcat(temp, buffer);
            printf("%s", temp);
            strcpy(temp, "\n                         ");
            buffer[0] = '\0';
         }
      }

      if(strlen(buffer))
      {
         strcat(temp, buffer);
         printf("%s", temp);
      }
   }
   else
   {
      strcpy(buffer, "None");
      strcat(temp, buffer);
      printf("%s", temp);
   }
}

