Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS (WIN) Common - SysInfo.c
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, 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:
    Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
    Redistribution 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.
    The name of the author may not 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".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */

#pragma warning( push, 3 )
#include <time.h>
#pragma warning( pop )
#pragma warning(disable : 4201) /* nonstandard extension used: nameless struct/union */


/* == Common ============================================================================================================================================================ */

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Constants                                                                                                                                                             */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

enum { ETgSI_MAX_MONITOR                            = 32 };

/* #define SM_CMONITORS                                80 */
#define SM_CLEANBOOT                                67
#define SM_NETWORK                                  63
#define SM_CXDOUBLECLK                              36
#define SM_CYDOUBLECLK                              37
#define SM_CXDRAG                                   68
#define SM_CYDRAG                                   69
/* #define SM_SERVERR2                                 89 */
#define SM_MOUSEWHEELPRESENT                        75
#define SM_MOUSEPRESENT                             19
/* #define PROCESSOR_ARCHITECTURE_AMD64                 9 */
/* #define VER_NT_WORKSTATION                   0x0000001 */
/* #define VER_SUITE_WH_SERVER                 0x00008000 */
/* #define PF_COMPARE_EXCHANGE_DOUBLE                   2 */
#define PF_MMX_INSTRUCTIONS_AVAILABLE                3
#define PF_XMMI_INSTRUCTIONS_AVAILABLE               6
#define PF_3DNOW_INSTRUCTIONS_AVAILABLE              7
#define PF_RDTSC_INSTRUCTION_AVAILABLE               8
/* #define PF_XMMI64_INSTRUCTIONS_AVAILABLE            10 */
/* #define PF_SSE3_INSTRUCTIONS_AVAILABLE              13 */
/* #define PF_COMPARE_EXCHANGE128                      14 */
/* #define PF_COMPARE64_EXCHANGE128                    15 */




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions and Data                                                                                                                                         */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

#if !defined(TgCOMPILE_PLATFORM_UWP)
static TgBOOL __stdcall                     Monitor_Handle_Callback( TgMS_HMONITOR, TgMS_HDC, P_TgVOID, TgSINT64 );
#endif

static TgRESULT                             Init_Timer( TgVOID );
TgINLINE TgVOID                             SYSTEM_Set_Mouse( C_TgBOOL );
TgINLINE TgVOID                             SYSTEM_Set_Network( C_TgBOOL );
TgINLINE TgVOID                             SYSTEM_Set_Clean_Boot( C_TgBOOL );
TgINLINE TgBOOL                             SYSTEM_Has_Mouse( TgVOID );
TgINLINE TgBOOL                             SYSTEM_Has_Network( TgVOID );
TgINLINE TgBOOL                             SYSTEM_Clean_Boot( TgVOID );
TgINLINE TgVOID                             MATH_Set_MMX( C_TgBOOL );
TgINLINE TgVOID                             MATH_Set_XMM( C_TgBOOL );
TgINLINE TgVOID                             MATH_Set_XMM2( C_TgBOOL );
TgINLINE TgVOID                             MATH_Set_3DNow( C_TgBOOL );
TgINLINE TgVOID                             MATH_Set_RDTSC( C_TgBOOL );
TgINLINE TgBOOL                             MATH_Has_MMX( TgVOID );
TgINLINE TgBOOL                             MATH_Has_XMM( TgVOID );
TgINLINE TgBOOL                             MATH_Has_XMM2( TgVOID );
TgINLINE TgBOOL                             MATH_Has_3DNow( TgVOID );
TgINLINE TgBOOL                             MATH_Has_RDTSC( TgVOID );
TgINLINE TgVOID                             INPUT_Set_Mouse_Wheel( C_TgBOOL );

/* Console Functions */
#if TgCOMPILE_CONSOLE
static TgVOID                               SI_CO_Print_Configuration( C_TgUINT32 nuiArg, CP_TgCHAR pArgV[KTgMAX_CMD_LINE_COUNT] );
static TgVOID                               SI_CO_Print_Modules( C_TgUINT32 nuiArg, CP_TgCHAR pArgV[KTgMAX_CMD_LINE_COUNT] );
static TgVOID                               SI_CO_Print_Threads( C_TgUINT32 nuiArg, CP_TgCHAR pArgV[KTgMAX_CMD_LINE_COUNT] );
/*# TgCOMPILE_CONSOLE */
#endif

static ETgMODULE_STATE                      s_enSI_PM_State = ETgMODULE_STATE__FREED;

/* System Parameters */
static TgUINT32                             s_uiSI_Page_Size = 0;
static TgFLOAT64                            s_fSI_Seconds_Per_CounterTick = 0.0;
static P_TgCHAR                             s_szSI_System_Dir = nullptr;
static P_TgCHAR                             s_szSI_Window_Dir = nullptr;
static P_TgCHAR                             s_szSI_Current_Dir = nullptr;
static P_TgCHAR                             s_szSI_Module_Dir = nullptr;
static P_TgCHAR                             s_szSI_Computer_Name = nullptr;
static P_TgCHAR                             s_szSI_User_Name = nullptr;
static P_TgCHAR                             s_szSI_Hardware_Profile_GUID = nullptr;
static P_TgCHAR                             s_szSI_Hardware_Profile_Name = nullptr;
static TgUINT32                             s_nuiSI_Processors = 0;
static TgMS_HMONITOR                        *s_aSI_Monitor_Handle = nullptr;
static TgSINT32                             s_niSI_Monitors = 0;
#if !defined(TgCOMPILE_PLATFORM_UWP)
static P_TgMS_RECT                          s_aSI_Monitor_Work_Rect = nullptr;
static P_TgMS_RECT                          s_aSI_Monitor_Virt_Rect = nullptr;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

