/********************************************************************
	Created:	12:6:2003   22:03
	Filename: 	baseall.cpp
	Author:		Yubo
	
	Purpose:	base class:Find the token and open/close session.
*********************************************************************/

#include "BaseAll.h"
CBaseAll::CBaseAll()
{
}
CBaseAll::CBaseAll(char* dll_filepath):m_hDll(NULL),
										pSlotList(NULL_PTR)
										
{
	memset(m_dll_filepath, 0, MAX_FILEPATH);
	memcpy(m_dll_filepath, dll_filepath, strlen(dll_filepath));
	memset(m_ucPin, 0, 32);
}

CBaseAll::~CBaseAll()
{
	if(pSlotList != NULL_PTR)
	{
		free(pSlotList);
		pSlotList = NULL_PTR;
	}
	if(m_hDll != NULL_PTR)
	{
		FreeLibrary(m_hDll);
		m_hDll = NULL;
	}
}

CK_RV CBaseAll::BaseAllStart()
{
	cout<<"\n[ENTER: CBaseAll::BaseAllStart:LoadLibrary PKCS#11's dll and initialize it!]"<<endl;
	CK_RV rv = CKR_OK;
	m_hDll = LoadLibrary(m_dll_filepath);
	if(m_hDll == NULL)
	{
		cout<<"......LoadLibrary ["<<m_dll_filepath<<"] failed!"<<endl;
		return rv;
	}
	
	//Get the list of the PKCS#11 function entries.
	C_GETFUNCTIONLISTPROC pC_GetFunctionList = (C_GETFUNCTIONLISTPROC)GetProcAddress(m_hDll,"C_GetFunctionList");
	if(pC_GetFunctionList == NULL)
	{
		cout<<"...Err: (pC_GetFunctionList == NULL)!"<<endl;
		return rv;
	}
	
	//Get PKCS#11 function list.
	if(CKR_OK!=pC_GetFunctionList(&m_gToken))
	{
		cout<<"...Get PKCS#11 function list failed!"<<endl;
		return rv;
	}
	cout<<"Initialize the UsbToken PKCS#11 library..."<<endl;
	rv = m_gToken->C_Initialize(NULL_PTR);
	if(CKR_OK!=rv)
	{
		cout<<"...C_Initialize failed! Return Error Code="<<rv<<endl;
		return rv;
	}
	
	// Get the number of slots with a token attached.
	cout<<"Get the slots information..."<<endl;
	unsigned long ulCount;
	rv = m_gToken->C_GetSlotList(TRUE, NULL_PTR, &ulCount);
	if(CKR_OK!=rv)
	{
		cout<<"...C_GetSlotList failed! Return Error Code="<<rv<<endl;
		return rv;
	}
	if(ulCount <= 0)
		cout<<"...No slot with token attached."<<endl;
	
	// Allocate memory buffer for the slot list.
	cout<<"Allocate memory for slots..."<<endl;
	pSlotList = (CK_SLOT_ID_PTR)malloc(ulCount * sizeof(CK_SLOT_ID));
	if(! pSlotList) 
	{
		cout<<"...No slots!"<<endl;
		return rv;
	}
	else
	{
		cout<<"Get "<<ulCount<<" slot attached to USB port!"<<endl;
	}
	// Okay, we have the buffer allocated. Let's get the slot list.
	cout<<"Get the slots information."<<endl;
	 rv = m_gToken->C_GetSlotList(TRUE, pSlotList, &ulCount);
	if(CKR_OK!=rv)
	{
		cout<<"........C_GetSLotList failed! Return Error Code="<<rv<<endl;
		rv = m_gToken->C_Finalize(0);
		if(CKR_OK!=rv)
		{
			cout<<"..........C_Finalize failed!"<<endl;
			return rv;
		}
		m_gToken = NULL_PTR;
		Sleep(500);	
		if(m_hDll)
		{
			FreeLibrary(m_hDll);
			m_hDll = NULL;
		}
		return rv;
	}
	// Open a session to communicate with the token.
	cout<<"Open a session to communicate with the UsbToken..."<<endl;
	 rv = m_gToken->C_OpenSession(pSlotList[0],  CKF_RW_SESSION | CKF_SERIAL_SESSION,
		NULL_PTR, NULL_PTR, &hSession);
	if(CKR_OK!=rv)
	{
		cout<<"....C_OpenSession failed! Return Error Code="<<rv<<endl;
		BaseAllEnd();
		return rv;
	}

	cout<<"Input user-pin to login first:"<<endl;
	cin>>m_ucPin;

	rv = m_gToken->C_Login(hSession, CKU_USER, m_ucPin, strlen((char*)m_ucPin)); 
	if(rv!=CKR_OK)
	{
		cout<<"...C_Login failed!"<<rv<<endl;
		BaseAllEnd();
		return rv;
	} 
	cout<<"...C_Login OK!"<<endl;
	cout<<"\n[EXIT:CBaseAll::BaseAllStart()]"<<endl<<endl;
	return rv;
}

CK_RV CBaseAll::BaseAllEnd()
{
	cout<<"\n[ENTER:CBaseAll::BaseAllEnd:Close session and free the PKCS#11's dll]"<<endl;
	CK_RV rv = CKR_OK;
	cout<<"Release the session handle..."<<endl;
	if(m_gToken)
	{
		rv = m_gToken->C_CloseSession(hSession);
		if(CKR_OK!=rv)
		{
			cout<<"....C_CloseSession failed!"<<endl;
			return rv;
		}
		rv = m_gToken->C_Finalize(0);
		if(CKR_OK!=rv)
		{
			cout<<"...C_Finalize failed!"<<endl;
			return rv;
		}
		m_gToken = NULL_PTR;
	}
	Sleep(500);	
	if(m_hDll != NULL_PTR)
	{
		FreeLibrary(m_hDll);
		m_hDll = NULL;
	}
	cout<<"\n[EXIT:CBaseAll::BaseAllEnd()]"<<endl<<endl;
	return CKR_OK;
}

void CBaseAll::CheckRV(char* pFuncName, CK_RV rv)
{
	if(rv == CKR_OK)
	{
		cout <<"......";
		cout <<pFuncName;
		cout <<" OK! \n";
		return ;
	}
	else
	{
		cout <<"......";
		cout <<pFuncName;
		cout <<" failed: [0x"<<rv<<"] "<<endl;
		return ;
	}
}
