https://git.reactos.org/?p=reactos.git;a=commitdiff;h=28a091ac12e003854328fe...
commit 28a091ac12e003854328fe78465d11d5b8ed15fe Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Mon Feb 11 22:44:30 2019 +0100 Commit: Mark Jansen mark.jansen@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@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. 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@reactos.org) + * Copyright 2015-2019 Mark Jansen (mark.jansen@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;