https://git.reactos.org/?p=reactos.git;a=commitdiff;h=28a091ac12e003854328f…
commit 28a091ac12e003854328fe78465d11d5b8ed15fe
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Mon Feb 11 22:44:30 2019 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Mon Feb 25 20:00:34 2019 +0100
[APPHELP][APPHELP_APITEST] Implement SdbGetDatabaseInformation
CORE-11301
---
dll/appcompat/apphelp/apphelp.h | 16 ++++
dll/appcompat/apphelp/apphelp.spec | 4 +-
dll/appcompat/apphelp/sdbapi.c | 81 ++++++++++++++++++---
modules/rostests/apitests/apphelp/db.cpp | 121 ++++++++++++++++++++++++++++++-
sdk/include/reactos/appcompat/sdbtypes.h | 3 +
5 files changed, 210 insertions(+), 15 deletions(-)
diff --git a/dll/appcompat/apphelp/apphelp.h b/dll/appcompat/apphelp/apphelp.h
index fda2c501ad..90c52f866a 100644
--- a/dll/appcompat/apphelp/apphelp.h
+++ b/dll/appcompat/apphelp/apphelp.h
@@ -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 */
diff --git a/dll/appcompat/apphelp/apphelp.spec b/dll/appcompat/apphelp/apphelp.spec
index af6582f90c..8f08f24d47 100644
--- a/dll/appcompat/apphelp/apphelp.spec
+++ b/dll/appcompat/apphelp/apphelp.spec
@@ -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)
diff --git a/dll/appcompat/apphelp/sdbapi.c b/dll/appcompat/apphelp/sdbapi.c
index 0f380d0c1e..1a14424ca3 100644
--- a/dll/appcompat/apphelp/sdbapi.c
+++ b/dll/appcompat/apphelp/sdbapi.c
@@ -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(a)reactos.org)
+ * Copyright 2015-2019 Mark Jansen (mark.jansen(a)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.
diff --git a/modules/rostests/apitests/apphelp/db.cpp
b/modules/rostests/apitests/apphelp/db.cpp
index 1ea13f1660..2ddfca9199 100644
--- a/modules/rostests/apitests/apphelp/db.cpp
+++ b/modules/rostests/apitests/apphelp/db.cpp
@@ -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(a)reactos.org)
+ * Copyright 2015-2019 Mark Jansen (mark.jansen(a)reactos.org)
*/
#include <ntstatus.h>
@@ -120,6 +120,16 @@
#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();
diff --git a/sdk/include/reactos/appcompat/sdbtypes.h
b/sdk/include/reactos/appcompat/sdbtypes.h
index 22ef7ae751..b804bd07b6 100644
--- a/sdk/include/reactos/appcompat/sdbtypes.h
+++ b/sdk/include/reactos/appcompat/sdbtypes.h
@@ -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;