[APPHELP][APPHELP_APITEST] Implement SdbGetDatabaseInformation
authorMark Jansen <mark.jansen@reactos.org>
Mon, 11 Feb 2019 21:44:30 +0000 (22:44 +0100)
committerMark Jansen <mark.jansen@reactos.org>
Mon, 25 Feb 2019 19:00:34 +0000 (20:00 +0100)
CORE-11301

dll/appcompat/apphelp/apphelp.h
dll/appcompat/apphelp/apphelp.spec
dll/appcompat/apphelp/sdbapi.c
modules/rostests/apitests/apphelp/db.cpp
sdk/include/reactos/appcompat/sdbtypes.h

index fda2c50..90c52f8 100644 (file)
@@ -72,6 +72,20 @@ typedef struct tagSDBQUERYRESULT {
     GUID   rgGuidDB[SDB_MAX_SDBS];
 } SDBQUERYRESULT, *PSDBQUERYRESULT;
 
+
+#define DB_INFO_FLAGS_VALID_GUID    1
+
+typedef struct _DB_INFORMATION
+{
+    DWORD dwFlags;
+    DWORD dwMajor;
+    DWORD dwMinor;
+    LPCWSTR Description;
+    GUID Id;
+    /* Win10+ has an extra field here */
+} DB_INFORMATION, *PDB_INFORMATION;
+
+
 #ifndef APPHELP_NOSDBPAPI
 #include "sdbpapi.h"
 #endif
@@ -91,6 +105,8 @@ HRESULT WINAPI SdbGetAppPatchDir(HSDB db, LPWSTR path, DWORD size);
 LPWSTR WINAPI SdbGetStringTagPtr(PDB pdb, TAGID tagid);
 TAGID WINAPI SdbFindFirstNamedTag(PDB pdb, TAGID root, TAGID find, TAGID nametag, LPCWSTR find_name);
 DWORD WINAPI SdbQueryDataExTagID(PDB pdb, TAGID tiExe, LPCWSTR lpszDataName, LPDWORD lpdwDataType, LPVOID lpBuffer, LPDWORD lpcbBufferSize, TAGID *ptiData);
+BOOL WINAPI SdbGetDatabaseInformation(PDB pdb, PDB_INFORMATION information);
+VOID WINAPI SdbFreeDatabaseInformation(PDB_INFORMATION information);
 
 
 /* sdbread.c */
index af6582f..8f08f24 100644 (file)
@@ -47,7 +47,7 @@
 @ stub SdbFindNextStringIndexedTag
 @ stdcall SdbFindNextTag(ptr long long)
 @ stub SdbFindNextTagRef
-@ stub SdbFreeDatabaseInformation
+@ stdcall SdbFreeDatabaseInformation(ptr)
 @ stdcall SdbFreeFileAttributes(ptr)
 @ stub SdbFreeFileInfo
 @ stub SdbFreeFlagInfo
@@ -55,7 +55,7 @@
 @ stdcall SdbGetAppPatchDir(ptr wstr long)
 @ stdcall SdbGetBinaryTagData(ptr long)
 @ stdcall SdbGetDatabaseID(ptr ptr)
-@ stub SdbGetDatabaseInformation
+@ stdcall SdbGetDatabaseInformation(ptr ptr)
 @ stub SdbGetDatabaseInformationByName
 @ stub SdbGetDatabaseMatch
 @ stdcall SdbGetDatabaseVersion(wstr ptr ptr)
index 0f380d0..1a14424 100644 (file)
@@ -4,7 +4,7 @@
  * PURPOSE:     Sdb low level glue layer
  * COPYRIGHT:   Copyright 2011 André Hentschel
  *              Copyright 2013 Mislav Blaževic
- *              Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
+ *              Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org)
  */
 
 #include "ntndk.h"
@@ -145,7 +145,7 @@ void WINAPI SdbpFlush(PDB pdb)
     ASSERT(pdb->for_write);
     Status = NtWriteFile(pdb->file, NULL, NULL, NULL, &io,
         pdb->data, pdb->write_iter, NULL, NULL);
-    if!NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
         SHIM_WARN("failed with 0x%lx\n", Status);
 }
 
@@ -266,7 +266,7 @@ BOOL WINAPI SdbpCheckTagIDType(PDB pdb, TAGID tagid, WORD type)
     return SdbpCheckTagType(tag, type);
 }
 
-PDB SdbpOpenDatabase(LPCWSTR path, PATH_TYPE type, PDWORD major, PDWORD minor)
+PDB SdbpOpenDatabase(LPCWSTR path, PATH_TYPE type)
 {
     IO_STATUS_BLOCK io;
     FILE_STANDARD_INFORMATION fsi;
@@ -311,8 +311,8 @@ PDB SdbpOpenDatabase(LPCWSTR path, PATH_TYPE type, PDWORD major, PDWORD minor)
         return NULL;
     }
 
-    *major = *(DWORD*)&header[0];
-    *minor = *(DWORD*)&header[4];
+    pdb->major = *(DWORD*)&header[0];
+    pdb->minor = *(DWORD*)&header[4];
 
     return pdb;
 }
@@ -329,13 +329,13 @@ PDB SdbpOpenDatabase(LPCWSTR path, PATH_TYPE type, PDWORD major, PDWORD minor)
 PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type)
 {
     PDB pdb;
-    DWORD major, minor;
+    TAGID root, name;
 
-    pdb = SdbpOpenDatabase(path, type, &major, &minor);
+    pdb = SdbpOpenDatabase(path, type);
     if (!pdb)
         return NULL;
 
-    if (major != 2 && major != 3)
+    if (pdb->major != 2 && pdb->major != 3)
     {
         SdbCloseDatabase(pdb);
         SHIM_ERR("Invalid shim database version\n");
@@ -343,10 +343,25 @@ PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type)
     }
 
     pdb->stringtable = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_STRINGTABLE);
-    if(!SdbGetDatabaseID(pdb, &pdb->database_id))
+    if (!SdbGetDatabaseID(pdb, &pdb->database_id))
     {
         SHIM_INFO("Failed to get the database id\n");
     }
+
+    root = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
+    if (root != TAGID_NULL)
+    {
+        name = SdbFindFirstTag(pdb, root, TAG_NAME);
+        if (name != TAGID_NULL)
+        {
+            pdb->database_name = SdbGetStringTagPtr(pdb, name);
+        }
+    }
+    if (!pdb->database_name)
+    {
+        SHIM_INFO("Failed to get the database name\n");
+    }
+
     return pdb;
 }
 
