source: trunk/src/kernel32/module.cpp@ 7342

Last change on this file since 7342 was 7342, checked in by sandervl, 24 years ago

removed unnecessary changes

File size: 10.0 KB
Line 
1/* $Id: module.cpp,v 1.5 2001-11-14 18:38:49 sandervl Exp $
2 *
3 * GetBinaryTypeA/W (Wine Port)
4 *
5 * Copyright 1995 Alexandre Julliard
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 */
9
10#include <windows.h>
11#include <module.h>
12#include <debugtools.h>
13#include <heapstring.h>
14#include <misc.h>
15
16#define DBG_LOCALLOG DBG_module
17#include "dbglocal.h"
18
19#define FILE_strcasecmp strcmpi
20
21/* Check whether a file is an OS/2 or a very old Windows executable
22 * by testing on import of KERNEL.
23 *
24 * FIXME: is reading the module imports the only way of discerning
25 * old Windows binaries from OS/2 ones ? At least it seems so...
26 */
27static DWORD MODULE_Decide_OS2_OldWin(HANDLE hfile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
28{
29 DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
30 DWORD type = SCS_OS216_BINARY;
31 LPWORD modtab = NULL;
32 LPSTR nametab = NULL;
33 DWORD len;
34 int i;
35
36 /* read modref table */
37 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
38 || (!(modtab = (LPWORD)HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
39 || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
40 || (len != ne->ne_cmod*sizeof(WORD)) )
41 goto broken;
42
43 /* read imported names table */
44 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
45 || (!(nametab = (LPSTR)HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
46 || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
47 || (len != ne->ne_enttab - ne->ne_imptab) )
48 goto broken;
49
50 for (i=0; i < ne->ne_cmod; i++)
51 {
52 LPSTR module = &nametab[modtab[i]];
53 TRACE("modref: %.*s\n", module[0], &module[1]);
54 if (!(strncmp(&module[1], "KERNEL", module[0])))
55 { /* very old Windows file */
56 MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
57 type = SCS_WOW_BINARY;
58 goto good;
59 }
60 }
61
62broken:
63 ERR("Hmm, an error occurred. Is this binary file broken ?\n");
64
65good:
66 HeapFree( GetProcessHeap(), 0, modtab);
67 HeapFree( GetProcessHeap(), 0, nametab);
68 SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
69 return type;
70}
71
72/***********************************************************************
73 * MODULE_GetBinaryType
74 *
75 * The GetBinaryType function determines whether a file is executable
76 * or not and if it is it returns what type of executable it is.
77 * The type of executable is a property that determines in which
78 * subsystem an executable file runs under.
79 *
80 * Binary types returned:
81 * SCS_32BIT_BINARY: A Win32 based application
82 * SCS_DOS_BINARY: An MS-Dos based application
83 * SCS_WOW_BINARY: A Win16 based application
84 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
85 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
86 * SCS_OS216_BINARY: A 16bit OS/2 based application
87 *
88 * Returns TRUE if the file is an executable in which case
89 * the value pointed by lpBinaryType is set.
90 * Returns FALSE if the file is not an executable or if the function fails.
91 *
92 * To do so it opens the file and reads in the header information
93 * if the extended header information is not present it will
94 * assume that the file is a DOS executable.
95 * If the extended header information is present it will
96 * determine if the file is a 16 or 32 bit Windows executable
97 * by check the flags in the header.
98 *
99 * Note that .COM and .PIF files are only recognized by their
100 * file name extension; but Windows does it the same way ...
101 */
102static BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType )
103{
104 IMAGE_DOS_HEADER mz_header;
105 char magic[4], *ptr;
106 DWORD len;
107
108 /* Seek to the start of the file and read the DOS header information.
109 */
110 if ( SetFilePointer( hfile, 0, NULL, SEEK_SET ) != -1
111 && ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL )
112 && len == sizeof(mz_header) )
113 {
114 /* Now that we have the header check the e_magic field
115 * to see if this is a dos image.
116 */
117 if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
118 {
119 BOOL lfanewValid = FALSE;
120 /* We do have a DOS image so we will now try to seek into
121 * the file by the amount indicated by the field
122 * "Offset to extended header" and read in the
123 * "magic" field information at that location.
124 * This will tell us if there is more header information
125 * to read or not.
126 */
127 /* But before we do we will make sure that header
128 * structure encompasses the "Offset to extended header"
129 * field.
130 */
131 if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
132 if ( ( mz_header.e_crlc == 0 ) ||
133 ( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
134 if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER)
135 && SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ) != -1
136 && ReadFile( hfile, magic, sizeof(magic), &len, NULL )
137 && len == sizeof(magic) )
138 lfanewValid = TRUE;
139
140 if ( !lfanewValid )
141 {
142 /* If we cannot read this "extended header" we will
143 * assume that we have a simple DOS executable.
144 */
145 *lpBinaryType = SCS_DOS_BINARY;
146 return TRUE;
147 }
148 else
149 {
150 /* Reading the magic field succeeded so
151 * we will try to determine what type it is.
152 */
153 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
154 {
155 /* This is an NT signature.
156 */
157 *lpBinaryType = SCS_32BIT_BINARY;
158 return TRUE;
159 }
160 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
161 {
162 /* The IMAGE_OS2_SIGNATURE indicates that the
163 * "extended header is a Windows executable (NE)
164 * header." This can mean either a 16-bit OS/2
165 * or a 16-bit Windows or even a DOS program
166 * (running under a DOS extender). To decide
167 * which, we'll have to read the NE header.
168 */
169
170 IMAGE_OS2_HEADER ne;
171 if ( SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ) != -1
172 && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
173 && len == sizeof(ne) )
174 {
175 switch ( ne.ne_exetyp )
176 {
177 case 2: *lpBinaryType = SCS_WOW_BINARY; return TRUE;
178 case 5: *lpBinaryType = SCS_DOS_BINARY; return TRUE;
179 default: *lpBinaryType =
180 MODULE_Decide_OS2_OldWin(hfile, &mz_header, &ne);
181 return TRUE;
182 }
183 }
184 /* Couldn't read header, so abort. */
185 return FALSE;
186 }
187 else
188 {
189 /* Unknown extended header, but this file is nonetheless
190 DOS-executable.
191 */
192 *lpBinaryType = SCS_DOS_BINARY;
193 return TRUE;
194 }
195 }
196 }
197 }
198
199 /* If we get here, we don't even have a correct MZ header.
200 * Try to check the file extension for known types ...
201 */
202 ptr = strrchr( filename, '.' );
203 if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
204 {
205 if ( !FILE_strcasecmp( ptr, ".COM" ) )
206 {
207 *lpBinaryType = SCS_DOS_BINARY;
208 return TRUE;
209 }
210
211 if ( !FILE_strcasecmp( ptr, ".PIF" ) )
212 {
213 *lpBinaryType = SCS_PIF_BINARY;
214 return TRUE;
215 }
216 }
217
218 return FALSE;
219}
220
221/***********************************************************************
222 * GetBinaryTypeA [KERNEL32.280]
223 */
224BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
225{
226 BOOL ret = FALSE;
227 HANDLE hfile;
228
229 dprintf(("KERNEL32: GetBinaryTypeA %s %x", lpApplicationName, lpBinaryType));
230
231 /* Sanity check.
232 */
233 if ( lpApplicationName == NULL || lpBinaryType == NULL ) {
234 //TODO: Set last error?????
235 dprintf(("WARNING: Invalid parameter!"));
236 return FALSE;
237 }
238
239 /* Open the file indicated by lpApplicationName for reading.
240 */
241 hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
242 NULL, OPEN_EXISTING, 0, 0 );
243 if ( hfile == INVALID_HANDLE_VALUE )
244 return FALSE;
245
246 /* Check binary type
247 */
248 ret = MODULE_GetBinaryType( hfile, lpApplicationName, lpBinaryType );
249
250 /* Close the file.
251 */
252 CloseHandle( hfile );
253
254 //TODO: Set last error?????
255 return ret;
256}
257
258/***********************************************************************
259 * GetBinaryTypeW [KERNEL32.281]
260 */
261BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
262{
263 BOOL ret = FALSE;
264 LPSTR strNew = NULL;
265
266 dprintf(("KERNEL32: GetBinaryTypeW %x %x", lpApplicationName, lpBinaryType));
267
268 /* Sanity check.
269 */
270 if ( lpApplicationName == NULL || lpBinaryType == NULL ) {
271 //TODO: Set last error?????
272 dprintf(("WARNING: Invalid parameter!"));
273 return FALSE;
274 }
275
276 /* Convert the wide string to a ascii string.
277 */
278 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
279
280 if ( strNew != NULL )
281 {
282 ret = GetBinaryTypeA( strNew, lpBinaryType );
283
284 /* Free the allocated string.
285 */
286 HeapFree( GetProcessHeap(), 0, strNew );
287 }
288
289 return ret;
290}
Note: See TracBrowser for help on using the repository browser.