kernel32: Add a structure to store all the information about an executable.

This commit is contained in:
Alexandre Julliard 2009-10-27 19:30:30 +01:00
parent 072b737059
commit 28f13f83a6
3 changed files with 85 additions and 90 deletions

View File

@ -76,20 +76,31 @@ extern WCHAR *FILE_name_AtoW( LPCSTR name, BOOL alloc );
extern DWORD FILE_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen );
/* return values for MODULE_GetBinaryType */
#define BINARY_UNKNOWN 0x00
#define BINARY_PE 0x01
#define BINARY_WIN16 0x02
#define BINARY_OS216 0x03
#define BINARY_DOS 0x04
#define BINARY_UNIX_EXE 0x05
#define BINARY_UNIX_LIB 0x06
#define BINARY_TYPE_MASK 0x0f
#define BINARY_FLAG_DLL 0x10
#define BINARY_FLAG_64BIT 0x20
enum binary_type
{
BINARY_UNKNOWN = 0,
BINARY_PE,
BINARY_WIN16,
BINARY_OS216,
BINARY_DOS,
BINARY_UNIX_EXE,
BINARY_UNIX_LIB
};
#define BINARY_FLAG_DLL 0x01
#define BINARY_FLAG_64BIT 0x02
struct binary_info
{
enum binary_type type;
DWORD flags;
void *res_start;
void *res_end;
};
/* module.c */
extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module );
extern DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end );
extern void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info );
extern BOOL NLS_IsUnicodeOnlyLcid(LCID);

View File

