#pragma once
#ifdef WIN32
#include <windows.h>
#include <conio.h>
#else
#include <unistd.h>
#include <dlfcn.h>
#include <termios.h>
#include <strings.h>
#include <nl_types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include "pkcs11ctrl.h"

#ifdef WIN32
#define PKCS11_API_PATH "ls_rtpkcs11ecp"
#elif __APPLE__ 
#define PKCS11_API_PATH	"libls_rtpkcs11ecp.dylib"
#else
#define PKCS11_API_PATH	"libls_rtpkcs11ecp.so"
#endif

extern CK_CHAR *api_path; 
extern CK_CHAR *user_pin;
extern CK_UTF8CHAR *so_pin;

#define PIN_SIZE 80
#define BACK_SPACE '\b'
#define LINE_FEED  '\n'
#define CARRIAGE_RETURN '\r'
#define END_OF_TEXT 0x03	// ETX (Ctrl-C)

#ifdef WIN32
extern HMODULE dll;
#else
extern void *dll;
#endif
extern CK_FUNCTION_LIST_PTR funcs;
extern CK_C_Ctrl pctrl;
extern CK_C_INITIALIZE_ARGS *pinit_args_os_locking;
extern CK_C_INITIALIZE_ARGS *pinit_args_app_locking;
extern CK_SLOT_ID SlotId;
extern CK_SLOT_ID_PTR SlotList;
extern CK_ULONG SlotCount;

#define SYSTEMTIME  struct timeb
#define GetSystemTime(x)   ftime(x)

long process_time(struct timeb t1, struct timeb t2);
void show_error( char *str, CK_RV rc );
void process_ret_code( CK_RV rc );
void print_hex( CK_BYTE *buf, CK_ULONG len );
int print_bytes(CK_BYTE *buf, CK_ULONG len, char *str); 
CK_RV AppCreateMutex(void **pmutex);
CK_RV AppDestroyMutex(void *mutex);
CK_RV AppLockMutex(void *mutex);
CK_RV AppUnlockMutex(void *mutex);
CK_RV get_function_list(CK_CHAR *api_path, CK_FUNCTION_LIST_PTR *pfuncs);
CK_RV init(CK_CHAR *api_path, 
		   CK_FUNCTION_LIST_PTR *pfuncs, 
		   CK_C_INITIALIZE_ARGS *pinit_args);
CK_RV cleanup(CK_FUNCTION_LIST_PTR funcs);
CK_RV get_slot_list(CK_FUNCTION_LIST_PTR funcs, 
                    CK_SLOT_ID **ppSlotList, 
                    CK_ULONG *pulSlotCount);
CK_RV find_slot_with_token(CK_FUNCTION_LIST_PTR funcs, 
                           CK_SLOT_ID *pSlotList, 
                           CK_ULONG ulSlotCount, 
                           CK_SLOT_ID *pSlotId);
char *get_mechanism_name(CK_MECHANISM_TYPE);
CK_RV display_pkcs11_info(CK_FUNCTION_LIST_PTR funcs);
CK_RV display_slot_info(CK_FUNCTION_LIST_PTR funcs, CK_SLOT_ID SlotId);
CK_RV display_token_info(CK_FUNCTION_LIST_PTR funcs, CK_SLOT_ID SlotId);
CK_RV display_mechanisms(CK_FUNCTION_LIST_PTR funcs, CK_SLOT_ID slot_id); 
CK_RV pin_callback(
  CK_SESSION_HANDLE hSession,
  CK_NOTIFICATION   event,		  // CKN_LISSI_PIN_CALLBACK			
  CK_VOID_PTR       pApplication  // output PIN buffer here
); 
CK_RV test_main(int argc, char *argv[]); 
CK_RV check_value(CK_BYTE *value, CK_ULONG len, CK_BYTE *eth, CK_ULONG eth_len);

#define CHECK(v, len, ethalon) \
do { \
	if ((rc = check_value(v, len, ethalon, sizeof(ethalon))) != CKR_OK) { return rc; } \
} while (0)

