![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Определить тип приложения [D7, Win95/98, WinME, NT4, Win2k, WinXP]
-=GaLaN=- © (2005-05-27 01:03:00)У меня есть путь к файлу exe. Как можно определить тип приложения - консольное ли оно, DOS, Win32?
Digitman (2005-06-06 08:16:00) [1]
> пытаюсь открыть с помощью других программ
каких ?
Оля (2005-06-06 02:26:00) [2]Удалено модератором
Defunct (2005-05-27 15:53:00) [3]-=GaLaN=- (27.05.05 15:30) [73]
Вам забесплатно дали функцию [60] и описание констант и структур данных к ней - [61].
Остальные модули Игорь не считает нужным выкладывать на всеобщее обозрение, их там требуется ни много, ни мало все с тэгом HS. На то есть его право.
Defunct (2005-05-27 15:47:00) [4]wal © (27.05.05 14:03) [68]
ну и что с того?
По расширению (COM/EXE) определяется, что надо запустить загрузчик PE файла.
Далее,
Загрузчик открыл файл, нашел там 'MZ' и начал подготавливать этот файл к запуску как EXE (а не как ком, хоть файл и с расширением COM).
Вот лучше проведите другой эксперимент, частично затрите заголовок EXE файла и попробуйте его запустить.
Игорь Шевченко (2005-05-27 15:47:00) [5]-=GaLaN=- (27.05.05 15:30) [73]
Я вообще-то в посте написал, что это "кусок программы". И не рассчитывал на то, что кто-то компилировать мой код. Там еще нескольких юниов не хватает. Надо кодом обычно рекомендуется думать, смотреть, как реализованы те или иные идеи, применять эту реализацию к своему коду.
-=GaLaN=- (2005-05-27 15:30:00) [6]2Просто Джо:
Спасибо, работает неплохо на графических и консольных Win32, но... на DOS-приложениях функция скопытивается и выдаёт либо Unknown, либо Ambigous - и при том, что опциональный заголовок отсутствует, функция считает, будто он есть.
А Игорь Шевченко респект! У меня только маааленький вопросик - а где взять HSDosImage? Не компилит за отсутствием HSDosImage.dcu. :(
2All:
Честно говоря, нет смысла забирать com файлы. Пользователи моей программы будут сами себе злобные буратины, если начнут переименовывать всякие com в exe. Если консольность, графичность или dos'ность приложения не подтвердится, то его просто CreateProcess'ну - пускай система сама разбирается что к чему...
Eraser (2005-05-27 14:56:00) [7]wal © (27.05.05 14:53) [71]
Ну тогда единственный способ узнать тип файла - отослать его по почте в M$ дождаться их ответа.
wal (2005-05-27 14:53:00) [8]
> [69] Eraser © (27.05.05 14:39)
> Если заголовка нету, это com файл.
Или бессмысленный набор байтов.
> Чаще всего в таких файлах первая команда - безусловный переход.
Во первых не всегда, а во вторых это и есть анализ кода, о котором я говорил ;)
С уважением.
Eraser (2005-05-27 14:40:00) [9]Игорь Шевченко ©
Мда - весч впчатляет. Респект.
Eraser (2005-05-27 14:39:00) [10]wal © (27.05.05 14:03) [68]
Если заголовка нету, это com файл. Чаще всего в таких файлах первая команда - безусловный переход.
wal (2005-05-27 14:03:00) [11]
> [67] Defunct © (27.05.05 13:21)
1. Возьми в C:\WINNT\system32\ файл command.com
2. Скопируй его куда-нибудь.
3. Запусти и убедись, что работает
4. Переименуй его в command.exe
5. Запусти и убедись, что работает
6. Посмотри на его "изнутри" и убедись, что никаких MZ- и тем более PE-заголовка там нет.
7. А теперь на основании расширения (.exe) и заголовка (которого нет) определи однозначно, что это исполняемый файл.
С уважением.
Defunct (2005-05-27 13:21:00) [12]wal © (27.05.05 11:56) [66]
Как раз по расширению и заголовку тип файла определяется однозначно. Иначе бы Windows и гроша ломаного не стоила.
Анализом кода только антивирусы занимаются.
wal (2005-05-27 11:56:00) [13]
> [65] Digitman © (27.05.05 11:11)
Дак я об том и говорю, что однозначно определить только по расширению и заголовку программа это или нет без анализа кода невозможно. Так что времена хоть и "злые", но ничего существенно неизменилось. Только не виснет вся система, а вирт. машина ошибку выдает.
С уважением.
Digitman (2005-05-27 11:11:00) [14]
> wal © (27.05.05 09:56) [56]
> wal © (27.05.05 09:56) [56]
> В старые добрые времена
нынешние времена злые пошли .. "шаг влево, шаг вправо - попытка к побегу, расстрел на месте" )
иду я, к примеру, в папку c:\winnt\system32 и рассматриваю в лупу известный edit.com ... вижу там 'MZ' - значит, явно не com-формат ... но системе это по барабану - на мое требование запуска задачи система тут же стартует экземпляр виртуальной ДОС-машины, а та уже сама разбирается, как его, этот исп.файл, запустить - по EXE- или СОМ-соглашениям...
логика здесь, очевидно, такова :
- система, обнаружив что файл имеет одно из расширений - ЕХЕ или СОМ, шарит по заголовкам
- обнаружив в корректных заголовках все признаки того, что файл есть образ исполняемого Win32-модуля, система делает попытку старта соответствующего Win32-процесса
- обнаружив корректный ДОС-заголовок, но не обнаружив признаков образа исполняемого Win32-модуля, либо не обнаружив вообще никаких заголовков, система подразумевает что дан.файл является образом ДОС16-модуля и стартует новый процесс вирт. ДОС-машины, которая уже собственно и пытается исполнить код ДОС-задачи
- если файл в реальности не содержит ДОС16-образ (например, в файле некая абракадабра, внешне похожая на СОМ-файл, но при выполнении кода которого как правило возникнет искл.ситуация), вирт.машина сообщает об этом, и после подтверждения юзера система немедля снимает процесс вирт.машины с выполнения
Просто Джо (2005-05-27 10:59:00) [15]Игорь Шевченко ©
Спасибо, проделанная работа действительно впечатляет. Думаю, что автору топика это подойдет в самый раз. Да и я себе в заначку положу, на досуге поковыряюсь :)
Игорь Шевченко (2005-05-27 10:46:00) [16]Просто Джо © (27.05.05 10:18) [59]
procedure TPEImage.Load(Mapper: THSFileMapper);
begin
inherited;
FNtHeaders := PIMAGE_NT_HEADERS(Mapper.Map + DosHeader^._lfanew);
LoadSections (Mapper);
LoadModuleReferences (Mapper);
end;
procedure TPEImage.LoadDelayImports;
var
RawOffset: Integer;
ImportDescriptor: PDelayLoadImportTableItem;
DllName: string;
PFunctionsAddress: PDWORD;
ImportAddress: DWORD;
begin
with NtHeaders^.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT] do begin
if (VirtualAddress = 0) or (Size = 0) then
Exit;
RawOffset := RawAddress(VirtualAddress);
end;
ImportDescriptor := PDelayLoadImportTableItem(RawData + RawOffset);
while ImportDescriptor^.DllName <> 0 do begin
if ImportDescriptor^.Flags = 1 then begin
RawOffset := RawAddress(ImportDescriptor^.DllName);
if RawOffset <> 0 then
DllName := UpperCase(StrPas(RawData + RawOffset));
RawOffset := RawAddress(ImportDescriptor^.ImportNameTable);
PFunctionsAddress := PDWORD(RawData + RawOffset);
while PFunctionsAddress^ <> 0 do begin
ImportAddress := PFunctionsAddress^;
FDelayImports.Add(GetImportedFunctionName(DllName, ImportAddress));
Inc(PFunctionsAddress);
end;
end;
Inc(ImportDescriptor);
end;
end;
procedure TPEImage.LoadImports;
var
RawOffset: Integer;
ImportDescriptor: PIMAGE_IMPORT_DESCRIPTOR;
DllName: string;
PFunctionsAddress: PDWORD;
ImportAddress: DWORD;
begin
with NtHeaders^.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT] do begin
if (VirtualAddress = 0) or (Size = 0) then
Exit;
RawOffset := RawAddress(VirtualAddress);
end;
ImportDescriptor := PIMAGE_IMPORT_DESCRIPTOR(RawData + RawOffset);
while ImportDescriptor^.Name <> 0 do begin
RawOffset := RawAddress(ImportDescriptor^.Name);
if RawOffset <> 0 then
DllName := UpperCase(StrPas(RawData + RawOffset));
if ImportDescriptor^.Characteristics = 0 then
RawOffset := RawAddress(ImportDescriptor^.FirstThunk)
else
RawOffset := RawAddress(ImportDescriptor^.Characteristics);
PFunctionsAddress := PDWORD(RawData + RawOffset);
while PFunctionsAddress^ <> 0 do begin
ImportAddress := PFunctionsAddress^;
FImports.Add(GetImportedFunctionName(DllName, ImportAddress));
Inc(PFunctionsAddress);
end;
Inc(ImportDescriptor);
end;
end;
procedure TPEImage.LoadModuleReferences(Mapper: THSFileMapper);
var
IAddr: DWORD;
PImport: PIMAGE_IMPORT_DESCRIPTOR;
PModName: PChar;
begin
with NtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] do
if Size <> 0 then begin
IAddr := RawAddress(VirtualAddress);
PImport := PIMAGE_IMPORT_DESCRIPTOR(Mapper.Map + IAddr);
while PImport^.Name <> 0 do begin
PModName := Mapper.Map + RawAddress(PImport^.Name);
FModuleReferences.Add(PModName);
FImportLibraries.Add(UpperCase(PModName));
Inc(PImport);
end;
end;
end;
procedure TPEImage.LoadSections(Mapper: THSFileMapper);
var
PSection: PImageSectionHeader;
I: Integer;
begin
PSection := PImageSectionHeader(DWORD(@(NtHeaders^.OptionalHeader)) +
NtHeaders^.FileHeader.SizeOfOptionalHeader);
for I:=1 to NtHeaders^.FileHeader.NumberOfSections do begin
FSections.Add (PSection);
Inc(PSection);
end;
end;
function TPEImage.RawAddress(VirtualAddress: Cardinal): Cardinal;
var
I: Integer;
Position: Cardinal;
begin
Result := 0;
for I := 0 to Pred(FSections.Count) do
if (Sections[I].VirtualAddress <= VirtualAddress) and
(VirtualAddress < Sections[I].VirtualAddress +
Sections[I].SizeOfRawData) then begin
Position := VirtualAddress - Sections[I].VirtualAddress;
Result := Sections[I].PointerToRawData + Position;
Break;
end;
end;
end.
Кусок программы, анализирующей исполняемые файлы.
Игорь Шевченко (2005-05-27 10:44:00) [17]Просто Джо © (27.05.05 10:18) [59]
implementation
{ TPEImage }
constructor TPEImage.Create(const FileName: string);
begin
inherited Create(FileName);
FSections := TList.Create;
FModuleReferences := TStringList.Create;
FImportLibraries := TStringList.Create;
with FImportLibraries do begin
Sorted := true;
Duplicates := dupIgnore;
end;
FMapper := THSFileMapper.Create (FileName);
Load (FMapper);
end;
destructor TPEImage.Destroy;
begin
FMapper.Free;
FImportLibraries.Free;
FModuleReferences.Free;
FSections.Free;
FImports.Free;
FDelayImports.Free;
inherited;
end;
function TPEImage.EpCode: PByteArray;
var
EpAddr: DWORD;
begin
EpAddr := RawAddress(NtHeaders^.OptionalHeader.AddressOfEntryPoint);
if EpAddr <> 0 then
Result := PByteArray(FMapper.Map + EpAddr)
else
Result := nil;
end;
function TPEImage.FindSection(
VirtualAddress: Cardinal): PImageSectionHeader;
var
I: Integer;
begin
Result := nil;
for I := 0 to Pred(FSections.Count) do
if (Sections[I].VirtualAddress <= VirtualAddress) and
(VirtualAddress < Sections[I].VirtualAddress +
Sections[I].SizeOfRawData) then begin
Result := Sections[I];
Break;
end;
end;
function TPEImage.GetDelayImports: TStrings;
begin
if not Assigned(FDelayImports) then begin
FDelayImports := TStringList.Create;
FDelayImports.Sorted := true;
FDelayImports.Duplicates := dupIgnore;
LoadDelayImports;
end;
Result := FDelayImports;
end;
function TPEImage.GetFullImportedFunctionName(const DllName: string;
IATEntryRVA: DWORD): string;
begin
if (IATEntryRVA and $80000000) <> 0 then
Result := Format('%s.%d', [ChangeFileExt(DllName, ''),
(IATEntryRVA and $7FFFFFFF)])
else
Result := Format('%s.%s', [ChangeFileExt(DllName, ''),
GetImportedNameFromIATEntry(IATEntryRVA, true)]);
end;
function TPEImage.GetImportedFunctionName(const DllName: string;
IATEntryRVA: DWORD): string;
begin
if (IATEntryRVA and $80000000) <> 0 then
Result := Format('%s.%d', [ChangeFileExt(DllName, ''),
(IATEntryRVA and $7FFFFFFF)])
else
Result := Format('%s.%s', [ChangeFileExt(DllName, ''),
GetImportedNameFromIATEntry(IATEntryRVA)]);
end;
function TPEImage.GetImportedNameFromIATEntry(IATEntryRVA: DWORD;
FullInfo: Boolean): string;
var
RawOffset: DWORD;
begin
RawOffset := RawAddress (IATEntryRVA);
Result := StrPas(RawData + RawOffset + SizeOf(Word));
if FullInfo then
Result := Format('%s (Hint=%.4x)', [Result,
PIMAGE_IMPORT_BY_NAME(RawData + RawOffset)^.Hint]);
end;
function TPEImage.GetImports: TStrings;
begin
if not Assigned(FImports) then begin
FImports := TStringList.Create;
FImports.Sorted := true;
FImports.Duplicates := dupIgnore;
LoadImports;
end;
Result := FImports;
end;
function TPEImage.GetSection(I: Integer): PImageSectionHeader;
begin
Result := PImageSectionHeader(FSections[I]);
end;
function TPEImage.GetSubSystem: THSSubSystem;
begin
with NtHeaders.OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] do
if (VirtualAddress <> 0) and (Size <> 0) then
Result := hsssDotNet
else
case NtHeaders^.OptionalHeader.Subsystem of
IMAGE_SUBSYSTEM_WINDOWS_GUI:
Result := hsssGUI32;
IMAGE_SUBSYSTEM_WINDOWS_CUI:
Result := hsssCon32;
IMAGE_SUBSYSTEM_NATIVE:
Result := hsssNative;
else
Result := hsssUnknown;
end;
end;
Игорь Шевченко (2005-05-27 10:43:00) [18]Просто Джо © (27.05.05 10:18) [59]
{
Модуль: HSPEImage
Описание: Класс для образа 32-битного исполняемого файла Windows
Автор: Игорь Шевченко
Дата создания: 23.02.2003
История изменений:
03.04.2003 Добавлен метод получения имени импортируемой функции по адресу
в таблице импорта.
Добавлен метод получения импортируемых функций.
04.04.2003 Добавлено описание для структур .Net. При описании использовалась
статья Павла Румянцева в RSDN Magazine №2 2003.
}
unit HSPEImage;
interface
uses
Windows, HSDosImage, HSFileMapper, Classes, SysUtils, HSImageUtils,
HSObjectList;
type
PDwordArray = ^TDwordArray;
TDwordArray = array[0..8191] of DWORD;
USHORT = Word;
PIMAGE_NT_HEADERS = PImageNtHeaders;
PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
IMAGE_IMPORT_DESCRIPTOR = packed record
Characteristics: Cardinal; // 0 for terminating null import descriptor
// RVA to original unbound IAT (PIMAGE_THUNK_DATA)
TimeDateStamp: Cardinal; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
ForwarderChain: Cardinal; // -1 if no forwarders
Name: Cardinal;
FirstThunk: Cardinal; // RVA to IAT (if bound this IAT has actual addresses)
end;
IMAGE_IMPORT_BY_NAME = packed record
Hint: WORD;
Name: Char;
end;
PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME;
TDelayLoadImportTableItem = packed record
Flags: LongInt;
DllName: Cardinal;
Handle: Cardinal; //RVA to DATA segment
EpAddresses: Cardinal; //Array of entry point addresses for this library
ImportNameTable: Cardinal; //RVA of Module name table
Reserved2: Cardinal; //Don't know
Reserved3: Cardinal; //Don't know
Reserved4: Cardinal; //Don't know
end;
PDelayLoadImportTableItem = ^TDelayLoadImportTableItem;
TDelayLoadImportTableItemArray = array [0..1024] of TDelayLoadImportTableItem;
PDelayLoadImportTableItemArray = ^TDelayLoadImportTableItemArray;
PDelayLoadEntryItem = PIMAGE_IMPORT_BY_NAME;
IMAGE_COR20_HEADER = packed record
//Информация о версии
cb: ULONG;
MajorRuntimeVersion: USHORT;
MinorRuntimeVersion: USHORT;
//Таблицы метаданных, флаги и информация о точке входа
MetaData: IMAGE_DATA_DIRECTORY;
Flags: ULONG;
EntryPointToken: ULONG;
Resources: IMAGE_DATA_DIRECTORY;
StrongNameSignature: IMAGE_DATA_DIRECTORY;
CodeManagerTable: IMAGE_DATA_DIRECTORY;
VTableFixups: IMAGE_DATA_DIRECTORY;
ExportAddressTableJumps: IMAGE_DATA_DIRECTORY;
// Информация о прекомпилированном образе файла (только для внутреннего
// использования)
ManagedNativeHeader: IMAGE_DATA_DIRECTORY;
end;
PIMAGE_COR20_HEADER = ^IMAGE_COR20_HEADER;
// метадата .Net
STORAGESIGNATURE = packed record
lSignature: ULONG; // "Магическая" сигнатура ($424A5342)
iMajorVer: USHORT; // Старшая часть версии файла
iMinorVer: USHORT; // Младшая часть версии файла
iExtraData: ULONG; // Смещение следующей структуры с информацией
iVersionString: ULONG; // длина строки с названием версии
pVersion: array[0..0] of Char; //строка, содержащая название версии,
// длина определяется полем iVersionString
end;
PSTORAGESIGNATURE = ^STORAGESIGNATURE;
STORAGEHEADER = packed record
fFlags: BYTE; // Флаги STGHDR_
Pad: BYTE;
iStreams: USHORT; // Число стримов
end;
PSTORAGEHEADER = ^STORAGEHEADER;
STORAGESTREAM = packed record
iOffset: ULONG;
iSize: ULONG;
rcName: array[0..0] of Char;
end;
PSTORAGESTREAM = ^STORAGESTREAM;
TPEImage = class(TDosImage)
private
FMapper: THSFileMapper;
FModuleReferences: TStrings;
FImportLibraries: TStringList;
FNtHeaders: PIMAGE_NT_HEADERS;
FSections: TList;
FImports: TStringList;
FDelayImports: TStringList;
function GetSection(I: Integer): PImageSectionHeader;
procedure LoadSections (Mapper: THSFileMapper);
procedure LoadModuleReferences (Mapper: THSFileMapper);
function GetImportedNameFromIATEntry (IATEntryRVA: DWORD;
FullInfo: Boolean = false): string;
function GetSubSystem: THSSubSystem;
function GetImports: TStrings;
procedure LoadImports;
procedure LoadDelayImports;
function GetDelayImports: TStrings;
protected
procedure Load (Mapper: THSFileMapper); override;
public
constructor Create (const FileName: string); override;
destructor Destroy; override;
function EpCode: PByteArray; override;
function RawAddress (VirtualAddress: Cardinal): Cardinal;
function GetFullImportedFunctionName(const DllName: string;
IATEntryRVA: DWORD): string;
function GetImportedFunctionName(const DllName: string;
IATEntryRVA: DWORD): string;
function FindSection (VirtualAddress: Cardinal): PImageSectionHeader;
property Mapper: THSFileMapper read FMapper;
property ModuleReferences: TStrings read FModuleReferences;
property ImportLibraries: TStringList read FImportLibraries;
property NtHeaders: PIMAGE_NT_HEADERS read FNtHeaders;
property SectionList: TList read FSections;
property Sections[I: Integer]: PImageSectionHeader read GetSection;
property Subsystem: THSSubSystem read GetSubSystem;
property Imports: TStrings read GetImports;
property DelayImports: TStrings read GetDelayImports;
end;
{ Не вошедшие в Windows.pas константы из Platform SDK }
const
IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020;
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8; // image is a native Win9x driver.
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9; // Image runs in the Windows CE subsystem.
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10;
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11;
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12;
IMAGE_SUBSYSTEM_EFI_ROM = 13;
IMAGE_SUBSYSTEM_XBOX = 14;
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = $0200; // Image understands
// isolation and doesn't
// want it
IMAGE_DLLCHARACTERISTICS_NO_SEH = $0400; // Image does not use SEH.
// No SE handler may reside
// in this image
IMAGE_DLLCHARACTERISTICS_NO_BIND = $0800; // Do not bind this image.
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = $2000; // Driver uses WDM model
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13; // Delay Load Import Descriptors
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14; // COM Runtime descriptor
Игорь Шевченко (2005-05-27 10:40:00) [19]Просто Джо © (27.05.05 10:18) [59]
type
THSBinaryType = (hsbtError, hsbtWin32, hsbtWin16, hsbtDos16, hsbtCom,
hsbtVxd, hsbtW3, hsBtUnknown);
function HSGetBinaryType (const FileName: string): THSBinaryType;
type
PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
PIMAGE_NT_HEADERS = PImageNtHeaders;
var
Mapper: THSFileMapper;
DosHeader: PIMAGE_DOS_HEADER;
FileHeader: PIMAGE_NT_HEADERS;
begin
Result := hsbtError;
Mapper := THSFileMapper.Create (FileName);
try
if (Mapper.Map[0] <> 'M') or (Mapper.Map[1] <> 'Z') then begin
if UpperCase(ExtractFileExt(FileName)) = '.COM' then
Result := hsbtCom;
Exit;
end else if Mapper.FileSize >= SizeOf(IMAGE_DOS_HEADER) then begin
DosHeader := PIMAGE_DOS_HEADER(Mapper.Map);
if (DosHeader^._lfanew > $40) { Matt Pietrek } and
(DWORD(DosHeader^._lfanew) < Mapper.FileSize - SizeOf(WORD)) then begin
FileHeader := PIMAGE_NT_HEADERS(DWORD(DosHeader) +
DWORD(DosHeader^._lfanew));
if FileHeader^.Signature = IMAGE_NT_SIGNATURE then
Result := hsbtWin32
else if WORD(FileHeader^.Signature) = IMAGE_OS2_SIGNATURE then
Result := hsbtWin16
else if WORD(FileHeader^.Signature) = IMAGE_VXD_SIGNATURE then
Result := hsbtVxd
else if WORD(FileHeader^.Signature) = IMAGE_W3_SIGNATURE then
Result := hsbtW3
else
Result := hsbtUnknown;
end else
Result := hsbtDos16;
end;
finally
Mapper.Free;
end;
end;
Просто Джо (2005-05-27 10:18:00) [20]А все-таки, функцией GetBinaryType не определишь - консольное оно или нет, все равно придется в хэдэрах ковыряться.