Home

Resume

Blog

Teikitu


// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//  »Project«   Teikitu Gaming System (TgS) (∂)
//  »File«      TgS (WIN) Common - Base - API - Platform.c
//  »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  »Version«   4.0
// ------------------------------------------------------------------------------------------------------------------------------ //
//  Copyright: © 2002-2010, Andrew Aye.  All Rights Reserved.
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //

#include "TgS COMMON/TgS (WIN) Common - Base - Exec.h"
#include <stdio.h>
#include <excpt.h>


// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Type Definitions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

typedef struct
{
    TgUINT32                                    dwLowDateTime;
    TgUINT32                                    dwHighDateTime;
} TgMS_FILETIME;

typedef struct
{
    TgUINT32                                    dwFileAttributes;
    TgMS_FILETIME                               ftCreationTime;
    TgMS_FILETIME                               ftLastAccessTime;
    TgMS_FILETIME                               ftLastWriteTime;
    TgUINT32                                    dwVolumeSerialNumber;
    TgUINT32                                    nFileSizeHigh;
    TgUINT32                                    nFileSizeLow;
    TgUINT32                                    nNumberOfLinks;
    TgUINT32                                    nFileIndexHigh;
    TgUINT32                                    nFileIndexLow;
} TgMS_BY_HANDLE_FILE_INFORMATION;

#pragma pack(push, 8)
typedef struct
{
    P_TgVOID                                    DebugInfo;
    TgSINT32                                    LockCount;
    TgSINT32                                    RecursionCount;
    P_TgVOID                                    OwningThread;
    P_TgVOID                                    LockSemaphore;
    P_TgUINT                                    SpinCount;
} TgMS_CRITICAL_SECTION;
#pragma pack(pop)




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  File Local Function
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

unsigned int __stdcall tgTR_Thread_Start( void* pParam )
{
#if TgS_COMPILE_THREAD_INFO
#if TgS_WIDE_CHAR
    TgANSICHAR                          szNameAnsi[1024];
#endif
#pragma pack(push,8)
    struct
    {
        TgUINT32                            dwType; // Must be 0x1000.
        CP_TgANSICHAR                       szName; // Pointer to name (in user addr space).
        TgUINT32                            dwThreadID; // Thread ID (-1=caller thread).
        TgUINT32                            dwFlags; // Reserved for future use, must be zero.
    }                                   tgName_Data;
#pragma pack(pop)
#endif // TgS_COMPILE_THREAD_INFO

    C_TgSINTPTR                         iIndex = (TgSINTPTR)pParam;
    P_TgVOID                            hThread = g_pfnGetCurrentThread();
    TgSINT32                            iRet = -1;

    g_auiTR_Thread_Stack[iIndex] = tgTR_Stack_Size();

#if TgS_COMPILE_THREAD_INFO
#if TgS_WIDE_CHAR
    sprintf( szNameAnsi, "%S", g_aszTR_Name[iIndex] );
    tgName_Data.szName = szNameAnsi;
#else
    tgName_Data.szName = g_aszTR_Name[iIndex];
#endif
    tgName_Data.dwType = 0x1000;
    tgName_Data.dwThreadID = g_pfnGetCurrentThreadId();
    tgName_Data.dwFlags = 0;

    g_pfnSleep(10);

    __try
    {
        g_pfnRaiseException( 0x406D1388, 0, sizeof(tgName_Data) / sizeof(TgUINTPTR), (P_TgVOID)&tgName_Data );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    };
#endif // TgS_COMPILE_THREAD_INFO

    switch (g_aenTR_Thread_Priority[iIndex]) {
    case ETgTHREAD_PRIORITY__CRITICAL:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread, 15 ));
        break;
    case ETgTHREAD_PRIORITY__HIGHEST:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread,  2 ));
        break;
    case ETgTHREAD_PRIORITY__HIGH:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread,  1 ));
        break;
    case ETgTHREAD_PRIORITY__NORMAL:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread, 0 ));
        break;
    case ETgTHREAD_PRIORITY__LOW:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread, -1 ));
        break;
    case ETgTHREAD_PRIORITY__LOWEST:
        TgVERIFY(0 != g_pfnSetThreadPriority( hThread, -2 ));
        break;
    default:
        TgS_NO_DEFAULT(break);
    };

    iRet = g_afnTR_Thread_Function[iIndex]( g_auiTR_Thread_Param[iIndex] );

    _endthreadex( iRet );
    return (iRet);
}


// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
//  Public Functions
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// ---- tgTR_Create ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

extern TgUINTPTR                            g_ahTR_Thread_PM[ETgMAX_THREAD_ENTRIES];

TgSINT32 tgTR_Create(
    TgPLATFORM_THREAD_FCN pfnThread, C_TgUINTPTR uiParam, C_TgUINT32 uiStack, C_ETgTHREAD_PRIORITY enPriority, CPC_TgCHAR szName
) {
    TgSINT32                            iIndex;

    if (0 == pfnThread)
    {
        return (-1);
    }

    tgCM_UTM_SN_Lock_Spin( &g_tgTR_Lock.m_sLock );
    for (iIndex = 0; iIndex < ETgMAX_THREAD_ENTRIES; ++iIndex)
    {
        if (0 != g_afnTR_Thread_Function[iIndex])
        {
            continue;
        };

        g_auiTR_Thread_Stack[iIndex] = 0;
        g_afnTR_Thread_Function[iIndex] = pfnThread;
        g_auiTR_Thread_Param[iIndex] = uiParam;
        g_aenTR_Thread_Priority[iIndex] = enPriority;

    #if TgS_COMPILE_THREAD_INFO
        g_aszTR_Name[iIndex] = szName;
    #endif

        g_ahTR_Thread_PM[iIndex] = _beginthreadex( 0, uiStack, tgTR_Thread_Start, (P_TgVOID)(TgSINTPTR)iIndex, 0, 0 );

        tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );
        return (iIndex);
    };
    tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );
    return ((TgUINTPTR)-1);
}


// ---- tgTR_Close -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTR_Close( C_TgSINT32 iThread_Id )
{
    TgUINTPTR                           hThread;

    // Get the os handle
    tgCM_UTM_SN_Lock_Spin( &g_tgTR_Lock.m_sLock );
    TgASSERT(0 != g_afnTR_Thread_Function[iThread_Id]);
    hThread = g_ahTR_Thread_PM[iThread_Id];
    tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );

    while (0UL != g_pfnWaitForSingleObject( (P_TgVOID)hThread, 0xFFFFFFFF )); //« Wait for thread to close
    TgVERIFY( 0 != g_pfnCloseHandle( (P_TgVOID)hThread ) ); //« Close the handle

    // Mark the thread slot as available
    tgCM_UTM_SN_Lock_Spin( &g_tgTR_Lock.m_sLock );
    g_afnTR_Thread_Function[iThread_Id] = 0;
    tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );
}


// ---- tgTR_Query_Id ----------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgSINT32 tgTR_Query_Id()
{
    TgUINTPTR                           hThread = (TgUINTPTR)g_pfnGetCurrentThread();
    TgSINT32                            iIndex;

    tgCM_UTM_SN_Lock_Spin( &g_tgTR_Lock.m_sLock );

    for (iIndex = 0; iIndex < ETgMAX_THREAD_ENTRIES; ++iIndex)
    {
        if (hThread == g_ahTR_Thread_PM[iIndex])
        {
            tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );
            return (iIndex);
        };
    };

    tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );
    return (-1);
}


// ---- tgTR_Sleep -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTR_Sleep( C_TgUINT32 uiSleep_MS )
{
    g_pfnSleep( uiSleep_MS );
}


// ---- tgTR_Suspend ------------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTR_Suspend()
{
    g_pfnSuspendThread( g_pfnGetCurrentThread() );
}


// ---- tgTR_Resume ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTR_Resume( C_TgSINT32 iThread_Id )
{
    TgUINTPTR                           hThread;

    // Get the os handle
    tgCM_UTM_SN_Lock_Spin( &g_tgTR_Lock.m_sLock );
    TgASSERT(0 != g_afnTR_Thread_Function[iThread_Id]);
    hThread = g_ahTR_Thread_PM[iThread_Id];
    tgCM_UTM_SN_Signal( &g_tgTR_Lock.m_sLock );

    g_pfnResumeThread( (P_TgVOID)hThread );
}


