Author: mjansen Date: Sat Sep 3 16:20:52 2016 New Revision: 72549
URL: http://svn.reactos.org/svn/reactos?rev=72549&view=rev Log: [APPHELP][APPHELP_APITEST] Partially implement SdbGetMatchingExe, SdbInitDatabase and SdbTagRefToTagID. CORE-10367 - SdbGetMatchingExe, SdbInitDatabase partial implementation by Mislav Blažević - Tests by me, they pass on vista - win10. (Win2k3 has another struct layout) - Move shared test functions to a common header - SdbTagRefToTagID misses functionality related to multiple databases, but that is not supported anywhere yet.
Added: trunk/reactos/dll/appcompat/apphelp/hsdb.c (with props) trunk/rostests/apitests/apphelp/apphelp_apitest.h (with props) Modified: trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt trunk/reactos/dll/appcompat/apphelp/apphelp.c trunk/reactos/dll/appcompat/apphelp/apphelp.h trunk/reactos/dll/appcompat/apphelp/apphelp.spec trunk/reactos/dll/appcompat/apphelp/sdbapi.c trunk/rostests/apitests/apphelp/apphelp.c trunk/rostests/apitests/apphelp/data.c trunk/rostests/apitests/apphelp/db.c trunk/rostests/apitests/apphelp/layerapi.c
Modified: trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/CMake... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -3,6 +3,7 @@
list(APPEND SOURCE apphelp.c + hsdb.c layer.c sdbapi.c sdbfileattr.c
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apphe... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/apphelp.c [iso-8859-1] (original) +++ trunk/reactos/dll/appcompat/apphelp/apphelp.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -40,7 +40,7 @@ { UNICODE_STRING DebugKey, DebugValue; NTSTATUS Status; - ULONG NewLevel = 0; + ULONG NewLevel = SHIM_ERR; WCHAR Buffer[40];
RtlInitUnicodeString(&DebugKey, L"SHIM_DEBUG_LEVEL");
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apphe... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] (original) +++ trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -50,22 +50,58 @@ }; } ATTRINFO, *PATTRINFO;
+#define SDB_MAX_SDBS 16 +#define SDB_MAX_EXES 16 +#define SDB_MAX_LAYERS 8 + +/* Flags for adwExeFlags */ +#define SHIMREG_DISABLE_SHIM (0x00000001) +#define SHIMREG_DISABLE_APPHELP (0x00000002) +#define SHIMREG_APPHELP_NOUI (0x00000004) +#define SHIMREG_APPHELP_CANCEL (0x10000000) +#define SHIMREG_DISABLE_SXS (0x00000010) +#define SHIMREG_DISABLE_LAYER (0x00000020) +#define SHIMREG_DISABLE_DRIVER (0x00000040) + +#define SDBGMEF_IGNORE_ENVIRONMENT (0x1) + +typedef struct tagSDBQUERYRESULT { + TAGREF atrExes[SDB_MAX_EXES]; + DWORD adwExeFlags[SDB_MAX_EXES]; + TAGREF atrLayers[SDB_MAX_LAYERS]; + DWORD dwLayerFlags; + TAGREF trApphelp; + DWORD dwExeCount; + DWORD dwLayerCount; + GUID guidID; + DWORD dwFlags; + DWORD dwCustomSDBMap; + GUID rgGuidDB[SDB_MAX_SDBS]; +} SDBQUERYRESULT, *PSDBQUERYRESULT; + /* apphelp.c */
#include "sdbpapi.h"
PWSTR SdbpStrDup(LPCWSTR string); +HSDB WINAPI SdbInitDatabase(DWORD, LPCWSTR); +void WINAPI SdbReleaseDatabase(HSDB);
PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type); void WINAPI SdbCloseDatabase(PDB); BOOL WINAPI SdbIsNullGUID(CONST GUID *Guid); +BOOL WINAPI SdbGetAppPatchDir(HSDB db, LPWSTR path, DWORD size); +LPWSTR WINAPI SdbGetStringTagPtr(PDB db, TAGID tagid);
/* sdbread.c */ BOOL WINAPI SdbpReadData(PDB db, PVOID dest, DWORD offset, DWORD num); TAG WINAPI SdbGetTagFromTagID(PDB db, TAGID tagid); TAGID WINAPI SdbFindFirstTag(PDB db, TAGID parent, TAG tag); +TAGID WINAPI SdbFindNextTag(PDB db, TAGID parent, TAGID prev_child); BOOL WINAPI SdbGetDatabaseID(PDB db, GUID* Guid);
+/* sdbfileattr.c*/ +BOOL WINAPI SdbFreeFileAttributes(PATTRINFO attr_info);
/* layer.c */ BOOL WINAPI AllowPermLayer(PCWSTR path);
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apphe... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] (original) +++ trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -71,7 +71,7 @@ @ stub SdbGetLayerName @ stub SdbGetLayerTagRef @ stub SdbGetLocalPDB -@ stub SdbGetMatchingExe +@ stdcall SdbGetMatchingExe(ptr wstr wstr wstr long ptr) @ stub SdbGetMsiPackageInformation @ stub SdbGetNamedLayer @ stdcall SdbGetNextChild(ptr long long) @@ -87,7 +87,7 @@ @ stub SdbGrabMatchingInfoEx @ stdcall SdbGUIDFromString(wstr ptr) @ stdcall SdbGUIDToString(ptr wstr long) -@ stub SdbInitDatabase +@ stdcall SdbInitDatabase(long wstr) @ stub SdbInitDatabaseEx @ stdcall SdbIsNullGUID(ptr) @ stub SdbIsStandardDatabase @@ -129,7 +129,7 @@ @ stdcall SdbReadWORDTag(ptr long long) @ stub SdbReadWORDTagRef @ stub SdbRegisterDatabase -@ stub SdbReleaseDatabase +@ stdcall SdbReleaseDatabase(ptr) @ stub SdbReleaseMatchingExe @ stub SdbResolveDatabase @ stub SdbSetApphelpDebugParameters @@ -144,7 +144,7 @@ @ stub SdbStringReplace @ stub SdbStringReplaceArray @ stub SdbTagIDToTagRef -@ stub SdbTagRefToTagID +@ stdcall SdbTagRefToTagID(ptr long ptr ptr) @ stdcall SdbTagToString(long) @ stub SdbUnregisterDatabase @ stdcall SdbWriteBinaryTag(ptr long ptr long)
Added: trunk/reactos/dll/appcompat/apphelp/hsdb.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/hsdb.... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/hsdb.c (added) +++ trunk/reactos/dll/appcompat/apphelp/hsdb.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -0,0 +1,281 @@ +/* + * Copyright 2011 André Hentschel + * Copyright 2013 Mislav BlaževiÄ + * Copyright 2015,2016 Mark Jansen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define WIN32_NO_STATUS +#include "windows.h" +#include "ntndk.h" +#include "strsafe.h" +#include "apphelp.h" +//#include "sdbstringtable.h" + +#include "wine/unicode.h" + + +static BOOL WINAPI SdbpFileExists(LPCWSTR path) +{ + DWORD attr = GetFileAttributesW(path); + return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY)); +} + + +/** + * Opens specified shim database file Handle returned by this function may only be used by + * functions which take HSDB param thus differing it from SdbOpenDatabase. + * + * @param [in] flags Specifies type of path or predefined database. + * @param [in] path Path to the shim database file. + * + * @return Success: Handle to the opened shim database, NULL otherwise. + */ +HSDB WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path) +{ + static const WCHAR shim[] = {'\','s','y','s','m','a','i','n','.','s','d','b',0}; + static const WCHAR msi[] = {'\','m','s','i','m','a','i','n','.','s','d','b',0}; + static const WCHAR drivers[] = {'\','d','r','v','m','a','i','n','.','s','d','b',0}; + LPCWSTR name; + WCHAR buffer[128]; + HSDB sdb; + + sdb = SdbAlloc(sizeof(SDB)); + if (!sdb) + return NULL; + sdb->auto_loaded = 0; + + /* Check for predefined databases */ + if ((flags & HID_DATABASE_TYPE_MASK) && path == NULL) + { + switch (flags & HID_DATABASE_TYPE_MASK) + { + case SDB_DATABASE_MAIN_SHIM: name = shim; break; + case SDB_DATABASE_MAIN_MSI: name = msi; break; + case SDB_DATABASE_MAIN_DRIVERS: name = drivers; break; + default: return NULL; + } + SdbGetAppPatchDir(NULL, buffer, 128); + memcpy(buffer + lstrlenW(buffer), name, SdbpStrlen(name)); + } + + sdb->db = SdbOpenDatabase(path ? path : buffer, (flags & 0xF) - 1); + + /* If database could not be loaded, a handle doesn't make sense either */ + if (!sdb->db) + { + SdbReleaseDatabase(sdb); + return NULL; + } + + return sdb; +} + +/** + * Closes shim database opened by SdbInitDatabase. + * + * @param [in] hsdb Handle to the shim database. + */ +void WINAPI SdbReleaseDatabase(HSDB hsdb) +{ + SdbCloseDatabase(hsdb->db); + SdbFree(hsdb); +} + +/** + * Queries database for a specified exe If hsdb is NULL default database shall be loaded and + * searched. + * + * @param [in] hsdb Handle to the shim database. + * @param [in] path Path to executable for which we query database. + * @param [in] module_name Unused. + * @param [in] env Unused. + * @param [in] flags 0 or SDBGMEF_IGNORE_ENVIRONMENT. + * @param [out] result Pointer to structure in which query result shall be stored. + * + * @return TRUE if it succeeds, FALSE if it fails. + */ +BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name, + LPCWSTR env, DWORD flags, PSDBQUERYRESULT result) +{ + static const WCHAR fmt[] = {'%','s','%','s',0}; + BOOL ok, ret; + TAGID database, iter, attr; + PATTRINFO attribs = NULL; + /*DWORD attr_count;*/ + LPWSTR file_name; + WCHAR dir_path[128]; + WCHAR buffer[256]; + PDB db; + + /* Load default database if one is not specified */ + if (!hsdb) + { + /* To reproduce windows behaviour HID_DOS_PATHS needs + * to be specified when loading default database */ + hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL); + if(hsdb) + hsdb->auto_loaded = TRUE; + } + + /* No database could be loaded */ + if (!hsdb) + return FALSE; + + db = hsdb->db; + + /* Extract file name */ + file_name = strrchrW(path, '\') + 1; + + /* Extract directory path */ + memcpy(dir_path, path, (size_t)(file_name - path) * sizeof(WCHAR)); + + /* Get information about executable required to match it with database entry */ + /*if (!SdbGetFileAttributes(path, &attribs, &attr_count)) + return FALSE;*/ + + /* DATABASE is list TAG which contains all executables */ + database = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE); + if (database == TAGID_NULL) + return FALSE; + + /* EXE is list TAG which contains data required to match executable */ + iter = SdbFindFirstTag(db, database, TAG_EXE); + + /* Search for entry in database */ + while (iter != TAGID_NULL) + { + /* Check if exe name matches */ + attr = SdbFindFirstTag(db, iter, TAG_NAME); + if (lstrcmpiW(SdbGetStringTagPtr(db, attr), file_name) == 0) + { + /* Assume that entry is found (in case there are no "matching files") */ + ok = TRUE; + + /* Check if all "matching files" exist */ + /* TODO: check size/checksum as well */ + for (attr = SdbFindFirstTag(db, attr, TAG_MATCHING_FILE); + attr != TAGID_NULL; attr = SdbFindNextTag(db, iter, attr)) + { + snprintfW(buffer, 256, fmt, dir_path, SdbGetStringTagPtr(db, attr)); + if (!SdbpFileExists(buffer)) + ok = FALSE; + } + + /* Found it! */ + if (ok) + { + /* TODO: fill result data */ + /* TODO: there may be multiple matches */ + ret = TRUE; + goto cleanup; + } + } + + /* Continue iterating */ + iter = SdbFindNextTag(db, database, iter); + } + + /* Exe not found */ + ret = FALSE; + +cleanup: + SdbFreeFileAttributes(attribs); + if (hsdb->auto_loaded) SdbReleaseDatabase(hsdb); + return ret; +} + +/** + * 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}; + + /* In case function fails, path holds empty string */ + if (size > 0) + *path = 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); + } + if (!default_dir) + { + SHIM_ERR("Unable to obtain default AppPatch directory\n"); + return FALSE; + } + } + + if (!db) + { + return SUCCEEDED(StringCchCopyW(path, size, default_dir)); + } + else + { + SHIM_ERR("Unimplemented for db != NULL\n"); + return FALSE; + } +} + + +/** + * Translates the given trWhich to a specific database / tagid + * + * @param [in] hsdb Handle to the database. + * @param [in] trWhich Path to executable for which we query database. + * @param [out,opt] ppdb The Shim database that trWhich belongs to. + * @param [out,opt] ptiWhich The tagid that trWhich corresponds to. + * + * @return TRUE if it succeeds, FALSE if it fails. + */ +BOOL WINAPI SdbTagRefToTagID(HSDB hSDB, TAGREF trWhich, PDB* ppdb, TAGID* ptiWhich) +{ + if (trWhich & 0xf0000000) + { + SHIM_ERR("Multiple shim databases not yet implemented!\n"); + return FALSE; + } + + /* There seems to be no range checking on trWhich.. */ + if (ppdb) + *ppdb = hSDB->db; + if (ptiWhich) + *ptiWhich = trWhich & 0x0fffffff; + + return TRUE; +} +
Propchange: trunk/reactos/dll/appcompat/apphelp/hsdb.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/appcompat/apphelp/sdbapi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/sdbap... ============================================================================== --- trunk/reactos/dll/appcompat/apphelp/sdbapi.c [iso-8859-1] (original) +++ trunk/reactos/dll/appcompat/apphelp/sdbapi.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -458,59 +458,6 @@ 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}; - - /* In case function fails, path holds empty string */ - if (size > 0) - *path = 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); - } - if (!default_dir) - { - SHIM_ERR("Unable to obtain default AppPatch directory\n"); - return FALSE; - } - } - - if (!db) - { - return SUCCEEDED(StringCchCopyW(path, size, default_dir)); - } - else - { - /* fixme */ - return FALSE; - } }
/**
Modified: trunk/rostests/apitests/apphelp/apphelp.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/apphelp.c... ============================================================================== --- trunk/rostests/apitests/apphelp/apphelp.c [iso-8859-1] (original) +++ trunk/rostests/apitests/apphelp/apphelp.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -36,26 +36,7 @@
#include "wine/test.h"
-/* data.c */ -void test_create_exe_imp(const char* name, int skip_rsrc_exports); -void test_create_file_imp(const char* name, const char* contents, size_t len); -void test_create_ne_imp(const char* name, int skip_names); -DWORD get_host_winver(void); - -#define test_create_exe (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_exe_imp -#define test_create_file (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_file_imp -#define test_create_ne (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_ne_imp - - -static DWORD g_WinVersion; - -#define WINVER_ANY 0 -#define WINVER_WINXP 0x0501 -#define WINVER_2003 0x0502 -#define WINVER_VISTA 0x0600 -#define WINVER_WIN7 0x0601 -#define WINVER_WIN8 0x0602 -#define WINVER_WIN10 0x1000 +#include "apphelp_apitest.h"
typedef WORD TAG; @@ -848,6 +829,8 @@ { g_WinVersion = get_host_winver(); trace("Detected version: 0x%x\n", g_WinVersion); + silence_debug_output(); + //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4"); //SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp"); hdll = LoadLibraryA("apphelp.dll");
Added: trunk/rostests/apitests/apphelp/apphelp_apitest.h URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/apphelp_a... ============================================================================== --- trunk/rostests/apitests/apphelp/apphelp_apitest.h (added) +++ trunk/rostests/apitests/apphelp/apphelp_apitest.h [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -0,0 +1,31 @@ +#ifndef APPHELP_APITEST_H +#define APPHELP_APITEST_H + + +/* data.c */ +void test_create_db_imp(const char* name); +DWORD test_get_db_size(); +void test_create_exe_imp(const char* name, int skip_rsrc_exports); +void test_create_file_imp(const char* name, const char* contents, size_t len); +void test_create_ne_imp(const char* name, int skip_names); +DWORD get_host_winver(void); +void silence_debug_output(void); // Silence output if the environment variable is not set. + +#define test_create_db (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_db_imp +#define test_create_exe (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_exe_imp +#define test_create_file (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_file_imp +#define test_create_ne (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_ne_imp + + +static DWORD g_WinVersion; + +#define WINVER_ANY 0 +#define WINVER_WINXP 0x0501 +#define WINVER_2003 0x0502 +#define WINVER_VISTA 0x0600 +#define WINVER_WIN7 0x0601 +#define WINVER_WIN8 0x0602 +#define WINVER_WIN10 0x0a00 + + +#endif // APPHELP_APITEST_H
Propchange: trunk/rostests/apitests/apphelp/apphelp_apitest.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/rostests/apitests/apphelp/data.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/data.c?re... ============================================================================== --- trunk/rostests/apitests/apphelp/data.c [iso-8859-1] (original) +++ trunk/rostests/apitests/apphelp/data.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -771,11 +771,16 @@ 0x21, 0x00, 0x00, 0x00 };
+DWORD test_get_db_size() +{ + return sizeof(rawData); +} + void test_create_db_imp(const char* name) { HANDLE file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - ok(file != INVALID_HANDLE_VALUE, "can't create file\n"); - if(file != INVALID_HANDLE_VALUE) + winetest_ok(file != INVALID_HANDLE_VALUE, "can't create file '%s'\n", name); + if (file != INVALID_HANDLE_VALUE) { DWORD size; WriteFile(file, rawData, sizeof(rawData), &size, NULL); @@ -799,3 +804,11 @@ return g_WinVersion; }
+void silence_debug_output(void) +{ + if (GetEnvironmentVariableA("SHIM_DEBUG_LEVEL", NULL, 0) == ERROR_ENVVAR_NOT_FOUND) + SetEnvironmentVariableA("SHIM_DEBUG_LEVEL", "0"); + if (GetEnvironmentVariableA("SHIMENG_DEBUG_LEVEL", NULL, 0) == ERROR_ENVVAR_NOT_FOUND) + SetEnvironmentVariableA("SHIMENG_DEBUG_LEVEL", "0"); +} +
Modified: trunk/rostests/apitests/apphelp/db.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/db.c?rev=... ============================================================================== --- trunk/rostests/apitests/apphelp/db.c [iso-8859-1] (original) +++ trunk/rostests/apitests/apphelp/db.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -36,18 +36,23 @@
#include "wine/test.h"
-/* data.c */ -void test_create_db_imp(const char* name); - -#define test_create_db (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_db_imp +#include "apphelp_apitest.h" + +
typedef WORD TAG; typedef DWORD TAGID; typedef DWORD TAGREF; typedef UINT64 QWORD; typedef VOID* PDB; +typedef VOID* HSDB; typedef INT PATH_TYPE; + #define DOS_PATH 0 +#define HID_DATABASE_FULLPATH 2 + +#define SDB_DATABASE_MAIN_SHIM 0x80030000 +
#define TAGID_NULL 0x0 #define TAGID_ROOT 0x0 @@ -133,6 +138,26 @@ #define TAG_DATA_BITS (0x5 | TAG_TYPE_BINARY) #define TAG_DATABASE_ID (0x7 | TAG_TYPE_BINARY)
+ +#define SDB_MAX_SDBS 16 +#define SDB_MAX_EXES 16 +#define SDB_MAX_LAYERS 8 + +#define SDBQUERYRESULT_EXPECTED_SIZE 456 + +typedef struct tagSDBQUERYRESULT { + TAGREF atrExes[SDB_MAX_EXES]; + DWORD adwExeFlags[SDB_MAX_EXES]; + TAGREF atrLayers[SDB_MAX_LAYERS]; + DWORD dwLayerFlags; + TAGREF trApphelp; + DWORD dwExeCount; + DWORD dwLayerCount; + GUID guidID; + DWORD dwFlags; + DWORD dwCustomSDBMap; + GUID rgGuidDB[SDB_MAX_SDBS]; +} SDBQUERYRESULT, *PSDBQUERYRESULT;
static HMODULE hdll; @@ -166,6 +191,10 @@ static TAGID (WINAPI *pSdbGetNextChild)(PDB, TAGID, TAGID); static BOOL (WINAPI *pSdbGetDatabaseID)(PDB, GUID*); static BOOL (WINAPI *pSdbGUIDToString)(CONST GUID *, PCWSTR, SIZE_T); +static HSDB (WINAPI *pSdbInitDatabase)(DWORD, LPCWSTR); +static void (WINAPI *pSdbReleaseDatabase)(HSDB); +static BOOL(WINAPI *pSdbGetMatchingExe)(HSDB hsdb, LPCWSTR path, LPCWSTR module_name, LPCWSTR env, DWORD flags, PSDBQUERYRESULT result); +static BOOL (WINAPI *pSdbTagRefToTagID)(HSDB hSDB, TAGREF trWhich, PDB *ppdb, TAGID *ptiWhich); static LONGLONG(WINAPI* pSdbMakeIndexKeyFromString)(LPCWSTR);
@@ -717,6 +746,9 @@ } }
+// "C:\WINDOWS\system32\pcaui.exe" /g {bf39e0e6-c61c-4a22-8802-3ea8ad00b655} /x {4e50c93f-b863-4dfa-bae2-d80ef4ce5c89} /a "apphelp_name_allow" /v "apphelp_vendor_allow" /s "Allow it!" /b 1 /f 0 /k 0 /e "C:\Users\Mark\AppData\Local\Temp\apphelp_test\test_allow.exe" /u "http://reactos.org/allow" /c +// "C:\WINDOWS\system32\pcaui.exe" /g {fa150915-1244-4169-a4ba-fc098c442840} /x {156720e1-ef98-4d04-965a-d85de05e6d9f} /a "apphelp_name_disallow" /v "apphelp_vendor_disallow" /s "Not allowed!" /b 2 /f 0 /k 0 /e "C:\Users\Mark\AppData\Local\Temp\apphelp_test\test_disallow.exe" /u "http://reactos.org/disallow" /c + static void check_matching_apphelp(PDB pdb, TAGID apphelp, int num) { if(num == 0) @@ -789,8 +821,11 @@ const char* extra_file; DWORD dwLayerCount; TAGREF atrExes_0; + DWORD adwExeFlags_0; TAGREF atrLayers_0; -} test_exedata[4] = { + TAGREF trApphelp; + const char* env_var; +} test_exedata[5] = { { "test_allow.exe", "apphelp_name_allow", @@ -799,7 +834,10 @@ NULL, 0, 0x1c6, + 0x1000, 0, + 0x1c6, + NULL, }, { "test_disallow.exe", @@ -809,7 +847,10 @@ NULL, 0, 0x256, + 0x3000, 0, + 0x256, + NULL, }, { "test_new.exe", @@ -819,7 +860,10 @@ "test_checkfile.txt", 1, 0x2ec, + 0, 0x18e, + 0, + NULL, }, { "test_w2k3.exe", @@ -830,6 +874,22 @@ 0, 0x37c, 0, + 0, + 0, + NULL, + }, + { + "test_unknown_file.exe", + "apphelp_name_allow", + "apphelp_vendor_allow", + {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + NULL, + 1, + 0, + 0, + 0x18e, + 0, + "TestNewMode", }, };
@@ -967,6 +1027,314 @@ pSdbCloseDatabase(pdb); DeleteFileA("test_db.sdb"); } + +static void test_is_testdb(PDB pdb) +{ + if(pdb) + { + GUID guid; + memset(&guid, 0, sizeof(guid)); + ok(pSdbGetDatabaseID(pdb, &guid),"expected SdbGetDatabaseID not to fail.\n"); + ok(IsEqualGUID(&guid, &GUID_DATABASE_TEST), "Expected SdbGetDatabaseID to return the test db GUID, was: %s\n", wine_dbgstr_guid(&guid)); + } + else + { + skip("Not checking DB GUID, received a null pdb\n"); + } +} + + +static void test_mode_generic(const char* workdir, HSDB hsdb, int cur) +{ + char exename[MAX_PATH], testfile[MAX_PATH]; + WCHAR exenameW[MAX_PATH]; + BOOL ret; + SDBQUERYRESULT query; + PDB pdb; + TAGID tagid; + TAGREF trApphelp; + DWORD expect_flags = 0, adwExeFlags_0, exe_count; + int n; + + memset(&query, 0xab, sizeof(query)); + + sprintf(exename, "%s\%s", workdir, test_exedata[cur].name); + if (test_exedata[cur].extra_file) + sprintf(testfile, "%s\%s", workdir, test_exedata[cur].extra_file); + test_create_exe(exename, 0); + MultiByteToWideChar(CP_ACP, 0, exename, -1, exenameW, MAX_PATH); + + if (test_exedata[cur].extra_file) + { + /* First we try without the file at all. */ + DeleteFileA(testfile); + ret = pSdbGetMatchingExe(hsdb, exenameW, NULL, NULL, 0, &query); + ok(ret == 0, "SdbGetMatchingExe should have failed for %d.\n", cur); + /* Now re-try with the correct file */ + test_create_file(testfile, "aaaa", 4); + } + +#if 0 + // Results seem to be cached based on filename, until we can invalidate this, do not test the same filename twice! + DeleteFileA(exename); + // skip exports + test_create_exe(exename, 1); + ret = pSdbGetMatchingExe(hsdb, exenameW, NULL, NULL, 0, &query); + ok(ret == 0, "SdbGetMatchingExe should have failed for %d.\n", cur); + + DeleteFileA(exename); + test_create_exe(exename, 0); +#endif + + if (test_exedata[cur].env_var) + { + SetEnvironmentVariableA("__COMPAT_LAYER", test_exedata[cur].env_var); + } + + ret = pSdbGetMatchingExe(hsdb, exenameW, NULL, NULL, 0, &query); + ok(ret, "SdbGetMatchingExe should not fail for %d.\n", cur); + + exe_count = (test_exedata[cur].env_var == NULL) ? 1 : 0; + + ok(query.dwExeCount == exe_count, "Expected dwExeCount to be %d, was %d for %d\n", exe_count, query.dwExeCount, cur); + ok(query.dwLayerCount == test_exedata[cur].dwLayerCount, "Expected dwLayerCount to be %d, was %d for %d\n", test_exedata[cur].dwLayerCount, query.dwLayerCount, cur); + ok(query.dwCustomSDBMap == 1, "Expected dwCustomSDBMap to be 1, was %d for %d\n", query.dwCustomSDBMap, cur); + ok(query.dwLayerFlags == 0, "Expected dwLayerFlags to be 0, was 0x%x for %d\n", query.dwLayerFlags, cur); + trApphelp = (g_WinVersion < WINVER_WIN10) ? 0 : test_exedata[cur].trApphelp; + ok(query.trApphelp == trApphelp, "Expected trApphelp to be 0x%x, was 0x%x for %d\n", trApphelp, query.trApphelp, cur); + + if (g_WinVersion < WINVER_WIN7) + expect_flags = 0; + else if (g_WinVersion < WINVER_WIN8) + expect_flags = 1; + else if (g_WinVersion < WINVER_WIN10) + expect_flags = 0x101; + else + expect_flags = 0x121; + + if (test_exedata[cur].env_var) + expect_flags &= ~0x100; + + ok(query.dwFlags == expect_flags, "Expected dwFlags to be 0x%x, was 0x%x for %d\n", expect_flags, query.dwFlags, cur); + + ok(query.atrExes[0] == test_exedata[cur].atrExes_0, "Expected atrExes[0] to be 0x%x, was: 0x%x for %d\n", test_exedata[cur].atrExes_0, query.atrExes[0], cur); + for (n = 1; n < SDB_MAX_EXES; ++n) + ok(query.atrExes[n] == 0, "Expected atrExes[%d] to be 0, was: %x for %d\n", n, query.atrExes[n], cur); + + adwExeFlags_0 = (g_WinVersion < WINVER_WIN10) ? 0 : test_exedata[cur].adwExeFlags_0; + ok(query.adwExeFlags[0] == adwExeFlags_0, "Expected adwExeFlags[0] to be 0x%x, was: 0x%x for %d\n", adwExeFlags_0, query.adwExeFlags[0], cur); + for (n = 1; n < SDB_MAX_EXES; ++n) + ok(query.adwExeFlags[n] == 0, "Expected adwExeFlags[%d] to be 0, was: %x for %d\n", n, query.adwExeFlags[0], cur); + + ok(query.atrLayers[0] == test_exedata[cur].atrLayers_0, "Expected atrLayers[0] to be 0x%x, was: %x for %d\n", test_exedata[cur].atrLayers_0, query.atrLayers[0], cur); + for (n = 1; n < SDB_MAX_LAYERS; ++n) + ok(query.atrLayers[n] == 0, "Expected atrLayers[%d] to be 0, was: %x for %d\n", n, query.atrLayers[0], cur); + + ok(IsEqualGUID(&query.rgGuidDB[0], &GUID_DATABASE_TEST), "Expected rgGuidDB[0] to be the test db GUID, was: %s for %d\n", wine_dbgstr_guid(&query.rgGuidDB[0]), cur); + for (n = 1; n < SDB_MAX_SDBS; ++n) + ok(IsEqualGUID(&query.rgGuidDB[n], &GUID_NULL), "Expected rgGuidDB[%d] to be GUID_NULL, was: %s for %d\n", n, wine_dbgstr_guid(&query.rgGuidDB[n]), cur); + + if (query.atrExes[0]) + { + pdb = (PDB)0x12345678; + tagid = 0x76543210; + ret = pSdbTagRefToTagID(hsdb, query.atrExes[0], &pdb, &tagid); + ok(ret, "SdbTagRefToTagID failed for %d.\n", cur); + ok(pdb != NULL && pdb != (PDB)0x12345678, "SdbTagRefToTagID failed to return a pdb for %d.\n", cur); + ok(tagid != 0 && tagid != 0x76543210, "SdbTagRefToTagID failed to return a tagid for %d.\n", cur); + + if (pdb && pdb != (PDB)0x12345678) + { + TAG tag = pSdbGetTagFromTagID(pdb, tagid); + test_is_testdb(pdb); + ok(tag == TAG_EXE, "Expected tag to be TAG_EXE, was 0x%x for %d.\n", tag, cur); + match_str_attr(pdb, tagid, TAG_NAME, test_exedata[cur].name); + } + else + { + skip("Skipping a bunch of tests because of an invalid pointer\n"); + } + } + + if (test_exedata[cur].atrLayers_0) + { + pdb = (PDB)0x12345678; + tagid = 0x76543210; + ret = pSdbTagRefToTagID(hsdb, query.atrLayers[0], &pdb, &tagid); + ok(ret, "SdbTagRefToTagID failed for %d.\n", cur); + ok(pdb != NULL && pdb != (PDB)0x12345678, "SdbTagRefToTagID failed to return a pdb for %d.\n", cur); + ok(tagid != 0 && tagid != 0x76543210, "SdbTagRefToTagID failed to return a tagid for %d.\n", cur); + + if (pdb && pdb != (PDB)0x12345678) + { + TAG tag = pSdbGetTagFromTagID(pdb, tagid); + test_is_testdb(pdb); + ok(tag == TAG_LAYER, "Expected tag to be TAG_LAYER, was 0x%x for %d.\n", tag, cur); + match_str_attr(pdb, tagid, TAG_NAME, "TestNewMode"); + } + else + { + skip("Skipping a bunch of tests because of an invalid pointer\n"); + } + } + + pdb = (PDB)0x12345678; + tagid = 0x76543210; + ret = pSdbTagRefToTagID(hsdb, 0, &pdb, &tagid); + ok(pdb != NULL && pdb != (PDB)0x12345678, "Expected pdb to be set to a valid pdb, was: %p\n", pdb); + ok(tagid == 0, "Expected tagid to be set to 0, was: 0x%x\n", tagid); + + if (test_exedata[cur].extra_file) + DeleteFileA(testfile); + DeleteFileA(exename); + + if (test_exedata[cur].env_var) + { + SetEnvironmentVariableA("__COMPAT_LAYER", NULL); + } +} + + +static void test_MatchApplications(void) +{ + char workdir[MAX_PATH], dbpath[MAX_PATH]; + WCHAR dbpathW[MAX_PATH]; + BOOL ret; + HSDB hsdb; + + ret = GetTempPathA(MAX_PATH, workdir); + ok(ret, "GetTempPathA error: %d\n", GetLastError()); + lstrcatA(workdir, "apphelp_test"); + + ret = CreateDirectoryA(workdir, NULL); + ok(ret, "CreateDirectoryA error: %d\n", GetLastError()); + + /* SdbInitDatabase needs an nt-path */ + sprintf(dbpath, "\??\%s\test.sdb", workdir); + + test_create_db(dbpath + 4); + + MultiByteToWideChar(CP_ACP, 0, dbpath, -1, dbpathW, MAX_PATH); + hsdb = pSdbInitDatabase(HID_DATABASE_FULLPATH, dbpathW); + + ok(hsdb != NULL, "Expected a valid database handle\n"); + + if (!hsdb) + { + skip("SdbInitDatabase not implemented?\n"); + } + else + { + /* now that our enviroment is setup, let's go ahead and run the actual tests.. */ + int n; + for (n = 0; n < _countof(test_exedata); ++n) + test_mode_generic(workdir, hsdb, n); + pSdbReleaseDatabase(hsdb); + } + + DeleteFileA(dbpath + 4); + + ret = RemoveDirectoryA(workdir); + ok(ret, "RemoveDirectoryA error: %d\n", GetLastError()); +} + +static void test_TagRef(void) +{ + char tmpdir[MAX_PATH], dbpath[MAX_PATH]; + WCHAR dbpathW[MAX_PATH]; + BOOL ret; + HSDB hsdb; + PDB pdb; + TAGID db; + DWORD size; + + ret = GetTempPathA(MAX_PATH, tmpdir); + ok(ret, "GetTempPathA error: %d\n", GetLastError()); + + /* SdbInitDatabase needs an nt-path */ + sprintf(dbpath, "\??\%stest.sdb", tmpdir); + + test_create_db(dbpath + 4); + + MultiByteToWideChar(CP_ACP, 0, dbpath, -1, dbpathW, MAX_PATH); + hsdb = pSdbInitDatabase(HID_DATABASE_FULLPATH, dbpathW); + + /* HSDB is the only arg that can't be null */ + ret = pSdbTagRefToTagID(hsdb, 0, NULL, NULL); + ok(ret == TRUE, "Expected ret to be TRUE, was: %d\n", ret); + + size = test_get_db_size(); + + pdb = (PDB)&db; + db = 12345; + ret = pSdbTagRefToTagID(hsdb, size - 1, &pdb, &db); + ok(ret == TRUE, "Expected ret to be TRUE, was: %d\n", ret); + ok(pdb != NULL, "Expected a result, got: %p\n", pdb); + ok(db == (size - 1), "Expected %u, got: %u\n", size - 1, db); + + pdb = (PDB)&db; + db = 12345; + ret = pSdbTagRefToTagID(hsdb, size, &pdb, &db); + ok(ret == TRUE, "Expected ret to be TRUE, was: %d\n", ret); + ok(pdb != NULL, "Expected a result, got: %p\n", pdb); + ok(db == (size), "Expected %u, got: %u\n", size, db); + + pdb = (PDB)&db; + db = 12345; + ret = pSdbTagRefToTagID(hsdb, size + 1, &pdb, &db); + ok(ret == TRUE, "Expected ret to be TRUE, was: %d\n", ret); + ok(pdb != NULL, "Expected a result, got: %p\n", pdb); + ok(db == (size + 1), "Expected %u, got: %u\n", size + 1, db); + + pdb = (PDB)&db; + db = 12345; + ret = pSdbTagRefToTagID(hsdb, 0x0fffffff, &pdb, &db); + ok(ret == TRUE, "Expected ret to be TRUE, was: %d\n", ret); + ok(pdb != NULL, "Expected a result, got: %p\n", pdb); + ok(db == 0x0fffffff, "Expected %u, got: %u\n", 0x0fffffff, db); + + pdb = (PDB)&db; + db = 12345; + ret = pSdbTagRefToTagID(hsdb, 0x10000000, &pdb, &db); + ok(ret == FALSE, "Expected ret to be FALSE, was: %d\n", ret); + ok(pdb == NULL, "Expected no result, got: %p\n", pdb); + ok(db == 0, "Expected no result, got: 0x%x\n", db); + + pdb = NULL; + db = TAGID_NULL; + ret = pSdbTagRefToTagID(hsdb, TAGID_ROOT, &pdb, NULL); + ok(ret != FALSE, "Expected ret to be TRUE, was: %d\n", ret); + ok(pdb != NULL, "Expected pdb to be valid\n"); + + if(pdb == NULL) + { + skip("Cannot run tests without pdb\n"); + } + else + { + db = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE); + if(db != TAGID_NULL) + { + TAGID child; + child = pSdbGetFirstChild(pdb, db); + while(child != TAGID_NULL) + { + PDB pdb_res; + TAGID tagid_res; + ret = pSdbTagRefToTagID(hsdb, child, &pdb_res, &tagid_res); + ok(ret, "Expected SdbTagRefToTagID to succeed\n"); + child = pSdbGetNextChild(pdb, db, child); + } + } + else + { + skip("Cannot run tests without valid db tag\n"); + } + } + + DeleteFileA(dbpath + 4); +} +
static void expect_indexA_imp(const char* text, LONGLONG expected) @@ -1051,10 +1419,39 @@ wine_dbgstr_longlong(0xbc414044444444), wine_dbgstr_longlong(result)); }
+static int validate_SDBQUERYRESULT_size() +{ + unsigned char buffer[SDBQUERYRESULT_EXPECTED_SIZE * 2]; + WCHAR path[MAX_PATH]; + HSDB hsdb; + + memset(buffer, 0xab, sizeof(buffer)); + hsdb = pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM, NULL); + if (hsdb) + { + GetModuleFileNameW(NULL, path, MAX_PATH); + pSdbGetMatchingExe(hsdb, path, NULL, NULL, 0, (SDBQUERYRESULT*)buffer); + pSdbReleaseDatabase(hsdb); + if (buffer[0] == buffer[1] && buffer[1] == 0xab) + { + trace("SdbGetMatchingExe didnt do anything, cannot determine SDBQUERYRESULT size\n"); + return 1; + } + return buffer[SDBQUERYRESULT_EXPECTED_SIZE] == 0xab && buffer[SDBQUERYRESULT_EXPECTED_SIZE-1] != 0xab; + } + + return 1; +} +
START_TEST(db) { + g_WinVersion = get_host_winver(); + trace("Detected version: 0x%x\n", g_WinVersion); + silence_debug_output(); + //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4"); + //SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "4"); //SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp"); hdll = LoadLibraryA("apphelp.dll"); pSdbTagToString = (void *) GetProcAddress(hdll, "SdbTagToString"); @@ -1087,11 +1484,21 @@ pSdbGetNextChild = (void *) GetProcAddress(hdll, "SdbGetNextChild"); pSdbGetDatabaseID = (void *) GetProcAddress(hdll, "SdbGetDatabaseID"); pSdbGUIDToString = (void *) GetProcAddress(hdll, "SdbGUIDToString"); - pSdbMakeIndexKeyFromString = (void*) GetProcAddress(hdll, "SdbMakeIndexKeyFromString"); + pSdbInitDatabase = (void *) GetProcAddress(hdll, "SdbInitDatabase"); + pSdbReleaseDatabase = (void *) GetProcAddress(hdll, "SdbReleaseDatabase"); + pSdbGetMatchingExe = (void *) GetProcAddress(hdll, "SdbGetMatchingExe"); + pSdbTagRefToTagID = (void *) GetProcAddress(hdll, "SdbTagRefToTagID"); + pSdbMakeIndexKeyFromString = (void *) GetProcAddress(hdll, "SdbMakeIndexKeyFromString");
test_Sdb(); test_write_ex(); test_stringtable(); test_CheckDatabaseManually(); + if (validate_SDBQUERYRESULT_size()) + test_MatchApplications(); + else + skip("Skipping tests with SDBQUERYRESULT due to a wrong size reported\n"); + test_TagRef(); + skip("test_SecondaryDB()\n"); test_IndexKeyFromString(); }
Modified: trunk/rostests/apitests/apphelp/layerapi.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/apphelp/layerapi.... ============================================================================== --- trunk/rostests/apitests/apphelp/layerapi.c [iso-8859-1] (original) +++ trunk/rostests/apitests/apphelp/layerapi.c [iso-8859-1] Sat Sep 3 16:20:52 2016 @@ -31,8 +31,7 @@
#include "wine/test.h"
-/* data.c */ -DWORD get_host_winver(void); +#include "apphelp_apitest.h"
#define GPLK_USER 1 #define GPLK_MACHINE 2 @@ -45,12 +44,6 @@ static BOOL(WINAPI *pSdbSetPermLayerKeys)(PCWSTR wszPath, PCWSTR wszLayers, BOOL bMachine); static BOOL(WINAPI *pSdbGetPermLayerKeys)(PCWSTR wszPath, PWSTR pwszLayers, PDWORD pdwBytes, DWORD dwFlags); static BOOL(WINAPI *pSetPermLayerState)(PCWSTR wszPath, PCWSTR wszLayer, DWORD dwFlags, BOOL bMachine, BOOL bEnable); - - -static DWORD g_WinVersion; -#define WINVER_VISTA 0x0600 -#define WINVER_WIN8 0x0602 -#define WINVER_WIN10 0x1000
/* Helper function to disable Wow64 redirection on an os that reports it being enabled. */ @@ -877,6 +870,7 @@
START_TEST(layerapi) { + silence_debug_output(); /*SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");*/ hdll = LoadLibraryA("apphelp.dll"); pAllowPermLayer = (void *)GetProcAddress(hdll, "AllowPermLayer");