/*
[]=================================================================[]
	eps1kUtility.cpp

	Copyright (C) 2001 Feitian Tech. Co. Ltd. All rights reserved.
	by Water Bird

	Comment : Some functions maybe useful.
[]=================================================================[]
*/

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "eps1kUtility.h"

char* FormatErrMsg(EPAS_STATUS status)
{
    switch( status )
    {
        case FT_SUCCESS:
            return ("");
        case FT_CANNOT_OPEN_DRIVER:
            return ("Error : Can't open the driver.");
        case FT_INVALID_DRVR_VERSION:
            return ("Error : Driver version not supported.");
        case FT_INVALID_COMMAND:
            return ("Error : Invalid command sent to API.");
        case FT_ACCESS_DENIED:
            return ("Error : Access denied.");
        case FT_ALREADY_ZERO: 
            return ("Error : Counter already zero.");
        case FT_UNIT_NOT_FOUND:
            return ("Error : Device not found.");
        case FT_DEVICE_REMOVED:
            return ("Error : Device removed.");
        case FT_COMMUNICATIONS_ERROR: 
            return ("Error : Device communication error.");
        case FT_DIR_NOT_FOUND:
            return ("Error : Directory does not exist.");
        case FT_FILE_NOT_FOUND:
            return ("Error : File not found.");
        case FT_MEM_CORRUPT:
            return ("Error : Device memory is corrupted.");
        case FT_INTERNAL_HW_ERROR:
            return ("Error : Internal hardware error.");
        case FT_INVALID_RESP_SIZE:
            return ("Error : Invalid response received from the device.");
        case FT_PIN_EXPIRED: 
            return ("Error : PIN retry attempts has expired.");
        case FT_ALREADY_EXISTS: 
            return ("Error : Directory or file already exist.");
        case FT_NOT_ENOUGH_MEMORY: 
            return ("Error : Not enough memory to perform the operation.");
        case FT_INVALID_PARAMETER: 
            return ("Error : Invalid parameter sent to API.");
        case FT_INPUT_TOO_LONG: 
            return ("Error : Input data is too long.");
        case FT_INVALID_FILE_SELECTED: 
            return ("Error : Invalid file selected or operation.");
        case FT_DEVICE_IN_USE: 
            return ("Error : The device is currently in use.");
        case FT_INVALID_API_VERSION: 
            return ("Error : The version of this library is not supported.");
        case FT_TIME_OUT_ERROR: 
            return ("Error : Communication time-out.");
        case FT_ITEM_NOT_FOUND: 
            return ("Error : Item not found."); 
        case FT_COMMAND_ABORTED: 
            return ("Error : Communication error, command aborted.");
        case FT_INVALID_STATUS: 
            return ("Error : Invalid status.");
        default: 
            return ("Error : An unknown error occurred.");
    }
} // End of FormatErrMsg().

int CheckOP(EPAS_STATUS status, char* Msg)
{
    if (FT_SUCCESS == status) 
    {
        printf(Msg);
        printf(" successful.\n");
        return true;
    }
    else
    {
        printf(Msg);
        printf(" failed.\n -> ");
        printf(FormatErrMsg(status));
        printf("\n");
        return false;
    }
} // End of CheckOP().

EPAS_STATUS ShowDeviceInfo(EPAS_HANDLE hePass)
{
    EPAS_STATUS      epsRet;
    char             szTokenName[EPAS_FRIENDLY_NAME_SIZE] = {"{Not defined.}"};
    char             szAccessText[] = "";
    unsigned long    pulSN[2];
    unsigned long    ulCapabilites;
    unsigned long    ulMemSize;
    EPAS_ACCESSINFO  ai;
    EPAS_VERSIONINFO vi;
    EPAS_SYSINFO     si;

    epsRet = epas_GetProperty( hePass,                      // handle to the device
                               EPAS_PROP_SERNUM,            // flags
                               NULL,                        // reference data, not used.
                               pulSN,                       // serial number buffer, 2 unsigned longs
                               sizeof(pulSN)                // size of buffer
                             );
    if (CheckOP(epsRet, "Get serial number"))
    {
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_FRIENDLY_NAME, // flags
                                   NULL,                    // reference data, not used
                                   szTokenName,             // token name buffer
                                   sizeof(szTokenName)      // sizeo of buffer
                                 );
    }

    // If the return status is FT_ITEM_NOT_FOUND, it's means you never
    // set a token-name for this device and just skip it.
    if ( FT_SUCCESS == epsRet || FT_ITEM_NOT_FOUND == epsRet)
    {
        printf("Get token name successful.\n");
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_CAPABILITIES,  // flags
                                   NULL,                    // reference data
                                   &ulCapabilites,          // capabilities buffer
                                   sizeof(ulCapabilites)    // size of buffer
                                 );
    }

    if (CheckOP(epsRet, "Get capablities"))
    {
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_MEM_SIZE,      // flags
                                   NULL,                    // reference data, not used
                                   &ulMemSize,              // memory size buffer
                                   sizeof(ulMemSize)        // size of buffer
                                 );
    }

    if (CheckOP(epsRet, "Get memory size"))
    {
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_ACCESSINFO,    // flags
                                   NULL,                    // reference data, not used
                                   &ai,                     // access info structure
                                   sizeof(ai)               // size of structure
                                 );
    }

    if (CheckOP(epsRet, "Get access information"))
    {
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_VERSIONINFO,   // flags
                                   NULL,                    // reference data not used.
                                   &vi,                     // version info structure
                                   sizeof(vi)               // size of structure
                                 );
    }

    if (CheckOP(epsRet, "Get version information"))
    {
        epsRet = epas_GetProperty( hePass,                  // handle to the device
                                   EPAS_PROP_SYSINFO,       // flags
                                   NULL,                    // reference data, not used
                                   &si,                     // system info structure
                                   sizeof(si)               // size of structure
                                 );
    }

    if (CheckOP(epsRet, "Get system information"))
    {
        printf("\nDevice information :\n");
        printf("---------------------------------------------------------\n");
        printf("  Serial Number ...... = 0x%08X-%08X\n", pulSN[1],pulSN[0]);
        printf("  Token Name ......... = %s\n", szTokenName);
        printf("  Driver API Version . = %d.%d.%d\n", vi.ulDriverVersion >> 24,
                                                     (vi.ulDriverVersion >> 16) & 0x00FF,
                                                      vi.ulDriverVersion & 0x0000FFFF);
        printf("  Firmware Version ... = %d.%d\n", vi.ucFwVerMajor, vi.ucFwVerMinor);
        printf("  Product Code ....... = 0x%X\n", vi.ucProductCode);
        printf("  Total Memory ....... = %d (bytes)\n", ulMemSize);
        printf("  Available Memory ... = %d (bytes)\n", si.ulFreeSpace);
        printf("  Max PIN Retries .... = %d\n", ai.ucMaxPinRetries);
        printf("  Current PIN Counter  = %d\n", ai.ucCurPinCounter);
        printf("  Create Access ...... = %s\n", FormatAccessText(ai.ucCreateAccess));
        printf("  Delete Access ...... = %s\n", FormatAccessText(ai.ucDeleteAccess));
        printf("  Capabilities........ = %s\n", FormatCapabilitesText(ulCapabilites));
        printf( "---------------------------------------------------------\n");
    }
    return(epsRet);
} // End of ShowDeviceInfo().

