Commit 8b492467 authored by Alexandre Julliard's avatar Alexandre Julliard

kernel32: Move MODULE_get_binary_info implementation to process.c.

parent e3d57fe5
......@@ -63,32 +63,8 @@ extern void FILE_SetDosError(void) DECLSPEC_HIDDEN;
extern WCHAR *FILE_name_AtoW( LPCSTR name, BOOL alloc ) DECLSPEC_HIDDEN;
extern DWORD FILE_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen ) DECLSPEC_HIDDEN;
/* return values for MODULE_GetBinaryType */
enum binary_type
{
BINARY_UNKNOWN = 0,
BINARY_PE,
BINARY_WIN16,
BINARY_UNIX_EXE,
BINARY_UNIX_LIB
};
#define BINARY_FLAG_DLL 0x01
#define BINARY_FLAG_64BIT 0x02
#define BINARY_FLAG_FAKEDLL 0x04
struct binary_info
{
enum binary_type type;
DWORD arch;
DWORD flags;
ULONGLONG res_start;
ULONGLONG res_end;
};
/* module.c */
extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) DECLSPEC_HIDDEN;
extern void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info ) DECLSPEC_HIDDEN;
extern BOOL NLS_IsUnicodeOnlyLcid(LCID) DECLSPEC_HIDDEN;
......
......@@ -260,206 +260,6 @@ BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
/***********************************************************************
* MODULE_GetBinaryType
*/
void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info )
{
union
{
struct
{
unsigned char magic[4];
unsigned char class;
unsigned char data;
unsigned char ignored1[10];
unsigned short type;
unsigned short machine;
unsigned char ignored2[8];
unsigned int phoff;
unsigned char ignored3[12];
unsigned short phnum;
} elf;
struct
{
unsigned char magic[4];
unsigned char class;
unsigned char data;
unsigned char ignored1[10];
unsigned short type;
unsigned short machine;
unsigned char ignored2[12];
unsigned __int64 phoff;
unsigned char ignored3[16];
unsigned short phnum;
} elf64;
struct
{
unsigned int magic;
unsigned int cputype;
unsigned int cpusubtype;
unsigned int filetype;
} macho;
IMAGE_DOS_HEADER mz;
} header;
DWORD len;
memset( info, 0, sizeof(*info) );
/* Seek to the start of the file and read the header information. */
if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1) return;
if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header)) return;
if (!memcmp( header.elf.magic, "\177ELF", 4 ))
{
#ifdef WORDS_BIGENDIAN
BOOL byteswap = (header.elf.data == 1);
#else
BOOL byteswap = (header.elf.data == 2);
#endif
if (header.elf.class == 2) info->flags |= BINARY_FLAG_64BIT;
if (byteswap)
{
header.elf.type = RtlUshortByteSwap( header.elf.type );
header.elf.machine = RtlUshortByteSwap( header.elf.machine );
}
switch(header.elf.type)
{
case 2:
info->type = BINARY_UNIX_EXE;
break;
case 3:
{
LARGE_INTEGER phoff;
unsigned short phnum;
unsigned int type;
if (header.elf.class == 2)
{
phoff.QuadPart = byteswap ? RtlUlonglongByteSwap( header.elf64.phoff ) : header.elf64.phoff;
phnum = byteswap ? RtlUshortByteSwap( header.elf64.phnum ) : header.elf64.phnum;
}
else
{
phoff.QuadPart = byteswap ? RtlUlongByteSwap( header.elf.phoff ) : header.elf.phoff;
phnum = byteswap ? RtlUshortByteSwap( header.elf.phnum ) : header.elf.phnum;
}
while (phnum--)
{
if (SetFilePointerEx( hfile, phoff, NULL, FILE_BEGIN ) == -1) return;
if (!ReadFile( hfile, &type, sizeof(type), &len, NULL ) || len < sizeof(type)) return;
if (byteswap) type = RtlUlongByteSwap( type );
if (type == 3)
{
info->type = BINARY_UNIX_EXE;
break;
}
phoff.QuadPart += (header.elf.class == 2) ? 56 : 32;
}
if (!info->type) info->type = BINARY_UNIX_LIB;
break;
}
default:
return;
}
switch(header.elf.machine)
{
case 3: info->arch = IMAGE_FILE_MACHINE_I386; break;
case 20: info->arch = IMAGE_FILE_MACHINE_POWERPC; break;
case 40: info->arch = IMAGE_FILE_MACHINE_ARMNT; break;
case 50: info->arch = IMAGE_FILE_MACHINE_IA64; break;
case 62: info->arch = IMAGE_FILE_MACHINE_AMD64; break;
case 183: info->arch = IMAGE_FILE_MACHINE_ARM64; break;
}
}
/* Mach-o File with Endian set to Big Endian or Little Endian */
else if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe ||
header.macho.magic == 0xfeedfacf || header.macho.magic == 0xcffaedfe)
{
if ((header.macho.cputype >> 24) == 1) info->flags |= BINARY_FLAG_64BIT;
if (header.macho.magic == 0xcefaedfe || header.macho.magic == 0xcffaedfe)
{
header.macho.filetype = RtlUlongByteSwap( header.macho.filetype );
header.macho.cputype = RtlUlongByteSwap( header.macho.cputype );
}
switch(header.macho.filetype)
{
case 2: info->type = BINARY_UNIX_EXE; break;
case 8: info->type = BINARY_UNIX_LIB; break;
}
switch(header.macho.cputype)
{
case 0x00000007: info->arch = IMAGE_FILE_MACHINE_I386; break;
case 0x01000007: info->arch = IMAGE_FILE_MACHINE_AMD64; break;
case 0x0000000c: info->arch = IMAGE_FILE_MACHINE_ARMNT; break;
case 0x0100000c: info->arch = IMAGE_FILE_MACHINE_ARM64; break;
case 0x00000012: info->arch = IMAGE_FILE_MACHINE_POWERPC; break;
}
}
/* Not ELF, try DOS */
else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
union
{
IMAGE_OS2_HEADER os2;
IMAGE_NT_HEADERS32 nt;
IMAGE_NT_HEADERS64 nt64;
} ext_header;
/* We do have a DOS image so we will now try to seek into
* the file by the amount indicated by the field
* "Offset to extended header" and read in the
* "magic" field information at that location.
* This will tell us if there is more header information
* to read or not.
*/
info->type = BINARY_WIN16;
info->arch = IMAGE_FILE_MACHINE_I386;
if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1) return;
if (!ReadFile( hfile, &ext_header, sizeof(ext_header), &len, NULL ) || len < 4) return;
/* Reading the magic field succeeded so
* we will try to determine what type it is.
*/
if (!memcmp( &ext_header.nt.Signature, "PE\0\0", 4 ))
{
if (len >= sizeof(ext_header.nt.FileHeader))
{
static const char fakedll_signature[] = "Wine placeholder DLL";
char buffer[sizeof(fakedll_signature)];
info->type = BINARY_PE;
info->arch = ext_header.nt.FileHeader.Machine;
if (ext_header.nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
info->flags |= BINARY_FLAG_DLL;
if (len < sizeof(ext_header)) /* clear remaining part of header if missing */
memset( (char *)&ext_header + len, 0, sizeof(ext_header) - len );
switch (ext_header.nt.OptionalHeader.Magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
info->res_start = ext_header.nt.OptionalHeader.ImageBase;
info->res_end = info->res_start + ext_header.nt.OptionalHeader.SizeOfImage;
break;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
info->res_start = ext_header.nt64.OptionalHeader.ImageBase;
info->res_end = info->res_start + ext_header.nt64.OptionalHeader.SizeOfImage;
info->flags |= BINARY_FLAG_64BIT;
break;
}
if (header.mz.e_lfanew >= sizeof(header.mz) + sizeof(fakedll_signature) &&
SetFilePointer( hfile, sizeof(header.mz), NULL, SEEK_SET ) == sizeof(header.mz) &&
ReadFile( hfile, buffer, sizeof(fakedll_signature), &len, NULL ) &&
len == sizeof(fakedll_signature) &&
!memcmp( buffer, fakedll_signature, sizeof(fakedll_signature) ))
{
info->flags |= BINARY_FLAG_FAKEDLL;
}
}
}
}
}
/***********************************************************************
* GetBinaryTypeW [KERNEL32.@]
*
* Determine whether a file is executable, and if so, what kind.
......
......@@ -113,6 +113,29 @@ static void exec_process( LPCWSTR name );
extern void SHELL_LoadRegistry(void);
/* return values for get_binary_info */
enum binary_type
{
BINARY_UNKNOWN = 0,
BINARY_PE,
BINARY_WIN16,
BINARY_UNIX_EXE,
BINARY_UNIX_LIB
};
#define BINARY_FLAG_DLL 0x01
#define BINARY_FLAG_64BIT 0x02
#define BINARY_FLAG_FAKEDLL 0x04
struct binary_info
{
enum binary_type type;
DWORD arch;
DWORD flags;
ULONGLONG res_start;
ULONGLONG res_end;
};
/***********************************************************************
* contains_path
......@@ -154,6 +177,207 @@ static inline unsigned int is_path_prefix( const WCHAR *prefix, const WCHAR *fil
}
/***********************************************************************
* get_binary_info
*/
static void get_binary_info( HANDLE hfile, struct binary_info *info )
{
union
{
struct
{
unsigned char magic[4];
unsigned char class;
unsigned char data;
unsigned char ignored1[10];
unsigned short type;
unsigned short machine;
unsigned char ignored2[8];
unsigned int phoff;
unsigned char ignored3[12];
unsigned short phnum;
} elf;
struct
{
unsigned char magic[4];
unsigned char class;
unsigned char data;
unsigned char ignored1[10];
unsigned short type;
unsigned short machine;
unsigned char ignored2[12];
unsigned __int64 phoff;
unsigned char ignored3[16];
unsigned short phnum;
} elf64;
struct
{
unsigned int magic;
unsigned int cputype;
unsigned int cpusubtype;
unsigned int filetype;
} macho;
IMAGE_DOS_HEADER mz;
} header;
DWORD len;
memset( info, 0, sizeof(*info) );
/* Seek to the start of the file and read the header information. */
if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1) return;
if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header)) return;
if (!memcmp( header.elf.magic, "\177ELF", 4 ))
{
#ifdef WORDS_BIGENDIAN
BOOL byteswap = (header.elf.data == 1);
#else
BOOL byteswap = (header.elf.data == 2);
#endif
if (header.elf.class == 2) info->flags |= BINARY_FLAG_64BIT;
if (byteswap)
{
header.elf.type = RtlUshortByteSwap( header.elf.type );
header.elf.machine = RtlUshortByteSwap( header.elf.machine );
}
switch(header.elf.type)
{
case 2:
info->type = BINARY_UNIX_EXE;
break;
case 3:
{
LARGE_INTEGER phoff;
unsigned short phnum;
unsigned int type;
if (header.elf.class == 2)
{
phoff.QuadPart = byteswap ? RtlUlonglongByteSwap( header.elf64.phoff ) : header.elf64.phoff;
phnum = byteswap ? RtlUshortByteSwap( header.elf64.phnum ) : header.elf64.phnum;
}
else
{
phoff.QuadPart = byteswap ? RtlUlongByteSwap( header.elf.phoff ) : header.elf.phoff;
phnum = byteswap ? RtlUshortByteSwap( header.elf.phnum ) : header.elf.phnum;
}
while (phnum--)
{
if (SetFilePointerEx( hfile, phoff, NULL, FILE_BEGIN ) == -1) return;
if (!ReadFile( hfile, &type, sizeof(type), &len, NULL ) || len < sizeof(type)) return;
if (byteswap) type = RtlUlongByteSwap( type );
if (type == 3)
{
info->type = BINARY_UNIX_EXE;
break;
}
phoff.QuadPart += (header.elf.class == 2) ? 56 : 32;
}
if (!info->type) info->type = BINARY_UNIX_LIB;
break;
}
default:
return;
}
switch(header.elf.machine)
{
case 3: info->arch = IMAGE_FILE_MACHINE_I386; break;
case 20: info->arch = IMAGE_FILE_MACHINE_POWERPC; break;
case 40: info->arch = IMAGE_FILE_MACHINE_ARMNT; break;
case 50: info->arch = IMAGE_FILE_MACHINE_IA64; break;
case 62: info->arch = IMAGE_FILE_MACHINE_AMD64; break;
case 183: info->arch = IMAGE_FILE_MACHINE_ARM64; break;
}
}
/* Mach-o File with Endian set to Big Endian or Little Endian */
else if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe ||
header.macho.magic == 0xfeedfacf || header.macho.magic == 0xcffaedfe)
{
if ((header.macho.cputype >> 24) == 1) info->flags |= BINARY_FLAG_64BIT;
if (header.macho.magic == 0xcefaedfe || header.macho.magic == 0xcffaedfe)
{
header.macho.filetype = RtlUlongByteSwap( header.macho.filetype );
header.macho.cputype = RtlUlongByteSwap( header.macho.cputype );
}
switch(header.macho.filetype)
{
case 2: info->type = BINARY_UNIX_EXE; break;
case 8: info->type = BINARY_UNIX_LIB; break;
}
switch(header.macho.cputype)
{
case 0x00000007: info->arch = IMAGE_FILE_MACHINE_I386; break;
case 0x01000007: info->arch = IMAGE_FILE_MACHINE_AMD64; break;
case 0x0000000c: info->arch = IMAGE_FILE_MACHINE_ARMNT; break;
case 0x0100000c: info->arch = IMAGE_FILE_MACHINE_ARM64; break;
case 0x00000012: info->arch = IMAGE_FILE_MACHINE_POWERPC; break;
}
}
/* Not ELF, try DOS */
else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
union
{
IMAGE_OS2_HEADER os2;
IMAGE_NT_HEADERS32 nt;
IMAGE_NT_HEADERS64 nt64;
} ext_header;
/* We do have a DOS image so we will now try to seek into
* the file by the amount indicated by the field
* "Offset to extended header" and read in the
* "magic" field information at that location.
* This will tell us if there is more header information
* to read or not.
*/
info->type = BINARY_WIN16;
info->arch = IMAGE_FILE_MACHINE_I386;
if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1) return;
if (!ReadFile( hfile, &ext_header, sizeof(ext_header), &len, NULL ) || len < 4) return;
/* Reading the magic field succeeded so
* we will try to determine what type it is.
*/
if (!memcmp( &ext_header.nt.Signature, "PE\0\0", 4 ))
{
if (len >= sizeof(ext_header.nt.FileHeader))
{
static const char fakedll_signature[] = "Wine placeholder DLL";
char buffer[sizeof(fakedll_signature)];
info->type = BINARY_PE;
info->arch = ext_header.nt.FileHeader.Machine;
if (ext_header.nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
info->flags |= BINARY_FLAG_DLL;
if (len < sizeof(ext_header)) /* clear remaining part of header if missing */
memset( (char *)&ext_header + len, 0, sizeof(ext_header) - len );
switch (ext_header.nt.OptionalHeader.Magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
info->res_start = ext_header.nt.OptionalHeader.ImageBase;
info->res_end = info->res_start + ext_header.nt.OptionalHeader.SizeOfImage;
break;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
info->res_start = ext_header.nt64.OptionalHeader.ImageBase;
info->res_end = info->res_start + ext_header.nt64.OptionalHeader.SizeOfImage;
info->flags |= BINARY_FLAG_64BIT;
break;
}
if (header.mz.e_lfanew >= sizeof(header.mz) + sizeof(fakedll_signature) &&
SetFilePointer( hfile, sizeof(header.mz), NULL, SEEK_SET ) == sizeof(header.mz) &&
ReadFile( hfile, buffer, sizeof(fakedll_signature), &len, NULL ) &&
len == sizeof(fakedll_signature) &&
!memcmp( buffer, fakedll_signature, sizeof(fakedll_signature) ))
{
info->flags |= BINARY_FLAG_FAKEDLL;
}
}
}
}
}
/***************************************************************************
* get_builtin_path
*
......@@ -247,7 +471,7 @@ static HANDLE open_exe_file( const WCHAR *name, struct binary_info *binary_info
if (contains_path( name ) && get_builtin_path( name, NULL, buffer, sizeof(buffer), binary_info ))
handle = 0;
}
else MODULE_get_binary_info( handle, binary_info );
else get_binary_info( handle, binary_info );
return handle;
}
......@@ -272,7 +496,7 @@ static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen,
if ((*handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE)
{
MODULE_get_binary_info( *handle, binary_info );
get_binary_info( *handle, binary_info );
return TRUE;
}
return FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment