[APPHELP] Implement SdbpMatchExe, allowing to match applications / files based on properties. CORE-13284

svn path=/trunk/; revision=75238
This commit is contained in:
Mark Jansen 2017-06-29 17:32:03 +00:00
parent 2fc232f21e
commit af96013370
3 changed files with 132 additions and 22 deletions

View file

@ -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);
@ -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 */

View file

@ -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 matching_file;
TAGID child;
/* 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 (child = SdbGetFirstChild(pdb, matching_file);
child != TAGID_NULL; child = SdbGetNextChild(pdb, matching_file, child))
{
TAGID tagName = SdbFindFirstTag(db, matching_file, TAG_NAME);
LPWSTR name = SdbGetStringTagPtr(db, tagName);
TAG tag = SdbGetTagFromTagID(pdb, child);
DWORD n;
if (!wcscmp(name, L"*"))
/* 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)
{
// if attributes dont match main file, return FALSE!
SHIM_WARN("Unimplemented TAG_UPTO_XXXXX\n");
continue;
}
snprintfW(buffer, _countof(buffer), fmt, dir, name);
if (!SdbpFileExists(buffer))
return FALSE;
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));
for (matching_file = SdbFindFirstTag(pdb, exe, TAG_MATCHING_FILE);
matching_file != TAGID_NULL; matching_file = SdbFindNextTag(pdb, exe, matching_file))
{
TAGID tagName = SdbFindFirstTag(pdb, matching_file, TAG_NAME);
UNICODE_STRING Name;
USHORT Len;
RtlInitUnicodeString(&Name, SdbGetStringTagPtr(pdb, tagName));
if (!Name.Buffer)
goto Cleanup;
if (!wcscmp(Name.Buffer, L"*"))
{
if (!SdbpMatchFileAttributes(pdb, matching_file, main_attribs, main_attr_count))
goto Cleanup;
continue;
}
/* 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)
@ -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;
@ -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)
@ -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);

View file

@ -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)