program "builder"
{
source "source";
+ if_arch "windows"
+ {
+ build_info
+ {
+ library "ole32";
+ library "advapi32";
+ };
+ };
install true;
};
{
"gnu",
"clang",
+ "msvc",
0
};
{
if((system=="darwin" || system=="freebsd") && builder.get_vfs().find_binary("clang"))
toolchain = "clang";
+ else if(system=="windows" && native)
+ toolchain = "msvc";
else
toolchain = "gnu";
}
name += format("-%s", fpu);
name += format("-%d-%s-%s", bits, system, toolchain);
- add_pattern<ObjectFile>("%.o");
if(system=="windows")
{
add_pattern<SharedLibrary>("%.dll");
- add_pattern<SharedLibrary>("lib%.dll");
- add_pattern<ImportLibrary>("lib%.dll.a");
- add_pattern<StaticLibrary>("lib%.a");
- add_pattern<StaticLibrary>("%.lib");
+ if(toolchain=="msvc")
+ {
+ add_pattern<ObjectFile>("%.obj");
+ add_pattern<ImportLibrary>("%.lib");
+ add_pattern<StaticLibrary>("%_static.lib");
+ }
+ else
+ {
+ add_pattern<ObjectFile>("%.o");
+ add_pattern<SharedLibrary>("lib%.dll");
+ add_pattern<ImportLibrary>("lib%.dll.a");
+ add_pattern<StaticLibrary>("lib%.a");
+ }
add_pattern<Executable>("%.exe");
}
else
{
+ add_pattern<ObjectFile>("%.o");
if(system=="darwin")
add_pattern<SharedLibrary>("lib%.dylib");
else
#include "datatool.h"
#include "gnutools.h"
#include "installedfile.h"
+#include "microsofttools.h"
#include "package.h"
#include "sharedlibrary.h"
#include "sourcepackage.h"
const string &arch_tc = current_arch->get_toolchain();
if(current_arch->get_system()=="android")
toolchain.add_toolchain(new AndroidTools(*this, *current_arch));
+ else if(arch_tc=="msvc")
+ toolchain.add_toolchain(new MicrosoftTools(*this, *current_arch));
else if(arch_tc=="clang")
toolchain.add_toolchain(new ClangTools(*this, *current_arch));
else if(arch_tc=="gnu")
--- /dev/null
+#include <msp/core/algorithm.h>
+#include <msp/fs/dir.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "externaltask.h"
+#include "logger.h"
+#include "microsofttools.h"
+#include "msvcarchiver.h"
+#include "msvccompiler.h"
+#include "msvclinker.h"
+#include "sysutils.h"
+
+using namespace std;
+using namespace Msp;
+
+MicrosoftTools::MicrosoftTools(Builder &builder, const Architecture &arch)
+{
+ find_vc_bin_dir(builder, arch);
+ find_windows_sdk_dir(builder);
+
+ add_tool(new MsvcCompiler(builder, arch, "CC", *this));
+ add_tool(new MsvcCompiler(builder, arch, "CXX", *this));
+ add_tool(new MsvcLinker(builder, arch, *this));
+ add_tool(new MsvcArchiver(builder, arch, *this));
+}
+
+void MicrosoftTools::find_vc_bin_dir(Builder &builder, const Architecture &arch)
+{
+ FS::Path program_files_x86 = get_program_files_x86_dir();
+
+ ExternalTask::Arguments argv;
+ argv.push_back((program_files_x86/"Microsoft Visual Studio"/"Installer"/"vswhere.exe").str());
+ argv.push_back("-latest");
+ argv.push_back("-property");
+ argv.push_back("installationPath");
+
+ builder.get_logger().log("auxcommands", format("Running %s", join(argv.begin(), argv.end())));
+
+ string output = ExternalTask::run_and_capture_output(argv, FS::Path(), true);
+ FS::Path vs_path = strip(output);
+
+ builder.get_logger().log("tools", format("Visual Studio found in %s", vs_path));
+
+ FS::Path vc_version_fn = vs_path/"VC"/"Auxiliary"/"Build"/"Microsoft.VCToolsVersion.v142.default.txt";
+ builder.get_logger().log("files", format("Reading %s", vc_version_fn));
+ char buffer[256];
+ unsigned len = IO::File(vc_version_fn.str()).read(buffer, sizeof(buffer));
+ string vc_version = strip(string(buffer, len));
+
+ builder.get_logger().log("tools", format("Detected MSVC version %s", vc_version));
+
+ const Architecture &native_arch = builder.get_native_arch();
+ string host = (native_arch.get_bits()==64 ? "Hostx64" : "Hostx86");
+ string target = (arch.get_bits()==64 ? "x64" : "x86");
+
+ vc_base_dir = vs_path/"VC"/"Tools"/"MSVC"/vc_version;
+ vc_bin_dir = vc_base_dir/"bin"/host/target;
+}
+
+void MicrosoftTools::find_windows_sdk_dir(Builder &builder)
+{
+ win_sdk_dir = get_registry_value<string>("HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0\\InstallationFolder");
+ if(win_sdk_dir.empty())
+ win_sdk_dir = get_program_files_x86_dir()/"Windows Kits"/"10";
+
+ builder.get_logger().log("files", format("Traversing %s", win_sdk_dir/"include"));
+ vector<string> sdk_versions = FS::list_filtered(win_sdk_dir/"include", "^10\\.");
+ if(sdk_versions.empty())
+ {
+ builder.get_logger().log("problems", "No Windows SDK versions found");
+ return;
+ }
+
+ sort(sdk_versions);
+ win_sdk_version = sdk_versions.back();
+
+ builder.get_logger().log("tools", format("Windows SDK version %s found in %s", win_sdk_version, win_sdk_dir));
+}
--- /dev/null
+#ifndef MICROSOFTTOOLS_H_
+#define MICROSOFTTOOLS_H_
+
+#include <msp/fs/path.h>
+#include "toolchain.h"
+
+class Architecture;
+class Builder;
+
+class MicrosoftTools: public Toolchain
+{
+private:
+ Msp::FS::Path vc_base_dir;
+ Msp::FS::Path vc_bin_dir;
+ Msp::FS::Path win_sdk_dir;
+ std::string win_sdk_version;
+
+public:
+ MicrosoftTools(Builder &, const Architecture &);
+
+private:
+ void find_vc_bin_dir(Builder &, const Architecture &);
+ void find_windows_sdk_dir(Builder &);
+
+public:
+ const Msp::FS::Path &get_vc_base_dir() const { return vc_base_dir; }
+ const Msp::FS::Path &get_vc_bin_dir() const { return vc_bin_dir; }
+ const Msp::FS::Path &get_windows_sdk_dir() const { return win_sdk_dir; }
+ const std::string &get_windows_sdk_version() const { return win_sdk_version; }
+};
+
+#endif
--- /dev/null
+#include <msp/fs/utils.h>
+#include "component.h"
+#include "externaltask.h"
+#include "microsofttools.h"
+#include "msvcarchiver.h"
+#include "objectfile.h"
+#include "sourcepackage.h"
+#include "staticlibrary.h"
+
+using namespace std;
+using namespace Msp;
+
+MsvcArchiver::MsvcArchiver(Builder &b, const Architecture &a, const MicrosoftTools &m):
+ Tool(b, a, "AR"),
+ ms_tools(m)
+{
+ input_suffixes.push_back(".o");
+ processing_unit = COMPONENT;
+ set_command((ms_tools.get_vc_bin_dir()/"lib.exe").str(), false);
+}
+
+Target *MsvcArchiver::create_target(const list<Target *> &sources, const string &)
+{
+ if(sources.empty())
+ throw invalid_argument("MsvcArchiver::create_target");
+
+ list<ObjectFile *> objs;
+ for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+ {
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+ objs.push_back(obj);
+ else
+ throw invalid_argument("MsvcArchiver::create_target");
+ }
+
+ const Component &comp = *objs.front()->get_component();
+ StaticLibrary *lib = new StaticLibrary(builder, comp, objs);
+ lib->set_tool(*this);
+ return lib;
+}
+
+string MsvcArchiver::create_build_signature(const BuildInfo &) const
+{
+ return FS::basename(executable->get_path());
+}
+
+Task *MsvcArchiver::run(const Target &target) const
+{
+ const StaticLibrary &lib = dynamic_cast<const StaticLibrary &>(target);
+ const Component &comp = *lib.get_component();
+
+ vector<string> argv;
+ argv.push_back(executable->get_path().str());
+ argv.push_back("/NOLOGO");
+
+ FS::Path work_dir = comp.get_package().get_source_directory();
+
+ argv.push_back("/OUT:"+relative(lib.get_path(), work_dir).str());
+
+ const Target::Dependencies &deps = lib.get_dependencies();
+ for(Target::Dependencies::const_iterator i=deps.begin(); i!=deps.end(); ++i)
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+ argv.push_back(relative(obj->get_path(), work_dir).str());
+
+ return new ExternalTask(argv, work_dir);
+}
--- /dev/null
+#ifndef MSVCARCHIVER_H_
+#define MSVCARCHIVER_H_
+
+#include "tool.h"
+
+class MicrosoftTools;
+
+class MsvcArchiver: public Tool
+{
+private:
+ const MicrosoftTools &ms_tools;
+
+public:
+ MsvcArchiver(Builder &, const Architecture &, const MicrosoftTools &);
+
+ virtual Target *create_target(const std::list<Target *> &, const std::string &);
+ virtual std::string create_build_signature(const BuildInfo &) const;
+
+ virtual Task *run(const Target &) const;
+};
+
+#endif
--- /dev/null
+#include <msp/core/environ.h>
+#include <msp/core/maputils.h>
+#include <msp/fs/utils.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "csourcefile.h"
+#include "externaltask.h"
+#include "microsofttools.h"
+#include "msvccompiler.h"
+#include "objectfile.h"
+#include "sourcepackage.h"
+
+using namespace std;
+using namespace Msp;
+
+MsvcCompiler::MsvcCompiler(Builder &b, const Architecture &a, const string &t, const MicrosoftTools &m):
+ Tool(b, a, t),
+ ms_tools(m)
+{
+ if(tag=="CC")
+ {
+ input_suffixes.push_back(".c");
+ aux_suffixes.push_back(".h");
+ }
+ else if(tag=="CXX")
+ {
+ input_suffixes.push_back(".cpp");
+ input_suffixes.push_back(".cc");
+ aux_suffixes.push_back(".hpp");
+ }
+ else
+ throw invalid_argument("MsvcCompiler::MsvcCompiler");
+
+ set_command((ms_tools.get_vc_bin_dir()/"cl.exe").str(), false);
+}
+
+Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const
+{
+ return new CSourceFile(builder, comp, path);
+}
+
+Target *MsvcCompiler::create_source(const FS::Path &path) const
+{
+ return new CSourceFile(builder, path);
+}
+
+Target *MsvcCompiler::create_target(const list<Target *> &sources, const string &)
+{
+ if(sources.size()!=1)
+ throw invalid_argument("MsvcCompiler::create_target");
+ SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
+ ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
+ obj->set_tool(*this);
+ return obj;
+}
+
+string MsvcCompiler::create_build_signature(const BuildInfo &binfo) const
+{
+ string result = FS::basename(executable->get_path());
+ result += ',';
+ if(binfo.debug)
+ result += 'g';
+ if(binfo.optimize)
+ {
+ result += 'O';
+ result += (binfo.optimize<0 ? '1' : binfo.optimize==1 ? 'x' : '2');
+ }
+ if(binfo.libmode<=BuildInfo::STATIC)
+ result += 't';
+ return result;
+}
+
+void MsvcCompiler::do_prepare()
+{
+ const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
+ system_path.push_back(vc_base_dir/"include");
+
+ const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
+ const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
+ system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"ucrt");
+ system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"shared");
+ system_path.push_back(win_sdk_dir/"include"/win_sdk_ver/"um");
+
+ string path;
+ for(SearchPath::const_iterator i=system_path.begin(); i!=system_path.end(); ++i)
+ {
+ append(path, ";", i->str());
+ builder.get_logger().log("tools", format("Got %s system path: %s", tag, *i));
+ }
+
+ setenv("INCLUDE", path);
+}
+
+Task *MsvcCompiler::run(const Target &target) const
+{
+ const ObjectFile &object = dynamic_cast<const ObjectFile &>(target);
+
+ ExternalTask::Arguments argv;
+ argv.push_back(executable->get_path().str());
+ argv.push_back("/nologo");
+ argv.push_back("/c");
+
+ BuildInfo binfo;
+ target.collect_build_info(binfo);
+
+ if(binfo.standards.count(tag))
+ {
+ string std = get_item(binfo.standards, tag);
+ if(std!="c++11" && std!="c99")
+ argv.push_back("/std:"+std);
+ }
+
+ if(binfo.warning_level>=1)
+ {
+ argv.push_back(format("/W%d", binfo.warning_level));
+ if(binfo.fatal_warnings)
+ argv.push_back("/WX");
+ if(binfo.warning_level>=3)
+ argv.push_back("/permissive-");
+
+ argv.push_back("/wd4068"); // Unknown pragma
+ if(binfo.warning_level<4)
+ {
+ argv.push_back("/wd4244"); // Narrowing conversion on arg or return
+ argv.push_back("/wd4267"); // Narrowing conversion
+ }
+ }
+ else
+ argv.push_back("/w");
+
+ for(BuildInfo::PathList::const_iterator i=binfo.local_incpath.begin(); i!=binfo.local_incpath.end(); ++i)
+ {
+ argv.push_back("/I");
+ argv.push_back(i->str());
+ }
+ for(BuildInfo::PathList::const_iterator i=binfo.incpath.begin(); i!=binfo.incpath.end(); ++i)
+ {
+ argv.push_back("/I");
+ argv.push_back(i->str());
+ }
+
+ for(BuildInfo::DefineMap::const_iterator i=binfo.defines.begin(); i!=binfo.defines.end(); ++i)
+ {
+ argv.push_back("/D");
+ if(i->second.empty())
+ argv.push_back(i->first);
+ else
+ argv.push_back(format("%s=%s", i->first, i->second));
+ }
+
+ if(binfo.debug)
+ argv.push_back("/Z7");
+ if(binfo.optimize)
+ {
+ if(binfo.optimize<0)
+ argv.push_back("/O1");
+ else if(binfo.optimize==1)
+ argv.push_back("/Ox");
+ else
+ argv.push_back("/O2");
+ }
+
+ if(binfo.libmode<=BuildInfo::STATIC)
+ argv.push_back(binfo.debug ? "/MTd" : "/MT");
+ else
+ argv.push_back(binfo.debug ? "/MDd" : "/MD");
+
+ argv.push_back("/EHsc");
+
+ FS::Path obj_path = object.get_path();
+ FS::Path src_path = object.get_source().get_path();
+ FS::Path work_dir = object.get_component()->get_package().get_source_directory();
+
+ argv.push_back("/Fo"+relative(obj_path, work_dir).str());
+ argv.push_back(relative(src_path, work_dir).str());
+
+ return new ExternalTask(argv, work_dir);
+}
--- /dev/null
+#ifndef MSVCCOMPILER_H_
+#define MSVCCOMPILER_H_
+
+#include "tool.h"
+
+class MicrosoftTools;
+
+class MsvcCompiler: public Tool
+{
+private:
+ const MicrosoftTools &ms_tools;
+
+public:
+ MsvcCompiler(Builder &, const Architecture &, const std::string &, const MicrosoftTools &);
+
+ virtual Target *create_source(const Component &, const Msp::FS::Path &) const;
+ virtual Target *create_source(const Msp::FS::Path &) const;
+ virtual Target *create_target(const std::list<Target *> &, const std::string &);
+ virtual std::string create_build_signature(const BuildInfo &) const;
+
+protected:
+ virtual void do_prepare();
+
+public:
+ virtual Task *run(const Target &) const;
+};
+
+#endif
--- /dev/null
+#include <msp/core/environ.h>
+#include <msp/fs/utils.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+#include "builder.h"
+#include "component.h"
+#include "executable.h"
+#include "externaltask.h"
+#include "importlibrary.h"
+#include "microsofttools.h"
+#include "msvclinker.h"
+#include "objectfile.h"
+#include "sharedlibrary.h"
+#include "sourcepackage.h"
+#include "staticlibrary.h"
+
+using namespace std;
+using namespace Msp;
+
+MsvcLinker::MsvcLinker(Builder &b, const Architecture &a, const MicrosoftTools &m):
+ Tool(b, a, "LINK"),
+ ms_tools(m)
+{
+ input_suffixes.push_back(".o");
+ input_suffixes.push_back(".a");
+
+ processing_unit = COMPONENT;
+
+ set_command((ms_tools.get_vc_bin_dir()/"link.exe").str(), false);
+}
+
+Target *MsvcLinker::create_target(const list<Target *> &sources, const string &arg)
+{
+ if(sources.empty())
+ throw invalid_argument("MsvcLinker::create_target");
+
+ list<ObjectFile *> objs;
+ for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+ {
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(*i))
+ objs.push_back(obj);
+ else
+ throw invalid_argument("MsvcLinker::create_target");
+ }
+
+ const Component &comp = *objs.front()->get_component();
+ Binary *bin = 0;
+ if(arg=="shared")
+ bin = new SharedLibrary(builder, comp, objs);
+ else
+ bin = new Executable(builder, comp, objs);
+ bin->set_tool(*this);
+ return bin;
+}
+
+string MsvcLinker::create_build_signature(const BuildInfo &binfo) const
+{
+ string result = FS::basename(executable->get_path());
+ result += ',';
+ if(binfo.strip)
+ result += 's';
+ if(!binfo.libs.empty())
+ {
+ result += ",l";
+ result += join(binfo.libs.begin(), binfo.libs.end(), ",l");
+ }
+ return result;
+}
+
+void MsvcLinker::do_prepare()
+{
+ string arch_dir = (architecture->get_bits()==64 ? "x64" : "x86");
+
+ const FS::Path &vc_base_dir = ms_tools.get_vc_base_dir();
+ system_path.push_back(vc_base_dir/"lib"/arch_dir);
+
+ const FS::Path &win_sdk_dir = ms_tools.get_windows_sdk_dir();
+ const string &win_sdk_ver = ms_tools.get_windows_sdk_version();
+ system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"ucrt"/arch_dir);
+ system_path.push_back(win_sdk_dir/"lib"/win_sdk_ver/"um"/arch_dir);
+
+ string path;
+ for(SearchPath::const_iterator i=system_path.begin(); i!=system_path.end(); ++i)
+ {
+ append(path, ";", i->str());
+ builder.get_logger().log("tools", format("Got %s system path: %s", tag, *i));
+ }
+
+ setenv("LIB", path);
+}
+
+Task *MsvcLinker::run(const Target &target) const
+{
+ const Binary &bin = dynamic_cast<const Binary &>(target);
+
+ vector<string> argv;
+ argv.push_back(executable->get_path().str());
+ argv.push_back("/NOLOGO");
+
+ FS::Path work_dir = bin.get_component()->get_package().get_source_directory();
+
+ if(dynamic_cast<const SharedLibrary *>(&bin))
+ argv.push_back("/DLL");
+
+ BuildInfo binfo;
+ target.collect_build_info(binfo);
+
+ /*for(BuildInfo::PathList::const_iterator i=binfo.libpath.begin(); i!=binfo.libpath.end(); ++i)
+ argv.push_back("/LIBPATH:"+i->str());*/
+ if(binfo.strip)
+ argv.push_back("/INCREMENTAL:NO");
+ else
+ argv.push_back("/DEBUG:FULL");
+
+ argv.push_back("/OUT:"+relative(bin.get_path(), work_dir).str());
+
+ const Target::Dependencies &depends = target.get_dependencies();
+ for(Target::Dependencies::const_iterator i=depends.begin(); i!=depends.end(); ++i)
+ {
+ FileTarget *file = dynamic_cast<FileTarget *>(*i);
+ Target *tgt = (*i)->get_real_target();
+
+ if(ObjectFile *obj = dynamic_cast<ObjectFile *>(tgt))
+ argv.push_back(relative(obj->get_path(), work_dir).str());
+ else if(StaticLibrary *stlib = dynamic_cast<StaticLibrary *>(tgt))
+ argv.push_back((file?file:stlib)->get_path().str());
+ else if(ImportLibrary *imp = dynamic_cast<ImportLibrary *>(tgt))
+ argv.push_back((file?file:imp)->get_path().str());
+ }
+
+ argv.push_back("/SUBSYSTEM:CONSOLE");
+
+ return new ExternalTask(argv, work_dir);
+}
--- /dev/null
+#ifndef MSVCLINKER_H_
+#define MSVCLINKER_H_
+
+#include "tool.h"
+
+class MicrosoftTools;
+
+class MsvcLinker: public Tool
+{
+private:
+ const MicrosoftTools &ms_tools;
+
+public:
+ MsvcLinker(Builder &, const Architecture &, const MicrosoftTools &);
+
+ virtual Target *create_target(const std::list<Target *> &, const std::string &);
+ virtual std::string create_build_signature(const BuildInfo &) const;
+
+protected:
+ virtual void do_prepare();
+
+public:
+ virtual Task *run(const Target &) const;
+};
+
+#endif
+#define _WIN32_WINNT _WIN32_WINNT_VISTA
#define WIN32_LEAN_AND_MEAN
+#define INITGUID
#ifdef _WIN32
#include <windows.h>
+#include <shlobj.h>
+#include <knownfolders.h>
#else
#include <sys/utsname.h>
#endif
+#include <msp/core/systemerror.h>
+#include <msp/stringcodec/utf16.h>
+#include <msp/stringcodec/utf8.h>
#include <msp/strings/format.h>
#include <msp/strings/utils.h>
#include "sysutils.h"
return string();
}
+
+FS::Path get_program_files_x86_dir()
+{
+#ifdef _WIN32
+ wchar_t *program_files_x86_ptr = 0;
+ HRESULT err = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, 0, NULL, &program_files_x86_ptr);
+ if(err!=S_OK)
+ throw runtime_error("Can't get Program Files path");
+
+ unsigned len = wcslen(program_files_x86_ptr);
+ FS::Path program_files_x86 = StringCodec::transcode<StringCodec::Utf16Le, StringCodec::Utf8>(
+ string(reinterpret_cast<const char *>(program_files_x86_ptr), len*sizeof(wchar_t)));
+
+ CoTaskMemFree(program_files_x86_ptr);
+
+ return program_files_x86;
+#else
+ return "/mnt/c/Program Files (x86)";
+#endif
+}
+
+template<>
+string get_registry_value<string>(const string &path)
+{
+#ifdef _WIN32
+ string::size_type first_sep = path.find('\\');
+ string::size_type last_sep = path.rfind('\\');
+ string root = path.substr(0, first_sep);
+ string key_path = path.substr(first_sep+1, last_sep-first_sep-1);
+ string value_name = path.substr(last_sep+1);
+
+ HKEY root_handle;
+ if(root=="HKCR")
+ root_handle = HKEY_CLASSES_ROOT;
+ else if(root=="HKCC")
+ root_handle = HKEY_CURRENT_CONFIG;
+ else if(root=="HKCU")
+ root_handle = HKEY_CURRENT_USER;
+ else if(root=="HKLM")
+ root_handle = HKEY_LOCAL_MACHINE;
+ else if(root=="HKU")
+ root_handle = HKEY_USERS;
+ else
+ throw invalid_argument("get_registry_value");
+
+ HKEY key;
+ LSTATUS err = RegOpenKeyEx(root_handle, key_path.c_str(), 0, KEY_READ, &key);
+ if(err!=ERROR_SUCCESS)
+ throw Msp::system_error("RegOpenKey", err);
+
+ DWORD value_len;
+ err = RegGetValue(key, 0, value_name.c_str(), RRF_RT_REG_SZ, 0, 0, &value_len);
+ if(err!=ERROR_SUCCESS)
+ throw Msp::system_error("RegGetValue", err);
+
+ char *buffer = new char[value_len];
+ err = RegGetValue(key, 0, value_name.c_str(), RRF_RT_REG_SZ, 0, buffer, &value_len);
+ if(err!=ERROR_SUCCESS)
+ {
+ delete[] buffer;
+ throw Msp::system_error("RegGetValue", err);
+ }
+
+ string result(buffer);
+ delete[] buffer;
+ return result;
+#else
+ (void)path;
+ return string();
+#endif
+}
#define SYSUTILS_H_
#include <string>
+#include <msp/fs/path.h>
std::string get_system_type();
+Msp::FS::Path get_program_files_x86_dir();
+
+template<typename T>
+T get_registry_value(const std::string &);
#endif