text: /******************************************************************************
   *
   *  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;
  }
  
  