4 * Copyright 1995 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
29 #include <sys/types.h>
34 #define WIN32_NO_STATUS
39 #include "kernel_private.h"
42 #include "wine/exception.h"
43 #include "wine/list.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(module
);
51 /****************************************************************************
52 * GetDllDirectoryA (KERNEL32.@)
54 DWORD WINAPI
GetDllDirectoryA( DWORD buf_len
, LPSTR buffer
)
62 str
.MaximumLength
= sizeof(data
);
66 status
= LdrGetDllDirectory( &str
);
67 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
68 if (str
.Buffer
!= data
) HeapFree( GetProcessHeap(), 0, str
.Buffer
);
69 str
.MaximumLength
= str
.Length
;
70 if (!(str
.Buffer
= HeapAlloc( GetProcessHeap(), 0, str
.MaximumLength
)))
72 status
= STATUS_NO_MEMORY
;
77 if (!set_ntstatus( status
)) return 0;
79 len
= FILE_name_WtoA( str
.Buffer
, str
.Length
/ sizeof(WCHAR
), NULL
, 0 );
80 if (buffer
&& buf_len
> len
)
82 FILE_name_WtoA( str
.Buffer
, -1, buffer
, buf_len
);
86 len
++; /* for terminating null */
87 if (buffer
) *buffer
= 0;
89 if (str
.Buffer
!= data
) HeapFree( GetProcessHeap(), 0, str
.Buffer
);
94 /****************************************************************************
95 * GetDllDirectoryW (KERNEL32.@)
97 DWORD WINAPI
GetDllDirectoryW( DWORD buf_len
, LPWSTR buffer
)
103 str
.MaximumLength
= min( buf_len
, UNICODE_STRING_MAX_CHARS
) * sizeof(WCHAR
);
104 status
= LdrGetDllDirectory( &str
);
105 if (status
== STATUS_BUFFER_TOO_SMALL
) status
= STATUS_SUCCESS
;
106 if (!set_ntstatus( status
)) return 0;
107 return str
.Length
/ sizeof(WCHAR
);
111 /****************************************************************************
112 * SetDllDirectoryA (KERNEL32.@)
114 BOOL WINAPI
SetDllDirectoryA( LPCSTR dir
)
119 if (dir
&& !(dirW
= FILE_name_AtoW( dir
, TRUE
))) return FALSE
;
120 ret
= SetDllDirectoryW( dirW
);
121 HeapFree( GetProcessHeap(), 0, dirW
);
126 /****************************************************************************
127 * SetDllDirectoryW (KERNEL32.@)
129 BOOL WINAPI
SetDllDirectoryW( LPCWSTR dir
)
133 RtlInitUnicodeString( &str
, dir
);
134 return set_ntstatus( LdrSetDllDirectory( &str
));
138 /***********************************************************************
139 * GetBinaryTypeW [KERNEL32.@]
141 * Determine whether a file is executable, and if so, what kind.
144 * lpApplicationName [I] Path of the file to check
145 * lpBinaryType [O] Destination for the binary type
148 * TRUE, if the file is an executable, in which case lpBinaryType is set.
149 * FALSE, if the file is not an executable or if the function fails.
152 * The type of executable is a property that determines which subsystem an
153 * executable file runs under. lpBinaryType can be set to one of the following
155 * SCS_32BIT_BINARY: A Win32 based application
156 * SCS_64BIT_BINARY: A Win64 based application
157 * SCS_DOS_BINARY: An MS-Dos based application
158 * SCS_WOW_BINARY: A Win16 based application
159 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
160 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
161 * SCS_OS216_BINARY: A 16bit OS/2 based application
163 * To find the binary type, this function reads in the files header information.
164 * If extended header information is not present it will assume that the file
165 * is a DOS executable. If extended header information is present it will
166 * determine if the file is a 16, 32 or 64 bit Windows executable by checking the
167 * flags in the header.
169 * ".com" and ".pif" files are only recognized by their file name extension,
170 * as per native Windows.
172 BOOL WINAPI
GetBinaryTypeW( LPCWSTR name
, LPDWORD type
)
174 static const WCHAR comW
[] = { '.','c','o','m',0 };
175 static const WCHAR pifW
[] = { '.','p','i','f',0 };
176 HANDLE hfile
, mapping
;
180 TRACE("%s\n", debugstr_w(name
) );
182 if (type
== NULL
) return FALSE
;
184 hfile
= CreateFileW( name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
185 if ( hfile
== INVALID_HANDLE_VALUE
)
188 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
,
189 NULL
, NULL
, PAGE_READONLY
, SEC_IMAGE
, hfile
);
190 CloseHandle( hfile
);
196 SECTION_IMAGE_INFORMATION info
;
198 status
= NtQuerySection( mapping
, SectionImageInformation
, &info
, sizeof(info
), NULL
);
199 CloseHandle( mapping
);
200 if (status
) return FALSE
;
201 switch (info
.Machine
)
203 case IMAGE_FILE_MACHINE_I386
:
204 case IMAGE_FILE_MACHINE_ARM
:
205 case IMAGE_FILE_MACHINE_THUMB
:
206 case IMAGE_FILE_MACHINE_ARMNT
:
207 case IMAGE_FILE_MACHINE_POWERPC
:
208 *type
= SCS_32BIT_BINARY
;
210 case IMAGE_FILE_MACHINE_AMD64
:
211 case IMAGE_FILE_MACHINE_ARM64
:
212 *type
= SCS_64BIT_BINARY
;
217 case STATUS_INVALID_IMAGE_WIN_16
:
218 *type
= SCS_WOW_BINARY
;
220 case STATUS_INVALID_IMAGE_WIN_32
:
221 *type
= SCS_32BIT_BINARY
;
223 case STATUS_INVALID_IMAGE_WIN_64
:
224 *type
= SCS_64BIT_BINARY
;
226 case STATUS_INVALID_IMAGE_NE_FORMAT
:
227 *type
= SCS_OS216_BINARY
;
229 case STATUS_INVALID_IMAGE_PROTECT
:
230 *type
= SCS_DOS_BINARY
;
232 case STATUS_INVALID_IMAGE_NOT_MZ
:
233 if ((ptr
= strrchrW( name
, '.' )))
235 if (!strcmpiW( ptr
, comW
))
237 *type
= SCS_DOS_BINARY
;
240 if (!strcmpiW( ptr
, pifW
))
242 *type
= SCS_PIF_BINARY
;
252 /***********************************************************************
253 * GetBinaryTypeA [KERNEL32.@]
254 * GetBinaryType [KERNEL32.@]
256 * See GetBinaryTypeW.
258 BOOL WINAPI
GetBinaryTypeA( LPCSTR lpApplicationName
, LPDWORD lpBinaryType
)
260 ANSI_STRING app_nameA
;
262 TRACE("%s\n", debugstr_a(lpApplicationName
));
266 if ( lpApplicationName
== NULL
|| lpBinaryType
== NULL
)
269 RtlInitAnsiString(&app_nameA
, lpApplicationName
);
270 if (!set_ntstatus( RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
271 &app_nameA
, FALSE
)))
273 return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString
.Buffer
, lpBinaryType
);
276 /***********************************************************************
277 * GetProcAddress (KERNEL32.@)
279 * Find the address of an exported symbol in a loaded dll.
282 * hModule [I] Handle to the dll returned by LoadLibraryA().
283 * function [I] Name of the symbol, or an integer ordinal number < 16384
286 * Success: A pointer to the symbol in the process address space.
287 * Failure: NULL. Use GetLastError() to determine the cause.
289 FARPROC
get_proc_address( HMODULE hModule
, LPCSTR function
)
293 if (!hModule
) hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
295 if ((ULONG_PTR
)function
>> 16)
299 RtlInitAnsiString( &str
, function
);
300 if (!set_ntstatus( LdrGetProcedureAddress( hModule
, &str
, 0, (void**)&fp
))) return NULL
;
303 if (!set_ntstatus( LdrGetProcedureAddress( hModule
, NULL
, LOWORD(function
), (void**)&fp
)))
311 * Work around a Delphi bug on x86_64. When delay loading a symbol,
312 * Delphi saves rcx, rdx, r8 and r9 to the stack. It then calls
313 * GetProcAddress(), pops the saved registers and calls the function.
314 * This works fine if all of the parameters are ints. However, since
315 * it does not save xmm0 - 3, it relies on GetProcAddress() preserving
316 * these registers if the function takes floating point parameters.
317 * This wrapper saves xmm0 - 3 to the stack.
319 extern FARPROC
get_proc_address_wrapper( HMODULE module
, LPCSTR function
);
321 __ASM_GLOBAL_FUNC( get_proc_address_wrapper
,
323 __ASM_SEH(".seh_pushreg %rbp\n\t")
324 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
325 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
327 __ASM_SEH(".seh_setframe %rbp,0\n\t")
328 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
329 "subq $0x40,%rsp\n\t"
330 __ASM_SEH(".seh_stackalloc 0x40\n\t")
331 __ASM_SEH(".seh_endprologue\n\t")
332 "movaps %xmm0,-0x10(%rbp)\n\t"
333 "movaps %xmm1,-0x20(%rbp)\n\t"
334 "movaps %xmm2,-0x30(%rbp)\n\t"
335 "movaps %xmm3,-0x40(%rbp)\n\t"
336 "call " __ASM_NAME("get_proc_address") "\n\t"
337 "movaps -0x40(%rbp), %xmm3\n\t"
338 "movaps -0x30(%rbp), %xmm2\n\t"
339 "movaps -0x20(%rbp), %xmm1\n\t"
340 "movaps -0x10(%rbp), %xmm0\n\t"
341 "leaq 0(%rbp),%rsp\n\t"
342 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
344 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
345 __ASM_CFI(".cfi_same_value %rbp\n\t")
347 #else /* __x86_64__ */
349 static inline FARPROC
get_proc_address_wrapper( HMODULE module
, LPCSTR function
)
351 return get_proc_address( module
, function
);
354 #endif /* __x86_64__ */
356 FARPROC WINAPI
GetProcAddress( HMODULE hModule
, LPCSTR function
)
358 return get_proc_address_wrapper( hModule
, function
);
363 /***********************************************************************
364 * __wine_dll_register_16 (KERNEL32.@)
368 void __wine_dll_register_16( const IMAGE_DOS_HEADER
*header
, const char *file_name
)
370 ERR( "loading old style 16-bit dll %s no longer supported\n", file_name
);
374 /***********************************************************************
375 * __wine_dll_unregister_16 (KERNEL32.@)
379 void __wine_dll_unregister_16( const IMAGE_DOS_HEADER
*header
)