Registriert seit: 29. Mai 2002
37.621 Beiträge
Delphi 2006 Professional
|
Re: Compilierdatum
11. Nov 2003, 16:28
Code von Nico:
Delphi-Quellcode:
function GetImageLinkTimeStamp( const FileName: string) : DWORD;
const
INVALID_SET_FILE_POINTER = DWORD(-1) ;
BorlandMagicTimeStamp = $2A425E19; // Delphi 4-6 (and above?)
FileTime1970: TFileTime = ( dwLowDateTime:$D53E8000; dwHighDateTime:$019DB1DE) ;
type
PImageSectionHeaders = ^TImageSectionHeaders;
TImageSectionHeaders = array [ Word] of TImageSectionHeader;
type
PImageResourceDirectory = ^TImageResourceDirectory;
TImageResourceDirectory = packed record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
NumberOfNamedEntries: Word;
NumberOfIdEntries: Word;
end;
var
FileHandle: THandle;
BytesRead: DWORD;
ImageDosHeader: TImageDosHeader;
ImageNtHeaders: TImageNtHeaders;
SectionHeaders: PImageSectionHeaders;
Section: Word;
ResDirRVA: DWORD;
ResDirSize: DWORD;
ResDirRaw: DWORD;
ResDirTable: TImageResourceDirectory;
FileTime: TFileTime;
begin
Result := 0;
// Open file for read access
FileHandle := CreateFile( PChar( FileName) , GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, 0, 0) ;
if ( FileHandle < > INVALID_HANDLE_VALUE) then
try
// Read MS-DOS header to get the offset of the PE32 header
// (not required on WinNT based systems - but mostly available)
if not ReadFile( FileHandle, ImageDosHeader, SizeOf( TImageDosHeader) ,
BytesRead, nil) or ( BytesRead < > SizeOf( TImageDosHeader) ) or
( ImageDosHeader.e_magic < > IMAGE_DOS_SIGNATURE) then
begin
ImageDosHeader._lfanew := 0;
end;
// Read PE32 header (including optional header
if ( SetFilePointer( FileHandle, ImageDosHeader._lfanew, nil, FILE_BEGIN) =
INVALID_SET_FILE_POINTER) then
begin
Exit;
end;
if not( ReadFile( FileHandle, ImageNtHeaders, SizeOf( TImageNtHeaders) ,
BytesRead, nil) and ( BytesRead = SizeOf( TImageNtHeaders) ) ) then
begin
Exit;
end;
// Validate PE32 image header
if ( ImageNtHeaders.Signature < > IMAGE_NT_SIGNATURE) then
begin
Exit;
end;
// Seconds since 1970 (UTC)
Result := ImageNtHeaders.FileHeader.TimeDateStamp;
// Check for Borland's magic value for the link time stamp
// (we take the time stamp from the resource directory table)
if ( ImageNtHeaders.FileHeader.TimeDateStamp = BorlandMagicTimeStamp) then
with ImageNtHeaders, FileHeader, OptionalHeader do
begin
// Validate Optional header
if ( SizeOfOptionalHeader < IMAGE_SIZEOF_NT_OPTIONAL_HEADER) or
( Magic < > IMAGE_NT_OPTIONAL_HDR_MAGIC) then
begin
Exit;
end;
// Read section headers
SectionHeaders :=
GetMemory( NumberOfSections * SizeOf( TImageSectionHeader) ) ;
if Assigned( SectionHeaders) then
try
if ( SetFilePointer( FileHandle,
SizeOfOptionalHeader - IMAGE_SIZEOF_NT_OPTIONAL_HEADER, nil,
FILE_CURRENT) = INVALID_SET_FILE_POINTER) then
begin
Exit;
end;
if not( ReadFile( FileHandle, SectionHeaders^, NumberOfSections *
SizeOf( TImageSectionHeader) , BytesRead, nil) and ( BytesRead =
NumberOfSections * SizeOf( TImageSectionHeader) ) ) then
begin
Exit;
end;
// Get RVA and size of the resource directory
with DataDirectory[ IMAGE_DIRECTORY_ENTRY_RESOURCE] do
begin
ResDirRVA := VirtualAddress;
ResDirSize := Size;
end;
// Search for section which contains the resource directory
ResDirRaw := 0;
for Section := 0 to NumberOfSections - 1 do
with SectionHeaders[ Section] do
if ( VirtualAddress < = ResDirRVA) and
( VirtualAddress + SizeOfRawData > = ResDirRVA + ResDirSize) then
begin
ResDirRaw := PointerToRawData - ( VirtualAddress - ResDirRVA) ;
Break;
end;
// Resource directory table found?
if ( ResDirRaw = 0) then
begin
Exit;
end;
// Read resource directory table
if ( SetFilePointer( FileHandle, ResDirRaw, nil, FILE_BEGIN) =
INVALID_SET_FILE_POINTER) then
begin
Exit;
end;
if not( ReadFile( FileHandle, ResDirTable,
SizeOf( TImageResourceDirectory) , BytesRead, nil) and
( BytesRead = SizeOf( TImageResourceDirectory) ) ) then
begin
Exit;
end;
// Convert from DosDateTime to SecondsSince1970
if DosDateTimeToFileTime( HiWord( ResDirTable.TimeDateStamp) ,
LoWord( ResDirTable.TimeDateStamp) , FileTime) then
begin
// FIXME: Borland's linker uses the local system time
// of the user who linked the executable image file.
// (is that information anywhere?)
Result := ( ULARGE_INTEGER( FileTime) .QuadPart -
ULARGE_INTEGER( FileTime1970) .QuadPart) div 10000000;
end;
finally
FreeMemory( SectionHeaders) ;
end;
end;
finally
CloseHandle( FileHandle) ;
end;
end;
Rückgabewert ist ein Unix TimeStamp.
Michael Ein Teil meines Codes würde euch verunsichern.
|
|
Zitat
|