/*++ 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 "logmsg.h" #include "osfiles.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(CheckSum, CHECKSUM, 1) \ DEFMAC(ExeType, EXETYPE, 1) \ DEFMAC(Description, DESCRIPTION, 1) \ DEFMAC(HasVersion, HASVERSION, 0) \ 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) \ typedef struct { PCTSTR 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) {TEXT(#id), fn, regargs}, static ATTRIBUTE_STRUCT g_AttributeFunctions[] = { ATTRIBUTE_FUNCTIONS {NULL, NULL} }; #undef DEFMAC BOOL pAlwaysFalseAttribute ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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 PCTSTR 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; } PCTSTR 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 TEXT("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 PCTSTR FileName ) { VRVALUE_ENUM Version; ULONGLONG result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryFileVersion (&Version); VrDestroyEnumStruct (&Version); } return result; } ULONGLONG GetBinProductVer ( IN PCTSTR FileName ) { VRVALUE_ENUM Version; ULONGLONG result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryProductVersion (&Version); VrDestroyEnumStruct (&Version); } return result; } DWORD GetFileDateHi ( IN PCTSTR FileName ) { VRVALUE_ENUM Version; DWORD result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryFileDateHi (&Version); VrDestroyEnumStruct (&Version); } return result; } DWORD GetFileDateLo ( IN PCTSTR FileName ) { VRVALUE_ENUM Version; DWORD result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryFileDateLo (&Version); VrDestroyEnumStruct (&Version); } return result; } DWORD GetFileVerOs ( IN PCTSTR FileName ) { VRVALUE_ENUM Version; DWORD result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryOsVersion (&Version); VrDestroyEnumStruct (&Version); } return result; } DWORD GetFileVerType ( IN PCTSTR FileName ) { VRVALUE_ENUM Version; DWORD result = 0; if (VrCreateEnumStruct (&Version, FileName)) { result = VrGetBinaryFileType (&Version); VrDestroyEnumStruct (&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 PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("CompanyName"), Args); } BOOL FileDescription ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("FileDescription"), Args); } BOOL FileVersion ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("FileVersion"), Args); } BOOL InternalName ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("InternalName"), Args); } BOOL LegalCopyright ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("LegalCopyright"), Args); } BOOL OriginalFilename ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("OriginalFilename"), Args); } BOOL ProductName ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("ProductName"), Args); } BOOL ProductVersion ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("ProductVersion"), Args); } BOOL FileSize ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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; _stscanf (Args, TEXT("%lx"), &fileSize); if (fileSize == AttribParams->FileParams->FindData->nFileSizeLow) { return TRUE; } else { return (_ttoi64 (Args) == AttribParams->FileParams->FindData->nFileSizeLow); } } BOOL IsMsBinary ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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 --*/ { return VrCheckFileVersion (AttribParams->FileParams->NativeObjectName, TEXT("CompanyName"), TEXT("*Microsoft*")); } BOOL CheckSum ( PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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 = MdGetCheckSum (AttribParams->FileParams->NativeObjectName); _stscanf (Args, TEXT("%lx"), &oldSum); if (oldSum == checkSum) { return TRUE; } else { return (_ttoi64 (Args) == checkSum); } } BOOL SizeCheckSum ( PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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 --*/ { PCTSTR currArg = Args; if (!FileSize (AttribParams, currArg)) { return FALSE; } currArg = GetEndOfString (currArg); if (!currArg) { return FALSE; } currArg = _tcsinc (currArg); if (!currArg) { return FALSE; } return (CheckSum (AttribParams, currArg)); } PTSTR g_ExeTypes[] = { TEXT("NONE"), TEXT("DOS"), TEXT("WIN16"), TEXT("WIN32") }; BOOL ExeType ( PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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[MdGetModuleType (AttribParams->FileParams->NativeObjectName)]); } BOOL Description ( PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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 --*/ { PCTSTR descr = NULL; BOOL result = FALSE; descr = MdGet16ModuleDescription (AttribParams->FileParams->NativeObjectName); if (descr != NULL) { result = IsPatternMatch (Args, descr); FreePathString (descr); } return result; } BOOL HasVersion ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR 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. --*/ { VRVALUE_ENUM Version; BOOL Result = FALSE; if (VrCreateEnumStruct (&Version, AttribParams->FileParams->NativeObjectName)) { Result = TRUE; VrDestroyEnumStruct (&Version); } return Result; } BOOL pHexMatch ( IN DWORD NewValue, IN PCTSTR Args ) { DWORD oldValue; _stscanf (Args, TEXT("%lx"), &oldValue); if (oldValue == NewValue) { return TRUE; } else { return (_ttoi64 (Args) == NewValue); } } BOOL pConvertDotStringToValue ( IN PCTSTR 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) _tcstoul (String, &(PTSTR) String, 10); if (*String && (_tcsnextc (String) != TEXT('.'))) { return FALSE; } String = _tcsinc (String); valueIdx--; } return TRUE; } BOOL pMaskHexMatch ( IN ULONGLONG NewValue, IN PCTSTR 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) _tcstoul ((PTSTR)Args, &((PTSTR)Args), 10); if (*Args) { if (_tcsnextc (Args) != TEXT('.')) { return FALSE; } Args = _tcsinc (Args); } *maskIdx = 65535; valueIdx--; maskIdx--; index++; } NewValue = NewValue & mask; return (oldValue == NewValue); } BOOL BinFileVer ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pMaskHexMatch (GetBinFileVer (AttribParams->FileParams->NativeObjectName), Args); } BOOL BinProductVer ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pMaskHexMatch (GetBinProductVer (AttribParams->FileParams->NativeObjectName), Args); } BOOL FileDateHi ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pHexMatch (GetFileDateHi (AttribParams->FileParams->NativeObjectName), Args); } BOOL FileDateLo ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pHexMatch (GetFileDateLo (AttribParams->FileParams->NativeObjectName), Args); } BOOL FileVerOs ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pHexMatch (GetFileVerOs (AttribParams->FileParams->NativeObjectName), Args); } BOOL FileVerType ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { return pHexMatch (GetFileVerType (AttribParams->FileParams->NativeObjectName), Args); } BOOL UpToBinProductVer ( IN PDBATTRIB_PARAMS AttribParams, IN PCTSTR Args ) { VRVALUE_ENUM Version; ULONGLONG versionStampValue = 0; ULONGLONG maxValue; if (VrCreateEnumStruct (&Version, AttribParams->FileParams->NativeObjectName)) { versionStampValue = VrGetBinaryProductVersion (&Version); VrDestroyEnumStruct (&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 PCTSTR Args ) { VRVALUE_ENUM Version; ULONGLONG versionStampValue = 0; ULONGLONG maxValue; if (VrCreateEnumStruct (&Version, AttribParams->FileParams->NativeObjectName)) { versionStampValue = VrGetBinaryFileVersion (&Version); VrDestroyEnumStruct (&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; }