widl: Generate helper macros for WinRT implementation.
[wine/zf.git] / dlls / kernel32 / module.c
blob0449bedf83f7f91ea97a9a36cbaa88b0e5b7fd13
1 /*
2 * Modules
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
21 #include <fcntl.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winternl.h"
34 #include "kernel_private.h"
35 #include "psapi.h"
37 #include "wine/exception.h"
38 #include "wine/list.h"
39 #include "wine/asm.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 )
50 UNICODE_STRING str;
51 NTSTATUS status;
52 WCHAR data[MAX_PATH];
53 DWORD len;
55 str.Buffer = data;
56 str.MaximumLength = sizeof(data);
58 for (;;)
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;
67 break;
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 );
78 else
80 len++; /* for terminating null */
81 if (buffer) *buffer = 0;
83 if (str.Buffer != data) HeapFree( GetProcessHeap(), 0, str.Buffer );
84 return len;
88 /****************************************************************************
89 * GetDllDirectoryW (KERNEL32.@)
91 DWORD WINAPI GetDllDirectoryW( DWORD buf_len, LPWSTR buffer )
93 UNICODE_STRING str;
94 NTSTATUS status;
96 str.Buffer = 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 )
110 WCHAR *dirW = NULL;
111 BOOL ret;
113 if (dir && !(dirW = FILE_name_AtoW( dir, TRUE ))) return FALSE;
114 ret = SetDllDirectoryW( dirW );
115 HeapFree( GetProcessHeap(), 0, dirW );
116 return ret;
120 /****************************************************************************
121 * SetDllDirectoryW (KERNEL32.@)
123 BOOL WINAPI SetDllDirectoryW( LPCWSTR dir )
125 UNICODE_STRING str;
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.
137 * PARAMS
138 * lpApplicationName [I] Path of the file to check
139 * lpBinaryType [O] Destination for the binary type
141 * RETURNS
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.
145 * NOTES
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
148 * values:
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;
169 NTSTATUS status;
170 const WCHAR *ptr;
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 )
178 return FALSE;
180 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY,
181 NULL, NULL, PAGE_READONLY, SEC_IMAGE, hfile );
182 CloseHandle( hfile );
184 switch (status)
186 case STATUS_SUCCESS:
188 SECTION_IMAGE_INFORMATION info;
190 status = NtQuerySection( mapping, SectionImageInformation, &info, sizeof(info), NULL );
191 CloseHandle( mapping );
192 if (status) return FALSE;
193 switch (info.Machine)
195 case IMAGE_FILE_MACHINE_I386:
196 case IMAGE_FILE_MACHINE_ARM:
197 case IMAGE_FILE_MACHINE_THUMB:
198 case IMAGE_FILE_MACHINE_ARMNT:
199 case IMAGE_FILE_MACHINE_POWERPC:
200 *type = SCS_32BIT_BINARY;
201 return TRUE;
202 case IMAGE_FILE_MACHINE_AMD64:
203 case IMAGE_FILE_MACHINE_ARM64:
204 *type = SCS_64BIT_BINARY;
205 return TRUE;
207 return FALSE;
209 case STATUS_INVALID_IMAGE_WIN_16:
210 *type = SCS_WOW_BINARY;
211 return TRUE;
212 case STATUS_INVALID_IMAGE_WIN_32:
213 *type = SCS_32BIT_BINARY;
214 return TRUE;
215 case STATUS_INVALID_IMAGE_WIN_64:
216 *type = SCS_64BIT_BINARY;
217 return TRUE;
218 case STATUS_INVALID_IMAGE_NE_FORMAT:
219 *type = SCS_OS216_BINARY;
220 return TRUE;
221 case STATUS_INVALID_IMAGE_PROTECT:
222 *type = SCS_DOS_BINARY;
223 return TRUE;
224 case STATUS_INVALID_IMAGE_NOT_MZ:
225 if ((ptr = wcsrchr( name, '.' )))
227 if (!wcsicmp( ptr, L".com" ))
229 *type = SCS_DOS_BINARY;
230 return TRUE;
232 if (!wcsicmp( ptr, L".pif" ))
234 *type = SCS_PIF_BINARY;
235 return TRUE;
238 return FALSE;
239 default:
240 return FALSE;
244 /***********************************************************************
245 * GetBinaryTypeA [KERNEL32.@]
246 * GetBinaryType [KERNEL32.@]
248 * See GetBinaryTypeW.
250 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
252 ANSI_STRING app_nameA;
254 TRACE("%s\n", debugstr_a(lpApplicationName));
256 /* Sanity check.
258 if ( lpApplicationName == NULL || lpBinaryType == NULL )
259 return FALSE;
261 RtlInitAnsiString(&app_nameA, lpApplicationName);
262 if (!set_ntstatus( RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
263 &app_nameA, FALSE )))
264 return FALSE;
265 return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
268 /***********************************************************************
269 * GetProcAddress (KERNEL32.@)
271 * Find the address of an exported symbol in a loaded dll.
273 * PARAMS
274 * hModule [I] Handle to the dll returned by LoadLibraryA().
275 * function [I] Name of the symbol, or an integer ordinal number < 16384
277 * RETURNS
278 * Success: A pointer to the symbol in the process address space.
279 * Failure: NULL. Use GetLastError() to determine the cause.
281 FARPROC get_proc_address( HMODULE hModule, LPCSTR function )
283 FARPROC fp;
285 if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
287 if ((ULONG_PTR)function >> 16)
289 ANSI_STRING str;
291 RtlInitAnsiString( &str, function );
292 if (!set_ntstatus( LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp ))) return NULL;
294 else
295 if (!set_ntstatus( LdrGetProcedureAddress( hModule, NULL, LOWORD(function), (void**)&fp )))
296 return NULL;
298 return fp;
301 #ifdef __x86_64__
303 * Work around a Delphi bug on x86_64. When delay loading a symbol,
304 * Delphi saves rcx, rdx, r8 and r9 to the stack. It then calls
305 * GetProcAddress(), pops the saved registers and calls the function.
306 * This works fine if all of the parameters are ints. However, since
307 * it does not save xmm0 - 3, it relies on GetProcAddress() preserving
308 * these registers if the function takes floating point parameters.
309 * This wrapper saves xmm0 - 3 to the stack.
311 extern FARPROC get_proc_address_wrapper( HMODULE module, LPCSTR function );
313 __ASM_GLOBAL_FUNC( get_proc_address_wrapper,
314 "pushq %rbp\n\t"
315 __ASM_SEH(".seh_pushreg %rbp\n\t")
316 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
317 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
318 "movq %rsp,%rbp\n\t"
319 __ASM_SEH(".seh_setframe %rbp,0\n\t")
320 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
321 __ASM_SEH(".seh_endprologue\n\t")
322 "subq $0x60,%rsp\n\t"
323 "andq $~15,%rsp\n\t"
324 "movaps %xmm0,0x20(%rsp)\n\t"
325 "movaps %xmm1,0x30(%rsp)\n\t"
326 "movaps %xmm2,0x40(%rsp)\n\t"
327 "movaps %xmm3,0x50(%rsp)\n\t"
328 "call " __ASM_NAME("get_proc_address") "\n\t"
329 "movaps 0x50(%rsp), %xmm3\n\t"
330 "movaps 0x40(%rsp), %xmm2\n\t"
331 "movaps 0x30(%rsp), %xmm1\n\t"
332 "movaps 0x20(%rsp), %xmm0\n\t"
333 "leaq 0(%rbp),%rsp\n\t"
334 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
335 "popq %rbp\n\t"
336 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
337 __ASM_CFI(".cfi_same_value %rbp\n\t")
338 "ret" )
339 #else /* __x86_64__ */
341 static inline FARPROC get_proc_address_wrapper( HMODULE module, LPCSTR function )
343 return get_proc_address( module, function );
346 #endif /* __x86_64__ */
348 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
350 return get_proc_address_wrapper( hModule, function );