Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355/* * PROJECT: ReactOS Application compatibility module * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Shim database manipulation functions * COPYRIGHT: Copyright 2011 André Hentschel * Copyright 2013 Mislav Blažević * Copyright 2015-2025 Mark Jansen <mark.jansen@reactos.org> */
#if !defined(SDBWRITE_HOSTTOOL)#define WIN32_NO_STATUS#include "windef.h"#include "ntndk.h"#include <appcompat/sdbtypes.h>#include <appcompat/sdbtagid.h>#else#include <typedefs.h>#include <guiddef.h>#include <sdbtypes.h>#include <sdbtagid.h>#endif
#include "sdbpapi.h"#include "sdbstringtable.h"
/* Local functions */BOOL WINAPI SdbWriteStringRefTag(PDB pdb, TAG tag, TAGID tagid);BOOL WINAPI SdbWriteStringTag(PDB pdb, TAG tag, LPCWSTR string);TAGID WINAPI SdbBeginWriteListTag(PDB pdb, TAG tag);BOOL WINAPI SdbEndWriteListTag(PDB pdb, TAGID tagid);
/* sdbapi.c */void WINAPI SdbCloseDatabase(PDB);
/* Copy data to the allocated database */static void WINAPI SdbpWrite(PDB pdb, const void* data, DWORD size){ ASSERT(pdb->for_write); if (pdb->write_iter + size > pdb->size) { DWORD oldSize = pdb->size; /* Round to powers of two to prevent too many reallocations */ while (pdb->size < pdb->write_iter + size) pdb->size <<= 1; pdb->data = SdbReAlloc(pdb->data, pdb->size, oldSize); }
memcpy(pdb->data + pdb->write_iter, data, size); pdb->write_iter += size;}
/* Add a string to the string table (creating it when it did not exist yet), returning if it succeeded or not */static BOOL WINAPI SdbpGetOrAddStringRef(PDB pdb, LPCWSTR string, TAGID* tagid){ PDB buf = pdb->string_buffer; ASSERT(pdb->for_write);
if (pdb->string_buffer == NULL) { pdb->string_buffer = buf = SdbAlloc(sizeof(DB)); if (buf == NULL) return FALSE; buf->size = 128; buf->data = SdbAlloc(buf->size); buf->for_write = TRUE; if (buf->data == NULL) return FALSE; }
*tagid = buf->write_iter + sizeof(TAG) + sizeof(DWORD); if (SdbpAddStringToTable(&pdb->string_lookup, string, tagid)) return SdbWriteStringTag(buf, TAG_STRINGTABLE_ITEM, string);
return pdb->string_lookup != NULL;}
/* Write the in-memory stringtable to the specified db */static BOOL WINAPI SdbpWriteStringtable(PDB pdb){ TAGID table; PDB buf = pdb->string_buffer; if (buf == NULL || pdb->string_lookup == NULL) return FALSE;
table = SdbBeginWriteListTag(pdb, TAG_STRINGTABLE); SdbpWrite(pdb, buf->data, buf->write_iter); return SdbEndWriteListTag(pdb, table);}
/** * Creates new shim database file * * If a file already exists on specified path, that file shall be overwritten. * * @note Use SdbCloseDatabaseWrite to close the database opened with this function. * * @param [in] path Path to the new shim database. * @param [in] type Type of path. Either DOS_PATH or NT_PATH. * * @return Success: Handle to the newly created shim database, NULL otherwise. */PDB WINAPI SdbCreateDatabase(LPCWSTR path, PATH_TYPE type){ static const DWORD version_major = 2, version_minor = 1; static const char* magic = "sdbf"; PDB pdb;
pdb = SdbpCreate(path, type, TRUE); if (!pdb) return NULL;
pdb->size = sizeof(DWORD) + sizeof(DWORD) + (DWORD)strlen(magic); pdb->data = SdbAlloc(pdb->size);
SdbpWrite(pdb, &version_major, sizeof(DWORD)); SdbpWrite(pdb, &version_minor, sizeof(DWORD)); SdbpWrite(pdb, magic, (DWORD)strlen(magic));
return pdb;}
/** * Closes specified database and writes data to file. * * @param [in] pdb Handle to the shim database. */void WINAPI SdbCloseDatabaseWrite(PDB pdb){ ASSERT(pdb->for_write); SdbpWriteStringtable(pdb); SdbpFlush(pdb); SdbCloseDatabase(pdb);}
/** * Writes a tag-only (NULL) entry to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteNULLTag(PDB pdb, TAG tag){ if (!SdbpCheckTagType(tag, TAG_TYPE_NULL)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); return TRUE;}
/** * Writes a WORD entry to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] data WORD entry which will be written to the database. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteWORDTag(PDB pdb, TAG tag, WORD data){ if (!SdbpCheckTagType(tag, TAG_TYPE_WORD)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &data, sizeof(data)); return TRUE;}
/** * Writes a DWORD entry to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] data DWORD entry which will be written to the database. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteDWORDTag(PDB pdb, TAG tag, DWORD data){ if (!SdbpCheckTagType(tag, TAG_TYPE_DWORD)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &data, sizeof(data)); return TRUE;}
/** * Writes a DWORD entry to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] data QWORD entry which will be written to the database. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteQWORDTag(PDB pdb, TAG tag, QWORD data){ if (!SdbpCheckTagType(tag, TAG_TYPE_QWORD)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &data, sizeof(data)); return TRUE;}
/** * Writes a wide string entry to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] string Wide string entry which will be written to the database. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteStringTag(PDB pdb, TAG tag, LPCWSTR string){ DWORD size;
if (SdbpCheckTagType(tag, TAG_TYPE_STRINGREF)) { TAGID tagid = 0; if (!SdbpGetOrAddStringRef(pdb, string, &tagid)) return FALSE;
return SdbWriteStringRefTag(pdb, tag, tagid); }
if (!SdbpCheckTagType(tag, TAG_TYPE_STRING)) return FALSE;
size = SdbpStrsize(string); SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &size, sizeof(size)); SdbpWrite(pdb, string, size); return TRUE;}
/** * Writes a stringref tag to specified database * @note Reference (tagid) is not checked for validity. * * @param [in] pdb Handle to the shim database. * @param [in] tag TAG which will be written. * @param [in] tagid TAGID of the string tag refers to. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteStringRefTag(PDB pdb, TAG tag, TAGID tagid){ if (!SdbpCheckTagType(tag, TAG_TYPE_STRINGREF)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &tagid, sizeof(tagid)); return TRUE;}
/** * Writes data the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] data Pointer to data. * @param [in] size Number of bytes to write. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteBinaryTag(PDB pdb, TAG tag, const BYTE* data, DWORD size){ if (!SdbpCheckTagType(tag, TAG_TYPE_BINARY)) return FALSE;
SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &size, sizeof(size)); SdbpWrite(pdb, data, size); return TRUE;}
#if !defined(SDBWRITE_HOSTTOOL)/** * Writes data from a file to the specified shim database. * * @param [in] pdb Handle to the shim database. * @param [in] tag A tag for the entry. * @param [in] path Path of the input file. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbWriteBinaryTagFromFile(PDB pdb, TAG tag, LPCWSTR path){ MEMMAPPED mapped;
if (!SdbpCheckTagType(tag, TAG_TYPE_BINARY)) return FALSE;
if (!SdbpOpenMemMappedFile(path, &mapped)) return FALSE;
SdbWriteBinaryTag(pdb, tag, mapped.view, mapped.size); SdbpCloseMemMappedFile(&mapped); return TRUE;}#endif
/** * Writes a list tag to specified database All subsequent SdbWrite* functions shall write to * newly created list untill TAGID of that list is passed to SdbEndWriteListTag. * * @param [in] pdb Handle to the shim database. * @param [in] tag TAG for the list * * RETURNS Success: TAGID of the newly created list, or TAGID_NULL on failure. * * @return A TAGID. */TAGID WINAPI SdbBeginWriteListTag(PDB pdb, TAG tag){ TAGID list_id; DWORD dum = 0;
if (!SdbpCheckTagType(tag, TAG_TYPE_LIST)) return TAGID_NULL;
list_id = pdb->write_iter; SdbpWrite(pdb, &tag, sizeof(TAG)); SdbpWrite(pdb, &dum, sizeof(dum)); /* reserve some memory for storing list size */ return list_id;}
/** * Marks end of the specified list. * * @param [in] pdb Handle to the shim database. * @param [in] tagid TAGID of the list. * * @return TRUE if it succeeds, FALSE if it fails. */BOOL WINAPI SdbEndWriteListTag(PDB pdb, TAGID tagid){ ASSERT(pdb->for_write);
if (!SdbpCheckTagIDType(pdb, tagid, TAG_TYPE_LIST)) return FALSE;
/* Write size of list to list tag header */ *(DWORD*)&pdb->data[tagid + sizeof(TAG)] = pdb->write_iter - tagid - sizeof(TAG) - sizeof(TAGID); return TRUE;}