// ---- tgTR_Stack_Size --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgUINT32 tgTR_Stack_Size()
{
    struct {
        P_TgVOID                            DoNotUse00;
        P_TgVOID                            StackBase;
        P_TgVOID                            StackLimit;
        P_TgVOID                            DoNotUse01;
        P_TgVOID                            DoNotUse02;
        P_TgVOID                            DoNotUse03;
        P_TgVOID                            Self;
    }                                   *pTEB;

#if TgCOMPILE_64BIT_POINTER
    pTEB = (P_TgVOID)__readgsqword(48);
#else
    pTEB = (P_TgVOID)__readfsdword(24);
#endif

    return ((TgUINT32)((P_TgUINT08)(pTEB->StackBase) - (P_TgUINT08)(pTEB->StackLimit)));
}




// == Time Functions ============================================================================================================ //

static TgFLOAT64                    s_fFreq;
static TgMS_LARGE_INTEGER           s_iStart;
static TgFLOAT32                    s_fLast;
static TgFLOAT32                    s_fElapsed;
static TgFLOAT32                    s_fStop;


// ---- tgTM_Query_Absolute_Time ------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgFLOAT32 tgTM_Query_Absolute_Time()
{
    TgMS_LARGE_INTEGER                  iTime;
    g_pfnQueryPerformanceCounter( &iTime );
    return ((TgFLOAT32)(((TgFLOAT64)(iTime.QuadPart - s_iStart.QuadPart)) * s_fFreq));
}


// ---- tgTM_Query_Time --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgFLOAT32 tgTM_Query_Time()
{
    return (tgPM_FSEL_F32(-s_fStop, tgTM_Query_Absolute_Time(), s_fStop ));
}


// ---- tgTM_Elapsed_Time ------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgFLOAT32 tgTM_Elapsed_Time()
{
    return (s_fElapsed);
}


// ---- tgTM_Init --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Init()
{
    TgMS_LARGE_INTEGER                  iPerf;

    g_pfnQueryPerformanceFrequency( &iPerf );

    s_fFreq = 1.0 / (TgFLOAT64)iPerf.QuadPart;

    tgTM_Reset();
}

// ---- tgTM_Reset -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Reset()
{
    g_pfnQueryPerformanceCounter( &s_iStart );
    s_fLast = tgTM_Query_Absolute_Time();
    s_fElapsed = 1.0F / 60.0F;
    s_fStop = 0.0F;
}


// ---- tgTM_Start -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Start()
{
    if (!(s_fStop <= 0.0F))
    {
        s_fLast = tgTM_Query_Absolute_Time();
        s_fStop = 0.0F;
    };
}


// ---- tgTM_Stop --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Stop()
{
    if (!(s_fStop > 0.0F))
    {
        s_fStop = s_fLast;
    };
}


// ---- tgTM_Update ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Update()
{
    if (!(s_fStop > 0.0F))
    {
        C_TgFLOAT32 fTime                   = tgTM_Query_Absolute_Time();
        s_fElapsed                          = tgCM_MAX_F32( KTgEPS_F32, fTime - s_fLast );
        s_fLast                             = fTime;
        s_fStop                             = 0.0F;
    };
}


// ---- tgTM_Step --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgTM_Step( C_TgFLOAT32 fTimeAdvance )
{
    s_fStop += fTimeAdvance;
}




// == IO Functions ============================================================================================================== //

// ---- File_Error -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
static TgVOID File_Error( C_TgSINTPTR iFile )
{
    TgMS_BY_HANDLE_FILE_INFORMATION     sData;
    TgCHAR                              szBuf[256]; 
    P_TgVOID                            pMsgBuf;
    C_TgUINT32                          dwError = g_pfnGetLastError();

    TgASSERT(((TgSINTPTR)-1) != iFile);

    g_pfnGetFileInformationByHandle( (P_TgVOID)iFile, &sData );
    g_pfnFormatMessage( 0x00001100, 0, dwError, (1<<10), (P_TgCHAR)&pMsgBuf, 0, NULL );
    tgSZ_PrintF( szBuf, 256, TgT("File_Read failed with error %d: %s"), dwError, pMsgBuf );
    g_pfnLocalFree( pMsgBuf );

    g_pfnOutputDebugString( szBuf );
    TgCRITICAL_MSGF( 0, TgT("%s\n"), szBuf );
}


