diff --git a/.gitignore b/.gitignore
index b8bd026..dc30d1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,209 @@
*.exe
*.out
*.app
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
\ No newline at end of file
diff --git a/Build.cmd b/Build.cmd
new file mode 100644
index 0000000..4fed998
--- /dev/null
+++ b/Build.cmd
@@ -0,0 +1,22 @@
+@echo off
+setlocal EnableExtensions
+setlocal EnableDelayedExpansion
+pushd "%~dp0"
+reg.exe query "hklm\software\microsoft\Windows NT\currentversion" /v buildlabex | find /i "amd64" >nul 2>&1
+if %errorlevel% equ 0 set xOS=x64
+if /i "%PROCESSOR_ARCHITECTURE%"=="x86" if not defined PROCESSOR_ARCHITEW6432 set xOS=x86
+
+if "%xOS%"=="x86" (
+cd /D "%PROGRAMFILES%\MSBuild\12.0\Bin\
+) ELSE (
+cd /D "%PROGRAMFILES(x86)%\MSBuild\12.0\Bin\
+)
+
+REM Build x86 Release
+MSBuild "%~dp0KMSEmulator.sln" /p:configuration="Release" /p:platform="Win32"
+
+REM Build x64 Release
+MSBuild "%~dp0KMSEmulator.sln" /p:configuration="Release" /p:platform="x64"
+
+REM Clean Solution of Junk Files
+call "%~dp0Clean.cmd"
\ No newline at end of file
diff --git a/Clean.cmd b/Clean.cmd
new file mode 100644
index 0000000..ed44287
--- /dev/null
+++ b/Clean.cmd
@@ -0,0 +1,27 @@
+@echo off
+cd /D %~dp0
+REM Delete Precompiled Headers
+FOR /D /R %%X IN (ipch*) DO RD /S /Q "%%X"
+
+REM Delete obj Folders
+FOR /D /R %%X IN (obj*) DO RD /S /Q "%%X"
+
+REM Delete Debug Folders
+FOR /D /R %%X IN (Debug*) DO RD /S /Q "%%X"
+
+REM Delete Static Library Binary Folders
+RD /S /Q "%~dp0KMS Client Library\bin"
+RD /S /Q "%~dp0KMS Server Library\bin"
+RD /S /Q "%~dp0KMS Stub Library\bin"
+
+REM Delete EXP Files
+DEL /f /s /q *.exp
+
+REM Delete LIB Files
+DEL /f /s /q *.lib
+
+REM Delete PDB Files
+DEL /f /s /q *.pdb
+
+REM Delete SDF Files
+DEL /f /s /q *.sdf
\ No newline at end of file
diff --git a/KMS Client Library/KMS Client Library.vcxproj b/KMS Client Library/KMS Client Library.vcxproj
new file mode 100644
index 0000000..0ce2fcc
--- /dev/null
+++ b/KMS Client Library/KMS Client Library.vcxproj
@@ -0,0 +1,172 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}
+ Win32Proj
+ KMSClientLibrary
+
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ NoExtensions
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Windows
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ NoExtensions
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Client Library/KMS Client Library.vcxproj.filters b/KMS Client Library/KMS Client Library.vcxproj.filters
new file mode 100644
index 0000000..58c34e6
--- /dev/null
+++ b/KMS Client Library/KMS Client Library.vcxproj.filters
@@ -0,0 +1,51 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/KMS Client/KMS Client.vcxproj b/KMS Client/KMS Client.vcxproj
new file mode 100644
index 0000000..2876abf
--- /dev/null
+++ b/KMS Client/KMS Client.vcxproj
@@ -0,0 +1,173 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {bf8574c9-3770-48d5-a8fa-dcab6c3145d3}
+
+
+ {de697625-1bbe-40c1-877f-c5dd6d657199}
+
+
+
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}
+ KMSClient
+
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+ Level4
+ Disabled
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ %(PreprocessorDefinitions)
+ NoExtensions
+
+
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Disabled
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ %(PreprocessorDefinitions)
+ NoExtensions
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Client/KMS Client.vcxproj.filters b/KMS Client/KMS Client.vcxproj.filters
new file mode 100644
index 0000000..f474a0c
--- /dev/null
+++ b/KMS Client/KMS Client.vcxproj.filters
@@ -0,0 +1,35 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/KMS Client/Resource.rc b/KMS Client/Resource.rc
new file mode 100644
index 0000000..09671d3
Binary files /dev/null and b/KMS Client/Resource.rc differ
diff --git a/KMS Client/main.cpp b/KMS Client/main.cpp
new file mode 100644
index 0000000..1afe81c
--- /dev/null
+++ b/KMS Client/main.cpp
@@ -0,0 +1,15 @@
+// Includes and Namespaces
+#include "KMSClientLib.h"
+
+// KMS Client Console Main EntryPoint
+int wmain(int argc, wchar_t* argv[])
+{
+ // Get Application Parameters
+ LoadClientParameters(argc, argv, false);
+
+ // Start KMS Client
+ StartKMSClient();
+
+ // Progrem Stopped
+ return 0;
+}
\ No newline at end of file
diff --git a/KMS Client/resource.h b/KMS Client/resource.h
new file mode 100644
index 0000000..15ea5dd
Binary files /dev/null and b/KMS Client/resource.h differ
diff --git a/KMS Emulator DLL/KMS Emulator DLL.cpp b/KMS Emulator DLL/KMS Emulator DLL.cpp
new file mode 100644
index 0000000..26fec99
--- /dev/null
+++ b/KMS Emulator DLL/KMS Emulator DLL.cpp
@@ -0,0 +1,30 @@
+// KMS Emulator DLL.cpp : Defines the exported functions for the DLL application.
+//
+
+// Includes and Namespaces
+#include "stdafx.h"
+
+// DLL Export Function Prototypes
+extern "C" __declspec(dllexport) void RunKMSClient(int argc, wchar_t *argv[], bool RunAsService);
+extern "C" __declspec(dllexport) void RunKMSServer(int argc, wchar_t *argv[], bool RunAsService);
+extern "C" __declspec(dllexport) void KillKMSServer();
+
+// Load KMS Client Options and Start KMS Client
+extern "C" __declspec(dllexport) void RunKMSClient(int argc, wchar_t *argv[], bool RunAsService)
+{
+ LoadClientParameters(argc, argv, RunAsService);
+ StartKMSClient();
+}
+
+// Load KMS Server Options and Start KMS Server
+extern "C" __declspec(dllexport) void RunKMSServer(int argc, wchar_t *argv[], bool RunAsService)
+{
+ LoadServerParameters(argc, argv, RunAsService);
+ StartKMSServer();
+}
+
+// Stop KMS Server
+extern "C" __declspec(dllexport) void KillKMSServer()
+{
+ StopKMSServer();
+}
\ No newline at end of file
diff --git a/KMS Emulator DLL/KMS Emulator DLL.vcxproj b/KMS Emulator DLL/KMS Emulator DLL.vcxproj
new file mode 100644
index 0000000..d4ed0c3
--- /dev/null
+++ b/KMS Emulator DLL/KMS Emulator DLL.vcxproj
@@ -0,0 +1,202 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}
+ Win32Proj
+ KMSEmulatorDLL
+
+
+
+ DynamicLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ true
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ false
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ false
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+ NotUsing
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ NoExtensions
+
+
+ Windows
+ true
+
+
+
+
+ NotUsing
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Windows
+ true
+
+
+
+
+ Level4
+ NotUsing
+ Full
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;KMSEMULATORDLL_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ NoExtensions
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+ NotUsing
+ Full
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;KMSEMULATORDLL_EXPORTS;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+
+ false
+ false
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+ {bf8574c9-3770-48d5-a8fa-dcab6c3145d3}
+
+
+ {903184f0-3e00-40d5-82a7-0f99ddf11e37}
+
+
+ {de697625-1bbe-40c1-877f-c5dd6d657199}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Emulator DLL/KMS Emulator DLL.vcxproj.filters b/KMS Emulator DLL/KMS Emulator DLL.vcxproj.filters
new file mode 100644
index 0000000..f0d9847
--- /dev/null
+++ b/KMS Emulator DLL/KMS Emulator DLL.vcxproj.filters
@@ -0,0 +1,44 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/KMS Emulator DLL/Resource.rc b/KMS Emulator DLL/Resource.rc
new file mode 100644
index 0000000..cf6a5b7
Binary files /dev/null and b/KMS Emulator DLL/Resource.rc differ
diff --git a/KMS Emulator DLL/dllmain.cpp b/KMS Emulator DLL/dllmain.cpp
new file mode 100644
index 0000000..f425dc7
--- /dev/null
+++ b/KMS Emulator DLL/dllmain.cpp
@@ -0,0 +1,19 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ // No Unreferenced Parameter Warnings
+ UNREFERENCED_PARAMETER(hModule);
+ UNREFERENCED_PARAMETER(lpReserved);
+
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
\ No newline at end of file
diff --git a/KMS Emulator DLL/resource.h b/KMS Emulator DLL/resource.h
new file mode 100644
index 0000000..15ea5dd
Binary files /dev/null and b/KMS Emulator DLL/resource.h differ
diff --git a/KMS Emulator DLL/stdafx.cpp b/KMS Emulator DLL/stdafx.cpp
new file mode 100644
index 0000000..7c90cf0
--- /dev/null
+++ b/KMS Emulator DLL/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// KMS Server DLL.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/KMS Emulator DLL/stdafx.h b/KMS Emulator DLL/stdafx.h
new file mode 100644
index 0000000..fbea841
--- /dev/null
+++ b/KMS Emulator DLL/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include
+
+// Reference additional headers your program requires here
+#include "KMSClientLib.h"
+#include "KMSServerLib.h"
\ No newline at end of file
diff --git a/KMS Emulator DLL/targetver.h b/KMS Emulator DLL/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/KMS Emulator DLL/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include
diff --git a/KMS Server Library/KMS Server Library.vcxproj b/KMS Server Library/KMS Server Library.vcxproj
new file mode 100644
index 0000000..2a6ff2b
--- /dev/null
+++ b/KMS Server Library/KMS Server Library.vcxproj
@@ -0,0 +1,176 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}
+ Win32Proj
+ KMSServerLibrary
+
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ NoExtensions
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Windows
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ NoExtensions
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Server Library/KMS Server Library.vcxproj.filters b/KMS Server Library/KMS Server Library.vcxproj.filters
new file mode 100644
index 0000000..4c62cbd
--- /dev/null
+++ b/KMS Server Library/KMS Server Library.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/KMS Server Service/KMS Server Service.vcxproj b/KMS Server Service/KMS Server Service.vcxproj
new file mode 100644
index 0000000..fbc8588
--- /dev/null
+++ b/KMS Server Service/KMS Server Service.vcxproj
@@ -0,0 +1,170 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {903184f0-3e00-40d5-82a7-0f99ddf11e37}
+
+
+ {de697625-1bbe-40c1-877f-c5dd6d657199}
+
+
+
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}
+ KMSServerService
+ KMS Server Service
+
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+ Level4
+ Disabled
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ NoExtensions
+
+
+ true
+ Console
+ 1.0
+
+
+
+
+ Level4
+ Disabled
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ true
+ Console
+ 1.0
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ NoExtensions
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Server Service/KMS Server Service.vcxproj.filters b/KMS Server Service/KMS Server Service.vcxproj.filters
new file mode 100644
index 0000000..fe26905
--- /dev/null
+++ b/KMS Server Service/KMS Server Service.vcxproj.filters
@@ -0,0 +1,35 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/KMS Server Service/Resource.rc b/KMS Server Service/Resource.rc
new file mode 100644
index 0000000..a4c9c88
Binary files /dev/null and b/KMS Server Service/Resource.rc differ
diff --git a/KMS Server Service/main.cpp b/KMS Server Service/main.cpp
new file mode 100644
index 0000000..d7e7319
--- /dev/null
+++ b/KMS Server Service/main.cpp
@@ -0,0 +1,81 @@
+// Includes and Namespaces
+#include "KMSServerLib.h"
+
+// Function Prototypes
+void ServiceMain(int argc, char** argv);
+void ControlHandler(DWORD code);
+
+// Windows Service Parameters
+extern SERVICE_STATUS ServerServiceStatus;
+extern SERVICE_STATUS_HANDLE ServerServiceHandle;
+WCHAR ServiceName[] = L"KMSServerService";
+
+// KMS Server Service Main EntryPoint
+int wmain(int argc, wchar_t* argv[])
+{
+ // Get Application Parameters
+ LoadServerParameters(argc, argv, true);
+
+ // Windows Service Parameters
+ SERVICE_TABLE_ENTRY ServiceTable[2] = {0};
+ ServiceTable[0].lpServiceName = ServiceName;
+ ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
+
+ // Start Service Control Dispatcher Thread for our Service
+ StartServiceCtrlDispatcher(ServiceTable);
+
+ // Service Stopped
+ return 0;
+}
+
+// KMS Server Service EntryPoint
+void ServiceMain(int argc, char* argv[])
+{
+ // No Unreferenced Parameter Warnings
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ // Register Control Handler
+ ServerServiceHandle = RegisterServiceCtrlHandlerW(ServiceName, (LPHANDLER_FUNCTION)ControlHandler);
+
+ // RegisterServiceCtrlHandlerW returned NULL PTR
+ if (ServerServiceHandle == NULL)
+ {
+ // Registering Control Handler failed
+ return;
+ }
+
+ ServerServiceStatus.dwServiceType = SERVICE_WIN32;
+ ServerServiceStatus.dwCurrentState = SERVICE_RUNNING;
+ ServerServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
+ ServerServiceStatus.dwWin32ExitCode = ERROR_SUCCESS;
+ ServerServiceStatus.dwServiceSpecificExitCode = NULL;
+ ServerServiceStatus.dwCheckPoint = NULL;
+ ServerServiceStatus.dwWaitHint = NULL;
+
+ // Report Service Status to SCM.
+ SetServiceStatus(ServerServiceHandle, &ServerServiceStatus);
+
+ // Start KMS Server
+ StartKMSServer();
+}
+
+// Control Handler
+void ControlHandler(DWORD code)
+{
+ switch(code)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ ServerServiceStatus.dwWin32ExitCode = ERROR_SUCCESS;
+ ServerServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ break;
+ case SERVICE_USER_DEFINED_CONTROL:
+ ServerServiceStatus.dwWin32ExitCode = ERROR_BAD_CONFIGURATION;
+ ServerServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ break;
+ }
+
+ // Report Service Status
+ SetServiceStatus(ServerServiceHandle, &ServerServiceStatus);
+}
\ No newline at end of file
diff --git a/KMS Server Service/resource.h b/KMS Server Service/resource.h
new file mode 100644
index 0000000..15ea5dd
Binary files /dev/null and b/KMS Server Service/resource.h differ
diff --git a/KMS Server/KMS Server.vcxproj b/KMS Server/KMS Server.vcxproj
new file mode 100644
index 0000000..926aada
--- /dev/null
+++ b/KMS Server/KMS Server.vcxproj
@@ -0,0 +1,170 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+ {903184f0-3e00-40d5-82a7-0f99ddf11e37}
+
+
+ {de697625-1bbe-40c1-877f-c5dd6d657199}
+
+
+
+
+
+
+ {B729294A-35C1-4720-A125-1C5996C8473F}
+ KMSServer
+
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+ Application
+ false
+ true
+ Unicode
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+ Level4
+ Disabled
+ MultiThreadedDebug
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ NoExtensions
+
+
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Disabled
+ MultiThreadedDebug
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+
+
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ MultiThreaded
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ NoExtensions
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+ Level4
+ Full
+ true
+ true
+ MultiThreaded
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+
+
+ true
+ true
+ true
+ Console
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Server/KMS Server.vcxproj.filters b/KMS Server/KMS Server.vcxproj.filters
new file mode 100644
index 0000000..6b383ec
--- /dev/null
+++ b/KMS Server/KMS Server.vcxproj.filters
@@ -0,0 +1,26 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Server/Resource.rc b/KMS Server/Resource.rc
new file mode 100644
index 0000000..89f9208
Binary files /dev/null and b/KMS Server/Resource.rc differ
diff --git a/KMS Server/main.cpp b/KMS Server/main.cpp
new file mode 100644
index 0000000..3d5986e
--- /dev/null
+++ b/KMS Server/main.cpp
@@ -0,0 +1,15 @@
+// Includes and Namespaces
+#include "KMSServerLib.h"
+
+// KMS Server Console Main EntryPoint
+int wmain(int argc, wchar_t* argv[])
+{
+ // Get Application Parameters
+ LoadServerParameters(argc, argv, false);
+
+ // Start KMS Server
+ StartKMSServer();
+
+ // Progrem Stopped
+ return 0;
+}
\ No newline at end of file
diff --git a/KMS Server/resource.h b/KMS Server/resource.h
new file mode 100644
index 0000000..15ea5dd
Binary files /dev/null and b/KMS Server/resource.h differ
diff --git a/KMS Stub Library/KMS Stub Library.vcxproj b/KMS Stub Library/KMS Stub Library.vcxproj
new file mode 100644
index 0000000..6dac95f
--- /dev/null
+++ b/KMS Stub Library/KMS Stub Library.vcxproj
@@ -0,0 +1,166 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}
+ Win32Proj
+ KMSStubLibrary
+
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ true
+ v120_xp
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+ bin\x86\$(Configuration)\
+ obj\x86\$(Configuration)\
+
+
+ bin\x64\$(Configuration)\
+ obj\x64\$(Configuration)\
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ NoExtensions
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level4
+ Disabled
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Windows
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ NoExtensions
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level4
+
+
+ Full
+ true
+ true
+ true
+ $(SolutionDir)\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KMS Stub Library/KMS Stub Library.vcxproj.filters b/KMS Stub Library/KMS Stub Library.vcxproj.filters
new file mode 100644
index 0000000..9303582
--- /dev/null
+++ b/KMS Stub Library/KMS Stub Library.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/KMSEmulator.sln b/KMSEmulator.sln
new file mode 100644
index 0000000..02bde28
--- /dev/null
+++ b/KMSEmulator.sln
@@ -0,0 +1,88 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Server", "KMS Server\KMS Server.vcxproj", "{B729294A-35C1-4720-A125-1C5996C8473F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Client", "KMS Client\KMS Client.vcxproj", "{4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Server Service", "KMS Server Service\KMS Server Service.vcxproj", "{9D4665B7-A3A4-4526-AACA-181AA64998C6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Client Library", "KMS Client Library\KMS Client Library.vcxproj", "{BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Server Library", "KMS Server Library\KMS Server Library.vcxproj", "{903184F0-3E00-40D5-82A7-0F99DDF11E37}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Emulator DLL", "KMS Emulator DLL\KMS Emulator DLL.vcxproj", "{0A20C4D6-B67A-4424-85BA-65FBAEB90259}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KMS Stub Library", "KMS Stub Library\KMS Stub Library.vcxproj", "{DE697625-1BBE-40C1-877F-C5DD6D657199}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Debug|Win32.Build.0 = Debug|Win32
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Debug|x64.ActiveCfg = Debug|x64
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Debug|x64.Build.0 = Debug|x64
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Release|Win32.ActiveCfg = Release|Win32
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Release|Win32.Build.0 = Release|Win32
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Release|x64.ActiveCfg = Release|x64
+ {B729294A-35C1-4720-A125-1C5996C8473F}.Release|x64.Build.0 = Release|x64
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Debug|Win32.Build.0 = Debug|Win32
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Debug|x64.ActiveCfg = Debug|x64
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Debug|x64.Build.0 = Debug|x64
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Release|Win32.ActiveCfg = Release|Win32
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Release|Win32.Build.0 = Release|Win32
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Release|x64.ActiveCfg = Release|x64
+ {4FFEE4C8-015E-4A1F-B6D4-82735E95B95B}.Release|x64.Build.0 = Release|x64
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Debug|Win32.Build.0 = Debug|Win32
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Debug|x64.ActiveCfg = Debug|x64
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Debug|x64.Build.0 = Debug|x64
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Release|Win32.ActiveCfg = Release|Win32
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Release|Win32.Build.0 = Release|Win32
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Release|x64.ActiveCfg = Release|x64
+ {9D4665B7-A3A4-4526-AACA-181AA64998C6}.Release|x64.Build.0 = Release|x64
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Debug|Win32.Build.0 = Debug|Win32
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Debug|x64.ActiveCfg = Debug|x64
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Debug|x64.Build.0 = Debug|x64
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Release|Win32.ActiveCfg = Release|Win32
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Release|Win32.Build.0 = Release|Win32
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Release|x64.ActiveCfg = Release|x64
+ {BF8574C9-3770-48D5-A8FA-DCAB6C3145D3}.Release|x64.Build.0 = Release|x64
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Debug|Win32.ActiveCfg = Debug|Win32
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Debug|Win32.Build.0 = Debug|Win32
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Debug|x64.ActiveCfg = Debug|x64
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Debug|x64.Build.0 = Debug|x64
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Release|Win32.ActiveCfg = Release|Win32
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Release|Win32.Build.0 = Release|Win32
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Release|x64.ActiveCfg = Release|x64
+ {903184F0-3E00-40D5-82A7-0F99DDF11E37}.Release|x64.Build.0 = Release|x64
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Debug|Win32.Build.0 = Debug|Win32
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Debug|x64.ActiveCfg = Debug|x64
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Debug|x64.Build.0 = Debug|x64
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Release|Win32.ActiveCfg = Release|Win32
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Release|Win32.Build.0 = Release|Win32
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Release|x64.ActiveCfg = Release|x64
+ {0A20C4D6-B67A-4424-85BA-65FBAEB90259}.Release|x64.Build.0 = Release|x64
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Debug|Win32.Build.0 = Debug|Win32
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Debug|x64.ActiveCfg = Debug|x64
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Debug|x64.Build.0 = Debug|x64
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Release|Win32.ActiveCfg = Release|Win32
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Release|Win32.Build.0 = Release|Win32
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Release|x64.ActiveCfg = Release|x64
+ {DE697625-1BBE-40C1-877F-C5DD6D657199}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/include/CoreKMS.h b/include/CoreKMS.h
new file mode 100644
index 0000000..4ee12e1
--- /dev/null
+++ b/include/CoreKMS.h
@@ -0,0 +1,166 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+//---------------------------------------------------------------------------
+// Defines
+#define MAX_RESPONSE_SIZE 512
+#define MAX_REQUEST_SIZE 256 // 260
+#define PID_BUFFER_SIZE 64
+#define PORT_BUFFER_SIZE 6
+#define GUID_BUFFER_SIZE 37
+#define HASH_SIZE 16
+#define HASH_SIZE_SHA256 32
+#define HASH_SIZE_HMAC_SHA256 16
+//---------------------------------------------------------------------------
+// Typdefs
+typedef unsigned long long QWORD;
+typedef unsigned long long *PQWORD;
+//---------------------------------------------------------------------------
+
+// Struct Prototypes
+#pragma warning( disable: 4201 ) // Disable warning C4201: nonstandard extension used : nameless struct/union
+// Base Properties for KMS Client Request
+struct REQUEST
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ DWORD IsClientVM; // Whether or not the KMS Client is a Virtual Machine
+ DWORD LicenseStatus; // Microsoft Licensing Status Code
+ DWORD GraceTime; // The time in Minutes of the KMS Client's Licensing Grace Period
+ GUID ApplicationId; // Microsoft Product Application ID
+ GUID SkuId; // Microsoft Product SKU ID
+ GUID KmsCountedId; // Microsoft Identifier for KMS Client Request Counting and Activation
+ GUID ClientMachineId; // Unique Identifier to Distinguish KMS Clients
+ DWORD RequiredClientCount; // Number of KMS Clients that must have requested KMS Server Activation
+ FILETIME RequestTime; // Time of KMS Client Request
+ GUID PreviousClientMachineId; // Previous Client Machine ID
+ WCHAR MachineName[64]; // KMS Client Network DNS Name
+};
+
+// Base Properties for KMS Server Response
+struct RESPONSE
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ DWORD KMSPIDLength; // Length of KMS PID
+ WCHAR KMSPID[PID_BUFFER_SIZE]; // Microsoft Product Key ID for KMS Server Activated Product Key
+ GUID ClientMachineId; // Unique Identifier of KMS Client
+ FILETIME RequestTime; // Time of KMS Client Request
+ DWORD KMSCurrentCount; // Number of KMS Clients that currently have requested KMS Server Activation
+ DWORD VLActivationInterval; // The time in Minutes that Unactivated KMS Clients will wait before requesting Activation
+ DWORD VLRenewalInterval; // The time in Minutes that Activated KMS Clients will wait before requesting Reactivation
+};
+
+// KMS Client Request V4 Object
+struct REQUEST_V4
+{
+ REQUEST RequestBase; // Unhashed KMS Client Request Data
+ BYTE Hash[HASH_SIZE]; // MAC Hash of KMS Client Request Data
+};
+
+// KMS Server Response V4 Object
+struct RESPONSE_V4
+{
+ RESPONSE ResponseBase; // Unhashed KMS Server Response Data
+ BYTE Hash[HASH_SIZE]; // MAC Hash of KMS Server Response Data
+};
+
+// KMS Client Request V5 Object
+struct REQUEST_V5
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ BYTE Salt[16]; // KMS Client AES Initialization Vector (Salt)
+ REQUEST RequestBase; // Unhashed KMS Client Request Data
+ BYTE Pad[4]; // Padding - Fill Message, so that encryptSize is divisible by blocklength
+};
+
+// KMS Server Response V5 Object
+struct RESPONSE_V5
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ BYTE RequestSalt[16]; // KMS Client AES Initialization Vector (Salt)
+ RESPONSE ResponseBase; // Unhashed KMS Server Response Data
+ BYTE Salt[16]; // KMS Server AES Initialization Vector (Salt) : Not Used. Possible MS Bug: The Request IV is used instead.
+ BYTE Hash[HASH_SIZE_SHA256]; // Hash of KMS Server Response Data
+ BYTE Pad[2]; // PKCS5 Padding
+};
+
+// KMS Client Request V6 Object
+struct REQUEST_V6
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ BYTE Salt[16]; // KMS Client AES Initialization Vector (Salt)
+ REQUEST RequestBase; // Unhashed KMS Client Request Data
+ BYTE Pad[4]; // Padding - Fill Message, so that encryptSize is divisible by blocklength
+};
+
+// KMS Server Response V6 Object
+struct RESPONSE_V6
+{
+ union
+ {
+ DWORD Version; // KMS Protocol Version
+ struct
+ {
+ WORD MinorVer; // KMS Protocol Minor Version
+ WORD MajorVer; // KMS Protocol Major Version
+ };
+ };
+
+ BYTE RequestSalt[16]; // KMS Client AES Initialization Vector (Salt)
+ RESPONSE ResponseBase; // Unhashed KMS Server Response Data
+ BYTE Salt[16]; // KMS Server AES Initialization Vector (Salt) : Not Used. Possible MS Bug: The Request IV is used instead.
+ BYTE Hash[HASH_SIZE_SHA256]; // Hash of KMS Server Response Data
+ BYTE MachineHardwareHash[8]; // Most likely the machine hardware hash of the server
+ BYTE Xor2[16]; // Xor2 ???
+ BYTE HMAC_SHA256[HASH_SIZE_HMAC_SHA256]; // HMAC-SHA256 (RFC 2104)
+ BYTE Pad[10]; // PKCS5 Padding
+};
+#pragma warning( default: 4201 ) // Enable warning C4201: nonstandard extension used : nameless struct/union
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/Crypto.h b/include/Crypto.h
new file mode 100644
index 0000000..37ecf17
--- /dev/null
+++ b/include/Crypto.h
@@ -0,0 +1,30 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+
+// Constants
+#define AES_TYPE_128 0
+#define AES_TYPE_192 1
+#define AES_TYPE_256 2
+
+#define AES_MODE_ECB 0
+#define AES_MODE_CBC 1
+#define AES_MODE_CFB 2
+#define AES_MODE_OFB 3
+#define AES_MODE_CTR 4
+
+//---------------------------------------------------------------------------
+// Function Prototypes
+void AESDecryptMessage(PBYTE const IV, PBYTE const Message, PDWORD const MessageSize);
+void AESEncryptMessage(PBYTE const IV, PBYTE const Message, PDWORD const MessageSize, DWORD BufferLen);
+
+BYTE MULx2(BYTE bIn);
+BYTE MULx3(BYTE bIn);
+DWORD AesInit(DWORD dwType, DWORD dwMode, BYTE bPadding, PBYTE pbKey, PBYTE pbIV);
+DWORD AesClear(void);
+void DecryptMessage(int MessageSize, PBYTE Message);
+void EncryptMessage(int MessageSize, PBYTE Message);
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/Hash.h b/include/Hash.h
new file mode 100644
index 0000000..9553c77
--- /dev/null
+++ b/include/Hash.h
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+//---------------------------------------------------------------------------
+
+// HMAC-SHA256 key blob structure
+struct HMAC_KEYBLOB {
+ BLOBHEADER hdr;
+ DWORD dwKeySize;
+ BYTE rgbKeyData[16];
+};
+
+// Function Prototypes
+void GetHash(DWORD MessageSize, PBYTE const Message, PBYTE const hash);
+void GetHashSHA256(DWORD dataSize, PBYTE const data, PBYTE const Hash);
+void GetHmacKey(FILETIME* timestamp, PBYTE hmackey);
+void GetHmacSHA256(DWORD dwDataLen, PBYTE const pbData, PBYTE const pbHash);
+//--------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSClientLib.h b/include/KMSClientLib.h
new file mode 100644
index 0000000..c6b7358
--- /dev/null
+++ b/include/KMSClientLib.h
@@ -0,0 +1,6 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include "KMSClientLogic.h"
\ No newline at end of file
diff --git a/include/KMSClientLogic.h b/include/KMSClientLogic.h
new file mode 100644
index 0000000..f364ce8
--- /dev/null
+++ b/include/KMSClientLogic.h
@@ -0,0 +1,29 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include "CoreKMS.h"
+//---------------------------------------------------------------------------
+// Function Prototypes
+void LoadClientParameters(int argc, wchar_t *argv[], bool RunAsService);
+void StartKMSClient();
+PBYTE CreateRequest();
+void CreateRequestBase(REQUEST* const Request);
+PBYTE CreateRequestV4();
+PBYTE CreateRequestV5();
+PBYTE CreateRequestV6();
+void ReadResponseV4(RESPONSE_V4& Response_v4, int responseSize, PBYTE response);
+void ReadResponseV5(RESPONSE_V5& Response_v5, int responseSize, PBYTE response);
+void ReadResponseV6(RESPONSE_V6& Response_v5, int responseSize, PBYTE response);
+int SendRequest(PBYTE request, const int requestsSent, int* const requestsNeeded);
+void ClientValidateKMSPort(WCHAR* KMSPort);
+void ClientValidateKMSHost(WCHAR* KMSHost);
+void ClientValidateKMSClientMode(WCHAR* KMSClientMode);
+void ClientWriteLogInformation(WCHAR* const Message);
+void ClientWriteLogError(WCHAR* const Message);
+void ClientWriteLogErrorTerminate(WCHAR* const Message, int ExitCode);
+void ClientWriteEventLogEntry(DWORD dwIdentifier, WCHAR* const lpszMessage, WORD wType);
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSClientSettings.h b/include/KMSClientSettings.h
new file mode 100644
index 0000000..0a91684
--- /dev/null
+++ b/include/KMSClientSettings.h
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include "CoreKMS.h"
+//---------------------------------------------------------------------------
+// Class Prototypes
+
+// Contain all KMS Client Parameters and Settings.
+class KMSClientSettings
+{
+public:
+ // KMS Client Parameters
+ static WCHAR KMSHost[256];
+ static WCHAR KMSPort[PORT_BUFFER_SIZE];
+ static WCHAR KMSClientMode[256];
+
+ // KMS Client Identification Data
+ static DWORD RequiredClientCount;
+ static WORD KMSProtocolMajorVersion;
+ static WORD KMSProtocolMinorVersion;
+ static DWORD KMSClientLicenseStatus;
+ static WCHAR KMSClientAppID[GUID_BUFFER_SIZE];
+ static WCHAR KMSClientSkuID[GUID_BUFFER_SIZE];
+ static WCHAR KMSClientKMSCountedID[GUID_BUFFER_SIZE];
+
+ // KMS Client Program Control
+ static bool RunAsService;
+
+ // Set Default Settings
+ static void Initialize();
+};
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSHWID.h b/include/KMSHWID.h
new file mode 100644
index 0000000..b7efe3d
--- /dev/null
+++ b/include/KMSHWID.h
@@ -0,0 +1,14 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include
+#include
+#include "CoreKMS.h"
+
+// Function Prototypes
+void GetKMSHWID(PQWORD KMSHWID, REQUEST* const Request);
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSPID.h b/include/KMSPID.h
new file mode 100644
index 0000000..7037e7b
--- /dev/null
+++ b/include/KMSPID.h
@@ -0,0 +1,15 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include
+#include
+#include "CoreKMS.h"
+
+// Function Prototypes
+void CreateKMSPID(WCHAR* const KMSPID, REQUEST* const Request);
+void GetKMSPID(WCHAR* const KMSPID, REQUEST* const Request);
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSServer.h b/include/KMSServer.h
new file mode 100644
index 0000000..6a60e78
--- /dev/null
+++ b/include/KMSServer.h
@@ -0,0 +1,85 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.00.0595 */
+/* at Thu Oct 18 15:24:14 2012
+ */
+/* Compiler settings for KMSServer.idl:
+ Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0595
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of
+#endif // __RPCNDR_H_VERSION__
+
+
+#ifndef __KMSServer_h_h__
+#define __KMSServer_h_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#ifndef __KMSServer_INTERFACE_DEFINED__
+#define __KMSServer_INTERFACE_DEFINED__
+
+/* interface KMSServer */
+/* [version][uuid] */
+
+int ActivationRequest(
+ /* [in] */ handle_t IDL_handle,
+ /* [in] */ int requestSize,
+ /* [size_is][in] */ unsigned char *request,
+ /* [out] */ int *responseSize,
+ /* [size_is][size_is][out] */ unsigned char **response);
+
+int ActivationResponse(
+ /* [in] */ handle_t IDL_handle,
+ /* [in] */ int requestSize,
+ /* [size_is][in] */ unsigned char *request,
+ /* [out] */ int *responseSize,
+ /* [size_is][size_is][out] */ unsigned char **response);
+
+
+
+extern RPC_IF_HANDLE KMSServer_v1_0_c_ifspec;
+extern RPC_IF_HANDLE KMSServer_v1_0_s_ifspec;
+#endif /* __KMSServer_INTERFACE_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/include/KMSServerLib.h b/include/KMSServerLib.h
new file mode 100644
index 0000000..4baa962
--- /dev/null
+++ b/include/KMSServerLib.h
@@ -0,0 +1,6 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include "KMSServerLogic.h"
\ No newline at end of file
diff --git a/include/KMSServerLogic.h b/include/KMSServerLogic.h
new file mode 100644
index 0000000..8c8d8b9
--- /dev/null
+++ b/include/KMSServerLogic.h
@@ -0,0 +1,29 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include "CoreKMS.h"
+//---------------------------------------------------------------------------
+// Function Prototypes
+void LoadServerParameters(int argc, wchar_t* argv[], bool RunAsService);
+void StartKMSServer();
+void StopKMSServer();
+DWORD CreateResponseBase(REQUEST* const Request, PBYTE const Response);
+PBYTE CreateResponseV4(REQUEST_V4* const Request, int* const responseSize);
+PBYTE CreateResponseV5(REQUEST_V5* const Request, int* const responseSize);
+PBYTE CreateResponseV6(REQUEST_V6* const Request, int* const responseSize);
+void ServerValidateKMSPort(WCHAR* KMSPort);
+void ServerValidateKMSPID(WCHAR* KMSPID);
+void ServerValidateKMSHWID(WCHAR* KMSHWID);
+void ServerValidateVLActivationInterval(int VLActivationInterval);
+void ServerValidateVLRenewalInterval(int VLRenewalInterval);
+void ServerWriteLogInformation(WCHAR* const Message);
+void ServerWriteLogError(WCHAR* const Message);
+void ServerWriteLogErrorTerminate(WCHAR* const Message, int ExitCode);
+void ServerWriteEventLogEntry(DWORD dwIdentifier, WCHAR* const lpszMessage, WORD wType);
+void GetHmacKey(FILETIME* timestamp, PBYTE hmackey);
+void GetHmacSHA256(DWORD dwDataLen, PBYTE const pbData, PBYTE const pbHash);
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/include/KMSServerSettings.h b/include/KMSServerSettings.h
new file mode 100644
index 0000000..f1f9e8b
--- /dev/null
+++ b/include/KMSServerSettings.h
@@ -0,0 +1,34 @@
+//---------------------------------------------------------------------------
+// Header Guard
+#pragma once
+
+// Includes and Namespaces
+#include
+#include
+#include "CoreKMS.h"
+//---------------------------------------------------------------------------
+// Class Prototypes
+
+// Contains all KMS Server Parameters and Settings.
+class KMSServerSettings
+{
+public:
+ // KMS Server Parameters
+ static WCHAR KMSPID[PID_BUFFER_SIZE];
+ static QWORD KMSHWID;
+ static WCHAR KMSPort[PORT_BUFFER_SIZE];
+ static DWORD CurrentClientCount;
+ static DWORD VLActivationInterval;
+ static DWORD VLRenewalInterval;
+
+ // KMS Server Program Control
+ static bool GenerateRandomKMSPID;
+ static bool RunAsService;
+
+ // Process Termination Control Variables
+ static bool KillProcesses;
+
+ // Set Default Settings
+ static void Initialize();
+};
+//---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/source/Crypto.cpp b/source/Crypto.cpp
new file mode 100644
index 0000000..8cf4fe9
--- /dev/null
+++ b/source/Crypto.cpp
@@ -0,0 +1,918 @@
+// Includes and Namespaces
+#include "Crypto.h"
+
+// AES 128-bit key blob structure
+struct AES_128_KEYBLOB
+{
+ BLOBHEADER hdr;
+ DWORD dwKeySize;
+ BYTE rgbKeyData[16];
+};
+
+// Static AES Session Key
+static const AES_128_KEYBLOB keyBlob =
+{
+ // Type, Version, Algorithm
+ {PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, NULL, CALG_AES_128},
+ // Blocklength
+ 16,
+ // Key
+ {0xCD, 0x7E, 0x79, 0x6F, 0x2A, 0xB2, 0x5D, 0xCB, 0x55, 0xFF, 0xC8, 0xEF, 0x83, 0x64, 0xC4, 0x70}
+};
+
+// Default Type
+static DWORD Type=AES_TYPE_128;
+
+// Default Mode
+static DWORD Mode=AES_MODE_ECB;
+
+// Default Padding
+static BYTE Padding=0x00;
+
+// Static Key Pointer
+static PBYTE pKey=NULL;
+
+// Static IV Pointer
+static PBYTE pIV=NULL;
+
+// Init
+static bool IsInit=false;
+
+// Nb: Number of blocks, Nr: Number of rounds, Nk: Number of keys
+static DWORD Nb,Nr,Nk;
+
+// Static SubKeys Pointer
+static PDWORD pSubKeys=NULL;
+
+// RCon
+static BYTE Rcon[11]= {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36};
+
+#pragma region Tables
+
+// Substitution Table
+static BYTE SubTable[256]=
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+// Inverse Substitution Table
+static BYTE InvSubTable[256]=
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+#pragma endregion
+
+// WinApi: AES-128 CBC PKCS5-Padding Encryption
+void AESEncryptMessage(PBYTE const IV, PBYTE const Message, PDWORD const MessageSize, DWORD BufferLen)
+{
+ HCRYPTPROV hProv = NULL;
+ HCRYPTKEY hKey = NULL;
+
+ if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
+ return;
+
+ CryptImportKey(hProv, (PBYTE)&keyBlob, sizeof(keyBlob), NULL, NULL, &hKey);
+ CryptSetKeyParam(hKey, KP_IV, IV, NULL);
+ CryptEncrypt(hKey, NULL, true, NULL, Message, MessageSize, BufferLen);
+
+ if(hKey)
+ CryptDestroyKey(hKey);
+
+ if(hProv)
+ CryptReleaseContext(hProv, NULL);
+}
+
+// WinApi: AES-128 CBC PKCS5-Padding Decryption
+void AESDecryptMessage(PBYTE const IV, PBYTE const Message, PDWORD const MessageSize)
+{
+ HCRYPTPROV hProv = NULL;
+ HCRYPTKEY hKey = NULL;
+
+ if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
+ return;
+
+ CryptImportKey(hProv, (PBYTE)&keyBlob, sizeof(keyBlob), NULL, NULL, &hKey);
+ CryptSetKeyParam(hKey, KP_IV, IV, NULL);
+ CryptDecrypt(hKey, NULL, true, NULL, Message, MessageSize);
+
+ if(hKey)
+ CryptDestroyKey(hKey);
+
+ if(hProv)
+ CryptReleaseContext(hProv, NULL);
+}
+
+#pragma region Math
+
+// MUL x 2
+BYTE MULx2(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=(bIn<<1);
+
+ if ((bIn & 0x80) != 0x00)
+ bOut^=0x1B;
+
+ return bOut;
+};
+
+// MUL x 3
+BYTE MULx3(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx2(bIn)^bIn;
+
+ return bOut;
+};
+
+// MUL x 4
+BYTE MULx4(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx2(bIn);
+ bOut=MULx2(bOut);
+
+ return bOut;
+};
+
+// MUL x 8
+BYTE MULx8(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx2(bIn);
+ bOut=MULx2(bOut);
+ bOut=MULx2(bOut);
+
+ return bOut;
+};
+
+// MUL x 9
+BYTE MULx9(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx8(bIn)^bIn;
+
+ return bOut;
+};
+
+// MUL x B
+BYTE MULxB(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx8(bIn)^MULx2(bIn)^bIn;
+
+ return bOut;
+};
+
+// MUL x D
+BYTE MULxD(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx8(bIn)^MULx4(bIn)^bIn;
+
+ return bOut;
+};
+
+// MUL x E
+BYTE MULxE(BYTE bIn)
+{
+ BYTE bOut;
+ bOut=MULx8(bIn)^MULx4(bIn)^MULx2(bIn);
+ return bOut;
+};
+
+// SBOX
+BYTE SBox(BYTE bIn)
+{
+ return SubTable[bIn];
+};
+
+// Inverse SBOX
+BYTE InvSBox(BYTE bIn)
+{
+ return InvSubTable[bIn];
+};
+
+// Substitute Word
+DWORD SubWord(DWORD dwIn)
+{
+ DWORD dwOut;
+
+ (*((PBYTE)(&dwOut)))=SBox(*((PBYTE)(&dwIn)));
+ (*(((PBYTE)(&dwOut))+1))=SBox(*(((PBYTE)(&dwIn))+1));
+ (*(((PBYTE)(&dwOut))+2))=SBox(*(((PBYTE)(&dwIn))+2));
+ (*(((PBYTE)(&dwOut))+3))=SBox(*(((PBYTE)(&dwIn))+3));
+
+ return dwOut;
+};
+
+// Rotate Word
+DWORD RotWord(DWORD dwIn)
+{
+ DWORD dwOut;
+
+ (*((PBYTE)(&dwOut)))=(*(((PBYTE)(&dwIn))+1));
+ (*(((PBYTE)(&dwOut))+1))=(*(((PBYTE)(&dwIn))+2));
+ (*(((PBYTE)(&dwOut))+2))=(*(((PBYTE)(&dwIn))+3));
+ (*(((PBYTE)(&dwOut))+3))=(*((PBYTE)(&dwIn)));
+
+ return dwOut;
+};
+
+// Substitute Bytes
+void SubBytes(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ for(i=0 ; i<16 ; i++)
+ pBytes[i]=SBox(bIn[i]);
+};
+
+// Shift Rows
+void ShiftRows(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ pBytes[0]=bIn[0];
+ pBytes[1]=bIn[5];
+ pBytes[2]=bIn[10];
+ pBytes[3]=bIn[15];
+ pBytes[4]=bIn[4];
+ pBytes[5]=bIn[9];
+ pBytes[6]=bIn[14];
+ pBytes[7]=bIn[3];
+ pBytes[8]=bIn[8];
+ pBytes[9]=bIn[13];
+ pBytes[10]=bIn[2];
+ pBytes[11]=bIn[7];
+ pBytes[12]=bIn[12];
+ pBytes[13]=bIn[1];
+ pBytes[14]=bIn[6];
+ pBytes[15]=bIn[11];
+};
+
+// Mix Columns
+void MixColumns(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ pBytes[0] = MULx2(bIn[0]) ^ MULx3(bIn[1]) ^ bIn[2] ^ bIn[3];
+ pBytes[1] = bIn[0] ^ MULx2(bIn[1]) ^ MULx3(bIn[2]) ^ bIn[3];
+ pBytes[2] = bIn[0] ^ bIn[1] ^ MULx2(bIn[2]) ^ MULx3(bIn[3]);
+ pBytes[3] = MULx3(bIn[0]) ^ bIn[1] ^ bIn[2] ^ MULx2(bIn[3]);
+ pBytes[4] = MULx2(bIn[4]) ^ MULx3(bIn[5]) ^ bIn[6] ^ bIn[7];
+ pBytes[5] = bIn[4] ^ MULx2(bIn[5]) ^ MULx3(bIn[6]) ^ bIn[7];
+ pBytes[6] = bIn[4] ^ bIn[5] ^ MULx2(bIn[6]) ^ MULx3(bIn[7]);
+ pBytes[7] = MULx3(bIn[4]) ^ bIn[5] ^ bIn[6] ^ MULx2(bIn[7]);
+ pBytes[8] = MULx2(bIn[8]) ^ MULx3(bIn[9]) ^ bIn[10] ^ bIn[11];
+ pBytes[9] = bIn[8] ^ MULx2(bIn[9]) ^ MULx3(bIn[10]) ^ bIn[11];
+ pBytes[10] = bIn[8] ^ bIn[9] ^ MULx2(bIn[10]) ^ MULx3(bIn[11]);
+ pBytes[11] = MULx3(bIn[8]) ^ bIn[9] ^ bIn[10] ^ MULx2(bIn[11]);
+ pBytes[12] = MULx2(bIn[12]) ^ MULx3(bIn[13]) ^ bIn[14] ^ bIn[15];
+ pBytes[13] = bIn[12] ^ MULx2(bIn[13]) ^ MULx3(bIn[14]) ^ bIn[15];
+ pBytes[14] = bIn[12] ^ bIn[13] ^ MULx2(bIn[14]) ^ MULx3(bIn[15]);
+ pBytes[15] = MULx3(bIn[12]) ^ bIn[13] ^ bIn[14] ^ MULx2(bIn[15]);
+};
+
+// Add Round Key
+void AddRoundKey(PBYTE pState, DWORD Round)
+{
+ (*((PDWORD)pState)) ^= pSubKeys[4*Round];
+ (*(((PDWORD)pState)+1)) ^= pSubKeys[4*Round+1];
+ (*(((PDWORD)pState)+2)) ^= pSubKeys[4*Round+2];
+ (*(((PDWORD)pState)+3)) ^= pSubKeys[4*Round+3];
+};
+
+// Inverse Substitute Bytes
+void InvSubBytes(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ for(i=0 ; i<16 ; i++)
+ pBytes[i]=InvSBox(bIn[i]);
+};
+
+// Inverse Shift Rows
+void InvShiftRows(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ pBytes[0]=bIn[0];
+ pBytes[1]=bIn[13];
+ pBytes[2]=bIn[10];
+ pBytes[3]=bIn[7];
+ pBytes[4]=bIn[4];
+ pBytes[5]=bIn[1];
+ pBytes[6]=bIn[14];
+ pBytes[7]=bIn[11];
+ pBytes[8]=bIn[8];
+ pBytes[9]=bIn[5];
+ pBytes[10]=bIn[2];
+ pBytes[11]=bIn[15];
+ pBytes[12]=bIn[12];
+ pBytes[13]=bIn[9];
+ pBytes[14]=bIn[6];
+ pBytes[15]=bIn[3];
+};
+
+// Inverse Mix Columns
+void InvMixColumns(PBYTE pBytes)
+{
+ DWORD i;
+ BYTE bIn[16];
+
+ for(i=0 ; i<16 ; i++)
+ bIn[i]=pBytes[i];
+
+ pBytes[0] = MULxE(bIn[0]) ^ MULxB(bIn[1]) ^ MULxD(bIn[2]) ^ MULx9(bIn[3]);
+ pBytes[1] = MULx9(bIn[0]) ^ MULxE(bIn[1]) ^ MULxB(bIn[2]) ^ MULxD(bIn[3]);
+ pBytes[2] = MULxD(bIn[0]) ^ MULx9(bIn[1]) ^ MULxE(bIn[2]) ^ MULxB(bIn[3]);
+ pBytes[3] = MULxB(bIn[0]) ^ MULxD(bIn[1]) ^ MULx9(bIn[2]) ^ MULxE(bIn[3]);
+ pBytes[4] = MULxE(bIn[4]) ^ MULxB(bIn[5]) ^ MULxD(bIn[6]) ^ MULx9(bIn[7]);
+ pBytes[5] = MULx9(bIn[4]) ^ MULxE(bIn[5]) ^ MULxB(bIn[6]) ^ MULxD(bIn[7]);
+ pBytes[6] = MULxD(bIn[4]) ^ MULx9(bIn[5]) ^ MULxE(bIn[6]) ^ MULxB(bIn[7]);
+ pBytes[7] = MULxB(bIn[4]) ^ MULxD(bIn[5]) ^ MULx9(bIn[6]) ^ MULxE(bIn[7]);
+ pBytes[8] = MULxE(bIn[8]) ^ MULxB(bIn[9]) ^ MULxD(bIn[10]) ^ MULx9(bIn[11]);
+ pBytes[9] = MULx9(bIn[8]) ^ MULxE(bIn[9]) ^ MULxB(bIn[10]) ^ MULxD(bIn[11]);
+ pBytes[10] = MULxD(bIn[8]) ^ MULx9(bIn[9]) ^ MULxE(bIn[10]) ^ MULxB(bIn[11]);
+ pBytes[11] = MULxB(bIn[8]) ^ MULxD(bIn[9]) ^ MULx9(bIn[10]) ^ MULxE(bIn[11]);
+ pBytes[12] = MULxE(bIn[12]) ^ MULxB(bIn[13]) ^ MULxD(bIn[14]) ^ MULx9(bIn[15]);
+ pBytes[13] = MULx9(bIn[12]) ^ MULxE(bIn[13]) ^ MULxB(bIn[14]) ^ MULxD(bIn[15]);
+ pBytes[14] = MULxD(bIn[12]) ^ MULx9(bIn[13]) ^ MULxE(bIn[14]) ^ MULxB(bIn[15]);
+ pBytes[15] = MULxB(bIn[12]) ^ MULxD(bIn[13]) ^ MULx9(bIn[14]) ^ MULxE(bIn[15]);
+};
+
+// Key Expansion
+void KeyExpansion(void)
+{
+ DWORD i,Temp;
+
+ for(i=0 ; i6)&&((i-Nk*(i/Nk)) == 4))
+ Temp=SubWord(Temp);
+ };
+
+ pSubKeys[i]=((pSubKeys[i-Nk])^Temp);
+ };
+};
+
+// Do Cipher
+void DoCipher(PBYTE pIn, PBYTE pOut)
+{
+ BYTE State[16];
+ DWORD Round;
+ DWORD i;
+
+ for(i=0 ; i<16 ; i++)
+ State[i]=pIn[i];
+
+ AddRoundKey(State,0);
+
+ for(Round=1 ; Round0 ; Round--){
+ InvShiftRows(State);
+ InvSubBytes(State);
+ AddRoundKey(State,Round);
+
+ // KMS V6
+ if(Round == 4){
+ State[0] ^= 0x73;
+ }else if(Round == 6){
+ State[0] ^= 0x09;
+ }else if(Round == 8){
+ State[0] ^= 0xE4;
+ }
+
+ InvMixColumns(State);
+ };
+
+ InvShiftRows(State);
+ InvSubBytes(State);
+ AddRoundKey(State,0);
+
+ for(i=0 ; i<16 ; i++)
+ pOut[i]=State[i];
+};
+
+#pragma endregion
+
+#pragma region Initialization and Cleanup
+
+// AES Init
+DWORD AesInit(DWORD dwType, DWORD dwMode, BYTE bPadding, PBYTE pbKey, PBYTE pbIV)
+{
+ DWORD i,N;
+
+ if ((dwType != AES_TYPE_128) && (dwType != AES_TYPE_192) && (dwType != AES_TYPE_256))
+ return 1;
+ if ((dwMode != AES_MODE_ECB) && (dwMode != AES_MODE_CBC) && (dwMode != AES_MODE_CFB) && (dwMode != AES_MODE_OFB) && (dwMode != AES_MODE_CTR))
+ return 2;
+ if (pbKey == NULL)
+ return 3;
+ if (pbIV == NULL)
+ return 4;
+
+ if (pKey != NULL){
+ for(i=0 ; i<32 ; i++)
+ pKey[i]=0x00;
+ delete(pKey);
+ };
+
+ if (pIV != NULL){
+ for(i=0 ; i<16 ; i++)
+ pIV[i]=0x00;
+ delete(pIV);
+ };
+
+ Type=dwType;
+ Mode=dwMode;
+ Padding=bPadding;
+ pKey = new BYTE[32];
+ Nb=4;
+
+ switch(Type){
+ case AES_TYPE_128:
+ N=16;
+ Nr=10;
+ Nk=4;
+ break;
+ case AES_TYPE_192:
+ N=24;
+ Nr=12;
+ Nk=6;
+ break;
+ default:
+ N=32;
+ Nr=14;
+ Nk=8;
+ };
+
+ for(i=0 ; i 16)
+ return 1;
+
+ for(i=0 ; i> 4;
+
+ // Remainding Bytes
+ k = MessageSize & 0xf;
+
+ // Hash
+ for (i = 0; i < j; i++){
+ HashXorBuffer(&Message[i << 4], hash, 16);
+ Hash(hash);
+ }
+
+ // Bit Padding
+ hash[k] ^= 0x80;
+
+ HashXorBuffer(&Message[i << 4], hash, k);
+ Hash(hash);
+}
+
+// Generate SHA-256 Hash with Win32 Crypt API Provider
+void GetHashSHA256(DWORD dataSize, PBYTE const data, PBYTE const Hash)
+{
+ HCRYPTPROV hProv = NULL;
+ HCRYPTHASH hHash = NULL;
+ DWORD HashSize = HASH_SIZE_SHA256;
+
+ if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
+ return;
+
+ CryptCreateHash(hProv, CALG_SHA_256, NULL, NULL, &hHash);
+ CryptHashData(hHash, data, dataSize, NULL);
+ CryptGetHashParam(hHash, HP_HASHVAL, Hash, &HashSize, NULL);
+
+ if(hHash)
+ CryptDestroyHash(hHash);
+
+ if(hProv)
+ CryptReleaseContext(hProv, NULL);
+}
+
+// Generate time based HMAC key
+void GetHmacKey(FILETIME* timestamp, PBYTE hmackey)
+{
+ BYTE Sha256Hash[32];
+ QWORD t, c1, c2, c3, seed;
+
+ t = *(PQWORD)timestamp;
+ c1 = 0x00000022816889BD;
+ c2 = 0x000000208CBAB5ED;
+ c3 = 0x3156CD5AC628477A;
+ seed = ((t / c1) * c2) + c3;
+
+ GetHashSHA256(8, (PBYTE)&seed, Sha256Hash);
+ memcpy(hmackey, Sha256Hash+16, 16);
+}
+
+// Generate HMAC-SHA-256
+void GetHmacSHA256(DWORD dwDataLen, PBYTE const pbData, PBYTE const pbHash)
+{
+ HCRYPTPROV hProv = NULL;
+ HCRYPTKEY hKey = NULL;
+ HCRYPTHASH hHmacHash = NULL;
+ HMAC_INFO HmacInfo = {0};
+ DWORD dwHmacSize = 32;
+
+ HmacInfo.HashAlgid = CALG_SHA_256;
+
+ if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
+ return;
+
+ CryptImportKey(hProv, (PBYTE)&Hmac_keyblob, sizeof(HMAC_KEYBLOB), NULL, NULL, &hKey);
+ CryptCreateHash(hProv, CALG_HMAC, hKey, NULL, &hHmacHash);
+ CryptSetHashParam(hHmacHash, HP_HMAC_INFO, (PBYTE)&HmacInfo, NULL);
+ CryptHashData(hHmacHash, pbData, dwDataLen, NULL);
+ CryptGetHashParam(hHmacHash, HP_HASHVAL, pbHash, &dwHmacSize, NULL);
+
+ if(hKey)
+ CryptDestroyKey(hKey);
+
+ if(hHmacHash)
+ CryptDestroyHash(hHmacHash);
+
+ if(hProv)
+ CryptReleaseContext(hProv, NULL);
+}
\ No newline at end of file
diff --git a/source/KMSClientLogic.cpp b/source/KMSClientLogic.cpp
new file mode 100644
index 0000000..495660f
--- /dev/null
+++ b/source/KMSClientLogic.cpp
@@ -0,0 +1,834 @@
+// Includes and Namespaces
+#include
+#include
+#include
+#include
+#include "Crypto.h"
+#include "Hash.h"
+#include "KMSServer.h"
+#include "KMSClientLogic.h"
+#include "KMSClientSettings.h"
+using namespace std;
+
+// Link Libraries
+#pragma comment(lib, "rpcrt4.lib")
+
+// Hold KMS Client Settings
+KMSClientSettings ClientSettings;
+
+// Windows Service Parameters for Service Application
+SERVICE_STATUS ClientServiceStatus;
+SERVICE_STATUS_HANDLE ClientServiceHandle;
+
+#pragma region Application Initialization Functions
+// Load Application Parameters from Command-Line
+void LoadClientParameters(int argc, wchar_t *argv[], bool RunAsService)
+{
+ // Initialize KMS Client Settings Object
+ ClientSettings.Initialize();
+ ClientSettings.RunAsService = RunAsService;
+
+ #pragma region Command-Line
+ // Handle Command-Line Arguments (KMS Port or Help)
+ if (argc >= 2)
+ {
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, argv[1], -1, L"/?", -1) == CSTR_EQUAL)
+ {
+ printf("Usage:\n");
+ printf("[KMS Port] [KMS Host] [Client Mode]\n\n");
+
+ printf("KMS Port:\n");
+ printf("\tDefaultPort:\t\tUse the built-in KMS Port.\n");
+ printf("\tInteger:\t\tNumber from 1 to 65535.\n\n");
+
+ printf("KMS Host:\n");
+ printf("\tDefaultHost:\t\tUse the built-in KMS Host Address.\n");
+ printf("\tString:\t\t\tA DNS Name or IP Address.\n\n");
+
+ printf("Client Mode:\n");
+ printf("\tWindows:\t\tWindows Vista Enterprise KMS (V4) Client.\n");
+ printf("\tWindowsVista:\t\tWindows Vista Enterprise KMS (V4) Client.\n");
+ printf("\tWindows7:\t\tWindows 7 Enterprise KMS (V4) Client.\n");
+ printf("\tWindows8:\t\tWindows 8 Enterprise KMS (V5) Client.\n");
+ printf("\tWindows81:\t\tWindows 8 Enterprise KMS (V6) Client.\n");
+ printf("\tOffice2010:\t\tOffice 2010 Pro Plus KMS (V4) Client.\n");
+ printf("\tOffice2013:\t\tOffice 2013 Pro Plus KMS (V4) Client.\n");
+ printf("\tOffice2013V4:\t\tOffice 2013 Pro Plus KMS (V4) Client.\n");
+ printf("\tOffice2013V5:\t\tOffice 2013 Pro Plus KMS (V5) Client.\n\n");
+ printf("\tOffice2013V6:\t\tOffice 2013 Pro Plus KMS (V6) Client.\n\n");
+
+ printf("Example:\n");
+ printf("\tC:\\>\"KMS Client.exe\" 1688 127.0.0.2 Windows");
+ ClientWriteLogErrorTerminate(L"\n", -1);
+ }
+ else
+ {
+ ClientValidateKMSPort(argv[1]);
+ }
+ }
+
+ // Handle Command-Line Arguments (KMS Host)
+ if (argc >= 3)
+ {
+ ClientValidateKMSHost(argv[2]);
+ }
+
+ // Handle Command-Line Arguments (Client Mode)
+ if (argc >= 4)
+ {
+ ClientValidateKMSClientMode(argv[3]);
+ }
+
+ #pragma endregion
+}
+
+// Start RPC Connection and try to contact a KMS Server.
+void StartKMSClient()
+{
+ // RPC Parameters
+ RPC_STATUS status;
+ RPC_WSTR pszUuid = NULL;
+ RPC_WSTR pszProtocolSequence = (RPC_WSTR)L"ncacn_ip_tcp";
+ RPC_WSTR pszNetworkAddress = (RPC_WSTR)ClientSettings.KMSHost;
+ RPC_WSTR pszEndpoint = (RPC_WSTR)ClientSettings.KMSPort;
+ RPC_WSTR pszOptions = NULL;
+ RPC_WSTR pszStringBinding = NULL;
+
+ // Create String Binding
+ status = RpcStringBindingCompose
+ (
+ pszUuid,
+ pszProtocolSequence,
+ pszNetworkAddress,
+ pszEndpoint,
+ pszOptions,
+ &pszStringBinding
+ );
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcStringBindingCompose failed with code %i.\n", status);
+ ClientWriteLogErrorTerminate(Message, status);
+ }
+
+ // Get RPC Binding Handle from String Binding
+ status = RpcBindingFromStringBinding(pszStringBinding, &KMSServer_v1_0_c_ifspec);
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcBindingFromStringBinding failed with code %i.\n", status);
+ ClientWriteLogErrorTerminate(Message, status);
+ }
+
+ ClientWriteLogInformation(L"\nKMS Client Emulator started successfully.\n");
+
+ // Send Requests
+ int RequestsNeeded = ClientSettings.RequiredClientCount;
+ for (int requests = 0; requests < RequestsNeeded; requests++)
+ {
+ // Define the size of the request
+ int sizeRequest = 0;
+ if (ClientSettings.KMSProtocolMajorVersion == 4)
+ {
+ sizeRequest = sizeof(REQUEST_V4);
+ }
+ else if (ClientSettings.KMSProtocolMajorVersion == 5)
+ {
+ sizeRequest = sizeof(REQUEST_V5);
+ }
+ else
+ {
+ sizeRequest = sizeof(REQUEST_V6);
+ }
+
+ // Create KMS Client Request
+ PBYTE request = (PBYTE)midl_user_allocate(sizeRequest);
+ memcpy(request, (PBYTE)CreateRequest(), sizeRequest);
+
+ // Send KMS Client Request to KMS Server
+ status = SendRequest(request, requests, &RequestsNeeded);
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Activation request (KMS V%i.%i) %i of %i failed.\n", ClientSettings.KMSProtocolMajorVersion, ClientSettings.KMSProtocolMinorVersion, requests + 1, RequestsNeeded);
+ ClientWriteLogErrorTerminate(Message, status);
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Activation request (KMS V%i.%i) %i of %i sent.\n", ClientSettings.KMSProtocolMajorVersion, ClientSettings.KMSProtocolMinorVersion, requests + 1, RequestsNeeded);
+ ClientWriteLogInformation(Message);
+ }
+ }
+
+ // Free String Binding
+ status = RpcStringFree(&pszStringBinding);
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcStringFree failed with code %i.\n", status);
+ ClientWriteLogErrorTerminate(Message, status);
+ }
+
+ // Free RPC Binding
+ status = RpcBindingFree(&KMSServer_v1_0_c_ifspec);
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcBindingFree failed with code %i.\n", status);
+ ClientWriteLogErrorTerminate(Message, status);
+ }
+}
+#pragma endregion
+
+#pragma region KMS Client Request Generation Functions
+// Create KMS Client Request Data Based on KMS Client Protocol Version.
+PBYTE CreateRequest()
+{
+ // KMS Protocol Major Version
+ if (ClientSettings.KMSProtocolMajorVersion == 4)
+ {
+ return CreateRequestV4();
+ }
+ else if (ClientSettings.KMSProtocolMajorVersion == 5)
+ {
+ return CreateRequestV5();
+ }
+ else
+ {
+ return CreateRequestV6();
+ }
+}
+
+// Create Base KMS Client Request Object.
+void CreateRequestBase(REQUEST* const Request)
+{
+ // KMS Protocol Version
+ Request->MajorVer = ClientSettings.KMSProtocolMajorVersion;
+ Request->MinorVer = ClientSettings.KMSProtocolMinorVersion;
+
+ // KMS Client is NOT a VM
+ Request->IsClientVM = 0;
+
+ // License Status
+ Request->LicenseStatus = ClientSettings.KMSClientLicenseStatus;
+
+ // Grace Time
+ Request->GraceTime = 43200;
+
+ // Application ID
+ UuidFromStringW((RPC_WSTR)ClientSettings.KMSClientAppID, &Request->ApplicationId);
+
+ // SKU ID
+ UuidFromStringW((RPC_WSTR)ClientSettings.KMSClientSkuID, &Request->SkuId);
+
+ // KMS Counted ID
+ UuidFromStringW((RPC_WSTR)ClientSettings.KMSClientKMSCountedID, &Request->KmsCountedId);
+
+ // CMID
+ CoCreateGuid(&Request->ClientMachineId);
+
+ // Minimum Clients
+ Request->RequiredClientCount = ClientSettings.RequiredClientCount;
+
+ // Timestamp
+ GetSystemTimeAsFileTime(&Request->RequestTime);
+
+ // Machine Name
+ static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz";
+
+ // Seed Random Number Generator
+ srand(GetTickCount());
+
+ // Generate Random Machine Name (Up to 63 Characters)
+ int MachineNameLength = rand() % 63 + 1;
+ for (int i = 0; i < MachineNameLength; i++)
+ {
+ Request->MachineName[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
+ }
+ Request->MachineName[MachineNameLength] = 0;
+}
+
+// Create Hashed KMS Client Request Data for KMS Protocol Version 4.
+PBYTE CreateRequestV4()
+{
+ // Allocate KMS Client Request Buffer
+ PBYTE request = (PBYTE)midl_user_allocate(sizeof(REQUEST_V4));
+
+ // Clean buffer memory
+ memset(request, 0x00, sizeof(REQUEST_V4));
+
+ // Create KMS Client Request Base
+ CreateRequestBase((REQUEST*)request);
+
+ // Create Hash
+ GetHash(sizeof(REQUEST), request, request + sizeof(REQUEST));
+
+ // Return Request
+ return request;
+}
+
+// Create Encrypted KMS Client Request Data for KMS Protocol Version 5.
+PBYTE CreateRequestV5()
+{
+ // Allocate KMS Client Request Buffer
+ PBYTE request = (PBYTE)midl_user_allocate(sizeof(REQUEST_V5));
+
+ // Clean buffer memory
+ memset(request, 0x00, sizeof(REQUEST_V5));
+
+ // Temporary Pointer for access to REQUEST_V5 structure
+ REQUEST_V5 *requestptr = (REQUEST_V5 *)request;
+
+ // KMS Protocol Version
+ requestptr->MajorVer = ClientSettings.KMSProtocolMajorVersion;
+ requestptr->MinorVer = ClientSettings.KMSProtocolMinorVersion;
+
+ // Seed Random Number Generator
+ srand(GetTickCount());
+
+ // Generate a Random Salt Key
+ for(int i = 0; i < 16; i++)
+ {
+ requestptr->Salt[i] = rand() % 256;
+ }
+
+ // Set KMS Client Request Base
+ CreateRequestBase(&requestptr->RequestBase);
+
+ // Encrypted Size
+ DWORD EncryptedSize = sizeof(requestptr->RequestBase);
+
+ // AES-128 Encrypt
+ AESEncryptMessage(requestptr->Salt, (PBYTE)(&requestptr->RequestBase), &EncryptedSize, sizeof(requestptr->RequestBase) + sizeof(requestptr->Pad));
+
+ // Return Request
+ return request;
+}
+
+// Create Encrypted KMS Client Request Data for KMS Protocol Version 6.
+PBYTE CreateRequestV6()
+{
+ // V6: AES key
+ BYTE AES_V6_KEY[16] = {0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21};
+
+ // Allocate KMS Client Request Buffer
+ PBYTE request = (PBYTE)midl_user_allocate(sizeof(REQUEST_V6));
+
+ // Clean buffer memory
+ memset(request, 0x00, sizeof(REQUEST_V6));
+
+ // Temporary Pointer for access to REQUEST_V6 structure
+ REQUEST_V6 *requestptr = (REQUEST_V6 *)request;
+
+ // KMS Protocol Version
+ requestptr->MajorVer = ClientSettings.KMSProtocolMajorVersion;
+ requestptr->MinorVer = ClientSettings.KMSProtocolMinorVersion;
+
+ // Seed Random Number Generator
+ srand(GetTickCount());
+
+ // Generate a Random Salt Key
+ for(int i = 0; i < 16; i++)
+ {
+ requestptr->Salt[i] = rand() % 256;
+ }
+
+ // Set KMS Client Request Base
+ CreateRequestBase(&requestptr->RequestBase);
+
+ // Set Padding to 0x04
+ memset(&requestptr->Pad, 0x04, sizeof(&requestptr->Pad));
+
+ // Encrypted Size
+ DWORD EncryptedSize = sizeof(requestptr->RequestBase) + sizeof(requestptr->Pad);
+
+ AesInit(AES_TYPE_128, AES_MODE_CBC, 0x04, AES_V6_KEY, requestptr->Salt);
+ EncryptMessage(EncryptedSize, (PBYTE)(&requestptr->RequestBase));
+ AesClear();
+
+ // Return Request
+ return request;
+}
+
+// Read KMS Server Response V4 from Byte Array
+void ReadResponseV4(RESPONSE_V4& Response_v4, int responseSize, PBYTE response)
+{
+ int copySize =
+ sizeof(Response_v4.ResponseBase.Version) +
+ sizeof(Response_v4.ResponseBase.KMSPIDLength) +
+ (((RESPONSE_V4*)response)->ResponseBase.KMSPIDLength <= PID_BUFFER_SIZE << 1 ?
+ ((RESPONSE_V4*)response)->ResponseBase.KMSPIDLength :
+ PID_BUFFER_SIZE << 1);
+
+ memcpy(&Response_v4, response, copySize);
+ memcpy(&Response_v4.ResponseBase.ClientMachineId, response + copySize, responseSize - copySize);
+
+ // Ensure KMSPID is NULL Terminated
+ Response_v4.ResponseBase.KMSPID[PID_BUFFER_SIZE - 1] = 0;
+}
+
+// Read KMS Server Response V5 from Byte Array
+void ReadResponseV5(RESPONSE_V5& Response_v5, int responseSize, PBYTE response)
+{
+ // Get Size of the First Part of the Response
+ int copySize1 =
+ sizeof(Response_v5.Version) +
+ sizeof(Response_v5.RequestSalt);
+
+ // Decrypt KMS Server Response (Encrypted part starts after RequestSalt)
+ responseSize -= copySize1;
+ AESDecryptMessage(((RESPONSE_V5*)(response))->RequestSalt, response + copySize1, (DWORD*)&responseSize);
+
+ // Add Size of KMS Protocol Version, KMS PID Length and KMS PID (Variable Sized)
+ copySize1 +=
+ sizeof(Response_v5.ResponseBase.Version) +
+ sizeof(Response_v5.ResponseBase.KMSPIDLength) +
+ (((RESPONSE_V5*)response)->ResponseBase.KMSPIDLength <= PID_BUFFER_SIZE << 1 ?
+ ((RESPONSE_V5*)response)->ResponseBase.KMSPIDLength :
+ PID_BUFFER_SIZE << 1);
+
+ // Copy Part 1 of Response up to KMS PID (Variable Sized)
+ memcpy(&Response_v5, response, copySize1);
+
+ // Ensure KMSPID is NULL Terminated
+ Response_v5.ResponseBase.KMSPID[PID_BUFFER_SIZE - 1] = 0;
+
+ // Get Size of the Second Part of the Response
+ int copySize2 =
+ sizeof(Response_v5.ResponseBase.ClientMachineId) +
+ sizeof(Response_v5.ResponseBase.RequestTime) +
+ sizeof(Response_v5.ResponseBase.KMSCurrentCount) +
+ sizeof(Response_v5.ResponseBase.VLActivationInterval) +
+ sizeof(Response_v5.ResponseBase.VLRenewalInterval) +
+ sizeof(Response_v5.Salt) +
+ sizeof(Response_v5.Hash);
+
+ // Copy Part 2 of Response
+ memcpy(&Response_v5.ResponseBase.ClientMachineId, response + copySize1, copySize2);
+}
+
+// Read KMS Server Response V6 from Byte Array
+void ReadResponseV6(RESPONSE_V6& Response_v6, int responseSize, PBYTE response)
+{
+ // V6: AES key
+ BYTE AES_V6_KEY[16] = {0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21};
+
+ // Get Size of the First Part of the Response
+ int copySize =
+ sizeof(Response_v6.Version) +
+ sizeof(Response_v6.RequestSalt);
+
+ // Read the first part.
+ memcpy(&Response_v6, response, copySize);
+ response += copySize;
+ responseSize -= copySize;
+
+ // Decrypt the response.
+ AesInit(AES_TYPE_128, AES_MODE_CBC, 0x04, AES_V6_KEY, Response_v6.RequestSalt);
+ DecryptMessage(responseSize, response);
+ AesClear();
+
+ // Read version.
+ copySize = sizeof(Response_v6.ResponseBase.Version);
+ memcpy(&Response_v6.ResponseBase.Version, response, copySize);
+ response += copySize;
+ responseSize -= copySize;
+
+ // Read KMS PID length.
+ copySize = sizeof(Response_v6.ResponseBase.KMSPIDLength);
+ memcpy(&Response_v6.ResponseBase.KMSPIDLength, response, copySize);
+ response += copySize;
+ responseSize -= copySize;
+
+ // Read KMS PID.
+ copySize = Response_v6.ResponseBase.KMSPIDLength <= PID_BUFFER_SIZE << 1 ? Response_v6.ResponseBase.KMSPIDLength : PID_BUFFER_SIZE << 1;
+ memcpy(&Response_v6.ResponseBase.KMSPID, response, copySize);
+ response += copySize;
+ responseSize -= copySize;
+
+ // Ensure KMSPID is NULL Terminated
+ Response_v6.ResponseBase.KMSPID[PID_BUFFER_SIZE - 1] = 0;
+
+ // Read the rest into the structure.
+ memcpy(&Response_v6.ResponseBase.ClientMachineId, response, responseSize);
+}
+
+// Function to Send Request to KMS Server
+// Used to allow use of RpcTryExcept
+int SendRequest(PBYTE request, const int requestsSent, int* const requestsNeeded)
+{
+ RpcTryExcept
+ {
+ // Allocate Memory for Response
+ int responseSize = MAX_RESPONSE_SIZE;
+ PBYTE resp = (PBYTE)midl_user_allocate(MAX_RESPONSE_SIZE);
+
+ if (ClientSettings.KMSProtocolMajorVersion == 4)
+ {
+ // Call KMS Server via RPC for V4
+ ActivationRequest(KMSServer_v1_0_c_ifspec, sizeof(REQUEST_V4), request, &responseSize, &resp);
+ }
+ else if (ClientSettings.KMSProtocolMajorVersion == 5)
+ {
+ // Call KMS Server via RPC for V5
+ ActivationRequest(KMSServer_v1_0_c_ifspec, sizeof(REQUEST_V5), request, &responseSize, &resp);
+ }
+ else
+ {
+ // Call KMS Server via RPC for V6
+ ActivationRequest(KMSServer_v1_0_c_ifspec, sizeof(REQUEST_V6), request, &responseSize, &resp);
+ }
+
+ // Verify Response Was Received
+ if (resp == NULL)
+ {
+ ClientWriteLogErrorTerminate(L"Failed to get Activation response.\n", -1);
+ }
+
+ // Determine how many more requests are needed.
+ if (requestsSent < 1)
+ {
+ // Place to Store Base Response Data
+ RESPONSE response;
+
+ // KMSPID from Response
+ WCHAR* KMSPID = L"";
+
+ // KMSHWID from Response
+ WCHAR KMSHWID[256];
+
+ // ActivatedMachines from Response
+ DWORD ActivatedMachines;
+
+ if (ClientSettings.KMSProtocolMajorVersion == 4)
+ {
+ // Get KMS Server Response Object
+ RESPONSE_V4 response_v4;
+ ReadResponseV4(response_v4, responseSize, resp);
+
+ // Get Base KMS Server Response Object
+ response = response_v4.ResponseBase;
+
+ // Read KMSPID from Response
+ KMSPID = response.KMSPID;
+
+ // Read ActivatedMachines from Response
+ ActivatedMachines = response.KMSCurrentCount;
+ }
+ else if (ClientSettings.KMSProtocolMajorVersion == 5)
+ {
+ // Get KMS Server Response Object
+ RESPONSE_V5 response_v5;
+ ReadResponseV5(response_v5, responseSize, resp);
+
+ // Get Base KMS Server Response Object
+ response = response_v5.ResponseBase;
+
+ // Read KMSPID from Response
+ KMSPID = response.KMSPID;
+
+ // Read ActivatedMachines from Response
+ ActivatedMachines = response.KMSCurrentCount;
+ }
+ else
+ {
+ // Get KMS Server Response Object
+ RESPONSE_V6 response_v6;
+ ReadResponseV6(response_v6, responseSize, resp);
+
+ // Get Base KMS Server Response Object
+ response = response_v6.ResponseBase;
+
+ // Read KMSPID from Response
+ KMSPID = response.KMSPID;
+
+ // Read KMSHWID from Response
+ swprintf_s(KMSHWID, 256, L"%02X%02X%02X%02X%02X%02X%02X%02X", response_v6.MachineHardwareHash[7], response_v6.MachineHardwareHash[6], response_v6.MachineHardwareHash[5], response_v6.MachineHardwareHash[4], response_v6.MachineHardwareHash[3], response_v6.MachineHardwareHash[2], response_v6.MachineHardwareHash[1], response_v6.MachineHardwareHash[0]);
+
+ // Read ActivatedMachines from Response
+ ActivatedMachines = response.KMSCurrentCount;
+ }
+
+ ClientWriteLogInformation(L"Successfully received response from KMS Server.\n");
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Server PID: %s.\n", KMSPID);
+ ClientWriteLogInformation(Message);
+ if (ClientSettings.KMSProtocolMajorVersion > 5)
+ {
+ swprintf_s(Message, 256, L"KMS Server HWID: %s.\n", KMSHWID);
+ ClientWriteLogInformation(Message);
+ }
+
+ // Send no more requests if the client count was sufficient.
+ if (ActivatedMachines >= ClientSettings.RequiredClientCount)
+ {
+ *requestsNeeded = 1;
+ }
+ // Send as many requests as needed.
+ else
+ {
+ *requestsNeeded = (ClientSettings.RequiredClientCount - ActivatedMachines) + 1;
+ }
+ }
+ return 0;
+ }
+ RpcExcept(1)
+ {
+ // Get RPC Exception Code
+ unsigned long ulCode = RpcExceptionCode();
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
+ ClientWriteLogErrorTerminate(Message, ulCode);
+
+ // Return
+ return false;
+ }
+ RpcEndExcept
+}
+#pragma endregion
+
+#pragma region Parameter Validation Functions
+// Validate KMS Port Parameter
+void ClientValidateKMSPort(WCHAR* KMSPort)
+{
+ // Check if the KMS Port is not the Default
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSPort, -1, L"DefaultPort", -1) != CSTR_EQUAL)
+ {
+ // Check if KMS Port is Valid Number
+ if (regex_match(KMSPort, wregex(L"^([0-9]+)$")))
+ {
+ // Check if KMS Port is Valid Range
+ if(_wtoi(KMSPort) < 1 || _wtoi(KMSPort) > 65535)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Port Range! %s is not a valid argument.\n", KMSPort);
+ ClientWriteLogErrorTerminate(Message, -1);
+ }
+ else
+ {
+ // Apply Setting
+ StringCchCopyW(ClientSettings.KMSPort, PORT_BUFFER_SIZE, KMSPort);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Port: %s \n", KMSPort);
+ ClientWriteLogInformation(Message);
+ }
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Port! %s is not a valid argument.\n", KMSPort);
+ ClientWriteLogErrorTerminate(Message, -1);
+ }
+ }
+}
+
+// Validate KMS Host Parameter
+void ClientValidateKMSHost(WCHAR* KMSHost)
+{
+ // Check if the KMS PID is not the Default
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSHost, -1, L"DefaultHost", -1) != CSTR_EQUAL)
+ {
+ // Apply Setting
+ StringCchCopyW(ClientSettings.KMSHost, 256, KMSHost);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Host: %s \n", KMSHost);
+ ClientWriteLogInformation(Message);
+ }
+}
+
+// Validate KMS Client Mode
+void ClientValidateKMSClientMode(WCHAR* KMSClientMode)
+{
+ // Check if KMS Client Mode is Valid
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Windows", -1) == CSTR_EQUAL || CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"WindowsVista", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 25;
+ ClientSettings.KMSProtocolMajorVersion = 4;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"55c92734-d682-4d71-983e-d6ec3f16059f");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"cfd8ff08-c0d7-452b-9f60-ef5c70c32094");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"212a64dc-43b1-4d3d-a30c-2fc69d2095c6");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Windows7", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 25;
+ ClientSettings.KMSProtocolMajorVersion = 4;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"55c92734-d682-4d71-983e-d6ec3f16059f");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"ae2ee509-1b34-41c0-acb7-6d4650168915");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"7fde5219-fbfa-484a-82c9-34d1ad53e856");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Windows8", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 25;
+ ClientSettings.KMSProtocolMajorVersion = 5;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"55c92734-d682-4d71-983e-d6ec3f16059f");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"458e1bec-837a-45f6-b9d5-925ed5d299de");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"3c40b358-5948-45af-923b-53d21fcc7e79");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Windows81", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 25;
+ ClientSettings.KMSProtocolMajorVersion = 6;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"55c92734-d682-4d71-983e-d6ec3f16059f");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"81671aaf-79d1-4eb1-b004-8cbbe173afea");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"cb8fc780-2c05-495a-9710-85afffc904d7");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Office2010", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 5;
+ ClientSettings.KMSProtocolMajorVersion = 4;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"59a52881-a989-479d-af46-f275c6370663");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"6f327760-8c5c-417c-9b61-836a98287e0c");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"e85af946-2e25-47b7-83e1-bebcebeac611");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Office2013", -1) == CSTR_EQUAL ||
+ CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Office2013V4", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 5;
+ ClientSettings.KMSProtocolMajorVersion = 4;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"0ff1ce15-a989-479d-af46-f275c6370663");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"b322da9c-a2e2-4058-9e4e-f59a6970bd69");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Office2013V5", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 5;
+ ClientSettings.KMSProtocolMajorVersion = 5;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"0ff1ce15-a989-479d-af46-f275c6370663");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"b322da9c-a2e2-4058-9e4e-f59a6970bd69");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0");
+ }
+ else if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSClientMode, -1, L"Office2013V6", -1) == CSTR_EQUAL)
+ {
+ ClientSettings.RequiredClientCount = 5;
+ ClientSettings.KMSProtocolMajorVersion = 6;
+ StringCchCopyW(ClientSettings.KMSClientAppID, GUID_BUFFER_SIZE, L"0ff1ce15-a989-479d-af46-f275c6370663");
+ StringCchCopyW(ClientSettings.KMSClientSkuID, GUID_BUFFER_SIZE, L"b322da9c-a2e2-4058-9e4e-f59a6970bd69");
+ StringCchCopyW(ClientSettings.KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0");
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Client Type! %s is not a valid argument.\n", KMSClientMode);
+ ClientWriteLogErrorTerminate(Message, -1);
+ }
+
+ // Apply Setting
+ StringCchCopyW(ClientSettings.KMSClientMode, 256, KMSClientMode);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Client Mode: %s \n", KMSClientMode);
+ ClientWriteLogInformation(Message);
+}
+#pragma endregion
+
+#pragma region Logging Functions
+// Log an informational message to the Console or Windows Application Event Log.
+void ClientWriteLogInformation(WCHAR* const Message)
+{
+ // Log Message Buffer
+ WCHAR logMessage[256];
+
+ // Write Log Message to Buffer
+ StringCbPrintfW(logMessage, 256, Message);
+
+ // Choose Log Source
+ if (ClientSettings.RunAsService)
+ {
+ // Output to Windows Event Log: Qualifiers: 16384, EventId: 12290
+ ClientWriteEventLogEntry(0x40003002, logMessage, EVENTLOG_INFORMATION_TYPE);
+ }
+ else
+ {
+ // Output to Console
+ wprintf(L"%s", logMessage);
+ }
+}
+
+// Log an error message to the Console or Windows Application Event Log.
+void ClientWriteLogError(WCHAR* const Message)
+{
+ // Log Message Buffer
+ WCHAR logMessage[256];
+
+ // Write Log Message to Buffer
+ StringCbPrintfW(logMessage, 256, Message);
+
+ // Choose Log Source
+ if (ClientSettings.RunAsService)
+ {
+ // Output to Windows Event Log: Qualifiers: 16384, EventId: 902
+ ClientWriteEventLogEntry(0x40000386, logMessage, EVENTLOG_ERROR_TYPE);
+ }
+ else
+ {
+ // Output to Console
+ wprintf(L"%s", logMessage);
+ }
+}
+
+// Log an error message to the Console or Windows Application Event Log and terminate program.
+void ClientWriteLogErrorTerminate(WCHAR* const Message, int ExitCode)
+{
+ // Call ClientWriteLogError
+ ClientWriteLogError(Message);
+
+ if (!ClientSettings.RunAsService)
+ {
+ // Exit Program
+ exit(ExitCode);
+ }
+ else
+ {
+ // Exit Service
+ ClientServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ ClientServiceStatus.dwWin32ExitCode = ExitCode;
+ SetServiceStatus(ClientServiceHandle, &ClientServiceStatus);
+ }
+}
+
+// Log a message to the Windows Application Event Log.
+void ClientWriteEventLogEntry(DWORD dwIdentifier, WCHAR* const lpszMessage, WORD wType)
+{
+ HANDLE hEventSource = OpenEventLogW(NULL, L"KmsRequests"); // Provider: KmsRequests or Microsoft-Windows-Security-SPP
+
+ if(hEventSource != NULL)
+ {
+ ReportEventW(
+ hEventSource, // Event log handle
+ wType, // Event type
+ NULL, // Event category
+ dwIdentifier, // Event identifier
+ NULL, // No security identifier
+ 1, // Size of lpszStrings array
+ NULL, // No binary data
+ (LPCWSTR*)&lpszMessage, // Array of strings
+ NULL // No binary data
+ );
+
+ CloseEventLog(hEventSource);
+ }
+}
+#pragma endregion
\ No newline at end of file
diff --git a/source/KMSClientSettings.cpp b/source/KMSClientSettings.cpp
new file mode 100644
index 0000000..0b8cf8d
--- /dev/null
+++ b/source/KMSClientSettings.cpp
@@ -0,0 +1,35 @@
+// Includes and Namespaces
+#include "KMSClientSettings.h"
+
+// KMS Client Parameters
+WCHAR KMSClientSettings::KMSHost[256];
+WCHAR KMSClientSettings::KMSPort[PORT_BUFFER_SIZE];
+WCHAR KMSClientSettings::KMSClientMode[256];
+
+// KMS Client Identification Data
+DWORD KMSClientSettings::RequiredClientCount;
+WORD KMSClientSettings::KMSProtocolMajorVersion;
+WORD KMSClientSettings::KMSProtocolMinorVersion;
+DWORD KMSClientSettings::KMSClientLicenseStatus;
+WCHAR KMSClientSettings::KMSClientAppID[GUID_BUFFER_SIZE];
+WCHAR KMSClientSettings::KMSClientSkuID[GUID_BUFFER_SIZE];
+WCHAR KMSClientSettings::KMSClientKMSCountedID[GUID_BUFFER_SIZE];
+
+// KMS Client Program Control
+bool KMSClientSettings::RunAsService;
+
+// Set Default Settings
+void KMSClientSettings::Initialize()
+{
+ StringCchCopyW(KMSHost, 256, L"127.0.0.2");
+ StringCchCopyW(KMSPort, PORT_BUFFER_SIZE, L"1688");
+ StringCchCopyW(KMSClientMode, 256, L"Windows");
+ RequiredClientCount = 25;
+ KMSProtocolMajorVersion = 4;
+ KMSProtocolMinorVersion = 0;
+ KMSClientLicenseStatus = 2;
+ StringCchCopyW(KMSClientAppID, GUID_BUFFER_SIZE, L"55c92734-d682-4d71-983e-d6ec3f16059f");
+ StringCchCopyW(KMSClientSkuID, GUID_BUFFER_SIZE, L"cfd8ff08-c0d7-452b-9f60-ef5c70c32094");
+ StringCchCopyW(KMSClientKMSCountedID, GUID_BUFFER_SIZE, L"212a64dc-43b1-4d3d-a30c-2fc69d2095c6");
+ RunAsService = false;
+};
\ No newline at end of file
diff --git a/source/KMSHWID.cpp b/source/KMSHWID.cpp
new file mode 100644
index 0000000..b985da3
--- /dev/null
+++ b/source/KMSHWID.cpp
@@ -0,0 +1,40 @@
+// Includes and Namespaces
+#include "KMSHWID.h"
+using namespace std;
+
+// Get Application Specific KMSHWID from the Registry (KMS Server Service Only)
+void GetKMSHWID(PQWORD KMSHWID, REQUEST* const Request)
+{
+ // Open Registry Key
+ HKEY hKey;
+ DWORD bufferSize = 256;
+ WCHAR buffer[256] = {0};
+
+ // Get ClientAppID as String
+ WCHAR ClientAppID[GUID_BUFFER_SIZE];
+ StringCchPrintfW(ClientAppID, GUID_BUFFER_SIZE, L"%08X-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X", Request->ApplicationId.Data1, Request->ApplicationId.Data2, Request->ApplicationId.Data3, Request->ApplicationId.Data4[0], Request->ApplicationId.Data4[1], Request->ApplicationId.Data4[2], Request->ApplicationId.Data4[3], Request->ApplicationId.Data4[4], Request->ApplicationId.Data4[5], Request->ApplicationId.Data4[6], Request->ApplicationId.Data4[7]);
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\KMSServerService\\Parameters\\KMSHWID"), NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ // Get Registry Value
+ if (RegQueryValueExW(hKey, ClientAppID, NULL, NULL, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS)
+ {
+ if (regex_match(buffer, wregex(L"^[a-fA-F0-9]{16}$")))
+ {
+ // Close Registry Key
+ RegCloseKey(hKey);
+
+ // Apply Setting
+ *KMSHWID = wcstoull(buffer, NULL, 16);
+ }
+ }
+
+ // Close Registry Key
+ RegCloseKey(hKey);
+ }
+ else
+ {
+ // Return NULL KMSHWID
+ *KMSHWID = 0x0;
+ }
+}
\ No newline at end of file
diff --git a/source/KMSPID.cpp b/source/KMSPID.cpp
new file mode 100644
index 0000000..b72a7a6
--- /dev/null
+++ b/source/KMSPID.cpp
@@ -0,0 +1,176 @@
+// Includes and Namespaces
+#include "KMSPID.h"
+
+#pragma region Structs
+
+// HostType and OSBuild
+static const struct KMSHostOS { WORD Type; WORD Build; } HostOS[] =
+{
+ { 55041, 7601 }, // Windows Server 2008 R2 SP1
+ { 5426, 9200 }, // Windows Server 2012
+ { 6401, 9600 }, // Windows Server 2012 R2
+};
+
+// GroupID and PIDRange
+static const struct PKEYCONFIG { WORD GroupID; DWORD RangeMin; DWORD RangeMax; } pkeyconfig[] = {
+ { 206, 152000000, 152999999 }, // Windows Server 2012 KMS Host pkeyconfig, actual max is 191999999
+ { 206, 271000000, 271999999 }, // Windows Server 2012 R2 KMS Host pkeyconfig, actual max is 310999999
+ { 96, 199000000, 201999999 }, // Office2010 KMS Host pkeyconfig, actual max is 217999999
+ { 206, 234000000, 234999999 }, // Office2013 KMS Host pkeyconfig, actual max is 255999999
+};
+
+#pragma endregion
+
+#pragma region Defines
+
+// Defines
+static const GUID APP_ID_WINDOWS = {0x55C92734, 0xD682, 0x4D71, {0x98, 0x3E, 0xD6, 0xEC, 0x3F, 0x16, 0x05, 0x9F}};
+static const GUID APP_ID_OFFICE14 = {0x59A52881, 0xA989, 0x479D, {0xAF, 0x46, 0xF2, 0x75, 0xC6, 0x37, 0x06, 0x63}};
+static const GUID APP_ID_OFFICE15 = {0x0FF1CE15, 0xA989, 0x479D, {0xAF, 0x46, 0xF2, 0x75, 0xC6, 0x37, 0x06, 0x63}};
+
+#define HOST_SERVER2008R2 0
+#define HOST_SERVER2012 1
+#define HOST_SERVER2012R2 2
+
+#define PKEYCONFIG_SERVER2012_CSVLK 0
+#define PKEYCONFIG_SERVER2012R2_CSVLK 1
+#define PKEYCONFIG_OFFICE2010_CSVLK 2
+#define PKEYCONFIG_OFFICE2013_CSVLK 3
+
+// Minimum possible activation date for each Microsoft products (in UTC seconds)
+#define MinDateServer2008R2 ((time_t)1297875600LL) // Available on February 16, 2011 through TechNet or MSDN
+#define MinDateServer2012 ((time_t)1346778000LL) // Available on September 4, 2012 through TechNet or MSDN
+#define MinDateOffice2013 ((time_t)1351098000LL) // Available on October 24, 2012 through TechNet or MSDN
+#define MinDateServer2012R2 ((time_t)1382029200LL) // Available on October 17, 2013 through TechNet or MSDN
+
+// Macros
+#define countof( array ) ( sizeof( array )/sizeof( array[0] ) )
+
+#pragma endregion
+
+using namespace std;
+
+// Get GroupID and PIDRange for the specified AppID and KMS Protocol Version
+static const PKEYCONFIG *GetKMSHostPkeyConfig(REQUEST* const Request)
+{
+ if (Request->ApplicationId == APP_ID_WINDOWS)
+ return (Request->MajorVer == 6 ? &pkeyconfig[PKEYCONFIG_SERVER2012R2_CSVLK] : &pkeyconfig[PKEYCONFIG_SERVER2012_CSVLK]);
+
+ if (Request->ApplicationId == APP_ID_OFFICE15)
+ return &pkeyconfig[PKEYCONFIG_OFFICE2013_CSVLK];
+
+ if (Request->ApplicationId == APP_ID_OFFICE14)
+ return &pkeyconfig[PKEYCONFIG_OFFICE2010_CSVLK];
+
+ return &pkeyconfig[PKEYCONFIG_SERVER2012_CSVLK];
+}
+
+// Calculate Minimum Possible Date of KMS Host
+static const time_t GetMinKMSHostBuildDate(int HostIndex, REQUEST* const Request)
+{
+ // Request is KMS V6 or Server 2012 R2 Build # is used
+ if (Request->MajorVer == 6 || HostIndex == HOST_SERVER2012R2)
+ return MinDateServer2012R2;
+
+ // Request is Office 2013 (Both V4 and V5)
+ if (Request->ApplicationId == APP_ID_OFFICE15)
+ return MinDateOffice2013;
+
+ // Request is KMS V5 or Server 2012 Build # is used
+ if (Request->MajorVer == 5 || HostIndex == HOST_SERVER2012)
+ return MinDateServer2012;
+
+ // Otherwise, Request is KMS V4 (Office 2010/Vista/7) and Server 2008 R2 Build # is used
+ return MinDateServer2008R2;
+}
+
+// Random Number Generator
+BOOL GetRandomBytes(BYTE *RandomBuffer, DWORD RandomBufferLength)
+{
+ BOOL success = FALSE;
+ HCRYPTPROV hProv = NULL;
+
+ success = CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT) &&
+ CryptGenRandom(hProv, RandomBufferLength, RandomBuffer);
+
+ if (hProv)
+ CryptReleaseContext(hProv, 0);
+
+ return success;
+}
+
+void CreateKMSPID(WCHAR* const KMSPID, REQUEST* const Request)
+{
+ // Random Number Buffer
+ DWORD RandomNumber[4];
+ GetRandomBytes((BYTE *)RandomNumber, sizeof(RandomNumber));
+
+ // Choose KMS HostOS
+ int HostIndex = RandomNumber[0] % countof(HostOS);
+ const KMSHostOS *host = &HostOS[HostIndex];
+
+ // Set Product Specific Base pkeyconfig (use Windows if unknown product)
+ const PKEYCONFIG *config = GetKMSHostPkeyConfig(Request);
+
+ // Generate Random ID
+ int RandomID = config->RangeMin + RandomNumber[1] % (config->RangeMax - config->RangeMin);
+
+ // Generate Part 5: License Channel (00=Retail, 01=Retail, 02=OEM, 03=Volume(GVLK,MAK)) - always 03
+ DWORD LicenseChannel = 3;
+
+ // Generate Part 6: Language - use system default language
+ DWORD LanguageCode = GetSystemDefaultLCID();
+
+ // Get Product Specific Minimum Activation Date
+ time_t MinDate = GetMinKMSHostBuildDate(HostIndex, Request);
+
+ // Get Maximum Possible Value of Activation Date
+ time_t MaxDate = time(NULL) - 86400; // limit latest activation date to yesterday
+
+ // Generate Random Date between MinDate and MaxDate
+ time_t RandomDate = ((ULONG64 *)RandomNumber)[1] & 0x7FFFFFFFFFFFFFFFULL;
+ time_t GeneratedDate = MinDate + RandomDate % (MaxDate - MinDate);
+ struct tm Date;
+ localtime_s(&Date, &GeneratedDate);
+
+ StringCchPrintfW(KMSPID, PID_BUFFER_SIZE, L"%05u-%05u-%03u-%06u-%02u-%u-%04u.0000-%03d%04d",
+ host->Type, config->GroupID, RandomID / 1000000, RandomID % 1000000, LicenseChannel,
+ LanguageCode, host->Build, Date.tm_yday+1, Date.tm_year+1900);
+}
+
+// Get Application Specific KMS PID from the Registry (KMS Server Service Only)
+void GetKMSPID(WCHAR* const KMSPID, REQUEST* const Request)
+{
+ // Open Registry Key
+ HKEY hKey;
+ DWORD bufferSize = 256;
+ WCHAR buffer[256] = {0};
+
+ // Get ClientAppID as String
+ WCHAR ClientAppID[GUID_BUFFER_SIZE];
+ StringCchPrintfW(ClientAppID, GUID_BUFFER_SIZE, L"%08X-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X", Request->ApplicationId.Data1, Request->ApplicationId.Data2, Request->ApplicationId.Data3, Request->ApplicationId.Data4[0], Request->ApplicationId.Data4[1], Request->ApplicationId.Data4[2], Request->ApplicationId.Data4[3], Request->ApplicationId.Data4[4], Request->ApplicationId.Data4[5], Request->ApplicationId.Data4[6], Request->ApplicationId.Data4[7]);
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\KMSServerService\\Parameters\\KMSPID"), NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ // Get Registry Value
+ if (RegQueryValueExW(hKey, ClientAppID, NULL, NULL, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS)
+ {
+ if (regex_match(buffer, wregex(L"^([0-9]{5})-([0-9]{5})-([0-9]{3})-([0-9]{6})-([0-9]{2})-([0-9]{4,5})-([0-9]{4}).([0-9]{4})-([0-9]{7})$")))
+ {
+ // Close Registry Key
+ RegCloseKey(hKey);
+
+ // Apply Setting
+ StringCchCopyW(KMSPID, PID_BUFFER_SIZE, buffer);
+ }
+ }
+
+ // Close Registry Key
+ RegCloseKey(hKey);
+ }
+ else
+ {
+ // Return Empty KMSPID
+ StringCchCopyW(KMSPID, PID_BUFFER_SIZE, L"");
+ }
+}
\ No newline at end of file
diff --git a/source/KMSServer.idl b/source/KMSServer.idl
new file mode 100644
index 0000000..58153fa
--- /dev/null
+++ b/source/KMSServer.idl
@@ -0,0 +1,14 @@
+[
+ uuid(51C82175-844E-4750-B0D8-EC255555BC06),
+ version(1.0),
+]
+interface KMSServer
+{
+ int RequestActivation
+ (
+ [in] int requestSize,
+ [in, size_is(requestSize)] unsigned char* request,
+ [out] int* responseSize,
+ [out, size_is( , *responseSize)] unsigned char** response
+ );
+}
\ No newline at end of file
diff --git a/source/KMSServerLogic.cpp b/source/KMSServerLogic.cpp
new file mode 100644
index 0000000..0f38ce8
--- /dev/null
+++ b/source/KMSServerLogic.cpp
@@ -0,0 +1,949 @@
+// Includes and Namespaces
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Crypto.h"
+#include "Hash.h"
+#include "KMSPID.h"
+#include "KMSHWID.h"
+#include "KMSServer.h"
+#include "KMSServerLogic.h"
+#include "KMSServerSettings.h"
+using namespace std;
+
+// Link Libraries
+#pragma comment(lib, "rpcrt4.lib")
+#pragma comment(lib, "iphlpapi.lib")
+#pragma comment(lib, "ws2_32.lib")
+
+// Hold KMS Server Settings
+KMSServerSettings ServerSettings;
+
+// Windows Service Parameters for Service Application
+SERVICE_STATUS ServerServiceStatus;
+SERVICE_STATUS_HANDLE ServerServiceHandle;
+
+// Defined in Hash.cpp
+extern HMAC_KEYBLOB Hmac_keyblob;
+
+#pragma region Application Initialization Functions
+// Load Application Parameters from Command-Line or Registry.
+void LoadServerParameters(int argc, wchar_t* argv[], bool RunAsService)
+{
+ // Initialize KMS Server Settings Object
+ ServerSettings.Initialize();
+ ServerSettings.RunAsService = RunAsService;
+
+ if (!RunAsService)
+ {
+ #pragma region Command-Line
+ // Handle Command-Line Arguments (KMS Port or Help)
+ if (argc >= 2)
+ {
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, argv[1], -1, L"/?", -1) == CSTR_EQUAL)
+ {
+ printf("Usage:\n");
+ printf("[KMS Port] [KMS PID] [KMS HWID] [Activation Interval] [Renewal Interval] [Kill Processes]\n\n");
+
+ printf("KMS Port:\n");
+ printf("\tDefaultPort:\t\tUse the built-in KMS Port.\n");
+ printf("\tInteger:\t\tNumber from 1 to 65535.\n\n");
+
+ printf("KMS PID:\n");
+ printf("\tRandomKMSPID:\t\tGenerate a random KMS PID.\n");
+ printf("\tString:\t\t\tA Microsoft Extended Product Key ID.\n\n");
+
+ printf("KMS HWID:\n");
+ printf("\tDefaultKMSHWID:\t\tUse the built-in KMS HWID.\n");
+ printf("\tString:\t\t\t16 Hex character KMS HWID (No 0x).\n\n");
+
+ printf("Activation Interval:\n");
+ printf("\tDefaultAI:\t\tUse the built-in Activation Interval.\n");
+ printf("\tInteger:\t\tNumber (in minutes) from 15 to 43200.\n\n");
+
+ printf("Renewal Interval:\n");
+ printf("\tDefaultRI:\t\tUse the built-in Renewal Interval.\n");
+ printf("\tInteger:\t\tNumber (in minutes) from 15 to 43200.\n\n");
+
+ printf("Kill Processes:\n");
+ printf("\tKillProcessOnPort:\tForce open the KMS Port if this is present.\n\n");
+
+ printf("Example:\n");
+ printf("\tC:\\>\"KMS Server.exe\" 1688 RandomKMSPID DefaultKMSHWID 43200 43200 KillProcessOnPort");
+ ServerWriteLogErrorTerminate(L"\n", -1);
+ }
+ else
+ {
+ ServerValidateKMSPort(argv[1]);
+ }
+ }
+
+ // Handle Command-Line Arguments (KMS PID)
+ if (argc >= 3)
+ {
+ ServerValidateKMSPID(argv[2]);
+ }
+
+ // Handle Command-Line Arguments (KMS HWID)
+ if (argc >= 4)
+ {
+ ServerValidateKMSHWID(argv[3]);
+ }
+
+ // Handle Command-Line Arguments (Activation Interval)
+ if (argc >= 5)
+ {
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, argv[4], -1, L"DefaultAI", -1) != CSTR_EQUAL)
+ {
+ // Check if Activation Interval is Valid Number
+ if (regex_match(argv[4], wregex(L"^([0-9]+)$")))
+ {
+ ServerValidateVLActivationInterval(_wtoi(argv[4]));
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Activation Interval! %s is not a valid argument.\n", argv[4]);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ }
+ }
+
+ // Handle Command-Line Arguments (Renewal Interval)
+ if (argc >= 6)
+ {
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, argv[5], -1, L"DefaultRI", -1) != CSTR_EQUAL)
+ {
+ // Check if Renewal Interval is Valid Number
+ if (regex_match(argv[5], wregex(L"^([0-9]+)$")))
+ {
+ ServerValidateVLRenewalInterval(_wtoi(argv[5]));
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Renewal Interval! %s is not a valid argument.\n", argv[5]);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ }
+ }
+
+ // Handle Command-Line Arguments (Free TCP/IP)
+ if (argc >= 7)
+ {
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, argv[6], -1, L"KillProcessOnPort", -1) == CSTR_EQUAL)
+ {
+ // Apply Setting
+ ServerSettings.KillProcesses = true;
+ ServerWriteLogInformation(L"KMS Port Process Termination: Enabled \n");
+ }
+ else
+ {
+ // Apply Setting
+ ServerSettings.KillProcesses = false;
+ ServerWriteLogInformation(L"KMS Port Process Termination: Disabled \n");
+ }
+ }
+ #pragma endregion
+ }
+ else
+ {
+ #pragma region Registry
+ // Create Buffers for Values
+ WCHAR KMSPID[256] = {0};
+ WCHAR KMSHWID[256] = {0};
+ WCHAR KMSPort[256] = {0};
+ DWORD VLActivationInterval = 0;
+ DWORD VLRenewalInterval = 0;
+ DWORD KillProcesses = 0;
+
+ // Open Registry Key
+ HKEY hKey;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\KMSServerService\\Parameters", NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ // Buffer Size
+ DWORD bufferSize = 0;
+
+ // Handle Registry Parameters (KMS PID)
+ bufferSize = 256;
+ RegQueryValueExW(hKey, L"KMSPID", NULL, NULL, (LPBYTE)KMSPID, &bufferSize);
+
+ // Handle Registry Parameters (KMS HWID)
+ bufferSize = 256;
+ RegQueryValueExW(hKey, L"KMSHWID", NULL, NULL, (LPBYTE)KMSHWID, &bufferSize);
+
+ // Handle Registry Parameters (KMS Port)
+ bufferSize = 256;
+ RegQueryValueExW(hKey, L"KMSPort", NULL, NULL, (LPBYTE)KMSPort, &bufferSize);
+
+ // Handle Registry Parameters (Activation Interval)
+ bufferSize = sizeof(DWORD);
+ RegQueryValueExW(hKey, L"VLActivationInterval", NULL, NULL, (LPBYTE)&VLActivationInterval, &bufferSize);
+
+ // Handle Registry Parameters (Renewal Interval)
+ bufferSize = sizeof(DWORD);
+ RegQueryValueExW(hKey, L"VLRenewalInterval", NULL, NULL, (LPBYTE)&VLRenewalInterval, &bufferSize);
+
+ // Handle Registry Parameters (Free TCP/IP)
+ bufferSize = sizeof(DWORD);
+ RegQueryValueExW(hKey, L"KillProcessOnPort", NULL, NULL, (LPBYTE)&KillProcesses, &bufferSize);
+
+ // Close Registry Key
+ RegCloseKey(hKey);
+ }
+
+ // Validate Values
+ ServerValidateKMSPort(KMSPort);
+ ServerValidateKMSPID(KMSPID);
+ ServerValidateKMSHWID(KMSHWID);
+ ServerValidateVLActivationInterval(VLActivationInterval);
+ ServerValidateVLRenewalInterval(VLRenewalInterval);
+
+ // Handle External Process Termination
+ if (KillProcesses > 0)
+ {
+ // Apply Setting
+ ServerSettings.KillProcesses = true;
+ ServerWriteLogInformation(L"KMS Port Process Termination: Enabled \n");
+ }
+ else
+ {
+ // Apply Setting
+ ServerSettings.KillProcesses = false;
+ ServerWriteLogInformation(L"KMS Port Process Termination: Disabled \n");
+ }
+
+ #pragma endregion
+ }
+}
+
+// Start RPC Connection and listen indefinitely for KMS Clients.
+void StartKMSServer()
+{
+ // Uses the protocol combined with the endpoint for receiving remote procedure calls.
+ RPC_STATUS status = RpcServerUseProtseqEp
+ (
+ // Use TCP/IP protocol.
+ (RPC_WSTR)L"ncacn_ip_tcp",
+ // Backlog queue length for TCP/IP.
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ // TCP/IP port to use.
+ (RPC_WSTR)ServerSettings.KMSPort,
+ // No security.
+ NULL
+ );
+
+ if (status)
+ {
+ // TCP/IP Port in Use
+ if (status == RPC_S_DUPLICATE_ENDPOINT && ServerSettings.KillProcesses)
+ {
+ // TCP Table and TCP Table Size
+ MIB_TCPTABLE_OWNER_PID *pTCPInfo;
+ DWORD dwSize = 0;
+
+ // Get TCP Table Size
+ GetExtendedTcpTable(NULL, &dwSize, true, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
+
+ // Allocate Memory for TCP Table
+ pTCPInfo = (MIB_TCPTABLE_OWNER_PID*)malloc(dwSize);
+
+ // Get TCP Table Data
+ GetExtendedTcpTable(pTCPInfo, &dwSize, true, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
+
+ // Read TCP Table Data
+ for (DWORD i = 0; i < pTCPInfo->dwNumEntries; i++)
+ {
+ // Get Process ID, Opened Port of the Process and KMS Port
+ DWORD processID = pTCPInfo->table[i].dwOwningPid;
+ DWORD kmsport = _wtoi(ServerSettings.KMSPort);
+ DWORD port = ntohs((u_short)pTCPInfo->table[i].dwLocalPort);
+
+ // Check if this Process has the KMS Port
+ if (port == kmsport)
+ {
+
+ // Enable Debug Privileges
+ HANDLE tokenHandle;
+ OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle);
+ TOKEN_PRIVILEGES privilegeToken;
+ LookupPrivilegeValue(0, SE_DEBUG_NAME, &privilegeToken.Privileges[0].Luid);
+ privilegeToken.PrivilegeCount = 1;
+ privilegeToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ AdjustTokenPrivileges(tokenHandle, 0, &privilegeToken, sizeof(TOKEN_PRIVILEGES), 0, 0);
+ CloseHandle(tokenHandle);
+
+ // Kill Process using the KMS Port
+ HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
+ if (hProcess != NULL)
+ {
+ TerminateProcess(hProcess, 0);
+ CloseHandle(hProcess);
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Failed to get handle to kill Process ID: %i.\n", processID);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ break;
+ }
+ }
+
+ // Connect on Port Again
+ Sleep(5000);
+ status = RpcServerUseProtseqEp
+ (
+ // Use TCP/IP protocol.
+ (RPC_WSTR)L"ncacn_ip_tcp",
+ // Backlog queue length for TCP/IP.
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ // TCP/IP port to use.
+ (RPC_WSTR)ServerSettings.KMSPort,
+ // No security.
+ NULL
+ );
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcServerUseProtseqEp failed with code %i.\n", status);
+ ServerWriteLogErrorTerminate(Message, status);
+ }
+ }
+
+ // Registers the KMSServer interface.
+ status = RpcServerRegisterIfEx
+ (
+ // Interface to register.
+ KMSServer_v1_0_s_ifspec,
+ // Use the MIDL generated entry-point vector.
+ NULL,
+ // Use the MIDL generated entry-point vector.
+ NULL,
+ // Interface Registration Flags
+ RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH | RPC_IF_AUTOLISTEN,
+ // Maximum Calls
+ RPC_C_LISTEN_MAX_CALLS_DEFAULT,
+ // No Security Callback Function
+ NULL
+ );
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcServerRegisterIfEx failed with code %i.\n", status);
+ ServerWriteLogErrorTerminate(Message, status);
+ }
+
+ ServerWriteLogInformation(L"\nKMS Server Emulator started successfully.\n");
+
+ // Start to listen for remote procedure calls for all registered interfaces.
+ // This call will not return until RpcMgmtStopServerListening is called or the program is exited.
+ status = RpcServerListen
+ (
+ // Recommended minimum number of threads.
+ 1,
+ // Recommended maximum number of threads.
+ RPC_C_LISTEN_MAX_CALLS_DEFAULT,
+ // Start listening now.
+ 0
+ );
+
+ if (status)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"RpcServerListen failed with code %i.\n", status);
+ ServerWriteLogErrorTerminate(Message, status);
+ }
+}
+
+// Stop RPC Connection
+void StopKMSServer()
+{
+ RpcMgmtStopServerListening(NULL);
+ RpcServerUnregisterIf(NULL, NULL, FALSE);
+}
+#pragma endregion
+
+#pragma region RPC Interface Functions
+// RPC Function to Build and Send a KMS Server Response.
+int ActivationResponse(handle_t IDL_handle, int requestSize, unsigned char *request, int *responseSize, unsigned char **response)
+{
+ // No Unreferenced Parameter Warnings
+ UNREFERENCED_PARAMETER(IDL_handle);
+
+ // Verify Request Size
+ if (requestSize < 92)
+ {
+ return RPC_S_INVALID_ENDPOINT_FORMAT;
+ }
+
+ // KMS Protocol Version
+ if (request[2] == 4 && request[0] == 0)
+ {
+ // Send Response to KMS Client
+ *response = CreateResponseV4((REQUEST_V4 *)request, responseSize);
+
+ // Log Sent Response
+ ServerWriteLogInformation(L"Activation response (KMS V4.0) sent.\n");
+
+ // Return to RPC Interface
+ return RPC_S_OK;
+ }
+ else if (request[2] == 5 && request[0] == 0)
+ {
+ // Send Response to KMS Client
+ *response = CreateResponseV5((REQUEST_V5 *)request, responseSize);
+
+ // Log Sent Response
+ ServerWriteLogInformation(L"Activation response (KMS V5.0) sent.\n");
+
+ // Return to RPC Interface
+ return RPC_S_OK;
+ }
+ else if (request[2] == 6 && request[0] == 0)
+ {
+ // Send Response to KMS Client
+ *response = CreateResponseV6((REQUEST_V6 *)request, responseSize);
+
+ // Log Sent Response
+ ServerWriteLogInformation(L"Activation response (KMS V6.0) sent.\n");
+
+ // Return to RPC Interface
+ return RPC_S_OK;
+ }
+ else
+ {
+ // Unsupported Protocol
+ return RPC_S_INVALID_VERS_OPTION;
+ }
+}
+#pragma endregion
+
+#pragma region KMS Server Response Generation Functions
+// Create Base KMS Server Response Object and handle KMS PID and HWID.
+DWORD CreateResponseBase(REQUEST* const Request, PBYTE const Response)
+{
+ // Generate KMS PID or use Command Argument
+ WCHAR kmsPIDInstance[PID_BUFFER_SIZE] = { 0 };
+
+ // Try to Get Application Specific KMS PID and HWID if running as KMS Server Service
+ if (ServerSettings.RunAsService)
+ {
+ GetKMSPID(kmsPIDInstance, Request);
+ }
+
+ // No Specific KMS PID or not running as KMS Server Service
+ if (!regex_match(kmsPIDInstance, wregex(L"^([0-9]{5})-([0-9]{5})-([0-9]{3})-([0-9]{6})-([0-9]{2})-([0-9]{4,5})-([0-9]{4}).([0-9]{4})-([0-9]{7})$")))
+ {
+ if (ServerSettings.GenerateRandomKMSPID)
+ {
+ // Build Random KMS PID
+ CreateKMSPID(kmsPIDInstance, Request);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"\nKMS PID Generated: %s \n", kmsPIDInstance);
+ ServerWriteLogInformation(Message);
+ }
+ else
+ {
+ // Use Global KMS PID from Settings
+ StringCchCopyW(kmsPIDInstance, PID_BUFFER_SIZE, ServerSettings.KMSPID);
+ }
+ }
+
+ // Get KMS PID Length
+ DWORD kmsPIDLen = (DWORD)((wcslen(kmsPIDInstance) + 1) * sizeof(WCHAR));
+
+ // Current pointer
+ PBYTE current = Response;
+
+ // Set KMS Protocol Minor Version & Major Version
+ *(PDWORD)current = *(PDWORD)Request;
+ current += sizeof(DWORD);
+
+ // Set KMS PID Length
+ *(PDWORD)current = kmsPIDLen;
+ current += sizeof(DWORD);
+
+ // Copy KMS PID
+ memcpy(current, kmsPIDInstance, kmsPIDLen);
+ current += kmsPIDLen;
+
+ // Copy Client Machine ID
+ memcpy(current, &Request->ClientMachineId, sizeof(GUID));
+ current += sizeof(GUID);
+
+ // Copy KMS Client Request Timestamp
+ memcpy(current, &Request->RequestTime, sizeof(FILETIME));
+ current += sizeof(FILETIME);
+
+ // Set KMS Client Count Parameter
+ *(PDWORD)current = ServerSettings.CurrentClientCount;
+ current += sizeof(DWORD);
+
+ // Set KMS Activation Interval Parameter
+ *(PDWORD)current = ServerSettings.VLActivationInterval;
+ current += sizeof(DWORD);
+
+ // Set KMS Renewal Interval Parameter
+ *(PDWORD)current = ServerSettings.VLRenewalInterval;
+ current += sizeof(DWORD);
+
+ // Return ResponseBase Size
+ return (DWORD)(current - Response);
+}
+
+// Create Hashed KMS Server Response Data for KMS Protocol Version 4.
+PBYTE CreateResponseV4(REQUEST_V4* const Request, int* const responseSize)
+{
+ // Allocate KMS Server Response Buffer
+ BYTE buffer[MAX_RESPONSE_SIZE] = {0};
+
+ // Create KMS Server Response Base
+ int size = CreateResponseBase(&Request->RequestBase, buffer);
+
+ // Create Hash
+ GetHash(size, buffer, buffer + size);
+
+ // Create Proper Response with Hash
+ *responseSize = size + 16;
+ PBYTE response = (PBYTE)midl_user_allocate(*responseSize);
+ memcpy(response, buffer, *responseSize);
+
+ // Return Response
+ return response;
+}
+
+// Create Encrypted KMS Server Response Data for KMS Protocol Version 5.
+PBYTE CreateResponseV5(REQUEST_V5* const Request, int* const responseSize)
+{
+ // Allocate Response Buffer
+ BYTE buffer[MAX_RESPONSE_SIZE] = {0};
+
+ // Current pointer
+ PBYTE current = buffer;
+
+ // Set KMS Protocol Minor Version & Major Version
+ *(PDWORD)current = *(PDWORD)Request;
+ current += sizeof(DWORD);
+
+ // Store Response Salt pointer
+ PBYTE ResponseSalt = current;
+
+ // Copy Response Salt
+ memcpy(current, Request->Salt, 16);
+ current += 16;
+
+ // AES-128 Decrypt
+ DWORD DecryptSize = sizeof(Request->Salt) + sizeof(Request->RequestBase) + sizeof(Request->Pad);
+ AESDecryptMessage(Request->Salt, Request->Salt, &DecryptSize);
+
+ // Store Encrypt start pointer
+ PBYTE EncryptStart = current;
+
+ // Create Response Base Object
+ current += CreateResponseBase(&Request->RequestBase, current);
+
+ // Random Salt
+ BYTE RandomSalt[16];
+
+ // Seed Random Number Generator
+ srand(GetTickCount());
+
+ // Generate a Random Salt Key
+ for(int i = 0; i < 16; i++)
+ {
+ RandomSalt[i] = rand() % 256;
+ current[i] = Request->Salt[i] ^ ResponseSalt[i] ^ RandomSalt[i];
+ }
+ current += 16;
+
+ // Create Hash
+ GetHashSHA256(16, RandomSalt, current);
+ current += 32;
+
+ // Encrypted and Unencrypted size (KMS Protocol Major Version (2) + KMS Protocol Minor Version (2) + Salt (16))
+ DWORD UnencryptedSize = 20;
+ DWORD EncryptedSize = (DWORD)(current - EncryptStart);
+
+ // AES-128 Encrypt
+ AESEncryptMessage(ResponseSalt, EncryptStart, &EncryptedSize, MAX_RESPONSE_SIZE - UnencryptedSize);
+
+ // Make proper response with correct size
+ *responseSize = EncryptedSize + UnencryptedSize;
+ PBYTE response = (PBYTE)midl_user_allocate(*responseSize);
+ memcpy(response, buffer, *responseSize);
+
+ // Return Response
+ return response;
+}
+
+// Create Encrypted KMS Server Response Data for KMS Protocol Version 6.
+PBYTE CreateResponseV6(REQUEST_V6* const Request, int* const responseSize)
+{
+ // V6: AES key
+ BYTE AES_V6_KEY[16] = {0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21};
+
+ // Allocate Response Buffer
+ BYTE buffer[MAX_RESPONSE_SIZE] = {0};
+
+ // Current pointer
+ PBYTE current = buffer;
+
+ // Set KMS Protocol Minor Version & Major Version
+ *(PDWORD)current = *(PDWORD)Request;
+ current += sizeof(DWORD);
+
+ // Store Response Salt pointer
+ PBYTE ResponseSalt = current;
+
+ // Copy Response Salt
+ memcpy(current, Request->Salt, 16);
+ current += 16;
+
+ // AES-128 Decrypt
+ DWORD DecryptSize = sizeof(Request->Salt) + sizeof(Request->RequestBase) + sizeof(Request->Pad);
+
+ // Modded AES-CBC Decrypt
+ AesInit(AES_TYPE_128, AES_MODE_CBC, 0x04, AES_V6_KEY, Request->Salt);
+ DecryptMessage(DecryptSize, Request->Salt);
+ AesClear();
+
+ // Store Encrypt start pointer
+ PBYTE EncryptStart = current;
+
+ // Create Response Base Object
+ current += CreateResponseBase(&Request->RequestBase, current);
+
+ // Random Salt
+ BYTE RandomSalt[16];
+
+ // Seed Random Number Generator
+ srand(GetTickCount());
+
+ // Generate a Random Salt Key
+ for(int i = 0; i < 16; i++)
+ {
+ RandomSalt[i] = rand() % 256;
+ current[i] = Request->Salt[i] ^ ResponseSalt[i] ^ RandomSalt[i];
+ }
+ current += 16;
+
+ // Create Hash
+ GetHashSHA256(16, RandomSalt, current);
+ current += 32;
+
+ #pragma region KMS HWID
+ // Try to Get Application Specific KMS HWID if running as KMS Server Service
+ QWORD kmsHWIDInstance = 0x0;
+ if (ServerSettings.RunAsService)
+ {
+ GetKMSHWID(&kmsHWIDInstance, &Request->RequestBase);
+ }
+
+ // No Specific KMS HWID or not running as KMS Server Service
+ if (kmsHWIDInstance == 0x0)
+ {
+ // Use Global KMS PID from Settings
+ kmsHWIDInstance = ServerSettings.KMSHWID;
+ }
+
+ // Machine Hardware Hash
+ *(PQWORD) current = kmsHWIDInstance;
+ current += 8;
+ #pragma endregion
+
+ // HMAC message buffer
+ BYTE Hmac_msg[256];
+
+ // Xor2 and Hmac_msg
+ for(int i = 0; i < 16; i++)
+ {
+ Hmac_msg[i] = current[i] = Request->Salt[i] ^ ResponseSalt[i];
+ }
+ current += 16;
+
+ // HMAC size
+ DWORD Hmac_size = current - EncryptStart;
+ memcpy(Hmac_msg + 16, EncryptStart, Hmac_size);
+ Hmac_size += 16;
+
+ // HMAC-SHA256
+ BYTE Hmac_hash[32];
+ GetHmacKey(&Request->RequestBase.RequestTime, Hmac_keyblob.rgbKeyData);
+ GetHmacSHA256(Hmac_size, Hmac_msg, Hmac_hash);
+ memcpy(current, Hmac_hash + 16, 16);
+ current += 16;
+
+ // Encrypted and Unencrypted size (KMS Protocol Major Version (2) + KMS Protocol Minor Version (2) + Salt (16))
+ DWORD EncryptSize = (DWORD)(current - EncryptStart);
+
+ // PKCS5 Padding
+ BYTE bPadding =(~EncryptSize + 1) & 0x0f;
+ if(bPadding == 0){
+ bPadding = 16;
+ }
+
+ memset(current, bPadding, bPadding);
+ EncryptSize += bPadding;
+
+ // Modded AES-CBC Encrypt
+ AesInit(AES_TYPE_128, AES_MODE_CBC, bPadding, AES_V6_KEY, ResponseSalt);
+ EncryptMessage(EncryptSize, EncryptStart);
+ AesClear();
+
+ // Make proper response with correct size
+ *responseSize = EncryptSize + 20;
+ PBYTE response = (PBYTE)midl_user_allocate(*responseSize);
+ memcpy(response, buffer, *responseSize);
+
+ // Return Response
+ return response;
+}
+#pragma endregion
+
+#pragma region Parameter Validation Functions
+// Validate KMS Port Parameter
+void ServerValidateKMSPort(WCHAR* KMSPort)
+{
+ // Check if the KMS Port is not the Default
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSPort, -1, L"DefaultPort", -1) != CSTR_EQUAL)
+ {
+ // Check if KMS Port is Valid Number
+ if (regex_match(KMSPort, wregex(L"^([0-9]+)$")))
+ {
+ // Check if KMS Port is Valid Range
+ if(_wtoi(KMSPort) < 1 || _wtoi(KMSPort) > 65535)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Port Range! %s is not a valid argument.\n", KMSPort);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ else
+ {
+ // Apply Setting
+ StringCchCopyW(ServerSettings.KMSPort, PORT_BUFFER_SIZE, KMSPort);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Port: %s \n", KMSPort);
+ ServerWriteLogInformation(Message);
+ }
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Port! %s is not a valid argument.\n", KMSPort);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ }
+}
+
+// Validate KMS PID Parameter
+void ServerValidateKMSPID(WCHAR* KMSPID)
+{
+ // Check if KMS PID should be Random
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSPID, -1, L"RandomKMSPID", -1) == CSTR_EQUAL)
+ {
+ ServerSettings.GenerateRandomKMSPID = true;
+ }
+ // Check if KMS PID is Valid
+ else if (regex_match(KMSPID, wregex(L"^([0-9]{5})-([0-9]{5})-([0-9]{3})-([0-9]{6})-([0-9]{2})-([0-9]{4,5})-([0-9]{4}).([0-9]{4})-([0-9]{7})$")))
+ {
+ // Apply Setting
+ StringCchCopyW(ServerSettings.KMSPID, PID_BUFFER_SIZE, KMSPID);
+
+ // Disable Random KMSPID Generation
+ ServerSettings.GenerateRandomKMSPID = false;
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS PID: %s \n", KMSPID);
+ ServerWriteLogInformation(Message);
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS PID! %s is not a valid argument.\n", KMSPID);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+}
+
+// Validate KMS HWID Parameter
+void ServerValidateKMSHWID(WCHAR* KMSHWID)
+{
+ // Check if the KMS Port is not the Default
+ if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, KMSHWID, -1, L"DefaultKMSHWID", -1) != CSTR_EQUAL)
+ {
+ // Check if KMS HWID is Valid Hex String
+ if (regex_match(KMSHWID, wregex(L"^[a-fA-F0-9]{16}$")))
+ {
+ // Apply Setting
+ ServerSettings.KMSHWID = wcstoull(KMSHWID, NULL, 16);
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS HWID: %s \n", KMSHWID);
+ ServerWriteLogInformation(Message);
+ }
+ else
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Hardware ID! %s is not a valid argument.\n", KMSHWID);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ }
+}
+
+// Validate KMS Activation Interval Parameter
+void ServerValidateVLActivationInterval(int VLActivationInterval)
+{
+ // Check if KMS Activation Interval is Valid Range
+ if (VLActivationInterval < 15 || VLActivationInterval > 43200)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Activation Interval Range! %i is not a valid argument.\n", VLActivationInterval);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ else
+ {
+ // Apply Setting
+ ServerSettings.VLActivationInterval = VLActivationInterval;
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Activation Interval: %i minutes \n", VLActivationInterval);
+ ServerWriteLogInformation(Message);
+ }
+}
+
+// Validate KMS Activation Interval Parameter
+void ServerValidateVLRenewalInterval(int VLRenewalInterval)
+{
+ // Check if KMS Renewal Interval is Valid Range
+ if (VLRenewalInterval < 15 || VLRenewalInterval > 43200)
+ {
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"Invalid KMS Renewal Interval Range! %i is not a valid argument.\n", VLRenewalInterval);
+ ServerWriteLogErrorTerminate(Message, -1);
+ }
+ else
+ {
+ // Apply Setting
+ ServerSettings.VLRenewalInterval = VLRenewalInterval;
+
+ // Format Log Message
+ WCHAR Message[256];
+ swprintf_s(Message, 256, L"KMS Renewal Interval: %i minutes \n", VLRenewalInterval);
+ ServerWriteLogInformation(Message);
+ }
+}
+#pragma endregion
+
+#pragma region Logging Functions
+// Log an informational message to the Console or Windows Application Event Log.
+void ServerWriteLogInformation(WCHAR* const Message)
+{
+ // Log Message Buffer
+ WCHAR logMessage[256];
+
+ // Write Log Message to Buffer
+ StringCbPrintfW(logMessage, 256, Message);
+
+ // Choose Log Source
+ if (ServerSettings.RunAsService)
+ {
+ // Output to Windows Event Log: Qualifiers: 16384, EventId: 12290
+ ServerWriteEventLogEntry(0x40003002, logMessage, EVENTLOG_INFORMATION_TYPE);
+ }
+ else
+ {
+ // Output to Console
+ wprintf(L"%s", logMessage);
+ }
+}
+
+// Log an error message to the Console or Windows Application Event Log.
+void ServerWriteLogError(WCHAR* const Message)
+{
+ // Log Message Buffer
+ WCHAR logMessage[256];
+
+ // Write Log Message to Buffer
+ StringCbPrintfW(logMessage, 256, Message);
+
+ // Choose Log Source
+ if (ServerSettings.RunAsService)
+ {
+ // Output to Windows Event Log: Qualifiers: 16384, EventId: 902
+ ServerWriteEventLogEntry(0x40000386, logMessage, EVENTLOG_ERROR_TYPE);
+ }
+ else
+ {
+ // Output to Console
+ wprintf(L"%s", logMessage);
+ }
+}
+
+// Log an error message to the Console or Windows Application Event Log and terminate program.
+void ServerWriteLogErrorTerminate(WCHAR* const Message, int ExitCode)
+{
+ // Call ServerWriteLogError
+ ServerWriteLogError(Message);
+
+ if (!ServerSettings.RunAsService)
+ {
+ // Exit Program
+ exit(ExitCode);
+ }
+ else
+ {
+ // Exit Service
+ ServerServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ ServerServiceStatus.dwWin32ExitCode = ExitCode;
+ SetServiceStatus(ServerServiceHandle, &ServerServiceStatus);
+ }
+}
+
+// Log a message to the Windows Application Event Log.
+void ServerWriteEventLogEntry(DWORD dwIdentifier, WCHAR* const lpszMessage, WORD wType)
+{
+ HANDLE hEventSource = OpenEventLogW(NULL, L"KmsRequests"); // Provider: KmsRequests or Microsoft-Windows-Security-SPP
+
+ if(hEventSource != NULL)
+ {
+ ReportEventW(
+ hEventSource, // Event log handle
+ wType, // Event type
+ NULL, // Event category
+ dwIdentifier, // Event identifier
+ NULL, // No security identifier
+ 1, // Size of lpszStrings array
+ NULL, // No binary data
+ (LPCWSTR*)&lpszMessage, // Array of strings
+ NULL // No binary data
+ );
+
+ CloseEventLog(hEventSource);
+ }
+}
+#pragma endregion
\ No newline at end of file
diff --git a/source/KMSServerSettings.cpp b/source/KMSServerSettings.cpp
new file mode 100644
index 0000000..9cf92de
--- /dev/null
+++ b/source/KMSServerSettings.cpp
@@ -0,0 +1,29 @@
+// Includes and Namespaces
+#include "KMSServerSettings.h"
+
+// KMS Server Parameters
+WCHAR KMSServerSettings::KMSPID[PID_BUFFER_SIZE];
+QWORD KMSServerSettings::KMSHWID;
+WCHAR KMSServerSettings::KMSPort[PORT_BUFFER_SIZE];
+DWORD KMSServerSettings::CurrentClientCount;
+DWORD KMSServerSettings::VLActivationInterval;
+DWORD KMSServerSettings::VLRenewalInterval;
+
+// KMS Server Program Control
+bool KMSServerSettings::GenerateRandomKMSPID;
+bool KMSServerSettings::RunAsService;
+
+// Process Termination Control Variables
+bool KMSServerSettings:: KillProcesses;
+
+// Set Default Settings
+void KMSServerSettings::Initialize()
+{
+ StringCchCopyW(KMSPID, PID_BUFFER_SIZE, L"55041-00168-305-246209-03-1033-7600.0000-0522010");
+ KMSHWID = 0x364F463A8863D35F;
+ StringCchCopyW(KMSPort, PORT_BUFFER_SIZE, L"1688");
+ CurrentClientCount = 26;
+ VLActivationInterval = 120;
+ VLRenewalInterval = 10080;
+ GenerateRandomKMSPID = true;
+};
diff --git a/source/KMSServer_c.c b/source/KMSServer_c.c
new file mode 100644
index 0000000..65cf87d
--- /dev/null
+++ b/source/KMSServer_c.c
@@ -0,0 +1,498 @@
+// Win32 KMS Client RPC Stubs
+#if !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_)
+
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+
+#pragma warning( disable: 4211 ) /* redefine extern to static */
+#pragma warning( disable: 4232 ) /* dllimport identity*/
+#pragma warning( disable: 4024 ) /* array to pointer mapping*/
+#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */
+
+#pragma optimize("", off )
+
+#include
+
+#include "KMSServer.h"
+
+#define TYPE_FORMAT_STRING_SIZE 43
+#define PROC_FORMAT_STRING_SIZE 59
+#define EXPR_FORMAT_STRING_SIZE 1
+#define TRANSMIT_AS_TABLE_SIZE 0
+#define WIRE_MARSHAL_TABLE_SIZE 0
+
+typedef struct _KMSServer_MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_PROC_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_EXPR_FORMAT_STRING
+ {
+ long Pad;
+ unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_EXPR_FORMAT_STRING;
+
+
+static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
+
+
+extern const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString;
+extern const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString;
+extern const KMSServer_MIDL_EXPR_FORMAT_STRING KMSServer__MIDL_ExprFormatString;
+
+#define GENERIC_BINDING_TABLE_SIZE 0
+
+
+/* Standard interface: KMSServer, ver. 1.0,
+ GUID={0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}} */
+
+
+
+static const RPC_CLIENT_INTERFACE KMSServer___RpcClientInterface =
+ {
+ sizeof(RPC_CLIENT_INTERFACE),
+ {{0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}},{1,0}},
+ {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}},
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x00000000
+ };
+RPC_IF_HANDLE KMSServer_v1_0_c_ifspec = (RPC_IF_HANDLE)& KMSServer___RpcClientInterface;
+
+extern const MIDL_STUB_DESC KMSServer_StubDesc;
+
+static RPC_BINDING_HANDLE KMSServer__MIDL_AutoBindHandle;
+
+
+int ActivationRequest(
+ /* [in] */ handle_t IDL_handle,
+ /* [in] */ int requestSize,
+ /* [size_is][in] */ unsigned char *request,
+ /* [out] */ int *responseSize,
+ /* [size_is][size_is][out] */ unsigned char **response)
+{
+
+ CLIENT_CALL_RETURN _RetVal;
+
+ _RetVal = NdrClientCall2(
+ ( PMIDL_STUB_DESC )&KMSServer_StubDesc,
+ (PFORMAT_STRING) &KMSServer__MIDL_ProcFormatString.Format[0],
+ ( unsigned char * )&IDL_handle);
+ return ( int )_RetVal.Simple;
+
+}
+
+
+#if !defined(__RPC_WIN32__)
+#error Invalid build platform for this stub.
+#endif
+
+#if !(TARGET_IS_NT50_OR_LATER)
+#error You need Windows 2000 or later to run this stub because it uses these features:
+#error /robust command line switch.
+#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
+#error This app will fail with the RPC_X_WRONG_STUB_VERSION error.
+#endif
+
+
+static const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure ActivationRequest */
+
+ 0x0, /* 0 */
+ 0x48, /* Old Flags: */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x0 ), /* 0 */
+/* 8 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
+/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */
+ 0x0, /* 0 */
+/* 12 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */
+/* 14 */ NdrFcShort( 0x8 ), /* 8 */
+/* 16 */ NdrFcShort( 0x24 ), /* 36 */
+/* 18 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */
+ 0x5, /* 5 */
+/* 20 */ 0x8, /* 8 */
+ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */
+/* 22 */ NdrFcShort( 0x1 ), /* 1 */
+/* 24 */ NdrFcShort( 0x1 ), /* 1 */
+/* 26 */ NdrFcShort( 0x0 ), /* 0 */
+
+ /* Parameter IDL_handle */
+
+/* 28 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
+/* 30 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 32 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter requestSize */
+
+/* 34 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
+/* 36 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 38 */ NdrFcShort( 0x6 ), /* Type Offset=6 */
+
+ /* Parameter request */
+
+/* 40 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
+/* 42 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 44 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter responseSize */
+
+/* 46 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */
+/* 48 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
+/* 50 */ NdrFcShort( 0x16 ), /* Type Offset=22 */
+
+ /* Parameter response */
+
+/* 52 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 54 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
+/* 56 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x0, /* FC_RP */
+/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */
+/* 6 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 8 */ NdrFcShort( 0x1 ), /* 1 */
+/* 10 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x0, /* */
+/* 12 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 14 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 16 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+/* 18 */
+ 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 20 */ 0x8, /* FC_LONG */
+ 0x5c, /* FC_PAD */
+/* 22 */
+ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
+/* 24 */ NdrFcShort( 0x2 ), /* Offset= 2 (26) */
+/* 26 */
+ 0x12, 0x0, /* FC_UP */
+/* 28 */ NdrFcShort( 0x2 ), /* Offset= 2 (30) */
+/* 30 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 32 */ NdrFcShort( 0x1 ), /* 1 */
+/* 34 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x54, /* FC_DEREFERENCE */
+/* 36 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 38 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 40 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+
+ 0x0
+ }
+ };
+
+static const unsigned short KMSServer_FormatStringOffsetTable[] =
+ {
+ 0
+ };
+
+
+static const MIDL_STUB_DESC KMSServer_StubDesc =
+ {
+ (void *)& KMSServer___RpcClientInterface,
+ MIDL_user_allocate,
+ MIDL_user_free,
+ &KMSServer__MIDL_AutoBindHandle,
+ 0,
+ 0,
+ 0,
+ 0,
+ KMSServer__MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x50002, /* Ndr library version */
+ 0,
+ 0x8000253, /* MIDL Version 8.0.595 */
+ 0,
+ 0,
+ 0, /* notify & notify_flag routine table */
+ 0x1, /* MIDL flag */
+ 0, /* cs routines */
+ 0, /* proxy/server info */
+ 0
+ };
+#pragma optimize("", on )
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+
+#endif
+
+// x64 KMS Client RPC Stubs
+#if defined(_M_AMD64)
+
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+
+#pragma warning( disable: 4211 ) /* redefine extern to static */
+#pragma warning( disable: 4232 ) /* dllimport identity*/
+#pragma warning( disable: 4024 ) /* array to pointer mapping*/
+
+#include
+
+#include "KMSServer.h"
+
+#define TYPE_FORMAT_STRING_SIZE 43
+#define PROC_FORMAT_STRING_SIZE 61
+#define EXPR_FORMAT_STRING_SIZE 1
+#define TRANSMIT_AS_TABLE_SIZE 0
+#define WIRE_MARSHAL_TABLE_SIZE 0
+
+typedef struct _KMSServer_MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_PROC_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_EXPR_FORMAT_STRING
+ {
+ long Pad;
+ unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_EXPR_FORMAT_STRING;
+
+
+static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
+
+
+extern const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString;
+extern const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString;
+extern const KMSServer_MIDL_EXPR_FORMAT_STRING KMSServer__MIDL_ExprFormatString;
+
+#define GENERIC_BINDING_TABLE_SIZE 0
+
+
+/* Standard interface: KMSServer, ver. 1.0,
+ GUID={0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}} */
+
+
+
+static const RPC_CLIENT_INTERFACE KMSServer___RpcClientInterface =
+ {
+ sizeof(RPC_CLIENT_INTERFACE),
+ {{0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}},{1,0}},
+ {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}},
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x00000000
+ };
+RPC_IF_HANDLE KMSServer_v1_0_c_ifspec = (RPC_IF_HANDLE)& KMSServer___RpcClientInterface;
+
+extern const MIDL_STUB_DESC KMSServer_StubDesc;
+
+static RPC_BINDING_HANDLE KMSServer__MIDL_AutoBindHandle;
+
+
+int ActivationRequest(
+ /* [in] */ handle_t IDL_handle,
+ /* [in] */ int requestSize,
+ /* [size_is][in] */ unsigned char *request,
+ /* [out] */ int *responseSize,
+ /* [size_is][size_is][out] */ unsigned char **response)
+{
+
+ CLIENT_CALL_RETURN _RetVal;
+
+ _RetVal = NdrClientCall2(
+ ( PMIDL_STUB_DESC )&KMSServer_StubDesc,
+ (PFORMAT_STRING) &KMSServer__MIDL_ProcFormatString.Format[0],
+ IDL_handle,
+ requestSize,
+ request,
+ responseSize,
+ response);
+ return ( int )_RetVal.Simple;
+
+}
+
+
+#if !defined(__RPC_WIN64__)
+#error Invalid build platform for this stub.
+#endif
+
+static const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure ActivationRequest */
+
+ 0x0, /* 0 */
+ 0x48, /* Old Flags: */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x0 ), /* 0 */
+/* 8 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */
+/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */
+ 0x0, /* 0 */
+/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */
+/* 14 */ NdrFcShort( 0x8 ), /* 8 */
+/* 16 */ NdrFcShort( 0x24 ), /* 36 */
+/* 18 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */
+ 0x5, /* 5 */
+/* 20 */ 0xa, /* 10 */
+ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */
+/* 22 */ NdrFcShort( 0x1 ), /* 1 */
+/* 24 */ NdrFcShort( 0x1 ), /* 1 */
+/* 26 */ NdrFcShort( 0x0 ), /* 0 */
+/* 28 */ NdrFcShort( 0x0 ), /* 0 */
+
+ /* Parameter IDL_handle */
+
+/* 30 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
+/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */
+/* 34 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter requestSize */
+
+/* 36 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
+/* 38 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */
+/* 40 */ NdrFcShort( 0x6 ), /* Type Offset=6 */
+
+ /* Parameter request */
+
+/* 42 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
+/* 44 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */
+/* 46 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter responseSize */
+
+/* 48 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */
+/* 50 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */
+/* 52 */ NdrFcShort( 0x16 ), /* Type Offset=22 */
+
+ /* Parameter response */
+
+/* 54 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 56 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */
+/* 58 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x0, /* FC_RP */
+/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */
+/* 6 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 8 */ NdrFcShort( 0x1 ), /* 1 */
+/* 10 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x0, /* */
+/* 12 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */
+/* 14 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 16 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+/* 18 */
+ 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 20 */ 0x8, /* FC_LONG */
+ 0x5c, /* FC_PAD */
+/* 22 */
+ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
+/* 24 */ NdrFcShort( 0x2 ), /* Offset= 2 (26) */
+/* 26 */
+ 0x12, 0x0, /* FC_UP */
+/* 28 */ NdrFcShort( 0x2 ), /* Offset= 2 (30) */
+/* 30 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 32 */ NdrFcShort( 0x1 ), /* 1 */
+/* 34 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x54, /* FC_DEREFERENCE */
+/* 36 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */
+/* 38 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 40 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+
+ 0x0
+ }
+ };
+
+static const unsigned short KMSServer_FormatStringOffsetTable[] =
+ {
+ 0
+ };
+
+
+static const MIDL_STUB_DESC KMSServer_StubDesc =
+ {
+ (void *)& KMSServer___RpcClientInterface,
+ MIDL_user_allocate,
+ MIDL_user_free,
+ &KMSServer__MIDL_AutoBindHandle,
+ 0,
+ 0,
+ 0,
+ 0,
+ KMSServer__MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x50002, /* Ndr library version */
+ 0,
+ 0x8000253, /* MIDL Version 8.0.595 */
+ 0,
+ 0,
+ 0, /* notify & notify_flag routine table */
+ 0x1, /* MIDL flag */
+ 0, /* cs routines */
+ 0, /* proxy/server info */
+ 0
+ };
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+
+#endif
\ No newline at end of file
diff --git a/source/KMSServer_s.c b/source/KMSServer_s.c
new file mode 100644
index 0000000..06b26f2
--- /dev/null
+++ b/source/KMSServer_s.c
@@ -0,0 +1,502 @@
+// Win32 KMS Server RPC Stubs
+#if !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_)
+
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+
+#pragma warning( disable: 4211 ) /* redefine extern to static */
+#pragma warning( disable: 4232 ) /* dllimport identity*/
+#pragma warning( disable: 4024 ) /* array to pointer mapping*/
+#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */
+
+#pragma optimize("", off )
+
+#include
+#include "KMSServer.h"
+
+#define TYPE_FORMAT_STRING_SIZE 43
+#define PROC_FORMAT_STRING_SIZE 59
+#define EXPR_FORMAT_STRING_SIZE 1
+#define TRANSMIT_AS_TABLE_SIZE 0
+#define WIRE_MARSHAL_TABLE_SIZE 0
+
+typedef struct _KMSServer_MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_PROC_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_EXPR_FORMAT_STRING
+ {
+ long Pad;
+ unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_EXPR_FORMAT_STRING;
+
+
+static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
+
+extern const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString;
+extern const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString;
+extern const KMSServer_MIDL_EXPR_FORMAT_STRING KMSServer__MIDL_ExprFormatString;
+
+/* Standard interface: KMSServer, ver. 1.0,
+ GUID={0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}} */
+
+
+extern const MIDL_SERVER_INFO KMSServer_ServerInfo;
+
+extern const RPC_DISPATCH_TABLE KMSServer_v1_0_DispatchTable;
+
+static const RPC_SERVER_INTERFACE KMSServer___RpcServerInterface =
+ {
+ sizeof(RPC_SERVER_INTERFACE),
+ {{0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}},{1,0}},
+ {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}},
+ (RPC_DISPATCH_TABLE*)&KMSServer_v1_0_DispatchTable,
+ 0,
+ 0,
+ 0,
+ &KMSServer_ServerInfo,
+ 0x04000000
+ };
+RPC_IF_HANDLE KMSServer_v1_0_s_ifspec = (RPC_IF_HANDLE)& KMSServer___RpcServerInterface;
+
+extern const MIDL_STUB_DESC KMSServer_StubDesc;
+
+
+#if !defined(__RPC_WIN32__)
+#error Invalid build platform for this stub.
+#endif
+
+#if !(TARGET_IS_NT50_OR_LATER)
+#error You need Windows 2000 or later to run this stub because it uses these features:
+#error /robust command line switch.
+#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
+#error This app will fail with the RPC_X_WRONG_STUB_VERSION error.
+#endif
+
+
+static const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure ActivationResponse */
+
+ 0x0, /* 0 */
+ 0x48, /* Old Flags: */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x0 ), /* 0 */
+/* 8 */ NdrFcShort( 0x18 ), /* x86 Stack size/offset = 24 */
+/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */
+ 0x0, /* 0 */
+/* 12 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */
+/* 14 */ NdrFcShort( 0x8 ), /* 8 */
+/* 16 */ NdrFcShort( 0x24 ), /* 36 */
+/* 18 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */
+ 0x5, /* 5 */
+/* 20 */ 0x8, /* 8 */
+ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */
+/* 22 */ NdrFcShort( 0x1 ), /* 1 */
+/* 24 */ NdrFcShort( 0x1 ), /* 1 */
+/* 26 */ NdrFcShort( 0x0 ), /* 0 */
+
+ /* Parameter IDL_handle */
+
+/* 28 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
+/* 30 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 32 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter requestSize */
+
+/* 34 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
+/* 36 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
+/* 38 */ NdrFcShort( 0x6 ), /* Type Offset=6 */
+
+ /* Parameter request */
+
+/* 40 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
+/* 42 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 44 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter responseSize */
+
+/* 46 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */
+/* 48 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */
+/* 50 */ NdrFcShort( 0x16 ), /* Type Offset=22 */
+
+ /* Parameter response */
+
+/* 52 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 54 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */
+/* 56 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x0, /* FC_RP */
+/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */
+/* 6 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 8 */ NdrFcShort( 0x1 ), /* 1 */
+/* 10 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x0, /* */
+/* 12 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */
+/* 14 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 16 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+/* 18 */
+ 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 20 */ 0x8, /* FC_LONG */
+ 0x5c, /* FC_PAD */
+/* 22 */
+ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
+/* 24 */ NdrFcShort( 0x2 ), /* Offset= 2 (26) */
+/* 26 */
+ 0x12, 0x0, /* FC_UP */
+/* 28 */ NdrFcShort( 0x2 ), /* Offset= 2 (30) */
+/* 30 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 32 */ NdrFcShort( 0x1 ), /* 1 */
+/* 34 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x54, /* FC_DEREFERENCE */
+/* 36 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */
+/* 38 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 40 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+
+ 0x0
+ }
+ };
+
+static const unsigned short KMSServer_FormatStringOffsetTable[] =
+ {
+ 0
+ };
+
+
+static const MIDL_STUB_DESC KMSServer_StubDesc =
+ {
+ (void *)& KMSServer___RpcServerInterface,
+ MIDL_user_allocate,
+ MIDL_user_free,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ KMSServer__MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x50002, /* Ndr library version */
+ 0,
+ 0x8000253, /* MIDL Version 8.0.595 */
+ 0,
+ 0,
+ 0, /* notify & notify_flag routine table */
+ 0x1, /* MIDL flag */
+ 0, /* cs routines */
+ 0, /* proxy/server info */
+ 0
+ };
+
+static const RPC_DISPATCH_FUNCTION KMSServer_table[] =
+ {
+ NdrServerCall2,
+ 0
+ };
+static const RPC_DISPATCH_TABLE KMSServer_v1_0_DispatchTable =
+ {
+ 1,
+ (RPC_DISPATCH_FUNCTION*)KMSServer_table
+ };
+
+static const SERVER_ROUTINE KMSServer_ServerRoutineTable[] =
+ {
+ (SERVER_ROUTINE)ActivationResponse
+ };
+
+static const MIDL_SERVER_INFO KMSServer_ServerInfo =
+ {
+ &KMSServer_StubDesc,
+ KMSServer_ServerRoutineTable,
+ KMSServer__MIDL_ProcFormatString.Format,
+ KMSServer_FormatStringOffsetTable,
+ 0,
+ 0,
+ 0,
+ 0};
+#pragma optimize("", on )
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+
+#endif
+
+// x64 KMS Server RPC Stubs
+#if defined(_M_AMD64)
+
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#if _MSC_VER >= 1200
+#pragma warning(push)
+#endif
+
+#pragma warning( disable: 4211 ) /* redefine extern to static */
+#pragma warning( disable: 4232 ) /* dllimport identity*/
+#pragma warning( disable: 4024 ) /* array to pointer mapping*/
+
+#include
+#include "KMSServer.h"
+
+#define TYPE_FORMAT_STRING_SIZE 43
+#define PROC_FORMAT_STRING_SIZE 61
+#define EXPR_FORMAT_STRING_SIZE 1
+#define TRANSMIT_AS_TABLE_SIZE 0
+#define WIRE_MARSHAL_TABLE_SIZE 0
+
+typedef struct _KMSServer_MIDL_TYPE_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_PROC_FORMAT_STRING
+ {
+ short Pad;
+ unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_PROC_FORMAT_STRING;
+
+typedef struct _KMSServer_MIDL_EXPR_FORMAT_STRING
+ {
+ long Pad;
+ unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
+ } KMSServer_MIDL_EXPR_FORMAT_STRING;
+
+
+static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
+{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
+
+extern const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString;
+extern const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString;
+extern const KMSServer_MIDL_EXPR_FORMAT_STRING KMSServer__MIDL_ExprFormatString;
+
+/* Standard interface: KMSServer, ver. 1.0,
+ GUID={0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}} */
+
+
+extern const MIDL_SERVER_INFO KMSServer_ServerInfo;
+
+extern const RPC_DISPATCH_TABLE KMSServer_v1_0_DispatchTable;
+
+static const RPC_SERVER_INTERFACE KMSServer___RpcServerInterface =
+ {
+ sizeof(RPC_SERVER_INTERFACE),
+ {{0x51C82175,0x844E,0x4750,{0xB0,0xD8,0xEC,0x25,0x55,0x55,0xBC,0x06}},{1,0}},
+ {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}},
+ (RPC_DISPATCH_TABLE*)&KMSServer_v1_0_DispatchTable,
+ 0,
+ 0,
+ 0,
+ &KMSServer_ServerInfo,
+ 0x04000000
+ };
+RPC_IF_HANDLE KMSServer_v1_0_s_ifspec = (RPC_IF_HANDLE)& KMSServer___RpcServerInterface;
+
+extern const MIDL_STUB_DESC KMSServer_StubDesc;
+
+
+#if !defined(__RPC_WIN64__)
+#error Invalid build platform for this stub.
+#endif
+
+static const KMSServer_MIDL_PROC_FORMAT_STRING KMSServer__MIDL_ProcFormatString =
+ {
+ 0,
+ {
+
+ /* Procedure ActivationResponse */
+
+ 0x0, /* 0 */
+ 0x48, /* Old Flags: */
+/* 2 */ NdrFcLong( 0x0 ), /* 0 */
+/* 6 */ NdrFcShort( 0x0 ), /* 0 */
+/* 8 */ NdrFcShort( 0x30 ), /* X64 Stack size/offset = 48 */
+/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */
+ 0x0, /* 0 */
+/* 12 */ NdrFcShort( 0x0 ), /* X64 Stack size/offset = 0 */
+/* 14 */ NdrFcShort( 0x8 ), /* 8 */
+/* 16 */ NdrFcShort( 0x24 ), /* 36 */
+/* 18 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */
+ 0x5, /* 5 */
+/* 20 */ 0xa, /* 10 */
+ 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */
+/* 22 */ NdrFcShort( 0x1 ), /* 1 */
+/* 24 */ NdrFcShort( 0x1 ), /* 1 */
+/* 26 */ NdrFcShort( 0x0 ), /* 0 */
+/* 28 */ NdrFcShort( 0x0 ), /* 0 */
+
+ /* Parameter IDL_handle */
+
+/* 30 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */
+/* 32 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */
+/* 34 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter requestSize */
+
+/* 36 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
+/* 38 */ NdrFcShort( 0x10 ), /* X64 Stack size/offset = 16 */
+/* 40 */ NdrFcShort( 0x6 ), /* Type Offset=6 */
+
+ /* Parameter request */
+
+/* 42 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */
+/* 44 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */
+/* 46 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ /* Parameter responseSize */
+
+/* 48 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */
+/* 50 */ NdrFcShort( 0x20 ), /* X64 Stack size/offset = 32 */
+/* 52 */ NdrFcShort( 0x16 ), /* Type Offset=22 */
+
+ /* Parameter response */
+
+/* 54 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */
+/* 56 */ NdrFcShort( 0x28 ), /* X64 Stack size/offset = 40 */
+/* 58 */ 0x8, /* FC_LONG */
+ 0x0, /* 0 */
+
+ 0x0
+ }
+ };
+
+static const KMSServer_MIDL_TYPE_FORMAT_STRING KMSServer__MIDL_TypeFormatString =
+ {
+ 0,
+ {
+ NdrFcShort( 0x0 ), /* 0 */
+/* 2 */
+ 0x11, 0x0, /* FC_RP */
+/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */
+/* 6 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 8 */ NdrFcShort( 0x1 ), /* 1 */
+/* 10 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x0, /* */
+/* 12 */ NdrFcShort( 0x8 ), /* X64 Stack size/offset = 8 */
+/* 14 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 16 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+/* 18 */
+ 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 20 */ 0x8, /* FC_LONG */
+ 0x5c, /* FC_PAD */
+/* 22 */
+ 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
+/* 24 */ NdrFcShort( 0x2 ), /* Offset= 2 (26) */
+/* 26 */
+ 0x12, 0x0, /* FC_UP */
+/* 28 */ NdrFcShort( 0x2 ), /* Offset= 2 (30) */
+/* 30 */
+ 0x1b, /* FC_CARRAY */
+ 0x0, /* 0 */
+/* 32 */ NdrFcShort( 0x1 ), /* 1 */
+/* 34 */ 0x28, /* Corr desc: parameter, FC_LONG */
+ 0x54, /* FC_DEREFERENCE */
+/* 36 */ NdrFcShort( 0x18 ), /* X64 Stack size/offset = 24 */
+/* 38 */ NdrFcShort( 0x1 ), /* Corr flags: early, */
+/* 40 */ 0x2, /* FC_CHAR */
+ 0x5b, /* FC_END */
+
+ 0x0
+ }
+ };
+
+static const unsigned short KMSServer_FormatStringOffsetTable[] =
+ {
+ 0
+ };
+
+
+static const MIDL_STUB_DESC KMSServer_StubDesc =
+ {
+ (void *)& KMSServer___RpcServerInterface,
+ MIDL_user_allocate,
+ MIDL_user_free,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ KMSServer__MIDL_TypeFormatString.Format,
+ 1, /* -error bounds_check flag */
+ 0x50002, /* Ndr library version */
+ 0,
+ 0x8000253, /* MIDL Version 8.0.595 */
+ 0,
+ 0,
+ 0, /* notify & notify_flag routine table */
+ 0x1, /* MIDL flag */
+ 0, /* cs routines */
+ 0, /* proxy/server info */
+ 0
+ };
+
+static const RPC_DISPATCH_FUNCTION KMSServer_table[] =
+ {
+ NdrServerCall2,
+ 0
+ };
+static const RPC_DISPATCH_TABLE KMSServer_v1_0_DispatchTable =
+ {
+ 1,
+ (RPC_DISPATCH_FUNCTION*)KMSServer_table
+ };
+
+static const SERVER_ROUTINE KMSServer_ServerRoutineTable[] =
+ {
+ (SERVER_ROUTINE)ActivationResponse
+ };
+
+static const MIDL_SERVER_INFO KMSServer_ServerInfo =
+ {
+ &KMSServer_StubDesc,
+ KMSServer_ServerRoutineTable,
+ KMSServer__MIDL_ProcFormatString.Format,
+ KMSServer_FormatStringOffsetTable,
+ 0,
+ 0,
+ 0,
+ 0};
+#if _MSC_VER >= 1200
+#pragma warning(pop)
+#endif
+
+
+#endif
\ No newline at end of file
diff --git a/source/RPCMemory.c b/source/RPCMemory.c
new file mode 100644
index 0000000..410fcdd
--- /dev/null
+++ b/source/RPCMemory.c
@@ -0,0 +1,15 @@
+#include "KMSServer.h"
+
+// Memory allocation function for RPC.
+// The runtime uses these two functions for allocating/deallocating
+// enough memory to pass the string to the server.
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+{
+ return malloc(len);
+}
+
+// Memory deallocation function for RPC.
+void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
+{
+ free(ptr);
+}
\ No newline at end of file