@@ -397,7 +412,7 @@ BOOL WINAPI SdbGUIDFromString(PCWSTR GuidString, GUID *Guid)
 BOOL WINAPI SdbGUIDToString(CONST GUID *Guid, PWSTR GuidString, SIZE_T Length)
 {
     UNICODE_STRING GuidString_u;
-    if(NT_SUCCESS(RtlStringFromGUID(Guid, &GuidString_u)))
+    if (NT_SUCCESS(RtlStringFromGUID(Guid, &GuidString_u)))
     {
         HRESULT hr = StringCchCopyNW(GuidString, Length, GuidString_u.Buffer, GuidString_u.Length / 2);
         RtlFreeUnicodeString(&GuidString_u);
@@ -445,7 +460,7 @@ BOOL WINAPI SdbGetStandardDatabaseGUID(DWORD Flags, GUID* Guid)
         SHIM_ERR("Cannot obtain database guid for databases other than main\n");
         return FALSE;
     }
-    if(Guid)
+    if (Guid)
     {
         memcpy(Guid, copy_from, sizeof(GUID));
     }
@@ -465,13 +480,55 @@ BOOL WINAPI SdbGetDatabaseVersion(LPCWSTR database, PDWORD VersionHi, PDWORD Ver
 {
     PDB pdb;
 
-    pdb = SdbpOpenDatabase(database, DOS_PATH, VersionHi, VersionLo);
+    pdb = SdbpOpenDatabase(database, DOS_PATH);
     if (pdb)
+    {
+        *VersionHi = pdb->major;
+        *VersionLo = pdb->minor;
         SdbCloseDatabase(pdb);
+    }
 
     return TRUE;
 }
 
+/**
+ * @name SdbGetDatabaseInformation
+ * Get information about the database
+ *
+ * @param pdb           The database
+ * @param information   The returned information
+ * @return TRUE on success
+ */
+BOOL WINAPI SdbGetDatabaseInformation(PDB pdb, PDB_INFORMATION information)
+{
+    if (pdb && information)
+    {
+        information->dwFlags = 0;
+        information->dwMajor = pdb->major;
+        information->dwMinor = pdb->minor;
+        information->Description = pdb->database_name;
+        if (!SdbIsNullGUID(&pdb->database_id))
+        {
+            information->dwFlags |= DB_INFO_FLAGS_VALID_GUID;
+            information->Id = pdb->database_id;
+        }
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/**
+ * @name SdbFreeDatabaseInformation
+ * Free up resources allocated in SdbGetDatabaseInformation
+ *
+ * @param information   The information retrieved from SdbGetDatabaseInformation
+ */
+VOID WINAPI SdbFreeDatabaseInformation(PDB_INFORMATION information)
+{
+    // No-op
+}
+
 
 /**
  * Find the first named child tag.
index 1ea13f1..2ddfca9 100644 (file)
@@ -4,7 +4,7 @@
  * PURPOSE:     Tests for shim-database api's
  * COPYRIGHT:   Copyright 2012 Detlef Riekenberg
  *              Copyright 2013 Mislav Blažević
- *              Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
+ *              Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org)
  */
 
 #include <ntstatus.h>
 #define TAG_DATABASE_ID (0x7 | TAG_TYPE_BINARY)
 
 
+typedef struct _DB_INFORMATION
+{
+    DWORD dwSomething;
+    DWORD dwMajor;
+    DWORD dwMinor;
+    LPCWSTR Description;
+    GUID Id;
+    /* Win10+ has an extra field here */
+} DB_INFORMATION, *PDB_INFORMATION;
+
 
 static HMODULE hdll;
 static LPCWSTR (WINAPI *pSdbTagToString)(TAG);
@@ -163,6 +173,8 @@ static LONGLONG (WINAPI* pSdbMakeIndexKeyFromString)(LPCWSTR);
 static DWORD (WINAPI* pSdbQueryData)(HSDB hsdb, TAGREF trWhich, LPCWSTR lpszDataName, LPDWORD lpdwDataType, LPVOID lpBuffer, LPDWORD lpcbBufferSize);
 static DWORD (WINAPI* pSdbQueryDataEx)(HSDB hsdb, TAGREF trWhich, LPCWSTR lpszDataName, LPDWORD lpdwDataType, LPVOID lpBuffer, LPDWORD lpcbBufferSize, TAGREF *ptrData);
 static DWORD (WINAPI* pSdbQueryDataExTagID)(PDB pdb, TAGID tiExe, LPCWSTR lpszDataName, LPDWORD lpdwDataType, LPVOID lpBuffer, LPDWORD lpcbBufferSize, TAGID *ptiData);
+static BOOL (WINAPI* pSdbGetDatabaseInformation)(PDB pdb, PDB_INFORMATION information);
+static VOID (WINAPI* pSdbFreeDatabaseInformation)(PDB_INFORMATION information);
 
 DEFINE_GUID(GUID_DATABASE_TEST, 0xe39b0eb0, 0x55db, 0x450b, 0x9b, 0xd4, 0xd2, 0x0c, 0x94, 0x84, 0x26, 0x0f);
 DEFINE_GUID(GUID_MAIN_DATABASE, 0x11111111, 0x1111, 0x1111, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11);
@@ -174,6 +186,51 @@ static void Write(HANDLE file, LPCVOID buffer, DWORD size)
     WriteFile(file, buffer, size, &dwWritten, NULL);
 }
 
+static void test_GetDatabaseInformationEmpty(PDB pdb)
+{
+    PDB_INFORMATION pInfo;
+    BOOL fResult;
+
+    if (!pSdbGetDatabaseInformation || !pSdbFreeDatabaseInformation)
+    {
+        skip("GetDatabaseInformation or SdbFreeDatabaseInformation not found\n");
+        return;
+    }
+
+    pInfo = (PDB_INFORMATION)malloc(sizeof(*pInfo) * 4);
+    memset(pInfo, 0xDE, sizeof(*pInfo) * 2);
+
+    fResult = pSdbGetDatabaseInformation(pdb, pInfo);
+    ok(fResult, "SdbGetDatabaseInformation failed\n");
+    if (fResult)
+    {
+        ok_int(pInfo->dwSomething, 0);
+        ok(IsEqualGUID(GUID_NULL, pInfo->Id), "expected guid to be empty(%s)\n", wine_dbgstr_guid(&pInfo->Id));
+        ok(pInfo->Description == NULL, "Expected pInfo->Description to be NULL, was %s\n", wine_dbgstr_w(pInfo->Description));
+
+        /* Struct is slightly bigger on some Win10, and the DB version nr is different on all */
+        if (g_WinVersion >= WINVER_WIN10)
+        {
+            ok(pInfo->dwMajor == 3, "Expected pInfo->dwMajor to be 3, was: %d\n", pInfo->dwMajor);
+            ok(pInfo->dwMinor == 0, "Expected pInfo->dwMinor to be 0, was: %d\n", pInfo->dwMinor);
+
+            ok(pInfo[1].dwSomething == 0 || pInfo[1].dwSomething == 0xdededede, "Something amiss: 0x%x\n", pInfo[1].dwSomething);
+            ok(pInfo[1].dwMajor == 0xdededede, "Cookie2 corrupt: 0x%x\n", pInfo[1].dwMajor);
+        }
+        else
+        {
+            ok(pInfo->dwMajor == 2, "Expected pInfo->dwMajor to be 2, was: %d\n", pInfo->dwMajor);
+            ok(pInfo->dwMinor == 1, "Expected pInfo->dwMinor to be 1, was: %d\n", pInfo->dwMinor);
+
+            ok(pInfo[1].dwSomething == 0xdededede, "Cookie1 corrupt: 0x%x\n", pInfo[1].dwSomething);
+            ok(pInfo[1].dwMajor == 0xdededede, "Cookie2 corrupt: 0x%x\n", pInfo[1].dwMajor);
+        }
+
+    }
+    free(pInfo);
+}
+
+
 static void test_Sdb(void)
 {
     static const WCHAR temp[] = L"temp";
@@ -289,6 +346,8 @@ static void test_Sdb(void)
         word = pSdbReadWORDTag(pdb, tagid, 0);
         ok(word == 0xACE, "unexpected value 0x%x, expected 0x%x\n", word, 0xACE);
 
+        test_GetDatabaseInformationEmpty(pdb);
+
         pSdbCloseDatabase(pdb);
     }
     DeleteFileW(path1);
@@ -966,6 +1025,63 @@ static void check_db_apphelp(PDB pdb, TAGID root)
     ok(num == 2, "Expected to find 2 layer tags, found: %d\n", num);
 }
 
+static void test_GetDatabaseInformation(PDB pdb)
+{
+    PDB_INFORMATION pInfo;
+    BOOL fResult;
+
+    if (!pSdbGetDatabaseInformation || !pSdbFreeDatabaseInformation)
+    {
+        skip("GetDatabaseInformation or SdbFreeDatabaseInformation not found\n");
+        return;
+    }
+
+    _SEH2_TRY
+    {
+        pSdbFreeDatabaseInformation(NULL);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ok(0, "SdbFreeDatabaseInformation did not handle a NULL pointer very gracefully.\n");
+    }
+    _SEH2_END;
+
+
+    pInfo = (PDB_INFORMATION)malloc(sizeof(*pInfo) * 4);
+    memset(pInfo, 0xDE, sizeof(*pInfo) * 2);
+
+    fResult = pSdbGetDatabaseInformation(pdb, pInfo);
+    ok(fResult, "SdbGetDatabaseInformation failed\n");
+    if (fResult)
+    {
+        ok_int(pInfo->dwSomething, 1);
+        ok(IsEqualGUID(GUID_DATABASE_TEST, pInfo->Id), "expected guids to be equal(%s:%s)\n",
+           wine_dbgstr_guid(&GUID_DATABASE_TEST), wine_dbgstr_guid(&pInfo->Id));
+        ok(wcscmp(pInfo->Description, L"apphelp_test1") == 0,
+           "Expected pInfo->Description to be 'apphelp_test1', was %s\n", wine_dbgstr_w(pInfo->Description));
+
+        /* Struct is slightly bigger on some Win10, and the DB version nr is different on all */
+        if (g_WinVersion >= WINVER_WIN10)
+        {
+            ok(pInfo->dwMajor == 3, "Expected pInfo->dwMajor to be 3, was: %d\n", pInfo->dwMajor);
+            ok(pInfo->dwMinor == 0, "Expected pInfo->dwMinor to be 0, was: %d\n", pInfo->dwMinor);
+
+            ok(pInfo[1].dwSomething == 4 || pInfo[1].dwSomething == 0xdededede, "Something amiss: 0x%x\n", pInfo[1].dwSomething);
+            ok(pInfo[1].dwMajor == 0xdededede, "Cookie2 corrupt: 0x%x\n", pInfo[1].dwMajor);
+        }
+        else
+        {
+            ok(pInfo->dwMajor == 2, "Expected pInfo->dwMajor to be 2, was: %d\n", pInfo->dwMajor);
+            ok(pInfo->dwMinor == 1, "Expected pInfo->dwMinor to be 1, was: %d\n", pInfo->dwMinor);
+
+            ok(pInfo[1].dwSomething == 0xdededede, "Cookie1 corrupt: 0x%x\n", pInfo[1].dwSomething);
+            ok(pInfo[1].dwMajor == 0xdededede, "Cookie2 corrupt: 0x%x\n", pInfo[1].dwMajor);
+        }
+        
+    }
+    free(pInfo);
+}
+
 static void test_CheckDatabaseManually(void)
 {
     static const WCHAR path[] = {'t','e','s','t','_','d','b','.','s','d','b',0};
@@ -1040,6 +1156,7 @@ static void test_CheckDatabaseManually(void)
         check_db_exes(pdb, root);
         check_db_apphelp(pdb, root);
     }
+    test_GetDatabaseInformation(pdb);
 
     pSdbCloseDatabase(pdb);
     DeleteFileA("test_db.sdb");
@@ -1998,6 +2115,8 @@ START_TEST(db)
     *(void**)&pSdbQueryDataEx = (void *)GetProcAddress(hdll, "SdbQueryDataEx");
     *(void**)&pSdbQueryDataExTagID = (void *)GetProcAddress(hdll, "SdbQueryDataExTagID");
     *(void**)&pSdbGetLayerTagRef = (void *)GetProcAddress(hdll, "SdbGetLayerTagRef");
+    *(void**)&pSdbGetDatabaseInformation = (void *)GetProcAddress(hdll, "SdbGetDatabaseInformation");
+    *(void**)&pSdbFreeDatabaseInformation = (void *)GetProcAddress(hdll, "SdbFreeDatabaseInformation");
 
     test_Sdb();
     test_write_ex();
index 22ef7ae..b804bd0 100644 (file)
@@ -27,7 +27,10 @@ typedef struct _DB {
     BYTE* data;
     TAGID stringtable;
     DWORD write_iter;
+    DWORD major;
+    DWORD minor;
     GUID database_id;
+    PCWSTR database_name;
     BOOL for_write;
     struct SdbStringHashTable* string_lookup;
     struct _DB* string_buffer;