Reactos
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}