Reactos
at master 260 lines 5.9 kB view raw
1/* 2 * PROJECT: xml2sdb 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Implement platform agnostic read / write / allocation functions, parse commandline 5 * COPYRIGHT: Copyright 2016-2025 Mark Jansen <mark.jansen@reactos.org> 6 */ 7 8#include "xml2sdb.h" 9#include "sdbpapi.h" 10#include "sdbstringtable.h" 11#include <time.h> 12#include <stdio.h> 13#include <stdarg.h> 14 15extern "C" 16{ 17ULONG g_ShimDebugLevel = SHIM_WARN; 18 19LPVOID WINAPI SdbpAlloc(SIZE_T size) 20{ 21 return ::calloc(1, size); 22} 23 24LPVOID WINAPI SdbpReAlloc(LPVOID mem, SIZE_T size, SIZE_T oldSize) 25{ 26 LPVOID newMem = ::realloc(mem, size); 27 if (newMem && size > oldSize) 28 { 29 memset((BYTE*)newMem + oldSize, 0, size - oldSize); 30 } 31 return newMem; 32} 33 34void WINAPI SdbpFree(LPVOID mem) 35{ 36 return ::free(mem); 37} 38 39DWORD SdbpStrlen(PCWSTR string) 40{ 41 size_t len = 0; 42 while (string[len]) 43 len++; 44 return len; 45} 46 47DWORD WINAPI SdbpStrsize(PCWSTR string) 48{ 49 return (SdbpStrlen(string) + 1) * sizeof(WCHAR); 50} 51 52PDB WINAPI SdbpCreate(LPCWSTR path, PATH_TYPE type, BOOL write) 53{ 54 PDB pdb; 55 FILE* f; 56 std::string pathA(path, path + SdbpStrlen(path)); 57 58 f = fopen(pathA.c_str(), write ? "wb" : "rb"); 59 if (!f) 60 return NULL; 61 62 pdb = (PDB)SdbAlloc(sizeof(DB)); 63 pdb->file = f; 64 pdb->for_write = write; 65 66 return pdb; 67} 68 69void WINAPI SdbpFlush(PDB pdb) 70{ 71 ASSERT(pdb->for_write); 72 73 fwrite(pdb->data, pdb->write_iter, 1, (FILE*)pdb->file); 74} 75 76void WINAPI SdbCloseDatabase(PDB pdb) 77{ 78 if (!pdb) 79 return; 80 81 if (pdb->file) 82 fclose((FILE*)pdb->file); 83 if (pdb->string_buffer) 84 SdbCloseDatabase(pdb->string_buffer); 85 if (pdb->string_lookup) 86 SdbpTableDestroy(&pdb->string_lookup); 87 SdbFree(pdb->data); 88 SdbFree(pdb); 89} 90 91BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type) 92{ 93 if ((tag & TAG_TYPE_MASK) != type) 94 return FALSE; 95 return TRUE; 96} 97 98BOOL WINAPI SdbpReadData(PDB pdb, PVOID dest, DWORD offset, DWORD num) 99{ 100 DWORD size = offset + num; 101 102 /* Either overflow or no data to read */ 103 if (size <= offset) 104 return FALSE; 105 106 /* Overflow */ 107 if (pdb->size < size) 108 return FALSE; 109 110 memcpy(dest, pdb->data + offset, num); 111 return TRUE; 112} 113 114TAG WINAPI SdbGetTagFromTagID(PDB pdb, TAGID tagid) 115{ 116 TAG data; 117 if (!SdbpReadData(pdb, &data, tagid, sizeof(data))) 118 return TAG_NULL; 119 return data; 120} 121 122BOOL WINAPI SdbpCheckTagIDType(PDB pdb, TAGID tagid, WORD type) 123{ 124 TAG tag = SdbGetTagFromTagID(pdb, tagid); 125 if (tag == TAG_NULL) 126 return FALSE; 127 return SdbpCheckTagType(tag, type); 128} 129 130BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...) 131{ 132 va_list ArgList; 133 const char* LevelStr; 134 135 if ((ULONG)Level > g_ShimDebugLevel) 136 return FALSE; 137 138 switch (Level) 139 { 140 case SHIM_ERR: 141 LevelStr = "Err "; 142 break; 143 case SHIM_WARN: 144 LevelStr = "Warn"; 145 break; 146 case SHIM_INFO: 147 LevelStr = "Info"; 148 break; 149 default: 150 LevelStr = "User"; 151 break; 152 } 153 printf("[%s][%-20s] ", LevelStr, FunctionName); 154 va_start(ArgList, Format); 155 vprintf(Format, ArgList); 156 va_end(ArgList); 157 return TRUE; 158} 159 160 161#define TICKSPERSEC 10000000 162#if defined(__GNUC__) 163#define TICKSTO1970 0x019db1ded53e8000LL 164#else 165#define TICKSTO1970 0x019db1ded53e8000i64 166#endif 167VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970, 168 OUT PLARGE_INTEGER Time) 169{ 170 Time->QuadPart = ((LONGLONG)SecondsSince1970 * TICKSPERSEC) + TICKSTO1970; 171} 172 173 174} 175 176 177static bool convert(const std::string& input, const std::string& output, PlatformType platform) 178{ 179 sdbstring outputW(output.begin(), output.end()); 180 Database db; 181 if (!db.fromXml(input.c_str(), platform)) 182 { 183 printf("Failed to read XML file '%s'\n", input.c_str()); 184 return false; 185 } 186 if (!db.toSdb(outputW.c_str())) 187 { 188 printf("Failed to write SDB file '%s'\n", output.c_str()); 189 return false; 190 } 191 return true; 192} 193 194static std::string get_strarg(int argc, char* argv[], int& i) 195{ 196 if (argv[i][2] != 0) 197 return std::string(argv[i] + 2); 198 199 ++i; 200 if (i >= argc || !argv[i]) 201 return std::string(); 202 return argv[i]; 203} 204 205static void update_loglevel(int argc, char* argv[], int& i) 206{ 207 std::string value = get_strarg(argc, argv, i); 208 g_ShimDebugLevel = strtoul(value.c_str(), NULL, 10); 209} 210 211static PlatformType 212parse_platform(const std::string &input) 213{ 214 return (PlatformType)str_to_enum(input, platform_to_flag); 215} 216 217int main(int argc, char * argv[]) 218{ 219 std::string input, output; 220 PlatformType platform = PLATFORM_ANY; 221 srand(time(0)); 222 223 for (int i = 1; i < argc; ++i) 224 { 225 if (argv[i][0] != '/' && argv[i][0] != '-') 226 continue; 227 228 switch(argv[i][1]) 229 { 230 case 'i': 231 input = get_strarg(argc, argv, i); 232 break; 233 case 'o': 234 output = get_strarg(argc, argv, i); 235 break; 236 case 'l': 237 update_loglevel(argc, argv, i); 238 break; 239 case 'p': 240 platform = parse_platform(get_strarg(argc, argv, i)); 241 break; 242 } 243 } 244 if (input.empty() || output.empty()) 245 { 246 printf("Usage: %s -i <input.xml> -o <output.sdb> [-l <loglevel>] [-v <version>]\n", argv[0]); 247 printf(" -i <input.xml> : Input XML file to convert\n"); 248 printf(" -o <output.sdb> : Output SDB file to create\n"); 249 printf(" -l <loglevel> : Set log level (1=ERR, 2=WARN, 3=INFO)\n"); 250 printf(" -p <platform> : Set the runtime platform (X86, AMD64, ANY)\n"); 251 return 1; 252 } 253 254 if (!convert(input, output, platform)) 255 { 256 printf("Failed converting '%s' to '%s'\n", input.c_str(), output.c_str()); 257 return 1; 258 } 259 return 0; 260}