860208454ddddd95aaa9b93c0c29f1dcd915d65d
2 * PROJECT: ReactOS Application compatibility module
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Shim database manipulation functions
5 * COPYRIGHT: Copyright 2011 André Hentschel
6 * Copyright 2013 Mislav Blažević
7 * Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org)
10 #if !defined(SDBWRITE_HOSTTOOL)
11 #define WIN32_NO_STATUS
14 #include <appcompat/sdbtypes.h>
15 #include <appcompat/sdbtagid.h>
25 #include "sdbstringtable.h"
29 BOOL WINAPI
SdbWriteStringRefTag(PDB pdb
, TAG tag
, TAGID tagid
);
30 BOOL WINAPI
SdbWriteStringTag(PDB pdb
, TAG tag
, LPCWSTR string
);
31 TAGID WINAPI
SdbBeginWriteListTag(PDB pdb
, TAG tag
);
32 BOOL WINAPI
SdbEndWriteListTag(PDB pdb
, TAGID tagid
);
35 void WINAPI
SdbCloseDatabase(PDB
);
37 /* Copy data to the allocated database */
38 static void WINAPI
SdbpWrite(PDB pdb
, const void* data
, DWORD size
)
40 ASSERT(pdb
->for_write
);
41 if (pdb
->write_iter
+ size
> pdb
->size
)
43 DWORD oldSize
= pdb
->size
;
44 /* Round to powers of two to prevent too many reallocations */
45 while (pdb
->size
< pdb
->write_iter
+ size
) pdb
->size
<<= 1;
46 pdb
->data
= SdbReAlloc(pdb
->data
, pdb
->size
, oldSize
);
49 memcpy(pdb
->data
+ pdb
->write_iter
, data
, size
);
50 pdb
->write_iter
+= size
;
53 /* Add a string to the string table (creating it when it did not exist yet),
54 returning if it succeeded or not */
55 static BOOL WINAPI
SdbpGetOrAddStringRef(PDB pdb
, LPCWSTR string
, TAGID
* tagid
)
57 PDB buf
= pdb
->string_buffer
;
58 ASSERT(pdb
->for_write
);
60 if (pdb
->string_buffer
== NULL
)
62 pdb
->string_buffer
= buf
= SdbAlloc(sizeof(DB
));
66 buf
->data
= SdbAlloc(buf
->size
);
67 buf
->for_write
= TRUE
;
68 if (buf
->data
== NULL
)
72 *tagid
= buf
->write_iter
+ sizeof(TAG
) + sizeof(DWORD
);
73 if (SdbpAddStringToTable(&pdb
->string_lookup
, string
, tagid
))
74 return SdbWriteStringTag(buf
, TAG_STRINGTABLE_ITEM
, string
);
76 return pdb
->string_lookup
!= NULL
;
79 /* Write the in-memory stringtable to the specified db */
80 static BOOL WINAPI
SdbpWriteStringtable(PDB pdb
)
83 PDB buf
= pdb
->string_buffer
;
84 if (buf
== NULL
|| pdb
->string_lookup
== NULL
)
87 table
= SdbBeginWriteListTag(pdb
, TAG_STRINGTABLE
);
88 SdbpWrite(pdb
, buf
->data
, buf
->write_iter
);
89 return SdbEndWriteListTag(pdb
, table
);
93 * Creates new shim database file
95 * If a file already exists on specified path, that file shall be overwritten.
97 * @note Use SdbCloseDatabaseWrite to close the database opened with this function.
99 * @param [in] path Path to the new shim database.
100 * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
102 * @return Success: Handle to the newly created shim database, NULL otherwise.
104 PDB WINAPI
SdbCreateDatabase(LPCWSTR path
, PATH_TYPE type
)
106 static const DWORD version_major
= 2, version_minor
= 1;
107 static const char* magic
= "sdbf";
110 pdb
= SdbpCreate(path
, type
, TRUE
);
114 pdb
->size
= sizeof(DWORD
) + sizeof(DWORD
) + strlen(magic
);
115 pdb
->data
= SdbAlloc(pdb
->size
);
117 SdbpWrite(pdb
, &version_major
, sizeof(DWORD
));
118 SdbpWrite(pdb
, &version_minor
, sizeof(DWORD
));
119 SdbpWrite(pdb
, magic
, strlen(magic
));
125 * Closes specified database and writes data to file.
127 * @param [in] pdb Handle to the shim database.
129 void WINAPI
SdbCloseDatabaseWrite(PDB pdb
)
131 ASSERT(pdb
->for_write
);
132 SdbpWriteStringtable(pdb
);
134 SdbCloseDatabase(pdb
);
138 * Writes a tag-only (NULL) entry to the specified shim database.
140 * @param [in] pdb Handle to the shim database.
141 * @param [in] tag A tag for the entry.
143 * @return TRUE if it succeeds, FALSE if it fails.
145 BOOL WINAPI
SdbWriteNULLTag(PDB pdb
, TAG tag
)
147 if (!SdbpCheckTagType(tag
, TAG_TYPE_NULL
))
150 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
155 * Writes a WORD entry to the specified shim database.
157 * @param [in] pdb Handle to the shim database.
158 * @param [in] tag A tag for the entry.
159 * @param [in] data WORD entry which will be written to the database.
161 * @return TRUE if it succeeds, FALSE if it fails.
163 BOOL WINAPI
SdbWriteWORDTag(PDB pdb
, TAG tag
, WORD data
)
165 if (!SdbpCheckTagType(tag
, TAG_TYPE_WORD
))
168 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
169 SdbpWrite(pdb
, &data
, sizeof(data
));
174 * Writes a DWORD entry to the specified shim database.
176 * @param [in] pdb Handle to the shim database.
177 * @param [in] tag A tag for the entry.
178 * @param [in] data DWORD entry which will be written to the database.
180 * @return TRUE if it succeeds, FALSE if it fails.
182 BOOL WINAPI
SdbWriteDWORDTag(PDB pdb
, TAG tag
, DWORD data
)
184 if (!SdbpCheckTagType(tag
, TAG_TYPE_DWORD
))
187 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
188 SdbpWrite(pdb
, &data
, sizeof(data
));
193 * Writes a DWORD entry to the specified shim database.
195 * @param [in] pdb Handle to the shim database.
196 * @param [in] tag A tag for the entry.
197 * @param [in] data QWORD entry which will be written to the database.
199 * @return TRUE if it succeeds, FALSE if it fails.
201 BOOL WINAPI
SdbWriteQWORDTag(PDB pdb
, TAG tag
, QWORD data
)
203 if (!SdbpCheckTagType(tag
, TAG_TYPE_QWORD
))
206 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
207 SdbpWrite(pdb
, &data
, sizeof(data
));
212 * Writes a wide string entry to the specified shim database.
214 * @param [in] pdb Handle to the shim database.
215 * @param [in] tag A tag for the entry.
216 * @param [in] string Wide string entry which will be written to the database.
218 * @return TRUE if it succeeds, FALSE if it fails.
220 BOOL WINAPI
SdbWriteStringTag(PDB pdb
, TAG tag
, LPCWSTR string
)
224 if (SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
227 if (!SdbpGetOrAddStringRef(pdb
, string
, &tagid
))
230 return SdbWriteStringRefTag(pdb
, tag
, tagid
);
233 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRING
))
236 size
= SdbpStrsize(string
);
237 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
238 SdbpWrite(pdb
, &size
, sizeof(size
));
239 SdbpWrite(pdb
, string
, size
);
244 * Writes a stringref tag to specified database
245 * @note Reference (tagid) is not checked for validity.
247 * @param [in] pdb Handle to the shim database.
248 * @param [in] tag TAG which will be written.
249 * @param [in] tagid TAGID of the string tag refers to.
251 * @return TRUE if it succeeds, FALSE if it fails.
253 BOOL WINAPI
SdbWriteStringRefTag(PDB pdb
, TAG tag
, TAGID tagid
)
255 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
258 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
259 SdbpWrite(pdb
, &tagid
, sizeof(tagid
));
264 * Writes data the specified shim database.
266 * @param [in] pdb Handle to the shim database.
267 * @param [in] tag A tag for the entry.
268 * @param [in] data Pointer to data.
269 * @param [in] size Number of bytes to write.
271 * @return TRUE if it succeeds, FALSE if it fails.
273 BOOL WINAPI
SdbWriteBinaryTag(PDB pdb
, TAG tag
, const BYTE
* data
, DWORD size
)
275 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
278 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
279 SdbpWrite(pdb
, &size
, sizeof(size
));
280 SdbpWrite(pdb
, data
, size
);
284 #if !defined(SDBWRITE_HOSTTOOL)
286 * Writes data from a file to the specified shim database.
288 * @param [in] pdb Handle to the shim database.
289 * @param [in] tag A tag for the entry.
290 * @param [in] path Path of the input file.
292 * @return TRUE if it succeeds, FALSE if it fails.
294 BOOL WINAPI
SdbWriteBinaryTagFromFile(PDB pdb
, TAG tag
, LPCWSTR path
)
298 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
301 if (!SdbpOpenMemMappedFile(path
, &mapped
))
304 SdbWriteBinaryTag(pdb
, tag
, mapped
.view
, mapped
.size
);
305 SdbpCloseMemMappedFile(&mapped
);
311 * Writes a list tag to specified database All subsequent SdbWrite* functions shall write to
312 * newly created list untill TAGID of that list is passed to SdbEndWriteListTag.
314 * @param [in] pdb Handle to the shim database.
315 * @param [in] tag TAG for the list
317 * RETURNS Success: TAGID of the newly created list, or TAGID_NULL on failure.
321 TAGID WINAPI
SdbBeginWriteListTag(PDB pdb
, TAG tag
)
326 if (!SdbpCheckTagType(tag
, TAG_TYPE_LIST
))
329 list_id
= pdb
->write_iter
;
330 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
331 SdbpWrite(pdb
, &dum
, sizeof(dum
)); /* reserve some memory for storing list size */
336 * Marks end of the specified list.
338 * @param [in] pdb Handle to the shim database.
339 * @param [in] tagid TAGID of the list.
341 * @return TRUE if it succeeds, FALSE if it fails.
343 BOOL WINAPI
SdbEndWriteListTag(PDB pdb
, TAGID tagid
)
345 ASSERT(pdb
->for_write
);
347 if (!SdbpCheckTagIDType(pdb
, tagid
, TAG_TYPE_LIST
))
350 /* Write size of list to list tag header */
351 *(DWORD
*)&pdb
->data
[tagid
+ sizeof(TAG
)] = pdb
->write_iter
- tagid
- sizeof(TAG
) - sizeof(TAGID
);