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
26 #include <sys/types.h>
29 #define WIN32_NO_STATUS
34 #include "kernel_private.h"
37 #include "wine/exception.h"
38 #include "wine/list.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(module
);
45 /****************************************************************************
46 * GetDllDirectoryA (KERNEL32.@)
48 DWORD WINAPI
GetDllDirectoryA( DWORD buf_len
, LPSTR buffer
)
56 str
.MaximumLength
= sizeof(data
);
60 status
= LdrGetDllDirectory( &str
);
61 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
62 if (str
.Buffer
!= data
) HeapFree( GetProcessHeap(), 0, str
.Buffer
);
63 str
.MaximumLength
= str
.Length
;
64 if (!(str
.Buffer
= HeapAlloc( GetProcessHeap(), 0, str
.MaximumLength
)))
66 status
= STATUS_NO_MEMORY
;
71 if (!set_ntstatus( status
)) return 0;
73 len
= FILE_name_WtoA( str
.Buffer
, str
.Length
/ sizeof(WCHAR
), NULL
, 0 );
74 if (buffer
&& buf_len
> len
)
76 FILE_name_WtoA( str
.Buffer
, -1, buffer
, buf_len
);
80 len
++; /* for terminating null */
81 if (buffer
) *buffer
= 0;
83 if (str
.Buffer
!= data
) HeapFree( GetProcessHeap(), 0, str
.Buffer
);
88 /****************************************************************************
89 * GetDllDirectoryW (KERNEL32.@)
91 DWORD WINAPI
GetDllDirectoryW( DWORD buf_len
, LPWSTR buffer
)
97 str
.MaximumLength
= min( buf_len
, UNICODE_STRING_MAX_CHARS
) * sizeof(WCHAR
);
98 status
= LdrGetDllDirectory( &str
);
99 if (status
== STATUS_BUFFER_TOO_SMALL
) status
= STATUS_SUCCESS
;
100 if (!set_ntstatus( status
)) return 0;
101 return str
.Length
/ sizeof(WCHAR
);
105 /****************************************************************************
106 * SetDllDirectoryA (KERNEL32.@)
108 BOOL WINAPI
SetDllDirectoryA( LPCSTR dir
)
113 if (dir
&& !(dirW
= FILE_name_AtoW( dir
, TRUE
))) return FALSE
;
114 ret
= SetDllDirectoryW( dirW
);
115 HeapFree( GetProcessHeap(), 0, dirW
);
120 /****************************************************************************
121 * SetDllDirectoryW (KERNEL32.@)
123 BOOL WINAPI
SetDllDirectoryW( LPCWSTR dir
)
127 RtlInitUnicodeString( &str
, dir
);
128 return set_ntstatus( LdrSetDllDirectory( &str
));
132 /***********************************************************************
133 * GetBinaryTypeW [KERNEL32.@]
135 * Determine whether a file is executable, and if so, what kind.
138 * lpApplicationName [I] Path of the file to check
139 * lpBinaryType [O] Destination for the binary type
142 * TRUE, if the file is an executable, in which case lpBinaryType is set.
143 * FALSE, if the file is not an executable or if the function fails.
146 * The type of executable is a property that determines which subsystem an
147 * executable file runs under. lpBinaryType can be set to one of the following
149 * SCS_32BIT_BINARY: A Win32 based application
150 * SCS_64BIT_BINARY: A Win64 based application
151 * SCS_DOS_BINARY: An MS-Dos based application
152 * SCS_WOW_BINARY: A Win16 based application
153 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
154 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
155 * SCS_OS216_BINARY: A 16bit OS/2 based application
157 * To find the binary type, this function reads in the files header information.
158 * If extended header information is not present it will assume that the file
159 * is a DOS executable. If extended header information is present it will
160 * determine if the file is a 16, 32 or 64 bit Windows executable by checking the
161 * flags in the header.
163 * ".com" and ".pif" files are only recognized by their file name extension,
164 * as per native Windows.
166 BOOL WINAPI
GetBinaryTypeW( LPCWSTR name
, LPDWORD type
)
168 HANDLE hfile
, mapping
;
172 TRACE("%s\n", debugstr_w(name
) );
174 if (type
== NULL
) return FALSE
;
176 hfile
= CreateFileW( name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
177 if ( hfile
== INVALID_HANDLE_VALUE
)
180 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
,
181 NULL
, NULL
, PAGE_READONLY
, SEC_IMAGE
, hfile
);
182 CloseHandle( hfile
);
188 SECTION_IMAGE_INFORMATION info
;
190 status
= NtQuerySection( mapping
, SectionImageInformation
, &info
, sizeof(info
), NULL
);
191 CloseHandle( mapping
);
192 if (status
) return FALSE
;
193 if (info
.ImageCharacteristics
& IMAGE_FILE_DLL
) return FALSE
;
194 switch (info
.Machine
)
196 case IMAGE_FILE_MACHINE_I386
:
197 case IMAGE_FILE_MACHINE_ARMNT
:
198 *type
= SCS_32BIT_BINARY
;
200 case IMAGE_FILE_MACHINE_AMD64
:
201 case IMAGE_FILE_MACHINE_ARM64
:
202 *type
= SCS_64BIT_BINARY
;
207 case STATUS_INVALID_IMAGE_WIN_16
:
208 *type
= SCS_WOW_BINARY
;
210 case STATUS_INVALID_IMAGE_WIN_32
:
211 *type
= SCS_32BIT_BINARY
;
213 case STATUS_INVALID_IMAGE_WIN_64
:
214 *type
= SCS_64BIT_BINARY
;
216 case STATUS_INVALID_IMAGE_NE_FORMAT
:
217 *type
= SCS_OS216_BINARY
;
219 case STATUS_INVALID_IMAGE_PROTECT
:
220 *type
= SCS_DOS_BINARY
;
222 case STATUS_INVALID_IMAGE_NOT_MZ
:
223 if ((ptr
= wcsrchr( name
, '.' )))
225 if (!wcsicmp( ptr
, L
".com" ))
227 *type
= SCS_DOS_BINARY
;
230 if (!wcsicmp( ptr
, L
".pif" ))
232 *type
= SCS_PIF_BINARY
;
242 /***********************************************************************
243 * GetBinaryTypeA [KERNEL32.@]
244 * GetBinaryType [KERNEL32.@]
246 * See GetBinaryTypeW.
248 BOOL WINAPI
GetBinaryTypeA( LPCSTR lpApplicationName
, LPDWORD lpBinaryType
)
250 ANSI_STRING app_nameA
;
252 TRACE("%s\n", debugstr_a(lpApplicationName
));
256 if ( lpApplicationName
== NULL
|| lpBinaryType
== NULL
)
259 RtlInitAnsiString(&app_nameA
, lpApplicationName
);
260 if (!set_ntstatus( RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
261 &app_nameA
, FALSE
)))
263 return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString
.Buffer
, lpBinaryType
);
266 /***********************************************************************
267 * GetProcAddress (KERNEL32.@)
269 * Find the address of an exported symbol in a loaded dll.
272 * hModule [I] Handle to the dll returned by LoadLibraryA().
273 * function [I] Name of the symbol, or an integer ordinal number < 16384
276 * Success: A pointer to the symbol in the process address space.
277 * Failure: NULL. Use GetLastError() to determine the cause.
279 FARPROC
get_proc_address( HMODULE hModule
, LPCSTR function
)
283 if (!hModule
) hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
285 if ((ULONG_PTR
)function
>> 16)
289 RtlInitAnsiString( &str
, function
);
290 if (!set_ntstatus( LdrGetProcedureAddress( hModule
, &str
, 0, (void**)&fp
))) return NULL
;
293 if (!set_ntstatus( LdrGetProcedureAddress( hModule
, NULL
, LOWORD(function
), (void**)&fp
)))
301 * Work around a Delphi bug on x86_64. When delay loading a symbol,
302 * Delphi saves rcx, rdx, r8 and r9 to the stack. It then calls
303 * GetProcAddress(), pops the saved registers and calls the function.
304 * This works fine if all of the parameters are ints. However, since
305 * it does not save xmm0 - 3, it relies on GetProcAddress() preserving
306 * these registers if the function takes floating point parameters.
307 * This wrapper saves xmm0 - 3 to the stack.
309 extern FARPROC
get_proc_address_wrapper( HMODULE module
, LPCSTR function
);
311 __ASM_GLOBAL_FUNC( get_proc_address_wrapper
,
313 __ASM_SEH(".seh_pushreg %rbp\n\t")
314 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
315 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
317 __ASM_SEH(".seh_setframe %rbp,0\n\t")
318 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
319 __ASM_SEH(".seh_endprologue\n\t")
320 "subq $0x60,%rsp\n\t"
322 "movaps %xmm0,0x20(%rsp)\n\t"
323 "movaps %xmm1,0x30(%rsp)\n\t"
324 "movaps %xmm2,0x40(%rsp)\n\t"
325 "movaps %xmm3,0x50(%rsp)\n\t"
326 "call " __ASM_NAME("get_proc_address") "\n\t"
327 "movaps 0x50(%rsp), %xmm3\n\t"
328 "movaps 0x40(%rsp), %xmm2\n\t"
329 "movaps 0x30(%rsp), %xmm1\n\t"
330 "movaps 0x20(%rsp), %xmm0\n\t"
331 "leaq 0(%rbp),%rsp\n\t"
332 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
334 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
335 __ASM_CFI(".cfi_same_value %rbp\n\t")
337 #else /* __x86_64__ */
339 static inline FARPROC
get_proc_address_wrapper( HMODULE module
, LPCSTR function
)
341 return get_proc_address( module
, function
);
344 #endif /* __x86_64__ */
346 FARPROC WINAPI
GetProcAddress( HMODULE hModule
, LPCSTR function
)
348 return get_proc_address_wrapper( hModule
, function
);