diff --git a/msvc64/tools/depends/Depends2.suo b/msvc64/tools/depends/Depends2.suo new file mode 100644 index 00000000..f1ecba26 Binary files /dev/null and b/msvc64/tools/depends/Depends2.suo differ diff --git a/msvc64/tools/depends/ReadMe.txt b/msvc64/tools/depends/ReadMe.txt new file mode 100644 index 00000000..cb7ce895 --- /dev/null +++ b/msvc64/tools/depends/ReadMe.txt @@ -0,0 +1,13 @@ +Depends/ReadMe.txt +------------------ + +This project is "depends" and is code from MSJ (now MSDN) in 1997. I appreciate and respect the code provided by Matt Pietrik. I have made the following changes: +1) Added the -q option +2) Added the MSVC build environment (for 32bit and 64bit builds) +3) Modified the default response to report 1 and 2. + +The projects builds depends32.exe and depends64.exe which are used by runner32.bat and runner64.bat to test dependancies post build. + +Robin Mills +http://clanmills.com +2011-01-02 diff --git a/msvc64/tools/depends/depends.cpp b/msvc64/tools/depends/depends.cpp new file mode 100644 index 00000000..00f83242 --- /dev/null +++ b/msvc64/tools/depends/depends.cpp @@ -0,0 +1,12 @@ +// Depends2.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + +int main(int argc, char argv[]) +{ + printf("hello world\n") ; + return 0; +} + diff --git a/msvc64/tools/depends/depends.sln b/msvc64/tools/depends/depends.sln new file mode 100644 index 00000000..189a4057 --- /dev/null +++ b/msvc64/tools/depends/depends.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "depends", "depends.vcproj", "{E24D66E3-65A9-4BEB-8579-039AD77C2EFF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Debug|Win32.ActiveCfg = Debug|Win32 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Debug|Win32.Build.0 = Debug|Win32 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Debug|x64.ActiveCfg = Debug|x64 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Debug|x64.Build.0 = Debug|x64 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Release|Win32.ActiveCfg = Release|Win32 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Release|Win32.Build.0 = Release|Win32 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Release|x64.ActiveCfg = Release|x64 + {E24D66E3-65A9-4BEB-8579-039AD77C2EFF}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/msvc64/tools/depends/depends.vcproj b/msvc64/tools/depends/depends.vcproj new file mode 100644 index 00000000..ee26e259 --- /dev/null +++ b/msvc64/tools/depends/depends.vcproj @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msvc64/tools/depends/include/DEPENDENCYLIST.H b/msvc64/tools/depends/include/DEPENDENCYLIST.H new file mode 100644 index 00000000..4955f680 --- /dev/null +++ b/msvc64/tools/depends/include/DEPENDENCYLIST.H @@ -0,0 +1,57 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: DEPENDENCYLIST.H +//========================================== +#ifndef __DEPLIST_H__ +#define __DEPLIST_H__ + +#ifndef __MODULEFILEINFO_H__ +#include "modulefileinfo.h" +#endif + +enum errModuleDependencyList { errMDL_NO_ERROR, + errMDL_FILE_NOT_FOUND, + errMDL_NOT_PE_FILE, + errMDL_GENERAL_FAILURE }; + +// +// The MODULE_DEPENDENCY_LIST class creates a linked list of MODULE_FILE_INFO +// structures. In theory, this list will represent every executable file +// loaded by the Win32 loader when the executable is loaded. The class creates +// the list by starting with the file passed to the constructor, and recursing +// through all the import tables. +// +class MODULE_DEPENDENCY_LIST +{ + public: + + MODULE_DEPENDENCY_LIST( PSTR pszFileName ); + + ~MODULE_DEPENDENCY_LIST( ); + + BOOL IsValid( void ){ return (BOOL)(m_errorType == errMDL_NO_ERROR); } + + errModuleDependencyList GetErrorType( void ){ return m_errorType; } + + PSTR GetErrorString( void ); + + PMODULE_FILE_INFO GetNextModule( PMODULE_FILE_INFO p ); + + PMODULE_FILE_INFO LookupModule( PSTR pszFileName, BOOL fFullName ); + + unsigned GetNumberOfModules( void ){ return m_cModules; } + + protected: + + unsigned m_cModules; // Number of modules in list + + PMODULE_FILE_INFO m_pList; // Pointer to head of linked list + + // Recursively adds modules to the list + errModuleDependencyList AddModule( PSTR pszFullName ); + + errModuleDependencyList m_errorType; // Error type +}; + +#endif diff --git a/msvc64/tools/depends/include/EXEFILE.H b/msvc64/tools/depends/include/EXEFILE.H new file mode 100644 index 00000000..ae4ecba6 --- /dev/null +++ b/msvc64/tools/depends/include/EXEFILE.H @@ -0,0 +1,54 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: EXEFILE.H +//========================================== +#ifndef __EXEFILE_H__ +#define __EXEFILE_H__ + +#ifndef __MEMMAPFL_H__ +#include "memorymappedfile.h" +#endif + +// MakePtr is a macro that allows you to easily add to values (including +// pointers) together without dealing with C's pointer arithmetic. It +// essentially treats the last two parameters as DWORDs. The first +// parameter is used to typecast the result to the appropriate pointer type. +#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue)) + +enum EXE_TYPE { exeType_Invalid, exeType_DOS, exeType_NE, exeType_VXD, + exeType_LX, exeType_PE }; + +enum errEXE_FILE { errEXE_FILE_NO_ERROR, + errEXE_FILE_FILE_NOT_FOUND, + errEXE_FILE_INVALID_FORMAT }; + +class EXE_FILE : public MEMORY_MAPPED_FILE +{ + public: + + EXE_FILE( PSTR pszFileName ); + ~EXE_FILE( ){ ; } + + BOOL IsValid( void ){ return errMMF_NoError == m_errorType; } + + errEXE_FILE GetErrorType( void ){ return m_errorType; } + + DWORD GetSecondaryHeaderOffset( void ){ return m_secondaryHeaderOffset; } + + EXE_TYPE GetExeType( void ){ return m_exeType; } + + PSTR GetFileTypeDescription( void ); + + protected: + + errEXE_FILE m_errorType; + + private: + + LONG m_secondaryHeaderOffset; + EXE_TYPE m_exeType; + +}; + +#endif diff --git a/msvc64/tools/depends/include/MEMORYMAPPEDFILE.H b/msvc64/tools/depends/include/MEMORYMAPPEDFILE.H new file mode 100644 index 00000000..c0db0e2b --- /dev/null +++ b/msvc64/tools/depends/include/MEMORYMAPPEDFILE.H @@ -0,0 +1,35 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: MEMORYMAPPEDFILE.H +//========================================== +#ifndef __MEMMAPFL_H__ +#define __MEMMAPFL_H__ + +enum errMMF { errMMF_NoError, errMMF_FileOpen, + errMMF_FileMapping, errMMF_MapView }; + +class MEMORY_MAPPED_FILE +{ + public: + + MEMORY_MAPPED_FILE( PSTR pszFileName ); + ~MEMORY_MAPPED_FILE(void); + + PVOID GetBase( void ){ return m_pMemoryMappedFileBase; } + DWORD GetFileSize( void ){ return m_cbFile; } + BOOL IsValid( void ) { return errMMF_NoError == m_errCode; } + errMMF GetErrorType(){ return m_errCode; } + + private: + + HANDLE m_hFile; + HANDLE m_hFileMapping; // Handle of memory mapped file + PVOID m_pMemoryMappedFileBase; + DWORD m_cbFile; + errMMF m_errCode; +}; + +typedef MEMORY_MAPPED_FILE *PMEMORY_MAPPED_FILE; + +#endif diff --git a/msvc64/tools/depends/include/PEEXE.H b/msvc64/tools/depends/include/PEEXE.H new file mode 100644 index 00000000..95a9c95a --- /dev/null +++ b/msvc64/tools/depends/include/PEEXE.H @@ -0,0 +1,98 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: PEEXE.H +//========================================== +#ifndef __PEEXE_H__ +#define __PEEXE_H__ + +#ifndef __EXEFILE_H__ +#include "exefile.h" +#endif + +class PE_EXE : public EXE_FILE +{ + public: + + PE_EXE( PSTR pszFileName ); + ~PE_EXE( ){ } + + BOOL IsValid() { return m_pNtHdr ? TRUE : FALSE; } + + // For those who want at the data directly + PIMAGE_NT_HEADERS GetIMAGE_NT_HEADERS( void ) { return m_pNtHdr; } + + // IMAGE_FILE_HEADER fields + WORD GetMachine( void ) + { return m_pNtHdr->FileHeader.Machine; } + WORD GetNumberOfSections( void ) + { return m_pNtHdr->FileHeader.NumberOfSections; } + DWORD GetTimeDateStamp(void) + { return m_pNtHdr->FileHeader.TimeDateStamp; } + DWORD GetCharacteristics( void ) + { return m_pNtHdr->FileHeader.Characteristics; } + + // IMAGE_OPTIONAL_HEADER fields + DWORD GetSizeOfCode( void ) + { return m_pNtHdr->OptionalHeader.SizeOfCode; } + DWORD GetSizeOfInitializedData( void ) + { return m_pNtHdr->OptionalHeader.SizeOfInitializedData; } + DWORD GetSizeOfUninitializedData( void ) + { return m_pNtHdr->OptionalHeader.SizeOfUninitializedData; } + DWORD GetAddressOfEntryPoint( void ) + { return m_pNtHdr->OptionalHeader.AddressOfEntryPoint; } + DWORD GetBaseOfCode( void ) + { return m_pNtHdr->OptionalHeader.BaseOfCode; } +/* + DWORD GetBaseOfData( void ) + { return m_pNtHdr->OptionalHeader.BaseOfData; } +*/ + DWORD GetImageBase( void ) + { return m_pNtHdr->OptionalHeader.ImageBase; } + DWORD GetSectionAlignment( void ) + { return m_pNtHdr->OptionalHeader.SectionAlignment; } + DWORD GetFileAlignment( void ) + { return m_pNtHdr->OptionalHeader.FileAlignment; } + WORD GetMajorOperatingSystemVersion( void ) + { return m_pNtHdr->OptionalHeader.MajorOperatingSystemVersion; } + WORD GetMinorOperatingSystemVersion( void ) + { return m_pNtHdr->OptionalHeader.MinorOperatingSystemVersion; } + WORD GetMajorImageVersion( void ) + { return m_pNtHdr->OptionalHeader.MajorImageVersion; } + WORD GetMinorImageVersion( void ) + { return m_pNtHdr->OptionalHeader.MinorImageVersion; } + WORD GetMajorSubsystemVersion( void ) + { return m_pNtHdr->OptionalHeader.MajorSubsystemVersion; } + WORD GetMinorSubsystemVersion( void ) + { return m_pNtHdr->OptionalHeader.MinorSubsystemVersion; } +// DWORD GetWin32VersionValue( void ) +// { return m_pNtHdr->OptionalHeader.Win32VersionValue; } + DWORD GetSizeOfImage( void ) + { return m_pNtHdr->OptionalHeader.SizeOfImage; } + DWORD GetSizeOfHeaders( void ) + { return m_pNtHdr->OptionalHeader.SizeOfHeaders; } + WORD GetSubsystem( void ) + { return m_pNtHdr->OptionalHeader.Subsystem; } + DWORD GetSizeOfStackReserve( void ) + { return m_pNtHdr->OptionalHeader.SizeOfStackReserve; } + DWORD GetSizeOfStackCommit( void ) + { return m_pNtHdr->OptionalHeader.SizeOfStackCommit; } + DWORD GetSizeOfHeapReserve( void ) + { return m_pNtHdr->OptionalHeader.SizeOfHeapReserve; } + DWORD GetSizeOfHeapCommit( void ) + { return m_pNtHdr->OptionalHeader.SizeOfHeapCommit; } + + DWORD GetDataDirectoryEntryRVA( DWORD id ); + PVOID GetDataDirectoryEntryPointer( DWORD id ); + DWORD GetDataDirectoryEntrySize( DWORD id ); + + PVOID GetReadablePointerFromRVA( DWORD rva ); + + protected: + + DWORD RVAToFileOffset( DWORD rva ); + + PIMAGE_NT_HEADERS m_pNtHdr; +}; + +#endif diff --git a/msvc64/tools/depends/include/modulefileinfo.h b/msvc64/tools/depends/include/modulefileinfo.h new file mode 100644 index 00000000..27b17b59 --- /dev/null +++ b/msvc64/tools/depends/include/modulefileinfo.h @@ -0,0 +1,44 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: MODULEFILEINFO.H +//========================================== +#ifndef __MODULEFILEINFO_H__ +#define __MODULEFILEINFO_H__ + +class MODULE_DEPENDENCY_LIST; + +// +// This structure represents one executable file in a module dependency list. +// Both the base filename and the complete path are stored. +// +class MODULE_FILE_INFO +{ + public: + + MODULE_FILE_INFO( PSTR pszFileName ); + ~MODULE_FILE_INFO( void ){} + + PSTR GetBaseName( void ){ return m_szBaseName; } + PSTR GetFullName( void ){ return m_szFullName; } + + // For enumerating through the unlocatable imported modules + MODULE_FILE_INFO * GetNextNotFoundModule( MODULE_FILE_INFO * ); + + private: + + MODULE_FILE_INFO * m_pNext; + MODULE_FILE_INFO * m_pNotFoundNext; + + char m_szBaseName[MAX_PATH]; + char m_szFullName[MAX_PATH]; + + // And an unlocatable module to the "not found" list + void AddNotFoundModule( PSTR pszFileName ); + + friend class MODULE_DEPENDENCY_LIST; +}; + +typedef MODULE_FILE_INFO * PMODULE_FILE_INFO; + +#endif diff --git a/msvc64/tools/depends/src/DEPENDENCYLIST.CPP b/msvc64/tools/depends/src/DEPENDENCYLIST.CPP new file mode 100644 index 00000000..6b5a9042 --- /dev/null +++ b/msvc64/tools/depends/src/DEPENDENCYLIST.CPP @@ -0,0 +1,187 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: DEPENDENCYLIST.CPP +//========================================== +#include +#include +#pragma hdrstop +#include "peexe.h" +#include "dependencylist.h" + +MODULE_DEPENDENCY_LIST::MODULE_DEPENDENCY_LIST( PSTR pszFileName ) +{ + m_errorType = errMDL_GENERAL_FAILURE; + m_cModules = 0; + m_pList = 0; + + // Make a copy of the path that we can modify to get just the path portion + PSTR pszJustPath = _strdup( pszFileName ); + if ( !pszJustPath ) + return; + + BOOL fHasPath = FALSE; + PSTR pszEnd = strrchr( pszJustPath, '\\' ); + if ( pszEnd ) + { + *pszEnd = 0; /// Strip off the filename + fHasPath = TRUE; + } + + // + // If a path was part of the input filename, save the current directory, + // then switch to the new directory. + // + char szOriginalPath[MAX_PATH]; + if ( fHasPath ) + { + // This doesn't take into account "App_Paths"! + GetCurrentDirectory(MAX_PATH, szOriginalPath); // Save original dir + SetCurrentDirectory( pszJustPath ); // Switch to app's dir + } + + // + // recursively build the module list + // + m_errorType = AddModule( pszFileName ); + + if ( fHasPath ) // Set things back to the way they were + SetCurrentDirectory( szOriginalPath ); + + free( pszJustPath ); // Free the copy of the path that we allocated +} + + +MODULE_DEPENDENCY_LIST::~MODULE_DEPENDENCY_LIST( ) +{ + PMODULE_FILE_INFO pTemp; + + // Delete each MODULE_FILE_INFO structures in the regular linked list + pTemp = m_pList; + while ( pTemp ) + { + pTemp = m_pList->m_pNext; + + // Before we delete the module, delete each MODULE_FILE_INFO + // structures in the not found list + PMODULE_FILE_INFO pNotFound = m_pList->m_pNotFoundNext; + while ( pNotFound ) + { + pNotFound = m_pList->m_pNotFoundNext->m_pNotFoundNext; + delete m_pList->m_pNotFoundNext; + m_pList->m_pNotFoundNext = pNotFound; + } + + // Now it's OK to delete the module + delete m_pList; + m_pList = pTemp; + m_cModules--; + } + + m_pList = 0; +} + + + +PMODULE_FILE_INFO MODULE_DEPENDENCY_LIST::GetNextModule( PMODULE_FILE_INFO p ) +{ + // Returns the next module in the linked list of MODULE_FILE_INFO's + return p ? p->m_pNext : m_pList; +} + + +// Given the name of a file, find the MODULE_FILE_INFO structure that +// represents it. The fFullName parameter specifies whether the full path +// names or just the base file names will be compared. +PMODULE_FILE_INFO MODULE_DEPENDENCY_LIST::LookupModule( PSTR pszFileName, + BOOL fFullName ) +{ + PMODULE_FILE_INFO p = m_pList; // Start at the list head + + while ( p ) // While there's still entries in the list... + { + PSTR pszCompName = fFullName ? p->m_szFullName : p->m_szBaseName; + + if ( 0 == lstrcmpi( pszFileName, pszCompName ) ) + return p; + + p = p->m_pNext; + } + + return 0; +} + + +PSTR MODULE_DEPENDENCY_LIST::GetErrorString( void ) +{ + switch ( m_errorType ) + { + case errMDL_NO_ERROR: return "No error"; + case errMDL_FILE_NOT_FOUND: return "File not found"; + case errMDL_NOT_PE_FILE: return "Not a PE file"; + case errMDL_GENERAL_FAILURE:return "General failure"; + default: return ""; + } +} + + +// Adds a modules to the MODULE_FILE_INFO list. If the module imports other +// modules, this routine recurses to add them, and check their imports. +errModuleDependencyList +MODULE_DEPENDENCY_LIST::AddModule( PSTR pszFileName ) +{ + PE_EXE peFile( pszFileName ); // Get easy access to the executable + + if ( FALSE == peFile.IsValid() ) // A valid PE file??? + return (errModuleDependencyList)peFile.GetErrorType(); + + PMODULE_FILE_INFO pNew = new MODULE_FILE_INFO( pszFileName ); + if ( !pNew ) + return errMDL_GENERAL_FAILURE; + + pNew->m_pNext = m_pList; + m_pList = pNew; + + m_cModules++; + + // + // Now see if this module imports any other modules. If so, we need + // to recurse and add them as well. + // + if (0 == peFile.GetDataDirectoryEntrySize( IMAGE_DIRECTORY_ENTRY_IMPORT )) + return errMDL_NO_ERROR; + + // Make a pointer to the imports table + PIMAGE_IMPORT_DESCRIPTOR pImportDir; + pImportDir = (PIMAGE_IMPORT_DESCRIPTOR) + peFile.GetDataDirectoryEntryPointer(IMAGE_DIRECTORY_ENTRY_IMPORT); + if ( !pImportDir ) + return errMDL_NO_ERROR; + + // While there are still non-null IMAGE_IMPORT_DESCRIPTORs... + while ( pImportDir->Name ) + { + // Get a pointer to the imported module's base name + PSTR pszBaseName; + pszBaseName = (PSTR)peFile.GetReadablePointerFromRVA(pImportDir->Name); + if ( !pszBaseName ) + break; + + // Check to see if it's already in our list. Don't add again if so. + if ( 0 == LookupModule( pszBaseName, FALSE ) ) + { + // Search path supposedly has the same searching algorithm as + // the the Win32 loader... + char szPath[MAX_PATH]; + PSTR pszDontCare; + if ( SearchPath(0, pszBaseName, 0, MAX_PATH, szPath, &pszDontCare)) + AddModule( szPath ); + else + pNew->AddNotFoundModule( pszBaseName ); + } + + pImportDir++; // Advance to next imported module + } + + return errMDL_NO_ERROR; +} diff --git a/msvc64/tools/depends/src/EXEFILE.CPP b/msvc64/tools/depends/src/EXEFILE.CPP new file mode 100644 index 00000000..79e84491 --- /dev/null +++ b/msvc64/tools/depends/src/EXEFILE.CPP @@ -0,0 +1,72 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: EXEFILE.CPP +//========================================== +#include +#pragma hdrstop +#include "exefile.h" + +EXE_FILE::EXE_FILE( PSTR pszFileName ) : MEMORY_MAPPED_FILE( pszFileName ) +{ + m_errorType = errEXE_FILE_FILE_NOT_FOUND; + m_secondaryHeaderOffset = -1; // A bogus value to catch bugs + m_exeType = exeType_Invalid; + + if ( FALSE == MEMORY_MAPPED_FILE::IsValid() ) + return; // m_errorType already set to errEXE_FILE_FILE_NOT_FOUND + + // If we get here, the file exists, and was mapped. We're still not + // sure that it's a valid EXE though + m_errorType = errEXE_FILE_INVALID_FORMAT; + + if ( GetFileSize() < sizeof(IMAGE_DOS_HEADER) ) + return; + + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)GetBase(); + if ( IMAGE_DOS_SIGNATURE != pDosHdr->e_magic ) + return; + + // If we get here, it's at least a DOS 'MZ' file + m_errorType = errEXE_FILE_NO_ERROR; + + if ( pDosHdr->e_lfarlc < 0x40 ) // Theoretically, this field must be >= + { // 0x40 for it to be a non-DOS executable + m_exeType = exeType_DOS; + return; + } + + // Sanity check. Make sure the "new header" offset isn't past the end + // of the file + if ( pDosHdr->e_lfanew > (LONG)GetFileSize() ) + return; + + // Make a pointer to the secondary header + m_secondaryHeaderOffset = pDosHdr->e_lfanew; + PWORD pSecondHdr = MakePtr( PWORD, GetBase(), m_secondaryHeaderOffset ); + + // Decide what type of EXE, based on the start of the secondary header + switch ( *pSecondHdr ) + { + case IMAGE_OS2_SIGNATURE: m_exeType = exeType_NE; break; + case IMAGE_VXD_SIGNATURE: m_exeType = exeType_VXD; break; + case 0x4558: m_exeType = exeType_LX; break; // OS/2 2.X + } + + if ( *(PDWORD)pSecondHdr == IMAGE_NT_SIGNATURE ) + m_exeType = exeType_PE; +} + +PSTR EXE_FILE::GetFileTypeDescription( void ) +{ + // Returns a static string that describes what type this file is + switch ( m_exeType ) + { + case exeType_DOS: return "DOS"; + case exeType_NE: return "NE"; + case exeType_VXD: return "VXD"; + case exeType_LX: return "LX"; + case exeType_PE: return "PE"; + default: return "Invalid"; + } +} diff --git a/msvc64/tools/depends/src/MEMORYMAPPEDFILE.CPP b/msvc64/tools/depends/src/MEMORYMAPPEDFILE.CPP new file mode 100644 index 00000000..89237bbc --- /dev/null +++ b/msvc64/tools/depends/src/MEMORYMAPPEDFILE.CPP @@ -0,0 +1,75 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: MEMORYMPAPPEDFILE.CPP +//========================================== +#include +#pragma hdrstop +#include "memorymappedfile.h" + +MEMORY_MAPPED_FILE::MEMORY_MAPPED_FILE( PSTR pszFileName ) +{ + // + // Given a filename, the constructor opens a file handle, creates a file + // mapping, and maps the entire file into memory. + // + m_hFile = INVALID_HANDLE_VALUE; + m_hFileMapping = 0; + m_pMemoryMappedFileBase = 0; + m_cbFile = 0; + m_errCode = errMMF_FileOpen; // Initial error code: not found + + // First get a file handle + m_hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)0); + + if ( m_hFile == INVALID_HANDLE_VALUE ) + { + m_errCode = errMMF_FileOpen; + return; + } + + m_cbFile = ::GetFileSize( m_hFile, 0 ); + + // Now, create a file mapping + m_hFileMapping = CreateFileMapping(m_hFile,NULL, PAGE_READONLY, 0, 0,NULL); + if ( m_hFileMapping == 0 ) + { + // Oops. Something went wrong. Clean up. + CloseHandle(m_hFile); + m_hFile = INVALID_HANDLE_VALUE; + m_errCode = errMMF_FileMapping; + return; + } + + m_pMemoryMappedFileBase = (PCHAR)MapViewOfFile( m_hFileMapping, + FILE_MAP_READ, 0, 0, 0); + + if ( m_pMemoryMappedFileBase == 0 ) + { + // Oops. Something went wrong. Clean up. + CloseHandle(m_hFileMapping); + m_hFileMapping = 0; + CloseHandle(m_hFile); + m_hFile = INVALID_HANDLE_VALUE; + m_errCode = errMMF_MapView; + return; + } + + m_errCode = errMMF_NoError; +} + +MEMORY_MAPPED_FILE::~MEMORY_MAPPED_FILE(void) +{ + // Clean up everything that was created by the constructor + if ( m_pMemoryMappedFileBase ) + UnmapViewOfFile( m_pMemoryMappedFileBase ); + + if ( m_hFileMapping ) + CloseHandle( m_hFileMapping ); + + if ( m_hFile != INVALID_HANDLE_VALUE ) + CloseHandle( m_hFile ); + + m_errCode = errMMF_FileOpen; +} diff --git a/msvc64/tools/depends/src/PEEXE.CPP b/msvc64/tools/depends/src/PEEXE.CPP new file mode 100644 index 00000000..56f2f29c --- /dev/null +++ b/msvc64/tools/depends/src/PEEXE.CPP @@ -0,0 +1,99 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: PEEXE.CPP +//========================================== +#include +#include +#pragma hdrstop +#include "peexe.h" + +PE_EXE::PE_EXE( PSTR pszFileName ) : EXE_FILE( pszFileName ) +{ + m_pNtHdr = 0; + + if ( FALSE == EXE_FILE::IsValid() ) + return; + + // It's an EXE, but is it a *PE* file??? If not, set code and bail + if ( GetExeType() != exeType_PE ) + { + m_errorType = errEXE_FILE_INVALID_FORMAT; + return; + } + + m_pNtHdr = MakePtr(PIMAGE_NT_HEADERS,GetBase(),GetSecondaryHeaderOffset()); +} + +DWORD PE_EXE::GetDataDirectoryEntryRVA( DWORD id ) +{ + // Given a IMAGE_DIRECTORY_ENTRY_XXX value (see WINNT.H), retrive the + // RVA stored in the corresponding slot + + if ( id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ) + return (DWORD)-1; + + return m_pNtHdr->OptionalHeader.DataDirectory[id].VirtualAddress; +} + +PVOID PE_EXE::GetDataDirectoryEntryPointer( DWORD id ) +{ + // Given a IMAGE_DIRECTORY_ENTRY_XXX value (see WINNT.H), return a pointer + // to memory that corresponds to the RVA in the specified slot. + + if ( id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ) + return (PVOID)-1; + + DWORD va = m_pNtHdr->OptionalHeader.DataDirectory[id].VirtualAddress; + + if ( !va ) // Return 0 if the RVA is 0 + return 0; + + return GetReadablePointerFromRVA( va ); +} + +DWORD PE_EXE::GetDataDirectoryEntrySize( DWORD id ) +{ + // Given a IMAGE_DIRECTORY_ENTRY_XXX value (see WINNT.H), retrive the + // size value stored in the corresponding slot + + if ( id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ) + return (DWORD)-1; + + return m_pNtHdr->OptionalHeader.DataDirectory[id].Size; +} + +PVOID PE_EXE::GetReadablePointerFromRVA( DWORD rva ) +{ + // Given an RVA, translate it into a pointer within our linear memory + // mapping for the executable. + + DWORD fileOffset = RVAToFileOffset( rva ); + if ( (DWORD)-1 == fileOffset ) + return 0; + + return MakePtr( PVOID, GetBase(), fileOffset ); +} + +DWORD PE_EXE::RVAToFileOffset( DWORD rva ) +{ + // Given an RVA, figure out which section encompasses it. Next, using + // the PointerToRawData field for the found section, return an actual + // file offset that corresponds to the RVA + + PIMAGE_SECTION_HEADER pSectHdr = IMAGE_FIRST_SECTION( m_pNtHdr ); + + for ( unsigned i = 0; i < GetNumberOfSections(); i++, pSectHdr++ ) + { + DWORD cbMaxOnDisk + = min( pSectHdr->Misc.VirtualSize, pSectHdr->SizeOfRawData ); + + DWORD startSectRVA = pSectHdr->VirtualAddress; + DWORD endSectRVA = startSectRVA + cbMaxOnDisk; + + if ( (rva >= startSectRVA) && (rva < endSectRVA) ) + return pSectHdr->PointerToRawData + (rva - startSectRVA); + } + + return (DWORD)-1; // RVA not found in the section table... Ooops! +} diff --git a/msvc64/tools/depends/src/depends.cpp b/msvc64/tools/depends/src/depends.cpp new file mode 100644 index 00000000..f587eea6 --- /dev/null +++ b/msvc64/tools/depends/src/depends.cpp @@ -0,0 +1,321 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: DEPENDS.CPP +//========================================== +#include +#include +#include "dependencylist.h" +#include "peexe.h" + +//============================== Variables =============================== +char g_szHelpSyntax[] = +"DEPENDS - Matt Pietrek, 1997, for MSJ\n" +"Syntax: DEPENDS [args] \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 ) { + // keep quiet about these guys - they're build/compiler dependant + 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; +} diff --git a/msvc64/tools/depends/src/modulefileinfo.cpp b/msvc64/tools/depends/src/modulefileinfo.cpp new file mode 100644 index 00000000..ac82223d --- /dev/null +++ b/msvc64/tools/depends/src/modulefileinfo.cpp @@ -0,0 +1,42 @@ +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, Feb 1997 +// FILE: MODULEFILEINFO.CPP +//========================================== +#include +#include "modulefileinfo.h" + +MODULE_FILE_INFO::MODULE_FILE_INFO( PSTR pszFileName ) +{ + m_pNext = 0; + m_pNotFoundNext = 0; + + // Find the last '\\' to obtain a pointer to just the base filename part + PSTR pszBaseName = strrchr( pszFileName, '\\' ); + if ( pszBaseName ) // We found a path, so advance to the base filename + pszBaseName++; + else + pszBaseName = pszFileName; // No path. Use the same name for both + + // Initialize the new MODULE_FILE_INFO, and stick it at the head + // of the list. + lstrcpyn( m_szFullName, pszFileName, sizeof(m_szFullName) ); + lstrcpyn( m_szBaseName, pszBaseName, sizeof(m_szBaseName) ); + +} + +void MODULE_FILE_INFO::AddNotFoundModule( PSTR pszFileName ) +{ + PMODULE_FILE_INFO pNew = new MODULE_FILE_INFO( pszFileName ); + + pNew->m_pNotFoundNext = m_pNotFoundNext; + m_pNotFoundNext = pNew; +} + +MODULE_FILE_INFO * MODULE_FILE_INFO::GetNextNotFoundModule( PMODULE_FILE_INFO p) +{ + PMODULE_FILE_INFO pNext = p ? p->m_pNotFoundNext : m_pNotFoundNext; + + return pNext; +} + diff --git a/msvc64/tools/depends/stdafx.cpp b/msvc64/tools/depends/stdafx.cpp new file mode 100644 index 00000000..061fd2f1 --- /dev/null +++ b/msvc64/tools/depends/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Depends2.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/msvc64/tools/depends/stdafx.h b/msvc64/tools/depends/stdafx.h new file mode 100644 index 00000000..47a0d025 --- /dev/null +++ b/msvc64/tools/depends/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/msvc64/tools/depends/targetver.h b/msvc64/tools/depends/targetver.h new file mode 100644 index 00000000..a38195a4 --- /dev/null +++ b/msvc64/tools/depends/targetver.h @@ -0,0 +1,13 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif +