From ed8d5e30f05ad96e66ffdb209c7868f8ac8da4c1 Mon Sep 17 00:00:00 2001
From: gcontini <1121667+gcontini@users.noreply.github.com>
Date: 周一, 24 2月 2020 05:20:25 +0800
Subject: [PATCH] windows progress

---
 src/library/locate/ExternalDefinition.cpp             |    4 
 src/library/os/windows/isvm/BIOSReader.h              |   21 
 src/library/os/windows/isvm/BIOSReader.cpp            |  145 ++++++
 src/library/os/windows/network.cpp                    |  113 ++++
 src/library/hw_identifier/identification_strategy.hpp |    1 
 src/library/os/windows/cpu_info.cpp                   |   47 ++
 src/library/os/CMakeLists.txt                         |   18 
 src/library/os/windows/execution_environment.cpp      |   70 +++
 src/library/os/windows/isvm/Native.cpp                |  437 +++++++++++++++++++
 src/library/os/windows/isvm/Native.h                  |   18 
 doc/snippets/hardware.cpp                             |  266 +++++++++++
 /dev/null                                             |    1 
 src/library/os/execution_environment.hpp              |    5 
 src/library/os/linux/network.cpp                      |   20 
 doc/CREDITS.md                                        |    9 
 src/library/os/windows/os-win.c                       |  106 ----
 src/library/os/windows/isvm/main.cpp                  |   51 ++
 src/library/hw_identifier/default_strategy.cpp        |    2 
 18 files changed, 1,197 insertions(+), 137 deletions(-)

diff --git a/doc/CREDITS.md b/doc/CREDITS.md
index 918606c..74b8e5e 100644
--- a/doc/CREDITS.md
+++ b/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.
-=============================
+
 
diff --git a/doc/snippets/hardware.cpp b/doc/snippets/hardware.cpp
new file mode 100644
index 0000000..bf4e0be
--- /dev/null
+++ b/doc/snippets/hardware.cpp
@@ -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;
+}
+*/
\ No newline at end of file
diff --git a/src/library/hw_identifier/default_strategy.cpp b/src/library/hw_identifier/default_strategy.cpp
index a770512..b46771c 100644
--- a/src/library/hw_identifier/default_strategy.cpp
+++ b/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) {
diff --git a/src/library/hw_identifier/identification_strategy.hpp b/src/library/hw_identifier/identification_strategy.hpp
index ad3e2de..1b0985d 100644
--- a/src/library/hw_identifier/identification_strategy.hpp
+++ b/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"
 
diff --git a/src/library/locate/ExternalDefinition.cpp b/src/library/locate/ExternalDefinition.cpp
index 7add948..3ee7453 100644
--- a/src/library/locate/ExternalDefinition.cpp
+++ b/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) {}
diff --git a/src/library/os/CMakeLists.txt b/src/library/os/CMakeLists.txt
index 986550f..ef0fd62 100644
--- a/src/library/os/CMakeLists.txt
+++ b/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)
diff --git a/src/library/os/execution_environment.hpp b/src/library/os/execution_environment.hpp
index ce3fb63..1c15ab4 100644
--- a/src/library/os/execution_environment.hpp
+++ b/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_ */
diff --git a/src/library/os/linux/network.cpp b/src/library/os/linux/network.cpp
index e456989..475463b 100644
--- a/src/library/os/linux/network.cpp
+++ b/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;
-}
 
 /**
  *
diff --git a/src/library/os/windows/.gitignore b/src/library/os/windows/.gitignore
deleted file mode 100644
index f3d0437..0000000
--- a/src/library/os/windows/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/isvm/
diff --git a/src/library/os/windows/cpu_info.cpp b/src/library/os/windows/cpu_info.cpp
new file mode 100644
index 0000000..764b2fe
--- /dev/null
+++ b/src/library/os/windows/cpu_info.cpp
@@ -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 */
diff --git a/src/library/os/windows/execution_environment.cpp b/src/library/os/windows/execution_environment.cpp
new file mode 100644
index 0000000..b9d43ca
--- /dev/null
+++ b/src/library/os/windows/execution_environment.cpp
@@ -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
diff --git a/src/library/os/windows/isvm/BIOSReader.cpp b/src/library/os/windows/isvm/BIOSReader.cpp
new file mode 100644
index 0000000..0974f1b
--- /dev/null
+++ b/src/library/os/windows/isvm/BIOSReader.cpp
@@ -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;
+}
diff --git a/src/library/os/windows/isvm/BIOSReader.h b/src/library/os/windows/isvm/BIOSReader.h
new file mode 100644
index 0000000..569facf
--- /dev/null
+++ b/src/library/os/windows/isvm/BIOSReader.h
@@ -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
diff --git a/src/library/os/windows/isvm/Native.cpp b/src/library/os/windows/isvm/Native.cpp
new file mode 100644
index 0000000..99fbf8f
--- /dev/null
+++ b/src/library/os/windows/isvm/Native.cpp
@@ -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;
+}
diff --git a/src/library/os/windows/isvm/Native.h b/src/library/os/windows/isvm/Native.h
new file mode 100644
index 0000000..5124c8d
--- /dev/null
+++ b/src/library/os/windows/isvm/Native.h
@@ -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);
+
diff --git a/src/library/os/windows/isvm/main.cpp b/src/library/os/windows/isvm/main.cpp
new file mode 100644
index 0000000..105c105
--- /dev/null
+++ b/src/library/os/windows/isvm/main.cpp
@@ -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;
+}
+
diff --git a/src/library/os/windows/network.cpp b/src/library/os/windows/network.cpp
new file mode 100644
index 0000000..fd111aa
--- /dev/null
+++ b/src/library/os/windows/network.cpp
@@ -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
diff --git a/src/library/os/windows/os-win.c b/src/library/os/windows/os-win.c
index aa6c5f3..4a9e204 100644
--- a/src/library/os/windows/os-win.c
+++ b/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;
-}
 

--
Gitblit v1.9.1