/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
/*****************************************************************************
*
*   $/Plasma20/Sources/Plasma/NucleusLib/pnNetDiag/pnNetSys.cpp
*   
***/

#include "Pch.h"
#pragma hdrstop


/*****************************************************************************
*
*   Local types
*
***/

typedef DWORD (PASCAL FAR * FGetAdaptersInfo)(
    PIP_ADAPTER_INFO    pAdapterInfo,
    PULONG              pOutBufLen
);



/*****************************************************************************
*
*   Local data
*
***/

static FGetAdaptersInfo     GetAdaptersInfo;


/*****************************************************************************
*
*   Module functions
*
***/

//============================================================================
void SysStartup () {

    if (g_lib) {
        GetAdaptersInfo = (FGetAdaptersInfo)GetProcAddress(g_lib, "GetAdaptersInfo");
    }
}

//============================================================================
void SysShutdown () {

    GetAdaptersInfo = nil;
}


/*****************************************************************************
*
*   Exports
*
***/

//============================================================================
void NetDiagSys (
    NetDiag *               diag,
    FNetDiagDumpProc        dump,
    FNetDiagTestCallback    callback,
    void *                  param
) {
    ASSERT(diag);
    ASSERT(dump);
    ASSERT(callback);

    { // Timestamp
        wchar str[256];
        qword time = TimeGetTime();
        TimePrettyPrint(time, arrsize(str), str);
        dump(L"[SYS] Time: %s UTC", str);
    }
        
    { // Command line
        dump(L"[SYS] Cmdline: %s", AppGetCommandLine());
    }
    
    { // Product
        wchar product[128];
        ProductString(product, arrsize(product));
        dump(L"[SYS] Product: %s", product);
    }
    
    { // pnNetDiag version
        dump(L"[SYS] Cognomen: '%s'", g_version);
    }
    
    { // OS
        OSVERSIONINFOEX info;
        info.dwOSVersionInfoSize = sizeof(info);
        GetVersionEx((OSVERSIONINFO*)&info);
        dump(L"[SYS] OS Version: %u.%u", info.dwMajorVersion, info.dwMinorVersion);
        dump(L"[SYS] OS Patch: %u.%u (%S)", info.wServicePackMajor, info.wServicePackMinor, info.szCSDVersion);
    }
    
    { // System
        word    cpuCaps;
        dword   cpuVendor[3];
        word    cpuSignature;
        CpuGetInfo(&cpuCaps, cpuVendor, &cpuSignature);
        SYSTEM_INFO info;
        GetSystemInfo(&info);
        dump(L"[SYS] CPU Count: %u", info.dwNumberOfProcessors);
        dump(L"[SYS] CPU Vendor: %.*S", sizeof(cpuVendor), cpuVendor);
    }
    
    { // Adapters
        if (!GetAdaptersInfo) {
            dump(L"[SYS] Failed to load IP helper API");
            callback(diag, kNetProtocolNil, kNetErrNotSupported, param);
            return;
        }

        ULONG ulOutBufLen = 0;
        GetAdaptersInfo(nil, &ulOutBufLen);
        PIP_ADAPTER_INFO pInfo = (PIP_ADAPTER_INFO)ALLOC(ulOutBufLen);
        PIP_ADAPTER_INFO pAdapter;
        if (GetAdaptersInfo(pInfo, &ulOutBufLen) == NO_ERROR) {
            pAdapter = pInfo;
            while (pAdapter) {
                dump(L"[SYS] NIC: %S", pAdapter->Description);
                pAdapter = pAdapter->Next;
            }
            callback(diag, kNetProtocolNil, kNetSuccess, param);
        }
        else {
            dump(L"[SYS] Error getting adaper list");
            callback(diag, kNetProtocolNil, kNetErrFileNotFound, param);
        }
        FREE(pInfo);
    }
}