[APPHELP][APPHELP_APITEST] Update db apitests to succeed from 2k3 to 10, paving the...
[reactos.git] / reactos / dll / appcompat / apphelp / sdbapi.c
index 5d7b0a4..38ff2da 100644 (file)
@@ -23,6 +23,7 @@
 #include "ntndk.h"
 #include "strsafe.h"
 #include "apphelp.h"
+#include "sdbstringtable.h"
 
 #include "wine/unicode.h"
 
@@ -177,7 +178,7 @@ LPVOID SdbpAlloc(SIZE_T size
     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
@@ -202,20 +203,71 @@ void SdbpFree(LPVOID mem
     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;
 }
@@ -315,43 +367,14 @@ BOOL WINAPI SdbpCheckTagIDType(PDB db, TAGID tagid, WORD type)
 
 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);
@@ -402,7 +425,7 @@ PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type)
     if (!db)
         return NULL;
 
-    if (major != 2)
+    if (major != 2 && major != 3)
     {
         SdbCloseDatabase(db);
         SHIM_ERR("Invalid shim database version\n");
@@ -429,58 +452,14 @@ void WINAPI SdbCloseDatabase(PDB db)
 
     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.
  *
@@ -583,6 +562,108 @@ BOOL WINAPI SdbGetDatabaseVersion(LPCWSTR database, PDWORD VersionHi, PDWORD Ver
     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.
  *