/* Input Parameters */
static TgUINT32                             s_uiSI_IN_Mouse_Bounds_X_Double_Click = 0;
static TgUINT32                             s_uiSI_IN_Mouse_Bounds_Y_Double_Click = 0;
static TgUINT32                             s_uiSI_IN_Mouse_Bounds_X_Drag = 0;
static TgUINT32                             s_uiSI_IN_Mouse_Bounds_Y_Drag = 0;

static TgUINT32                             s_uiSI_Bounds_Hover_Height = 0;
static TgUINT32                             s_uiSI_Bounds_Hover_Width = 0;
static TgUINT32                             s_uiSI_Bounds_Hover_Time = 0;
static P_TgCHAR                             s_pszSI_String_Pool = 0;

static TgUINT32                             s_bfSystemChecks = 0;
static TgUINT32                             s_bfInputChecks = 0;




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

/* == Platform Implementation =========================================================================================================================================== */

/* ---- tgSI_PM_Init --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgSI_PM_Init( TgVOID )
{
    TgCHAR                              szTemp[6][512];
    TgUINT32                            uiSize[8];
    TgSINT32                            iSize;
    TgRESULT                            iResult;
#if !defined(TgCOMPILE_PLATFORM_UWP)
    TgMS_HMONITOR                       aSI_Monitor_Handle[ETgSI_MAX_MONITOR];
    TgSINT32                            iIndex;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    struct
    {
        union
        {
            TgUINT32                            dwOemId;
            struct
            {
                TgUINT16                            wProcessorArchitecture;
                TgUINT16                            wReserved;
            }                                   DUMMYSTRUCTNAME;
        }                                   DUMMYUNIONNAME;
        TgUINT32                            dwPageSize;
        P_TgVOID                            lpMinimumApplicationAddress;
        P_TgVOID                            lpMaximumApplicationAddress;
        P_TgUINT32                          dwActiveProcessorMask;
        TgUINT32                            dwNumberOfProcessors;
        TgUINT32                            dwProcessorType;
        TgUINT32                            dwAllocationGranularity;
        TgUINT16                            wProcessorLevel;
        TgUINT16                            wProcessorRevision;
    }                                   siSystemInfo;

    struct
    {
        TgUINT32                            dwDockInfo;
        TgCHAR                              szHwProfileGuid[39];
        TgCHAR                              szHwProfileName[81];
    }                                   siHardwareProfile;

    /* Verify the state of the system */
    TgERROR(ETgMODULE_STATE__FREED == s_enSI_PM_State);
    s_enSI_PM_State = ETgMODULE_STATE__INITIALIZING;

    uiSize[0] = 512;
    uiSize[1] = 512;
    uiSize[2] = 512;
    uiSize[3] = 512;
    uiSize[4] = 128;
    uiSize[5] = 512;
    uiSize[6] = 80;
    uiSize[7] = 39;

    tgBF_Reset_U32( &s_bfSystemChecks );
    tgBF_Reset_U32( &s_bfInputChecks );

    g_pfnGetSystemInfo( (TgMS_LPSYSTEM_INFO)&siSystemInfo );

    s_uiSI_Page_Size = siSystemInfo.dwPageSize;
    s_nuiSI_Processors = (TgUINT08)siSystemInfo.dwNumberOfProcessors;

#if !defined(TgCOMPILE_PLATFORM_UWP)
    SYSTEM_Set_Clean_Boot( 0 == g_pfnGetSystemMetrics( SM_CLEANBOOT ) );
    SYSTEM_Set_Mouse( 0 != g_pfnGetSystemMetrics( SM_MOUSEPRESENT ) );
    SYSTEM_Set_Network( 0 != g_pfnGetSystemMetrics( SM_NETWORK ) );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    MATH_Set_MMX( 0 != g_pfnIsProcessorFeaturePresent( PF_MMX_INSTRUCTIONS_AVAILABLE ) );
    MATH_Set_XMM( 0 != g_pfnIsProcessorFeaturePresent( PF_XMMI_INSTRUCTIONS_AVAILABLE ) );
    MATH_Set_3DNow( 0 != g_pfnIsProcessorFeaturePresent( PF_3DNOW_INSTRUCTIONS_AVAILABLE ) );
    MATH_Set_RDTSC( 0 != g_pfnIsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE ) );

#if !defined(TgCOMPILE_PLATFORM_UWP)
    s_uiSI_IN_Mouse_Bounds_X_Double_Click = (TgUINT08)g_pfnGetSystemMetrics( SM_CXDOUBLECLK );
    s_uiSI_IN_Mouse_Bounds_Y_Double_Click = (TgUINT08)g_pfnGetSystemMetrics( SM_CYDOUBLECLK );
    s_uiSI_IN_Mouse_Bounds_X_Drag = (TgUINT08)g_pfnGetSystemMetrics( SM_CXDRAG );
    s_uiSI_IN_Mouse_Bounds_Y_Drag = (TgUINT08)g_pfnGetSystemMetrics( SM_CYDRAG );

    g_pfnSystemParametersInfo( 0x0066, nullptr, &s_uiSI_Bounds_Hover_Time, 0 );
    g_pfnSystemParametersInfo( 0x0062, nullptr, &s_uiSI_Bounds_Hover_Height, 0 );
    g_pfnSystemParametersInfo( 0x0064, nullptr, &s_uiSI_Bounds_Hover_Width, 0 );

    INPUT_Set_Mouse_Wheel( 0 != g_pfnGetSystemMetrics( SM_MOUSEWHEELPRESENT ) );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    /* Init String Data - Directories, Computer and User Name */
    uiSize[0] = g_pfnGetCurrentDirectory( uiSize[0], szTemp[0] ) + 1;
