2 * Copyright 2011 André Hentschel
3 * Copyright 2013 Mislav Blažević
4 * Copyright 2015-2017 Mark Jansen (mark.jansen@reactos.org)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if !defined(SDBWRITE_HOSTTOOL)
22 #define WIN32_NO_STATUS
33 #include "sdbstringtable.h"
37 BOOL WINAPI
SdbWriteStringRefTag(PDB pdb
, TAG tag
, TAGID tagid
);
38 BOOL WINAPI
SdbWriteStringTag(PDB pdb
, TAG tag
, LPCWSTR string
);
39 TAGID WINAPI
SdbBeginWriteListTag(PDB pdb
, TAG tag
);
40 BOOL WINAPI
SdbEndWriteListTag(PDB pdb
, TAGID tagid
);
43 void WINAPI
SdbCloseDatabase(PDB
);
45 /* Copy data to the allocated database */
46 static void WINAPI
SdbpWrite(PDB pdb
, const void* data
, DWORD size
)
48 ASSERT(pdb
->for_write
);
49 if (pdb
->write_iter
+ size
> pdb
->size
)
51 DWORD oldSize
= pdb
->size
;
52 /* Round to powers of two to prevent too many reallocations */
53 while (pdb
->size
< pdb
->write_iter
+ size
) pdb
->size
<<= 1;
54 pdb
->data
= SdbReAlloc(pdb
->data
, pdb
->size
, oldSize
);
57 memcpy(pdb
->data
+ pdb
->write_iter
, data
, size
);
58 pdb
->write_iter
+= size
;
61 /* Add a string to the string table (creating it when it did not exist yet),
62 returning if it succeeded or not */
63 static BOOL WINAPI
SdbpGetOrAddStringRef(PDB pdb
, LPCWSTR string
, TAGID
* tagid
)
65 PDB buf
= pdb
->string_buffer
;
66 ASSERT(pdb
->for_write
);
68 if (pdb
->string_buffer
== NULL
)
70 pdb
->string_buffer
= buf
= SdbAlloc(sizeof(DB
));
74 buf
->data
= SdbAlloc(buf
->size
);
75 buf
->for_write
= TRUE
;
76 if (buf
->data
== NULL
)
80 *tagid
= buf
->write_iter
+ sizeof(TAG
) + sizeof(DWORD
);
81 if (SdbpAddStringToTable(&pdb
->string_lookup
, string
, tagid
))
82 return SdbWriteStringTag(buf
, TAG_STRINGTABLE_ITEM
, string
);
84 return pdb
->string_lookup
!= NULL
;
87 /* Write the in-memory stringtable to the specified db */
88 static BOOL WINAPI
SdbpWriteStringtable(PDB pdb
)
91 PDB buf
= pdb
->string_buffer
;
92 if (buf
== NULL
|| pdb
->string_lookup
== NULL
)
95 table
= SdbBeginWriteListTag(pdb
, TAG_STRINGTABLE
);
96 SdbpWrite(pdb
, buf
->data
, buf
->write_iter
);
97 return SdbEndWriteListTag(pdb
, table
);
101 * Creates new shim database file
103 * If a file already exists on specified path, that file shall be overwritten.
105 * @note Use SdbCloseDatabaseWrite to close the database opened with this function.
107 * @param [in] path Path to the new shim database.
108 * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
110 * @return Success: Handle to the newly created shim database, NULL otherwise.
112 PDB WINAPI
SdbCreateDatabase(LPCWSTR path
, PATH_TYPE type
)
114 static const DWORD version_major
= 2, version_minor
= 1;
115 static const char* magic
= "sdbf";
118 pdb
= SdbpCreate(path
, type
, TRUE
);
122 pdb
->size
= sizeof(DWORD
) + sizeof(DWORD
) + strlen(magic
);
123 pdb
->data
= SdbAlloc(pdb
->size
);
125 SdbpWrite(pdb
, &version_major
, sizeof(DWORD
));
126 SdbpWrite(pdb
, &version_minor
, sizeof(DWORD
));
127 SdbpWrite(pdb
, magic
, strlen(magic
));
133 * Closes specified database and writes data to file.
135 * @param [in] pdb Handle to the shim database.
137 void WINAPI
SdbCloseDatabaseWrite(PDB pdb
)
139 ASSERT(pdb
->for_write
);
140 SdbpWriteStringtable(pdb
);
142 SdbCloseDatabase(pdb
);
146 * Writes a tag-only (NULL) entry to the specified shim database.
148 * @param [in] pdb Handle to the shim database.
149 * @param [in] tag A tag for the entry.
151 * @return TRUE if it succeeds, FALSE if it fails.
153 BOOL WINAPI
SdbWriteNULLTag(PDB pdb
, TAG tag
)
155 if (!SdbpCheckTagType(tag
, TAG_TYPE_NULL
))
158 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
163 * Writes a WORD entry to the specified shim database.
165 * @param [in] pdb Handle to the shim database.
166 * @param [in] tag A tag for the entry.
167 * @param [in] data WORD entry which will be written to the database.
169 * @return TRUE if it succeeds, FALSE if it fails.
171 BOOL WINAPI
SdbWriteWORDTag(PDB pdb
, TAG tag
, WORD data
)
173 if (!SdbpCheckTagType(tag
, TAG_TYPE_WORD
))
176 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
177 SdbpWrite(pdb
, &data
, sizeof(data
));
182 * Writes a DWORD entry to the specified shim database.
184 * @param [in] pdb Handle to the shim database.
185 * @param [in] tag A tag for the entry.
186 * @param [in] data DWORD entry which will be written to the database.
188 * @return TRUE if it succeeds, FALSE if it fails.
190 BOOL WINAPI
SdbWriteDWORDTag(PDB pdb
, TAG tag
, DWORD data
)
192 if (!SdbpCheckTagType(tag
, TAG_TYPE_DWORD
))
195 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
196 SdbpWrite(pdb
, &data
, sizeof(data
));
201 * Writes a DWORD entry to the specified shim database.
203 * @param [in] pdb Handle to the shim database.
204 * @param [in] tag A tag for the entry.
205 * @param [in] data QWORD entry which will be written to the database.
207 * @return TRUE if it succeeds, FALSE if it fails.
209 BOOL WINAPI
SdbWriteQWORDTag(PDB pdb
, TAG tag
, QWORD data
)
211 if (!SdbpCheckTagType(tag
, TAG_TYPE_QWORD
))
214 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
215 SdbpWrite(pdb
, &data
, sizeof(data
));
220 * Writes a wide string entry to the specified shim database.
222 * @param [in] pdb Handle to the shim database.
223 * @param [in] tag A tag for the entry.
224 * @param [in] string Wide string entry which will be written to the database.
226 * @return TRUE if it succeeds, FALSE if it fails.
228 BOOL WINAPI
SdbWriteStringTag(PDB pdb
, TAG tag
, LPCWSTR string
)
232 if (SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
235 if (!SdbpGetOrAddStringRef(pdb
, string
, &tagid
))
238 return SdbWriteStringRefTag(pdb
, tag
, tagid
);
241 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRING
))
244 size
= SdbpStrsize(string
);
245 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
246 SdbpWrite(pdb
, &size
, sizeof(size
));
247 SdbpWrite(pdb
, string
, size
);
252 * Writes a stringref tag to specified database
253 * @note Reference (tagid) is not checked for validity.
255 * @param [in] pdb Handle to the shim database.
256 * @param [in] tag TAG which will be written.
257 * @param [in] tagid TAGID of the string tag refers to.
259 * @return TRUE if it succeeds, FALSE if it fails.
261 BOOL WINAPI
SdbWriteStringRefTag(PDB pdb
, TAG tag
, TAGID tagid
)
263 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
266 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
267 SdbpWrite(pdb
, &tagid
, sizeof(tagid
));
272 * Writes data the specified shim database.
274 * @param [in] pdb Handle to the shim database.
275 * @param [in] tag A tag for the entry.
276 * @param [in] data Pointer to data.
277 * @param [in] size Number of bytes to write.
279 * @return TRUE if it succeeds, FALSE if it fails.
281 BOOL WINAPI
SdbWriteBinaryTag(PDB pdb
, TAG tag
, const BYTE
* data
, DWORD size
)
283 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
286 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
287 SdbpWrite(pdb
, &size
, sizeof(size
));
288 SdbpWrite(pdb
, data
, size
);
292 #if !defined(SDBWRITE_HOSTTOOL)
294 * Writes data from a file to the specified shim database.
296 * @param [in] pdb Handle to the shim database.
297 * @param [in] tag A tag for the entry.
298 * @param [in] path Path of the input file.
300 * @return TRUE if it succeeds, FALSE if it fails.
302 BOOL WINAPI
SdbWriteBinaryTagFromFile(PDB pdb
, TAG tag
, LPCWSTR path
)
306 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
309 if (!SdbpOpenMemMappedFile(path
, &mapped
))
312 SdbWriteBinaryTag(pdb
, tag
, mapped
.view
, mapped
.size
);
313 SdbpCloseMemMappedFile(&mapped
);
319 * Writes a list tag to specified database All subsequent SdbWrite* functions shall write to
320 * newly created list untill TAGID of that list is passed to SdbEndWriteListTag.
322 * @param [in] pdb Handle to the shim database.
323 * @param [in] tag TAG for the list
325 * RETURNS Success: TAGID of the newly created list, or TAGID_NULL on failure.
329 TAGID WINAPI
SdbBeginWriteListTag(PDB pdb
, TAG tag
)
334 if (!SdbpCheckTagType(tag
, TAG_TYPE_LIST
))
337 list_id
= pdb
->write_iter
;
338 SdbpWrite(pdb
, &tag
, sizeof(TAG
));
339 SdbpWrite(pdb
, &dum
, sizeof(dum
)); /* reserve some memory for storing list size */
344 * Marks end of the specified list.
346 * @param [in] pdb Handle to the shim database.
347 * @param [in] tagid TAGID of the list.
349 * @return TRUE if it succeeds, FALSE if it fails.
351 BOOL WINAPI
SdbEndWriteListTag(PDB pdb
, TAGID tagid
)
353 ASSERT(pdb
->for_write
);
355 if (!SdbpCheckTagIDType(pdb
, tagid
, TAG_TYPE_LIST
))
358 /* Write size of list to list tag header */
359 *(DWORD
*)&pdb
->data
[tagid
+ sizeof(TAG
)] = pdb
->write_iter
- tagid
- sizeof(TAG
) - sizeof(TAGID
);