ported GetBinaryType() from wine

svn path=/trunk/; revision=9279
This commit is contained in:
Thomas Bluemel 2004-05-02 14:47:05 +00:00
parent 6ec9cfe422
commit 3cc6704954
5 changed files with 351 additions and 32 deletions

View file

@ -1314,6 +1314,7 @@ extern "C" {
#define SCS_PIF_BINARY (3)
#define SCS_POSIX_BINARY (4)
#define SCS_WOW_BINARY (2)
#define SCS_64BIT_BINARY (6)
/* GetBoundsRect, SetBoundsRect */
#define DCB_DISABLE (8)

View file

@ -0,0 +1,337 @@
/* $Id: bintype.c,v 1.1 2004/05/02 14:47:05 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/file/bintype.c
* PURPOSE: Binary detection functions
* PROGRAMMER: Alexandre Julliard (WINE)
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
* UPDATE HISTORY:
* 02/05/2004 - Ported/Adapted from WINE
*/
/* INCLUDES *****************************************************************/
#include <k32.h>
#include <ddk/ntifs.h>
#define NDEBUG
#include "../include/debug.h"
/* FUNCTIONS ****************************************************************/
/* Check whether a file is an OS/2 or a very old Windows executable
* by testing on import of KERNEL.
*
* FIXME: is reading the module imports the only way of discerning
* old Windows binaries from OS/2 ones ? At least it seems so...
*/
STATIC DWORD STDCALL
InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
{
DWORD CurPos;
LPWORD modtab = NULL;
LPSTR nametab = NULL;
DWORD Read, Ret;
int i;
Ret = BINARY_OS216;
CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
/* read modref table */
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_modtab, NULL, FILE_BEGIN) == -1) ||
(!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
(!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
(Read != ne->ne_cmod * sizeof(WORD)))
{
goto broken;
}
/* read imported names table */
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_imptab, NULL, FILE_BEGIN) == -1) ||
(!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
(!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
(Read != ne->ne_enttab - ne->ne_imptab))
{
goto broken;
}
for(i = 0; i < ne->ne_cmod; i++)
{
LPSTR module;
module = &nametab[modtab[i]];
if(!strncmp(&module[1], "KERNEL", module[0]))
{
/* very old windows file */
Ret = BINARY_WIN16;
goto done;
}
}
broken:
DPRINT("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
done:
HeapFree(GetProcessHeap(), 0, modtab);
HeapFree(GetProcessHeap(), 0, nametab);
SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
return Ret;
}
STATIC DWORD STDCALL
InternalGetBinaryType(HANDLE hFile)
{
union
{
struct
{
unsigned char magic[4];
unsigned char ignored[12];
unsigned short type;
} elf;
struct
{
unsigned long magic;
unsigned long cputype;
unsigned long cpusubtype;
unsigned long filetype;
} macho;
IMAGE_DOS_HEADER mz;
} Header;
char magic[4];
DWORD Read;
if((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == -1) ||
(!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
(Read != sizeof(Header))))
{
return BINARY_UNKNOWN;
}
if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
{
/* FIXME: we don't bother to check byte order, architecture, etc. */
switch(Header.elf.type)
{
case 2:
return BINARY_UNIX_EXE;
case 3:
return BINARY_UNIX_LIB;
}
return BINARY_UNKNOWN;
}
/* Mach-o File with Endian set to Big Endian or Little Endian*/
if(Header.macho.magic == 0xFEEDFACE ||
Header.macho.magic == 0xECAFDEEF)
{
switch(Header.macho.filetype)
{
case 0x8:
/* MH_BUNDLE */
return BINARY_UNIX_LIB;
}
return BINARY_UNKNOWN;
}
/* Not ELF, try DOS */
if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
/* 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.
*/
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == -1) ||
(!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
(Read != sizeof(magic))))
{
return BINARY_DOS;
}
/* Reading the magic field succeeded so
* we will try to determine what type it is.
*/
if(!memcmp(magic, "PE\0\0", sizeof(magic)))
{
IMAGE_FILE_HEADER FileHeader;
if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
(Read == sizeof(IMAGE_FILE_HEADER)))
{
return BINARY_DOS;
}
/* FIXME - detect 32/64 bit */
if(FileHeader.Characteristics & IMAGE_FILE_DLL)
return BINARY_PE_DLL32;
return BINARY_PE_EXE32;
}
if(!memcmp(magic, "NE", 1))
{
/* This is a Windows executable (NE) header. This can
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
* DOS program (running under a DOS extender). To decide
* which, we'll have to read the NE header.
*/
IMAGE_OS2_HEADER ne;
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
!ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
(Read == sizeof(IMAGE_OS2_HEADER)))
{
/* Couldn't read header, so abort. */
return BINARY_DOS;
}
switch(ne.ne_exetyp)
{
case 2:
return BINARY_WIN16;
case 5:
return BINARY_DOS;
default:
return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
}
}
return BINARY_DOS;
}
return BINARY_UNKNOWN;
}
/*
* @implemented
*/
BOOL
STDCALL
GetBinaryTypeW (
LPCWSTR lpApplicationName,
LPDWORD lpBinaryType
)
{
HANDLE hFile;
DWORD BinType;
if(!lpApplicationName || !lpBinaryType)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BinType = InternalGetBinaryType(hFile);
CloseHandle(hFile);
switch(BinType)
{
case BINARY_UNKNOWN:
{
WCHAR *dot;
/*
* guess from filename
*/
if(!(dot = wcsrchr(lpApplicationName, L'.')))
{
return FALSE;
}
if(!lstrcmpiW(dot, L".COM"))
{
*lpBinaryType = SCS_DOS_BINARY;
return TRUE;
}
if(!lstrcmpiW(dot, L".PIF"))
{
*lpBinaryType = SCS_PIF_BINARY;
return TRUE;
}
return FALSE;
}
case BINARY_PE_EXE32:
case BINARY_PE_DLL32:
{
*lpBinaryType = SCS_32BIT_BINARY;
return TRUE;
}
case BINARY_PE_EXE64:
case BINARY_PE_DLL64:
{
*lpBinaryType = SCS_64BIT_BINARY;
return TRUE;
}
case BINARY_WIN16:
{
*lpBinaryType = SCS_WOW_BINARY;
return TRUE;
}
case BINARY_OS216:
{
*lpBinaryType = SCS_OS216_BINARY;
return TRUE;
}
case BINARY_DOS:
{
*lpBinaryType = SCS_DOS_BINARY;
return TRUE;
}
case BINARY_UNIX_EXE:
case BINARY_UNIX_LIB:
{
return FALSE;
}
}
DPRINT1("Invalid binary type returned!\n", BinType);
return FALSE;
}
/*
* @implemented
*/
BOOL
STDCALL
GetBinaryTypeA (
LPCSTR lpApplicationName,
LPDWORD lpBinaryType
)
{
ANSI_STRING FileNameA;
UNICODE_STRING FileName;
NTSTATUS Status;
BOOL Ret;
if(!lpApplicationName || !lpBinaryType)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RtlInitAnsiString(&FileNameA, (LPSTR)lpApplicationName);
if(bIsFileApiAnsi)
Status = RtlAnsiStringToUnicodeString(&FileName, &FileNameA, TRUE);
else
Status = RtlOemStringToUnicodeString(&FileName, &FileNameA, TRUE);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
Ret = GetBinaryTypeW(FileName.Buffer, lpBinaryType);
RtlFreeUnicodeString(&FileName);
return Ret;
}
/* EOF */