#if !defined(TgCOMPILE_PLATFORM_UWP)
    uiSize[1] = g_pfnGetSystemDirectory( szTemp[1], uiSize[1] ) + 1;
    uiSize[2] = g_pfnGetWindowsDirectory( szTemp[2], uiSize[2] ) + 1;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#else
    szTemp[1][0] = 0;
    uiSize[1] = 1;
    szTemp[2][0] = 0;
    uiSize[2] = 1;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif
    uiSize[3] = g_pfnGetModuleFileName( nullptr, szTemp[3], uiSize[3] ) + 1;

#if !defined(TgCOMPILE_PLATFORM_UWP)
    if (0 == g_pfnGetComputerNameEx( 3, szTemp[4], &uiSize[4] ))
    {
        tgSZ_Copy( szTemp[4], TgARRAY_COUNT( szTemp[4] ), TgTEXT("Error") );
        uiSize[4] = 6;
    }
    else
    {
        ++uiSize[4];
    };

    if (0 == g_pfnGetUserName( szTemp[5], &uiSize[5] ))
    {
        tgSZ_Copy( szTemp[5], TgARRAY_COUNT( szTemp[5] ), TgTEXT("Error") );
        uiSize[5] = 6;
    }
    else
    {
        ++uiSize[5];
    };

    if (0 == g_pfnGetCurrentHwProfile( &siHardwareProfile ))
    {
        tgSZ_Copy( siHardwareProfile.szHwProfileGuid, TgARRAY_COUNT( siHardwareProfile.szHwProfileGuid ), TgTEXT("Error") );
        tgSZ_Copy( siHardwareProfile.szHwProfileName, TgARRAY_COUNT( siHardwareProfile.szHwProfileName ), TgTEXT("Error") );
        uiSize[6] = 6;
        uiSize[7] = 6;
    }
    else
    {
        uiSize[6] = (TgUINT32)tgSZ_Length( siHardwareProfile.szHwProfileGuid ) + 1;
        uiSize[7] = (TgUINT32)tgSZ_Length( siHardwareProfile.szHwProfileName ) + 1;
    };
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#else
    szTemp[4][0] = 0;
    uiSize[4] = 1;
    szTemp[5][0] = 0;
    uiSize[5] = 1;
    siHardwareProfile.szHwProfileGuid[0] = 0;
    uiSize[6] = 1;
    siHardwareProfile.szHwProfileName[0] = 0;
    uiSize[7] = 1;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    /* Concatenate all the Temp Buffers into one allocated permanent buffer */
    iSize = (TgSINT32)(uiSize[0] + uiSize[1] + uiSize[2] + uiSize[3] + uiSize[4] + uiSize[5] + uiSize[6] + uiSize[7] + 1u);
    s_pszSI_String_Pool = (P_TgCHAR)(malloc( sizeof( TgCHAR ) * (TgSIZE)iSize ));
    TgERROR(nullptr != s_pszSI_String_Pool);

    s_szSI_Current_Dir = s_pszSI_String_Pool;
    s_szSI_System_Dir = s_szSI_Current_Dir + uiSize[0];
    s_szSI_Window_Dir = s_szSI_System_Dir + uiSize[1];
    s_szSI_Module_Dir = s_szSI_Window_Dir + uiSize[2];
    s_szSI_Computer_Name = s_szSI_Module_Dir + uiSize[3];
    s_szSI_User_Name = s_szSI_Computer_Name + uiSize[4];
    s_szSI_Hardware_Profile_GUID = s_szSI_User_Name + uiSize[5];
    s_szSI_Hardware_Profile_Name = s_szSI_Hardware_Profile_GUID + uiSize[6];

    /* Error Control placed in - BUT there should be no time in which its true */
    if (uiSize[0] >= 512)
        g_pfnGetCurrentDirectory( uiSize[0], s_szSI_Current_Dir );
    else tgSZ_Copy( s_szSI_Current_Dir, uiSize[0], szTemp[0] );

#if !defined(TgCOMPILE_PLATFORM_UWP)
    if (uiSize[1] >= 512)
        g_pfnGetSystemDirectory( s_szSI_System_Dir, uiSize[1] );
    else tgSZ_Copy( s_szSI_System_Dir, uiSize[1], szTemp[1] );

    if (uiSize[2] >= 512)
    {
        TgVERIFY( uiSize[2] == g_pfnGetWindowsDirectory( s_szSI_Window_Dir, uiSize[2] ) );
    }
    else tgSZ_Copy( s_szSI_Window_Dir, uiSize[2], szTemp[2] );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#else
    s_szSI_System_Dir[0] = 0;
    s_szSI_Window_Dir[0] = 0;
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    if (uiSize[3] >= 512)
        g_pfnGetModuleFileName( nullptr, s_szSI_Module_Dir, uiSize[3] );
    else tgSZ_Copy( s_szSI_Module_Dir, uiSize[3], szTemp[3] );

    tgSZ_Copy( s_szSI_Computer_Name, uiSize[4], szTemp[4] );
    tgSZ_Copy( s_szSI_User_Name, uiSize[5], szTemp[5] );
    tgSZ_Copy( s_szSI_Hardware_Profile_GUID, uiSize[6], siHardwareProfile.szHwProfileGuid );
    tgSZ_Copy( s_szSI_Hardware_Profile_Name, uiSize[7], siHardwareProfile.szHwProfileName );

    /* Multi Monitor Support Queries */
    s_niSI_Monitors = 0;
