[XML2SDB] Add basic support for including/excluding shims based on platform

CORE-20159
This commit is contained in:
Mark Jansen
2025-11-25 19:32:02 +01:00
parent eb18696e72
commit 06983e3967
7 changed files with 280 additions and 195 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
/*
* PROJECT: ReactOS Application compatibility module
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Shim database string table builder
* COPYRIGHT: Copyright 2016-2019 Mark Jansen ([email protected])
* COPYRIGHT: Copyright 2016-2025 Mark Jansen <[email protected]>
*/
#if !defined(SDBWRITE_HOSTTOOL)
+1 -1
View File
@@ -4,7 +4,7 @@
* PURPOSE: Shim database manipulation functions
* COPYRIGHT: Copyright 2011 André Hentschel
* Copyright 2013 Mislav Blažević
* Copyright 2015-2019 Mark Jansen ([email protected])
* Copyright 2015-2025 Mark Jansen <[email protected]>
*/
#if !defined(SDBWRITE_HOSTTOOL)
+1 -1
View File
@@ -1,6 +1,6 @@
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sysmain.sdb
COMMAND native-xml2sdb -i ${CMAKE_CURRENT_SOURCE_DIR}/sysmain.xml -o ${CMAKE_CURRENT_BINARY_DIR}/sysmain.sdb
COMMAND native-xml2sdb -p ${ARCH} -i ${CMAKE_CURRENT_SOURCE_DIR}/sysmain.xml -o ${CMAKE_CURRENT_BINARY_DIR}/sysmain.sdb
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sysmain.xml native-xml2sdb)
add_custom_target(compatdb DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/sysmain.sdb)
-1
View File
@@ -1,7 +1,6 @@
<SDB>
<DATABASE>
<NAME>ReactOS compatibility fix database</NAME>
<OS_PLATFORM >1</OS_PLATFORM>
<DATABASE_ID>{11111111-1111-1111-1111-111111111111}</DATABASE_ID>
<LIBRARY>
<INCLUDE MODULE="kernel32.dll" />
+37 -14
View File
@@ -1,8 +1,8 @@
/*
* PROJECT: xml2sdb
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Implement platform agnostic read / write / allocation functions, parse commandline
* COPYRIGHT: Copyright 2016,2017 Mark Jansen ([email protected])
* COPYRIGHT: Copyright 2016-2025 Mark Jansen <[email protected]>
*/
#include "xml2sdb.h"
@@ -174,14 +174,20 @@ VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970,
}
bool xml_2_db(const char* xml, const WCHAR* sdb);
static bool run_one(std::string& input, std::string& output)
static bool convert(const std::string& input, const std::string& output, PlatformType platform)
{
sdbstring outputW(output.begin(), output.end());
if (!xml_2_db(input.c_str(), outputW.c_str()))
Database db;
if (!db.fromXml(input.c_str(), platform))
{
printf("Failed to read XML file '%s'\n", input.c_str());
return false;
input = output = "";
}
if (!db.toSdb(outputW.c_str()))
{
printf("Failed to write SDB file '%s'\n", output.c_str());
return false;
}
return true;
}
@@ -202,9 +208,16 @@ static void update_loglevel(int argc, char* argv[], int& i)
g_ShimDebugLevel = strtoul(value.c_str(), NULL, 10);
}
static PlatformType
parse_platform(const std::string &input)
{
return (PlatformType)str_to_enum(input, platform_to_flag);
}
int main(int argc, char * argv[])
{
std::string input, output;
PlatformType platform = PLATFORM_ANY;
srand(time(0));
for (int i = 1; i < argc; ++i)
@@ -223,15 +236,25 @@ int main(int argc, char * argv[])
case 'l':
update_loglevel(argc, argv, i);
break;
case 'p':
platform = parse_platform(get_strarg(argc, argv, i));
break;
}
if (input.empty() || output.empty())
continue;
}
if (input.empty() || output.empty())
{
printf("Usage: %s -i <input.xml> -o <output.sdb> [-l <loglevel>] [-v <version>]\n", argv[0]);
printf(" -i <input.xml> : Input XML file to convert\n");
printf(" -o <output.sdb> : Output SDB file to create\n");
printf(" -l <loglevel> : Set log level (1=ERR, 2=WARN, 3=INFO)\n");
printf(" -p <platform> : Set the runtime platform (X86, AMD64, ANY)\n");
return 1;
}
if (!run_one(input, output))
{
printf("Failed converting '%s' to '%s'\n", input.c_str(), output.c_str());
return 1;
}
if (!convert(input, output, platform))
{
printf("Failed converting '%s' to '%s'\n", input.c_str(), output.c_str());
return 1;
}
return 0;
}
+169 -117
View File
@@ -1,8 +1,8 @@
/*
* PROJECT: xml2sdb
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Conversion functions from xml -> db
* COPYRIGHT: Copyright 2016-2018 Mark Jansen ([email protected])
* COPYRIGHT: Copyright 2016-2025 Mark Jansen <[email protected]>
*/
#include "xml2sdb.h"
@@ -10,11 +10,12 @@
#include "tinyxml2.h"
#include <time.h>
#include <algorithm>
#include <sstream>
using tinyxml2::XMLText;
static const GUID GUID_NULL = { 0 };
static const char szCompilerVersion[] = "1.7.0.1";
static const char szCompilerVersion[] = "1.8.0.0";
#if !defined(C_ASSERT)
#define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1]
@@ -38,6 +39,36 @@ VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970,
/***********************************************************************
* Helper functions
*/
str_to_flag platform_to_flag[] = {
{"X86", PLATFORM_X86},
{"I386", PLATFORM_X86},
{"AMD64", PLATFORM_AMD64},
{"ANY", PLATFORM_ANY},
{nullptr, 0},
};
DWORD
str_to_enum(const std::string& str, const str_to_flag* table)
{
DWORD value = 0;
std::istringstream iss(str);
std::string item;
while (std::getline(iss, item, ','))
{
std::string trimmedItem = item;
trimmedItem.erase(remove_if(trimmedItem.begin(), trimmedItem.end(), isspace), trimmedItem.end());
std::transform(trimmedItem.begin(), trimmedItem.end(), trimmedItem.begin(), ::toupper);
for (const str_to_flag* p = table; p->name; ++p)
{
if (trimmedItem == p->name)
{
value |= p->flag;
break;
}
}
}
return value;
}
// Convert utf8 to utf16:
@@ -105,6 +136,15 @@ DWORD ReadDWordNode(XMLHandle dbNode, const char* nodeName)
return static_cast<DWORD>(ReadQWordNode(dbNode, nodeName));
}
PlatformType ReadPlatformNode(XMLHandle dbNode, const char *nodeName)
{
std::string value = ReadStringNode(dbNode, nodeName);
if (value.empty())
return PLATFORM_ANY;
DWORD platform = str_to_enum(value, platform_to_flag);
return static_cast<PlatformType>(platform);
}
unsigned char char2byte(char hexChar, bool* success = NULL)
{
if (hexChar >= '0' && hexChar <= '9')
@@ -253,13 +293,13 @@ bool InExclude::fromXml(XMLHandle dbNode)
return false;
}
bool InExclude::toSdb(PDB pdb, Database& db)
bool InExclude::toSdb(Database& db)
{
TAGID tagid = db.BeginWriteListTag(pdb, TAG_INEXCLUD);
db.WriteString(pdb, TAG_MODULE, Module, true);
TAGID tagid = db.BeginWriteListTag(TAG_INEXCLUD);
db.WriteString(TAG_MODULE, Module, true);
if (Include)
SdbWriteNULLTag(pdb, TAG_INCLUDE);
return !!db.EndWriteListTag(pdb, tagid);
db.WriteNull(TAG_INCLUDE);
return !!db.EndWriteListTag(tagid);
}
@@ -278,11 +318,25 @@ void ReadGeneric(XMLHandle dbNode, std::list<T>& result, const char* nodeName)
}
template<typename T>
bool WriteGeneric(PDB pdb, std::list<T>& data, Database& db)
void ReadGeneric(XMLHandle dbNode, std::list<T>& result, const char* nodeName, PlatformType platform)
{
XMLHandle node = dbNode.FirstChildElement(nodeName);
while (node.ToNode())
{
T object;
if (object.fromXml(node) && ((object.Platform & platform) != PLATFORM_NONE))
result.push_back(object);
node = node.NextSiblingElement(nodeName);
}
}
template<typename T>
bool WriteGeneric(std::list<T>& data, Database& db)
{
for (typename std::list<T>::iterator it = data.begin(); it != data.end(); ++it)
{
if (!it->toSdb(pdb, db))
if (!it->toSdb(db))
return false;
}
return true;
@@ -302,16 +356,16 @@ bool ShimRef::fromXml(XMLHandle dbNode)
return !Name.empty();
}
bool ShimRef::toSdb(PDB pdb, Database& db)
bool ShimRef::toSdb(Database& db)
{
TAGID tagid = db.BeginWriteListTag(pdb, TAG_SHIM_REF);
db.WriteString(pdb, TAG_NAME, Name, true);
db.WriteString(pdb, TAG_COMMAND_LINE, CommandLine);
TAGID tagid = db.BeginWriteListTag(TAG_SHIM_REF);
db.WriteString(TAG_NAME, Name, true);
db.WriteString(TAG_COMMAND_LINE, CommandLine);
if (!ShimTagid)
ShimTagid = db.FindShimTagid(Name);
SdbWriteDWORDTag(pdb, TAG_SHIM_TAGID, ShimTagid);
return !!db.EndWriteListTag(pdb, tagid);
db.WriteDWord(TAG_SHIM_TAGID, ShimTagid);
return !!db.EndWriteListTag(tagid);
}
@@ -326,15 +380,15 @@ bool FlagRef::fromXml(XMLHandle dbNode)
return !Name.empty();
}
bool FlagRef::toSdb(PDB pdb, Database& db)
bool FlagRef::toSdb(Database& db)
{
TAGID tagid = db.BeginWriteListTag(pdb, TAG_FLAG_REF);
db.WriteString(pdb, TAG_NAME, Name, true);
TAGID tagid = db.BeginWriteListTag(TAG_FLAG_REF);
db.WriteString(TAG_NAME, Name, true);
if (!FlagTagid)
FlagTagid = db.FindFlagTagid(Name);
SdbWriteDWORDTag(pdb, TAG_FLAG_TAGID, FlagTagid);
return !!db.EndWriteListTag(pdb, tagid);
db.WriteDWord(TAG_FLAG_TAGID, FlagTagid);
return !!db.EndWriteListTag(tagid);
}
@@ -354,18 +408,18 @@ bool Shim::fromXml(XMLHandle dbNode)
return !Name.empty() && !DllFile.empty();
}
bool Shim::toSdb(PDB pdb, Database& db)
bool Shim::toSdb(Database& db)
{
Tagid = db.BeginWriteListTag(pdb, TAG_SHIM);
Tagid = db.BeginWriteListTag(TAG_SHIM);
db.InsertShimTagid(Name, Tagid);
db.WriteString(pdb, TAG_NAME, Name);
db.WriteString(pdb, TAG_DLLFILE, DllFile);
db.WriteString(TAG_NAME, Name);
db.WriteString(TAG_DLLFILE, DllFile);
if (IsEmptyGuid(FixID))
RandomGuid(FixID);
db.WriteBinary(pdb, TAG_FIX_ID, FixID);
if (!WriteGeneric(pdb, InExcludes, db))
db.WriteBinary(TAG_FIX_ID, FixID);
if (!WriteGeneric(InExcludes, db))
return false;
return !!db.EndWriteListTag(pdb, Tagid);
return !!db.EndWriteListTag(Tagid);
}
@@ -384,17 +438,17 @@ bool Flag::fromXml(XMLHandle dbNode)
return !Name.empty();
}
bool Flag::toSdb(PDB pdb, Database& db)
bool Flag::toSdb(Database& db)
{
Tagid = db.BeginWriteListTag(pdb, TAG_FLAG);
Tagid = db.BeginWriteListTag(TAG_FLAG);
db.InsertFlagTagid(Name, Tagid);
db.WriteString(pdb, TAG_NAME, Name, true);
db.WriteString(TAG_NAME, Name, true);
db.WriteQWord(pdb, TAG_FLAG_MASK_KERNEL, KernelFlags);
db.WriteQWord(pdb, TAG_FLAG_MASK_USER, UserFlags);
db.WriteQWord(pdb, TAG_FLAG_PROCESSPARAM, ProcessParamFlags);
db.WriteQWord(TAG_FLAG_MASK_KERNEL, KernelFlags);
db.WriteQWord(TAG_FLAG_MASK_USER, UserFlags);
db.WriteQWord(TAG_FLAG_PROCESSPARAM, ProcessParamFlags);
return !!db.EndWriteListTag(pdb, Tagid);
return !!db.EndWriteListTag(Tagid);
}
@@ -437,28 +491,28 @@ bool Data::fromXml(XMLHandle dbNode)
return false;
}
bool Data::toSdb(PDB pdb, Database& db)
bool Data::toSdb(Database& db)
{
Tagid = db.BeginWriteListTag(pdb, TAG_DATA);
db.WriteString(pdb, TAG_NAME, Name, true);
db.WriteDWord(pdb, TAG_DATA_VALUETYPE, DataType, true);
Tagid = db.BeginWriteListTag(TAG_DATA);
db.WriteString(TAG_NAME, Name, true);
db.WriteDWord(TAG_DATA_VALUETYPE, DataType, true);
switch (DataType)
{
case REG_SZ:
db.WriteString(pdb, TAG_DATA_STRING, StringData);
db.WriteString(TAG_DATA_STRING, StringData);
break;
case REG_DWORD:
db.WriteDWord(pdb, TAG_DATA_DWORD, DWordData);
db.WriteDWord(TAG_DATA_DWORD, DWordData);
break;
case REG_QWORD:
db.WriteQWord(pdb, TAG_DATA_QWORD, QWordData);
db.WriteQWord(TAG_DATA_QWORD, QWordData);
break;
default:
SHIM_ERR("Data node (%s) with unknown type (0x%x)\n", Name.c_str(), DataType);
return false;
}
return !!db.EndWriteListTag(pdb, Tagid);
return !!db.EndWriteListTag(Tagid);
}
/***********************************************************************
@@ -474,17 +528,17 @@ bool Layer::fromXml(XMLHandle dbNode)
return true;
}
bool Layer::toSdb(PDB pdb, Database& db)
bool Layer::toSdb(Database& db)
{
Tagid = db.BeginWriteListTag(pdb, TAG_LAYER);
db.WriteString(pdb, TAG_NAME, Name, true);
if (!WriteGeneric(pdb, ShimRefs, db))
Tagid = db.BeginWriteListTag(TAG_LAYER);
db.WriteString(TAG_NAME, Name, true);
if (!WriteGeneric(ShimRefs, db))
return false;
if (!WriteGeneric(pdb, FlagRefs, db))
if (!WriteGeneric(FlagRefs, db))
return false;
if (!WriteGeneric(pdb, Datas, db))
if (!WriteGeneric(Datas, db))
return false;
return !!db.EndWriteListTag(pdb, Tagid);
return !!db.EndWriteListTag(Tagid);
}
@@ -512,30 +566,30 @@ bool MatchingFile::fromXml(XMLHandle dbNode)
return true;
}
bool MatchingFile::toSdb(PDB pdb, Database& db)
bool MatchingFile::toSdb(Database& db)
{
TAGID tagid = db.BeginWriteListTag(pdb, TAG_MATCHING_FILE);
TAGID tagid = db.BeginWriteListTag(TAG_MATCHING_FILE);
db.WriteString(pdb, TAG_NAME, Name, true);
db.WriteDWord(pdb, TAG_SIZE, Size);
db.WriteDWord(pdb, TAG_CHECKSUM, Checksum);
db.WriteString(pdb, TAG_COMPANY_NAME, CompanyName);
db.WriteString(pdb, TAG_INTERNAL_NAME, InternalName);
db.WriteString(pdb, TAG_PRODUCT_NAME, ProductName);
db.WriteString(pdb, TAG_PRODUCT_VERSION, ProductVersion);
db.WriteString(pdb, TAG_FILE_VERSION, FileVersion);
db.WriteString(TAG_NAME, Name, true);
db.WriteDWord(TAG_SIZE, Size);
db.WriteDWord(TAG_CHECKSUM, Checksum);
db.WriteString(TAG_COMPANY_NAME, CompanyName);
db.WriteString(TAG_INTERNAL_NAME, InternalName);
db.WriteString(TAG_PRODUCT_NAME, ProductName);
db.WriteString(TAG_PRODUCT_VERSION, ProductVersion);
db.WriteString(TAG_FILE_VERSION, FileVersion);
if (!BinFileVersion.empty())
SHIM_ERR("TAG_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_BIN_FILE_VERSION, BinFileVersion);
db.WriteDWord(pdb, TAG_LINK_DATE, LinkDate);
SHIM_ERR("TAG_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(TAG_BIN_FILE_VERSION, BinFileVersion);
db.WriteDWord(TAG_LINK_DATE, LinkDate);
if (!VerLanguage.empty())
SHIM_ERR("TAG_VER_LANGUAGE Unimplemented\n"); //db.WriteDWord(pdb, TAG_VER_LANGUAGE, VerLanguage);
db.WriteString(pdb, TAG_FILE_DESCRIPTION, FileDescription);
db.WriteString(pdb, TAG_ORIGINAL_FILENAME, OriginalFilename);
SHIM_ERR("TAG_VER_LANGUAGE Unimplemented\n"); //db.WriteDWord(TAG_VER_LANGUAGE, VerLanguage);
db.WriteString(TAG_FILE_DESCRIPTION, FileDescription);
db.WriteString(TAG_ORIGINAL_FILENAME, OriginalFilename);
if (!UptoBinFileVersion.empty())
SHIM_ERR("TAG_UPTO_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_UPTO_BIN_FILE_VERSION, UptoBinFileVersion);
db.WriteDWord(pdb, TAG_LINKER_VERSION, LinkerVersion);
SHIM_ERR("TAG_UPTO_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(TAG_UPTO_BIN_FILE_VERSION, UptoBinFileVersion);
db.WriteDWord(TAG_LINKER_VERSION, LinkerVersion);
return !!db.EndWriteListTag(pdb, tagid);
return !!db.EndWriteListTag(tagid);
}
@@ -555,30 +609,32 @@ bool Exe::fromXml(XMLHandle dbNode)
ReadGeneric(dbNode, ShimRefs, "SHIM_REF");
ReadGeneric(dbNode, FlagRefs, "FLAG_REF");
Platform = ReadPlatformNode(dbNode, "RUNTIME_PLATFORM");
return !Name.empty();
}
bool Exe::toSdb(PDB pdb, Database& db)
bool Exe::toSdb(Database& db)
{
Tagid = db.BeginWriteListTag(pdb, TAG_EXE);
Tagid = db.BeginWriteListTag(TAG_EXE);
db.WriteString(pdb, TAG_NAME, Name, true);
db.WriteString(TAG_NAME, Name, true);
if (IsEmptyGuid(ExeID))
RandomGuid(ExeID);
db.WriteBinary(pdb, TAG_EXE_ID, ExeID);
db.WriteBinary(TAG_EXE_ID, ExeID);
db.WriteString(pdb, TAG_APP_NAME, AppName);
db.WriteString(pdb, TAG_VENDOR, Vendor);
db.WriteString(TAG_APP_NAME, AppName);
db.WriteString(TAG_VENDOR, Vendor);
if (!WriteGeneric(pdb, MatchingFiles, db))
if (!WriteGeneric(MatchingFiles, db))
return false;
if (!WriteGeneric(pdb, ShimRefs, db))
if (!WriteGeneric(ShimRefs, db))
return false;
if (!WriteGeneric(pdb, FlagRefs, db))
if (!WriteGeneric(FlagRefs, db))
return false;
return !!db.EndWriteListTag(pdb, Tagid);
return !!db.EndWriteListTag(Tagid);
}
@@ -586,47 +642,52 @@ bool Exe::toSdb(PDB pdb, Database& db)
* Database
*/
void Database::WriteBinary(PDB pdb, TAG tag, const GUID& guid, bool always)
void Database::WriteBinary(TAG tag, const GUID& guid, bool always)
{
if (always || !IsEmptyGuid(guid))
SdbWriteBinaryTag(pdb, tag, (BYTE*)&guid, sizeof(GUID));
}
void Database::WriteBinary(PDB pdb, TAG tag, const std::vector<BYTE>& data, bool always)
void Database::WriteBinary(TAG tag, const std::vector<BYTE>& data, bool always)
{
if (always || !data.empty())
SdbWriteBinaryTag(pdb, tag, data.data(), data.size());
}
void Database::WriteString(PDB pdb, TAG tag, const sdbstring& str, bool always)
void Database::WriteString(TAG tag, const sdbstring& str, bool always)
{
if (always || !str.empty())
SdbWriteStringTag(pdb, tag, (LPCWSTR)str.c_str());
}
void Database::WriteString(PDB pdb, TAG tag, const std::string& str, bool always)
void Database::WriteString(TAG tag, const std::string& str, bool always)
{
WriteString(pdb, tag, sdbstring(str.begin(), str.end()), always);
WriteString(tag, sdbstring(str.begin(), str.end()), always);
}
void Database::WriteDWord(PDB pdb, TAG tag, DWORD value, bool always)
void Database::WriteDWord(TAG tag, DWORD value, bool always)
{
if (always || value)
SdbWriteDWORDTag(pdb, tag, value);
}
void Database::WriteQWord(PDB pdb, TAG tag, QWORD value, bool always)
void Database::WriteQWord(TAG tag, QWORD value, bool always)
{
if (always || value)
SdbWriteQWORDTag(pdb, tag, value);
}
TAGID Database::BeginWriteListTag(PDB pdb, TAG tag)
void Database::WriteNull(TAG tag)
{
SdbWriteNULLTag(pdb, tag);
}
TAGID Database::BeginWriteListTag(TAG tag)
{
return SdbBeginWriteListTag(pdb, tag);
}
BOOL Database::EndWriteListTag(PDB pdb, TAGID tagid)
BOOL Database::EndWriteListTag(TAGID tagid)
{
return SdbEndWriteListTag(pdb, tagid);
}
@@ -643,7 +704,7 @@ bool Database::fromXml(XMLHandle dbNode)
if (NodeName == "SHIM")
{
Shim shim;
if (shim.fromXml(libChild))
if (shim.fromXml(libChild) && ((shim.Platform & platform) != PLATFORM_NONE))
Library.Shims.push_back(shim);
}
else if (NodeName == "FLAG")
@@ -661,50 +722,52 @@ bool Database::fromXml(XMLHandle dbNode)
libChild = libChild.NextSibling();
}
ReadGeneric(dbNode, Layers, "LAYER");
ReadGeneric(dbNode, Exes, "EXE");
ReadGeneric(dbNode, Layers, "LAYER", platform);
ReadGeneric(dbNode, Exes, "EXE", platform);
return true;
}
bool Database::fromXml(const char* fileName)
bool Database::fromXml(const char* fileName, PlatformType platform_)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLError err = doc.LoadFile(fileName);
XMLHandle dbHandle = tinyxml2::XMLHandle(&doc).FirstChildElement("SDB").FirstChildElement("DATABASE");
platform = platform_;
return fromXml(dbHandle);
}
bool Database::toSdb(LPCWSTR path)
{
PDB pdb = SdbCreateDatabase(path, DOS_PATH);
TAGID tidDatabase = BeginWriteListTag(pdb, TAG_DATABASE);
pdb = SdbCreateDatabase(path, DOS_PATH);
TAGID tidDatabase = BeginWriteListTag(TAG_DATABASE);
LARGE_INTEGER li = { 0 };
RtlSecondsSince1970ToTime(time(0), &li);
SdbWriteQWORDTag(pdb, TAG_TIME, li.QuadPart);
WriteString(pdb, TAG_COMPILER_VERSION, szCompilerVersion);
SdbWriteDWORDTag(pdb, TAG_OS_PLATFORM, 1);
WriteString(pdb, TAG_NAME, Name, true);
WriteQWord(TAG_TIME, li.QuadPart);
WriteString(TAG_COMPILER_VERSION, szCompilerVersion);
WriteDWord(TAG_OS_PLATFORM, platform);
WriteString(TAG_NAME, Name, true);
if (IsEmptyGuid(ID))
{
SHIM_WARN("DB has empty ID!\n");
RandomGuid(ID);
}
WriteBinary(pdb, TAG_DATABASE_ID, ID);
TAGID tidLibrary = BeginWriteListTag(pdb, TAG_LIBRARY);
if (!WriteGeneric(pdb, Library.InExcludes, *this))
WriteBinary(TAG_DATABASE_ID, ID);
TAGID tidLibrary = BeginWriteListTag(TAG_LIBRARY);
if (!WriteGeneric(Library.InExcludes, *this))
return false;
if (!WriteGeneric(pdb, Library.Shims, *this))
if (!WriteGeneric(Library.Shims, *this))
return false;
if (!WriteGeneric(pdb, Library.Flags, *this))
if (!WriteGeneric(Library.Flags, *this))
return false;
EndWriteListTag(pdb, tidLibrary);
if (!WriteGeneric(pdb, Layers, *this))
EndWriteListTag(tidLibrary);
if (!WriteGeneric(Layers, *this))
return false;
if (!WriteGeneric(pdb, Exes, *this))
if (!WriteGeneric(Exes, *this))
return false;
EndWriteListTag(pdb, tidDatabase);
EndWriteListTag(tidDatabase);
SdbCloseDatabaseWrite(pdb);
pdb = nullptr;
return true;
}
@@ -760,14 +823,3 @@ TAGID Database::FindFlagTagid(const sdbstring& name)
{
return FindTagid(name, KnownFlags);
}
bool xml_2_db(const char* xml, const WCHAR* sdb)
{
Database db;
if (db.fromXml(xml))
{
return db.toSdb((LPCWSTR)sdb);
}
return false;
}
+70 -59
View File
@@ -1,8 +1,8 @@
/*
* PROJECT: xml2sdb
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Define mapping of all shim database types to xml
* COPYRIGHT: Copyright 2016-2019 Mark Jansen ([email protected])
* COPYRIGHT: Copyright 2016-2025 Mark Jansen <[email protected]>
*/
#pragma once
@@ -28,138 +28,147 @@ typedef std::basic_string<WCHAR> sdbstring;
struct Database;
enum PlatformType
{
PLATFORM_NONE = 0,
// This is all we support for now
PLATFORM_X86 = 1,
// There is another platform here, but we don't support it yet
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/kshim/drvmain.htm
PLATFORM_AMD64 = 4,
PLATFORM_ANY = PLATFORM_X86 | PLATFORM_AMD64
};
struct str_to_flag
{
const char *name;
DWORD flag;
};
extern str_to_flag platform_to_flag[];
DWORD str_to_enum(const std::string &str, const str_to_flag *table);
struct InExclude
{
InExclude() : Include(false) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Module;
bool Include;
bool Include = false;
};
struct ShimRef
{
ShimRef() : ShimTagid(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
std::string CommandLine;
TAGID ShimTagid;
TAGID ShimTagid = 0;
std::list<InExclude> InExcludes;
};
struct FlagRef
{
FlagRef() : FlagTagid(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
TAGID FlagTagid;
TAGID FlagTagid = 0;
};
struct Shim
{
Shim() : Tagid(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
std::string DllFile;
GUID FixID;
TAGID Tagid;
GUID FixID = {};
TAGID Tagid = 0;
std::list<InExclude> InExcludes;
PlatformType Platform = PLATFORM_ANY;
};
struct Flag
{
Flag() : Tagid(0), KernelFlags(0), UserFlags(0), ProcessParamFlags(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
TAGID Tagid;
QWORD KernelFlags;
QWORD UserFlags;
QWORD ProcessParamFlags;
TAGID Tagid = 0;
QWORD KernelFlags = 0;
QWORD UserFlags = 0;
QWORD ProcessParamFlags = 0;
};
struct Data
{
Data() : Tagid(0), DataType(0), DWordData(0), QWordData(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
TAGID Tagid;
DWORD DataType;
TAGID Tagid = 0;
DWORD DataType = 0;
std::string StringData;
DWORD DWordData;
QWORD QWordData;
DWORD DWordData = 0;
QWORD QWordData = 0;
};
struct Layer
{
Layer() : Tagid(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
TAGID Tagid;
TAGID Tagid = 0;
std::list<ShimRef> ShimRefs;
std::list<FlagRef> FlagRefs;
std::list<Data> Datas;
PlatformType Platform = PLATFORM_ANY;
};
struct MatchingFile
{
MatchingFile() : Size(0), Checksum(0), LinkDate(0), LinkerVersion(0) {;}
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
DWORD Size;
DWORD Checksum;
DWORD Size = 0;
DWORD Checksum = 0;
std::string CompanyName;
std::string InternalName;
std::string ProductName;
std::string ProductVersion;
std::string FileVersion;
std::string BinFileVersion;
DWORD LinkDate;
DWORD LinkDate = 0;
std::string VerLanguage;
std::string FileDescription;
std::string OriginalFilename;
std::string UptoBinFileVersion;
DWORD LinkerVersion;
DWORD LinkerVersion = 0;
};
struct Exe
{
Exe() : Tagid(0) { ; }
bool fromXml(XMLHandle dbNode);
bool toSdb(PDB pdb, Database& db);
bool toSdb(Database& db);
std::string Name;
GUID ExeID;
GUID ExeID = {};
std::string AppName;
std::string Vendor;
TAGID Tagid;
TAGID Tagid = 0;
std::list<MatchingFile> MatchingFiles;
std::list<ShimRef> ShimRefs;
std::list<FlagRef> FlagRefs;
PlatformType Platform = PLATFORM_ANY;
};
struct Library
@@ -171,19 +180,19 @@ struct Library
struct Database
{
bool fromXml(const char* fileName);
bool fromXml(const char* fileName, PlatformType platform);
bool fromXml(XMLHandle dbNode);
bool toSdb(LPCWSTR path);
void WriteString(PDB pdb, TAG tag, const sdbstring& str, bool always = false);
void WriteString(PDB pdb, TAG tag, const std::string& str, bool always = false);
void WriteBinary(PDB pdb, TAG tag, const GUID& guid, bool always = false);
void WriteBinary(PDB pdb, TAG tag, const std::vector<BYTE>& data, bool always = false);
void WriteDWord(PDB pdb, TAG tag, DWORD value, bool always = false);
void WriteQWord(PDB pdb, TAG tag, QWORD value, bool always = false);
TAGID BeginWriteListTag(PDB pdb, TAG tag);
BOOL EndWriteListTag(PDB pdb, TAGID tagid);
void WriteString(TAG tag, const sdbstring& str, bool always = false);
void WriteString(TAG tag, const std::string& str, bool always = false);
void WriteBinary(TAG tag, const GUID& guid, bool always = false);
void WriteBinary(TAG tag, const std::vector<BYTE>& data, bool always = false);
void WriteDWord(TAG tag, DWORD value, bool always = false);
void WriteQWord(TAG tag, QWORD value, bool always = false);
void WriteNull(TAG tag);
TAGID BeginWriteListTag(TAG tag);
BOOL EndWriteListTag(TAGID tagid);
void InsertShimTagid(const sdbstring& name, TAGID tagid);
inline void InsertShimTagid(const std::string& name, TAGID tagid)
@@ -220,7 +229,7 @@ struct Database
}
std::string Name;
GUID ID;
GUID ID = {};
struct Library Library;
std::list<Layer> Layers;
@@ -230,5 +239,7 @@ private:
std::map<sdbstring, TAGID> KnownShims;
std::map<sdbstring, TAGID> KnownPatches;
std::map<sdbstring, TAGID> KnownFlags;
PDB pdb = nullptr;
PlatformType platform = PLATFORM_ANY;
};