#include "ntndk.h"
#include "strsafe.h"
#include "apphelp.h"
+#include "sdbstringtable.h"
#include "wine/unicode.h"
return mem;
}
-LPVOID SdbpReAlloc(LPVOID mem, SIZE_T size
+LPVOID SdbpReAlloc(LPVOID mem, SIZE_T size, SIZE_T oldSize
#if SDBAPI_DEBUG_ALLOC
, int line, const char* file
#endif
HeapFree(SdbpHeap(), 0, mem);
}
-PDB WINAPI SdbpCreate(void)
+PDB WINAPI SdbpCreate(LPCWSTR path, PATH_TYPE type, BOOL write)
{
- PDB db = (PDB)SdbAlloc(sizeof(DB));
+ NTSTATUS Status;
+ IO_STATUS_BLOCK io;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ PDB db;
+
+ if (type == DOS_PATH)
+ {
+ if (!RtlDosPathNameToNtPathName_U(path, &str, NULL, NULL))
+ return NULL;
+ }
+ else
+ RtlInitUnicodeString(&str, path);
+
/* SdbAlloc zeroes the memory. */
+ db = (PDB)SdbAlloc(sizeof(DB));
+ if (!db)
+ {
+ SHIM_ERR("Failed to allocate memory for shim database\n");
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ Status = NtCreateFile(&db->file, (write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ )| SYNCHRONIZE,
+ &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
+ write ? FILE_SUPERSEDE : FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
+
+ if (type == DOS_PATH)
+ RtlFreeUnicodeString(&str);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SdbCloseDatabase(db);
+ SHIM_ERR("Failed to create shim database file: %lx\n", Status);
+ return NULL;
+ }
+
return db;
}
+
+void WINAPI SdbpFlush(PDB db)
+{
+ IO_STATUS_BLOCK io;
+ NTSTATUS Status = NtWriteFile(db->file, NULL, NULL, NULL, &io,
+ db->data, db->write_iter, NULL, NULL);
+ if( !NT_SUCCESS(Status))
+ SHIM_WARN("failed with 0x%lx\n", Status);
+}
+
DWORD SdbpStrlen(PCWSTR string)
{
- return (lstrlenW(string) + 1) * sizeof(WCHAR);
+ return lstrlenW(string);
+}
+
+DWORD SdbpStrsize(PCWSTR string)
+{
+ return (SdbpStrlen(string) + 1) * sizeof(WCHAR);
}
PWSTR SdbpStrDup(LPCWSTR string)
{
- PWSTR ret = SdbpAlloc(SdbpStrlen(string));
+ PWSTR ret = SdbpAlloc(SdbpStrsize(string));
lstrcpyW(ret, string);
return ret;
}
PDB SdbpOpenDatabase(LPCWSTR path, PATH_TYPE type, PDWORD major, PDWORD minor)
{
- UNICODE_STRING str;
- OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
PDB db;
NTSTATUS Status;
BYTE header[12];
- if (type == DOS_PATH)
- {
- if (!RtlDosPathNameToNtPathName_U(path, &str, NULL, NULL))
- return NULL;
- }
- else
- RtlInitUnicodeString(&str, path);
-
- db = SdbpCreate();
+ db = SdbpCreate(path, type, FALSE);
if (!db)
- {
- SHIM_ERR("Failed to allocate memory for shim database\n");
return NULL;
- }
-
- InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, NULL, NULL);
-
- Status = NtCreateFile(&db->file, FILE_GENERIC_READ | SYNCHRONIZE,
- &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
- FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
-
- if (type == DOS_PATH)
- RtlFreeUnicodeString(&str);
-
- if (!NT_SUCCESS(Status))
- {
- SdbCloseDatabase(db);
- SHIM_ERR("Failed to open shim database file: 0x%lx\n", Status);
- return NULL;
- }
db->size = GetFileSize(db->file, NULL);
db->data = SdbAlloc(db->size);
if (!db)
return NULL;
- if (major != 2)
+ if (major != 2 && major != 3)
{
SdbCloseDatabase(db);
SHIM_ERR("Invalid shim database version\n");
if (db->file)
NtClose(db->file);
+ if (db->string_buffer)
+ SdbCloseDatabase(db->string_buffer);
+ if (db->string_lookup)
+ SdbpTableDestroy(&db->string_lookup);
SdbFree(db->data);
SdbFree(db);
}
-/**
- * Retrieves AppPatch directory.
- *
- * @param [in] db Handle to the shim database.
- * @param [out] path Pointer to memory in which path shall be written.
- * @param [in] size Size of the buffer in characters.
- */
-BOOL WINAPI SdbGetAppPatchDir(HSDB db, LPWSTR path, DWORD size)
-{
- static WCHAR* default_dir = NULL;
- static CONST WCHAR szAppPatch[] = {'\\','A','p','p','P','a','t','c','h',0};
-
- if(!default_dir)
- {
- WCHAR* tmp = NULL;
- UINT len = GetSystemWindowsDirectoryW(NULL, 0) + lstrlenW(szAppPatch);
- tmp = SdbAlloc((len + 1)* sizeof(WCHAR));
- if(tmp)
- {
- UINT r = GetSystemWindowsDirectoryW(tmp, len+1);
- if (r && r < len)
- {
- if (SUCCEEDED(StringCchCatW(tmp, len+1, szAppPatch)))
- {
- if(InterlockedCompareExchangePointer((void**)&default_dir, tmp, NULL) == NULL)
- tmp = NULL;
- }
- }
- if (tmp)
- SdbFree(tmp);
- }
- }
-
- /* In case function fails, path holds empty string */
- if (size > 0)
- *path = 0;
-
- if (!db)
- {
- return SUCCEEDED(StringCchCopyW(path, size, default_dir));
- }
- else
- {
- /* fixme */
- return FALSE;
- }
-}
-
/**
* Parses a string to retrieve a GUID.
*
return TRUE;
}
+
+/**
+ * Find the first named child tag.
+ *
+ * @param [in] database The database.
+ * @param [in] root The tag to start at
+ * @param [in] find The tag type to find
+ * @param [in] nametag The child of 'find' that contains the name
+ * @param [in] find_name The name to find
+ *
+ * @return The found tag, or TAGID_NULL on failure
+ */
+TAGID WINAPI SdbFindFirstNamedTag(PDB db, TAGID root, TAGID find, TAGID nametag, LPCWSTR find_name)
+{
+ TAGID iter;
+
+ iter = SdbFindFirstTag(db, root, find);
+
+ while (iter != TAGID_NULL)
+ {
+ TAGID tmp = SdbFindFirstTag(db, iter, nametag);
+ if (tmp != TAGID_NULL)
+ {
+ LPCWSTR name = SdbGetStringTagPtr(db, tmp);
+ if (name && !lstrcmpiW(name, find_name))
+ return iter;
+ }
+ iter = SdbFindNextTag(db, root, iter);
+ }
+ return TAGID_NULL;
+}
+
+
+/**
+ * Find a named layer in a multi-db.
+ *
+ * @param [in] hsdb The multi-database.
+ * @param [in] layerName The named tag to find.
+ *
+ * @return The layer, or TAGREF_NULL on failure
+ */
+TAGREF WINAPI SdbGetLayerTagRef(HSDB hsdb, LPCWSTR layerName)
+{
+ PDB db = hsdb->db;
+
+ TAGID database = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE);
+ if (database != TAGID_NULL)
+ {
+ TAGID layer = SdbFindFirstNamedTag(db, database, TAG_LAYER, TAG_NAME, layerName);
+ if (layer != TAGID_NULL)
+ {
+ TAGREF tr;
+ if (SdbTagIDToTagRef(hsdb, db, layer, &tr))
+ {
+ return tr;
+ }
+ }
+ }
+ return TAGREF_NULL;
+}
+
+
+/**
+ * Converts the specified string to an index key.
+ *
+ * @param [in] str The string which will be converted.
+ *
+ * @return The resulting index key
+ *
+ * @todo: Fix this for unicode strings.
+ */
+LONGLONG WINAPI SdbMakeIndexKeyFromString(LPCWSTR str)
+{
+ LONGLONG result = 0;
+ int shift = 56;
+
+ while (*str && shift >= 0)
+ {
+ WCHAR c = toupper(*(str++));
+
+ if (c & 0xff)
+ {
+ result |= (((LONGLONG)(c & 0xff)) << shift);
+ shift -= 8;
+ }
+
+ if (shift < 0)
+ break;
+
+ c >>= 8;
+
+ if (c & 0xff)
+ {
+ result |= (((LONGLONG)(c & 0xff)) << shift);
+ shift -= 8;
+ }
+ }
+
+ return result;
+}
+
+
/**
* Converts specified tag into a string.
*