
#include "../inc/HR_Loader.h"



//*****************************************
///
/// This function Loads HR_Library C function interface by putting the
/// function pointer for each interface function into the function struct.
///
//*****************************************
HR_StatusType HR_LoaderLoadLib
(
    const char*      inLibraryFilePath, // can be just the file name
    HR_FunctionPtrs* outHRFunctions     // struct of function pointers
)
{
	HR_StatusType status = HR_OK;
    int OSStatus = 0;

	//*************************************
	// Test the arguments for NULL rather than crash
	//*************************************
	if (NULL == inLibraryFilePath) return HR_LOADER_ERR_PATH_NULL;
	if (NULL == outHRFunctions) return HR_LOADER_ERR_FUNCS_NULL;

    // Fill with NULL rather than crash
	memset(outHRFunctions, 0, sizeof(HR_FunctionPtrs));
	

	//*************************************
	// Make the OS call to load the library
	//*************************************
	
	outHRFunctions->WindowsModuleHandle = LoadLibrary(inLibraryFilePath);
	if (NULL == outHRFunctions->WindowsModuleHandle)
	{
		OSStatus = GetLastError(); // Purge the error
		return HR_ERR_LIB_LIB_NOT_FOUND;
	}

	//*************************************
	// load each of the function pointers one at a time
    // Test each one immediately after loading and exit then if error
	//*************************************
	
    if ( HR_OK == status )
	{
		outHRFunctions->OpenLibrary = (HR_OpenLibraryPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_OpenLibrary");
		if (NULL == outHRFunctions->OpenLibrary)
		{
			OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_OPENLIBRARY);
		}
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
		outHRFunctions->CloseLibrary = (HR_CloseLibraryPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_CloseLibrary");
		if (NULL == outHRFunctions->CloseLibrary)
		{
			OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_CLOSELIBRARY);
		}
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->OpenCamera = (HR_OpenCameraPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_OpenCamera");
	    if (NULL == outHRFunctions->OpenCamera)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_OPENCAMERA);            
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->CloseCamera = (HR_CloseCameraPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_CloseCamera");
	    if (NULL == outHRFunctions->CloseCamera)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_CLOSECAMERA);  
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->GetCameraList = (HR_GetCameraListPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_GetCameraList");
	    if (NULL == outHRFunctions->GetCameraList)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_GETCAMERALIST);  
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->TriggerCamera = (HR_TriggerCameraPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_TriggerCamera");
	    if (NULL == outHRFunctions->TriggerCamera)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_TRIGGERCAMERA);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->OpenImage = (HR_OpenImagePtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_OpenImage");
	    if (NULL == outHRFunctions->OpenImage)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_OPENIMAGE);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->CloseImage = (HR_CloseImagePtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_CloseImage");
	    if (NULL == outHRFunctions->CloseImage)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_CLOSEIMAGE);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->DeleteImage = (HR_DeleteImagePtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_DeleteImage");
	    if (NULL == outHRFunctions->DeleteImage)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_DELETEIMAGE);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->GetImageList = (HR_GetImageListPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_GetImageList");
	    if (NULL == outHRFunctions->GetImageList)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_GETIMAGELIST);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->GetParamInfo = (HR_GetParamInfoPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_GetParamInfo");
	    if (NULL == outHRFunctions->GetParamInfo)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_GETPARAMINFO);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->GetParam = (HR_GetParamPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_GetParam");
	    if (NULL == outHRFunctions->GetParam)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_GETPARAM);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->SetParam = (HR_SetParamPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_SetParam");
	    if (NULL == outHRFunctions->SetParam)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_SETPARAM);
	    }
    }
		
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->Poll = (HR_PollPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_Poll");
	    if (NULL == outHRFunctions->Poll)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_POLL);
	    }
    }
		
    //*************************************	
    /*
    if ( HR_OK == status )
	{
	    outHRFunctions->RegisterCallback = (HR_RegisterCallbackPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_RegisterCallback");
	    if (NULL == outHRFunctions->RegisterCallback)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_REGISTERCALLBACK);
	    }
    }
	*/
    //*************************************	
    if ( HR_OK == status )
	{
	    outHRFunctions->GetErrorString = (HR_GetErrorStringPtr)GetProcAddress(
                                        outHRFunctions->WindowsModuleHandle, 
                                        "HR_GetErrorString");
	    if (NULL == outHRFunctions->GetErrorString)
	    {
		    OSStatus = GetLastError(); // Purge the error
            status = (HR_LOADER_ERR_GETERRORSTRING);
	    }
    }
	
	return status;
}



//*************************************	
///
/// This function unloads the loaded library function pointers
///
//*************************************	
HR_StatusType HR_LoaderUnloadLib(HR_FunctionPtrs* inHRFunctions)
{
	HMODULE windowsHandle = 0;
	
	if (NULL == inHRFunctions) return HR_LOADER_ERR_FUNCS_NULL;

	windowsHandle = inHRFunctions->WindowsModuleHandle;

	FreeLibrary(windowsHandle);

	memset(inHRFunctions, 0, sizeof(HR_FunctionPtrs));
	
	return GetLastError(); // Purge the error
}