// ---- tgIO_File_Open ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Open( P_TgSINTPTR piFile, CPC_TgCHAR pszFile, ETgFILE_IO_ACCESS enAccess )
{
    TgUINT32                            dwDesiredAccess=0, dwShareMode=0;
    P_TgVOID                            hFile;

    TgASSERT((0 != piFile) && (0 != pszFile));

    switch (enAccess) {
    case ETgFILE_IO_ACCESS_INVALID:
        return (TgE_FAIL);

    case ETgFILE_IO_ACCESS_READ_SHARED:
        dwShareMode = 0x00000001L;
    case ETgFILE_IO_ACCESS_READ:
        dwDesiredAccess = 0x00120089L;
        break;

    case ETgFILE_IO_ACCESS_WRITE_SHARED:
        dwShareMode = 0x00000002L;
    case ETgFILE_IO_ACCESS_WRITE:
        dwDesiredAccess = 0x00120116L;
        break;

    case ETgFILE_IO_ACCESS_READ_WRITE_SHARED:
        dwShareMode = 0x00000003L;
    case ETgFILE_IO_ACCESS_READ_WRITE:
        dwDesiredAccess = 0x0012019FL;
        break;

    default:
        TgS_NO_DEFAULT(break);
    };

    hFile = g_pfnCreateFile( pszFile, dwDesiredAccess, dwShareMode, 0, 4, 0x10000080L, 0 );
    *piFile = (TgSINTPTR)hFile;
    return (hFile != ((P_TgVOID)(TgSINTPTR)-1) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_File_Read ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgSINT32 tgIO_File_Read( C_TgSINTPTR iFile, PC_TgVOID pDest, C_TgSINT32 nBytesToRead )
{
    TgUINT32                            nBytesRead;

    TgASSERT(((TgSINTPTR)-1) != iFile);

    if (!(g_pfnReadFile( (P_TgVOID)iFile, pDest, nBytesToRead, &nBytesRead, NULL)))
    {
        File_Error( iFile );
    };

    return ((TgSINT32)nBytesRead);
}


// ---- tgIO_File_Write --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgSINT32 tgIO_File_Write( C_TgSINTPTR iFile, CPC_TgVOID pSource, C_TgSINT32 nBytesToWrite )
{
    TgUINT32                            nBytesWrite;

    TgASSERT(((TgSINTPTR)-1) != iFile);

    if (!(g_pfnWriteFile( (P_TgVOID)iFile, pSource, nBytesToWrite, &nBytesWrite, NULL)))
    {
        File_Error( iFile );
    };

    return (nBytesWrite);
}


// ---- tgIO_File_Flush --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Flush( C_TgSINTPTR iFile )
{
    TgASSERT(((TgSINTPTR)-1) != iFile);
    TgVERIFY(0 != g_pfnFlushFileBuffers( (P_TgVOID)iFile ));
    return (TgS_OK);
}


// ---- tgIO_File_Close --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Close( C_TgSINTPTR iFile )
{
    TgASSERT(((TgSINTPTR)-1) != iFile);
    TgVERIFY(0 != g_pfnCloseHandle( (P_TgVOID)iFile ));
    return (TgS_OK);
}


// ---- tgIO_File_Valid --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgBOOL tgIO_File_Valid( C_TgSINTPTR iFile )
{
    TgASSERT(((TgSINTPTR)-1) != iFile);
    return (((TgSINTPTR)-1) != iFile ? TgTRUE : TgFALSE);
}


// ---- tgIO_File_Seek ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Seek( C_TgSINTPTR iFile, C_ETgIO_SEEK enSeek_Mode, C_TgSINT32 iPos )
{
    TgBOOL                              bSuccess = TgFALSE;
    TgUINT32                            uiSet;

    TgASSERT(((TgSINTPTR)-1) != iFile);

    switch (enSeek_Mode) {
    case ETgIO_SEEK_BEGIN:
        uiSet = g_pfnSetFilePointer( (P_TgVOID)iFile, iPos, 0, 0 );
        break;
    case ETgIO_SEEK_END:
        uiSet = g_pfnSetFilePointer( (P_TgVOID)iFile, iPos, 0, 2 );
        break;
    case ETgIO_SEEK_CURRENT:
        uiSet = g_pfnSetFilePointer( (P_TgVOID)iFile, iPos, 0, 1 );
        break;

    default:
        TgS_NO_DEFAULT(return (TgE_FAIL));
    }

    bSuccess = (TgSINT32)uiSet >= 0;

#if defined(_DEBUG)
    {
        TgUINT32                            uiNew_Position = g_pfnSetFilePointer( (P_TgVOID)iFile, 0, 0, 1 );

        bSuccess &= uiNew_Position <= tgIO_File_Size( iFile );
    }
#endif // defined(_DEBUG)

    return (bSuccess ? TgS_OK : TgE_FAIL);

}


// ---- tgIO_File_Size ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgSIZE tgIO_File_Size( C_TgSINTPTR iFile )
{
    TgUINT32                            uiHigh, uiLow;

    TgASSERT(((TgSINTPTR)-1) != iFile);
    uiLow = g_pfnGetFileSize( (P_TgVOID)iFile, &uiHigh );
    return (((TgSIZE)uiHigh << 31) | uiLow);
}


// ---- tgIO_Directory_Make ----------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_Directory_Make( CPC_TgCHAR pszPath )
{
    return (g_pfnCreateDirectory( pszPath, 0 ) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_Directory_Remove --------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_Directory_Remove( CPC_TgCHAR pszPath )
{
    return (g_pfnRemoveDirectory( pszPath ) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_Directory_Exists --------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgBOOL tgIO_Directory_Exists( CPC_TgCHAR pszPath )
{
    C_TgUINT32                          dwAttrib = g_pfnGetFileAttributes( pszPath );
    return (~0u != dwAttrib && 0 != (0x00000010 & dwAttrib) ? TgTRUE : TgFALSE);
}


// ---- tgIO_File_Delete -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Delete( CPC_TgCHAR pszFile )
{
    return (g_pfnDeleteFile( pszFile ) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_File_Copy ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Copy( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
    return (g_pfnCopyFile( pszExisting, pszDest, TgTRUE ) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_File_Move ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgIO_File_Move( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
    return (g_pfnMoveFile( pszExisting, pszDest ) ? TgS_OK : TgE_FAIL);
}


// ---- tgIO_File_Exists -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgBOOL tgIO_File_Exists( CPC_TgCHAR pszFile )
{
    C_TgUINT32                          dwAttrib = g_pfnGetFileAttributes( pszFile );
    return (~0u != dwAttrib && 0 == (0x00000010 & dwAttrib) ? TgTRUE : TgFALSE);
}




// == Synchronization Functions ================================================================================================= //

// ---- tgCM_MP_CS_Init -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgRESULT tgCM_MP_CS_Init( PCU_STg1_MP_CS ptgCS )
{
    ptgCS->m_pcsTimeLock = _aligned_malloc( sizeof(TgMS_CRITICAL_SECTION), TgCOMPILE_CACHE_LINE_SIZE );
    if (NULL == ptgCS->m_pcsTimeLock)
    {
        return (TgE_FAIL);
    }
    g_pfnInitializeCriticalSection( ptgCS->m_pcsTimeLock );
    return (TgS_OK);
}


// ---- tgCM_MP_CS_Free -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //
TgVOID tgCM_MP_CS_Free( PCU_STg1_MP_CS ptgCS )
{
    g_pfnDeleteCriticalSection( ptgCS->m_pcsTimeLock );
    _aligned_free( ptgCS->m_pcsTimeLock );
    ptgCS->m_pcsTimeLock = NULL;
}