[LDR][APPHELP] Add a shim that disables manifest compatibility version parsing
[reactos.git] / sdk / tools / xml2sdb / main.cpp
1 /*
2 * PROJECT: xml2sdb
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Implement platform agnostic read / write / allocation functions, parse commandline
5 * COPYRIGHT: Copyright 2016,2017 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
15 extern "C"
16 {
17 ULONG g_ShimDebugLevel = SHIM_WARN;
18
19 LPVOID WINAPI SdbpAlloc(SIZE_T size)
20 {
21 return ::calloc(1, size);
22 }
23
24 LPVOID 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
34 void WINAPI SdbpFree(LPVOID mem)
35 {
36 return ::free(mem);
37 }
38
39 DWORD SdbpStrlen(PCWSTR string)
40 {
41 size_t len = 0;
42 while (string[len])
43 len++;
44 return len;
45 }
46
47 DWORD WINAPI SdbpStrsize(PCWSTR string)
48 {
49 return (SdbpStrlen(string) + 1) * sizeof(WCHAR);
50 }
51
52 PDB 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
69 void WINAPI SdbpFlush(PDB pdb)
70 {
71 ASSERT(pdb->for_write);
72
73 fwrite(pdb->data, pdb->write_iter, 1, (FILE*)pdb->file);
74 }
75
76 void 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
91 BOOL WINAPI SdbpCheckTagType(TAG tag, WORD type)
92 {
93 if ((tag & TAG_TYPE_MASK) != type)
94 return FALSE;
95 return TRUE;
96 }
97
98 BOOL 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
114 TAG 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
122 BOOL 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
130 BOOL 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
167 VOID NTAPI RtlSecondsSince1970ToTime(IN ULONG SecondsSince1970,
168 OUT PLARGE_INTEGER Time)
169 {
170 Time->QuadPart = ((LONGLONG)SecondsSince1970 * TICKSPERSEC) + TICKSTO1970;
171 }
172
173
174 }
175
176
177 bool xml_2_db(const char* xml, const WCHAR* sdb);
178
179 static bool run_one(std::string& input, std::string& output)
180 {
181 sdbstring outputW(output.begin(), output.end());
182 if (!xml_2_db(input.c_str(), outputW.c_str()))
183 return false;
184 input = output = "";
185 return true;
186 }
187
188 static std::string get_strarg(int argc, char* argv[], int& i)
189 {
190 if (argv[i][2] != 0)
191 return std::string(argv[i] + 2);
192
193 ++i;
194 if (i >= argc || !argv[i])
195 return std::string();
196 return argv[i];
197 }
198
199 static void update_loglevel(int argc, char* argv[], int& i)
200 {
201 std::string value = get_strarg(argc, argv, i);
202 g_ShimDebugLevel = strtoul(value.c_str(), NULL, 10);
203 }
204
205 int main(int argc, char * argv[])
206 {
207 std::string input, output;
208 srand(time(0));
209
210 for (int i = 1; i < argc; ++i)
211 {
212 if (argv[i][0] != '/' && argv[i][0] != '-')
213 continue;
214
215 switch(argv[i][1])
216 {
217 case 'i':
218 input = get_strarg(argc, argv, i);
219 break;
220 case 'o':
221 output = get_strarg(argc, argv, i);
222 break;
223 case 'l':
224 update_loglevel(argc, argv, i);
225 break;
226 }
227 if (input.empty() || output.empty())
228 continue;
229
230 if (!run_one(input, output))
231 {
232 printf("Failed converting '%s' to '%s'\n", input.c_str(), output.c_str());
233 return 1;
234 }
235 }
236 return 0;
237 }