345 lines
9.7 KiB
C++
345 lines
9.7 KiB
C++
/******************************************************************************
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*
|
|
* Module Name:
|
|
* FileInfo.cxx
|
|
*
|
|
* Abstract:
|
|
* Tool for getting file information
|
|
*
|
|
* Revision History:
|
|
*
|
|
* Weiyou Cui (weiyouc) 02-May-2001
|
|
* - Created
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "srheader.hxx"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function prototypes
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT InfoPerFile(LPTSTR ptszLogFile, LPTSTR ptszFileName);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Some global structures and variables
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
struct LANGANDCODEPAGE {
|
|
WORD wLanguage;
|
|
WORD wCodePage;
|
|
} *lpTranslate;
|
|
|
|
LPCTSTR g_tszFileVersionList[] =
|
|
{
|
|
TEXT("\\system32\\drivers\\sr.sys"),
|
|
TEXT("\\system32\\srclient.dll"),
|
|
TEXT("\\system32\\srsvc.dll"),
|
|
TEXT("\\system32\\srrstr.dll"),
|
|
TEXT("\\system32\\restore\\filelist.xml"),
|
|
TEXT("\\system32\\restore\\rstrui.exe"),
|
|
TEXT("\\system32\\restore\\srframe.mmf"),
|
|
TEXT("\\system32\\restore\\sr.mof"),
|
|
};
|
|
|
|
LPCTSTR g_tszVersionResource[] =
|
|
{
|
|
TEXT("Comments"),
|
|
TEXT("CompanyName"),
|
|
TEXT("FileDescription"),
|
|
TEXT("FileVersion"),
|
|
TEXT("InternalName"),
|
|
TEXT("LegalCopyright"),
|
|
TEXT("LegalTrademarks"),
|
|
TEXT("OriginalFilename"),
|
|
TEXT("ProductName"),
|
|
TEXT("ProductVersion"),
|
|
TEXT("PrivateBuild"),
|
|
TEXT("SpecialBuild"),
|
|
};
|
|
|
|
extern LPCTSTR g_tszMonth[];
|
|
extern LPCTSTR g_tszDay[];
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SRGetFileInfo
|
|
//
|
|
// Synopsis: This is the wrapper function for InfoPerFile, where I will assemble
|
|
// the file path for each of the relevant files that we need to get
|
|
// file statistics.
|
|
//
|
|
// Arguments: [ptszLogFile] -- log file name
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 9/21/00 SHeffner Created
|
|
//
|
|
// 03-May-2001 Weiyouc ReWritten
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT GetSRFileInfo(LPTSTR ptszLogFile)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int iCount = 0;
|
|
TCHAR tszFileName[MAX_PATH];
|
|
|
|
DH_VDATEPTRIN(ptszLogFile, TCHAR);
|
|
|
|
for (iCount = 0; iCount < ARRAYSIZE(g_tszFileVersionList); iCount++)
|
|
{
|
|
//
|
|
// Assemble the path, since I just have the relative path from windir
|
|
//
|
|
|
|
_tcscpy(tszFileName, _tgetenv(TEXT("WINDIR")));
|
|
_tcscat(tszFileName, g_tszFileVersionList[iCount]);
|
|
|
|
//
|
|
// Call function to do the work since we have full path
|
|
//
|
|
|
|
hr = InfoPerFile(ptszLogFile, tszFileName);
|
|
DH_HRCHECK_ABORT(hr, TEXT("InfoPerFile"));
|
|
}
|
|
|
|
ErrReturn:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: InfoPerFile
|
|
//
|
|
// Synopsis: This function takes the log file path, and the filename,
|
|
// and then will put out the relevant information from the
|
|
// file to be logged.
|
|
//
|
|
//
|
|
// Arguments: [ptszLogFile] -- Log file name
|
|
// [ptszFileName] -- File to be examined
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 9/21/00 SHeffner Created
|
|
//
|
|
// 03-May-2001 WeiyouC ReWritten
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT InfoPerFile(LPTSTR ptszLogFile, LPTSTR ptszFileName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
FILE* fpLog = NULL;
|
|
void* pvBuf = NULL;
|
|
UINT uLen = 0;;
|
|
DWORD dwSize = 0;
|
|
DWORD dwResult = 0;
|
|
DWORD i = 0;;
|
|
TCHAR szString[MAX_PATH];
|
|
BY_HANDLE_FILE_INFORMATION FileInfo;
|
|
SYSTEMTIME SysTime;
|
|
VS_FIXEDFILEINFO FixedFileInfo;
|
|
|
|
DH_VDATEPTRIN(ptszLogFile, TCHAR);
|
|
DH_VDATEPTRIN(ptszFileName, TCHAR);
|
|
|
|
//
|
|
// Open up our log file, and log the file we are processing
|
|
//
|
|
|
|
fpLog = _tfopen(ptszLogFile, TEXT("a"));
|
|
DH_ABORTIF(NULL == fpLog,
|
|
E_FAIL,
|
|
TEXT("a"));
|
|
|
|
fprintf(fpLog, "\n%S\n", ptszFileName);
|
|
|
|
//
|
|
// Open up the file so that we can get the information from the handle
|
|
// If we are unable to do this we will just log the generic not
|
|
// able to find file.
|
|
//
|
|
|
|
hFile = CreateFile(ptszFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
if (INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
if (FALSE != GetFileInformationByHandle(hFile, &FileInfo))
|
|
{
|
|
//
|
|
// Get file creation time
|
|
//
|
|
|
|
FileTimeToSystemTime(&FileInfo.ftCreationTime, &SysTime);
|
|
fprintf(fpLog,
|
|
"\tCreation Date=%S %S %lu, %lu %lu:%lu:%lu\n",
|
|
g_tszDay[SysTime.wDayOfWeek],
|
|
g_tszMonth[SysTime.wMonth - 1],
|
|
SysTime.wDay,
|
|
SysTime.wYear,
|
|
SysTime.wHour,
|
|
SysTime.wMinute,
|
|
SysTime.wSecond);
|
|
|
|
//
|
|
// Get file last access time
|
|
//
|
|
|
|
FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SysTime);
|
|
fprintf(fpLog,
|
|
"\tLast Access Date=%S %S %lu, %lu %lu:%lu:%lu\n",
|
|
g_tszDay[SysTime.wDayOfWeek],
|
|
g_tszMonth[SysTime.wMonth - 1],
|
|
SysTime.wDay,
|
|
SysTime.wYear,
|
|
SysTime.wHour,
|
|
SysTime.wMinute,
|
|
SysTime.wSecond);
|
|
|
|
//
|
|
// Get file last write time
|
|
//
|
|
|
|
FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SysTime);
|
|
fprintf(fpLog,
|
|
"\tLast Write Date=%S %S %lu, %lu %lu:%lu:%lu\n",
|
|
g_tszDay[SysTime.wDayOfWeek],
|
|
g_tszMonth[SysTime.wMonth - 1],
|
|
SysTime.wDay,
|
|
SysTime.wYear,
|
|
SysTime.wHour,
|
|
SysTime.wMinute,
|
|
SysTime.wSecond);
|
|
|
|
//
|
|
// Get file attributes
|
|
//
|
|
|
|
_tcscpy(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? TEXT("ARCHIVE ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED ? TEXT("COMPRESSED ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? TEXT("DIRECTORY ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED ? TEXT("ENCRYPTED ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? TEXT("HIDDEN ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? TEXT("NORMAL ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE ? TEXT("OFFLINE ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? TEXT("READONLY ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? TEXT("REPARSE_POINT ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ? TEXT("SPARSE_FILE ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? TEXT("SYSTEM ") : TEXT(""));
|
|
_tcscat(szString, FileInfo.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY ? TEXT("TEMPORARY ") : TEXT(""));
|
|
fprintf(fpLog, "\tAttributes=%S\n", szString);
|
|
|
|
//
|
|
// Get the VolumeSerialNumber, FileSize, and Number of Links
|
|
//
|
|
|
|
fprintf(fpLog,
|
|
"\tVolumeSerialNumber=%lu\n",
|
|
FileInfo.dwVolumeSerialNumber);
|
|
fprintf(fpLog,
|
|
"\tFileSize=%lu%lu\n",
|
|
FileInfo.nFileSizeHigh,
|
|
FileInfo.nFileSizeLow);
|
|
fprintf(fpLog,
|
|
"\tNumberOfLinks=%lu\n",
|
|
FileInfo.nNumberOfLinks);
|
|
|
|
dwSize = GetFileVersionInfoSize(ptszFileName, &dwResult);
|
|
if (0 != dwSize)
|
|
{
|
|
pvBuf = malloc(dwSize);
|
|
DH_ABORTIF(NULL == pvBuf,
|
|
E_OUTOFMEMORY,
|
|
TEXT("malloc"));
|
|
|
|
GetFileVersionInfo(ptszFileName,
|
|
dwResult,
|
|
dwSize,
|
|
(LPVOID) pvBuf);
|
|
|
|
//
|
|
// Read the list of languages and code pages.
|
|
//
|
|
|
|
VerQueryValue(pvBuf,
|
|
TEXT("\\VarFileInfo\\Translation"),
|
|
(LPVOID*)&lpTranslate,
|
|
&uLen);
|
|
|
|
//
|
|
// Read the Version info for each language and code page.
|
|
//
|
|
|
|
for (i=0; i < (uLen / sizeof(struct LANGANDCODEPAGE)); i++ )
|
|
{
|
|
char* lpBuffer;
|
|
DWORD dwBytes, dwCount = 0;
|
|
|
|
fprintf(fpLog,
|
|
"\tLanguage=%x%x\n",
|
|
lpTranslate[i].wLanguage,
|
|
lpTranslate[i].wCodePage);
|
|
|
|
for (dwCount = 0; dwCount < ARRAYSIZE(g_tszVersionResource); dwCount++)
|
|
{
|
|
//
|
|
// Generate the string, for getting the resource
|
|
// based on the language, then retrieve this, and
|
|
// then put it to the log file.
|
|
//
|
|
|
|
_stprintf(szString,
|
|
TEXT("\\StringFileInfo\\%04x%04x\\%s"),
|
|
lpTranslate[i].wLanguage,
|
|
lpTranslate[i].wCodePage,
|
|
g_tszVersionResource[dwCount]);
|
|
VerQueryValue(pvBuf,
|
|
szString,
|
|
(LPVOID *) &lpBuffer,
|
|
&uLen);
|
|
if (0 != uLen)
|
|
{
|
|
fprintf(fpLog,
|
|
"\t%S=%S\n",
|
|
g_tszVersionResource[dwCount],
|
|
lpBuffer);
|
|
}
|
|
} //While loop end, for each resource
|
|
} //for loop end for each language
|
|
} //If check for getting the fileversioninfosize
|
|
} //if check for GetFileInformationByHandle on the file
|
|
} //if check on can I open this file
|
|
|
|
ErrReturn:
|
|
|
|
if (INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
CloseHandle(hFile);
|
|
hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
if (NULL != fpLog)
|
|
{
|
|
fclose(fpLog);
|
|
}
|
|
if (NULL != pvBuf)
|
|
{
|
|
free(pvBuf);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|