#include "acFileAttr.h" #include "attr.h" #include "version.h" #include #include #include // the global array with all the file attributes FILEATTR g_arrFileAttr[] = { {VTID_FILESIZE, "File Size", "SIZE", QueryFileSize, BlobToStringLong, DumpDWORD}, {VTID_EXETYPE, "Module Type", "MODULETYPE*", QueryModuleType, BlobToStringDWORD, DumpDWORD}, {VTID_BINFILEVER, "Binary File Version", "BIN_FILE_VERSION", QueryBinFileVer, BlobToStringBinVer, DumpBinVer}, {VTID_BINPRODUCTVER, "Binary Product Version", "BIN_PRODUCT_VERSION", QueryBinProductVer, BlobToStringBinVer, DumpBinVer}, {VTID_FILEDATEHI, "File Date (HI)", "VERFILEDATEHI", QueryFileDateHi, BlobToStringDWORD, DumpDWORD}, {VTID_FILEDATELO, "File Date (LO)", "VERFILEDATELO", QueryFileDateLo, BlobToStringDWORD, DumpDWORD}, {VTID_FILEVEROS, "File OS Version", "VERFILEOS", QueryFileVerOs, BlobToStringDWORD, DumpDWORD}, {VTID_FILEVERTYPE, "File Type", "VERFILETYPE", QueryFileVerType, BlobToStringDWORD, DumpDWORD}, {VTID_CHECKSUM, "File CheckSum", "CHECKSUM", QueryFileCheckSum, BlobToStringDWORD, DumpDWORD}, {VTID_PECHECKSUM, "File Header CheckSum", "PECHECKSUM", QueryFilePECheckSum, BlobToStringDWORD, DumpDWORD}, {VTID_COMPANYNAME, "Company Name", "COMPANY_NAME", QueryCompanyName, BlobToStringString, DumpString}, {VTID_PRODUCTVERSION, "Product Version", "PRODUCT_VERSION", QueryProductVersion, BlobToStringString, DumpString}, {VTID_PRODUCTNAME, "Product Name", "PRODUCT_NAME", QueryProductName, BlobToStringString, DumpString}, {VTID_FILEDESCRIPTION, "File Description", "FILE_DESCRIPTION", QueryFileDescription, BlobToStringString, DumpString}, {VTID_FILEVERSION, "File Version", "FILEVERSION", QueryFileVersion, BlobToStringString, DumpString}, {VTID_ORIGINALFILENAME, "Original File Name", "ORIGINALFILENAME", QueryOriginalFileName, BlobToStringString, DumpString}, {VTID_INTERNALNAME, "Internal Name", "INTERNALNAME", QueryInternalName, BlobToStringString, DumpString}, {VTID_LEGALCOPYRIGHT, "Legal Copyright", "LEGALCOPYRIGHT", QueryLegalCopyright, BlobToStringString, DumpString}, {VTID_16BITDESCRIPTION, "16 Bit Description", "S16BITDESCRIPTION", Query16BitDescription, BlobToStringString, DumpString}, {VTID_UPTOBINPRODUCTVER,"Up To Binary Product Version", "UPTO_BIN_PRODUCT_VERSION", QueryBinProductVer, BlobToStringUpToBinVer, DumpUpToBinVer} }; #define FAIL_IF_NO_VERSION() \ { \ if (pMgr->ver.FixedInfoSize < sizeof(VS_FIXEDFILEINFO)) { \ LogMsg("No version info\n"); \ return FALSE; \ } \ } #define ALLOC_VALUE_AND_RETURN() \ { \ pFileAttr->pszValue = (PSTR)Alloc(lstrlen(szBuffer) + 1); \ \ if (pFileAttr->pszValue == NULL) { \ LogMsg("QueryAttr: memory allocation error\n"); \ return FALSE; \ } \ \ lstrcpy(pFileAttr->pszValue, szBuffer); \ \ pFileAttr->dwFlags = ATTR_FLAG_AVAILABLE; \ \ return TRUE; \ } #define QUERYENTRY(szEntryName) \ { \ pFileAttr->pszValue = QueryVersionEntry(&pMgr->ver, szEntryName); \ \ if (pFileAttr->pszValue == NULL) { \ LogMsg("QueryEntry: attribute %s N/A\n", szEntryName); \ return FALSE; \ } \ pFileAttr->dwFlags = ATTR_FLAG_AVAILABLE; \ \ return TRUE; \ } #if DBG void LogMsgDbg( LPSTR pszFmt, ... ) { CHAR gszT[1024]; va_list arglist; va_start(arglist, pszFmt); _vsnprintf(gszT, 1023, pszFmt, arglist); gszT[1023] = 0; va_end(arglist); OutputDebugString(gszT); } #endif // DBG // dump to blob functions int DumpDWORD( DWORD dwId, PFILEATTRVALUE pFileAttr, BYTE* pBlob) { *(DWORD*)pBlob = dwId; pBlob += sizeof(DWORD); *(DWORD*)pBlob = sizeof(DWORD); pBlob += sizeof(DWORD); *(DWORD*)pBlob = pFileAttr->dwValue; return (3 * sizeof(DWORD)); } int DumpString( DWORD dwId, PFILEATTRVALUE pFileAttr, BYTE* pBlob) { int strLen, nWideChars; WCHAR wszOut[256]; strLen = lstrlen(pFileAttr->pszValue); nWideChars = MultiByteToWideChar( CP_ACP, 0, pFileAttr->pszValue, strLen, wszOut, 256); wszOut[nWideChars] = 0; *(DWORD*)pBlob = dwId; pBlob += sizeof(DWORD); *(DWORD*)pBlob = (nWideChars + 1) * sizeof(WCHAR); pBlob += sizeof(DWORD); CopyMemory(pBlob, wszOut, (nWideChars + 1) * sizeof(WCHAR)); return (2 * sizeof(DWORD) + (nWideChars + 1) * sizeof(WCHAR)); } int DumpBinVer( DWORD dwId, PFILEATTRVALUE pFileAttr, BYTE* pBlob) { *(DWORD*)pBlob = dwId; pBlob += sizeof(DWORD); *(DWORD*)pBlob = 8 * sizeof(WORD); pBlob += sizeof(DWORD); CopyMemory(pBlob, pFileAttr->wValue, 4 * sizeof(WORD)); pBlob += (4 * sizeof(WORD)); CopyMemory(pBlob, pFileAttr->wMask, 4 * sizeof(WORD)); return (8 * sizeof(WORD) + 2 * sizeof(DWORD)); } int DumpUpToBinVer( DWORD dwId, PFILEATTRVALUE pFileAttr, BYTE* pBlob) { *(DWORD*)pBlob = dwId; pBlob += sizeof(DWORD); *(DWORD*)pBlob = 4 * sizeof(WORD); pBlob += sizeof(DWORD); CopyMemory(pBlob, pFileAttr->wValue, 4 * sizeof(WORD)); return (4 * sizeof(WORD) + 2 * sizeof(DWORD)); } // blob to string functions int BlobToStringBinVer( BYTE* pBlob, char* pszOut) { DWORD dwSize; // read the size first dwSize = *(DWORD*)pBlob; if (dwSize != 8 * sizeof(WORD)) { LogMsg("BlobToStringBinVer: invalid blob\n"); return -1; } pBlob += sizeof(DWORD); wsprintf(pszOut, "Ver %d.%d.%d.%d Mask %04X.%04X.%04X.%04X\r\n", *((WORD*)pBlob + 3), *((WORD*)pBlob + 2), *((WORD*)pBlob + 1), *((WORD*)pBlob + 0), *((WORD*)pBlob + 7), *((WORD*)pBlob + 6), *((WORD*)pBlob + 5), *((WORD*)pBlob + 4)); return sizeof(DWORD) + 8 * sizeof(WORD); } int BlobToStringUpToBinVer( BYTE* pBlob, char* pszOut) { DWORD dwSize; // read the size first dwSize = *(DWORD*)pBlob; if (dwSize != 4 * sizeof(WORD)) { LogMsg("BlobToStringUpToBinVer: invalid blob\n"); return -1; } pBlob += sizeof(DWORD); wsprintf(pszOut, "Ver %d.%d.%d.%d\r\n", *((WORD*)pBlob + 3), *((WORD*)pBlob + 2), *((WORD*)pBlob + 1), *((WORD*)pBlob + 0)); return sizeof(DWORD) + 4 * sizeof(WORD); } int BlobToStringDWORD( BYTE* pBlob, char* pszOut) { DWORD dwSize; // read the size first dwSize = *(DWORD*)pBlob; if (dwSize != sizeof(DWORD)) { LogMsg("BlobToStringDWORD: invalid blob\n"); return -1; } pBlob += sizeof(DWORD); wsprintf(pszOut, "0x%X\r\n", *(DWORD*)pBlob); return 2 * sizeof(DWORD); } int BlobToStringLong( BYTE* pBlob, char* pszOut) { DWORD dwSize; // read the size first dwSize = *(DWORD*)pBlob; if (dwSize != sizeof(DWORD)) { LogMsg("BlobToStringLong: invalid blob\n"); return -1; } pBlob += sizeof(DWORD); wsprintf(pszOut, "%d\r\n", *(ULONG*)pBlob); return 2 * sizeof(DWORD); } int BlobToStringString( BYTE* pBlob, char* pszOut) { DWORD dwSize; // read the size first dwSize = *(DWORD*)pBlob; pBlob += sizeof(DWORD); WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)pBlob, (int)dwSize, pszOut, (int)dwSize, NULL, NULL); lstrcat(pszOut, "\r\n"); return sizeof(DWORD) + (int)dwSize; } // query functions BOOL QueryFileSize( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; HANDLE findHandle; WIN32_FIND_DATA findData; findHandle = FindFirstFile(pMgr->ver.pszFile, &findData); if (findHandle == INVALID_HANDLE_VALUE) { LogMsg("QueryFileSize: file not found\n"); return FALSE; } pFileAttr->dwValue = findData.nFileSizeLow; FindClose(findHandle); wsprintf(szBuffer, "%d", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } BOOL QueryModuleType( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { // not implemented return FALSE; } BOOL QueryBinFileVer( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { ULONGLONG binFileVer; char szBuffer[64]; FAIL_IF_NO_VERSION(); *((PDWORD)(&binFileVer)) = pMgr->ver.FixedInfo->dwFileVersionLS; *(((PDWORD)(&binFileVer)) + 1) = pMgr->ver.FixedInfo->dwFileVersionMS; CopyMemory(pFileAttr->wValue, &binFileVer, 4 * sizeof(WORD)); wsprintf(szBuffer, "%d.%d.%d.%d", pFileAttr->wValue[3], pFileAttr->wValue[2], pFileAttr->wValue[1], pFileAttr->wValue[0]); pFileAttr->wMask[0] = pFileAttr->wMask[1] = pFileAttr->wMask[2] = pFileAttr->wMask[3] = 0xFFFF; ALLOC_VALUE_AND_RETURN(); } BOOL QueryBinProductVer( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { ULONGLONG binProdVer; char szBuffer[64]; FAIL_IF_NO_VERSION(); *((PDWORD)(&binProdVer)) = pMgr->ver.FixedInfo->dwProductVersionLS; *(((PDWORD)(&binProdVer)) + 1) = pMgr->ver.FixedInfo->dwProductVersionMS; CopyMemory(pFileAttr->wValue, &binProdVer, 4 * sizeof(WORD)); wsprintf(szBuffer, "%d.%d.%d.%d", pFileAttr->wValue[3], pFileAttr->wValue[2], pFileAttr->wValue[1], pFileAttr->wValue[0]); pFileAttr->wMask[0] = pFileAttr->wMask[1] = pFileAttr->wMask[2] = pFileAttr->wMask[3] = 0xFFFF; ALLOC_VALUE_AND_RETURN(); } BOOL QueryFileDateHi( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; FAIL_IF_NO_VERSION(); pFileAttr->dwValue = pMgr->ver.FixedInfo->dwFileDateMS; wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } BOOL QueryFileDateLo( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; FAIL_IF_NO_VERSION(); pFileAttr->dwValue = pMgr->ver.FixedInfo->dwFileDateLS; wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } BOOL QueryFileVerOs( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; FAIL_IF_NO_VERSION(); pFileAttr->dwValue = pMgr->ver.FixedInfo->dwFileOS; wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } BOOL QueryFileVerType( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; FAIL_IF_NO_VERSION(); pFileAttr->dwValue = pMgr->ver.FixedInfo->dwFileType; wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } // ComputeFileCheckSum // // computes 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. DWORD ComputeFileCheckSum( PSTR pszFile, WIN32_FIND_DATA* pFindData) { INT i,size = 4096; DWORD startAddr = 512; HANDLE fileHandle = INVALID_HANDLE_VALUE; PCHAR buffer = NULL; DWORD checkSum = 0; DWORD dontCare; if (pFindData->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 = pFindData->nFileSizeLow; } else if (startAddr + size > pFindData->nFileSizeLow) { // // File size is too small. We set the start address so that size of checksum can be 4096 bytes // startAddr = pFindData->nFileSizeLow - size; } if (size <= 3) { // // we need at least 3 bytes to be able to do something here. // return 0; } __try { buffer = (PCHAR)HeapAlloc(GetProcessHeap(), 0, size); if (buffer == NULL) { __leave; } fileHandle = CreateFile(pszFile, 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) { HeapFree(GetProcessHeap(), 0, buffer); } } return checkSum; } BOOL QueryFileCheckSum( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { WIN32_FIND_DATA findData; HANDLE findHandle; char szBuffer[64]; findHandle = FindFirstFile(pMgr->ver.pszFile, &findData); if (findHandle == INVALID_HANDLE_VALUE) { LogMsg("QueryFileCheckSum: Cannot find file %s\n", pMgr->ver.pszFile); return FALSE; } pFileAttr->dwValue = ComputeFileCheckSum(pMgr->ver.pszFile, &findData); FindClose(findHandle); wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } // GetImageNtHeader // // This function returns the address of the NT Header. // Returns the address of the NT Header. PIMAGE_NT_HEADERS GetImageNtHeader( IN PVOID Base) { PIMAGE_NT_HEADERS NtHeaders; if (Base != NULL && Base != (PVOID)-1) { if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) { NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew); if (NtHeaders->Signature == IMAGE_NT_SIGNATURE) { return NtHeaders; } } } return NULL; } BOOL GetHeaderCheckSum( PFILEATTRMGR pMgr, DWORD* pdwCheckSum) { HANDLE fileHandle; DWORD bytesRead; IMAGE_DOS_HEADER dh; LOADED_IMAGE image; DWORD sign; PWORD signNE = (PWORD)&sign; BOOL result = FALSE; *pdwCheckSum = 0; fileHandle = CreateFile(pMgr->ver.pszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { return FALSE; } __try { __try { if (!ReadFile(fileHandle, &dh, sizeof(IMAGE_DOS_HEADER), &bytesRead, NULL) || bytesRead != sizeof (IMAGE_DOS_HEADER)) { __leave; } if (dh.e_magic != IMAGE_DOS_SIGNATURE) { __leave; } if (SetFilePointer(fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) { __leave; } if (!ReadFile(fileHandle, &sign, sizeof(DWORD), &bytesRead, NULL) || bytesRead != sizeof (DWORD)) { __leave; } CloseHandle(fileHandle); fileHandle = INVALID_HANDLE_VALUE; if (sign == IMAGE_NT_SIGNATURE) { if (MapAndLoad(pMgr->ver.pszFile, NULL, &image, FALSE, TRUE)) { PIMAGE_NT_HEADERS NtHeaders; __try { NtHeaders = GetImageNtHeader(image.MappedAddress); if (NtHeaders != NULL) { if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { *pdwCheckSum = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum; } else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { *pdwCheckSum = ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum; } result = TRUE; } } __except (1) { LogMsg("Access violation while examining %s\n", pMgr->ver.pszFile); } UnMapAndLoad(&image); } } } __finally { if (fileHandle != INVALID_HANDLE_VALUE) { CloseHandle(fileHandle); } } } __except (EXCEPTION_EXECUTE_HANDLER) { CloseHandle(fileHandle); result = FALSE; } return result; } BOOL QueryFilePECheckSum( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { char szBuffer[64]; if (!GetHeaderCheckSum(pMgr, &pFileAttr->dwValue) || pFileAttr->dwValue == 0) { LogMsg("QueryFilePECheckSum: Cannot get the header check sum for %s\n", pMgr->ver.pszFile); return FALSE; } wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); ALLOC_VALUE_AND_RETURN(); } BOOL QueryCompanyName( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("COMPANYNAME"); } BOOL QueryProductVersion( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("PRODUCTVERSION"); } BOOL QueryProductName( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("PRODUCTNAME"); } BOOL QueryFileDescription( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("FILEDESCRIPTION"); } BOOL QueryFileVersion( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("FILEVERSION"); } BOOL QueryOriginalFileName( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("ORIGINALFILENAME"); } BOOL QueryInternalName( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("INTERNALNAME"); } BOOL QueryLegalCopyright( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { FAIL_IF_NO_VERSION(); QUERYENTRY("LEGALCOPYRIGHT"); } BOOL Query16BitDescription( PFILEATTRMGR pMgr, PFILEATTRVALUE pFileAttr) { //char szBuffer[64]; pFileAttr->dwValue = 0; //wsprintf(szBuffer, "0x%X", pFileAttr->dwValue); return FALSE; //ALLOC_VALUE_AND_RETURN(); }