You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
9.0 KiB
C++
322 lines
9.0 KiB
C++
15 years ago
|
//==========================================
|
||
|
// Matt Pietrek
|
||
|
// Microsoft Systems Journal, Feb 1997
|
||
|
// FILE: DEPENDS.CPP
|
||
|
//==========================================
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include "dependencylist.h"
|
||
|
#include "peexe.h"
|
||
|
|
||
|
//============================== Variables ===============================
|
||
|
char g_szHelpSyntax[] =
|
||
|
"DEPENDS - Matt Pietrek, 1997, for MSJ\n"
|
||
|
"Syntax: DEPENDS [args] <executable filename>\n"
|
||
|
" /v show version information\n"
|
||
|
" /t show time & date information\n"
|
||
|
" /p show full path\n"
|
||
|
" /q quiet (don't report some MS dlls)\n"
|
||
|
" /l show link time & date information\n\n";
|
||
|
|
||
|
char * g_pszPrimaryFile = 0;
|
||
|
|
||
|
BOOL g_fShowDateTime = FALSE;
|
||
|
BOOL g_fShowLinkDateTime = FALSE;
|
||
|
BOOL g_fShowVersion = FALSE;
|
||
|
BOOL g_fShowFullPath = FALSE;
|
||
|
BOOL g_fQuiet = FALSE;
|
||
|
|
||
|
//============================== Prototypes ===============================
|
||
|
void DisplayFileInformation( PMODULE_FILE_INFO pModInfo,BOOL bQuiet );
|
||
|
void ShowVersionInfo( PSTR pszFileName );
|
||
|
BOOL TimeDateStampToFileTime( DWORD timeDateStamp, LPFILETIME pFileTime );
|
||
|
BOOL GetFileDateAsString( LPFILETIME pFt, char * pszDate, unsigned cbIn );
|
||
|
BOOL GetFileTimeAsString( LPFILETIME pFt, char * pszTime, unsigned cbIn,
|
||
|
BOOL fSeconds );
|
||
|
|
||
|
//=================================== Code ================================
|
||
|
|
||
|
BOOL ProcessCommandLine( int argc, char * argv[] )
|
||
|
{
|
||
|
BOOL fSawFileName = FALSE;
|
||
|
|
||
|
if ( argc < 2 )
|
||
|
return FALSE;
|
||
|
|
||
|
for ( int i = 1; i < argc; i++ )
|
||
|
{
|
||
|
PSTR pArg = argv[i];
|
||
|
|
||
|
if ( (*pArg == '/') || (*pArg == '-') ) // Is it a switch char?
|
||
|
{
|
||
|
pArg++; // Point past switch char
|
||
|
|
||
|
if ( 0 == lstrcmpi( pArg, "v" ) )
|
||
|
g_fShowVersion = TRUE;
|
||
|
else if ( 0 == lstrcmpi( pArg, "t" ) )
|
||
|
g_fShowDateTime = TRUE;
|
||
|
else if ( 0 == lstrcmpi( pArg, "l" ) )
|
||
|
g_fShowLinkDateTime = TRUE;
|
||
|
else if ( 0 == lstrcmpi( pArg, "p" ) )
|
||
|
g_fShowFullPath = TRUE;
|
||
|
else if ( 0 == lstrcmpi( pArg, "q" ) )
|
||
|
g_fQuiet = TRUE;
|
||
|
else
|
||
|
{
|
||
|
printf( "Unrecognized option: \"%s\"\n", pArg );
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( fSawFileName )
|
||
|
return FALSE;
|
||
|
|
||
|
g_pszPrimaryFile = pArg;
|
||
|
fSawFileName = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fSawFileName;
|
||
|
}
|
||
|
|
||
|
LPCTSTR getModuleBase(PMODULE_FILE_INFO pModule,BOOL bQuiet)
|
||
|
{
|
||
|
LPCTSTR base = pModule->GetBaseName() ;
|
||
|
LPCTSTR result = base ;
|
||
|
if ( bQuiet ) {
|
||
11 years ago
|
// keep quiet about these guys - they're build/compiler dependent
|
||
15 years ago
|
if ( _strnicmp(base,"MSVCR",5) == 0 ) result = NULL ;
|
||
|
if ( _strnicmp(base,"MSVCP",5) == 0 ) result = NULL ;
|
||
|
if ( _strnicmp(base,"API-MS-Win",10) == 0 ) result = NULL ;
|
||
|
}
|
||
|
return result ;
|
||
|
}
|
||
|
|
||
|
int main( int argc, char * argv[] )
|
||
|
{
|
||
|
if ( !ProcessCommandLine( argc, argv ) )
|
||
|
{
|
||
|
printf( "%s %d bit build\n%s",argv[0],8*sizeof(void*),g_szHelpSyntax );
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
MODULE_DEPENDENCY_LIST depends( g_pszPrimaryFile );
|
||
|
|
||
|
if ( !depends.IsValid() )
|
||
|
{
|
||
|
printf( "Error: %s %s\n", g_pszPrimaryFile, depends.GetErrorString() );
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
PMODULE_FILE_INFO pModInfo = 0;
|
||
|
|
||
|
while ( pModInfo = depends.GetNextModule( pModInfo ) )
|
||
|
{
|
||
|
DisplayFileInformation( pModInfo,g_fQuiet );
|
||
|
|
||
|
PMODULE_FILE_INFO pNotFound = 0;
|
||
|
|
||
|
while ( pNotFound = pModInfo->GetNextNotFoundModule(pNotFound) )
|
||
|
{
|
||
|
LPCTSTR base = getModuleBase(pNotFound,g_fQuiet) ;
|
||
|
if ( base ) printf( " Not found: %s\n", base );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void DisplayFileInformation( PMODULE_FILE_INFO pModInfo, BOOL bQuiet )
|
||
|
{
|
||
|
LPCTSTR base = getModuleBase(pModInfo,bQuiet);
|
||
|
if ( !base ) return ;
|
||
|
printf( "%-14s", base) ; // ->GetBaseName() );
|
||
|
|
||
|
PSTR pszFullName = pModInfo->GetFullName();
|
||
|
|
||
|
if ( g_fShowDateTime )
|
||
|
{
|
||
|
HFILE hFile = _lopen( pszFullName, OF_READ );
|
||
|
if ( HFILE_ERROR != hFile )
|
||
|
{
|
||
|
FILETIME ft;
|
||
|
|
||
|
if ( GetFileTime( (HANDLE)hFile, 0, 0, &ft ) )
|
||
|
{
|
||
|
char szFileDate[32] = { 0 };
|
||
|
char szFileTime[32] = { 0 };
|
||
|
|
||
|
GetFileDateAsString(&ft, szFileDate, sizeof(szFileDate) );
|
||
|
GetFileTimeAsString(&ft, szFileTime, sizeof(szFileTime),
|
||
|
TRUE);
|
||
|
|
||
|
printf( "%s %s ", szFileDate, szFileTime );
|
||
|
}
|
||
|
|
||
|
_lclose( hFile );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( g_fShowLinkDateTime )
|
||
|
{
|
||
|
FILETIME ft;
|
||
|
char szFileDate[32] = { 0 };
|
||
|
char szFileTime[32] = { 0 };
|
||
|
|
||
|
PE_EXE exe( pszFullName );
|
||
|
|
||
|
TimeDateStampToFileTime( exe.GetTimeDateStamp(), &ft );
|
||
|
|
||
|
GetFileDateAsString(&ft, szFileDate, sizeof(szFileDate) );
|
||
|
GetFileTimeAsString(&ft, szFileTime, sizeof(szFileTime),
|
||
|
TRUE);
|
||
|
|
||
|
printf( "%s %s ", szFileDate, szFileTime );
|
||
|
}
|
||
|
|
||
|
if ( g_fShowFullPath )
|
||
|
printf( "(%s)", pszFullName );
|
||
|
|
||
|
printf( "\n" );
|
||
|
|
||
|
if ( g_fShowVersion )
|
||
|
ShowVersionInfo( pszFullName );
|
||
|
}
|
||
|
|
||
|
void ShowVersionInfo( PSTR pszFileName )
|
||
|
{
|
||
|
DWORD cbVerInfo, dummy;
|
||
|
|
||
|
// How big is the version info?
|
||
|
cbVerInfo = GetFileVersionInfoSize( pszFileName, &dummy );
|
||
|
if ( !cbVerInfo )
|
||
|
return;
|
||
|
|
||
|
// Allocate space to hold the info
|
||
|
PBYTE pVerInfo = new BYTE[cbVerInfo];
|
||
|
if ( !pVerInfo )
|
||
|
return;
|
||
|
|
||
|
_try
|
||
|
{
|
||
|
if ( !GetFileVersionInfo(pszFileName, 0, cbVerInfo, pVerInfo) )
|
||
|
_leave;
|
||
|
|
||
|
char * predefResStrings[] =
|
||
|
{
|
||
|
"CompanyName",
|
||
|
"FileDescription",
|
||
|
"FileVersion",
|
||
|
"InternalName",
|
||
|
"LegalCopyright",
|
||
|
"OriginalFilename",
|
||
|
"ProductName",
|
||
|
"ProductVersion",
|
||
|
0
|
||
|
};
|
||
|
|
||
|
for ( unsigned i=0; predefResStrings[i]; i++ )
|
||
|
{
|
||
|
char szQueryStr[ 0x100 ];
|
||
|
char szQueryStr2[0x100 ];
|
||
|
|
||
|
// Format the string with the 1200 codepage (Unicode)
|
||
|
wsprintf( szQueryStr, "\\StringFileInfo\\%04X%04X\\%s",
|
||
|
GetUserDefaultLangID(), 1200,
|
||
|
predefResStrings[i] );
|
||
|
|
||
|
// Format the string with the 1252 codepage (Windows Multilingual)
|
||
|
wsprintf( szQueryStr2, "\\StringFileInfo\\%04X%04X\\%s",
|
||
|
GetUserDefaultLangID(), 1252,
|
||
|
predefResStrings[i] );
|
||
|
// We may want to format a string with the "0000" codepage
|
||
|
|
||
|
PSTR pszVerRetVal;
|
||
|
UINT cbReturn;
|
||
|
BOOL fFound;
|
||
|
|
||
|
// Try first with the 1252 codepage
|
||
|
fFound = VerQueryValue( pVerInfo, szQueryStr,
|
||
|
(LPVOID *)&pszVerRetVal, &cbReturn );
|
||
|
if ( !fFound )
|
||
|
{
|
||
|
// Hmm... 1252 wasn't found. Try the 1200 codepage
|
||
|
fFound = VerQueryValue( pVerInfo, szQueryStr2,
|
||
|
(LPVOID *)&pszVerRetVal, &cbReturn );
|
||
|
}
|
||
|
|
||
|
if ( fFound )
|
||
|
printf( " %s %s\n", predefResStrings[i], pszVerRetVal );
|
||
|
}
|
||
|
}
|
||
|
_finally
|
||
|
{
|
||
|
delete []pVerInfo;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Convert a TimeDateStamp (i.e., # of seconds since 1/1/1970) into a FILETIME
|
||
|
|
||
|
BOOL TimeDateStampToFileTime( DWORD timeDateStamp, LPFILETIME pFileTime )
|
||
|
{
|
||
|
__int64 t1970 = 0x019DB1DED53E8000; // Magic... GMT... Don't ask....
|
||
|
|
||
|
__int64 timeStampIn100nsIncr = (__int64)timeDateStamp * 10000000;
|
||
|
|
||
|
__int64 finalValue = t1970 + timeStampIn100nsIncr;
|
||
|
|
||
|
memcpy( pFileTime, &finalValue, sizeof( finalValue ) );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL GetFileDateAsString( LPFILETIME pFt, char * pszDate, unsigned cbIn )
|
||
|
{
|
||
|
FILETIME ftLocal;
|
||
|
SYSTEMTIME st;
|
||
|
|
||
|
if ( !FileTimeToLocalFileTime( pFt, &ftLocal ) )
|
||
|
return FALSE;
|
||
|
|
||
|
if ( !FileTimeToSystemTime( &ftLocal, &st ) )
|
||
|
return FALSE;
|
||
|
|
||
|
char szTemp[12];
|
||
|
|
||
|
wsprintf( szTemp, "%02u/%02u/%04u",
|
||
|
st.wMonth, st.wDay, st.wYear );
|
||
|
lstrcpyn( pszDate, szTemp, cbIn );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL GetFileTimeAsString( LPFILETIME pFt, char * pszTime, unsigned cbIn,
|
||
|
BOOL fSeconds )
|
||
|
{
|
||
|
FILETIME ftLocal;
|
||
|
SYSTEMTIME st;
|
||
|
|
||
|
if ( !FileTimeToLocalFileTime( pFt, &ftLocal ) )
|
||
|
return FALSE;
|
||
|
|
||
|
if ( !FileTimeToSystemTime( &ftLocal, &st ) )
|
||
|
return FALSE;
|
||
|
|
||
|
char szTemp[12];
|
||
|
|
||
|
if ( fSeconds ) // Want seconds???
|
||
|
{
|
||
|
wsprintf( szTemp, "%02u:%02u:%02u", st.wHour, st.wMinute, st.wSecond );
|
||
|
}
|
||
|
else // No thanks.. Just hours and minutes
|
||
|
{
|
||
|
wsprintf( szTemp, "%02u:%02u", st.wHour, st.wMinute );
|
||
|
}
|
||
|
|
||
|
lstrcpyn( pszTime, szTemp, cbIn );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|