Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1824 lines
38 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
dbattrib.c
Abstract:
This source implements attribute functions used by MigDb
Author:
Calin Negreanu (calinn) 07-Jan-1998
Revision History:
28-May-1999 ovidiut Added SECTIONKEY attribute
22-Apr-1999 jimschm Added UPTOBIN*VER attributes
07-Jan-1999 jimschm Added HASVERSION attribute
18-May-1998 jimschm Added INPARENTDIR attribute
08-Apr-1998 calinn Added two more attributes (ExeType and Description)
29-Jan-1998 calinn Modified CheckSum and FileSize to work with hex numbers
19-Jan-1998 calinn added CheckSum attribute
--*/
#include "pch.h"
#include "migdbp.h"
/*++
Macro Expansion List Description:
ATTRIBUTE_FUNCTIONS lists all valid attributes to query for a specific file.
They are used by migdb in it's attempt to locate files.
Line Syntax:
DEFMAC(AttribFn, AttribName, ReqArgs)
Arguments:
AttribFn - This is a boolean function that returnes TRUE if a specified file has
the specified attribute. You must implement a function with this name
and required parameters.
AttribName - This is the string that identifies the attribute function. It should
have the same value as listed in migdb.inf
ReqArgs - Specifies the number of args that are required for the action. Used
by the parser.
Variables Generated From List:
g_AttributeFunctions - do not touch!
For accessing the array there are the following functions:
MigDb_GetAttributeAddr
MigDb_GetAttributeIdx
MigDb_GetAttributeName
MigDb_GetReqArgCount
--*/
#define ATTRIBUTE_FUNCTIONS \
DEFMAC(CompanyName, COMPANYNAME, 1) \
DEFMAC(FileDescription, FILEDESCRIPTION, 1) \
DEFMAC(FileVersion, FILEVERSION, 1) \
DEFMAC(InternalName, INTERNALNAME, 1) \
DEFMAC(LegalCopyright, LEGALCOPYRIGHT, 1) \
DEFMAC(OriginalFilename, ORIGINALFILENAME, 1) \
DEFMAC(ProductName, PRODUCTNAME, 1) \
DEFMAC(ProductVersion, PRODUCTVERSION, 1) \
DEFMAC(FileSize, FILESIZE, 1) \
DEFMAC(IsMsBinary, ISMSBINARY, 0) \
DEFMAC(IsWin9xBinary, ISWIN9XBINARY, 0) \
DEFMAC(InWinDir, INWINDIR, 0) \
DEFMAC(InCatDir, INCATDIR, 0) \
DEFMAC(InHlpDir, INHLPDIR, 0) \
DEFMAC(InSysDir, INSYSDIR, 0) \
DEFMAC(InProgramFiles, INPROGRAMFILES, 0) \
DEFMAC(IsNotSysRoot, ISNOTSYSROOT, 0) \
DEFMAC(CheckSum, CHECKSUM, 1) \
DEFMAC(ExeType, EXETYPE, 1) \
DEFMAC(Description, DESCRIPTION, 1) \
DEFMAC(InParentDir, INPARENTDIR, 1) \
DEFMAC(InRootDir, INROOTDIR, 0) \
DEFMAC(PnpIdAttrib, PNPID, 1) \
DEFMAC(HlpTitle, HLPTITLE, 1) \
DEFMAC(IsWin98, ISWIN98, 0) \
DEFMAC(HasVersion, HASVERSION, 0) \
DEFMAC(ReqFile, REQFILE, 1) \
DEFMAC(BinFileVer, BINFILEVER, 1) \
DEFMAC(BinProductVer, BINPRODUCTVER, 1) \
DEFMAC(FileDateHi, FILEDATEHI, 1) \
DEFMAC(FileDateLo, FILEDATELO, 1) \
DEFMAC(FileVerOs, FILEVEROS, 1) \
DEFMAC(FileVerType, FILEVERTYPE, 1) \
DEFMAC(SizeCheckSum, FC, 2) \
DEFMAC(UpToBinProductVer, UPTOBINPRODUCTVER, 1) \
DEFMAC(UpToBinFileVer, UPTOBINFILEVER, 1) \
DEFMAC(SectionKey, SECTIONKEY, 1) \
DEFMAC(RegKeyPresent, REGKEYPRESENT, 1) \
DEFMAC(AtLeastWin98, ATLEASTWIN98, 0) \
DEFMAC(HasUninstall, HASUNINSTALL, 1) \
DEFMAC(IsItInstalled, ISITINSTALLED, 1) \
typedef struct {
PCSTR AttributeName;
PATTRIBUTE_PROTOTYPE AttributeFunction;
UINT RequiredArgs;
} ATTRIBUTE_STRUCT, *PATTRIBUTE_STRUCT;
//
// Declare the attribute functions
//
#define DEFMAC(fn,id,reqargs) ATTRIBUTE_PROTOTYPE fn;
ATTRIBUTE_FUNCTIONS
#undef DEFMAC
//
// Declare a global array of functions and name identifiers for attribute functions
//
#define DEFMAC(fn,id,regargs) {#id, fn, regargs},
static ATTRIBUTE_STRUCT g_AttributeFunctions[] = {
ATTRIBUTE_FUNCTIONS
{NULL, NULL}
};
#undef DEFMAC
//
// if this is TRUE, all attributes that check directories (InWinDir, InHlpDir, InCatDir, InSysDir)
// will return TRUE, otherwise will actually do the appropriate tests.
//
BOOL g_InAnyDir = FALSE;
BOOL
pAlwaysFalseAttribute (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return FALSE;
}
PATTRIBUTE_PROTOTYPE
MigDb_GetAttributeAddr (
IN INT AttributeIdx
)
/*++
Routine Description:
MigDb_GetAttributeAddr returns the address of the attribute function based on the attribute index
Arguments:
AttributeIdx - Attribute index.
Return value:
Attribute function address. Note that no checking is made so the address returned could be invalid.
This is not a problem since the parsing code did the right job.
--*/
{
if (AttributeIdx == -1) {
return &pAlwaysFalseAttribute;
}
return g_AttributeFunctions[AttributeIdx].AttributeFunction;
}
INT
MigDb_GetAttributeIdx (
IN PCSTR AttributeName
)
/*++
Routine Description:
MigDb_GetAttributeIdx returns the attribute index based on the attribute name
Arguments:
AttributeName - Attribute name.
Return value:
Attribute index. If the name is not found, the index returned is -1.
--*/
{
PATTRIBUTE_STRUCT p = g_AttributeFunctions;
INT i = 0;
while (p->AttributeName != NULL) {
if (StringIMatch (p->AttributeName, AttributeName)) {
return i;
}
p++;
i++;
}
return -1;
}
PCSTR
MigDb_GetAttributeName (
IN INT AttributeIdx
)
/*++
Routine Description:
MigDb_GetAttributeName returns the name of an attribute based on the attribute index
Arguments:
AttributeIdx - Attribute index.
Return value:
Attribute name. Note that no checking is made so the returned pointer could be invalid.
This is not a problem since the parsing code did the right job.
--*/
{
if (AttributeIdx == -1) {
return "nul";
}
return g_AttributeFunctions[AttributeIdx].AttributeName;
}
UINT
MigDb_GetReqArgCount (
IN INT AttributeIndex
)
/*++
Routine Description:
MigDb_GetReqArgCount is called by the migdb parser to get the required
argument count. When the parser sees arguments that lack the required
arguments, it skips them.
Arguments:
Index - Specifies the argument index
Return Value:
The required argument count, which can be zero or more.
--*/
{
if (AttributeIndex == -1) {
return 0;
}
return g_AttributeFunctions[AttributeIndex].RequiredArgs;
}
ULONGLONG
GetBinFileVer (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
ULONGLONG result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetFileVer (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
ULONGLONG
GetBinProductVer (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
ULONGLONG result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetProductVer (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
DWORD
GetFileDateHi (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
DWORD result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetFileDateHi (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
DWORD
GetFileDateLo (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
DWORD result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetFileDateLo (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
DWORD
GetFileVerOs (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
DWORD result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetFileVerOs (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
DWORD
GetFileVerType (
IN PCSTR FileName
)
{
VERSION_STRUCT Version;
DWORD result = 0;
if (CreateVersionStruct (&Version, FileName)) {
result = VerGetFileVerType (&Version);
DestroyVersionStruct (&Version);
}
return result;
}
PSTR
QueryVersionEntry (
IN PCSTR FileName,
IN PCSTR VersionEntry
)
/*++
Routine Description:
QueryVersionEntry queries the file's version structure returning the
value for a specific entry
Arguments:
FileName - File to query for version struct.
VersionEntry - Name to query in version structure.
Return value:
Value of specified entry or NULL if unsuccessful
--*/
{
VERSION_STRUCT Version;
PCSTR CurrentStr;
PSTR result = NULL;
MYASSERT (VersionEntry);
if (CreateVersionStruct (&Version, FileName)) {
__try {
CurrentStr = EnumFirstVersionValue (&Version, VersionEntry);
if (CurrentStr) {
CurrentStr = SkipSpace (CurrentStr);
result = DuplicatePathString (CurrentStr, 0);
}
else {
__leave;
}
}
__finally {
DestroyVersionStruct (&Version);
}
}
return result;
}
BOOL
GlobalVersionCheck (
IN PCSTR FileName,
IN PCSTR NameToCheck,
IN PCSTR ValueToCheck
)
/*++
Routine Description:
GlobalVersionCheck queries the file's version structure trying to
see if a specific name has a specific value.
Arguments:
FileName - File to query for version struct.
NameToCheck - Name to query in version structure.
ValueToCheck - Value to query in version structure.
Return value:
TRUE - the query was successful
FALSE - the query failed
--*/
{
VERSION_STRUCT Version;
PCSTR CurrentStr;
BOOL result = FALSE;
MYASSERT (NameToCheck);
MYASSERT (ValueToCheck);
if (CreateVersionStruct (&Version, FileName)) {
__try {
CurrentStr = EnumFirstVersionValue (&Version, NameToCheck);
while (CurrentStr) {
CurrentStr = SkipSpace (CurrentStr);
TruncateTrailingSpace ((PSTR) CurrentStr);
if (IsPatternMatchA (ValueToCheck, CurrentStr)) {
result = TRUE;
__leave;
}
CurrentStr = EnumNextVersionValue (&Version);
}
}
__finally {
DestroyVersionStruct (&Version);
}
}
return result;
}
/*++
CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, OriginalFilename,
ProductName, ProductVersion are attribute functions that are querying the version structure
for their specific entries. They all return TRUE if the specific entry has specific value,
FALSE otherwise.
--*/
BOOL
CompanyName (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "CompanyName", Args);
}
BOOL
FileDescription (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "FileDescription", Args);
}
BOOL
FileVersion (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "FileVersion", Args);
}
BOOL
InternalName (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "InternalName", Args);
}
BOOL
LegalCopyright (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "LegalCopyright", Args);
}
BOOL
OriginalFilename (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "OriginalFilename", Args);
}
BOOL
ProductName (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "ProductName", Args);
}
BOOL
ProductVersion (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return GlobalVersionCheck (AttribParams->FileParams->FullFileSpec, "ProductVersion", Args);
}
BOOL
FileSize (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
FileSize checks for the size of a file.
Arguments:
Params - See definition.
Args - MultiSz. First Sz is the file size we need to check.
Return value:
TRUE - the file size matches Args
FALSE - otherwise
--*/
{
DWORD fileSize;
if (!sscanf (Args, "%lx", &fileSize)) {
DEBUGMSG ((DBG_ERROR, "FileSize: Invalid argument value (%s) in migdb.inf", Args));
return FALSE;
}
if (fileSize == AttribParams->FileParams->FindData->nFileSizeLow) {
return TRUE;
}
else {
return (_atoi64 (Args) == AttribParams->FileParams->FindData->nFileSizeLow);
}
}
BOOL
IsMsBinary (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
IsMsBinary checks to see if a certain file is Microsoft stuff. For 32 bit modules
we query CompanyName for "Microsoft" somewhere inside. For other modules we are
relying on InWinDir attribute
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is MS stuff
FALSE - otherwise
--*/
{
VERSION_STRUCT Version;
PCTSTR CompanyStr;
BOOL result = FALSE;
//
// InWinDir has some collision risks. But for some files, we have no other
// choice. We know the file was shipped by Microsoft.
//
if (InWinDir (AttribParams, Args)) {
result = TRUE;
}
//
// If it's not in %WinDir%, then it has to have Microsoft in the company name
//
else if (CreateVersionStruct (
&Version,
AttribParams->FileParams->FullFileSpec
)) {
__try {
CompanyStr = EnumFirstVersionValue (&Version, TEXT("CompanyName"));
while (CompanyStr) {
if (_mbsistr (CompanyStr, TEXT("Microsoft"))) {
result = TRUE;
__leave;
}
CompanyStr = EnumNextVersionValue (&Version);
}
}
__finally {
DestroyVersionStruct (&Version);
}
}
return result;
}
BOOL
IsWin9xBinary (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
IsWon9xBinary checks to see if a certain file is Microsoft Win9x stuff. It works only for
16 and 32 bit modules with version stamp. The COMPANYNAME is checked against *Microsoft* and
the PRODUCTVERSION is checked against 4.*
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is MS stuff
FALSE - otherwise
--*/
{
VERSION_STRUCT Version;
PCTSTR CurrentStr;
BOOL result;
if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
result = FALSE;
CurrentStr = EnumFirstVersionValue (&Version, TEXT("CompanyName"));
while (CurrentStr) {
CurrentStr = SkipSpace (CurrentStr);
TruncateTrailingSpace ((PSTR) CurrentStr);
if (IsPatternMatchA (TEXT("*Microsoft*"), CurrentStr)) {
result = TRUE;
break;
}
CurrentStr = EnumNextVersionValue (&Version);
}
if (result) {
result = FALSE;
CurrentStr = EnumFirstVersionValue (&Version, TEXT("ProductVersion"));
while (CurrentStr) {
CurrentStr = SkipSpace (CurrentStr);
TruncateTrailingSpace ((PSTR) CurrentStr);
if (IsPatternMatchA (TEXT("4.*"), CurrentStr)) {
result = TRUE;
break;
}
CurrentStr = EnumNextVersionValue (&Version);
}
}
DestroyVersionStruct (&Version);
}
else {
result = FALSE;
}
return result;
}
BOOL
InWinDir (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InWinDir returns TRUE if file is located in %Windir% or one of it's subdirectories
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is located in %Windir%
FALSE - otherwise
--*/
{
if (g_InAnyDir) {
return TRUE;
}
return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_WinDirWack, g_WinDirWackChars));
}
BOOL
InCatDir (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InCatDir returns TRUE if file is located in %Windir%\CATROOT or one of it's subdirectories
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is located in %Windir%
FALSE - otherwise
--*/
{
if (g_InAnyDir) {
return TRUE;
}
return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_CatRootDirWack, g_CatRootDirWackChars));
}
BOOL
InHlpDir (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InHlpDir returns TRUE if file is located in %Windir%\HELP or one of it's subdirectories
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is located in %Windir%
FALSE - otherwise
--*/
{
if (g_InAnyDir) {
return TRUE;
}
return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_HelpDirWack, g_HelpDirWackChars));
}
BOOL
InSysDir (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InSysDir returns TRUE if file is located in %Windir%\SYSTEM or one of it's subdirectories
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is located in %Windir%
FALSE - otherwise
--*/
{
if (g_InAnyDir) {
return TRUE;
}
return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_SystemDirWack, g_SystemDirWackChars));
}
BOOL
InProgramFiles (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InProgramFiles returns TRUE if file is located in Program Files or one of it's subdirectories
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is located in Program Files
FALSE - otherwise
--*/
{
if (g_InAnyDir) {
return TRUE;
}
return (StringIMatchCharCount (AttribParams->FileParams->FullFileSpec, g_ProgramFilesDirWack, g_ProgramFilesDirWackChars));
}
BOOL
IsNotSysRoot (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
IsNotSysRoot returns TRUE if file is not located in C:\ directory
Arguments:
Params - See definition.
Args - MultiSz. Not used.
Return value:
TRUE - the file is not located in C:\ directory
FALSE - otherwise
--*/
{
PSTR pathEnd;
CHAR savedChar;
BOOL result = FALSE;
pathEnd = (PSTR)GetFileNameFromPath (AttribParams->FileParams->FullFileSpec);
if (pathEnd == NULL) {
return TRUE;
}
savedChar = pathEnd [0];
__try {
pathEnd [0] = 0;
result = (!StringIMatch (AttribParams->FileParams->FullFileSpec, g_BootDrivePath));
}
__finally {
pathEnd [0] = savedChar;
}
return result;
}
UINT
ComputeCheckSum (
PFILE_HELPER_PARAMS Params
)
/*++
Routine Description:
ComputeCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
the chunk are modified if the file size is too small.
Arguments:
Params - See definition.
Return value:
The computed checksum
--*/
{
INT i,size = 4096;
DWORD startAddr = 512;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCHAR buffer = NULL;
UINT checkSum = 0;
DWORD dontCare;
if (Params->FindData->nFileSizeLow < (ULONG)size) {
//
// File size is less than 4096. We set the start address to 0 and set the size for the checksum
// to the actual file size.
//
startAddr = 0;
size = Params->FindData->nFileSizeLow;
}
else
if (startAddr + size > Params->FindData->nFileSizeLow) {
//
// File size is too small. We set the start address so that size of checksum can be 4096 bytes
//
startAddr = Params->FindData->nFileSizeLow - size;
}
if (size <= 3) {
//
// we need at least 3 bytes to be able to do something here.
//
return 0;
}
__try {
buffer = MemAlloc (g_hHeap, 0, size);
if (buffer == NULL) {
__leave;
}
fileHandle = CreateFile (Params->FullFileSpec, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
__leave;
}
if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
__leave;
}
if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
__leave;
}
for (i = 0; i<(size - 3); i+=4) {
checkSum += *((PDWORD) (buffer + i));
checkSum = _rotr (checkSum ,1);
}
}
__finally {
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
if (buffer != NULL) {
MemFree (g_hHeap, 0, buffer);
}
}
return checkSum;
}
BOOL
CheckSum (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
CheckSum returns TRUE if file's checksum equals the value in Args
Arguments:
Params - See definition.
Args - checksum value.
Return value:
TRUE - the file's checksum equals the value in Args
FALSE - otherwise
--*/
{
UINT checkSum = 0;
UINT oldSum = 0;
checkSum = ComputeCheckSum (AttribParams->FileParams);
if (!sscanf (Args, "%lx", &oldSum)) {
DEBUGMSG ((DBG_ERROR, "Invalid checksum value (%s) in migdb.inf", Args));
return FALSE;
}
if (oldSum == checkSum) {
return TRUE;
}
else {
return (_atoi64 (Args) == checkSum);
}
}
BOOL
SizeCheckSum (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
Returns TRUE if file's size equals first arg and checksum equals to the second arg
Arguments:
Params - See definition.
Args - checksum value.
Return value:
TRUE - the file's checksum equals the value in Args
FALSE - otherwise
--*/
{
PCSTR currArg = Args;
if (!FileSize (AttribParams, currArg)) {
return FALSE;
}
currArg = GetEndOfString (currArg);
if (!currArg) {
return FALSE;
}
currArg = _mbsinc (currArg);
if (!currArg) {
return FALSE;
}
return (CheckSum (AttribParams, currArg));
}
PSTR g_ExeTypes[] = {
"NONE",
"DOS",
"WIN16",
"WIN32"
};
BOOL
ExeType (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
ExeType returns TRUE if file's type is according with Args. This can be:
NONE, DOS, WIN16, WIN32
Arguments:
Params - See definition.
Args - type of module.
Return value:
TRUE - the file's type is the same as Args
FALSE - otherwise
--*/
{
return IsPatternMatch (Args, g_ExeTypes[GetModuleType (AttribParams->FileParams->FullFileSpec)]);
}
BOOL
Description (
PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
Description returns TRUE if file's description matches Args
Arguments:
Params - See definition.
Args - description
Return value:
TRUE - the file's description matches Args
FALSE - otherwise
--*/
{
PCSTR descr = NULL;
BOOL result = FALSE;
descr = Get16ModuleDescription (AttribParams->FileParams->FullFileSpec);
if (descr != NULL) {
result = IsPatternMatch (Args, descr);
FreePathString (descr);
}
return result;
}
BOOL
InParentDir (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InParentDir compares the sub directory of the matching file against the arg
specified. This is used for apps that maintain static subdirs off their
main app dir.
Arguments:
Params - Specifies parameters for current file being processed.
Args - Specifies multi-sz of args passed in migdb.inf.
Return Value:
TRUE - the file's subdirectory matches Args
FALSE - otherwise
--*/
{
PCTSTR stop = NULL;
PCTSTR start = NULL;
TCHAR lastDir[MAX_TCHAR_PATH];
// _tcsrchr validates the multibyte characters
stop = _tcsrchr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
if (stop) {
//
// Go back to previous wack
//
start = _tcsdec2 (AttribParams->FileParams->FullFileSpec, stop);
if (start) {
start = GetPrevChar (AttribParams->FileParams->FullFileSpec, start, TEXT('\\'));
}
}
if (start) {
//
// Check string against arg
//
start = _tcsinc (start);
_tcssafecpyab (lastDir, start, stop, MAX_TCHAR_PATH);
if (Args) {
return (IsPatternMatch (Args, lastDir));
} else {
DEBUGMSG ((DBG_WHOOPS, "InParentDir requires arg"));
}
}
return FALSE;
}
BOOL
InRootDir (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
InRootDir returns TRUE is the file is located in root dir of the drive, FALSE otherwise.
Arguments:
Params - Specifies parameters for current file being processed.
Args - Specifies multi-sz of args passed in migdb.inf.
Return Value:
TRUE - the file is in root dir of the drive
FALSE - otherwise
--*/
{
PCTSTR p1,p2;
p1 = _tcschr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
p2 = _tcsrchr (AttribParams->FileParams->FullFileSpec, TEXT('\\'));
if (p1 && p2) {
return (p1==p2);
}
return FALSE;
}
BOOL
PnpIdAttrib (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
PnpIdAttrib implements the PNPID() attribute, which is TRUE if the
specified ID exists on the machine. The ID can be a complete instance ID
(enumerator\PNPID\instance), or part of the ID (PNPID for example).
Arguments:
Params - Specifies parameters for current file being processed
Args - Specifies the PNP ID argument
Return Value:
TRUE if the specified argument exists on the machine, otherwise FALSE.
--*/
{
BOOL Result = FALSE;
MULTISZ_ENUM e;
TCHAR Node[MEMDB_MAX];
if (EnumFirstMultiSz (&e, Args)) {
Result = TRUE;
do {
MemDbBuildKey (Node, MEMDB_CATEGORY_PNPIDS, e.CurrentString, NULL, NULL);
if (!MemDbGetValue (Node, NULL)) {
Result = FALSE;
break;
}
} while (EnumNextMultiSz (&e));
}
return Result;
}
BOOL
HlpTitle (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
PSTR title = NULL;
BOOL result=FALSE;
title = GetHlpFileTitle (AttribParams->FileParams->FullFileSpec);
if (title) {
result = StringIMatch (title, Args);
}
if (title) {
FreePathString (title);
}
return result;
}
BOOL
IsWin98 (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return ISMEMPHIS();
}
BOOL
HasVersion (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
/*++
Routine Description:
HasVersion determines if a file has any entries in its version
stamp.
Arguments:
Params - Specifies the helper params that give the files to test.
Args - Unused
Return Value:
TRUE if the specified file has an entry in its version stamp,
FALSE otherwsie.
--*/
{
VERSION_STRUCT Version;
BOOL Result = FALSE;
if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
Result = TRUE;
DestroyVersionStruct (&Version);
}
return Result;
}
BOOL
ReqFile (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
static INT reqFileSeq = 0;
TCHAR reqFileSeqStr [20];
PMIGDB_REQ_FILE reqFile;
DBATTRIB_PARAMS reqFileAttribs;
PMIGDB_ATTRIB migDbAttrib;
FILE_HELPER_PARAMS newParams;
WIN32_FIND_DATA findData;
HANDLE findHandle;
PSTR oldFileSpec;
PSTR oldFilePtr;
BOOL result = TRUE;
if (!AttribParams->ExtraData) {
return TRUE;
}
reqFile = (PMIGDB_REQ_FILE)AttribParams->ExtraData;
while (reqFile) {
newParams.Handled = 0;
oldFileSpec = DuplicatePathString (AttribParams->FileParams->FullFileSpec, 0);
oldFilePtr = (PSTR)GetFileNameFromPath (oldFileSpec);
if (oldFilePtr) {
*oldFilePtr = 0;
}
newParams.FullFileSpec = JoinPaths (oldFileSpec, reqFile->ReqFilePath);
FreePathString (oldFileSpec);
newParams.Extension = GetFileExtensionFromPath (reqFile->ReqFilePath);
findHandle = FindFirstFile (newParams.FullFileSpec, &findData);
if (findHandle == INVALID_HANDLE_VALUE) {
result = FALSE;
break;
}
newParams.IsDirectory = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
newParams.FindData = &findData;
newParams.VirtualFile = FALSE;
newParams.CurrentDirData = AttribParams->FileParams->CurrentDirData;
reqFileAttribs.FileParams = &newParams;
reqFileAttribs.ExtraData = NULL;
migDbAttrib = reqFile->FileAttribs;
while (migDbAttrib) {
if (!CallAttribute (migDbAttrib, &reqFileAttribs)) {
result = FALSE;
break;
}
migDbAttrib = migDbAttrib->Next;
}
if (newParams.FullFileSpec) {
FreePathString (newParams.FullFileSpec);
newParams.FullFileSpec = NULL;
}
if (migDbAttrib == NULL) {
reqFileSeq ++;
_itoa (reqFileSeq, reqFileSeqStr, 10);
if (MemDbSetValueEx (
MEMDB_CATEGORY_REQFILES_MAIN,
AttribParams->FileParams->FullFileSpec,
reqFileSeqStr,
NULL,
0,
NULL
)) {
MemDbSetValueEx (
MEMDB_CATEGORY_REQFILES_ADDNL,
reqFileSeqStr,
reqFile->ReqFilePath,
NULL,
0,
NULL
);
}
}
reqFile = reqFile->Next;
}
if (newParams.FullFileSpec) {
FreePathString (newParams.FullFileSpec);
}
return result;
}
BOOL
pHexMatch (
IN DWORD NewValue,
IN PCSTR Args
)
{
DWORD oldValue;
if (!sscanf (Args, "%lx", &oldValue)) {
DEBUGMSG ((DBG_ERROR, "pHexMatch: Invalid argument value (%s) in migdb.inf", Args));
return FALSE;
}
if (oldValue == NewValue) {
return TRUE;
}
else {
return (_atoi64 (Args) == NewValue);
}
}
BOOL
pConvertDotStringToValue (
IN PCSTR String,
OUT ULONGLONG *Value
)
{
PWORD valueIdx;
UINT index;
valueIdx = (PWORD) Value + 3;
for (index = 0 ; index < 4 ; index++) {
if (*String == 0) {
*valueIdx = 0xFFFF;
valueIdx--;
continue;
}
*valueIdx = (WORD) strtoul (String, &(PSTR) String, 10);
if (*String && (_mbsnextc (String) != '.')) {
return FALSE;
}
String = _mbsinc (String);
valueIdx--;
}
return TRUE;
}
BOOL
pMaskHexMatch (
IN ULONGLONG NewValue,
IN PCSTR Args
)
{
ULONGLONG oldValue = 0;
ULONGLONG mask = 0;
PWORD maskIdx;
PWORD valueIdx;
UINT index;
maskIdx = (PWORD)&mask + 3;
valueIdx = (PWORD)&oldValue + 3;
index = 0;
while (Args && *Args) {
if (index >= 4) {
return FALSE;
}
*valueIdx = (WORD) strtoul ((PSTR)Args, &((PSTR)Args), 10);
if (*Args) {
if (_mbsnextc (Args) != '.') {
return FALSE;
}
Args = _mbsinc (Args);
}
*maskIdx = 65535;
valueIdx--;
maskIdx--;
index++;
}
NewValue = NewValue & mask;
return (oldValue == NewValue);
}
BOOL
BinFileVer (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pMaskHexMatch (GetBinFileVer (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
BinProductVer (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pMaskHexMatch (GetBinProductVer (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
FileDateHi (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pHexMatch (GetFileDateHi (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
FileDateLo (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pHexMatch (GetFileDateLo (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
FileVerOs (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pHexMatch (GetFileVerOs (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
FileVerType (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return pHexMatch (GetFileVerType (AttribParams->FileParams->FullFileSpec), Args);
}
BOOL
UpToBinProductVer (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
VERSION_STRUCT Version;
ULONGLONG versionStampValue = 0;
ULONGLONG maxValue;
if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
versionStampValue = VerGetProductVer (&Version);
DestroyVersionStruct (&Version);
} else {
return FALSE;
}
if (!pConvertDotStringToValue (Args, &maxValue)) {
DEBUGMSG ((DBG_WHOOPS, "Invalid value of %s caused UpToBinProductVer to fail", Args));
return FALSE;
}
return versionStampValue <= maxValue;
}
BOOL
UpToBinFileVer (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
VERSION_STRUCT Version;
ULONGLONG versionStampValue = 0;
ULONGLONG maxValue;
if (CreateVersionStruct (&Version, AttribParams->FileParams->FullFileSpec)) {
versionStampValue = VerGetFileVer (&Version);
DestroyVersionStruct (&Version);
} else {
return FALSE;
}
if (!pConvertDotStringToValue (Args, &maxValue)) {
DEBUGMSG ((DBG_WHOOPS, "Invalid value of %s caused UpToBinFileVer to fail", Args));
return FALSE;
}
return versionStampValue <= maxValue;
}
BOOL
SectionKey (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
PSTR Section, Key;
PSTR Value = NULL;
CHAR Return[1024];
DWORD Count;
BOOL b = FALSE;
Section = DuplicateText (Args);
MYASSERT (Section);
Key = _mbschr (Section, '\\');
if (Key) {
*Key = 0;
Key++;
Value = _mbschr (Key, '\\');
if (Value) {
*Value = 0;
Value++;
}
}
Count = GetPrivateProfileString (
Section,
Key,
"",
Return,
sizeof (Return),
AttribParams->FileParams->FullFileSpec
);
if (Count > 0) {
if (!Value || StringIMatch (Value, Return)) {
b = TRUE;
}
}
FreeText (Section);
return b;
}
BOOL
IsItInstalled (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
TCHAR RegKey[MAX_REGISTRY_KEY] = "HKLM\\SOFTWARE\\Microsoft\\";
StringCat(RegKey, Args);
return RegKeyPresent(AttribParams, RegKey);
}
BOOL
HasUninstall (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
TCHAR RegKey[MAX_REGISTRY_KEY] = "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
StringCat(RegKey, Args);
StringCat(RegKey, TEXT("\\[UninstallString]"));
return RegKeyPresent(AttribParams, RegKey);
}
BOOL
RegKeyPresent (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
BOOL b = FALSE;
CHAR RegKey[MAX_REGISTRY_KEY];
CHAR RegValue[MAX_REGISTRY_VALUE_NAME];
BOOL HasValue;
INT Index;
PCSTR p;
BOOL IsHkr;
BOOL Present;
HKEY Key;
PBYTE Data;
HasValue = DecodeRegistryString (Args, RegKey, RegValue, NULL);
//
// Is this HKR?
//
Index = GetOffsetOfRootString (RegKey, NULL);
p = GetRootStringFromOffset (Index);
if (!p) {
DEBUGMSG ((DBG_WHOOPS, "Parse error: %s is not a valid key", Args));
return FALSE;
}
IsHkr = !StringICompare (p, "HKR") || !StringICompare (p, "HKEY_ROOT");
//
// Verify value is present
//
if (IsHkr) {
//
// Check global table for the root
//
if (!g_PerUserRegKeys) {
return FALSE;
}
if (HtFindStringAndData (g_PerUserRegKeys, Args, &Present)) {
b = Present;
}
ELSE_DEBUGMSG ((DBG_WHOOPS, "Arg %s is not in the HKR hash table", Args));
} else {
//
// Ping the registry
//
Key = OpenRegKeyStr (RegKey);
if (Key) {
if (HasValue) {
Data = GetRegValueData (Key, RegValue);
if (Data) {
b = TRUE;
MemFree (g_hHeap, 0, Data);
}
} else {
b = TRUE;
}
CloseRegKey (Key);
}
}
return b;
}
BOOL
AtLeastWin98 (
IN PDBATTRIB_PARAMS AttribParams,
IN PCSTR Args
)
{
return ISATLEASTWIN98();
}