Author: mjansen
Date: Fri May 19 20:13:08 2017
New Revision: 74601
URL:
http://svn.reactos.org/svn/reactos?rev=74601&view=rev
Log:
[APPHELP] Initial implementation of ApphelpCheckRunAppEx. CORE-10368
Modified:
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/hsdb.c
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.c [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.c [iso-8859-1] Fri May 19 20:13:08 2017
@@ -1,7 +1,7 @@
/*
* Copyright 2011 André Hentschel
* Copyright 2013 Mislav BlaževiÄ
- * Copyright 2015 Mark Jansen
+ * Copyright 2015-2017 Mark Jansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,8 +24,9 @@
#include "winver.h"
#include "strsafe.h"
#include "apphelp.h"
-
-#include "wine/winternl.h"
+#include "ndk/rtlfuncs.h"
+#include "ndk/kdtypes.h"
+
/* from dpfilter.h */
#define DPFLTR_APPCOMPAT_ID 123
@@ -35,23 +36,19 @@
#endif
ULONG g_ShimDebugLevel = 0xffffffff;
+HMODULE g_hInstance;
void ApphelppInitDebugLevel(void)
{
- UNICODE_STRING DebugKey, DebugValue;
+ static const UNICODE_STRING DebugKey =
RTL_CONSTANT_STRING(L"SHIM_DEBUG_LEVEL");
+ UNICODE_STRING DebugValue;
NTSTATUS Status;
ULONG NewLevel = SHIM_ERR;
WCHAR Buffer[40];
- RtlInitUnicodeString(&DebugKey, L"SHIM_DEBUG_LEVEL");
- DebugValue.MaximumLength = sizeof(Buffer);
- DebugValue.Buffer = Buffer;
- DebugValue.Length = 0;
-
- /* Hold the lock as short as possible. */
- RtlAcquirePebLock();
+ RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer));
+
Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
- RtlReleasePebLock();
if (NT_SUCCESS(Status))
{
@@ -60,6 +57,7 @@
}
g_ShimDebugLevel = NewLevel;
}
+
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
{
@@ -70,6 +68,7 @@
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH:
+ g_hInstance = hinst;
DisableThreadLibraryCalls( hinst );
SdbpHeapInit();
break;
@@ -145,9 +144,11 @@
break;
}
StringCchPrintfExA(Current, Length, &Current, &Length,
STRSAFE_NULL_ON_FAILURE, "[%s][%-20s] ", LevelStr, FunctionName);
+
va_start(ArgList, Format);
StringCchVPrintfExA(Current, Length, &Current, &Length,
STRSAFE_NULL_ON_FAILURE, Format, ArgList);
va_end(ArgList);
+
#if defined(APPCOMPAT_USE_DBGPRINTEX) && APPCOMPAT_USE_DBGPRINTEX
return NT_SUCCESS(DbgPrintEx(DPFLTR_APPCOMPAT_ID, Level, "%s", Buffer));
#else
@@ -156,3 +157,102 @@
#endif
}
+
+#define APPHELP_DONTWRITE_REASON 2
+#define APPHELP_CLEARBITS 0x100 /* TODO: Investigate */
+#define APPHELP_IGNORE_ENVIRONMENT 0x400
+
+#define APPHELP_VALID_RESULT 0x10000
+#define APPHELP_RESULT_NOTFOUND 0x20000
+#define APPHELP_RESULT_FOUND 0x40000
+
+/**
+ * Lookup Shims / Fixes for the specified application
+ *
+ * @param [in] FileHandle Handle to the file to check.
+ * @param [in] Unk1
+ * @param [in] Unk2
+ * @param [in] ApplicationName Exe to check
+ * @param [in] Environment The environment variables to use, or NULL to
use the current environment.
+ * @param [in] ExeType Exe type (MACHINE_TYPE_XXXX)
+ * @param [in,out] Reason Input/output flags
+ * @param [in] SdbQueryAppCompatData The resulting data.
+ * @param [in] SdbQueryAppCompatDataSize The resulting data size.
+ * @param [in] SxsData TODO
+ * @param [in] SxsDataSize TODO
+ * @param [in] FusionFlags TODO
+ * @param [in] SomeFlag1 TODO
+ * @param [in] SomeFlag2 TODO
+ *
+ * @return TRUE if the application is allowed to run.
+ */
+BOOL
+WINAPI
+ApphelpCheckRunAppEx(
+ _In_ HANDLE FileHandle,
+ _In_opt_ PVOID Unk1,
+ _In_opt_ PVOID Unk2,
+ _In_opt_z_ PWCHAR ApplicationName,
+ _In_opt_ PVOID Environment,
+ _In_opt_ USHORT ExeType,
+ _Inout_opt_ PULONG Reason,
+ _Out_opt_ PVOID* SdbQueryAppCompatData,
+ _Out_opt_ PULONG SdbQueryAppCompatDataSize,
+ _Out_opt_ PVOID* SxsData,
+ _Out_opt_ PULONG SxsDataSize,
+ _Out_opt_ PULONG FusionFlags,
+ _Out_opt_ PULONG64 SomeFlag1,
+ _Out_opt_ PULONG SomeFlag2)
+{
+ SDBQUERYRESULT* result = NULL;
+ HSDB hsdb = NULL;
+ DWORD dwFlags = 0;
+
+ if (SxsData)
+ *SxsData = NULL;
+ if (SxsDataSize)
+ *SxsDataSize = 0;
+ if (FusionFlags)
+ *FusionFlags = 0;
+ if (SomeFlag1)
+ *SomeFlag1 = 0;
+ if (SomeFlag2)
+ *SomeFlag2 = 0;
+ if (Reason)
+ dwFlags = *Reason;
+
+ dwFlags &= ~APPHELP_CLEARBITS;
+
+ *SdbQueryAppCompatData = result = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(SDBQUERYRESULT));
+ if (SdbQueryAppCompatDataSize)
+ *SdbQueryAppCompatDataSize = sizeof(*result);
+
+
+ hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
+ if (hsdb)
+ {
+ BOOL FoundMatch;
+ DWORD MatchingExeFlags = 0;
+
+ if (dwFlags & APPHELP_IGNORE_ENVIRONMENT)
+ MatchingExeFlags |= SDBGMEF_IGNORE_ENVIRONMENT;
+
+ FoundMatch = SdbGetMatchingExe(hsdb, ApplicationName, NULL, Environment,
MatchingExeFlags, result);
+ if (FileHandle != INVALID_HANDLE_VALUE)
+ {
+ dwFlags |= APPHELP_VALID_RESULT;
+ dwFlags |= (FoundMatch ? APPHELP_RESULT_FOUND : APPHELP_RESULT_NOTFOUND);
+ }
+
+ SdbReleaseDatabase(hsdb);
+ }
+
+ if (Reason && !(dwFlags & APPHELP_DONTWRITE_REASON))
+ *Reason = dwFlags;
+
+
+ /* We should _ALWAYS_ return TRUE here, unless we want to block an application from
starting! */
+ return TRUE;
+}
+
+
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] Fri May 19 20:13:08 2017
@@ -1,6 +1,6 @@
/*
* Copyright 2013 Mislav BlaževiÄ
- * Copyright 2015,2016 Mark Jansen
+ * Copyright 2015-2017 Mark Jansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -63,6 +63,10 @@
#define SHIMREG_DISABLE_LAYER (0x00000020)
#define SHIMREG_DISABLE_DRIVER (0x00000040)
+/* Flags for dwFlags */
+#define SHIMREG_HAS_ENVIRONMENT (0x1)
+
+/* Flags for SdbGetMatchingExe */
#define SDBGMEF_IGNORE_ENVIRONMENT (0x1)
typedef struct tagSDBQUERYRESULT {
@@ -100,6 +104,7 @@
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);
+DWORD WINAPI SdbReadDWORDTag(PDB db, TAGID tagid, DWORD ret);
/* sdbfileattr.c*/
BOOL WINAPI SdbFreeFileAttributes(PATTRINFO attr_info);
@@ -110,6 +115,7 @@
BOOL WINAPI SetPermLayerState(PCWSTR wszPath, PCWSTR wszLayer, DWORD dwFlags, BOOL
bMachine, BOOL bEnable);
/* hsdb.c */
+BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name, LPCWSTR env,
DWORD flags, PSDBQUERYRESULT result);
BOOL WINAPI SdbTagIDToTagRef(HSDB hsdb, PDB pdb, TAGID tiWhich, TAGREF* ptrWhich);
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.spec [iso-8859-1] Fri May 19 20:13:08
2017
@@ -3,7 +3,7 @@
@ stdcall ApphelpCheckInstallShieldPackage(ptr wstr)
@ stub ApphelpCheckMsiPackage
@ stub ApphelpCheckRunApp
-@ stub ApphelpCheckRunAppEx
+@ stdcall ApphelpCheckRunAppEx(ptr ptr ptr wstr ptr long ptr ptr ptr ptr ptr ptr ptr
ptr)
@ stdcall ApphelpCheckShellObject(ptr long ptr)
@ stub ApphelpCreateAppcompatData
@ stub ApphelpFixMsiPackage
Modified: 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 [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/hsdb.c [iso-8859-1] Fri May 19 20:13:08 2017
@@ -1,7 +1,7 @@
/*
* Copyright 2011 André Hentschel
* Copyright 2013 Mislav BlaževiÄ
- * Copyright 2015,2016 Mark Jansen
+ * Copyright 2015-2017 Mark Jansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,12 +26,214 @@
#include "wine/unicode.h"
+#define MAX_LAYER_LENGTH 256
+#define GPLK_USER 1
+#define GPLK_MACHINE 2
static BOOL WINAPI SdbpFileExists(LPCWSTR path)
{
DWORD attr = GetFileAttributesW(path);
return (attr != INVALID_FILE_ATTRIBUTES && !(attr &
FILE_ATTRIBUTE_DIRECTORY));
}
+
+static BOOL WINAPI SdbpMatchExe(PDB db, TAGID exe, WCHAR* dir)
+{
+ static const WCHAR fmt[] = {'%','s','%','s',0};
+ WCHAR buffer[256]; /* FIXME: rewrite using a buffer that can grow if needed, f.e.
RtlInitBuffer stuff! */
+ TAGID matching_file;
+
+ /* TODO: check size/checksum from the main exe as well as from the extra files */
+ for (matching_file = SdbFindFirstTag(db, exe, TAG_MATCHING_FILE);
+ matching_file != TAGID_NULL; matching_file = SdbFindNextTag(db, exe,
matching_file))
+ {
+ TAGID tagName = SdbFindFirstTag(db, matching_file, TAG_NAME);
+ LPWSTR name = SdbGetStringTagPtr(db, tagName);
+
+ if (!wcscmp(name, L"*"))
+ {
+ // if attributes dont match main file, return FALSE!
+ continue;
+ }
+
+ snprintfW(buffer, _countof(buffer), fmt, dir, name);
+ if (!SdbpFileExists(buffer))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void SdbpAddDatabaseGuid(PDB db, PSDBQUERYRESULT result)
+{
+ size_t n;
+
+ for (n = 0; n < _countof(result->rgGuidDB); ++n)
+ {
+ if (!memcmp(&result->rgGuidDB[n], &db->database_id,
sizeof(db->database_id)))
+ return;
+
+ if (result->dwCustomSDBMap & (1<<n))
+ continue;
+
+ memcpy(&result->rgGuidDB[n], &db->database_id,
sizeof(result->rgGuidDB[n]));
+ result->dwCustomSDBMap |= (1<<n);
+ return;
+ }
+}
+
+static BOOL SdbpAddSingleLayerMatch(TAGREF layer, PSDBQUERYRESULT result)
+{
+ size_t n;
+
+ for (n = 0; n < result->dwLayerCount; ++n)
+ {
+ if (result->atrLayers[n] == layer)
+ return FALSE;
+ }
+
+ if (n >= _countof(result->atrLayers))
+ return FALSE;
+
+ result->atrLayers[n] = layer;
+ result->dwLayerCount++;
+
+ return TRUE;
+}
+
+
+static BOOL SdbpAddNamedLayerMatch(HSDB hsdb, PCWSTR layerName, PSDBQUERYRESULT result)
+{
+ TAGID database, layer;
+ TAGREF tr;
+ PDB db = hsdb->db;
+
+ database = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE);
+ if (database == TAGID_NULL)
+ return FALSE;
+
+ layer = SdbFindFirstNamedTag(db, database, TAG_LAYER, TAG_NAME, layerName);
+ if (layer == TAGID_NULL)
+ return FALSE;
+
+ if (!SdbTagIDToTagRef(hsdb, db, layer, &tr))
+ return FALSE;
+
+ if (!SdbpAddSingleLayerMatch(tr, result))
+ return FALSE;
+
+ SdbpAddDatabaseGuid(db, result);
+ return TRUE;
+}
+
+static void SdbpAddExeLayers(HSDB hsdb, PDB db, TAGID tagExe, PSDBQUERYRESULT result)
+{
+ TAGID layer = SdbFindFirstTag(db, tagExe, TAG_LAYER);
+
+ while (layer != TAGID_NULL)
+ {
+ TAGREF tr;
+ TAGID layerIdTag = SdbFindFirstTag(db, layer, TAG_LAYER_TAGID);
+ DWORD tagId = SdbReadDWORDTag(db, layerIdTag, TAGID_NULL);
+
+ if (layerIdTag != TAGID_NULL &&
+ tagId != TAGID_NULL &&
+ SdbTagIDToTagRef(hsdb, db, tagId, &tr))
+ {
+ SdbpAddSingleLayerMatch(tr, result);
+ }
+ else
+ {
+ /* Try a name lookup */
+ TAGID layerTag = SdbFindFirstTag(db, layer, TAG_NAME);
+ if (layerTag != TAGID_NULL)
+ {
+ LPCWSTR layerName = SdbGetStringTagPtr(db, layerTag);
+ if (layerName)
+ {
+ SdbpAddNamedLayerMatch(hsdb, layerName, result);
+ }
+ }
+ }
+
+ layer = SdbFindNextTag(db, tagExe, layer);
+ }
+}
+
+static void SdbpAddExeMatch(HSDB hsdb, PDB db, TAGID tagExe, PSDBQUERYRESULT result)
+{
+ size_t n;
+ TAGREF tr;
+
+ if (!SdbTagIDToTagRef(hsdb, db, tagExe, &tr))
+ return;
+
+ for (n = 0; n < result->dwExeCount; ++n)
+ {
+ if (result->atrExes[n] == tr)
+ return;
+ }
+
+ if (n >= _countof(result->atrExes))
+ return;
+
+ result->atrExes[n] = tr;
+ result->dwExeCount++;
+
+ SdbpAddExeLayers(hsdb, db, tagExe, result);
+
+ SdbpAddDatabaseGuid(db, result);
+}
+
+static ULONG SdbpAddLayerMatches(HSDB hsdb, PWSTR pwszLayers, DWORD pdwBytes,
PSDBQUERYRESULT result)
+{
+ PWSTR start = pwszLayers, p;
+ ULONG Added = 0;
+
+ const PWSTR end = pwszLayers + (pdwBytes / sizeof(WCHAR));
+ while (start < end && (*start == L'!' || *start == L'#' ||
*start == L' ' || *start == L'\t'))
+ start++;
+
+ if (start == end)
+ return 0;
+
+ do
+ {
+ while (*start == L' ' || *start == L'\t')
+ ++start;
+
+ if (*start == UNICODE_NULL)
+ break;
+ p = wcspbrk(start, L" \t");
+
+ if (p)
+ *p = UNICODE_NULL;
+
+ if (SdbpAddNamedLayerMatch(hsdb, start, result))
+ Added++;
+
+ start = p + 1;
+ } while (start < end && p);
+
+ return Added;
+}
+
+static BOOL SdbpPropagateEnvLayers(HSDB hsdb, LPWSTR Environment, PSDBQUERYRESULT
Result)
+{
+ static const UNICODE_STRING EnvKey =
RTL_CONSTANT_STRING(L"__COMPAT_LAYER");
+ UNICODE_STRING EnvValue;
+ NTSTATUS Status;
+ WCHAR Buffer[MAX_LAYER_LENGTH];
+
+ RtlInitEmptyUnicodeString(&EnvValue, Buffer, sizeof(Buffer));
+
+ Status = RtlQueryEnvironmentVariable_U(Environment, &EnvKey, &EnvValue);
+
+ if (!NT_SUCCESS(Status))
+ return FALSE;
+
+ return SdbpAddLayerMatches(hsdb, Buffer, EnvValue.Length, Result) > 0;
+}
+
/**
@@ -50,12 +252,12 @@
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)
+ HSDB hsdb;
+
+ hsdb = SdbAlloc(sizeof(SDB));
+ if (!hsdb)
return NULL;
- sdb->auto_loaded = 0;
+ hsdb->auto_loaded = 0;
/* Check for predefined databases */
if ((flags & HID_DATABASE_TYPE_MASK) && path == NULL)
@@ -66,23 +268,24 @@
case SDB_DATABASE_MAIN_MSI: name = msi; break;
case SDB_DATABASE_MAIN_DRIVERS: name = drivers; break;
default:
- SdbReleaseDatabase(sdb);
+ SdbReleaseDatabase(hsdb);
return NULL;
}
SdbGetAppPatchDir(NULL, buffer, 128);
- memcpy(buffer + lstrlenW(buffer), name, SdbpStrlen(name));
- }
-
- sdb->db = SdbOpenDatabase(path ? path : buffer, (flags & 0xF) - 1);
+ memcpy(buffer + lstrlenW(buffer), name, SdbpStrsize(name));
+ flags = HID_DOS_PATHS;
+ }
+
+ hsdb->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);
+ if (!hsdb->db)
+ {
+ SdbReleaseDatabase(hsdb);
return NULL;
}
- return sdb;
+ return hsdb;
}
/**
@@ -103,7 +306,7 @@
* @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] env The environment block to use
* @param [in] flags 0 or SDBGMEF_IGNORE_ENVIRONMENT.
* @param [out] result Pointer to structure in which query result shall be stored.
*
@@ -112,14 +315,16 @@
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;
+ BOOL ret = FALSE;
+ TAGID database, iter, name;
PATTRINFO attribs = NULL;
/*DWORD attr_count;*/
+ RTL_UNICODE_STRING_BUFFER DosApplicationName = { { 0 } };
+ WCHAR DosPathBuffer[MAX_PATH];
+ ULONG PathType = 0;
LPWSTR file_name;
- WCHAR dir_path[128];
- WCHAR buffer[256];
+ WCHAR wszLayers[MAX_LAYER_LENGTH];
+ DWORD dwSize;
PDB db;
/* Load default database if one is not specified */
@@ -128,21 +333,49 @@
/* 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)
+ if (hsdb)
hsdb->auto_loaded = TRUE;
}
+ ZeroMemory(result, sizeof(*result));
+
/* No database could be loaded */
- if (!hsdb)
- return FALSE;
-
+ if (!hsdb || !path)
+ return FALSE;
+
+ /* We do not support multiple db's yet! */
db = hsdb->db;
+ RtlInitUnicodeString(&DosApplicationName.String, path);
+ RtlInitBuffer(&DosApplicationName.ByteBuffer, (PUCHAR)DosPathBuffer,
sizeof(DosPathBuffer));
+ if (!NT_SUCCESS(RtlEnsureBufferSize(RTL_SKIP_BUFFER_COPY,
&DosApplicationName.ByteBuffer, DosApplicationName.String.MaximumLength)))
+ {
+ SHIM_ERR("Failed to convert allocate buffer.");
+ goto Cleanup;
+ }
+ /* Update the internal buffer to contain the string */
+ memcpy(DosApplicationName.ByteBuffer.Buffer, path,
DosApplicationName.String.MaximumLength);
+ /* Make sure the string uses our internal buffer (we want to modify the buffer,
+ and RtlNtPathNameToDosPathName does not always modify the String to point to the
Buffer)! */
+ DosApplicationName.String.Buffer = (PWSTR)DosApplicationName.ByteBuffer.Buffer;
+
+ if (!NT_SUCCESS(RtlNtPathNameToDosPathName(0, &DosApplicationName, &PathType,
NULL)))
+ {
+ SHIM_ERR("Failed to convert %S to DOS Path.", path);
+ goto Cleanup;
+ }
+
+
/* Extract file name */
- file_name = strrchrW(path, '\\') + 1;
-
- /* Extract directory path */
- memcpy(dir_path, path, (size_t)(file_name - path) * sizeof(WCHAR));
+ file_name = strrchrW(DosApplicationName.String.Buffer, '\\');
+ if (!file_name)
+ {
+ SHIM_ERR("Failed to find Exe name in %wZ.",
&DosApplicationName.String);
+ goto Cleanup;
+ }
+
+ /* We will use the buffer for exe name and directory. */
+ *(file_name++) = UNICODE_NULL;
/* Get information about executable required to match it with database entry */
/*if (!SdbGetFileAttributes(path, &attribs, &attr_count))
@@ -151,38 +384,28 @@
/* DATABASE is list TAG which contains all executables */
database = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE);
if (database == TAGID_NULL)
- return FALSE;
+ {
+ goto Cleanup;
+ }
/* EXE is list TAG which contains data required to match executable */
iter = SdbFindFirstTag(db, database, TAG_EXE);
- /* Search for entry in database */
+ /* Search for entry in database, we should look into indexing tags! */
while (iter != TAGID_NULL)
{
+ LPWSTR foundName;
/* 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))
+ name = SdbFindFirstTag(db, iter, TAG_NAME);
+ /* If this is a malformed DB, (no TAG_NAME), we should not crash. */
+ foundName = SdbGetStringTagPtr(db, name);
+ if (foundName && !lstrcmpiW(foundName, file_name))
+ {
+ /* We have a null terminator before the application name, so
DosApplicationName only contains the path. */
+ if (SdbpMatchExe(db, iter, DosApplicationName.String.Buffer))
{
- 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;
+ SdbpAddExeMatch(hsdb, db, iter, result);
}
}
@@ -190,12 +413,31 @@
iter = SdbFindNextTag(db, database, iter);
}
- /* Exe not found */
- ret = FALSE;
-
-cleanup:
- SdbFreeFileAttributes(attribs);
- if (hsdb->auto_loaded) SdbReleaseDatabase(hsdb);
+ /* Restore the full path. */
+ *(--file_name) = L'\\';
+
+ dwSize = sizeof(wszLayers);
+ if (SdbGetPermLayerKeys(DosApplicationName.String.Buffer, wszLayers, &dwSize,
GPLK_MACHINE | GPLK_USER))
+ {
+ SdbpAddLayerMatches(hsdb, wszLayers, dwSize, result);
+ ret = TRUE;
+ }
+
+ if (!(flags & SDBGMEF_IGNORE_ENVIRONMENT))
+ {
+ if (SdbpPropagateEnvLayers(hsdb, (LPWSTR)env, result))
+ {
+ ret = TRUE;
+ result->dwFlags |= SHIMREG_HAS_ENVIRONMENT;
+ }
+ }
+
+Cleanup:
+ RtlFreeBuffer(&DosApplicationName.ByteBuffer);
+ if (attribs)
+ SdbFreeFileAttributes(attribs);
+ if (hsdb->auto_loaded)
+ SdbReleaseDatabase(hsdb);
return ret;
}