Skip to content

Commit

Permalink
[APPHELP] Implement SdbpMatchExe, allowing to match applications / fi…
Browse files Browse the repository at this point in the history
…les based on properties. CORE-13284

svn path=/trunk/; revision=75238
  • Loading branch information
learn-more committed Jun 29, 2017
1 parent 2fc232f commit af96013
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 21 deletions.
5 changes: 5 additions & 0 deletions reactos/dll/appcompat/apphelp/apphelp.h
Expand Up @@ -90,6 +90,7 @@ PWSTR SdbpStrDup(LPCWSTR string);
HSDB WINAPI SdbInitDatabase(DWORD, LPCWSTR);
void WINAPI SdbReleaseDatabase(HSDB);
BOOL WINAPI SdbGUIDToString(CONST GUID *Guid, PWSTR GuidString, SIZE_T Length);
LPCWSTR WINAPI SdbTagToString(TAG tag);

PDB WINAPI SdbOpenDatabase(LPCWSTR path, PATH_TYPE type);
void WINAPI SdbCloseDatabase(PDB);
Expand All @@ -105,8 +106,12 @@ 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);
QWORD WINAPI SdbReadQWORDTag(PDB db, TAGID tagid, QWORD ret);
TAGID WINAPI SdbGetFirstChild(PDB db, TAGID parent);
TAGID WINAPI SdbGetNextChild(PDB db, TAGID parent, TAGID prev_child);

/* sdbfileattr.c*/
BOOL WINAPI SdbGetFileAttributes(LPCWSTR path, PATTRINFO *attr_info_ret, LPDWORD attr_count);
BOOL WINAPI SdbFreeFileAttributes(PATTRINFO attr_info);

/* layer.c */
Expand Down
145 changes: 125 additions & 20 deletions reactos/dll/appcompat/apphelp/hsdb.c
Expand Up @@ -49,31 +49,132 @@ static BOOL WINAPI SdbpFileExists(LPCWSTR path)
return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY));
}

static BOOL WINAPI SdbpMatchExe(PDB db, TAGID exe, WCHAR* dir)
static BOOL SdbpMatchFileAttributes(PDB pdb, TAGID matching_file, PATTRINFO attribs, DWORD attr_count)
{
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 child;

for (child = SdbGetFirstChild(pdb, matching_file);
child != TAGID_NULL; child = SdbGetNextChild(pdb, matching_file, child))
{
TAG tag = SdbGetTagFromTagID(pdb, child);
DWORD n;

/* Already handled! */
if (tag == TAG_NAME)
continue;

if (tag == TAG_UPTO_BIN_FILE_VERSION ||
tag == TAG_UPTO_BIN_PRODUCT_VERSION ||
tag == TAG_UPTO_LINK_DATE)
{
SHIM_WARN("Unimplemented TAG_UPTO_XXXXX\n");
continue;
}

for (n = 0; n < attr_count; ++n)
{
PATTRINFO attr = attribs + n;
if (attr->flags == ATTRIBUTE_AVAILABLE && attr->type == tag)
{
DWORD dwval;
WCHAR* lpval;
QWORD qwval;
switch (tag & TAG_TYPE_MASK)
{
case TAG_TYPE_DWORD:
dwval = SdbReadDWORDTag(pdb, child, 0);
if (dwval != attr->dwattr)
return FALSE;
break;
case TAG_TYPE_STRINGREF:
lpval = SdbGetStringTagPtr(pdb, child);
if (!lpval || wcsicmp(attr->lpattr, lpval))
return FALSE;
break;
case TAG_TYPE_QWORD:
qwval = SdbReadQWORDTag(pdb, child, 0);
if (qwval != attr->qwattr)
return FALSE;
break;
default:
SHIM_WARN("Unhandled type 0x%x MATCHING_FILE\n", (tag & TAG_TYPE_MASK));
return FALSE;
}
}
}
if (n == attr_count)
SHIM_WARN("Unhandled tag %ws in MACHING_FILE\n", SdbTagToString(tag));
}
return TRUE;
}

