2 * Copyright 2011 André Hentschel
3 * Copyright 2013 Mislav Bla\9eevic
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 #define WIN32_NO_STATUS
26 #include "wine/unicode.h"
29 static void WINAPI
SdbpFlush(PDB db
)
32 NTSTATUS Status
= NtWriteFile(db
->file
, NULL
, NULL
, NULL
, &io
,
33 db
->data
, db
->write_iter
, NULL
, NULL
);
34 if( !NT_SUCCESS(Status
))
35 SHIM_WARN("failed with 0x%lx\n", Status
);
38 static void WINAPI
SdbpWrite(PDB db
, LPCVOID data
, DWORD size
)
40 if (db
->write_iter
+ size
> db
->size
)
42 /* Round to powers of two to prevent too many reallocations */
43 while (db
->size
< db
->write_iter
+ size
) db
->size
<<= 1;
44 db
->data
= SdbReAlloc(db
->data
, db
->size
);
47 memcpy(db
->data
+ db
->write_iter
, data
, size
);
48 db
->write_iter
+= size
;
52 * Creates new shim database file
54 * If a file already exists on specified path, that file shall be overwritten.
56 * @note Use SdbCloseDatabasWrite to close the database opened with this function.
58 * @param [in] path Path to the new shim database.
59 * @param [in] type Type of path. Either DOS_PATH or NT_PATH.
61 * @return Success: Handle to the newly created shim database, NULL otherwise.
63 PDB WINAPI
SdbCreateDatabase(LPCWSTR path
, PATH_TYPE type
)
65 static const DWORD version_major
= 2, version_minor
= 1;
66 static const char* magic
= "sdbf";
69 OBJECT_ATTRIBUTES attr
;
75 if (!RtlDosPathNameToNtPathName_U(path
, &str
, NULL
, NULL
))
79 RtlInitUnicodeString(&str
, path
);
84 SHIM_ERR("Failed to allocate memory for shim database\n");
88 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
90 Status
= NtCreateFile(&db
->file
, FILE_GENERIC_WRITE
| SYNCHRONIZE
,
91 &attr
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
92 FILE_SUPERSEDE
, FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
95 RtlFreeUnicodeString(&str
);
97 if (!NT_SUCCESS(Status
))
100 SHIM_ERR("Failed to create shim database file: %lx\n", Status
);
104 db
->size
= sizeof(DWORD
) + sizeof(DWORD
) + strlen(magic
);
105 db
->data
= SdbAlloc(db
->size
);
107 SdbpWrite(db
, &version_major
, sizeof(DWORD
));
108 SdbpWrite(db
, &version_minor
, sizeof(DWORD
));
109 SdbpWrite(db
, magic
, strlen(magic
));
115 * Closes specified database and writes data to file.
117 * @param [in] db Handle to the shim database.
119 void WINAPI
SdbCloseDatabaseWrite(PDB db
)
122 SdbCloseDatabase(db
);
126 * Writes a tag-only (NULL) entry to the specified shim database.
128 * @param [in] db Handle to the shim database.
129 * @param [in] tag A tag for the entry.
131 * @return TRUE if it succeeds, FALSE if it fails.
133 BOOL WINAPI
SdbWriteNULLTag(PDB db
, TAG tag
)
135 if (!SdbpCheckTagType(tag
, TAG_TYPE_NULL
))
138 SdbpWrite(db
, &tag
, sizeof(TAG
));
143 * Writes a WORD entry to the specified shim database.
145 * @param [in] db Handle to the shim database.
146 * @param [in] tag A tag for the entry.
147 * @param [in] data WORD entry which will be written to the database.
149 * @return TRUE if it succeeds, FALSE if it fails.
151 BOOL WINAPI
SdbWriteWORDTag(PDB db
, TAG tag
, WORD data
)
153 if (!SdbpCheckTagType(tag
, TAG_TYPE_WORD
))
156 SdbpWrite(db
, &tag
, sizeof(TAG
));
157 SdbpWrite(db
, &data
, sizeof(data
));
162 * Writes a DWORD entry to the specified shim database.
164 * @param [in] db Handle to the shim database.
165 * @param [in] tag A tag for the entry.
166 * @param [in] data DWORD entry which will be written to the database.
168 * @return TRUE if it succeeds, FALSE if it fails.
170 BOOL WINAPI
SdbWriteDWORDTag(PDB db
, TAG tag
, DWORD data
)
172 if (!SdbpCheckTagType(tag
, TAG_TYPE_DWORD
))
175 SdbpWrite(db
, &tag
, sizeof(TAG
));
176 SdbpWrite(db
, &data
, sizeof(data
));
181 * Writes a DWORD entry to the specified shim database.
183 * @param [in] db Handle to the shim database.
184 * @param [in] tag A tag for the entry.
185 * @param [in] data QWORD entry which will be written to the database.
187 * @return TRUE if it succeeds, FALSE if it fails.
189 BOOL WINAPI
SdbWriteQWORDTag(PDB db
, TAG tag
, QWORD data
)
191 if (!SdbpCheckTagType(tag
, TAG_TYPE_QWORD
))
194 SdbpWrite(db
, &tag
, sizeof(TAG
));
195 SdbpWrite(db
, &data
, sizeof(data
));
200 * Writes a wide string entry to the specified shim database.
202 * @param [in] db Handle to the shim database.
203 * @param [in] tag A tag for the entry.
204 * @param [in] string Wide string entry which will be written to the database.
206 * @return TRUE if it succeeds, FALSE if it fails.
208 BOOL WINAPI
SdbWriteStringTag(PDB db
, TAG tag
, LPCWSTR string
)
212 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRING
))
215 size
= SdbpStrlen(string
);
216 SdbpWrite(db
, &tag
, sizeof(TAG
));
217 SdbpWrite(db
, &size
, sizeof(size
));
218 SdbpWrite(db
, string
, size
);
223 * Writes a stringref tag to specified database
224 * @note Reference (tagid) is not checked for validity.
226 * @param [in] db Handle to the shim database.
227 * @param [in] tag TAG which will be written.
228 * @param [in] tagid TAGID of the string tag refers to.
230 * @return TRUE if it succeeds, FALSE if it fails.
232 BOOL WINAPI
SdbWriteStringRefTag(PDB db
, TAG tag
, TAGID tagid
)
234 if (!SdbpCheckTagType(tag
, TAG_TYPE_STRINGREF
))
237 SdbpWrite(db
, &tag
, sizeof(TAG
));
238 SdbpWrite(db
, &tagid
, sizeof(tagid
));
243 * Writes data the specified shim database.
245 * @param [in] db Handle to the shim database.
246 * @param [in] tag A tag for the entry.
247 * @param [in] data Pointer to data.
248 * @param [in] size Number of bytes to write.
250 * @return TRUE if it succeeds, FALSE if it fails.
252 BOOL WINAPI
SdbWriteBinaryTag(PDB db
, TAG tag
, PBYTE data
, DWORD size
)
254 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
257 SdbpWrite(db
, &tag
, sizeof(TAG
));
258 SdbpWrite(db
, &size
, sizeof(size
));
259 SdbpWrite(db
, data
, size
);
264 * Writes data from a file to 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] path Path of the input file.
270 * @return TRUE if it succeeds, FALSE if it fails.
272 BOOL WINAPI
SdbWriteBinaryTagFromFile(PDB db
, TAG tag
, LPCWSTR path
)
276 if (!SdbpCheckTagType(tag
, TAG_TYPE_BINARY
))
279 if (!SdbpOpenMemMappedFile(path
, &mapped
))
282 SdbWriteBinaryTag(db
, tag
, mapped
.view
, mapped
.size
);
283 SdbpCloseMemMappedFile(&mapped
);
288 * Writes a list tag to specified database All subsequent SdbWrite* functions shall write to
289 * newly created list untill TAGID of that list is passed to SdbEndWriteListTag.
291 * @param [in] db Handle to the shim database.
292 * @param [in] tag TAG for the list
294 * RETURNS Success: TAGID of the newly created list, or TAGID_NULL on failure.
298 TAGID WINAPI
SdbBeginWriteListTag(PDB db
, TAG tag
)
302 if (!SdbpCheckTagType(tag
, TAG_TYPE_LIST
))
305 list_id
= db
->write_iter
;
306 SdbpWrite(db
, &tag
, sizeof(TAG
));
307 db
->write_iter
+= sizeof(DWORD
); /* reserve some memory for storing list size */
312 * Marks end of the specified list.
314 * @param [in] db Handle to the shim database.
315 * @param [in] tagid TAGID of the list.
317 * @return TRUE if it succeeds, FALSE if it fails.
319 BOOL WINAPI
SdbEndWriteListTag(PDB db
, TAGID tagid
)
321 if (!SdbpCheckTagIDType(db
, tagid
, TAG_TYPE_LIST
))
324 /* Write size of list to list tag header */
325 *(DWORD
*)&db
->data
[tagid
+ sizeof(TAG
)] = db
->write_iter
- tagid
- sizeof(TAG
);