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

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

thread handler call workaround for app bugs + GetBinaryTypeA/W port

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