amstream: Implement AMAudioStream::NewSegment.
[wine/zf.git] / dlls / kernel32 / module.c
blob7f27293ee2f9b952d4b3e85b9207eef0236d8f51
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 "config.h"
22 #include "wine/port.h"
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "winerror.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winternl.h"
39 #include "kernel_private.h"
40 #include "psapi.h"
42 #include "wine/exception.h"
43 #include "wine/list.h"
44 #include "wine/asm.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 )
56 UNICODE_STRING str;
57 NTSTATUS status;
58 WCHAR data[MAX_PATH];
59 DWORD len;
61 str.Buffer = data;
62 str.MaximumLength = sizeof(data);
64 for (;;)
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;
73 break;
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 );
84 else
86 len++; /* for terminating null */
87 if (buffer) *buffer = 0;
89 if (str.Buffer != data) HeapFree( GetProcessHeap(), 0, str.Buffer );
90 return len;
94 /****************************************************************************
95 * GetDllDirectoryW (KERNEL32.@)
97 DWORD WINAPI GetDllDirectoryW( DWORD buf_len, LPWSTR buffer )
99 UNICODE_STRING str;
100 NTSTATUS status;
102 str.Buffer = 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 )
116 WCHAR *dirW = NULL;
117 BOOL ret;
119 if (dir && !(dirW = FILE_name_AtoW( dir, TRUE ))) return FALSE;
120 ret = SetDllDirectoryW( dirW );
121 HeapFree( GetProcessHeap(), 0, dirW );
122 return ret;
126 /****************************************************************************
127 * SetDllDirectoryW (KERNEL32.@)
129 BOOL WINAPI SetDllDirectoryW( LPCWSTR dir )
131 UNICODE_STRING str;
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.
143 * PARAMS
144 * lpApplicationName [I] Path of the file to check
145 * lpBinaryType [O] Destination for the binary type
147 * RETURNS
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.
151 * NOTES
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
154 * values:
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;
177 NTSTATUS status;
178 const WCHAR *ptr;
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 )
186 return FALSE;
188 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY,
189 NULL, NULL, PAGE_READONLY, SEC_IMAGE, hfile );
190 CloseHandle( hfile );
192 switch (status)
194 case STATUS_SUCCESS:
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;
209 return TRUE;
210 case IMAGE_FILE_MACHINE_AMD64:
211 case IMAGE_FILE_MACHINE_ARM64:
212 *type = SCS_64BIT_BINARY;
213 return TRUE;
215 return FALSE;
217 case STATUS_INVALID_IMAGE_WIN_16:
218 *type = SCS_WOW_BINARY;
219 return TRUE;
220 case STATUS_INVALID_IMAGE_WIN_32:
221 *type = SCS_32BIT_BINARY;
222 return TRUE;
223 case STATUS_INVALID_IMAGE_WIN_64:
224 *type = SCS_64BIT_BINARY;
225 return TRUE;
226 case STATUS_INVALID_IMAGE_NE_FORMAT:
227 *type = SCS_OS216_BINARY;
228 return TRUE;
229 case STATUS_INVALID_IMAGE_PROTECT:
230 *type = SCS_DOS_BINARY;
231 return TRUE;
232 case STATUS_INVALID_IMAGE_NOT_MZ:
233 if ((ptr = strrchrW( name, '.' )))
235 if (!strcmpiW( ptr, comW ))
237 *type = SCS_DOS_BINARY;
238 return TRUE;
240 if (!strcmpiW( ptr, pifW ))
242 *type = SCS_PIF_BINARY;
243 return TRUE;
246 return FALSE;
247 default:
248 return FALSE;
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));
264 /* Sanity check.
266 if ( lpApplicationName == NULL || lpBinaryType == NULL )
267 return FALSE;
269 RtlInitAnsiString(&app_nameA, lpApplicationName);
270 if (!set_ntstatus( RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
271 &app_nameA, FALSE )))
272 return FALSE;
273 return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
276 /***********************************************************************
277 * GetProcAddress (KERNEL32.@)
279 * Find the address of an exported symbol in a loaded dll.
281 * PARAMS
282 * hModule [I] Handle to the dll returned by LoadLibraryA().
283 * function [I] Name of the symbol, or an integer ordinal number < 16384
285 * RETURNS
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 )
291 FARPROC fp;
293 if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
295 if ((ULONG_PTR)function >> 16)
297 ANSI_STRING str;
299 RtlInitAnsiString( &str, function );
300 if (!set_ntstatus( LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp ))) return NULL;
302 else
303 if (!set_ntstatus( LdrGetProcedureAddress( hModule, NULL, LOWORD(function), (void**)&fp )))
304 return NULL;
306 return fp;
309 #ifdef __x86_64__
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,
322 "pushq %rbp\n\t"
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")
326 "movq %rsp,%rbp\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")
343 "popq %rbp\n\t"
344 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
345 __ASM_CFI(".cfi_same_value %rbp\n\t")
346 "ret" )
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 );
361 #ifdef __i386__
363 /***********************************************************************
364 * __wine_dll_register_16 (KERNEL32.@)
366 * No longer used.
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.@)
377 * No longer used.
379 void __wine_dll_unregister_16( const IMAGE_DOS_HEADER *header )
383 #endif