char* FormatFileTypeText( unsigned char Type )
{
    switch( Type )
    {
        case EPAS_FILETYPE_UNUSED  : return "FREE";
        case EPAS_FILETYPE_DIR     : return "DIR";
        case EPAS_FILETYPE_DATA    : return "DATA";
        case EPAS_FILETYPE_KEY     : return "KEY";
    }
    return "N/A";
} // End of FormatFileTypeText().

char* FormatAccessText( unsigned char access )
{
    switch( access )
    {
        case EPAS_ACCESS_ANYONE    : return "ALWAYS";
        case EPAS_ACCESS_USER      : return "PIN";
        case EPAS_ACCESS_OFFICER   : return "MASTER";
        case EPAS_ACCESS_NONE      : return "NEVER";
    }
    return "N/A";
} // End of FormatAccessText().

char* FormatCapabilitesText(unsigned long ulCap)
{
    static char szText[100] = "";

    if ( (ulCap & EPAS_CAPS_MD5HMAC) == (EPAS_CAPS_MD5HMAC) )
        lstrcat(szText, "MD5-HMAC ");

    if (lstrcmpi(szText,"") == 0) 
        lstrcat(szText, "N/A");

    return (szText);
} // End of FormatCapabilitesText().

void ShowData(unsigned char* pData, unsigned long ulSize)
{
	DWORD i, n;

	while( ulSize > 0 )
	{
		n = (ulSize > 8) ? 8 : ulSize;
		for( i = 0; i < n; i++ )
			printf("%02X ",pData[i]);

		while( i++ < 8 )
			printf("   ");

		printf("  [");

		for( i = 0; i < n; i++, pData++ )
			printf("%c",(*pData < 32 || *pData > 127) ? '.' : *pData);

		while( i++ < 8 )
			printf(" ");
		
		printf("]");

		ulSize -= n;
		if( ulSize > 0 )
			printf("\n");
	}
} // End of ShowData().


EPAS_STATUS
OpenAnUnusedDevice(EPAS_HANDLE handle)
{
	EPAS_STATUS epsRet;

	epsRet = epas_OpenDevice(
		handle,
		EPAS_OPEN_FIRST,
		NULL
		);

	// If first device is in use, try next one.
	if (FT_DEVICE_IN_USE == epsRet)
	{
		// Try and try...
		while (1)
		{
			epsRet = epas_OpenDevice(
				handle,
				EPAS_OPEN_NEXT,
				NULL
				);
			if (FT_DEVICE_IN_USE == epsRet)
				continue;
			break;
		}
	}
	return epsRet;
} // End of OpenAnUnusedDevice().

/*
 *	GetUserInput() routine let user input some character
 */
void
GetUserInput(unsigned char* pBuf, unsigned long ulMaxSize)
{
	unsigned char ch;
	unsigned long i = 0;
	printf("\nInput some thing, I'll save it into ePass. Press \"Enter\" to end input.\n");
	printf("But remember, do not exceed %d characters.\n\n",ulMaxSize);

	ch = _getch();
	while( ch != '\r' && i < ulMaxSize)
	{
		if (isprint(ch))
		{
			putch(ch);
			pBuf[i] = ch;
			i++;
		}
		ch = _getch();
	}
	printf("\n\n");
} // End of GetUserInput().