2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/client/vdm.c
5 * PURPOSE: Virtual Dos Machine (VDM) Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *******************************************************************/
16 /* TYPES **********************************************************************/
18 /* FUNCTIONS ******************************************************************/
21 /* Check whether a file is an OS/2 or a very old Windows executable
22 * by testing on import of KERNEL.
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...
28 InternalIsOS2OrOldWin(HANDLE hFile
, IMAGE_DOS_HEADER
*mz
, IMAGE_OS2_HEADER
*ne
)
37 CurPos
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
39 /* read modref table */
40 if((SetFilePointer(hFile
, mz
->e_lfanew
+ ne
->ne_modtab
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
41 (!(modtab
= HeapAlloc(GetProcessHeap(), 0, ne
->ne_cmod
* sizeof(WORD
)))) ||
42 (!(ReadFile(hFile
, modtab
, ne
->ne_cmod
* sizeof(WORD
), &Read
, NULL
))) ||
43 (Read
!= (DWORD
)ne
->ne_cmod
* sizeof(WORD
)))
48 /* read imported names table */
49 if((SetFilePointer(hFile
, mz
->e_lfanew
+ ne
->ne_imptab
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
50 (!(nametab
= HeapAlloc(GetProcessHeap(), 0, ne
->ne_enttab
- ne
->ne_imptab
))) ||
51 (!(ReadFile(hFile
, nametab
, ne
->ne_enttab
- ne
->ne_imptab
, &Read
, NULL
))) ||
52 (Read
!= (DWORD
)ne
->ne_enttab
- ne
->ne_imptab
))
57 for(i
= 0; i
< ne
->ne_cmod
; i
++)
60 module
= &nametab
[modtab
[i
]];
61 if(!strncmp(&module
[1], "KERNEL", module
[0]))
63 /* very old windows file */
70 DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
73 HeapFree(GetProcessHeap(), 0, modtab
);
74 HeapFree(GetProcessHeap(), 0, nametab
);
75 SetFilePointer(hFile
, CurPos
, NULL
, FILE_BEGIN
);
80 InternalGetBinaryType(HANDLE hFile
)
86 unsigned char magic
[4];
87 unsigned char ignored
[12];
93 unsigned long cputype
;
94 unsigned long cpusubtype
;
95 unsigned long filetype
;
102 if((SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
103 (!ReadFile(hFile
, &Header
, sizeof(Header
), &Read
, NULL
) ||
104 (Read
!= sizeof(Header
))))
106 return BINARY_UNKNOWN
;
109 if(!memcmp(Header
.elf
.magic
, "\177ELF", sizeof(Header
.elf
.magic
)))
111 /* FIXME: we don't bother to check byte order, architecture, etc. */
112 switch(Header
.elf
.type
)
115 return BINARY_UNIX_EXE
;
117 return BINARY_UNIX_LIB
;
119 return BINARY_UNKNOWN
;
122 /* Mach-o File with Endian set to Big Endian or Little Endian*/
123 if(Header
.macho
.magic
== 0xFEEDFACE ||
124 Header
.macho
.magic
== 0xCEFAEDFE)
126 switch(Header
.macho
.filetype
)
130 return BINARY_UNIX_LIB
;
132 return BINARY_UNKNOWN
;
135 /* Not ELF, try DOS */
136 if(Header
.mz
.e_magic
== IMAGE_DOS_SIGNATURE
)
138 /* We do have a DOS image so we will now try to seek into
139 * the file by the amount indicated by the field
140 * "Offset to extended header" and read in the
141 * "magic" field information at that location.
142 * This will tell us if there is more header information
145 if((SetFilePointer(hFile
, Header
.mz
.e_lfanew
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
146 (!ReadFile(hFile
, magic
, sizeof(magic
), &Read
, NULL
) ||
147 (Read
!= sizeof(magic
))))
152 /* Reading the magic field succeeded so
153 * we will try to determine what type it is.
155 if(!memcmp(magic
, "PE\0\0", sizeof(magic
)))
157 IMAGE_FILE_HEADER FileHeader
;
158 if(!ReadFile(hFile
, &FileHeader
, sizeof(IMAGE_FILE_HEADER
), &Read
, NULL
) ||
159 (Read
!= sizeof(IMAGE_FILE_HEADER
)))
164 /* FIXME - detect 32/64 bit */
166 if(FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
167 return BINARY_PE_DLL32
;
168 return BINARY_PE_EXE32
;
171 if(!memcmp(magic
, "NE", 1))
173 /* This is a Windows executable (NE) header. This can
174 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
175 * DOS program (running under a DOS extender). To decide
176 * which, we'll have to read the NE header.
179 if((SetFilePointer(hFile
, Header
.mz
.e_lfanew
, NULL
, FILE_BEGIN
) == 1) ||
180 !ReadFile(hFile
, &ne
, sizeof(IMAGE_OS2_HEADER
), &Read
, NULL
) ||
181 (Read
!= sizeof(IMAGE_OS2_HEADER
)))
183 /* Couldn't read header, so abort. */
194 return InternalIsOS2OrOldWin(hFile
, &Header
.mz
, &ne
);
199 return BINARY_UNKNOWN
;
208 LPCWSTR lpApplicationName
,
215 if(!lpApplicationName
|| !lpBinaryType
)
217 SetLastError(ERROR_INVALID_PARAMETER
);
221 hFile
= CreateFileW(lpApplicationName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
222 OPEN_EXISTING
, 0, 0);
223 if(hFile
== INVALID_HANDLE_VALUE
)
228 BinType
= InternalGetBinaryType(hFile
);
238 * guess from filename
240 if(!(dot
= wcsrchr(lpApplicationName
, L
'.')))
244 if(!lstrcmpiW(dot
, L
".COM"))
246 *lpBinaryType
= SCS_DOS_BINARY
;
249 if(!lstrcmpiW(dot
, L
".PIF"))
251 *lpBinaryType
= SCS_PIF_BINARY
;
256 case BINARY_PE_EXE32
:
257 case BINARY_PE_DLL32
:
259 *lpBinaryType
= SCS_32BIT_BINARY
;
262 case BINARY_PE_EXE64
:
263 case BINARY_PE_DLL64
:
265 *lpBinaryType
= SCS_64BIT_BINARY
;
270 *lpBinaryType
= SCS_WOW_BINARY
;
275 *lpBinaryType
= SCS_OS216_BINARY
;
280 *lpBinaryType
= SCS_DOS_BINARY
;
283 case BINARY_UNIX_EXE
:
284 case BINARY_UNIX_LIB
:
290 DPRINT1("Invalid binary type returned!\n", BinType
);
299 GetBinaryTypeA(IN LPCSTR lpApplicationName
,
300 OUT LPDWORD lpBinaryType
)
302 ANSI_STRING ApplicationNameString
;
303 UNICODE_STRING ApplicationNameW
;
304 BOOL StringAllocated
= FALSE
, Result
;
307 RtlInitAnsiString(&ApplicationNameString
, lpApplicationName
);
309 if (ApplicationNameString
.Length
* sizeof(WCHAR
) >= NtCurrentTeb()->StaticUnicodeString
.MaximumLength
)
311 StringAllocated
= TRUE
;
312 Status
= RtlAnsiStringToUnicodeString(&ApplicationNameW
, &ApplicationNameString
, TRUE
);
316 Status
= RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString
), &ApplicationNameString
, FALSE
);
319 if (!NT_SUCCESS(Status
))
321 BaseSetLastNTError(Status
);
327 Result
= GetBinaryTypeW(ApplicationNameW
.Buffer
, lpBinaryType
);
328 RtlFreeUnicodeString(&ApplicationNameW
);
332 Result
= GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString
.Buffer
, lpBinaryType
);
385 GetVDMCurrentDirectories (
424 RegisterWowBaseHandlers (
452 SetVDMCurrentDirectories (
466 VDMConsoleOperation (
481 VDMOperationStarted (