/*@P************************************************************************
 * File           : TSTRESET.C
 * Project        : EVERLOCK EVMOV32.DLL Test Application
 * Compiler       : Borland C++ v4.52 & Microsoft Visual C++ 4.0
 *
 * Copyright (c) 1994-97 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 "sb.h"
#include "tstreset.h"

// disable Microsoft warning for unknown pragmas
#pragma warning (disable: 4068)

/***************************************************************************
 * Function Prototypes.
 ***************************************************************************/
void CenterDialog( HWND hDlg );
void ParseCommand( SB *pSB, LPSTR lpszArgs );
int NormalizeStatus( int status );
void GlobalDialogBox( HINSTANCE hInstance, FARPROC dlgProc, UINT resId );
LRESULT CALLBACK ResetDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
void ResetOnCommand( HWND, int, HWND, UINT );
BOOL ResetOnInitDialog( HWND, HWND, LPARAM );

// if the code you will be using is C++ code then you will need to define the
// EVMOV32 function as 'extern "C"' so name mangling does not cause compile
// problems.

#ifdef __cplusplus
   #ifdef __BORLANDC__
   extern "C" short WINAPI __import EVMOV32( SB *lpUserSB );
   #else  // __BORLANDC__
   extern "C" __declspec(dllimport) short WINAPI EVMOV32( SB *lpUserSB );
   #endif // __BORLANDC__
#else  // __cplusplus
   #ifdef __BORLANDC__
   short WINAPI __import EVMOV32( SB *lpUserSB );
   #else  // __BORLANDC__
   __declspec(dllimport) short WINAPI EVMOV32( SB *lpUserSB );
   #endif // __BORLANDC__
#endif // __cplusplus

/***************************************************************************
 * Global Variables.
 ***************************************************************************/
char szAppName[] = "EVERLOCK EVMOV32.DLL Reset Test Application";
UINT errFlags = MB_ICONSTOP | MB_OK;
UINT okFlags = MB_ICONINFORMATION | MB_OK;
UINT confFlags = MB_ICONQUESTION | MB_OKCANCEL;
SB sb;
char szText[255];

#pragma argsused
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszArgs,
                    int nWinMode )
{
   int comp_status;
   HCURSOR hSaveCursor, hWaitCursor;

   // if we are a second instance, just quit
   if ( hPrevInst )
      return 0;

   // get the handle of the hourglass (waiting) cursor
   hWaitCursor = LoadCursor( NULL, IDC_WAIT );

   // turn on the waiting cursor
   hSaveCursor = SetCursor( hWaitCursor );

   // zero out the contents of the SB structure
   memset( &sb, 0, sizeof( SB ) );

   // initialize the contents of the SB buffer
   strncpy( sb.id, "AZSB", 4 );

   // parse out the command line parameters
   ParseCommand( &sb, lpszArgs );

   // get the reset use-count and product serial numbers
   sb.func = 0;
   comp_status = EVMOV32( &sb );

   // restore the original cursor
   SetCursor( hSaveCursor );

   // verify the success of the information gathering
   if ( comp_status )
   {
      // format the error message
      sprintf( szText, "EVMOV32.DLL Error %04X!", comp_status );

      // display the error message
      MessageBox( NULL, szText, szAppName, errFlags );

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

   } else if ( sb.stat1 ) {

      // format the error message
      sprintf( szText, "Security Error %04X-%04X-%04X!", sb.stat1,
               sb.stat2, sb.stat3 );

      // display the error message
      MessageBox( NULL, szText, szAppName, errFlags );

      // return to the OS
      return NormalizeStatus( sb.stat1 );
   }

   // get the reset information?
   GlobalDialogBox( hInstance, (FARPROC) ResetDlgProc, IDD_RESET );

   // if the user aborted, return to our caller to handle error
   if ( sb.stat1 )
   {
      // inform the user why we are ending
      MessageBox( NULL, "TSTRESET ending at user's request.", szAppName,
                  errFlags );

      // return to the operating system
      return NormalizeStatus( sb.stat1 );
   }

   // turn on the waiting cursor
   hSaveCursor = SetCursor( hWaitCursor );

   // perform the actual reset operation
   sb.func = 2;
   comp_status = EVMOV32( &sb );

   // restore the original cursor
   SetCursor( hSaveCursor );

   // verify the reset operation
   if ( comp_status )
   {
      // format the error message
      sprintf( szText, "EVMOV32.DLL Error %04X!", comp_status );

      // display the error message
      MessageBox( NULL, szText, szAppName, errFlags );

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

   } else if ( sb.stat1 ) {

      // format the error message
      sprintf( szText, "Security Error %04X-%04X-%04X!", sb.stat1,
               sb.stat2, sb.stat3 );

      // display the error message
      MessageBox( NULL, szText, szAppName, errFlags );

      // return to the OS
      return NormalizeStatus( sb.stat1 );
   }

   // let the user know we were successfull
   MessageBox( NULL, "Reset Successfull!", szAppName, okFlags );

   // return to the OS
   return 0;
}