@ -226,7 +226,7 @@ good:
/***********************************************************************
* MODULE_GetBinaryType
*/
DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end )
void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info )
{
union
{
@ -252,39 +252,34 @@ DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end )
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 BINARY_UNKNOWN;
if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
return BINARY_UNKNOWN;
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 ))
{
DWORD flags = (header.elf.class == 2) ? BINARY_FLAG_64BIT : 0;
if (header.elf.class == 2) info->flags |= BINARY_FLAG_64BIT;
/* FIXME: we don't bother to check byte order, architecture, etc. */
switch(header.elf.type)
{
case 2: return flags | BINARY_UNIX_EXE;
case 3: return flags | BINARY_UNIX_LIB;
case 2: info->type = BINARY_UNIX_EXE; break;
case 3: info->type = BINARY_UNIX_LIB; break;
}
return BINARY_UNKNOWN;
}
/* Mach-o File with Endian set to Big Endian or Little Endian */
if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe)
else if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe)
{
DWORD flags = (header.macho.cputype >> 24) == 1 ? BINARY_FLAG_64BIT : 0;
if ((header.macho.cputype >> 24) == 1) info->flags |= BINARY_FLAG_64BIT;
switch(header.macho.filetype)
{
case 2: return flags | BINARY_UNIX_EXE;
case 8: return flags | BINARY_UNIX_LIB;
case 2: info->type = BINARY_UNIX_EXE; break;
case 8: info->type = BINARY_UNIX_LIB; break;
}
return BINARY_UNKNOWN;
}
/* Not ELF, try DOS */
if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
union
{
@ -299,10 +294,9 @@ DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end )
* This will tell us if there is more header information
* to read or not.
*/
if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
return BINARY_DOS;
if (!ReadFile( hfile, &ext_header, sizeof(ext_header), &len, NULL ) || len < 4)
return BINARY_DOS;
info->type = BINARY_DOS;
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.
@ -311,27 +305,25 @@ DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end )
{
if (len >= sizeof(ext_header.nt.FileHeader))
{
DWORD ret = BINARY_PE;
if (ext_header.nt.FileHeader.Characteristics & IMAGE_FILE_DLL) ret |= BINARY_FLAG_DLL;
info->type = BINARY_PE;
if (ext_header.nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
info->flags |= BINARY_FLAG_DLL;
if (len < sizeof(ext_header.nt)) /* clear remaining part of header if missing */
memset( (char *)&ext_header.nt + len, 0, sizeof(ext_header.nt) - len );
switch (ext_header.nt.OptionalHeader.Magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
if (res_start) *res_start = (void *)(ULONG_PTR)ext_header.nt.OptionalHeader.ImageBase;
if (res_end) *res_end = (void *)((ULONG_PTR)ext_header.nt.OptionalHeader.ImageBase +
info->res_start = (void *)(ULONG_PTR)ext_header.nt.OptionalHeader.ImageBase;
info->res_end = (void *)((ULONG_PTR)ext_header.nt.OptionalHeader.ImageBase +
ext_header.nt.OptionalHeader.SizeOfImage);
return ret;
break;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
if (res_start) *res_start = NULL;
if (res_end) *res_end = NULL;
return ret | BINARY_FLAG_64BIT;
info->flags |= BINARY_FLAG_64BIT;
break;
}
}
return BINARY_DOS;
}
if (!memcmp( &ext_header.os2.ne_magic, "NE", 2 ))
else if (!memcmp( &ext_header.os2.ne_magic, "NE", 2 ))
{
/* This is a Windows executable (NE) header. This can
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
@ -340,27 +332,20 @@ DWORD MODULE_GetBinaryType( HANDLE hfile, void **res_start, void **res_end )
*/
if (len >= sizeof(ext_header.os2))
{
DWORD flags = (ext_header.os2.ne_flags & NE_FFLAGS_LIBMODULE) ? BINARY_FLAG_DLL : 0;
if (ext_header.os2.ne_flags & NE_FFLAGS_LIBMODULE) info->flags |= BINARY_FLAG_DLL;
switch ( ext_header.os2.ne_exetyp )
{
case 1: return flags | BINARY_OS216; /* OS/2 */
case 2: return flags | BINARY_WIN16; /* Windows */
case 3: return flags | BINARY_DOS; /* European MS-DOS 4.x */
case 4: return flags | BINARY_WIN16; /* Windows 386; FIXME: is this 32bit??? */
case 5: return flags | BINARY_DOS; /* BOSS, Borland Operating System Services */
case 1: info->type = BINARY_OS216; break; /* OS/2 */
case 2: info->type = BINARY_WIN16; break; /* Windows */
case 3: info->type = BINARY_DOS; break; /* European MS-DOS 4.x */
case 4: info->type = BINARY_WIN16; break; /* Windows 386; FIXME: is this 32bit??? */
case 5: info->type = BINARY_DOS; break; /* BOSS, Borland Operating System Services */
/* other types, e.g. 0 is: "unknown" */
default: return flags | MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ext_header.os2);
default: info->type = MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ext_header.os2); break;
}
}
/* Couldn't read header, so abort. */
return BINARY_DOS;
}
/* Unknown extended header, but this file is nonetheless DOS-executable. */
return BINARY_DOS;
}
return BINARY_UNKNOWN;
}
/***********************************************************************
@ -400,7 +385,7 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
{
BOOL ret = FALSE;
HANDLE hfile;
DWORD binary_type;
struct binary_info binary_info;
TRACE("%s\n", debugstr_w(lpApplicationName) );
@ -418,8 +403,8 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
/* Check binary type
*/
binary_type = MODULE_GetBinaryType( hfile, NULL, NULL );
switch (binary_type & BINARY_TYPE_MASK)
MODULE_get_binary_info( hfile, &binary_info );
switch (binary_info.type)
{
case BINARY_UNKNOWN:
{
@ -443,7 +428,7 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
break;
}
case BINARY_PE:
*lpBinaryType = (binary_type & BINARY_FLAG_64BIT) ? SCS_64BIT_BINARY : SCS_32BIT_BINARY;
*lpBinaryType = (binary_info.flags & BINARY_FLAG_64BIT) ? SCS_64BIT_BINARY : SCS_32BIT_BINARY;
ret = TRUE;
break;
case BINARY_WIN16:

View File

@ -1589,7 +1589,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
LPCWSTR cur_dir, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags, LPSTARTUPINFOW startup,
LPPROCESS_INFORMATION info, LPCSTR unixdir,
void *res_start, void *res_end, DWORD binary_type, int exec_only )
const struct binary_info *binary_info, int exec_only )
{
BOOL ret, success = FALSE;
HANDLE process_info;
@ -1602,7 +1602,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
pid_t pid;
int err;
if (sizeof(void *) == sizeof(int) && !is_wow64 && (binary_type & BINARY_FLAG_64BIT))
if (sizeof(void *) == sizeof(int) && !is_wow64 && (binary_info->flags & BINARY_FLAG_64BIT))
{
ERR( "starting 64-bit process %s not supported on this platform\n", debugstr_w(filename) );
SetLastError( ERROR_BAD_EXE_FORMAT );
@ -1730,7 +1730,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd[0] );
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx",
(unsigned long)res_start, (unsigned long)res_end );
(unsigned long)binary_info->res_start, (unsigned long)binary_info->res_end );
putenv( preloader_reserve );
putenv( socket_env );
@ -1793,7 +1793,7 @@ static BOOL create_vdm_process( LPCWSTR filename, LPWSTR cmd_line, LPWSTR env, L
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags, LPSTARTUPINFOW startup,
LPPROCESS_INFORMATION info, LPCSTR unixdir,
DWORD binary_type, int exec_only )
const struct binary_info *binary_info, int exec_only )
{
static const WCHAR argsW[] = {'%','s',' ','-','-','a','p','p','-','n','a','m','e',' ','"','%','s','"',' ','%','s',0};
@ -1808,7 +1808,7 @@ static BOOL create_vdm_process( LPCWSTR filename, LPWSTR cmd_line, LPWSTR env, L
}
sprintfW( new_cmd_line, argsW, winevdmW, filename, cmd_line );
ret = create_process( 0, winevdmW, new_cmd_line, env, cur_dir, psa, tsa, inherit,
flags, startup, info, unixdir, NULL, NULL, binary_type, exec_only );
flags, startup, info, unixdir, binary_info, exec_only );
HeapFree( GetProcessHeap(), 0, new_cmd_line );
return ret;
}
@ -1985,8 +1985,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( LPCWSTR app_name, LPWSTR cmd_line,
char *unixdir = NULL;
WCHAR name[MAX_PATH];
WCHAR *tidy_cmdline, *p, *envW = env;
void *res_start, *res_end;
DWORD binary_type;
struct binary_info binary_info;
/* Process the AppName and/or CmdLine to get module name and path */
@ -2039,38 +2038,38 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( LPCWSTR app_name, LPWSTR cmd_line,
if (!hFile) /* builtin exe */
{
TRACE( "starting %s as Winelib app\n", debugstr_w(name) );
memset( &binary_info, 0, sizeof(binary_info) );
binary_info.type = BINARY_UNIX_LIB;
retv = create_process( 0, name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir, NULL, NULL,
BINARY_UNIX_LIB, FALSE );
inherit, flags, startup_info, info, unixdir, &binary_info, FALSE );
goto done;
}
binary_type = MODULE_GetBinaryType( hFile, &res_start, &res_end );
if (binary_type & BINARY_FLAG_DLL)
MODULE_get_binary_info( hFile, &binary_info );
if (binary_info.flags & BINARY_FLAG_DLL)
{
TRACE( "not starting %s since it is a dll\n", debugstr_w(name) );
SetLastError( ERROR_BAD_EXE_FORMAT );
}
else switch (binary_type & BINARY_TYPE_MASK)
else switch (binary_info.type)
{
case BINARY_PE:
TRACE( "starting %s as Win32 binary (%p-%p)\n", debugstr_w(name), res_start, res_end );
TRACE( "starting %s as Win32 binary (%p-%p)\n",
debugstr_w(name), binary_info.res_start, binary_info.res_end );
retv = create_process( hFile, name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir,
res_start, res_end, binary_type, FALSE );
inherit, flags, startup_info, info, unixdir, &binary_info, FALSE );
break;
case BINARY_OS216:
case BINARY_WIN16:
case BINARY_DOS:
TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(name) );
retv = create_vdm_process( name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir, binary_type, FALSE );
inherit, flags, startup_info, info, unixdir, &binary_info, FALSE );
break;
case BINARY_UNIX_LIB:
TRACE( "%s is a Unix library, starting as Winelib app\n", debugstr_w(name) );
retv = create_process( hFile, name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir,
NULL, NULL, binary_type, FALSE );
inherit, flags, startup_info, info, unixdir, &binary_info, FALSE );
break;
case BINARY_UNKNOWN:
/* check for .com or .bat extension */
@ -2081,7 +2080,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW( LPCWSTR app_name, LPWSTR cmd_line,
TRACE( "starting %s as DOS binary\n", debugstr_w(name) );
retv = create_vdm_process( name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir,
binary_type, FALSE );
&binary_info, FALSE );
break;
}
if (!strcmpiW( p, batW ) || !strcmpiW( p, cmdW ) )
@ -2127,10 +2126,9 @@ static void exec_process( LPCWSTR name )
{
HANDLE hFile;
WCHAR *p;
void *res_start, *res_end;
STARTUPINFOW startup_info;
PROCESS_INFORMATION info;
DWORD binary_type;
struct binary_info binary_info;
hFile = open_exe_file( name );
if (!hFile || hFile == INVALID_HANDLE_VALUE) return;
@ -2140,19 +2138,20 @@ static void exec_process( LPCWSTR name )
/* Determine executable type */
binary_type = MODULE_GetBinaryType( hFile, &res_start, &res_end );
if (binary_type & BINARY_FLAG_DLL) return;
switch (binary_type & BINARY_TYPE_MASK)
MODULE_get_binary_info( hFile, &binary_info );
if (binary_info.flags & BINARY_FLAG_DLL) return;
switch (binary_info.type)
{
case BINARY_PE:
TRACE( "starting %s as Win32 binary (%p-%p)\n", debugstr_w(name), res_start, res_end );
TRACE( "starting %s as Win32 binary (%p-%p)\n",
debugstr_w(name), binary_info.res_start, binary_info.res_end );
create_process( hFile, name, GetCommandLineW(), NULL, NULL, NULL, NULL,
FALSE, 0, &startup_info, &info, NULL, res_start, res_end, binary_type, TRUE );
FALSE, 0, &startup_info, &info, NULL, &binary_info, TRUE );
break;
case BINARY_UNIX_LIB:
TRACE( "%s is a Unix library, starting as Winelib app\n", debugstr_w(name) );
create_process( hFile, name, GetCommandLineW(), NULL, NULL, NULL, NULL,
FALSE, 0, &startup_info, &info, NULL, NULL, NULL, binary_type, TRUE );
FALSE, 0, &startup_info, &info, NULL, &binary_info, TRUE );
break;
case BINARY_UNKNOWN:
/* check for .com or .pif extension */
@ -2164,7 +2163,7 @@ static void exec_process( LPCWSTR name )
case BINARY_DOS:
TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(name) );
create_vdm_process( name, GetCommandLineW(), NULL, NULL, NULL, NULL,
FALSE, 0, &startup_info, &info, NULL, binary_type, TRUE );
FALSE, 0, &startup_info, &info, NULL, &binary_info, TRUE );
break;
default:
break;