Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / sdk / tools / xml2sdb / xml2sdb.cpp
diff --git a/reactos/sdk/tools/xml2sdb/xml2sdb.cpp b/reactos/sdk/tools/xml2sdb/xml2sdb.cpp
deleted file mode 100644 (file)
index 4d136d2..0000000
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * PROJECT:     xml2sdb
- * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
- * PURPOSE:     Conversion functions from xml -> db
- * COPYRIGHT:   Copyright 2016,2017 Mark Jansen (mark.jansen@reactos.org)
- */
-
-#include "xml2sdb.h"
-#include "sdbpapi.h"
-#include "tinyxml2.h"
-#include <time.h>
-#include <algorithm>
-
-using tinyxml2::XMLText;
-
-static const GUID GUID_NULL = { 0 };
-static const char szCompilerVersion[] = "1.6.0.0";
-
-#if !defined(C_ASSERT)
-#define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1]
-#endif
-
-
-C_ASSERT(sizeof(GUID) == 16);
-C_ASSERT(sizeof(ULONG) == 4);
-C_ASSERT(sizeof(LARGE_INTEGER) == 8);
-C_ASSERT(sizeof(WCHAR) == 2);
-C_ASSERT(sizeof(wchar_t) == 2);
-C_ASSERT(sizeof(TAG) == 2);
-C_ASSERT(sizeof(TAGID) == 4);
-
-
-extern "C"
-VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970,
-                          OUT PLARGE_INTEGER Time);
-
-
-/***********************************************************************
- *   Helper functions
- */
-
-
-// Convert utf8 to utf16:
-// http://stackoverflow.com/a/7154226/4928207
-
-bool IsEmptyGuid(const GUID& g)
-{
-    return !memcmp(&g, &GUID_NULL, sizeof(GUID));
-}
-
-void RandomGuid(GUID& g)
-{
-    BYTE* p = (BYTE*)&g;
-    for (size_t n = 0; n < sizeof(GUID); ++n)
-        p[n] = (BYTE)(rand() % 0xff);
-}
-
-// Given a node, return the node value (safe)
-std::string ToString(XMLHandle node)
-{
-    XMLText* txtNode = node.FirstChild().ToText();
-    const char* txt = txtNode ? txtNode->Value() : NULL;
-    if (txt)
-        return std::string(txt);
-    return std::string();
-}
-
-// Given a node, return the node name (safe)
-std::string ToNodeName(XMLHandle node)
-{
-    tinyxml2::XMLNode* raw = node.ToNode();
-    const char* txt = raw ? raw->Value() : NULL;
-    if (txt)
-        return std::string(txt);
-    return std::string();
-}
-
-// Read either an attribute, or a child node
-std::string ReadStringNode(XMLHandle dbNode, const char* nodeName)
-{
-    tinyxml2::XMLElement* elem = dbNode.ToElement();
-    if (elem)
-    {
-        const char* rawVal = elem->Attribute(nodeName);
-        if (rawVal)
-            return std::string(rawVal);
-    }
-    return ToString(dbNode.FirstChildElement(nodeName));
-}
-
-DWORD ReadDWordNode(XMLHandle dbNode, const char* nodeName)
-{
-    std::string value = ReadStringNode(dbNode, nodeName);
-    int base = 10;
-    if (value.size() > 2 && value[0] == '0' && value[1] == 'x')
-    {
-        base = 16;
-        value = value.substr(2);
-    }
-    return static_cast<DWORD>(strtoul(value.c_str(), NULL, base));
-}
-
-unsigned char char2byte(char hexChar, bool* success = NULL)
-{
-    if (hexChar >= '0' && hexChar <= '9')
-        return hexChar - '0';
-    if (hexChar >= 'A' && hexChar <= 'F')
-        return hexChar - 'A' + 10;
-    if (hexChar >= 'a' && hexChar <= 'f')
-        return hexChar - 'a' + 10;
-
-    if (success)
-        *success = false;
-    return 0;
-}
-
-// adapted from wine's ntdll\rtlstr.c rev 1.45
-static bool StringToGuid(const std::string& str, GUID& guid)
-{
-    const char *lpszGUID = str.c_str();
-    BYTE* lpOut = (BYTE*)&guid;
-    int i = 0;
-    bool expectBrace = true;
-    while (i <= 37)
-    {
-        switch (i)
-        {
-        case 0:
-            if (*lpszGUID != '{')
-            {
-                i++;
-                expectBrace = false;
-                continue;
-            }
-            break;
-
-        case 9:
-        case 14:
-        case 19:
-        case 24:
-            if (*lpszGUID != '-')
-                return false;
-            break;
-
-        case 37:
-            return expectBrace == (*lpszGUID == '}');
-
-        default:
-        {
-            CHAR ch = *lpszGUID, ch2 = lpszGUID[1];
-            unsigned char byte;
-            bool converted = true;
-
-            byte = char2byte(ch, &converted) << 4 | char2byte(ch2, &converted);
-            if (!converted)
-                return false;
-
-            switch (i)
-            {
-#ifndef WORDS_BIGENDIAN
-                /* For Big Endian machines, we store the data such that the
-                 * dword/word members can be read as DWORDS and WORDS correctly. */
-                /* Dword */
-            case 1:
-                lpOut[3] = byte;
-                break;
-            case 3:
-                lpOut[2] = byte;
-                break;
-            case 5:
-                lpOut[1] = byte;
-                break;
-            case 7:
-                lpOut[0] = byte;
-                lpOut += 4;
-                break;
-                /* Word */
-            case 10:
-            case 15:
-                lpOut[1] = byte;
-                break;
-            case 12:
-            case 17:
-                lpOut[0] = byte;
-                lpOut += 2;
-                break;
-#endif
-                /* Byte */
-            default:
-                lpOut[0] = byte;
-                lpOut++;
-                break;
-            }
-
-            lpszGUID++; /* Skip 2nd character of byte */
-            i++;
-        }
-        }
-
-        lpszGUID++;
-        i++;
-    }
-    return false;
-}
-
-bool ReadGuidNode(XMLHandle dbNode, const char* nodeName, GUID& guid)
-{
-    std::string value = ReadStringNode(dbNode, nodeName);
-    if (!StringToGuid(value, guid))
-    {
-        memset(&guid, 0, sizeof(GUID));
-        return false;
-    }
-    return true;
-}
-
-bool ReadBinaryNode(XMLHandle dbNode, const char* nodeName, std::vector<BYTE>& data)
-{
-    std::string value = ReadStringNode(dbNode, nodeName);
-    value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end());
-
-    size_t length = value.size() / 2;
-    if (length * 2 != value.size())
-        return false;
-
-    data.resize(length);
-    for (size_t n = 0; n < length; ++n)
-    {
-        data[n] = (BYTE)(char2byte(value[n * 2]) << 4 | char2byte(value[(n * 2) + 1]));
-    }
-    return true;
-}
-
-
-/***********************************************************************
- *   InExclude
- */
-
-bool InExclude::fromXml(XMLHandle dbNode)
-{
-    Module = ReadStringNode(dbNode, "MODULE");
-    // Special module names: '$' and '*'
-    if (!Module.empty())
-    {
-        Include = ToNodeName(dbNode) == "INCLUDE";
-        return true;
-    }
-    return false;
-}
-
-bool InExclude::toSdb(PDB pdb, Database& db)
-{
-    TAGID tagid = db.BeginWriteListTag(pdb, TAG_INEXCLUD);
-    db.WriteString(pdb, TAG_MODULE, Module, true);
-    if (Include)
-        SdbWriteNULLTag(pdb, TAG_INCLUDE);
-    return !!db.EndWriteListTag(pdb, tagid);
-}
-
-
-template<typename T>
-void ReadGeneric(XMLHandle dbNode, std::list<T>& result, const char* nodeName)
-{
-    XMLHandle node = dbNode.FirstChildElement(nodeName);
-    while (node.ToNode())
-    {
-        T object;
-        if (object.fromXml(node))
-            result.push_back(object);
-
-        node = node.NextSiblingElement(nodeName);
-    }
-}
-
-template<typename T>
-bool WriteGeneric(PDB pdb, std::list<T>& data, Database& db)
-{
-    for (typename std::list<T>::iterator it = data.begin(); it != data.end(); ++it)
-    {
-        if (!it->toSdb(pdb, db))
-            return false;
-    }
-    return true;
-}
-
-
-/***********************************************************************
- *   ShimRef
- */
-
-bool ShimRef::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    CommandLine = ReadStringNode(dbNode, "COMMAND_LINE");
-    ReadGeneric(dbNode, InExcludes, "INCLUDE");
-    ReadGeneric(dbNode, InExcludes, "EXCLUDE");
-    return !Name.empty();
-}
-
-bool ShimRef::toSdb(PDB pdb, Database& db)
-{
-    TAGID tagid = db.BeginWriteListTag(pdb, TAG_SHIM_REF);
-    db.WriteString(pdb, TAG_NAME, Name, true);
-    db.WriteString(pdb, TAG_COMMAND_LINE, CommandLine);
-
-    if (!ShimTagid)
-        ShimTagid = db.FindShimTagid(Name);
-    SdbWriteDWORDTag(pdb, TAG_SHIM_TAGID, ShimTagid);
-    return !!db.EndWriteListTag(pdb, tagid);
-}
-
-
-/***********************************************************************
- *   Shim
- */
-
-bool Shim::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    DllFile = ReadStringNode(dbNode, "DLLFILE");
-    ReadGuidNode(dbNode, "FIX_ID", FixID);
-    // GENERAL ?
-    // DESCRIPTION_RC_ID
-    ReadGeneric(dbNode, InExcludes, "INCLUDE");
-    ReadGeneric(dbNode, InExcludes, "EXCLUDE");
-    return !Name.empty() && !DllFile.empty();
-}
-
-bool Shim::toSdb(PDB pdb, Database& db)
-{
-    Tagid = db.BeginWriteListTag(pdb, TAG_SHIM);
-    db.InsertShimTagid(Name, Tagid);
-    db.WriteString(pdb, TAG_NAME, Name);
-    db.WriteString(pdb, TAG_DLLFILE, DllFile);
-    if (IsEmptyGuid(FixID))
-        RandomGuid(FixID);
-    db.WriteBinary(pdb, TAG_FIX_ID, FixID);
-    if (!WriteGeneric(pdb, InExcludes, db))
-        return false;
-    return !!db.EndWriteListTag(pdb, Tagid);
-}
-
-
-/***********************************************************************
- *   Layer
- */
-
-bool Layer::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    ReadGeneric(dbNode, ShimRefs, "SHIM_REF");
-    return true;
-}
-
-bool Layer::toSdb(PDB pdb, Database& db)
-{
-    Tagid = db.BeginWriteListTag(pdb, TAG_LAYER);
-    db.WriteString(pdb, TAG_NAME, Name, true);
-    if (!WriteGeneric(pdb, ShimRefs, db))
-        return false;
-    return !!db.EndWriteListTag(pdb, Tagid);
-}
-
-
-/***********************************************************************
- *   MatchingFile
- */
-
-bool MatchingFile::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    Size = ReadDWordNode(dbNode, "SIZE");
-    Checksum = ReadDWordNode(dbNode, "CHECKSUM");
-    CompanyName = ReadStringNode(dbNode, "COMPANY_NAME");
-    InternalName = ReadStringNode(dbNode, "INTERNAL_NAME");
-    ProductName = ReadStringNode(dbNode, "PRODUCT_NAME");
-    ProductVersion = ReadStringNode(dbNode, "PRODUCT_VERSION");
-    FileVersion = ReadStringNode(dbNode, "FILE_VERSION");
-    BinFileVersion = ReadStringNode(dbNode, "BIN_FILE_VERSION");
-    LinkDate = ReadStringNode(dbNode, "LINK_DATE");
-    VerLanguage = ReadStringNode(dbNode, "VER_LANGUAGE");
-    FileDescription = ReadStringNode(dbNode, "FILE_DESCRIPTION");
-    OriginalFilename = ReadStringNode(dbNode, "ORIGINAL_FILENAME");
-    UptoBinFileVersion = ReadStringNode(dbNode, "UPTO_BIN_FILE_VERSION");
-    LinkerVersion = ReadStringNode(dbNode, "LINKER_VERSION");
-    return true;
-}
-
-bool MatchingFile::toSdb(PDB pdb, Database& db)
-{
-    TAGID tagid = db.BeginWriteListTag(pdb, 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);
-    if (!BinFileVersion.empty())
-        SHIM_ERR("TAG_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_BIN_FILE_VERSION, BinFileVersion);
-    if (!LinkDate.empty())
-        SHIM_ERR("TAG_LINK_DATE Unimplemented\n"); //db.WriteDWord(pdb, 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);
-    if (!UptoBinFileVersion.empty())
-        SHIM_ERR("TAG_UPTO_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_UPTO_BIN_FILE_VERSION, UptoBinFileVersion);
-    if (!LinkerVersion.empty())
-        SHIM_ERR("TAG_LINKER_VERSION Unimplemented\n"); //db.WriteDWord(pdb, TAG_LINKER_VERSION, LinkerVersion);
-
-
-    return !!db.EndWriteListTag(pdb, tagid);
-}
-
-
-/***********************************************************************
- *   Exe
- */
-
-bool Exe::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    ReadGuidNode(dbNode, "EXE_ID", ExeID);
-    AppName = ReadStringNode(dbNode, "APP_NAME");
-    Vendor = ReadStringNode(dbNode, "VENDOR");
-
-    ReadGeneric(dbNode, MatchingFiles, "MATCHING_FILE");
-
-    ReadGeneric(dbNode, ShimRefs, "SHIM_REF");
-
-    return !Name.empty();
-}
-
-bool Exe::toSdb(PDB pdb, Database& db)
-{
-    Tagid = db.BeginWriteListTag(pdb, TAG_EXE);
-
-    db.WriteString(pdb, TAG_NAME, Name, true);
-    if (IsEmptyGuid(ExeID))
-        RandomGuid(ExeID);
-    db.WriteBinary(pdb, TAG_EXE_ID, ExeID);
-
-
-    db.WriteString(pdb, TAG_APP_NAME, AppName);
-    db.WriteString(pdb, TAG_VENDOR, Vendor);
-
-    if (!WriteGeneric(pdb, MatchingFiles, db))
-        return false;
-    if (!WriteGeneric(pdb, ShimRefs, db))
-        return false;
-
-    return !!db.EndWriteListTag(pdb, Tagid);
-}
-
-
-/***********************************************************************
- *   Database
- */
-
-void Database::WriteBinary(PDB pdb, 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)
-{
-    if (always || !data.empty())
-    SdbWriteBinaryTag(pdb, tag, data.data(), data.size());
-}
-
-void Database::WriteString(PDB pdb, 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)
-{
-    WriteString(pdb, tag, sdbstring(str.begin(), str.end()), always);
-}
-
-void Database::WriteDWord(PDB pdb, TAG tag, DWORD value, bool always)
-{
-    if (always || value)
-        SdbWriteDWORDTag(pdb, tag, value);
-}
-
-TAGID Database::BeginWriteListTag(PDB pdb, TAG tag)
-{
-    return SdbBeginWriteListTag(pdb, tag);
-}
-
-BOOL Database::EndWriteListTag(PDB pdb, TAGID tagid)
-{
-    return SdbEndWriteListTag(pdb, tagid);
-}
-
-bool Database::fromXml(XMLHandle dbNode)
-{
-    Name = ReadStringNode(dbNode, "NAME");
-    ReadGuidNode(dbNode, "DATABASE_ID", ID);
-
-    XMLHandle libChild = dbNode.FirstChildElement("LIBRARY").FirstChild();
-    while (libChild.ToNode())
-    {
-        std::string NodeName = ToNodeName(libChild);
-        if (NodeName == "SHIM")
-        {
-            Shim shim;
-            if (shim.fromXml(libChild))
-                Library.Shims.push_back(shim);
-        }
-        else if (NodeName == "FLAG")
-        {
-            SHIM_ERR("Unhanled FLAG type\n");
-        }
-        else if (NodeName == "INCLUDE" || NodeName == "EXCLUDE")
-        {
-            InExclude inex;
-            if (inex.fromXml(libChild))
-                Library.InExcludes.push_back(inex);
-        }
-        libChild = libChild.NextSibling();
-    }
-
-    ReadGeneric(dbNode, Layers, "LAYER");
-    ReadGeneric(dbNode, Exes, "EXE");
-    return true;
-}
-
-bool Database::fromXml(const char* fileName)
-{
-    tinyxml2::XMLDocument doc;
-    tinyxml2::XMLError err = doc.LoadFile(fileName);
-    XMLHandle dbHandle = tinyxml2::XMLHandle(&doc).FirstChildElement("SDB").FirstChildElement("DATABASE");
-    return fromXml(dbHandle);
-}
-
-bool Database::toSdb(LPCWSTR path)
-{
-    PDB pdb = SdbCreateDatabase(path, DOS_PATH);
-    TAGID tidDatabase = BeginWriteListTag(pdb, 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);
-    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))
-        return false;
-    if (!WriteGeneric(pdb, Library.Shims, *this))
-        return false;
-    EndWriteListTag(pdb, tidLibrary);
-    if (!WriteGeneric(pdb, Layers, *this))
-        return false;
-    if (!WriteGeneric(pdb, Exes, *this))
-        return false;
-    EndWriteListTag(pdb, tidDatabase);
-
-    SdbCloseDatabaseWrite(pdb);
-    return true;
-}
-
-static void InsertTagid(const sdbstring& name, TAGID tagid, std::map<sdbstring, TAGID>& lookup, const char* type)
-{
-    sdbstring nameLower = name;
-    std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower);
-    if (lookup.find(nameLower) != lookup.end())
-    {
-        std::string nameA(name.begin(), name.end());
-        SHIM_WARN("%s '%s' redefined\n", type, nameA.c_str());
-        return;
-    }
-    lookup[nameLower] = tagid;
-}
-
-static TAGID FindTagid(const sdbstring& name, const std::map<sdbstring, TAGID>& lookup)
-{
-    sdbstring nameLower = name;
-    std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower);
-    std::map<sdbstring, TAGID>::const_iterator it = lookup.find(nameLower);
-    if (it == lookup.end())
-        return 0;
-    return it->second;
-}
-
-void Database::InsertShimTagid(const sdbstring& name, TAGID tagid)
-{
-    InsertTagid(name, tagid, KnownShims, "Shim");
-}
-
-TAGID Database::FindShimTagid(const sdbstring& name)
-{
-    return FindTagid(name, KnownShims);
-}
-
-void Database::InsertPatchTagid(const sdbstring& name, TAGID tagid)
-{
-    InsertTagid(name, tagid, KnownPatches, "Patch");
-}
-
-TAGID Database::FindPatchTagid(const sdbstring& name)
-{
-    return FindTagid(name, KnownPatches);
-}
-
-
-
-bool xml_2_db(const char* xml, const WCHAR* sdb)
-{
-    Database db;
-    if (db.fromXml(xml))
-    {
-        return db.toSdb((LPCWSTR)sdb);
-    }
-    return false;
-}