#if !defined(TgCOMPILE_PLATFORM_UWP)
    s_aSI_Monitor_Handle = aSI_Monitor_Handle;
    g_pfnEnumDisplayMonitors( nullptr, nullptr, Monitor_Handle_Callback, 0 );
    if (!(s_niSI_Monitors > 0))
    {
        TgERROR_MSGF( 0, TgT("%-16.16s(%-32.32s): Failed to Find a Monitor.\n"), TgT("Global"), TgT("Init") );
        return (KTgE_FAIL);
    };

    s_aSI_Monitor_Work_Rect = (P_TgMS_RECT)malloc( (TgSIZE)s_niSI_Monitors*sizeof( TgMS_RECT ) );
    s_aSI_Monitor_Virt_Rect = (P_TgMS_RECT)malloc( (TgSIZE)s_niSI_Monitors*sizeof( TgMS_RECT ) );
    s_aSI_Monitor_Handle = (TgMS_HMONITOR*)malloc( (TgSIZE)s_niSI_Monitors*sizeof( TgMS_HMONITOR ) );

    memcpy( s_aSI_Monitor_Handle, aSI_Monitor_Handle, (TgSIZE)s_niSI_Monitors*sizeof( TgMS_HMONITOR ) );

    for (iIndex = 0; iIndex < s_niSI_Monitors; ++iIndex)
    {
        struct
        {
            TgUINT32                            cbSize;
            TgMS_RECT                           rcMonitor;
            TgMS_RECT                           rcWork;
            TgUINT32                            dwFlags;
        }                                   tgMonitor_Info;

        tgMonitor_Info.cbSize = sizeof( tgMonitor_Info );

        if (g_pfnGetMonitorInfo( aSI_Monitor_Handle[iIndex], &tgMonitor_Info ))
        {
            s_aSI_Monitor_Work_Rect[iIndex] = tgMonitor_Info.rcWork;
            s_aSI_Monitor_Virt_Rect[iIndex] = tgMonitor_Info.rcMonitor;
        }
        else
        {
            memset( s_aSI_Monitor_Work_Rect + iIndex, 0, sizeof( TgMS_RECT ) );
            memset( s_aSI_Monitor_Virt_Rect + iIndex, 0, sizeof( TgMS_RECT ) );
        };
    };
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    /* Init the CPU Counter to Real Time Translation */
    srand( (unsigned)time( nullptr ) );
    iResult = Init_Timer();
    s_enSI_PM_State = ETgMODULE_STATE__INITIALIZED;

    if (TgFAILED( iResult ))
    {
        tgSI_PM_Free();
        return (KTgE_FAIL);
    };
    return (KTgS_OK);
}

/* ---- tgSI_PM_Boot --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgSI_PM_Boot( TgVOID )
{
    /* Verify the state of the system */
    TgERROR(ETgMODULE_STATE__INITIALIZED == s_enSI_PM_State);
    s_enSI_PM_State = ETgMODULE_STATE__BOOTING;

#if TgCOMPILE_CONSOLE
    tgCN_Insert_Command_Function( TgT("print_info_configuration"), SI_CO_Print_Configuration, TgT("Print basic operating system information") );
    tgCN_Insert_Command_Function( TgT("print_info_modules"), SI_CO_Print_Modules, TgT("Print a list of modules current loads (DLLs)") );
    tgCN_Insert_Command_Function( TgT("print_info_threads"), SI_CO_Print_Threads, TgT("Print a list of all the active threads") );
/*# TgCOMPILE_CONSOLE */
#endif

    s_enSI_PM_State = ETgMODULE_STATE__BOOTED;
    return (KTgS_OK);
}


/* ---- tgSI_PM_Stop --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgSI_PM_Stop( TgVOID )
{
    if ((ETgMODULE_STATE__FREED == s_enSI_PM_State) || (ETgMODULE_STATE__INITIALIZED == s_enSI_PM_State))
    {
        return (KTgS_OK);
    };

    /* Verify the state of the system */
    TgERROR(ETgMODULE_STATE__BOOTED == s_enSI_PM_State);
    s_enSI_PM_State = ETgMODULE_STATE__STOPPING;

#if TgCOMPILE_CONSOLE
    tgCN_Remove_Command_Function( TgT("print_info_threads") );
    tgCN_Remove_Command_Function( TgT("print_info_modules") );
    tgCN_Remove_Command_Function( TgT("print_info_configuration") );
/*# TgCOMPILE_CONSOLE */
#endif

    s_enSI_PM_State = ETgMODULE_STATE__STOPPED;
    return (KTgS_OK);
}


/* ---- tgSI_PM_Free --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgSI_PM_Free( TgVOID )
{
    if (ETgMODULE_STATE__FREED == s_enSI_PM_State)
    {
        return (KTgS_OK);
    };

    /* Verify the state of the system */
    TgERROR((ETgMODULE_STATE__STOPPED == s_enSI_PM_State) || (ETgMODULE_STATE__INITIALIZED == s_enSI_PM_State));
    s_enSI_PM_State = ETgMODULE_STATE__FREEING;

    if (s_aSI_Monitor_Handle)
    {
        free( s_aSI_Monitor_Handle );
        s_aSI_Monitor_Handle = nullptr;
    }
#if !defined(TgCOMPILE_PLATFORM_UWP)
    if (s_aSI_Monitor_Virt_Rect)
    {
        free( s_aSI_Monitor_Virt_Rect );
        s_aSI_Monitor_Virt_Rect = nullptr;
    }
    if (s_aSI_Monitor_Work_Rect)
    {
        free( s_aSI_Monitor_Work_Rect );
        s_aSI_Monitor_Work_Rect = nullptr;
    }
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif
    if (s_pszSI_String_Pool)
    {
        free( s_pszSI_String_Pool );
        s_pszSI_String_Pool = nullptr;
    }

    s_enSI_PM_State = ETgMODULE_STATE__FREED;
    return (KTgS_OK);
}


