1ee1b0a7625852e9d4f106d459c2328f6879a9c5
2 * Copyright 2011 André Hentschel
3 * Copyright 2013 Mislav Blažević
4 * Copyright 2015,2016 Mark Jansen
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 db
, TAG tag
, TAGID tagid
);
38 BOOL WINAPI
SdbWriteStringTag(PDB db
, TAG tag
, LPCWSTR string
);
39 TAGID WINAPI
SdbBeginWriteListTag(PDB db
, TAG tag
);
40 BOOL WINAPI
SdbEndWriteListTag(PDB db
, TAGID tagid
);
43 void WINAPI
SdbCloseDatabase(PDB
);
46 static void WINAPI
SdbpWrite(PDB db
, const void* data
, DWORD size
)
48 if (db
->write_iter
+ size
> db
->size
)
50 DWORD oldSize
= db
->size
;
51 /* Round to powers of two to prevent too many reallocations */
52 while (db
->size
< db
->write_iter
+ size
) db
->size
<<= 1;
53 db
->data
= SdbReAlloc(db
->data
, db
->size
, oldSize
);
56 memcpy(db
->data
+ db
->write_iter
, data
, size
);
57 db
->write_iter
+= size
;
60 static BOOL WINAPI
SdbpGetOrAddStringRef(PDB db
, LPCWSTR string
, TAGID
* tagid
)
62 PDB buf
= db
->string_buffer
;
63 if (db
->string_buffer
== NULL
)
65 db
->string_buffer
= buf
= SdbpAlloc(sizeof(DB
));
69 buf
->data
= SdbAlloc(buf
->size
);
70 if (buf
->data
== NULL
)
74 *tagid
= buf
->write_iter
+ sizeof(TAG
) + sizeof(DWORD
);
75 if (SdbpAddStringToTable(&db
->string_lookup
, string
, tagid
))
76 return SdbWriteStringTag(buf
, TAG_STRINGTABLE_ITEM
, string
);
78 return db
->string_lookup
!= NULL
;
81 static BOOL WINAPI
SdbpWriteStringtable(PDB db
)
84 PDB buf
= db
->string_buffer
;
85 if (buf
== NULL
|| db
->string_lookup
== NULL
)
88 table
= SdbBeginWriteListTag(db
, TAG_STRINGTABLE
);
89 SdbpWrite(db
, buf
->data
, buf
->write_iter
);
90 return SdbEndWriteListTag(db
, table
);
94 * Creates new shim database file
96 * If a file already exists on specified path, that file shall be overwritten.
98 * @note Use SdbCloseDatabaseWrite to close the database opened with this function.
100 * @param [in] path Path to the new shim database.
101 * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
103 * @return Success: Handle to the newly created shim database, NULL otherwise.
105 PDB WINAPI
SdbCreateDatabase(LPCWSTR path
, PATH_TYPE type
)
107 static const DWORD version_major
= 2, version_minor
= 1;
108 static const char* magic
= "sdbf";
111 db
= SdbpCreate(path
, type
, TRUE
);
115 db
->size
= sizeof(DWORD
) + sizeof(DWORD
) + strlen(magic
);
116 db
->data
= SdbAlloc(db
->size
);
118 SdbpWrite(db
, &version_major
, sizeof(DWORD
));
119 SdbpWrite(db
, &version_minor
, sizeof(DWORD
));
120 SdbpWrite(db
, magic
, strlen(magic
));
126 * Closes specified database and writes data to file.
128 * @param [in] db Handle to the shim database.
130 void WINAPI
SdbCloseDatabaseWrite(PDB db
)
132 SdbpWriteStringtable(db
);
134 SdbCloseDatabase(db
);
138 * Writes a tag-only (NULL) entry to the specified shim database.
140 * @param [in] db 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 db
, TAG tag
)
147 if (!SdbpCheckTagType(tag
, TAG_TYPE_NULL
))
150 SdbpWrite(db
, &tag
, sizeof(TAG
));
155 * Writes a WORD entry to the specified shim database.
157 * @param [in] db 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 db
, TAG tag
, WORD data
)
165 if (!SdbpCheckTagType(tag
, TAG_TYPE_WORD
))
168 SdbpWrite(db
, &tag
, sizeof(TAG
));
169 SdbpWrite(db
, &data
, sizeof(data
));
174 * Writes a DWORD entry to the specified shim database.
176 * @param [in] db 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 db
, TAG tag
, DWORD data
)
184 if (!SdbpCheckTagType(tag
, TAG_TYPE_DWORD
))
187 SdbpWrite(db
, &tag
, sizeof(TAG
));
188 SdbpWrite(db
, &data
, sizeof(data
));
193 * Writes a DWORD entry to the specified shim database.
195 * @param [in] db 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 db
, TAG tag
, QWORD data
)
203 if (!SdbpCheckTagType(tag
, TAG_TYPE_QWORD
))
206 SdbpWrite(db
, &tag
, sizeof(TAG
));
207 SdbpWrite(db
, &data
, sizeof(data
));
212 * Writes a wide string entry to the specified shim database.
214 * @param [in] db 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 db
, TAG tag
, LPCWSTR string
)
224 if (SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
227 if (!SdbpGetOrAddStringRef(db
, string
, &tagid
))
230 return SdbWriteStringRefTag(db
, tag
, tagid
);
233 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRING
))
236 size
= SdbpStrsize(string
);
237 SdbpWrite(db
, &tag
, sizeof(TAG
));
238 SdbpWrite(db
, &size
, sizeof(size
));
239 SdbpWrite(db
, string
, size
);
244 * Writes a stringref tag to specified database
245 * @note Reference (tagid) is not checked for validity.
247 * @param [in] db 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 db
, TAG tag
, TAGID tagid
)
255 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
258 SdbpWrite(db
, &tag
, sizeof(TAG
));
259 SdbpWrite(db
, &tagid
, sizeof(tagid
));
264 * Writes data the specified shim database.
266 * @param [in] db 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 db
, TAG tag
, const BYTE
* data
, DWORD size
)
275 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
278 SdbpWrite(db
, &tag
, sizeof(TAG
));
279 SdbpWrite(db
, &size
, sizeof(size
));
280 SdbpWrite(db
, data
, size
);
284 #if !defined(SDBWRITE_HOSTTOOL)
286 * Writes data from a file to the specified shim database.
288 * @param [in] db 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 db
, TAG tag
, LPCWSTR path
)
298 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
301 if (!SdbpOpenMemMappedFile(path
, &mapped
))
304 SdbWriteBinaryTag(db
, 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] db 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 db
, TAG tag
)
326 if (!SdbpCheckTagType(tag
, TAG_TYPE_LIST
))
329 list_id
= db
->write_iter
;
330 SdbpWrite(db
, &tag
, sizeof(TAG
));
331 SdbpWrite(db
, &dum
, sizeof(dum
)); /* reserve some memory for storing list size */
336 * Marks end of the specified list.
338 * @param [in] db 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 db
, TAGID tagid
)
345 if (!SdbpCheckTagIDType(db
, tagid
, TAG_TYPE_LIST
))
348 /* Write size of list to list tag header */
349 *(DWORD
*)&db
->data
[tagid
+ sizeof(TAG
)] = db
->write_iter
- tagid
- sizeof(TAG
) - sizeof(TAGID
);