1/*
2 * Copyright 2013-2014, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *	Alexander von Gluck IV, <kallisti5@unixzen.com>
7 */
8
9
10#include "pe.h"
11
12#include <ctype.h>
13#include <dlfcn.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18
19static status_t
20parse_mz_header(MzHeader* mzHeader, off_t* peOffset)
21{
22	if (memcmp(&mzHeader->magic, MZ_MAGIC, 2) != 0)
23		return B_NOT_AN_EXECUTABLE;
24
25	*peOffset = (off_t)mzHeader->lfaNew;
26	return B_OK;
27}
28
29
30static status_t
31parse_pe_header(PeHeader* peHeader)
32{
33	if (memcmp(&peHeader->magic, PE_MAGIC, 2) != 0)
34		return B_NOT_AN_EXECUTABLE;
35
36	// Looks like an old BeOS R3 x86 program
37	if (peHeader->characteristics == 0x10E)
38		return B_LEGACY_EXECUTABLE;
39
40	return B_OK;
41}
42
43
44/*! Read and verify the PE header */
45status_t
46pe_verify_header(void *header, size_t length)
47{
48	if (length < sizeof(MzHeader))
49		return B_NOT_AN_EXECUTABLE;
50
51	// Verify MZ header, pull PE header offset
52	off_t peOffset = 0;
53	if (parse_mz_header((MzHeader*)header, &peOffset) != B_OK)
54		return B_NOT_AN_EXECUTABLE;
55
56	// MS-DOS program
57	if (peOffset == 0)
58		return B_UNKNOWN_EXECUTABLE;
59
60	// Something is wrong with the binary
61	if (peOffset + sizeof(PeHeader) > length)
62		return B_UNKNOWN_EXECUTABLE;
63
64	// Find the PE header based on MZ provided offset
65	uint8* pePtr = (uint8*)header;
66	pePtr += peOffset;
67
68	// Win32 program or old BeOS R3 x86 program
69	return parse_pe_header((PeHeader*)pePtr);
70}
71