/* ---- tgSI_PM_Query_Init ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgSI_PM_Query_Init( TgVOID )
{
    return (ETgMODULE_STATE__INITIALIZED <= s_enSI_PM_State && s_enSI_PM_State <= ETgMODULE_STATE__STOPPED ? TgTRUE : TgFALSE);
}


/* ---- tgSI_PM_Query_Boot ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgSI_PM_Query_Boot( TgVOID )
{
    return (ETgMODULE_STATE__BOOTED == s_enSI_PM_State ? TgTRUE : TgFALSE);
}


/* ---- tgSI_PM_Query_Fixed_Memory -------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSIZE tgSI_PM_Query_Fixed_Memory( TgVOID )
{
    return (0
        + sizeof( s_uiSI_Page_Size )
        + sizeof( s_fSI_Seconds_Per_CounterTick )
        + sizeof( s_szSI_System_Dir )
        + sizeof( s_szSI_Window_Dir )
        + sizeof( s_szSI_Current_Dir )
        + sizeof( s_szSI_Module_Dir )
        + sizeof( s_szSI_Computer_Name )
        + sizeof( s_szSI_User_Name )
        + sizeof( s_szSI_Hardware_Profile_GUID )
        + sizeof( s_szSI_Hardware_Profile_Name )
        + sizeof( s_nuiSI_Processors )
#if !defined(TgCOMPILE_PLATFORM_UWP)
        + sizeof( s_aSI_Monitor_Work_Rect )
        + sizeof( s_aSI_Monitor_Virt_Rect )
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif
        + sizeof( s_aSI_Monitor_Handle )
        + sizeof( s_niSI_Monitors )
        + sizeof( s_uiSI_IN_Mouse_Bounds_X_Double_Click )
        + sizeof( s_uiSI_IN_Mouse_Bounds_Y_Double_Click )
        + sizeof( s_uiSI_IN_Mouse_Bounds_X_Drag )
        + sizeof( s_uiSI_IN_Mouse_Bounds_Y_Drag )
        + sizeof( s_uiSI_Bounds_Hover_Height )
        + sizeof( s_uiSI_Bounds_Hover_Width )
        + sizeof( s_uiSI_Bounds_Hover_Time )
        + sizeof( s_pszSI_String_Pool )
        + sizeof( s_bfSystemChecks )
        + sizeof( s_bfInputChecks )
    );
}


/* ---- tgSI_PM_Stats --------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgSI_PM_Stats( P_STg2_Output pOutput )
{
    tgIO_PrintF( pOutput, TgT("System Information --------------------------------------------------------------------------------")
        TgT("---------------------------------\n\n") );

    tgSI_Print_Configuration( pOutput );
#if !defined(TgCOMPILE_PLATFORM_UWP)
    tgSI_Print_Modules( pOutput );
    tgSI_Print_Threads( pOutput );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    tgIO_PrintF( pOutput, TgT("\nSystem Information ------------------------------------------------------------------------------")
        TgT("-----------------------------------\n\n") );
}


/* == Platform Specific Functions ======================================================================================================================================= */

