Gabriele Contini
2020-02-24 46f5b467557acc4b62f1d89943f39cd0ee6cb213
windows progress
8个文件已修改
9个文件已添加
1个文件已删除
1334 ■■■■ 已修改文件
doc/CREDITS.md 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/snippets/hardware.cpp 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/hw_identifier/default_strategy.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/hw_identifier/identification_strategy.hpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/ExternalDefinition.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/CMakeLists.txt 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/execution_environment.hpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/linux/network.cpp 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/.gitignore 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/cpu_info.cpp 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/execution_environment.cpp 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/isvm/BIOSReader.cpp 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/isvm/BIOSReader.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/isvm/Native.cpp 437 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/isvm/Native.h 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/isvm/main.cpp 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/network.cpp 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/windows/os-win.c 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/CREDITS.md
@@ -1,7 +1,10 @@
The following code has been used in OpenLicenseManager. Many thanks to the authors
The following open source code has been used in OpenLicenseManager.
Thanks to every one of the authors of such projects. Without you open license manager would never have been completed.
========================================================
## isVM
Thanks for the great smbios parsing code. It saved me days.
isvm : https://github.com/0of/isvm
The MIT License (MIT)
@@ -25,5 +28,5 @@
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=============================
doc/snippets/hardware.cpp
New file
@@ -0,0 +1,266 @@
/*********************  physical_processors.cpp   *****************************
* Author:        Agner Fog
* Date created:  2019-10-29
* Last modified: 2019-11-25
* Version:       1.02 beta
* Project:       vector class library
* Description:   Detect number of physical and logical processors on CPU chip.
*                Compile for C++11 or later
*
* (c) Copyright 2019 Agner Fog.
* Apache License version 2.0 or later.
*******************************************************************************
Some modern CPUs can run two threads in each CPU core when simultaneous
multithreading (SMT, called hyperthreading by Intel) is enabled.
The number of physical processors is the number of CPU cores.
The number of logical processors is the same number multiplied by the number of
threads that can run simultaneously in each CPU core.
Simultaneous multithreading will slow down performance when two CPU-intensive
threads running in the same physical processor (CPU core) are competing for the
same resources. Therefore, the optimal number of threads for CPU-intensive
tasks is most likely to be the number of physical processors.
Tasks that are less CPU-intensive but limited by RAM access, disk access,
network, etc. may get an advantage by running as many threads as the number of
logical processors. This will be double the number of physical processors when
simultaneous multithreading is enabled.
The physicalProcessors function detects the number of physical processors and
logical processors on an x86 computer. This is useful for determining the
optimal number of threads.
Note: There are several problems in detecting the number of physical processors:
1. The CPUID instruction on Intel CPUs will return a wrong number of logical
   processors when SMT (hyperthreading) is disabled. It may be necessary to
   compare the number of processors returned by the CPUID instruction with the
   number of processors reported by the operating system to detect if SMT is
   enabled (AMD processors do not have this problem).
2. It is necessary to rely on system functions to detect if there is more than
   one CPU chip installed. It is assumed that the status of SMT is the same on
   all CPU chips in a system.
3. The behavior of VIA processors is undocumented.
4. This function is not guaranteed to work on future CPUs. It may need updating
   when new CPUs with different configurations or different CPUID functionality
   appear.
******************************************************************************/
#include <thread>     // std::thread functions
#ifdef _MSC_VER
#include <intrin.h>   // __cpuidex intrinsic function available on microsoft compilers
#endif
// Define interface to CPUID instruction.
// input:  leaf = eax, subleaf = ecx
// output: output[0] = eax, output[1] = ebx, output[2] = ecx, output[3] = edx
static inline void cpuid(int output[4], int leaf, int subleaf = 0) {
#if defined(__GNUC__) || defined(__clang__)      // use inline assembly, Gnu/AT&T syntax
    int a, b, c, d;
    __asm("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(leaf), "c"(subleaf) : );
    output[0] = a;
    output[1] = b;
    output[2] = c;
    output[3] = d;
#elif defined (_MSC_VER)                         // Microsoft compiler, intrin.h included
    __cpuidex(output, leaf, subleaf);            // intrinsic function for CPUID
#else                                            // unknown platform. try inline assembly with masm/intel syntax
    __asm {
        mov eax, leaf
        mov ecx, subleaf
        cpuid;
        mov esi, output
        mov[esi], eax
        mov[esi + 4], ebx
        mov[esi + 8], ecx
        mov[esi + 12], edx
    }
#endif
}
// Function prototype:
int physicalProcessors(int * logical_processors = 0);
// Find the number of physical and logical processors supported by CPU
// Parameter:
// logical_processors: an optional pointer to an integer that will receive the number of logical processors.
// Return value: number of physical processors
int physicalProcessors(int * logical_processors) {
    int vendor = 0;                              // CPU vendor: 1 = Intel, 2 = AMD, 3 = VIA, 0 = other
    int logicalProc = 1;                         // number of logical processor cores
    int physicalProc = 1;                        // number of physical processor cores
    int procPerCore = 1;                         // logical cores per physical core
    bool hyperthreadingSupported = false;        // CPU supports hyperthreading / simultaneous multithreading
    int systemProcessors = std::thread::hardware_concurrency(); // number of processors reported by operating system
    int abcd[4] = { 0,0,0,0 };                   // CPUID output
    cpuid(abcd, 0);                              // CPUID function 0
    int maxLeaf = abcd[0];                       // maximum eax input for CPUID
    if (abcd[2] == 0x6C65746E) {                 // last 4 chars of "GenuineIntel"
        vendor = 1;
    }
    else if (abcd[2] == 0x444D4163) {            // last 4 chars of "AuthenticAMD"
        vendor = 2;
    }
    else if (abcd[2] == 0x736C7561) {            // last 4 chars of "CentaurHauls"
        vendor = 3;
    }
    if (maxLeaf >= 1) {
        cpuid(abcd, 1);
        if (abcd[3] & (1 << 28)) {               // hyperthreading supported
            hyperthreadingSupported = true;
        }
    }
    if (vendor == 1) {
        //////////////////
        //    Intel     //
        //////////////////
        int hyper = 0;                           // hyperthreading status: 0 = unknown, 1 = disabled, 2 = enabled
        if (maxLeaf >= 0xB) {                    // leaf 0xB or 0x1F: Extended Topology Enumeration
            int num = 0xB;
            // if (maxLeaf >= 0x1F) num = 0x1F;
            for (int c = 0; c < 5; c++) {
                cpuid(abcd, num, c);             // enumeration level c
                int type = (abcd[2] >> 8) & 0xFF;// enumeration type at level c
                if (type == 1) {                 // SMT level
                    procPerCore = abcd[1] & 0xFFFF;
                }
                else if (type >= 2) {            // core level
                    logicalProc = abcd[1] & 0xFFFF;
                }
                else if (type == 0) break;
                // There are more types/levels to consider if we use num = 0x1F. We may need
                // to fix this in the future if CPUs with more complex configurations appear
            }
            physicalProc = logicalProc / procPerCore;
            // The number of performance monitor registers depends on hyperthreading status
            // on Intel CPUs with performance monitoring version 3 or 4
            cpuid(abcd, 0xA, 0);                 // performance monitor counters information
            int perfVersion = abcd[0] & 0xFF;    // performance monitoring version
            int perfNum = (abcd[0] >> 8) & 0xFF; // number of performance monitoring registers
            if (perfVersion == 3 || perfVersion == 4) {
                if (perfNum == 4) {
                    hyper = 2;                   // 4 performance registers when hyperthreading enabled
                }
                else if (perfNum == 8) {         // 8 performance registers when hyperthreading disabled
                    hyper = 1;
                    procPerCore = 1;
                    logicalProc = physicalProc;  // reduce the number of logical processors when hyperthreading is disabled
                }
                // hyper remains 0 in all other cases, indicating unknown status
            }
        }
        else if (maxLeaf >= 4) {                 // CPUID function 4: cache parameters and cores
            cpuid(abcd, 4);
            logicalProc = (abcd[0] >> 26) + 1;
            if (hyperthreadingSupported) {
                // number of logical processors per core is not known. Assume 2 if hyperthreading supported
                procPerCore = 2;
            }
            physicalProc = logicalProc / procPerCore;
        }
        else {
            // no information. Assume 1 processor
        }
        if (systemProcessors > logicalProc) {
            // Multiple CPU chips. Assume that chips are identical with respect to hypethreading
            physicalProc = systemProcessors * physicalProc / logicalProc;
            logicalProc = systemProcessors;
        }
        else if (logicalProc > systemProcessors && systemProcessors > 0 && hyper == 0) {
            // Hyperthreading is disabled
            logicalProc = systemProcessors;
            physicalProc = systemProcessors;
        }
    }
    else if (vendor == 2) {
        //////////////////
        //    AMD       //
        //////////////////
        cpuid(abcd, 0x80000000);                 // AMD specific CPUID functions
        int maxLeaf8 = abcd[0] & 0xFFFF;         // maximum eax 0x8000.... input for CPUID
        if (maxLeaf8 >= 8) {
            cpuid(abcd, 0x80000008);
            logicalProc = (abcd[2] & 0xFF) + 1;
            if (maxLeaf8 >= 0x1E) {
                cpuid(abcd, 0x8000001E);
                procPerCore = ((abcd[1] >> 8) & 0x03) + 1;
                // procPerCore = 2 if simultaneous multithreading is enabled, 1 if disabled
            }
            else {
                if (hyperthreadingSupported) {
                    procPerCore = 2;
                }
                else {
                    procPerCore = 1;
                }
            }
            physicalProc = logicalProc / procPerCore;
        }
        else if (hyperthreadingSupported) {
            // number of logical processors per core is not known. Assume 2 if SMT supported
            logicalProc = 2;
            physicalProc = 1;
        }
        if (systemProcessors > logicalProc) {
            // Multiple CPU chips. Assume that chips are identical with respect to SMT
            physicalProc = systemProcessors * physicalProc / logicalProc;
            logicalProc = systemProcessors;
        }
    }
    else {
        //////////////////////////////
        //    VIA or unknown CPU    //
        //////////////////////////////
        // The behavior of VIA processors is undocumented! It is not known how to detect threads on a VIA processor
        physicalProc = logicalProc = systemProcessors;
        if (hyperthreadingSupported && physicalProc > 1) {
            physicalProc /= 2;
        }
    }
    if (logical_processors) {
        // return logical_processors if pointer is not null
        *logical_processors = logicalProc;
    }
    return physicalProc;
}
/* Uncomment this for testing:
#include <stdio.h>
int main() {
    int logicalProc = 0;
    int physicalProc = physicalProcessors(&logicalProc);
    printf("\nlogical processors: %i",  logicalProc);
    printf("\nphysical processors: %i", physicalProc);
    printf("\nlogical processors per core: %i", logicalProc / physicalProc);
    int sysproc = std::thread::hardware_concurrency();
    printf("\nsystem processors: %i", sysproc);
    return 0;
}
*/
src/library/hw_identifier/default_strategy.cpp
@@ -14,7 +14,7 @@
namespace hw_identifier {
static vector<LCC_API_IDENTIFICATION_STRATEGY> available_strategies() {
    ExecutionEnvironment exec;
    os::ExecutionEnvironment exec;
    VIRTUALIZATION virtualization = exec.getVirtualization();
    vector<LCC_API_IDENTIFICATION_STRATEGY> strategy_to_try;
    if (virtualization == CONTAINER) {
src/library/hw_identifier/identification_strategy.hpp
@@ -11,7 +11,6 @@
#include <licensecc/datatypes.h>
#include <licensecc_properties.h>
#include <vector>
#include <bits/unique_ptr.h>
#include "../base/base.h"
#include "hw_identifier.hpp"
src/library/locate/ExternalDefinition.cpp
@@ -9,7 +9,7 @@
#include <cstring>
#include <string>
#include <vector>
#include <stdexcept>
#include <licensecc/datatypes.h>
#include "../base/base64.h"
@@ -21,7 +21,7 @@
namespace license {
namespace locate {
using namespace std;
    using namespace std;
ExternalDefinition::ExternalDefinition(const LicenseLocation *location)
    : LocatorStrategy("ExternalDefinition"), m_location(location) {}
src/library/os/CMakeLists.txt
@@ -9,11 +9,25 @@
            linux/os-linux.c) 
    ELSE(UNIX)
          add_library(os OBJECT 
          cpu_info_common.cpp openssl/signature_verifier.cpp windows/os-win.c)
          cpu_info_common.cpp windows/cpu_info.cpp
          openssl/signature_verifier.cpp
          windows/execution_environment.cpp
          windows/isvm/Native.cpp
        windows/isvm/BIOSReader.cpp
          windows/os-win.c
          windows/network.cpp)
    ENDIF(UNIX)
ELSE(UNIX OR OPENSSL_FOUND)
#windows no openssl
    add_library(os OBJECT
        cpu_info_common.cpp windows/signature_verifier.cpp windows/os-win.c)
        cpu_info_common.cpp
        windows/cpu_info.cpp
        windows/signature_verifier.cpp
        windows/execution_environment.cpp
        windows/isvm/Native.cpp
        windows/isvm/BIOSReader.cpp
        windows/os-win.c
        windows/network.cpp)
ENDIF(UNIX OR OPENSSL_FOUND)
if(CODE_COVERAGE AND UNIX)
src/library/os/execution_environment.hpp
@@ -9,7 +9,7 @@
#define SRC_LIBRARY_OS_VIRTUALIZATION_HPP_
namespace license {
namespace os {
typedef enum { NONE, CONTAINER, VM } VIRTUALIZATION;
typedef enum {
    ON_PREMISE,
@@ -25,7 +25,6 @@
    ALI_CLOUD
} CLOUD_PROVIDER;
class ExecutionEnvironment {
public:
    ExecutionEnvironment(){};
@@ -35,7 +34,7 @@
    bool is_docker();
    CLOUD_PROVIDER getCloudProvider();
};
}  // namespace os
}  // namespace license
#endif /* SRC_LIBRARY_OS_VIRTUALIZATION_HPP_ */
src/library/os/linux/network.cpp
@@ -23,7 +23,6 @@
#include <ifaddrs.h>
#include <linux/if_link.h>
#include <netpacket/packet.h>
#include <string.h>
#include <stdio.h>
#include <unordered_map>
@@ -35,25 +34,6 @@
namespace os {
using namespace std;
/**
 *
 * @param ifnames
 * @param ifname
 * @param ifnames_max
 * @return
 */
static int ifname_position(char *ifnames, char *ifname, int ifnames_max) {
    int i, position;
    position = -1;
    for (i = 0; i < ifnames_max; i++) {
        if (strcmp(ifname, &ifnames[i * NI_MAXHOST]) == 0) {
            position = i;
            break;
        }
    }
    return position;
}
/**
 *
src/library/os/windows/.gitignore
File was deleted
src/library/os/windows/cpu_info.cpp
New file
@@ -0,0 +1,47 @@
/*
 * cpu_info.cpp
 *
 *  Created on: Dec 14, 2019
 *      Author: devel
 */
#include <intrin.h>
#include <string>
#include <unordered_set>
#include "../cpu_info.hpp"
namespace license {
using namespace std;
CpuInfo::CpuInfo() {}
CpuInfo::~CpuInfo() {}
/**
 * Detect Virtual machine using hypervisor bit.
 * @return true if the cpu hypervisor bit is set to 1
 */
bool CpuInfo::is_hypervisor_set() const {
    int cpui[4] = {0};
    __cpuid(cpui, 0x1);
    return ((cpui[2] >> 31) & 1);
}
uint32_t CpuInfo::model() const {
    int cpui[4] = {0};
    __cpuid(cpui, 0x1);
    // ax bits 0-3 stepping,4-7 model,8-11 family id,12-13 processor type
    //        14-15 reserved, 16-19 extended model, 20-27 extended family, 27-31 reserved
    // bx bits 0-7 brand index
    return (cpui[0] & 0x3FFF) | (cpui[0] & 0x3FF8000) >> 2 | (cpui[1] & 0xff) << 24;
}
string CpuInfo::vendor() const {
    // hypervisor flag false, try to get the vendor name, see if it's a virtual cpu
    int cpui[4] = {0};
    __cpuid(cpui, 0x0);
    return string(reinterpret_cast<const char *>(cpui), 12);
}
} /* namespace license */
src/library/os/windows/execution_environment.cpp
New file
@@ -0,0 +1,70 @@
/*
 * virtualization.cpp
 *
 *  Created on: Dec 15, 2019
 *      Author: GC
 */
#include <paths.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/utsname.h>
#include "isvm/BIOSReader.h"
#include "isvm/Native.h"
#include "../../base/base.h"
#include "../cpu_info.hpp"
#include "../execution_environment.hpp"
namespace license {
using namespace std;
VIRTUALIZATION ExecutionEnvironment::getVirtualization() {
    VIRTUALIZATION result;
    CpuInfo cpuInfo;
    bool isContainer = false;
    if (isContainer) {
        result = CONTAINER;
    } else if (cpuInfo.cpu_virtual() || is_cloud()) {
        result = VM;
    } else {
        result = NONE;
    }
    return result;
}
bool ExecutionEnvironment::is_cloud() { return getCloudProvider() != ON_PREMISE; }
bool ExecutionEnvironment::is_docker() { return false; }
CLOUD_PROVIDER ExecutionEnvironment::getCloudProvider() {
    if (InitEntryPoints()) {
        BIOSReader reader;
        SystemInformation info = reader.readSystemInfo();
        const char *vmVendors[] = {
            "VMware", "Microsoft Corporation", "Virtual Machine", "innotek GmbH", "PowerVM", "Bochs", "KVM"};
        const int count = _countof(vmVendors);
        for (int i = 0; i != count; ++i) {
            const char *vendor = vmVendors[i];
            if (std::string::npos != info.Manufacturer.find(vendor) ||
                std::string::npos != info.ProductName.find(vendor) ||
                std::string::npos != info.SerialNum.find(vendor)) {
                std::cout << "Inside virual machine!";
                return 1;
            }
        }
    } else {
        return -1;
    }
}
}  // namespace license
src/library/os/windows/isvm/BIOSReader.cpp
New file
@@ -0,0 +1,145 @@
#include "BIOSReader.h"
#include <cstdint>
#include "Native.h"
struct smbios_structure_header
{
    uint8_t type;
    uint8_t length;
    uint16_t handle;
};
//
//    System information
//
struct smbios_type_1
{
    struct smbios_structure_header header;
    uint8_t manufacturer_str;
    uint8_t product_name_str;
    uint8_t version_str;
    uint8_t serial_number_str;
    uint8_t uuid[16];
    uint8_t wake_up_type;
    uint8_t sku_number_str;
    uint8_t family_str;
};
#define _TYPE_COUNT1 6
#define _CONCATE(x,y) x##y
#define CONCATE(x,y) _CONCATE(x,y)
#define TYPE_COUNT(t) CONCATE(_TYPE_COUNT, t)
//
//    Windows
//
#include <Windows.h>
#include <tchar.h>
int8_t * parse_smbiod_content(int8_t *addr, int8_t **indexes, int32_t *count)
{
    //!    ignore 0
    int8_t parsed_count = 0;
    int8_t *raw_addr = addr;
    //!    first one
    if (indexes)
        *indexes = raw_addr;
    bool reach_terminal = false;
    while (true)
    {
        if (0 == *raw_addr++)
        {
            if (reach_terminal)
                break;
            else
            {
                ++parsed_count;
                if (count && parsed_count < *count)
                {
                    if (indexes)
                        *(indexes + parsed_count) = raw_addr;
                }
                reach_terminal = true;
            }
        }
        else
        {
            reach_terminal = false;
            continue;
        }
    }
    if (count)
        *count = parsed_count;
    return raw_addr;
}
void read_smbios_type_1(int8_t *addr, SystemInformation *info)
{
    smbios_type_1 *t1 = (smbios_type_1 *)addr;
    int32_t offset = ((0x0F) & (t1->header.length >> 4)) * 16 + (t1->header.length & 0x0F);
    int8_t *string_addr[TYPE_COUNT(1)] = { 0 };
    int32_t count = TYPE_COUNT(1);
    parse_smbiod_content((int8_t *)t1 + offset, string_addr, &count);
    if (0 != t1->manufacturer_str)
        info->Manufacturer = (std::string::traits_type::char_type *)string_addr[t1->manufacturer_str - 1];
    if (0 != t1->product_name_str)
        info->ProductName = (std::string::traits_type::char_type *)string_addr[t1->product_name_str - 1];
    if (0 != t1->serial_number_str)
        info->SerialNum = (std::string::traits_type::char_type *)string_addr[t1->serial_number_str - 1];
    if (0 != t1->version_str)
        info->SysVersion = (std::string::traits_type::char_type *)string_addr[t1->version_str - 1];
}
SystemInformation BIOSReader::readSystemInfo()
{
    SystemInformation info;
    uint32_t size = 0;
    RawSMBIOSData *data = (RawSMBIOSData *)(LocateSMBIOS(&size));
    if (NULL == data || 0 == size)
        return info;
    smbios_structure_header *header = (smbios_structure_header *)(data->SMBIOSTableData);
    while (NULL != header)
    {
        if (1 == header->type)
        {
            read_smbios_type_1((int8_t *)header, &info);
            header = NULL;    //!    stop
        }
        else
        {
            int32_t offset = ((0x0F) & (header->length >> 4)) * 16 + (header->length & 0x0F);
            header = (smbios_structure_header *)parse_smbiod_content((int8_t *)header + offset, NULL, NULL);
        }
    }
    free(data);
    return info;
}
src/library/os/windows/isvm/BIOSReader.h
New file
@@ -0,0 +1,21 @@
#ifndef BIOSREADER_H
#define BIOSREADER_H
#include <string>
class SystemInformation
{
public:
    std::string Manufacturer;
    std::string ProductName;
    std::string SysVersion;
    std::string SerialNum;
};
class BIOSReader
{
public:
    SystemInformation readSystemInfo();
};
#endif
src/library/os/windows/isvm/Native.cpp
New file
@@ -0,0 +1,437 @@
#include "Native.h"
#include <tchar.h>
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; // windbgkd
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
#ifdef MIDL_PASS
    [size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT * Buffer;
#else // MIDL_PASS
    PWSTR  Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef enum _SECTION_INHERIT
{
    ViewShare = 1,
    ViewUnmap = 2
} SECTION_INHERIT;
#define OBJ_INHERIT             0x00000002L
#define OBJ_PERMANENT           0x00000010L
#define OBJ_EXCLUSIVE           0x00000020L
#define OBJ_CASE_INSENSITIVE    0x00000040L
#define OBJ_OPENIF              0x00000080L
#define OBJ_OPENLINK            0x00000100L
#define OBJ_VALID_ATTRIBUTES    0x000001F2L
static bool bIsWindowsXPLater = false;
static DWORD dwPageSize = 0;
#ifdef _UNICODE
#define GetVersionExProc "GetVersionExW"
#else
#define GetVersionExProc "GetVersionExA"
#endif
typedef struct _OBJECT_ATTRIBUTES
{
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef struct SMBIOSEntryPoint
{
    char EntryPointString[4];
    uint8_t Checksum;
    uint8_t Length;
    uint8_t MajorVersion;
    uint8_t MinorVersion;
    uint16_t MaxStructureSize;
    uint8_t EntryPointRevision;
    char FormattedArea[5];
    char EntryPointString2[5];
    uint8_t Checksum2;
    uint16_t TableLength;
    uint32_t TableAddress;
    uint16_t NumberOfStructures;
    uint8_t BCDRevision;
} SMBIOSEntryPoint, *PSMBIOSEntryPoint;
#define InitializeObjectAttributes( p, n, a, r, s ) { \
    (p)->Length = sizeof(OBJECT_ATTRIBUTES);          \
    (p)->RootDirectory = r;                             \
    (p)->Attributes = a;                                \
    (p)->ObjectName = n;                                \
    (p)->SecurityDescriptor = s;                        \
    (p)->SecurityQualityOfService = NULL;               \
}
NTSTATUS(WINAPI *NtUnmapViewOfSection)(
    IN HANDLE  ProcessHandle,
    IN PVOID  BaseAddress
    );
NTSTATUS(WINAPI *NtOpenSection)(
    OUT PHANDLE  SectionHandle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_ATTRIBUTES  ObjectAttributes
    );
NTSTATUS(WINAPI *NtMapViewOfSection)(
    IN HANDLE  SectionHandle,
    IN HANDLE  ProcessHandle,
    IN OUT PVOID *BaseAddress,
    IN ULONG  ZeroBits,
    IN ULONG  CommitSize,
    IN OUT PLARGE_INTEGER  SectionOffset,    /* optional */
    IN OUT PULONG  ViewSize,
    IN SECTION_INHERIT  InheritDisposition,
    IN ULONG  AllocationType,
    IN ULONG  Protect
    );
VOID(WINAPI *RtlInitUnicodeString)(
    IN OUT PUNICODE_STRING  DestinationString,
    IN PCWSTR  SourceString
    );
ULONG(WINAPI *RtlNtStatusToDosError) (
    IN NTSTATUS Status
    );
UINT(WINAPI *Win32GetSystemFirmwareTable)(
    _In_ DWORD FirmwareTableProviderSignature,
    _In_ DWORD FirmwareTableID,
    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer,
    _In_ DWORD BufferSize);
BOOL(WINAPI *Win32GetVersionEx)(
    _Inout_  LPOSVERSIONINFO lpVersionInfo
    );
VOID(WINAPI *Win32GetSystemInfo)(
    _Out_  LPSYSTEM_INFO lpSystemInfo
    );
BOOL(WINAPI *Win32VirtualProtect)(
    _In_   LPVOID lpAddress,
    _In_   SIZE_T dwSize,
    _In_   DWORD flNewProtect,
    _Out_  PDWORD lpflOldProtect
    );
//----------------------------------------------------------------------
//
// PrintError
//
// Formats an error message for the last error
//
// Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//----------------------------------------------------------------------
void PrintError(char *message, NTSTATUS status)
{
    char *errMsg;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, RtlNtStatusToDosError(status),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&errMsg, 0, NULL);
    LocalFree(errMsg);
}
//--------------------------------------------------------
//
// UnmapPhysicalMemory
//
// Maps a view of a section.
//
// Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//--------------------------------------------------------
static VOID UnmapPhysicalMemory(PVOID Address)
{
    NTSTATUS        status;
    status = NtUnmapViewOfSection((HANDLE)-1, Address);
    if (!NT_SUCCESS(status))
    {
        PrintError("Unable to unmap view", status);
    }
}
//--------------------------------------------------------
//
// MapPhysicalMemory
//
// Maps a view of a section.
//
// Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//--------------------------------------------------------
static BOOLEAN MapPhysicalMemory(HANDLE PhysicalMemory,
    PVOID Address, PDWORD Length,
    PVOID *VirtualAddress)
{
    NTSTATUS            ntStatus;
    PHYSICAL_ADDRESS    viewBase;
    char                error[256];
    viewBase.QuadPart = (ULONGLONG)(Address);
    ntStatus = NtMapViewOfSection(PhysicalMemory,
        (HANDLE)-1,
        VirtualAddress,
        0L, *Length,
        &viewBase,
        Length,
        ViewShare,
        0,
        PAGE_READONLY);
    if (!NT_SUCCESS(ntStatus)) {
        PrintError(error, ntStatus);
        return FALSE;
    }
    return TRUE;
}
//--------------------------------------------------------
//
// OpensPhysicalMemory
//
// This function opens the physical memory device. It
// uses the native API since
//
// Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//--------------------------------------------------------
static HANDLE OpenPhysicalMemory()
{
    NTSTATUS        status;
    HANDLE            physmem;
    UNICODE_STRING    physmemString;
    OBJECT_ATTRIBUTES attributes;
    WCHAR            physmemName[] = L"\\device\\physicalmemory";
    RtlInitUnicodeString(&physmemString, physmemName);
    InitializeObjectAttributes(&attributes, &physmemString,
        OBJ_CASE_INSENSITIVE, NULL, NULL);
    status = NtOpenSection(&physmem, SECTION_MAP_READ, &attributes);
    if (!NT_SUCCESS(status))
    {
        PrintError("Could not open \\device\\physicalmemory", status);
        return NULL;
    }
    return physmem;
}
static PVOID MapPhysicalMemoryWithBase(HANDLE hPhyHandle, PVOID pBase, PDWORD pLen, PVOID *pVirtualBase)
{
    DWORD dwOffset = (ULONGLONG)pBase % dwPageSize;
    DWORD dwLen = *pLen + dwOffset;
    PVOID pVAddr = NULL;
    if (MapPhysicalMemory(hPhyHandle, pBase, &dwLen, &pVAddr))
    {
        *pVirtualBase = pVAddr;
        *pLen = dwLen;
        return (PBYTE)pVAddr + dwOffset;
    }
    else
    {
        return NULL;
    }
}
bool InitEntryPoints()
{
    Win32GetVersionEx = decltype(Win32GetVersionEx)(GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), GetVersionExProc));
    if (!Win32GetVersionEx)
        return false;
    Win32GetSystemInfo = decltype(Win32GetSystemInfo)(GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "GetSystemInfo"));
    if (!Win32GetSystemInfo)
        return false;
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!Win32GetVersionEx(&osvi))
        return false;
    bIsWindowsXPLater = ((osvi.dwMajorVersion > 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion > 1)));
    SYSTEM_INFO sysinfo;
    ::ZeroMemory(&sysinfo, sizeof (SYSTEM_INFO));
    Win32GetSystemInfo(&sysinfo);
    dwPageSize = sysinfo.dwPageSize;
    if (bIsWindowsXPLater)
    {
        Win32GetSystemFirmwareTable = decltype(Win32GetSystemFirmwareTable)(GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetSystemFirmwareTable"));
        if (!Win32GetSystemFirmwareTable)
            return false;
    }
    else
    {
        Win32VirtualProtect = decltype(Win32VirtualProtect)(GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "VirtualProtect"));
        if (!Win32VirtualProtect)
            return false;
        RtlInitUnicodeString = (decltype(RtlInitUnicodeString))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "RtlInitUnicodeString"));
        if (!RtlInitUnicodeString)
            return false;
        NtUnmapViewOfSection = (decltype(NtUnmapViewOfSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtUnmapViewOfSection"));
        if (!NtUnmapViewOfSection)
            return false;
        NtOpenSection = (decltype(NtOpenSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtOpenSection"));
        if (!NtOpenSection)
            return false;
        NtMapViewOfSection = (decltype(NtMapViewOfSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtMapViewOfSection"));
        if (!NtMapViewOfSection)
            return false;
        RtlNtStatusToDosError = (decltype(RtlNtStatusToDosError))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "RtlNtStatusToDosError"));
        if (!NtMapViewOfSection)
            return false;
    }
    return true;
}
void *LocateSMBIOS(uint32_t *smbios_size)
{
    void *buf = NULL;
    if (bIsWindowsXPLater)
    {
        uint32_t size = 0;
        size = Win32GetSystemFirmwareTable('RSMB', 0, buf, size);
        if (0 == size)
        {
            return NULL;
        }
        buf = malloc(size);
        if (buf)
        {
            if (0 == Win32GetSystemFirmwareTable('RSMB', 0, buf, size))
            {
                free(buf);
                buf = NULL;
            }
            else
            {
                *smbios_size = size;
            }
        }
    }
    else
    {
        HANDLE hPhysMem = OpenPhysicalMemory();
        if (NULL == hPhysMem)
            return NULL;
        DWORD dwReadLen = 0x10000;
        DWORD dwActualLen = dwReadLen;
        PVOID pBaseVAddr = NULL;
        PVOID pVAddr = MapPhysicalMemoryWithBase(hPhysMem, (PVOID)0xF0000, &dwActualLen, &pBaseVAddr);
        if (!pVAddr)
        {
            ::CloseHandle(hPhysMem);
            return NULL;
        }
        DWORD dwReadOffset = 0;
        PBYTE pbVAddr = (PBYTE)pVAddr;
        PBYTE pbGuardVAddr = pbVAddr + dwReadLen;
        while (pbVAddr < pbGuardVAddr)
        {
            if (pbVAddr[0] == '_' && pbVAddr[1] == 'S' && pbVAddr[2] == 'M' && pbVAddr[3] == '_')
            {
                break;
            }
            pbVAddr += 16;
        }
        //!    no SMBIOS found
        if (pbVAddr >= pbGuardVAddr)
        {
            UnmapPhysicalMemory(pVAddr);
            ::CloseHandle(hPhysMem);
            return NULL;
        }
        PSMBIOSEntryPoint pEntryPoint = (PSMBIOSEntryPoint)pbVAddr;
        RawSMBIOSData *pData = (RawSMBIOSData *)::malloc(pEntryPoint->TableLength + sizeof(RawSMBIOSData));
        PVOID pTableBaseVAddr = NULL;
        if (NULL != pData)
        {
            DWORD dwTableLen = pEntryPoint->TableLength;
            PVOID pTableVAddr = MapPhysicalMemoryWithBase(hPhysMem, (PVOID)pEntryPoint->TableAddress, &dwTableLen, &pTableBaseVAddr);
            if (!pTableVAddr)
            {
                UnmapPhysicalMemory(pBaseVAddr);
                ::CloseHandle(hPhysMem);
                return NULL;
            }
            pData->Used20CallingMethod = 0;
            pData->DmiRevision = 0;
            pData->SMBIOSMajorVersion = pEntryPoint->MajorVersion;
            pData->SMBIOSMinorVersion = pEntryPoint->MinorVersion;
            pData->Length = pEntryPoint->TableLength;
            ::memcpy(pData->SMBIOSTableData, (PVOID)pTableVAddr, pEntryPoint->TableLength);
            *smbios_size = pEntryPoint->TableLength;
        }
        if (NULL != pTableBaseVAddr)
            UnmapPhysicalMemory(pTableBaseVAddr);
        if (NULL != pBaseVAddr)
            UnmapPhysicalMemory(pBaseVAddr);
        ::CloseHandle(hPhysMem);
        buf = pData;
    }
    return buf;
}
src/library/os/windows/isvm/Native.h
New file
@@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
#include <Windows.h>
struct RawSMBIOSData
{
    BYTE    Used20CallingMethod;
    BYTE    SMBIOSMajorVersion;
    BYTE    SMBIOSMinorVersion;
    BYTE    DmiRevision;
    DWORD   Length;
    BYTE    SMBIOSTableData[];
};
bool InitEntryPoints();
void *LocateSMBIOS(uint32_t *smbios_size);
src/library/os/windows/isvm/main.cpp
New file
@@ -0,0 +1,51 @@
#include "intrin.h"
#include <iostream>
#include "BIOSReader.h"
#include "Native.h"
int _tmain(int argc, _TCHAR* argv[])
{
    int cpui[4] = { 0 };
    __cpuid(cpui, 0x1);
    if ((cpui[2] >> 31) & 1)
    {
        std::cout << "Inside virual machine!";
        return 1;
    }
    if (InitEntryPoints())
    {
        BIOSReader reader;
        SystemInformation info = reader.readSystemInfo();
        const char *vmVendors[] =
        {
            "VMware", "Microsoft Corporation", "Virtual Machine", "innotek GmbH", "PowerVM", "Bochs", "KVM"
        };
        const int count = _countof(vmVendors);
        for (int i = 0; i != count; ++i)
        {
            const char *vendor = vmVendors[i];
            if (std::string::npos != info.Manufacturer.find(vendor) ||
                std::string::npos != info.ProductName.find(vendor) ||
                std::string::npos != info.SerialNum.find(vendor))
            {
                std::cout << "Inside virual machine!";
                return 1;
            }
        }
    }
    else
    {
        return -1;
    }
    std::cout << "Inside host machine!";
    return 0;
}
src/library/os/windows/network.cpp
New file
@@ -0,0 +1,113 @@
/**
 * @file network_id.c
 * @date 16 Sep 2014
 * @brief File containing network interface detection functions for Windows.
 *
 * The only public function of this module is #getAdapterInfos(OsAdapterInfo *,
 *        size_t *), other functions are either static or inline.
 *
 * Responsibility of this module is to fill OsAdapterInfo structures, in a predictable way (skip loopback/vpn interfaces)
 */
#ifdef _MSC_VER
#include <Windows.h>
#endif
#include <iphlpapi.h>
#include <unordered_map>
#include <stdio.h>
#pragma comment(lib, "IPHLPAPI.lib")
#include "../../base/StringUtils.h"
#include "../../base/logger.h"
#include "../network.hpp"
namespace license {
namespace os {
using namespace std;
static int translate(char ipStringIn[16], unsigned char ipv4[4]) {
    size_t index = 0;
    char *str2 = ipStringIn; /* save the pointer */
    while (*str2) {
        if (isdigit((unsigned char)*str2)) {
            ipv4[index] *= 10;
            ipv4[index] += *str2 - '0';
        } else {
            index++;
        }
        str2++;
    }
    return 0;
}
/**
 *
 * @param adapterInfos
 * @param adapter_info_size
 * @return
 */
FUNCTION_RETURN getAdapterInfos(vector<OsAdapterInfo> &adapterInfos) {
    unordered_map<string, OsAdapterInfo> adapterByName;
    FUNCTION_RETURN f_return = FUNC_RET_OK;
    DWORD dwStatus;
    int adapter_info_size;
    PIP_ADAPTER_INFO pAdapterInfo;
    DWORD dwBufLen = sizeof(IP_ADAPTER_INFO);
    unsigned int i = 3;
    do {
        pAdapterInfo = (PIP_ADAPTER_INFO)malloc(dwBufLen);
        dwStatus = GetAdaptersInfo(     // Call GetAdapterInfo
            pAdapterInfo,  // [out] buffer to receive data
            &dwBufLen  // [in] size of receive data buffer
        );
        if (dwStatus != NO_ERROR && pAdapterInfo != nullptr) {
            free(pAdapterInfo);
            pAdapterInfo = nullptr;
        }
    } while (dwStatus == ERROR_BUFFER_OVERFLOW && i-- > 0);
    if (dwStatus == ERROR_BUFFER_OVERFLOW) {
        return FUNC_RET_ERROR;
    }
    adapter_info_size = dwBufLen / sizeof(IP_ADAPTER_INFO);
    if (adapter_info_size == 0) {
        return FUNC_RET_NOT_AVAIL;
    }
    PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
    i = 0;
    FUNCTION_RETURN result = FUNC_RET_OK;
    while (pAdapter) {
        OsAdapterInfo ai = {};
        strncpy(ai.description, pAdapter->Description,
                min(sizeof(ai.description), MAX_ADAPTER_DESCRIPTION_LENGTH));
        memcpy(ai.mac_address, pAdapter->Address, 8);
        translate(pAdapter->IpAddressList.IpAddress.String, ai.ipv4_address);
        ai.type = IFACE_TYPE_ETHERNET;
        i++;
        pAdapter = pAdapter->Next;
        if (i == adapter_info_size) {
            result = FUNC_RET_BUFFER_TOO_SMALL;
            break;
        }
        adapterByName[string(ai.description)] = ai;
    }
    free(pAdapterInfo);
    // FIXME sort by eth , enps, wlan
    if (adapterByName.size() == 0) {
        f_return = FUNC_RET_NOT_AVAIL;
    } else {
        f_return = FUNC_RET_OK;
        adapterInfos.reserve(adapterByName.size());
        for (auto &it : adapterByName) {
            adapterInfos.push_back(it.second);
        }
    }
    return f_return;
}
}  // namespace os
}  // namespace license
src/library/os/windows/os-win.c
@@ -1,17 +1,13 @@
#ifdef _MSC_VER
#include <Windows.h>
#endif
#include "../base/logger.h"
#include "os.h"
#include "../../base/logger.h"
#include "../os.h"
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "IPHLPAPI.lib")
unsigned char* unbase64(const char* ascii, int len, int *flen);
FUNCTION_RETURN getOsSpecificIdentifier(unsigned char identifier[6]) {
    return FUNC_RET_NOT_AVAIL;
}
FUNCTION_RETURN getMachineName(unsigned char identifier[6]) {
    FUNCTION_RETURN result = FUNC_RET_ERROR;
@@ -100,79 +96,6 @@
    return return_value;
}
static int translate(char ipStringIn[16], unsigned char ipv4[4]) {
    size_t index = 0;
    char* str2 = ipStringIn; /* save the pointer */
    while (*str2) {
        if (isdigit((unsigned char) *str2)) {
            ipv4[index] *= 10;
            ipv4[index] += *str2 - '0';
        } else {
            index++;
        }
        str2++;
    }
    return 0;
}
//http://stackoverflow.com/questions/18046063/mac-address-using-c
//TODO: count only interfaces with type (MIB_IF_TYPE_ETHERNET IF_TYPE_IEEE80211)
FUNCTION_RETURN getAdapterInfos(OsAdapterInfo * adapterInfos,
        size_t * adapter_info_size) {
    DWORD dwStatus;
    PIP_ADAPTER_INFO pAdapterInfo;
    //IP_ADAPTER_INFO AdapterInfo[20];              // Allocate information for up to 16 NICs
    DWORD dwBufLen = sizeof(IP_ADAPTER_INFO); //10 * sizeof(IP_ADAPTER_INFO);  // Save the memory size of buffer
    unsigned int i = 3;
    do {
        pAdapterInfo = (PIP_ADAPTER_INFO) malloc(dwBufLen);
        dwStatus = GetAdaptersInfo(               // Call GetAdapterInfo
                pAdapterInfo, // [out] buffer to receive data
                &dwBufLen   // [in] size of receive data buffer
                );
        if (dwStatus != NO_ERROR) {
            free(pAdapterInfo);
            pAdapterInfo = NULL;
        }
    } while (dwStatus == ERROR_BUFFER_OVERFLOW && i-- > 0);
    if (dwStatus == ERROR_BUFFER_OVERFLOW) {
        return FUNC_RET_ERROR;
    }
    if (adapterInfos == NULL || *adapter_info_size == 0) {
        *adapter_info_size = dwBufLen / sizeof(IP_ADAPTER_INFO);
        if (pAdapterInfo != NULL){
            free(pAdapterInfo);
        }
        return FUNC_RET_OK;
    }
    *adapter_info_size = dwBufLen / sizeof(IP_ADAPTER_INFO);
    memset(adapterInfos, 0, dwBufLen);
    PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
    i = 0;
    FUNCTION_RETURN result = FUNC_RET_OK;
    while (pAdapter) {
        strncpy(adapterInfos[i].description, pAdapter->Description,
                min(sizeof(adapterInfos->description),
                        MAX_ADAPTER_DESCRIPTION_LENGTH));
        memcpy(adapterInfos[i].mac_address, pAdapter->Address, 8);
        translate(pAdapter->IpAddressList.IpAddress.String,
                adapterInfos[i].ipv4_address);
        adapterInfos[i].type = IFACE_TYPE_ETHERNET;
        i++;
        pAdapter = pAdapter->Next;
        if (i == *adapter_info_size) {
            result = FUNC_RET_BUFFER_TOO_SMALL;
            break;
        }
    }
    free(pAdapterInfo);
    return result;
}
FUNCTION_RETURN getModuleName(char buffer[MAX_PATH]) {
    FUNCTION_RETURN result = FUNC_RET_OK;
@@ -183,29 +106,4 @@
    return result;
}
// TODO: remove unused
static void printHash(HCRYPTHASH* hHash) {
    DWORD dwHashLen;
    DWORD dwHashLenSize = sizeof(DWORD);
    if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE *) &dwHashLen,
            &dwHashLenSize, 0)) {
        BYTE* pbHash = (BYTE*)malloc(dwHashLen);
        char* hashStr = (char*)malloc(dwHashLen * 2 + 1);
        if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) {
            for (unsigned int i = 0; i < dwHashLen; i++) {
                sprintf(&hashStr[i * 2], "%02x", pbHash[i]);
            } LOG_DEBUG("Hash to verify: %s", hashStr);
        }
        free(pbHash);
        free(hashStr);
    }
}
/**
 * Not implemented yet.
 */
VIRTUALIZATION getVirtualization() {
    return NONE;
}