Geoff Chappell, Software Analyst
The APPHELP functions SdbGrabMatchingInfo and SdbGrabMatchingInfoEx functions collect into an XML file various sorts of information about files that seem related to a given executable. The intended use seems to be that the executable needs a patch, shim or similar support in particular circumstances and the collected descriptions of the related files, or some extract from them, can help those circumstances be recognised later (and elsewhere) by the presence of matching files. The XML output is suitable for use as input for creating, or editing, an SDB file that describes patches, shims, etc.
Both functions have an argument that Microsoft names dwFilter (inferred from text that APPHELP can write to log files). The low 16 bits define what type of files to look for and what information to collect. The high 16 bits are bit flags that more generally vary the operation of the functions.
The supported values for the low 16 bits of the dwFilter argument are:
|Numeric Value||Symbolic Name||Search Path||Matching Files|
|0||GRABMI_FILTER_NORMAL||path from szExe;
|any number of files with certain extensions (see below);
up to 10 others per directory
|1||GRABMI_FILTER_PRIVACY||path from szExe;
|any number of files with certain extensions (see below)|
|2||GRABMI_FILTER_DRIVERS||path from szExe;
|any number of files with .sys extension;
up to 10 others per directory
|3||GRABMI_FILTER_VERBOSE||path from szExe;
|4||GRABMI_FILTER_SYSTEM||Windows system directory;
|pre-set list of system DLLs (see below)|
|5||GRABMI_FILTER_THISFILEONLY||path from szExe;
|file from szExe|
Here, szExe is an invented name for the first argument of both functions. The symbolic names that Microsoft’s programmers use for the numeric values can be known with confidence from the XML files that these functions produce as their output (and, in one case, from text that APPHELP can write to a log file). Whether Microsoft defines these names as macros or as members of a formal enumeration is not known.
Some types of filter do not permit recursion into subdirectories. Where recursion is permitted, it is limited to three levels and is defeated by the 0x80000000 flag.
The GRABMI_FILTER_NORMAL and GRABMI_FILTER_PRIVACY filters are concerned primarily to find files whose names have particular extensions:
The difference between these two filters is that the Normal filter reports on at least some files with other extensions but the Privacy filter does not. Even the Normal filter ignores files with other extensions once it has found too many. This limit is hard-coded as 10 in all known versions but is re-applied for each subdirectory that is searched.
The GRABMI_FILTER_DRIVER filter is similar to GRABMI_FILTER_NORMAL in the sense of finding files whose names have a particular extension but of reporting other files until there are too many. It differs in two notable respects. First, the descriptions of each file are put in SYS tags, not MATCHING_FILE. Second, the descriptions are limited to just four attributes:
It is not known why these are the only attributes that are thought relevant or what is meant by the SYS tag.
The GRABMI_FILTER_SYSTEM reports only the following DLLs from the Windows system directory:
It is not known why advapi32.dll appears twice in APPHELP’s list. The second is redundant. It is not as if each file is sought in turn: the search is of all files in the directory, checking each for appearance in the list.
Four flags are known to be defined in the high 16 bits of dwFilter:
|0x10000000||do not close DATABASE tag|
|0x20000000||append to output file;
assume XML header and open DATABASE tag
|0x40000000||limit to 25 matching files|
|0x80000000||do not examine subdirectories|
Microsoft’s names for these flags are not known.
The 0x10000000 and 0x20000000 bits allow that multiple calls to the function can build one XML file with one DATABASE tag that lists matching information for multiple executables. Of course, the XML will not be satisfactory without coordinating these multiple calls so that the output file gets only one XML header, one opening of a DATABASE tag and one closing. For the first call, set the 0x10000000 bit so that the function knows not to close the DATABASE tag. For subsequent calls except the last, set both bits, so that the function knows to append to the file’s open DATABASE tag, still without closing the DATABASE tag. For the last call, set the 0x20000000 bit but not the 0x10000000 bit. The DATABASE tag gets closed and the XML is complete.
The description given above for the 0x40000000 bit is correct if the limit is reached in the first directory that is searched. Otherwise, it is at best a summary and might better be regarded just as my thought on what Microsoft’s programmers may have intended. If the limit isn’t reached before the recursion into subdirectories, the recursion can continue and report one more matching file per subdirectory.