/* ---- tgSI_SYSTEM_Seconds_Per_CounterTick ----------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFLOAT64 tgSI_SYSTEM_Seconds_Per_CounterTick( TgVOID )
{
    return (s_fSI_Seconds_Per_CounterTick);
}


/* ---- tgSI_INPUT_Has_Mouse_Wheel -------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgSI_INPUT_Has_Mouse_Wheel( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfInputChecks, 0 ));
}


/* ---- tgSI_SYSTEM_Page_Size ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgUINT32 tgSI_SYSTEM_Page_Size( TgVOID )
{
    return (s_uiSI_Page_Size);
}


/* ---- tgSI_SYSTEM_Number_Of_Processors -------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgUINT32 tgSI_SYSTEM_Number_Of_Processors( TgVOID )
{
    return (s_nuiSI_Processors);
}


/* ---- tgSI_Query_WorkPath --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_WorkPath( TgVOID )
{
    return (s_szSI_Current_Dir);
}


/* ---- tgSI_Query_SysPath ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_SysPath( TgVOID )
{
    return (s_szSI_System_Dir);
}


/* ---- tgSI_Query_WinPath ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_WinPath( TgVOID )
{
    return (s_szSI_Window_Dir);
}


/* ---- tgSI_Query_ExePath ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_ExePath( TgVOID )
{
    return (s_szSI_Module_Dir);
}


/* ---- tgSI_Query_Computer_Name ---------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_Computer_Name( TgVOID )
{
    return (s_szSI_Computer_Name);
}


/* ---- tgSI_Query_User_Name -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
CPC_TgCHAR tgSI_Query_User_Name( TgVOID )
{
    return (s_szSI_User_Name);
}


/* ---- tgSI_Query_Monitor_Virt_Rect ------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
CP_TgMS_RECT tgSI_Query_Monitor_Virt_Rect( C_TgSINT32 iIndex )
{
    if (iIndex < 0 || iIndex >= s_niSI_Monitors)
    {
        return (nullptr);
    }

    return (s_aSI_Monitor_Virt_Rect + iIndex);
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- tgSI_Query_Monitor_Work_Rect ------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
CP_TgMS_RECT tgSI_Query_Monitor_Work_Rect( C_TgSINT32 iIndex )
{
    if (iIndex < 0 || iIndex >= s_niSI_Monitors)
    {
        return (nullptr);
    }

    return (s_aSI_Monitor_Work_Rect + iIndex);
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- tgSI_Query_Monitor_Count ---------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
TgSINT32 tgSI_Query_Monitor_Count( TgVOID )
{
    return (s_niSI_Monitors);
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- tgSI_Get_Monitor_Index_From_Handle ------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
TgSINT32 tgSI_Get_Monitor_Index_From_Handle( TgMS_HMONITOR hMonitor )
{
    TgSINT32                            iIndex;

    for (iIndex = 0; iIndex < s_niSI_Monitors; ++iIndex)
    {
        if (s_aSI_Monitor_Handle[iIndex] == hMonitor)
        {
            return (iIndex);
        }
    };

    return (0);
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- tgSI_Print_Configuration ---------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgSI_Print_Configuration( P_STg2_Output pOutput )
{
    struct
    {
        TgUINT32                            dwLength;
        TgUINT32                            dwMemoryLoad;
        TgUINT64                            ullTotalPhys;
        TgUINT64                            ullAvailPhys;
        TgUINT64                            ullTotalPageFile;
        TgUINT64                            ullAvailPageFile;
        TgUINT64                            ullTotalVirtual;
        TgUINT64                            ullAvailVirtual;
        TgUINT64                            ullAvailExtendedVirtual;
    }                                   sMemoryStatus;
#if !defined(TgCOMPILE_PLATFORM_UWP)
    TgSINT32                            iIndex;
#endif

    memset( &sMemoryStatus, 0, sizeof( sMemoryStatus ) );
    sMemoryStatus.dwLength = sizeof( sMemoryStatus );
#if !defined(TgCOMPILE_PLATFORM_UWP)
    g_pfnGlobalMemoryStatusEx( &sMemoryStatus );
#endif

    tgIO_PrintF( pOutput, TgT("% 25.25s: %d\n"), TgT("Number of Processors"), s_nuiSI_Processors );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %.0f\n"), TgT("CPU Speed"), (0.000001 / s_fSI_Seconds_Per_CounterTick) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("MMX Instructions"), MATH_Has_MMX() ? TgT("TRUE") : TgT("FALSE") );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("XMM Instructions"), MATH_Has_XMM() ? TgT("TRUE") : TgT("FALSE") );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("XMM2 Instructions"), MATH_Has_XMM2() ? TgT("TRUE") : TgT("FALSE") );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("3DNOW Instructions"), MATH_Has_3DNow() ? TgT("TRUE") : TgT("FALSE") );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n\n"), TgT("RDTSC Instruction"), MATH_Has_RDTSC() ? TgT("TRUE") : TgT("FALSE") );

    tgIO_PrintF( pOutput, TgT("% 25.25s: %d\n"), TgT("Memory in Use"), sMemoryStatus.dwMemoryLoad );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Total Physical Memory"), (sMemoryStatus.ullTotalPhys / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Free Physical Memory"), (sMemoryStatus.ullAvailPhys / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Total Paging File"), (sMemoryStatus.ullTotalPageFile / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Free Paging File"), (sMemoryStatus.ullAvailPageFile / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Total Virtual Memory"), (sMemoryStatus.ullTotalVirtual / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %I64d KB\n"), TgT("Free Virtual Memory"), (sMemoryStatus.ullAvailVirtual / 1024) );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %d\n\n"), TgT("Memory Page_Size"), s_uiSI_Page_Size );

#if !defined(TgCOMPILE_PLATFORM_UWP)
    tgIO_PrintF( pOutput, TgT("% 25.25s: %d\n\n"), TgT("Number of Monitors"), s_niSI_Monitors );
    for (iIndex = 0; iIndex < s_niSI_Monitors; ++iIndex)
    {
        tgIO_PrintF( pOutput, TgT("% 20.20s (% 2d): Virtual Rect | X0:% 6d Y0:% 6d X1:% 6d Y1:% 6d\n"), TgT("Monitor"),
            iIndex, s_aSI_Monitor_Virt_Rect[iIndex].left, s_aSI_Monitor_Virt_Rect[iIndex].top,
            s_aSI_Monitor_Virt_Rect[iIndex].right, s_aSI_Monitor_Virt_Rect[iIndex].bottom );
        tgIO_PrintF( pOutput, TgT("% 20.20s (% 2d):    Work Rect | X0:% 6d Y0:% 6d X1:% 6d Y1:% 6d\n"), TgT("Monitor"),
            iIndex, s_aSI_Monitor_Work_Rect[iIndex].left, s_aSI_Monitor_Work_Rect[iIndex].top,
            s_aSI_Monitor_Work_Rect[iIndex].right, s_aSI_Monitor_Work_Rect[iIndex].bottom );
    };
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif

    tgIO_PrintF( pOutput, TgT("\n% 25.25s: %s\n"), TgT("System Directory"), s_szSI_System_Dir );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("Windows Directory: "), s_szSI_Window_Dir );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("Current Directory"), s_szSI_Current_Dir );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n\n"), TgT("Module Directory"), s_szSI_Module_Dir );

    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("Computer Name"), s_szSI_Computer_Name );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("User Name"), s_szSI_User_Name );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n"), TgT("Hardware Profile GUID"), s_szSI_Hardware_Profile_GUID );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %s\n\n"), TgT("Hardware Profile Name"), s_szSI_Hardware_Profile_Name );

    tgIO_PrintF( pOutput, TgT("% 25.25s: %d %d\n"), TgT("Mouse DblClik Bounds"), s_uiSI_IN_Mouse_Bounds_X_Double_Click, s_uiSI_IN_Mouse_Bounds_Y_Double_Click );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %d %d\n"), TgT("Mouse Drag Bounds"), s_uiSI_IN_Mouse_Bounds_X_Drag, s_uiSI_IN_Mouse_Bounds_Y_Drag );
    tgIO_PrintF( pOutput, TgT("% 25.25s: %d %d %d\n\n"), TgT("Mouse Hover Bounds"), s_uiSI_Bounds_Hover_Width, s_uiSI_Bounds_Hover_Height, s_uiSI_Bounds_Hover_Time );
}


/* ---- tgSI_Print_Modules ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
TgVOID tgSI_Print_Modules( P_STg2_Output pOutput )
{
    TgMS_HINSTANCE                      hProcess;
    TgMS_HINSTANCE                      hMods[1024];
    TgUINT32                            cbNeeded;

    hProcess = g_pfnGetCurrentProcess();

    tgIO_PrintF( pOutput, TgT("% 25.25s: %u\n"), TgT("Process ID"), hProcess );

    if (g_pfnEnumProcessModulesEx( hProcess, hMods, sizeof( hMods ), &cbNeeded, 3 ))
    {
        TgUINT32                            iIndex;

        for (iIndex = 0; iIndex < (cbNeeded / sizeof( TgMS_HINSTANCE )); ++iIndex)
        {
            TgCHAR                              szModName[1024];

            TgCOMPILER_ASSERT( 1024 > KTgMAX_FILE_PATH, 0 );

            if (g_pfnGetModuleFileNameEx( hProcess, hMods[iIndex], szModName, sizeof( szModName ) / sizeof( TgCHAR ) ))
            {
                tgIO_PrintF( pOutput, TgT("% 25.25s: 0x%08X %s\n"), TgT("Module"), hMods[iIndex], szModName );
            };
        };
    };
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- tgSI_Print_Threads ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
TgVOID tgSI_Print_Threads( P_STg2_Output pOutput )
{
    struct
    {
        TgUINT32                            dwSize;
        TgUINT32                            cntUsage;
        TgUINT32                            th32ThreadID;
        TgUINT32                            th32OwnerProcessID;
        TgSINT32                            tpBasePri;
        TgSINT32                            tpDeltaPri;
        TgUINT32                            dwFlags;
    }                                   te32;
    P_TgVOID                            hThreadSnap;
    TgUINT32                            uiOwnerPID;
    TgBOOL                              bPrint_Header = TgTRUE;

    hThreadSnap = (P_TgVOID)~((TgUINTPTR)0);
    uiOwnerPID = g_pfnGetCurrentProcessId();

    /* Take a snapshot of all running threads */
    hThreadSnap = g_pfnCreateToolhelp32Snapshot( 0x00000004, 0 );
    if (hThreadSnap == (P_TgVOID)~((TgUINTPTR)0))
        return;

    /* Fill in the size of the structure before using it. */
    te32.dwSize = sizeof( te32 );

    /* Retrieve information about the first thread, and exit if unsuccessful */
    if (!g_pfnThread32First( hThreadSnap, &te32 ))
    {
        g_pfnCloseHandle( hThreadSnap );
        return;
    }