//@PB
void GlobalDialogBox( HINSTANCE hInstance, FARPROC dlgProc, UINT resId )
{
   DLGPROC lpProc;

   // create, display and release the dialog box
   DialogBox( hInstance, MAKEINTRESOURCE( resId ), NULL, (DLGPROC) dlgProc );
}

//@PB
void CenterDialog( HWND hDlg )
{
   RECT rc, rcParent;
   int newX, newY, centerX, centerY;

   // get screen rectangle size and dialog box rectangle size
   GetWindowRect( GetDesktopWindow(), &rcParent );
   GetWindowRect( hDlg, &rc );

   // calculate center of screen
   centerX = ( rcParent.left + rcParent.right  ) / 2;
   centerY = ( rcParent.top  + rcParent.bottom ) / 2;

   // calculate new origin of dialog box
   newX = centerX - ( ( rc.right  - rc.left ) / 2 );
   newY = centerY - ( ( rc.bottom - rc.top  ) / 2 );

   // set the dialog box's new location
   SetWindowPos( hDlg, NULL, newX, newY, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE );
}

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

//@PB
void ParseCommand( SB *pSB, LPSTR lpszArgs )
{
   int pos;
   int state;
   int i;
   int len;
   BOOL fLoop;

   // get the length of the command line
   len = lstrlen( lpszArgs );

   // setup variables
   pos = state = 0;
   fLoop = TRUE;

   // loop to scan for cmd line arguments
   while ( fLoop && pos <= len )
   {
      // handle the different things we can find on the cmdline
      switch ( lpszArgs[pos] )
      {
         case '\0':

            // we're at the end, stop searching
            fLoop = FALSE;
            break;

         case ' ':

            // skip the space character
            break;

         default:

            // copy the arguments to the from and to path buffers
            switch ( state )
            {
               case 0:     // source path

                  // setup the starting position of the copy destination
                  i = 0;

                  // save the source media
                  while ( ' ' != lpszArgs[pos] && '\0' != lpszArgs[pos] )
                     pSB->source[i++] = lpszArgs[pos++];

                  // set the state to get the dest media next
                  state++;

                  break;

               case 1:     // target path

                  // setup the starting position of the copy destination
                  i = 0;

                  // save the destination media
                  while ( ' ' != lpszArgs[pos] && '\0' != lpszArgs[pos] )
                     pSB->target[i++] = lpszArgs[pos++];

                  // set the state to get nothing next
                  state++;

                  break;
            }
      }

      // move to the next character
      pos++;
   }
}

//@PB
LRESULT CALLBACK ResetDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
   switch ( msg )
   {
      HANDLE_MSG( hDlg, WM_COMMAND,        ResetOnCommand         );
      HANDLE_MSG( hDlg, WM_INITDIALOG,     ResetOnInitDialog      );
   }

   return FALSE;
}

#pragma argsused
void ResetOnCommand( HWND hDlg, int id, HWND hCtl, UINT codeNotify )
{
   int ctlId;

   switch ( id )
   {
      case IDOK:

         // get the reset code entered into the edit control
         GetDlgItemText( hDlg, IDC_RESETCODE, sb.code, 18 );

         // show that there was no error
         sb.stat1 = 0x0000;

         break;

      case IDCANCEL:

         // flag that the user hit abort
         sb.stat1 = 0x7001;

         break;

      default:

         // we can't handle it so let someone else do the dirty work
         return;
   }

   // finish the dialog and clear it out
   EndDialog( hDlg, 0 );
}

#pragma argsused
BOOL ResetOnInitDialog( HWND hDlg, HWND hWndFocus, LPARAM lParam )
{
   char szTemp[20] = "\0";

   // blank out the initial edit field contents
   SetDlgItemText( hDlg, IDC_RESETCODE, szTemp );

   // build the serial number/use count display field
   wsprintf( szTemp, "%lu-%u", sb.snp, sb.ruc );

   // display the serial number/use count in our dialog box
   SetDlgItemText( hDlg, IDC_SERNUM, szTemp );

   // display the current system date in the dialog box
   SetDlgItemText( hDlg, IDC_DATE, sb.cdate );

   // set the focus to the reset code edit control
   SetFocus( GetDlgItem( hDlg, IDC_RESETCODE ) );

   // center the dialog box in the display screen
   CenterDialog( hDlg );

   // return success to our caller
   return FALSE;
}
