/*****************************************************************************************
*  Copyright (c) 2004, Beijing Senselock Data Security Centre
*  All rights reserved.
*
*  Filename£ºsample_14_mt_win32.c
*          
*  Briefs£º  The purpose of this snippet is to demonstrate how a multi-thread application can    
*            access SenseLock EL successfully.
*            
*  History:        
*  --------------------------------------------------------        
*            10/28/2004 v1.0.0.0 Lihua created
*            
*            
*******************************************************************************************/

#include <stdio.h>
#include <conio.h>
#include <assert.h>

#include "..\..\inc\win32\sense4.h"
#include "..\..\inc\win32\ses_err_msg.h"/* for debug purpose only */
#include "..\..\common\common.h"


#define S4_EXE_FILE_ID "ef11"

/* global variables definition */
SENSE4_CONTEXT stS4Ctx = {0};
unsigned long dwResult = 0;
unsigned char test[8] = {3,1,8,2,5,4,7,6};
unsigned long dwBytesReturned = 0;

unsigned long thread_func1()
{
	unsigned char lpUserPin[8] = "zaq12wsx";
	int i = 0;
	for (; i<100; i++)
	{
		HANDLE hMutex; 
		
		hMutex = CreateMutex( 
			NULL,                  // no security descriptor
			FALSE,                 // mutex not owned
			"NameOfMutexObject");  // object name
		
		if (hMutex == NULL) 
		{
			printf("CreateMutex error: %d\n", GetLastError() ); 
		}
		else if ( GetLastError() == ERROR_ALREADY_EXISTS ) 
		{	
			printf("CreateMutex opened existing mutex\n"); 
		}
		else 
		{
			printf("CreateMutex created new mutex\n"); 
		}
		
		WaitForSingleObject(hMutex, INFINITE);
		
		dwResult = S4ChangeDir(&stS4Ctx, "\\df01");
		if (dwResult != S4_SUCCESS) 
		{
			printf("Change directory failed! <error code: 0x%08x>\n",dwResult);
			S4Close(&stS4Ctx);
			return 0;
		}
		
		// Call S4VerifyPin(...) to verify User PIN so as to get the privilege to execute the program in SenseLock EL.
		dwResult = S4VerifyPin(&stS4Ctx, lpUserPin, sizeof(lpUserPin), S4_USER_PIN);
		if (dwResult != S4_SUCCESS) 
		{
			printf("Verify Pin failed! <error code: 0x%08x>\n",dwResult);
			S4Close(&stS4Ctx);
			return 0;
		}	
		
		printf("Data to be bubble-ordered:");
		hexprint(stdout, test, sizeof(test));
		
		printf("Execute program \"df01\\ef11\" in SenseLock EL...\n");
		dwResult = S4Execute(&stS4Ctx, S4_EXE_FILE_ID, test, sizeof(test), test, sizeof(test), &dwBytesReturned);
		if (dwResult != S4_SUCCESS) 
		{
			printf("Execute program in SenseLock EL failed! <error code: 0x%08x>\n",dwResult);
			ResetAndCloseS4(&stS4Ctx);
			return 0;
		}
		printf("Success!\n");
		
		printf("Data after being bubble-ordered:");
		hexprint(stdout, test, sizeof(test));
		if (! ReleaseMutex(hMutex)) 
		{ 
			return 0;
		} 
		
	}
	printf("Thread1 finished! \n");
	return 1;
}

unsigned long thread_func2()
{
	unsigned char lpUserPin[8] = "heha1235";
	int i = 0;
	for (; i<100; i++)
	{
		HANDLE hMutex; 
		
		hMutex = CreateMutex( 
			NULL,                  // no security descriptor
			FALSE,                 // mutex not owned
			"NameOfMutexObject");  // object name
		
		if (hMutex == NULL) 
		{
			printf("CreateMutex error: %d\n", GetLastError() ); 
		}
		else if ( GetLastError() == ERROR_ALREADY_EXISTS ) 
		{	
			printf("CreateMutex opened existing mutex\n"); 
		}
		else 
		{
			printf("CreateMutex created new mutex\n"); 
		}
		
		WaitForSingleObject(hMutex, INFINITE);
		
		dwResult = S4ChangeDir(&stS4Ctx, "\\df02");
		if (dwResult != S4_SUCCESS) 
		{
			printf("Change directory failed! <error code: 0x%08x>\n",dwResult);
			S4Close(&stS4Ctx);
			return 0;
		}
		
		// Call S4VerifyPin(...) to verify User PIN so as to get the privilege to execute the program in SenseLock EL.
		dwResult = S4VerifyPin(&stS4Ctx, lpUserPin, sizeof(lpUserPin), S4_USER_PIN);
		if (dwResult != S4_SUCCESS) 
		{
			printf("Verify Pin failed! <error code: 0x%08x>\n",dwResult);
			S4Close(&stS4Ctx);
			return 0;
		}	
		
		printf("Data to be bubble-ordered:");
		hexprint(stdout, test, sizeof(test));
		
		printf("Execute program \"df02\\ef11\" in SenseLock EL...\n");
		dwResult = S4Execute(&stS4Ctx, S4_EXE_FILE_ID, test, sizeof(test), test, sizeof(test), &dwBytesReturned);
		if (dwResult != S4_SUCCESS) 
		{
			printf("Execute program in SenseLock EL failed! <error code: 0x%08x>\n",dwResult);
			ResetAndCloseS4(&stS4Ctx);
			return 0;
		}
		printf("Success!\n");
		
		printf("Data after being bubble-ordered:");
		hexprint(stdout, test, sizeof(test));
		if (! ReleaseMutex(hMutex)) 
		{ 
			return 0;
		} 
		
	}
	printf("Thread2 finished! \n");
	return 1;
}

int main(int argc, char* argv[])
{
	
    DWORD dwThread_1_Id;
	DWORD dwThread_2_Id;
	HANDLE hThread1;
	HANDLE hThread2;

	if (!(dwResult = OpenS4ByIndex(FIRST_S4_INDEX,&stS4Ctx)))
	{
		return 1;
	} 

	hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func1, NULL, 0, &dwThread_1_Id);
	if (hThread1 !=  NULL) 
	{
		CloseHandle(hThread1);
	}
	hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func2, NULL, 0, &dwThread_2_Id);
	if (hThread2 !=  NULL) 
	{
		CloseHandle(hThread2);
	}
	/* pause primary thread */
	getch(); 
	/* for better security,use the following instead of using S4close() directly */
	ResetAndCloseS4(&stS4Ctx);
    

	return dwResult;
}