View file

@ -1,6 +1,16 @@
#ifndef _KERNEL32_INCLUDE_KERNEL32_H
#define _KERNEL32_INCLUDE_KERNEL32_H
#define BINARY_UNKNOWN (0)
#define BINARY_PE_EXE32 (1)
#define BINARY_PE_DLL32 (2)
#define BINARY_PE_EXE64 (3)
#define BINARY_PE_DLL64 (4)
#define BINARY_WIN16 (5)
#define BINARY_OS216 (6)
#define BINARY_DOS (7)
#define BINARY_UNIX_EXE (8)
#define BINARY_UNIX_LIB (9)
#define MAGIC(c1,c2,c3,c4) ((c1) + ((c2)<<8) + ((c3)<<16) + ((c4)<<24))

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.78 2004/03/14 09:21:41 weiden Exp $
# $Id: makefile,v 1.79 2004/05/02 14:47:05 weiden Exp $
PATH_TO_TOP = ../..
@ -41,7 +41,7 @@ FILE_OBJECTS = file/file.o file/curdir.o file/lfile.o file/dir.o \
file/create.o file/find.o file/copy.o file/pipe.o \
file/move.o file/lock.o file/rw.o file/delete.o \
file/npipe.o file/tape.o file/mailslot.o file/backup.o \
file/cnotify.o file/hardlink.o
file/cnotify.o file/hardlink.o file/bintype.o
MEM_OBJECTS = mem/global.o mem/heap.o mem/isbad.o mem/local.o \
mem/procmem.o mem/section.o mem/virtual.o

View file

@ -1,4 +1,4 @@
/* $Id: stubs.c,v 1.73 2004/04/22 02:20:52 jimtabor Exp $
/* $Id: stubs.c,v 1.74 2004/05/02 14:47:05 weiden Exp $
*
* KERNEL32.DLL stubs (unimplemented functions)
* Remove from this file, if you implement them.
@ -171,35 +171,6 @@ FreeVirtualBuffer (
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
GetBinaryTypeW (
LPCWSTR lpApplicationName,
LPDWORD lpBinaryType
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* @unimplemented
*/
BOOL
STDCALL
GetBinaryTypeA (
LPCSTR lpApplicationName,
LPDWORD lpBinaryType
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
#ifndef _OLE2NLS_IN_BUILD_