#if TgCOMPILE_THREAD_INFO
    tgCM_UTM_SN_Lock_Spin( &g_sTR_Lock.m_sLock );
#endif
    do
    {
        if (te32.th32OwnerProcessID == uiOwnerPID)
        {
        #if TgCOMPILE_THREAD_INFO
            TgSINT32                            iIndex = 0;

            for (iIndex = 0; iIndex < KTgMAX_THREAD_ENTRIES; ++iIndex)
            {
                if (te32.th32ThreadID == (TgUINT32)g_atiTR_Thread[iIndex].m.iI )
                {
                    break;
                };
            };

            if (bPrint_Header)
            {
                tgIO_PrintF( pOutput, TgT("\n% 25.25s: %10.10s %s\n"), TgT("Thread"), TgT("Stack"), TgT("Name") );
                bPrint_Header = TgFALSE;
            };

            if (iIndex >= KTgMAX_THREAD_ENTRIES)
            {
                tgIO_PrintF( pOutput, TgT("% 25.25s: 0x%08X\n"), TgT("Thread"), te32.th32ThreadID );
            }
            else
            {
                tgIO_PrintF( pOutput, TgT("% 25.25s: % 10d %s\n"), TgT("Thread"), g_auiTR_Thread_Stack[iIndex], g_aszTR_Name[iIndex] );
            };
        #else
            if (bPrint_Header)
            {
                tgIO_PrintF( pOutput, TgT("\n% 25.25s: %10.10s\n"), TgT("Thread"), TgT("ID") );
                bPrint_Header = TgFALSE;
            };
            tgIO_PrintF( pOutput, TgT("% 25.25s: 0x%08X\n"), TgT("Thread"), te32.th32ThreadID );
        #endif
        }
    }
    while (g_pfnThread32Next( hThreadSnap, &te32 ));
#if TgCOMPILE_THREAD_INFO
    tgCM_UTM_SN_Signal( &g_sTR_Lock.m_sLock );
#endif

    /*  Don't forget to clean up the snapshot object. */
    g_pfnCloseHandle( hThreadSnap );
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions                                                                                                                                                  */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- Monitor_Count_Callback ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgCOMPILE_PLATFORM_UWP)
static TgBOOL __stdcall Monitor_Handle_Callback( TgMS_HMONITOR hMonitor, TgMS_HDC UNUSED_PARAM hDC, P_TgVOID UNUSED_PARAM pRect, TgSINT64 UNUSED_PARAM wParam )
{
    if (s_niSI_Monitors < ETgSI_MAX_MONITOR)
    {
        s_aSI_Monitor_Handle[s_niSI_Monitors++] = hMonitor;
        return (TgTRUE);
    }
    return (TgFALSE);
}
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif


/* ---- InitTimer ------------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
MSVC_PRAGMA(optimize("",off))

static TgRESULT Init_Timer( TgVOID )
{
    LARGE_INTEGER                       liFreq, liCycles1, liCycles2;
    TgFLOAT64                           aTimeArray[TIME_MAXITERATIONS];
    TgFLOAT64                           dFrequency;
    TgUINT08                            nCount;

    /* Call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function */

    if (!MATH_Has_RDTSC())
        return (KTgE_FAIL);

    if (!g_pfnQueryPerformanceFrequency( &liFreq ))
    {
        TgERROR_MSGF( 0, TgT("%-16.16s(%-32.32s): CPU does not Support RDTSC.\n"), TgT("Global"), TgT("InitTimer") );
        return (KTgE_FAIL);
    };

    dFrequency = (TgFLOAT64)liFreq.QuadPart; /* Counts per second */

    for (nCount = 0; nCount < TIME_MAXITERATIONS; nCount++)
    {
        TgFLOAT64                           dSeconds1, dSeconds2;
        TgUINT08                            uiIndex;
        TgUINT64                            uiStart_Time;

        g_pfnQueryPerformanceCounter( &liCycles1 );

        uiStart_Time = g_pfnGetTickCount64();
        while (g_pfnGetTickCount64() - uiStart_Time < 10)
        {
        };

        g_pfnQueryPerformanceCounter( &liCycles2 );

        dSeconds1 = (TgFLOAT64)liCycles1.QuadPart / dFrequency;
        dSeconds2 = (TgFLOAT64)liCycles2.QuadPart / dFrequency;
        aTimeArray[nCount] = (dSeconds2 - dSeconds1) / (TgFLOAT64)(liCycles2.QuadPart - liCycles1.QuadPart);

        for (uiIndex = 0; uiIndex < nCount - 1; ++uiIndex)
        {
            if (aTimeArray[uiIndex] > aTimeArray[nCount])
            {
                tgCM_SWP_F64( aTimeArray + uiIndex, aTimeArray + nCount );
            };
        };
    }
    s_fSI_Seconds_Per_CounterTick = aTimeArray[(TIME_MAXITERATIONS - 1) / 2];

    return (KTgS_OK);
}
MSVC_PRAGMA(optimize("",on))


CLANG_WARN_DISABLE_PUSH(unused-function)

/* ---- SYSTEM_Set_Mouse ------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID SYSTEM_Set_Mouse( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 0, bFlag );
}


/* ---- SYSTEM_Set_Network ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID SYSTEM_Set_Network( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 1, bFlag );
}


/* ---- SYSTEM_Set_Clean_Boot ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID SYSTEM_Set_Clean_Boot( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 6, bFlag );
}


/* ---- SYSTEM_Has_Mouse ------------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL SYSTEM_Has_Mouse( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 0 ));
}


/* ---- SYSTEM_Has_Network ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL SYSTEM_Has_Network( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 1 ));
}


/* ---- SYSTEM_Clean_Boot ----------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL SYSTEM_Clean_Boot( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 6 ));
}


/* ---- MATH_Set_MMX ---------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID MATH_Set_MMX( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 2, bFlag );
}


/* ---- MATH_Set_XMM ---------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID MATH_Set_XMM( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 3, bFlag );
}


/* ---- MATH_Set_XMM2 --------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID MATH_Set_XMM2( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 7, bFlag );
}


/* ---- MATH_Set_3DNow -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID MATH_Set_3DNow( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 4, bFlag );
}


/* ---- MATH_Set_RDTSC -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID MATH_Set_RDTSC( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfSystemChecks, 5, bFlag );
}


/* ---- MATH_Has_MMX ---------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL MATH_Has_MMX( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 2 ));
}


/* ---- MATH_Has_XMM ---------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL MATH_Has_XMM( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 3 ));
}


/* ---- MATH_Has_XMM2 --------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL MATH_Has_XMM2( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 7 ));
}


/* ---- MATH_Has_3DNow -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL MATH_Has_3DNow( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 4 ));
}


/* ---- MATH_Has_RDTSC -------------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgBOOL MATH_Has_RDTSC( TgVOID )
{
    return (tgBF_Query_Flag_U32( &s_bfSystemChecks, 5 ));
}


/* ---- INPUT_Set_Mouse_Wheel ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgINLINE TgVOID INPUT_Set_Mouse_Wheel( C_TgBOOL bFlag )
{
    tgBF_Set_Flag_U32( &s_bfInputChecks, 0, bFlag );
}
CLANG_WARN_DISABLE_POP(unused-function)


/* Console Functions */
#if TgCOMPILE_CONSOLE
/* ---- SI_CO_Print_Configuration --------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID SI_CO_Print_Configuration( C_TgUINT32 UNUSED_PARAM nuiArg, CP_TgCHAR UNUSED_PARAM pArgV[KTgMAX_CMD_LINE_COUNT] )
{
    tgSI_Print_Configuration( &g_sOutCon );
}
/*# TgCOMPILE_CONSOLE */
#endif


/* ---- SI_CO_Print_Modules --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if TgCOMPILE_CONSOLE
static TgVOID SI_CO_Print_Modules( C_TgUINT32 UNUSED_PARAM nuiArg, CP_TgCHAR UNUSED_PARAM pArgV[KTgMAX_CMD_LINE_COUNT] )
{
#if !defined(TgCOMPILE_PLATFORM_UWP)
    tgSI_Print_Modules( &g_sOutCon );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif
}
/*# TgCOMPILE_CONSOLE */
#endif


/* ---- SI_CO_Print_Threads --------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if TgCOMPILE_CONSOLE
static TgVOID SI_CO_Print_Threads( C_TgUINT32 UNUSED_PARAM nuiArg, CP_TgCHAR UNUSED_PARAM pArgV[KTgMAX_CMD_LINE_COUNT] )
{
#if !defined(TgCOMPILE_PLATFORM_UWP)
    tgSI_Print_Threads( &g_sOutCon );
/*# !defined(TgCOMPILE_PLATFORM_UWP) */
#endif
}
/*# TgCOMPILE_CONSOLE */
#endif