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

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

added mailslot implemenation, named pipe fixes + FreeLibraryAndExitThread

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