static BOOL WINAPI SdbpMatchExe(PDB pdb, TAGID exe, const WCHAR* dir, PATTRINFO main_attribs, DWORD main_attr_count)
{
RTL_UNICODE_STRING_BUFFER FullPathName = { { 0 } };
WCHAR FullPathBuffer[MAX_PATH];
UNICODE_STRING UnicodeDir;
TAGID matching_file;
PATTRINFO attribs = NULL;
DWORD attr_count;
BOOL IsMatch = FALSE;

RtlInitUnicodeString(&UnicodeDir, dir);
RtlInitBuffer(&FullPathName.ByteBuffer, (PUCHAR)FullPathBuffer, sizeof(FullPathBuffer));

/* 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))
for (matching_file = SdbFindFirstTag(pdb, exe, TAG_MATCHING_FILE);
matching_file != TAGID_NULL; matching_file = SdbFindNextTag(pdb, exe, matching_file))
{
TAGID tagName = SdbFindFirstTag(db, matching_file, TAG_NAME);
LPWSTR name = SdbGetStringTagPtr(db, tagName);
TAGID tagName = SdbFindFirstTag(pdb, matching_file, TAG_NAME);
UNICODE_STRING Name;
USHORT Len;

if (!wcscmp(name, L"*"))
RtlInitUnicodeString(&Name, SdbGetStringTagPtr(pdb, tagName));

if (!Name.Buffer)
goto Cleanup;

if (!wcscmp(Name.Buffer, L"*"))
{
// if attributes dont match main file, return FALSE!
if (!SdbpMatchFileAttributes(pdb, matching_file, main_attribs, main_attr_count))
goto Cleanup;
continue;
}

snprintfW(buffer, _countof(buffer), fmt, dir, name);
if (!SdbpFileExists(buffer))
return FALSE;
/* Technically, one UNICODE_NULL and one path separator. */
Len = UnicodeDir.Length + Name.Length + sizeof(UNICODE_NULL) + sizeof(UNICODE_NULL);
if (!NT_SUCCESS(RtlEnsureBufferSize(RTL_SKIP_BUFFER_COPY, &FullPathName.ByteBuffer, Len)))
goto Cleanup;

if (Len > FullPathName.ByteBuffer.Size)
goto Cleanup;

RtlInitEmptyUnicodeString(&FullPathName.String, (PWCHAR)FullPathName.ByteBuffer.Buffer, FullPathName.ByteBuffer.Size);

RtlCopyUnicodeString(&FullPathName.String, &UnicodeDir);
RtlAppendUnicodeToString(&FullPathName.String, L"\\");
RtlAppendUnicodeStringToString(&FullPathName.String, &Name);

if (!SdbpFileExists(FullPathName.String.Buffer))
goto Cleanup;

if (attribs)
SdbFreeFileAttributes(attribs);

if (!SdbGetFileAttributes(FullPathName.String.Buffer, &attribs, &attr_count))
goto Cleanup;

if (!SdbpMatchFileAttributes(pdb, matching_file, attribs, attr_count))
goto Cleanup;
}

return TRUE;
IsMatch = TRUE;

Cleanup:
RtlFreeBuffer(&FullPathName.ByteBuffer);
if (attribs)
SdbFreeFileAttributes(attribs);

return IsMatch;
}

static void SdbpAddDatabaseGuid(PDB db, PSDBQUERYRESULT result)
Expand Down Expand Up @@ -331,7 +432,7 @@ BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name,
BOOL ret = FALSE;
TAGID database, iter, name;
PATTRINFO attribs = NULL;
/*DWORD attr_count;*/
DWORD attr_count;
RTL_UNICODE_STRING_BUFFER DosApplicationName = { { 0 } };
WCHAR DosPathBuffer[MAX_PATH];
ULONG PathType = 0;
Expand Down Expand Up @@ -390,10 +491,6 @@ BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name,
/* 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))
return FALSE;*/

/* DATABASE is list TAG which contains all executables */
database = SdbFindFirstTag(db, TAGID_ROOT, TAG_DATABASE);
if (database == TAGID_NULL)
Expand All @@ -414,8 +511,16 @@ BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name,
foundName = SdbGetStringTagPtr(db, name);
if (foundName && !lstrcmpiW(foundName, file_name))
{
/* Get information about executable required to match it with database entry */
if (!attribs)
{
if (!SdbGetFileAttributes(path, &attribs, &attr_count))
goto Cleanup;
}


/* We have a null terminator before the application name, so DosApplicationName only contains the path. */
if (SdbpMatchExe(db, iter, DosApplicationName.String.Buffer))
if (SdbpMatchExe(db, iter, DosApplicationName.String.Buffer, attribs, attr_count))
{
ret = TRUE;
SdbpAddExeMatch(hsdb, db, iter, result);
Expand Down
2 changes: 1 addition & 1 deletion reactos/dll/appcompat/apphelp/sdbfileattr.c
Expand Up @@ -86,7 +86,7 @@ static WCHAR* WINAPI SdbpGetStringAttr(LPWSTR translation, LPCWSTR attr, PVOID f
return NULL;
}

static void WINAPI SdbpSetStringAttrFromAnsiString(PATTRINFO attr, TAG tag, PBYTE string, BYTE len)
static void WINAPI SdbpSetStringAttrFromAnsiString(PATTRINFO attr, TAG tag, PBYTE string, size_t len)
{
WCHAR* dest;
if (!string)
Expand Down

0 comments on commit af96013

Please sign in to comment.