1 /* 2 * PROJECT: xml2sdb 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Conversion functions from xml -> db 5 * COPYRIGHT: Copyright 2016-2018 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include "xml2sdb.h" 9 #include "sdbpapi.h" 10 #include "tinyxml2.h" 11 #include <time.h> 12 #include <algorithm> 13 14 using tinyxml2::XMLText; 15 16 static const GUID GUID_NULL = { 0 }; 17 static const char szCompilerVersion[] = "1.7.0.0"; 18 19 #if !defined(C_ASSERT) 20 #define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1] 21 #endif 22 23 24 C_ASSERT(sizeof(GUID) == 16); 25 C_ASSERT(sizeof(ULONG) == 4); 26 C_ASSERT(sizeof(LARGE_INTEGER) == 8); 27 C_ASSERT(sizeof(WCHAR) == 2); 28 C_ASSERT(sizeof(wchar_t) == 2); 29 C_ASSERT(sizeof(TAG) == 2); 30 C_ASSERT(sizeof(TAGID) == 4); 31 32 33 extern "C" 34 VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970, 35 OUT PLARGE_INTEGER Time); 36 37 38 /*********************************************************************** 39 * Helper functions 40 */ 41 42 43 // Convert utf8 to utf16: 44 // http://stackoverflow.com/a/7154226/4928207 45 46 bool IsEmptyGuid(const GUID& g) 47 { 48 return !memcmp(&g, &GUID_NULL, sizeof(GUID)); 49 } 50 51 void RandomGuid(GUID& g) 52 { 53 BYTE* p = (BYTE*)&g; 54 for (size_t n = 0; n < sizeof(GUID); ++n) 55 p[n] = (BYTE)(rand() % 0xff); 56 } 57 58 // Given a node, return the node value (safe) 59 std::string ToString(XMLHandle node) 60 { 61 XMLText* txtNode = node.FirstChild().ToText(); 62 const char* txt = txtNode ? txtNode->Value() : NULL; 63 if (txt) 64 return std::string(txt); 65 return std::string(); 66 } 67 68 // Given a node, return the node name (safe) 69 std::string ToNodeName(XMLHandle node) 70 { 71 tinyxml2::XMLNode* raw = node.ToNode(); 72 const char* txt = raw ? raw->Value() : NULL; 73 if (txt) 74 return std::string(txt); 75 return std::string(); 76 } 77 78 // Read either an attribute, or a child node 79 std::string ReadStringNode(XMLHandle dbNode, const char* nodeName) 80 { 81 tinyxml2::XMLElement* elem = dbNode.ToElement(); 82 if (elem) 83 { 84 const char* rawVal = elem->Attribute(nodeName); 85 if (rawVal) 86 return std::string(rawVal); 87 } 88 return ToString(dbNode.FirstChildElement(nodeName)); 89 } 90 91 DWORD ReadQWordNode(XMLHandle dbNode, const char* nodeName) 92 { 93 std::string value = ReadStringNode(dbNode, nodeName); 94 int base = 10; 95 if (value.size() > 2 && value[0] == '0' && value[1] == 'x') 96 { 97 base = 16; 98 value = value.substr(2); 99 } 100 return static_cast<QWORD>(strtoul(value.c_str(), NULL, base)); 101 } 102 103 DWORD ReadDWordNode(XMLHandle dbNode, const char* nodeName) 104 { 105 return static_cast<DWORD>(ReadQWordNode(dbNode, nodeName)); 106 } 107 108 unsigned char char2byte(char hexChar, bool* success = NULL) 109 { 110 if (hexChar >= '0' && hexChar <= '9') 111 return hexChar - '0'; 112 if (hexChar >= 'A' && hexChar <= 'F') 113 return hexChar - 'A' + 10; 114 if (hexChar >= 'a' && hexChar <= 'f') 115 return hexChar - 'a' + 10; 116 117 if (success) 118 *success = false; 119 return 0; 120 } 121 122 // adapted from wine's ntdll\rtlstr.c rev 1.45 123 static bool StringToGuid(const std::string& str, GUID& guid) 124 { 125 const char *lpszGUID = str.c_str(); 126 BYTE* lpOut = (BYTE*)&guid; 127 int i = 0; 128 bool expectBrace = true; 129 while (i <= 37) 130 { 131 switch (i) 132 { 133 case 0: 134 if (*lpszGUID != '{') 135 { 136 i++; 137 expectBrace = false; 138 continue; 139 } 140 break; 141 142 case 9: 143 case 14: 144 case 19: 145 case 24: 146 if (*lpszGUID != '-') 147 return false; 148 break; 149 150 case 37: 151 return expectBrace == (*lpszGUID == '}'); 152 153 default: 154 { 155 CHAR ch = *lpszGUID, ch2 = lpszGUID[1]; 156 unsigned char byte; 157 bool converted = true; 158 159 byte = char2byte(ch, &converted) << 4 | char2byte(ch2, &converted); 160 if (!converted) 161 return false; 162 163 switch (i) 164 { 165 #ifndef WORDS_BIGENDIAN 166 /* For Big Endian machines, we store the data such that the 167 * dword/word members can be read as DWORDS and WORDS correctly. */ 168 /* Dword */ 169 case 1: 170 lpOut[3] = byte; 171 break; 172 case 3: 173 lpOut[2] = byte; 174 break; 175 case 5: 176 lpOut[1] = byte; 177 break; 178 case 7: 179 lpOut[0] = byte; 180 lpOut += 4; 181 break; 182 /* Word */ 183 case 10: 184 case 15: 185 lpOut[1] = byte; 186 break; 187 case 12: 188 case 17: 189 lpOut[0] = byte; 190 lpOut += 2; 191 break; 192 #endif 193 /* Byte */ 194 default: 195 lpOut[0] = byte; 196 lpOut++; 197 break; 198 } 199 200 lpszGUID++; /* Skip 2nd character of byte */ 201 i++; 202 } 203 } 204 205 lpszGUID++; 206 i++; 207 } 208 return false; 209 } 210 211 bool ReadGuidNode(XMLHandle dbNode, const char* nodeName, GUID& guid) 212 { 213 std::string value = ReadStringNode(dbNode, nodeName); 214 if (!StringToGuid(value, guid)) 215 { 216 memset(&guid, 0, sizeof(GUID)); 217 return false; 218 } 219 return true; 220 } 221 222 bool ReadBinaryNode(XMLHandle dbNode, const char* nodeName, std::vector<BYTE>& data) 223 { 224 std::string value = ReadStringNode(dbNode, nodeName); 225 value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end()); 226 227 size_t length = value.size() / 2; 228 if (length * 2 != value.size()) 229 return false; 230 231 data.resize(length); 232 for (size_t n = 0; n < length; ++n) 233 { 234 data[n] = (BYTE)(char2byte(value[n * 2]) << 4 | char2byte(value[(n * 2) + 1])); 235 } 236 return true; 237 } 238 239 240 /*********************************************************************** 241 * InExclude 242 */ 243 244 bool InExclude::fromXml(XMLHandle dbNode) 245 { 246 Module = ReadStringNode(dbNode, "MODULE"); 247 // Special module names: '$' and '*' 248 if (!Module.empty()) 249 { 250 Include = ToNodeName(dbNode) == "INCLUDE"; 251 return true; 252 } 253 return false; 254 } 255 256 bool InExclude::toSdb(PDB pdb, Database& db) 257 { 258 TAGID tagid = db.BeginWriteListTag(pdb, TAG_INEXCLUD); 259 db.WriteString(pdb, TAG_MODULE, Module, true); 260 if (Include) 261 SdbWriteNULLTag(pdb, TAG_INCLUDE); 262 return !!db.EndWriteListTag(pdb, tagid); 263 } 264 265 266 template<typename T> 267 void ReadGeneric(XMLHandle dbNode, std::list<T>& result, const char* nodeName) 268 { 269 XMLHandle node = dbNode.FirstChildElement(nodeName); 270 while (node.ToNode()) 271 { 272 T object; 273 if (object.fromXml(node)) 274 result.push_back(object); 275 276 node = node.NextSiblingElement(nodeName); 277 } 278 } 279 280 template<typename T> 281 bool WriteGeneric(PDB pdb, std::list<T>& data, Database& db) 282 { 283 for (typename std::list<T>::iterator it = data.begin(); it != data.end(); ++it) 284 { 285 if (!it->toSdb(pdb, db)) 286 return false; 287 } 288 return true; 289 } 290 291 292 /*********************************************************************** 293 * ShimRef 294 */ 295 296 bool ShimRef::fromXml(XMLHandle dbNode) 297 { 298 Name = ReadStringNode(dbNode, "NAME"); 299 CommandLine = ReadStringNode(dbNode, "COMMAND_LINE"); 300 ReadGeneric(dbNode, InExcludes, "INCLUDE"); 301 ReadGeneric(dbNode, InExcludes, "EXCLUDE"); 302 return !Name.empty(); 303 } 304 305 bool ShimRef::toSdb(PDB pdb, Database& db) 306 { 307 TAGID tagid = db.BeginWriteListTag(pdb, TAG_SHIM_REF); 308 db.WriteString(pdb, TAG_NAME, Name, true); 309 db.WriteString(pdb, TAG_COMMAND_LINE, CommandLine); 310 311 if (!ShimTagid) 312 ShimTagid = db.FindShimTagid(Name); 313 SdbWriteDWORDTag(pdb, TAG_SHIM_TAGID, ShimTagid); 314 return !!db.EndWriteListTag(pdb, tagid); 315 } 316 317 318 319 /*********************************************************************** 320 * FlagRef 321 */ 322 323 bool FlagRef::fromXml(XMLHandle dbNode) 324 { 325 Name = ReadStringNode(dbNode, "NAME"); 326 return !Name.empty(); 327 } 328 329 bool FlagRef::toSdb(PDB pdb, Database& db) 330 { 331 TAGID tagid = db.BeginWriteListTag(pdb, TAG_FLAG_REF); 332 db.WriteString(pdb, TAG_NAME, Name, true); 333 334 if (!FlagTagid) 335 FlagTagid = db.FindFlagTagid(Name); 336 SdbWriteDWORDTag(pdb, TAG_FLAG_TAGID, FlagTagid); 337 return !!db.EndWriteListTag(pdb, tagid); 338 } 339 340 341 /*********************************************************************** 342 * Shim 343 */ 344 345 bool Shim::fromXml(XMLHandle dbNode) 346 { 347 Name = ReadStringNode(dbNode, "NAME"); 348 DllFile = ReadStringNode(dbNode, "DLLFILE"); 349 ReadGuidNode(dbNode, "FIX_ID", FixID); 350 // GENERAL ? 351 // DESCRIPTION_RC_ID 352 ReadGeneric(dbNode, InExcludes, "INCLUDE"); 353 ReadGeneric(dbNode, InExcludes, "EXCLUDE"); 354 return !Name.empty() && !DllFile.empty(); 355 } 356 357 bool Shim::toSdb(PDB pdb, Database& db) 358 { 359 Tagid = db.BeginWriteListTag(pdb, TAG_SHIM); 360 db.InsertShimTagid(Name, Tagid); 361 db.WriteString(pdb, TAG_NAME, Name); 362 db.WriteString(pdb, TAG_DLLFILE, DllFile); 363 if (IsEmptyGuid(FixID)) 364 RandomGuid(FixID); 365 db.WriteBinary(pdb, TAG_FIX_ID, FixID); 366 if (!WriteGeneric(pdb, InExcludes, db)) 367 return false; 368 return !!db.EndWriteListTag(pdb, Tagid); 369 } 370 371 372 /*********************************************************************** 373 * Flag 374 */ 375 376 bool Flag::fromXml(XMLHandle dbNode) 377 { 378 Name = ReadStringNode(dbNode, "NAME"); 379 380 KernelFlags = ReadQWordNode(dbNode, "FLAG_MASK_KERNEL"); 381 UserFlags = ReadQWordNode(dbNode, "FLAG_MASK_USER"); 382 ProcessParamFlags = ReadQWordNode(dbNode, "FLAG_PROCESSPARAM"); 383 384 return !Name.empty(); 385 } 386 387 bool Flag::toSdb(PDB pdb, Database& db) 388 { 389 Tagid = db.BeginWriteListTag(pdb, TAG_FLAG); 390 db.InsertFlagTagid(Name, Tagid); 391 db.WriteString(pdb, TAG_NAME, Name, true); 392 393 db.WriteQWord(pdb, TAG_FLAG_MASK_KERNEL, KernelFlags); 394 db.WriteQWord(pdb, TAG_FLAG_MASK_USER, UserFlags); 395 db.WriteQWord(pdb, TAG_FLAG_PROCESSPARAM, ProcessParamFlags); 396 397 return !!db.EndWriteListTag(pdb, Tagid); 398 } 399 400 401 /*********************************************************************** 402 * Layer 403 */ 404 405 bool Layer::fromXml(XMLHandle dbNode) 406 { 407 Name = ReadStringNode(dbNode, "NAME"); 408 ReadGeneric(dbNode, ShimRefs, "SHIM_REF"); 409 ReadGeneric(dbNode, FlagRefs, "FLAG_REF"); 410 return true; 411 } 412 413 bool Layer::toSdb(PDB pdb, Database& db) 414 { 415 Tagid = db.BeginWriteListTag(pdb, TAG_LAYER); 416 db.WriteString(pdb, TAG_NAME, Name, true); 417 if (!WriteGeneric(pdb, ShimRefs, db)) 418 return false; 419 if (!WriteGeneric(pdb, FlagRefs, db)) 420 return false; 421 return !!db.EndWriteListTag(pdb, Tagid); 422 } 423 424 425 /*********************************************************************** 426 * MatchingFile 427 */ 428 429 bool MatchingFile::fromXml(XMLHandle dbNode) 430 { 431 Name = ReadStringNode(dbNode, "NAME"); 432 Size = ReadDWordNode(dbNode, "SIZE"); 433 Checksum = ReadDWordNode(dbNode, "CHECKSUM"); 434 CompanyName = ReadStringNode(dbNode, "COMPANY_NAME"); 435 InternalName = ReadStringNode(dbNode, "INTERNAL_NAME"); 436 ProductName = ReadStringNode(dbNode, "PRODUCT_NAME"); 437 ProductVersion = ReadStringNode(dbNode, "PRODUCT_VERSION"); 438 FileVersion = ReadStringNode(dbNode, "FILE_VERSION"); 439 BinFileVersion = ReadStringNode(dbNode, "BIN_FILE_VERSION"); 440 LinkDate = ReadStringNode(dbNode, "LINK_DATE"); 441 VerLanguage = ReadStringNode(dbNode, "VER_LANGUAGE"); 442 FileDescription = ReadStringNode(dbNode, "FILE_DESCRIPTION"); 443 OriginalFilename = ReadStringNode(dbNode, "ORIGINAL_FILENAME"); 444 UptoBinFileVersion = ReadStringNode(dbNode, "UPTO_BIN_FILE_VERSION"); 445 LinkerVersion = ReadStringNode(dbNode, "LINKER_VERSION"); 446 return true; 447 } 448 449 bool MatchingFile::toSdb(PDB pdb, Database& db) 450 { 451 TAGID tagid = db.BeginWriteListTag(pdb, TAG_MATCHING_FILE); 452 453 db.WriteString(pdb, TAG_NAME, Name, true); 454 db.WriteDWord(pdb, TAG_SIZE, Size); 455 db.WriteDWord(pdb, TAG_CHECKSUM, Checksum); 456 db.WriteString(pdb, TAG_COMPANY_NAME, CompanyName); 457 db.WriteString(pdb, TAG_INTERNAL_NAME, InternalName); 458 db.WriteString(pdb, TAG_PRODUCT_NAME, ProductName); 459 db.WriteString(pdb, TAG_PRODUCT_VERSION, ProductVersion); 460 db.WriteString(pdb, TAG_FILE_VERSION, FileVersion); 461 if (!BinFileVersion.empty()) 462 SHIM_ERR("TAG_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_BIN_FILE_VERSION, BinFileVersion); 463 if (!LinkDate.empty()) 464 SHIM_ERR("TAG_LINK_DATE Unimplemented\n"); //db.WriteDWord(pdb, TAG_LINK_DATE, LinkDate); 465 if (!VerLanguage.empty()) 466 SHIM_ERR("TAG_VER_LANGUAGE Unimplemented\n"); //db.WriteDWord(pdb, TAG_VER_LANGUAGE, VerLanguage); 467 db.WriteString(pdb, TAG_FILE_DESCRIPTION, FileDescription); 468 db.WriteString(pdb, TAG_ORIGINAL_FILENAME, OriginalFilename); 469 if (!UptoBinFileVersion.empty()) 470 SHIM_ERR("TAG_UPTO_BIN_FILE_VERSION Unimplemented\n"); //db.WriteQWord(pdb, TAG_UPTO_BIN_FILE_VERSION, UptoBinFileVersion); 471 if (!LinkerVersion.empty()) 472 SHIM_ERR("TAG_LINKER_VERSION Unimplemented\n"); //db.WriteDWord(pdb, TAG_LINKER_VERSION, LinkerVersion); 473 474 475 return !!db.EndWriteListTag(pdb, tagid); 476 } 477 478 479 /*********************************************************************** 480 * Exe 481 */ 482 483 bool Exe::fromXml(XMLHandle dbNode) 484 { 485 Name = ReadStringNode(dbNode, "NAME"); 486 ReadGuidNode(dbNode, "EXE_ID", ExeID); 487 AppName = ReadStringNode(dbNode, "APP_NAME"); 488 Vendor = ReadStringNode(dbNode, "VENDOR"); 489 490 ReadGeneric(dbNode, MatchingFiles, "MATCHING_FILE"); 491 492 ReadGeneric(dbNode, ShimRefs, "SHIM_REF"); 493 ReadGeneric(dbNode, FlagRefs, "FLAG_REF"); 494 495 return !Name.empty(); 496 } 497 498 bool Exe::toSdb(PDB pdb, Database& db) 499 { 500 Tagid = db.BeginWriteListTag(pdb, TAG_EXE); 501 502 db.WriteString(pdb, TAG_NAME, Name, true); 503 if (IsEmptyGuid(ExeID)) 504 RandomGuid(ExeID); 505 db.WriteBinary(pdb, TAG_EXE_ID, ExeID); 506 507 508 db.WriteString(pdb, TAG_APP_NAME, AppName); 509 db.WriteString(pdb, TAG_VENDOR, Vendor); 510 511 if (!WriteGeneric(pdb, MatchingFiles, db)) 512 return false; 513 if (!WriteGeneric(pdb, ShimRefs, db)) 514 return false; 515 if (!WriteGeneric(pdb, FlagRefs, db)) 516 return false; 517 518 return !!db.EndWriteListTag(pdb, Tagid); 519 } 520 521 522 /*********************************************************************** 523 * Database 524 */ 525 526 void Database::WriteBinary(PDB pdb, TAG tag, const GUID& guid, bool always) 527 { 528 if (always || !IsEmptyGuid(guid)) 529 SdbWriteBinaryTag(pdb, tag, (BYTE*)&guid, sizeof(GUID)); 530 } 531 532 void Database::WriteBinary(PDB pdb, TAG tag, const std::vector<BYTE>& data, bool always) 533 { 534 if (always || !data.empty()) 535 SdbWriteBinaryTag(pdb, tag, data.data(), data.size()); 536 } 537 538 void Database::WriteString(PDB pdb, TAG tag, const sdbstring& str, bool always) 539 { 540 if (always || !str.empty()) 541 SdbWriteStringTag(pdb, tag, (LPCWSTR)str.c_str()); 542 } 543 544 void Database::WriteString(PDB pdb, TAG tag, const std::string& str, bool always) 545 { 546 WriteString(pdb, tag, sdbstring(str.begin(), str.end()), always); 547 } 548 549 void Database::WriteDWord(PDB pdb, TAG tag, DWORD value, bool always) 550 { 551 if (always || value) 552 SdbWriteDWORDTag(pdb, tag, value); 553 } 554 555 void Database::WriteQWord(PDB pdb, TAG tag, QWORD value, bool always) 556 { 557 if (always || value) 558 SdbWriteQWORDTag(pdb, tag, value); 559 } 560 561 TAGID Database::BeginWriteListTag(PDB pdb, TAG tag) 562 { 563 return SdbBeginWriteListTag(pdb, tag); 564 } 565 566 BOOL Database::EndWriteListTag(PDB pdb, TAGID tagid) 567 { 568 return SdbEndWriteListTag(pdb, tagid); 569 } 570 571 bool Database::fromXml(XMLHandle dbNode) 572 { 573 Name = ReadStringNode(dbNode, "NAME"); 574 ReadGuidNode(dbNode, "DATABASE_ID", ID); 575 576 XMLHandle libChild = dbNode.FirstChildElement("LIBRARY").FirstChild(); 577 while (libChild.ToNode()) 578 { 579 std::string NodeName = ToNodeName(libChild); 580 if (NodeName == "SHIM") 581 { 582 Shim shim; 583 if (shim.fromXml(libChild)) 584 Library.Shims.push_back(shim); 585 } 586 else if (NodeName == "FLAG") 587 { 588 Flag flag; 589 if (flag.fromXml(libChild)) 590 Library.Flags.push_back(flag); 591 } 592 else if (NodeName == "INCLUDE" || NodeName == "EXCLUDE") 593 { 594 InExclude inex; 595 if (inex.fromXml(libChild)) 596 Library.InExcludes.push_back(inex); 597 } 598 libChild = libChild.NextSibling(); 599 } 600 601 ReadGeneric(dbNode, Layers, "LAYER"); 602 ReadGeneric(dbNode, Exes, "EXE"); 603 return true; 604 } 605 606 bool Database::fromXml(const char* fileName) 607 { 608 tinyxml2::XMLDocument doc; 609 tinyxml2::XMLError err = doc.LoadFile(fileName); 610 XMLHandle dbHandle = tinyxml2::XMLHandle(&doc).FirstChildElement("SDB").FirstChildElement("DATABASE"); 611 return fromXml(dbHandle); 612 } 613 614 bool Database::toSdb(LPCWSTR path) 615 { 616 PDB pdb = SdbCreateDatabase(path, DOS_PATH); 617 TAGID tidDatabase = BeginWriteListTag(pdb, TAG_DATABASE); 618 LARGE_INTEGER li = { 0 }; 619 RtlSecondsSince1970ToTime(time(0), &li); 620 SdbWriteQWORDTag(pdb, TAG_TIME, li.QuadPart); 621 WriteString(pdb, TAG_COMPILER_VERSION, szCompilerVersion); 622 SdbWriteDWORDTag(pdb, TAG_OS_PLATFORM, 1); 623 WriteString(pdb, TAG_NAME, Name, true); 624 if (IsEmptyGuid(ID)) 625 { 626 SHIM_WARN("DB has empty ID!\n"); 627 RandomGuid(ID); 628 } 629 WriteBinary(pdb, TAG_DATABASE_ID, ID); 630 TAGID tidLibrary = BeginWriteListTag(pdb, TAG_LIBRARY); 631 if (!WriteGeneric(pdb, Library.InExcludes, *this)) 632 return false; 633 if (!WriteGeneric(pdb, Library.Shims, *this)) 634 return false; 635 if (!WriteGeneric(pdb, Library.Flags, *this)) 636 return false; 637 EndWriteListTag(pdb, tidLibrary); 638 if (!WriteGeneric(pdb, Layers, *this)) 639 return false; 640 if (!WriteGeneric(pdb, Exes, *this)) 641 return false; 642 EndWriteListTag(pdb, tidDatabase); 643 644 SdbCloseDatabaseWrite(pdb); 645 return true; 646 } 647 648 static void InsertTagid(const sdbstring& name, TAGID tagid, std::map<sdbstring, TAGID>& lookup, const char* type) 649 { 650 sdbstring nameLower = name; 651 std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower); 652 if (lookup.find(nameLower) != lookup.end()) 653 { 654 std::string nameA(name.begin(), name.end()); 655 SHIM_WARN("%s '%s' redefined\n", type, nameA.c_str()); 656 return; 657 } 658 lookup[nameLower] = tagid; 659 } 660 661 static TAGID FindTagid(const sdbstring& name, const std::map<sdbstring, TAGID>& lookup) 662 { 663 sdbstring nameLower = name; 664 std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower); 665 std::map<sdbstring, TAGID>::const_iterator it = lookup.find(nameLower); 666 if (it == lookup.end()) 667 return 0; 668 return it->second; 669 } 670 671 void Database::InsertShimTagid(const sdbstring& name, TAGID tagid) 672 { 673 InsertTagid(name, tagid, KnownShims, "Shim"); 674 } 675 676 TAGID Database::FindShimTagid(const sdbstring& name) 677 { 678 return FindTagid(name, KnownShims); 679 } 680 681 void Database::InsertPatchTagid(const sdbstring& name, TAGID tagid) 682 { 683 InsertTagid(name, tagid, KnownPatches, "Patch"); 684 } 685 686 TAGID Database::FindPatchTagid(const sdbstring& name) 687 { 688 return FindTagid(name, KnownPatches); 689 } 690 691 void Database::InsertFlagTagid(const sdbstring& name, TAGID tagid) 692 { 693 InsertTagid(name, tagid, KnownFlags, "Flag"); 694 } 695 696 TAGID Database::FindFlagTagid(const sdbstring& name) 697 { 698 return FindTagid(name, KnownFlags); 699 } 700 701 702 bool xml_2_db(const char* xml, const WCHAR* sdb) 703 { 704 Database db; 705 if (db.fromXml(xml)) 706 { 707 return db.toSdb((LPCWSTR)sdb); 708 } 709 return false; 710 } 711