/*******************************************************************************
 * Copyright (c) 2005, 2007 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Hoang M Nguyen, Intel - TPTP OS Calls Windows specific implementation
 * $Id: TPTPOSCalls_win.c,v 1.11 2007/04/13 16:05:43 jkubasta Exp $
 *******************************************************************************/ 


#ifdef _WIN32     // Windows-specific


#include <stdio.h>
#include "TPTPOSCalls.h"
#include <string.h>


const char OS_SPECIFIC_NAME_SEPARATOR = '\\' ;

/**
 *********************************************************
 *
 * @brief
 *    Return a global unique id string (GUID or UUID)
 *
 * @note
 *    This requires to link with Windows "rpcrt4.lib" library.
 *    The caller is responsible to free the returned string using free() function
 *
 *********************************************************/

char * getGlobalUniqueId()
{
   char *pTokenStr = NULL ;

   UUID  token ;

   int rc = UuidCreate(&token) ;

   unsigned char * pIdStr = NULL ;

   rc = UuidToString(&token, &pIdStr) ;

   if (pIdStr != NULL)
   {
	   pTokenStr = strdup(pIdStr) ;
	   
	   RpcStringFree(&pIdStr) ;
   } 

   return ( pTokenStr ) ;
}

/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    convenient way to compare string ignoring case
 *    and is still platform independent.
 *
 *********************************************************/
 
int compareIgnoreCase(const char *pStr1, const char *pStr2)
{
	return ( stricmp(pStr1, pStr2) ) ;
}


/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    load a given DLL name
 *
 *********************************************************/

void * loadTheModule(const char *pLibName)
{
	int rc = 0 ;
	HINSTANCE  dllHolder = NULL ;

	//printf("load this library: %s...\n", pLibName) ;

	dllHolder = LoadLibrary( pLibName ) ;

	return (void *) dllHolder ;
}


/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Start a new running thread and execute the given function
 *       in that running thread.
 *
 * @return
 *    0 - Success
 *    Nonzero - Error
 *
 *********************************************************/

int  startNewThread(RUN_FUNC_TYPE  pFunc, void * pParmBlock, TID *pThreadId, HANDLE *pThreadHandle)
{
	int    rc = 0 ;

	*pThreadHandle = CreateThread(NULL, 0, pFunc, (PVOID) pParmBlock, 0, pThreadId);

	if (*pThreadHandle == NULL)
		rc = 1 ;

	return ( rc ) ;
}

int  tptpStartThread(RUN_FUNC_TYPE  pFunc, void * pParamBlock, TID *pThreadId, HANDLE *pThreadHandle)
{
	return startNewThread (pFunc, pParamBlock, pThreadId, pThreadHandle);
}

/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Return the process id of the current running process
 *
 *********************************************************/

PID  getCurrentlyRunningProcessId()
{
	return ( GetCurrentProcessId() ) ;
}

/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Return the executable name of the current running process.
 *    Caller must free the allocated memory for the name string returned.
 *
 *********************************************************/

char *getExecutableName()
{
	char *ptr = NULL;
	char *commandLine = GetCommandLine();
	char *exeName = NULL;
	int len = 0;

	if (!commandLine) return NULL;

	/* Strip off any arguments that following the command name */
	ptr = commandLine;
	len = 0;
	while (*ptr!='\0' && *ptr!=' ' && *ptr!='\t' && *ptr!='\n')
	{
		ptr++;
		len++;
	}

	if (len < 1) return NULL;
	exeName = (char *)tptp_malloc(len +1);
	strncpy(exeName, commandLine, len);
	exeName[len] = '\0';
	return exeName;

}

/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Return the process id of the current running process
 *
 *********************************************************/

TID  getCurrentlyRunningThreadId()
{
	return ( GetCurrentThreadId() ) ;
}

/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Print out the current system error message
 *
 *********************************************************/
void printCurrentSysError()
{
		LPVOID lpMsgBuf;
		FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPTSTR) &lpMsgBuf,
			0,
			NULL 
		);

		printf( (LPTSTR)lpMsgBuf );

		// Free the buffer.
		LocalFree( lpMsgBuf );
}


/**
 *********************************************************
 *                                                       
 * @brief                                                
 *    Put the current thread in sleep mode
 *    for a given amount of time (in milliseconds)
 *
 *********************************************************/
void  tptpSleep(int milliseconds)
{
	Sleep(milliseconds) ;
}

#endif   // end-of-Windows-specific

