wine  6.0.1
About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs.
  Fossies Dox: wine-6.0.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

loader.c
Go to the documentation of this file.
1 /*
2  * Loader functions
3  *
4  * Copyright 1995, 2003 Alexandre Julliard
5  * Copyright 2002 Dmitry Timoshkov for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <assert.h>
23 #include <stdarg.h>
24 
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winnt.h"
31 #include "winioctl.h"
32 #include "winternl.h"
33 #include "delayloadhandler.h"
34 
35 #include "wine/exception.h"
36 #include "wine/debug.h"
37 #include "wine/list.h"
38 #include "wine/server.h"
39 #include "ntdll_misc.h"
40 #include "ddk/wdm.h"
41 
47 
48 #ifdef _WIN64
49 #define DEFAULT_SECURITY_COOKIE_64 (((ULONGLONG)0x00002b99 << 32) | 0x2ddfa232)
50 #endif
51 #define DEFAULT_SECURITY_COOKIE_32 0xbb40e64e
52 #define DEFAULT_SECURITY_COOKIE_16 (DEFAULT_SECURITY_COOKIE_32 >> 16)
53 
54 /* we don't want to include winuser.h */
55 #define RT_MANIFEST ((ULONG_PTR)24)
56 #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID ((ULONG_PTR)2)
57 
60 
62 
63 const struct unix_funcs *unix_funcs = NULL;
64 
65 /* windows directory */
66 const WCHAR windows_dir[] = L"C:\\windows";
67 /* system directory with trailing backslash */
68 const WCHAR system_dir[] = L"C:\\windows\\system32\\";
69 const WCHAR syswow64_dir[] = L"C:\\windows\\syswow64\\";
70 
71 static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
73 
74 /* system search path */
75 static const WCHAR system_path[] = L"C:\\windows\\system32;C:\\windows\\system;C:\\windows";
76 
77 static BOOL imports_fixup_done = FALSE; /* set once the imports have been fixed up, before attaching them */
78 static BOOL process_detaching = FALSE; /* set on process detach to avoid deadlocks with thread detach */
79 static int free_lib_count; /* recursion depth of LdrUnloadDll calls */
80 static ULONG path_safe_mode; /* path mode set by RtlSetSearchPathMode */
81 static ULONG dll_safe_mode = 1; /* dll search mode */
82 static UNICODE_STRING dll_directory; /* extra path for LdrSetDllDirectory */
83 static DWORD default_search_flags; /* default flags set by LdrSetDefaultDllDirectories */
84 
86 {
87  struct list entry;
88  WCHAR dir[1];
89 };
90 
91 static struct list dll_dir_list = LIST_INIT( dll_dir_list ); /* extra dirs from LdrAddDllDirectory */
92 
94 {
95  struct list entry;
97  void *context;
98 };
99 
101 
102 static const char * const reason_names[] =
103 {
104  "PROCESS_DETACH",
105  "PROCESS_ATTACH",
106  "THREAD_ATTACH",
107  "THREAD_DETACH",
108  NULL, NULL, NULL, NULL,
109  "WINE_PREATTACH"
110 };
111 
112 struct file_id
113 {
115 };
116 
117 /* internal representation of loaded modules */
118 typedef struct _wine_modref
119 {
121  struct file_id id;
122  void *unix_entry;
124  int nDeps;
125  struct _wine_modref **deps;
127 
128 static UINT tls_module_count; /* number of modules with TLS directory */
129 static IMAGE_TLS_DIRECTORY *tls_dirs; /* array of TLS directories */
131 
134 {
135  0, 0, &loader_section,
137  0, 0, { (DWORD_PTR)(__FILE__ ": loader_section") }
138 };
139 static RTL_CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
140 
143 {
144  0, 0, &dlldir_section,
146  0, 0, { (DWORD_PTR)(__FILE__ ": dlldir_section") }
147 };
148 static CRITICAL_SECTION dlldir_section = { &dlldir_critsect_debug, -1, 0, 0, 0, 0 };
149 
152 {
153  0, 0, &peb_lock,
155  0, 0, { (DWORD_PTR)(__FILE__ ": peb_lock") }
156 };
157 static RTL_CRITICAL_SECTION peb_lock = { &peb_critsect_debug, -1, 0, 0, 0, 0 };
158 
159 static PEB_LDR_DATA ldr = { sizeof(ldr), TRUE };
162 
166 
167 static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
168  DWORD flags, WINE_MODREF** pwm );
169 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved );
171  DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
173  DWORD exp_size, const char *name, int hint, LPCWSTR load_path );
174 
175 /* convert PE image VirtualAddress to Real Address */
176 static inline void *get_rva( HMODULE module, DWORD va )
177 {
178  return (void *)((char *)module + va);
179 }
180 
181 /* check whether the file name contains a path */
182 static inline BOOL contains_path( LPCWSTR name )
183 {
184  return ((*name && (name[1] == ':')) || wcschr(name, '/') || wcschr(name, '\\'));
185 }
186 
187 #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
188 
190 {
191  void *BaseAddress;
198 
201 static unsigned int unload_trace_seq;
202 
204 {
206  unsigned int len = min(sizeof(ptr->ImageName) - sizeof(WCHAR), ldr->BaseDllName.Length);
207 
208  ptr->BaseAddress = ldr->DllBase;
209  ptr->SizeOfImage = ldr->SizeOfImage;
210  ptr->Sequence = unload_trace_seq;
211  ptr->TimeDateStamp = ldr->TimeDateStamp;
212  ptr->CheckSum = ldr->CheckSum;
213  memcpy(ptr->ImageName, ldr->BaseDllName.Buffer, len);
214  ptr->ImageName[len / sizeof(*ptr->ImageName)] = 0;
215 
218 }
219 
220 /*********************************************************************
221  * RtlGetUnloadEventTrace [NTDLL.@]
222  */
224 {
225  return unload_traces;
226 }
227 
228 /*********************************************************************
229  * RtlGetUnloadEventTraceEx [NTDLL.@]
230  */
231 void WINAPI RtlGetUnloadEventTraceEx(ULONG **size, ULONG **count, void **trace)
232 {
233  static unsigned int element_size = sizeof(*unload_traces);
234  static unsigned int element_count = ARRAY_SIZE(unload_traces);
235 
236  *size = &element_size;
237  *count = &element_count;
238  *trace = &unload_trace_ptr;
239 }
240 
241 /*************************************************************************
242  * call_dll_entry_point
243  *
244  * Some brain-damaged dlls (ir32_32.dll for instance) modify ebx in
245  * their entry point, so we need a small asm wrapper. Testing indicates
246  * that only modifying esi leads to a crash, so use this one to backup
247  * ebp while running the dll entry proc.
248  */
249 #ifdef __i386__
250 extern BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module, UINT reason, void *reserved );
252  "pushl %ebp\n\t"
253  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
254  __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
255  "movl %esp,%ebp\n\t"
256  __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
257  "pushl %ebx\n\t"
258  __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t")
259  "pushl %esi\n\t"
260  __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
261  "pushl %edi\n\t"
262  __ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
263  "movl %ebp,%esi\n\t"
264  __ASM_CFI(".cfi_def_cfa_register %esi\n\t")
265  "pushl 20(%ebp)\n\t"
266  "pushl 16(%ebp)\n\t"
267  "pushl 12(%ebp)\n\t"
268  "movl 8(%ebp),%eax\n\t"
269  "call *%eax\n\t"
270  "movl %esi,%ebp\n\t"
271  __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
272  "leal -12(%ebp),%esp\n\t"
273  "popl %edi\n\t"
274  __ASM_CFI(".cfi_same_value %edi\n\t")
275  "popl %esi\n\t"
276  __ASM_CFI(".cfi_same_value %esi\n\t")
277  "popl %ebx\n\t"
278  __ASM_CFI(".cfi_same_value %ebx\n\t")
279  "popl %ebp\n\t"
280  __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
281  __ASM_CFI(".cfi_same_value %ebp\n\t")
282  "ret" )
283 #else /* __i386__ */
285  UINT reason, void *reserved )
286 {
287  return proc( module, reason, reserved );
288 }
289 #endif /* __i386__ */
290 
291 
292 #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
293 /*************************************************************************
294  * stub_entry_point
295  *
296  * Entry point for stub functions.
297  */
298 static void WINAPI stub_entry_point( const char *dll, const char *name, void *ret_addr )
299 {
300  EXCEPTION_RECORD rec;
301 
304  rec.ExceptionRecord = NULL;
305  rec.ExceptionAddress = ret_addr;
306  rec.NumberParameters = 2;
309  for (;;) RtlRaiseException( &rec );
310 }
311 
312 
313 #include "pshpack1.h"
314 #ifdef __i386__
315 struct stub
316 {
317  BYTE pushl1; /* pushl $name */
318  const char *name;
319  BYTE pushl2; /* pushl $dll */
320  const char *dll;
321  BYTE call; /* call stub_entry_point */
322  DWORD entry;
323 };
324 #elif defined(__arm__)
325 struct stub
326 {
327  DWORD ldr_r0; /* ldr r0, $dll */
328  DWORD ldr_r1; /* ldr r1, $name */
329  DWORD mov_r2_lr; /* mov r2, lr */
330  DWORD ldr_pc_pc; /* ldr pc, [pc, #4] */
331  const char *dll;
332  const char *name;
333  const void* entry;
334 };
335 #elif defined(__aarch64__)
336 struct stub
337 {
338  DWORD ldr_x0; /* ldr x0, $dll */
339  DWORD ldr_x1; /* ldr x1, $name */
340  DWORD mov_x2_lr; /* mov x2, lr */
341  DWORD ldr_x16; /* ldr x16, $entry */
342  DWORD br_x16; /* br x16 */
343  const char *dll;
344  const char *name;
345  const void *entry;
346 };
347 #else
348 struct stub
349 {
350  BYTE movq_rdi[2]; /* movq $dll,%rdi */
351  const char *dll;
352  BYTE movq_rsi[2]; /* movq $name,%rsi */
353  const char *name;
354  BYTE movq_rsp_rdx[4]; /* movq (%rsp),%rdx */
355  BYTE movq_rax[2]; /* movq $entry, %rax */
356  const void* entry;
357  BYTE jmpq_rax[2]; /* jmp %rax */
358 };
359 #endif
360 #include "poppack.h"
361 
362 /*************************************************************************
363  * allocate_stub
364  *
365  * Allocate a stub entry point.
366  */
367 static ULONG_PTR allocate_stub( const char *dll, const char *name )
368 {
369 #define MAX_SIZE 65536
370  static struct stub *stubs;
371  static unsigned int nb_stubs;
372  struct stub *stub;
373 
374  if (nb_stubs >= MAX_SIZE / sizeof(*stub)) return 0xdeadbeef;
375 
376  if (!stubs)
377  {
378  SIZE_T size = MAX_SIZE;
379  if (NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&stubs, 0, &size,
381  return 0xdeadbeef;
382  }
383  stub = &stubs[nb_stubs++];
384 #ifdef __i386__
385  stub->pushl1 = 0x68; /* pushl $name */
386  stub->name = name;
387  stub->pushl2 = 0x68; /* pushl $dll */
388  stub->dll = dll;
389  stub->call = 0xe8; /* call stub_entry_point */
390  stub->entry = (BYTE *)stub_entry_point - (BYTE *)(&stub->entry + 1);
391 #elif defined(__arm__)
392  stub->ldr_r0 = 0xe59f0008; /* ldr r0, [pc, #8] ($dll) */
393  stub->ldr_r1 = 0xe59f1008; /* ldr r1, [pc, #8] ($name) */
394  stub->mov_r2_lr = 0xe1a0200e; /* mov r2, lr */
395  stub->ldr_pc_pc = 0xe59ff004; /* ldr pc, [pc, #4] */
396  stub->dll = dll;
397  stub->name = name;
398  stub->entry = stub_entry_point;
399 #elif defined(__aarch64__)
400  stub->ldr_x0 = 0x580000a0; /* ldr x0, #20 ($dll) */
401  stub->ldr_x1 = 0x580000c1; /* ldr x1, #24 ($name) */
402  stub->mov_x2_lr = 0xaa1e03e2; /* mov x2, lr */
403  stub->ldr_x16 = 0x580000d0; /* ldr x16, #24 ($entry) */
404  stub->br_x16 = 0xd61f0200; /* br x16 */
405  stub->dll = dll;
406  stub->name = name;
407  stub->entry = stub_entry_point;
408 #else
409  stub->movq_rdi[0] = 0x48; /* movq $dll,%rcx */
410  stub->movq_rdi[1] = 0xb9;
411  stub->dll = dll;
412  stub->movq_rsi[0] = 0x48; /* movq $name,%rdx */
413  stub->movq_rsi[1] = 0xba;
414  stub->name = name;
415  stub->movq_rsp_rdx[0] = 0x4c; /* movq (%rsp),%r8 */
416  stub->movq_rsp_rdx[1] = 0x8b;
417  stub->movq_rsp_rdx[2] = 0x04;
418  stub->movq_rsp_rdx[3] = 0x24;
419  stub->movq_rax[0] = 0x48; /* movq $entry, %rax */
420  stub->movq_rax[1] = 0xb8;
421  stub->entry = stub_entry_point;
422  stub->jmpq_rax[0] = 0xff; /* jmp %rax */
423  stub->jmpq_rax[1] = 0xe0;
424 #endif
425  return (ULONG_PTR)stub;
426 }
427 
428 #else /* __i386__ */
429 static inline ULONG_PTR allocate_stub( const char *dll, const char *name ) { return 0xdeadbeef; }
430 #endif /* __i386__ */
431 
432 /* call ldr notifications */
434 {
435  struct ldr_notification *notify, *notify_next;
437 
438  data.Loaded.Flags = 0;
439  data.Loaded.FullDllName = &module->FullDllName;
440  data.Loaded.BaseDllName = &module->BaseDllName;
441  data.Loaded.DllBase = module->DllBase;
442  data.Loaded.SizeOfImage = module->SizeOfImage;
443 
445  {
446  TRACE_(relay)("\1Call LDR notification callback (proc=%p,reason=%u,data=%p,context=%p)\n",
447  notify->callback, reason, &data, notify->context );
448 
449  notify->callback(reason, &data, notify->context);
450 
451  TRACE_(relay)("\1Ret LDR notification callback (proc=%p,reason=%u,data=%p,context=%p)\n",
452  notify->callback, reason, &data, notify->context );
453  }
454 }
455 
456 /*************************************************************************
457  * get_modref
458  *
459  * Looks for the referenced HMODULE in the current process
460  * The loader_section must be locked while calling this function.
461  */
463 {
464  PLIST_ENTRY mark, entry;
466 
467  if (cached_modref && cached_modref->ldr.DllBase == hmod) return cached_modref;
468 
469  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
470  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
471  {
472  mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
473  if (mod->DllBase == hmod)
475  }
476  return NULL;
477 }
478 
479 
480 /**********************************************************************
481  * find_basename_module
482  *
483  * Find a module from its base name.
484  * The loader_section must be locked while calling this function
485  */
487 {
488  PLIST_ENTRY mark, entry;
490 
492 
494  return cached_modref;
495 
496  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
497  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
498  {
501  {
503  return cached_modref;
504  }
505  }
506  return NULL;
507 }
508 
509 
510 /**********************************************************************
511  * find_fullname_module
512  *
513  * Find a module from its full path name.
514  * The loader_section must be locked while calling this function
515  */
517 {
518  PLIST_ENTRY mark, entry;
519  UNICODE_STRING name = *nt_name;
520 
521  if (name.Length <= 4 * sizeof(WCHAR)) return NULL;
522  name.Length -= 4 * sizeof(WCHAR); /* for \??\ prefix */
523  name.Buffer += 4;
524 
526  return cached_modref;
527 
528  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
529  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
530  {
532  if (RtlEqualUnicodeString( &name, &mod->FullDllName, TRUE ))
533  {
535  return cached_modref;
536  }
537  }
538  return NULL;
539 }
540 
541 
542 /**********************************************************************
543  * find_fileid_module
544  *
545  * Find a module from its file id.
546  * The loader_section must be locked while calling this function
547  */
548 static WINE_MODREF *find_fileid_module( const struct file_id *id )
549 {
550  LIST_ENTRY *mark, *entry;
551 
552  if (cached_modref && !memcmp( &cached_modref->id, id, sizeof(*id) )) return cached_modref;
553 
554  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
555  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
556  {
559 
560  if (!memcmp( &wm->id, id, sizeof(*id) ))
561  {
562  cached_modref = wm;
563  return wm;
564  }
565  }
566  return NULL;
567 }
568 
569 
570 /*************************************************************************
571  * grow_module_deps
572  */
573 static WINE_MODREF **grow_module_deps( WINE_MODREF *wm, int count )
574 {
575  WINE_MODREF **deps;
576 
577  if (wm->alloc_deps)
579  (wm->alloc_deps + count) * sizeof(*deps) );
580  else
581  deps = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(*deps) );
582 
583  if (deps)
584  {
585  wm->deps = deps;
586  wm->alloc_deps += count;
587  }
588  return deps;
589 }
590 
591 /*************************************************************************
592  * find_forwarded_export
593  *
594  * Find the final function pointer for a forwarded function.
595  * The loader_section must be locked while calling this function.
596  */
598 {
599  const IMAGE_EXPORT_DIRECTORY *exports;
600  DWORD exp_size;
601  WINE_MODREF *wm;
602  WCHAR buffer[32], *mod_name = buffer;
603  const char *end = strrchr(forward, '.');
604  FARPROC proc = NULL;
605 
606  if (!end) return NULL;
607  if ((end - forward) * sizeof(WCHAR) > sizeof(buffer) - sizeof(L".dll"))
608  {
609  if (!(mod_name = RtlAllocateHeap( GetProcessHeap(), 0,
610  (end - forward + sizeof(L".dll")) * sizeof(WCHAR) )))
611  return NULL;
612  }
613  ascii_to_unicode( mod_name, forward, end - forward );
614  mod_name[end - forward] = 0;
615  if (!wcschr( mod_name, '.' ))
616  memcpy( mod_name + (end - forward), L".dll", sizeof(L".dll") );
617 
618  if (!(wm = find_basename_module( mod_name )))
619  {
620  TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
621  if (load_dll( load_path, mod_name, L".dll", 0, &wm ) == STATUS_SUCCESS &&
623  {
625  {
627  if (deps) deps[current_modref->nDeps++] = wm;
628  }
629  else if (process_attach( wm, NULL ) != STATUS_SUCCESS)
630  {
631  LdrUnloadDll( wm->ldr.DllBase );
632  wm = NULL;
633  }
634  }
635 
636  if (!wm)
637  {
638  if (mod_name != buffer) RtlFreeHeap( GetProcessHeap(), 0, mod_name );
639  ERR( "module not found for forward '%s' used by %s\n",
640  forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
641  return NULL;
642  }
643  }
644  if ((exports = RtlImageDirectoryEntryToData( wm->ldr.DllBase, TRUE,
645  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
646  {
647  const char *name = end + 1;
648  if (*name == '#') /* ordinal */
649  proc = find_ordinal_export( wm->ldr.DllBase, exports, exp_size, atoi(name+1), load_path );
650  else
651  proc = find_named_export( wm->ldr.DllBase, exports, exp_size, name, -1, load_path );
652  }
653 
654  if (!proc)
655  {
656  ERR("function not found for forward '%s' used by %s."
657  " If you are using builtin %s, try using the native one instead.\n",
658  forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
659  debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
660  }
661  if (mod_name != buffer) RtlFreeHeap( GetProcessHeap(), 0, mod_name );
662  return proc;
663 }
664 
665 
666 /*************************************************************************
667  * find_ordinal_export
668  *
669  * Find an exported function by ordinal.
670  * The exports base must have been subtracted from the ordinal already.
671  * The loader_section must be locked while calling this function.
672  */
674  DWORD exp_size, DWORD ordinal, LPCWSTR load_path )
675 {
676  FARPROC proc;
677  const DWORD *functions = get_rva( module, exports->AddressOfFunctions );
678 
679  if (ordinal >= exports->NumberOfFunctions)
680  {
681  TRACE(" ordinal %d out of range!\n", ordinal + exports->Base );
682  return NULL;
683  }
684  if (!functions[ordinal]) return NULL;
685 
686  proc = get_rva( module, functions[ordinal] );
687 
688  /* if the address falls into the export dir, it's a forward */
689  if (((const char *)proc >= (const char *)exports) &&
690  ((const char *)proc < (const char *)exports + exp_size))
691  return find_forwarded_export( module, (const char *)proc, load_path );
692 
693  if (TRACE_ON(snoop))
694  {
696  proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal, user );
697  }
698  if (TRACE_ON(relay))
699  {
701  proc = RELAY_GetProcAddress( module, exports, exp_size, proc, ordinal, user );
702  }
703  return proc;
704 }
705 
706 
707 /*************************************************************************
708  * find_named_export
709  *
710  * Find an exported function by name.
711  * The loader_section must be locked while calling this function.
712  */
714  DWORD exp_size, const char *name, int hint, LPCWSTR load_path )
715 {
716  const WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
717  const DWORD *names = get_rva( module, exports->AddressOfNames );
718  int min = 0, max = exports->NumberOfNames - 1;
719 
720  /* first check the hint */
721  if (hint >= 0 && hint <= max)
722  {
723  char *ename = get_rva( module, names[hint] );
724  if (!strcmp( ename, name ))
725  return find_ordinal_export( module, exports, exp_size, ordinals[hint], load_path );
726  }
727 
728  /* then do a binary search */
729  while (min <= max)
730  {
731  int res, pos = (min + max) / 2;
732  char *ename = get_rva( module, names[pos] );
733  if (!(res = strcmp( ename, name )))
734  return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path );
735  if (res > 0) max = pos - 1;
736  else min = pos + 1;
737  }
738  return NULL;
739 
740 }
741 
742 
743 /*************************************************************************
744  * import_dll
745  *
746  * Import the dll specified by the given import descriptor.
747  * The loader_section must be locked while calling this function.
748  */
750 {
752  WINE_MODREF *wmImp;
753  HMODULE imp_mod;
754  const IMAGE_EXPORT_DIRECTORY *exports;
755  DWORD exp_size;
756  const IMAGE_THUNK_DATA *import_list;
757  IMAGE_THUNK_DATA *thunk_list;
758  WCHAR buffer[32];
759  const char *name = get_rva( module, descr->Name );
760  DWORD len = strlen(name);
761  PVOID protect_base;
762  SIZE_T protect_size = 0;
763  DWORD protect_old;
764 
765  thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
766  if (descr->u.OriginalFirstThunk)
767  import_list = get_rva( module, (DWORD)descr->u.OriginalFirstThunk );
768  else
769  import_list = thunk_list;
770 
771  if (!import_list->u1.Ordinal)
772  {
773  WARN( "Skipping unused import %s\n", name );
774  *pwm = NULL;
775  return TRUE;
776  }
777 
778  while (len && name[len-1] == ' ') len--; /* remove trailing spaces */
779 
780  if (len * sizeof(WCHAR) < sizeof(buffer))
781  {
783  buffer[len] = 0;
784  status = load_dll( load_path, buffer, L".dll", 0, &wmImp );
785  }
786  else /* need to allocate a larger buffer */
787  {
788  WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
789  if (!ptr) return FALSE;
790  ascii_to_unicode( ptr, name, len );
791  ptr[len] = 0;
792  status = load_dll( load_path, ptr, L".dll", 0, &wmImp );
793  RtlFreeHeap( GetProcessHeap(), 0, ptr );
794  }
795 
796  if (status)
797  {
799  ERR("Library %s (which is needed by %s) not found\n",
800  name, debugstr_w(current_modref->ldr.FullDllName.Buffer));
801  else
802  ERR("Loading library %s (which is needed by %s) failed (error %x).\n",
804  return FALSE;
805  }
806 
807  /* unprotect the import address table since it can be located in
808  * readonly section */
809  while (import_list[protect_size].u1.Ordinal) protect_size++;
810  protect_base = thunk_list;
811  protect_size *= sizeof(*thunk_list);
812  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,
813  &protect_size, PAGE_READWRITE, &protect_old );
814 
815  imp_mod = wmImp->ldr.DllBase;
816  exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
817 
818  if (!exports)
819  {
820  /* set all imported function to deadbeef */
821  while (import_list->u1.Ordinal)
822  {
823  if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
824  {
825  int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
826  WARN("No implementation for %s.%d", name, ordinal );
827  thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );
828  }
829  else
830  {
831  IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
832  WARN("No implementation for %s.%s", name, pe_name->Name );
833  thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );
834  }
835  WARN(" imported from %s, allocating stub %p\n",
836  debugstr_w(current_modref->ldr.FullDllName.Buffer),
837  (void *)thunk_list->u1.Function );
838  import_list++;
839  thunk_list++;
840  }
841  goto done;
842  }
843 
844  while (import_list->u1.Ordinal)
845  {
846  if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
847  {
848  int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
849 
850  thunk_list->u1.Function = (ULONG_PTR)find_ordinal_export( imp_mod, exports, exp_size,
851  ordinal - exports->Base, load_path );
852  if (!thunk_list->u1.Function)
853  {
854  thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );
855  WARN("No implementation for %s.%d imported from %s, setting to %p\n",
856  name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer),
857  (void *)thunk_list->u1.Function );
858  }
859  TRACE_(imports)("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function );
860  }
861  else /* import by name */
862  {
863  IMAGE_IMPORT_BY_NAME *pe_name;
864  pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
865  thunk_list->u1.Function = (ULONG_PTR)find_named_export( imp_mod, exports, exp_size,
866  (const char*)pe_name->Name,
867  pe_name->Hint, load_path );
868  if (!thunk_list->u1.Function)
869  {
870  thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );
871  WARN("No implementation for %s.%s imported from %s, setting to %p\n",
872  name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer),
873  (void *)thunk_list->u1.Function );
874  }
875  TRACE_(imports)("--- %s %s.%d = %p\n",
876  pe_name->Name, name, pe_name->Hint, (void *)thunk_list->u1.Function);
877  }
878  import_list++;
879  thunk_list++;
880  }
881 
882 done:
883  /* restore old protection of the import address table */
884  NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, &protect_old );
885  *pwm = wmImp;
886  return TRUE;
887 }
888 
889 
890 /***********************************************************************
891  * create_module_activation_context
892  */
894 {
898 
899  info.Type = RT_MANIFEST;
901  info.Language = 0;
902  if (!(status = LdrFindResource_U( module->DllBase, &info, 3, &entry )))
903  {
904  ACTCTXW ctx;
905  ctx.cbSize = sizeof(ctx);
906  ctx.lpSource = NULL;
908  ctx.hModule = module->DllBase;
910  status = RtlCreateActivationContext( &module->ActivationContext, &ctx );
911  }
912  return status;
913 }
914 
915 
916 /*************************************************************************
917  * is_dll_native_subsystem
918  *
919  * Check if dll is a proper native driver.
920  * Some dlls (corpol.dll from IE6 for instance) are incorrectly marked as native
921  * while being perfectly normal DLLs. This heuristic should catch such breakages.
922  */
924 {
926  DWORD i, size;
927  WCHAR buffer[16];
928 
931  if (mod->Flags & LDR_WINE_INTERNAL) return TRUE;
932 
935  {
936  for (i = 0; imports[i].Name; i++)
937  {
938  const char *name = get_rva( mod->DllBase, imports[i].Name );
939  DWORD len = strlen(name);
940  if (len * sizeof(WCHAR) >= sizeof(buffer)) continue;
941  ascii_to_unicode( buffer, name, len + 1 );
942  if (!wcsicmp( buffer, L"ntdll.dll" ) || !wcsicmp( buffer, L"kernel32.dll" ))
943  {
944  TRACE( "%s imports %s, assuming not native\n", debugstr_w(filename), debugstr_w(buffer) );
945  return FALSE;
946  }
947  }
948  }
949  return TRUE;
950 }
951 
952 /*************************************************************************
953  * alloc_tls_slot
954  *
955  * Allocate a TLS slot for a newly-loaded module.
956  * The loader_section must be locked while calling this function.
957  */
959 {
960  const IMAGE_TLS_DIRECTORY *dir;
961  ULONG i, size;
962  void *new_ptr;
963  LIST_ENTRY *entry;
964 
966  return -1;
967 
968  size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
969  if (!size && !dir->SizeOfZeroFill && !dir->AddressOfCallBacks) return -1;
970 
971  for (i = 0; i < tls_module_count; i++)
972  {
973  if (!tls_dirs[i].StartAddressOfRawData && !tls_dirs[i].EndAddressOfRawData &&
974  !tls_dirs[i].SizeOfZeroFill && !tls_dirs[i].AddressOfCallBacks)
975  break;
976  }
977 
978  TRACE( "module %p data %p-%p zerofill %u index %p callback %p flags %x -> slot %u\n", mod->DllBase,
979  (void *)dir->StartAddressOfRawData, (void *)dir->EndAddressOfRawData, dir->SizeOfZeroFill,
980  (void *)dir->AddressOfIndex, (void *)dir->AddressOfCallBacks, dir->Characteristics, i );
981 
982  if (i == tls_module_count)
983  {
984  UINT new_count = max( 32, tls_module_count * 2 );
985 
986  if (!tls_dirs)
987  new_ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*tls_dirs) );
988  else
990  new_count * sizeof(*tls_dirs) );
991  if (!new_ptr) return -1;
992 
993  /* resize the pointer block in all running threads */
994  for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
995  {
996  TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
997  void **old = teb->ThreadLocalStoragePointer;
998  void **new = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new));
999 
1000  if (!new) return -1;
1001  if (old) memcpy( new, old, tls_module_count * sizeof(*new) );
1002  teb->ThreadLocalStoragePointer = new;
1003 #ifdef __x86_64__ /* macOS-specific hack */
1004  if (teb->Reserved5[0]) ((TEB *)teb->Reserved5[0])->ThreadLocalStoragePointer = new;
1005 #endif
1006  TRACE( "thread %04lx tls block %p -> %p\n", (ULONG_PTR)teb->ClientId.UniqueThread, old, new );
1007  /* FIXME: can't free old block here, should be freed at thread exit */
1008  }
1009 
1010  tls_dirs = new_ptr;
1011  tls_module_count = new_count;
1012  }
1013 
1014  /* allocate the data block in all running threads */
1015  for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
1016  {
1017  TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
1018 
1019  if (!(new_ptr = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) return -1;
1020  memcpy( new_ptr, (void *)dir->StartAddressOfRawData, size );
1021  memset( (char *)new_ptr + size, 0, dir->SizeOfZeroFill );
1022 
1023  TRACE( "thread %04lx slot %u: %u/%u bytes at %p\n",
1024  (ULONG_PTR)teb->ClientId.UniqueThread, i, size, dir->SizeOfZeroFill, new_ptr );
1025 
1027  InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr ));
1028  }
1029 
1030  *(DWORD *)dir->AddressOfIndex = i;
1031  tls_dirs[i] = *dir;
1032  return i;
1033 }
1034 
1035 
1036 /*************************************************************************
1037  * free_tls_slot
1038  *
1039  * Free the module TLS slot on unload.
1040  * The loader_section must be locked while calling this function.
1041  */
1043 {
1044  ULONG i = (USHORT)mod->TlsIndex;
1045 
1046  if (mod->TlsIndex == -1) return;
1047  assert( i < tls_module_count );
1048  memset( &tls_dirs[i], 0, sizeof(tls_dirs[i]) );
1049 }
1050 
1051 
1052 /****************************************************************
1053  * fixup_imports_ilonly
1054  *
1055  * Fixup imports for an IL-only module. All we do is import mscoree.
1056  * The loader_section must be locked while calling this function.
1057  */
1059 {
1060  IMAGE_EXPORT_DIRECTORY *exports;
1061  DWORD exp_size;
1062  NTSTATUS status;
1063  void *proc = NULL;
1064  WINE_MODREF *prev, *imp;
1065 
1066  if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */
1067  wm->ldr.Flags &= ~~LDR_DONT_RESOLVE_REFS;
1068 
1069  if (!grow_module_deps( wm, 1 )) return STATUS_NO_MEMORY;
1070  wm->nDeps = 1;
1071 
1072  prev = current_modref;
1073  current_modref = wm;
1074  if (!(status = load_dll( load_path, L"mscoree.dll", NULL, 0, &imp ))) wm->deps[0] = imp;
1075  current_modref = prev;
1076  if (status)
1077  {
1078  ERR( "mscoree.dll not found, IL-only binary %s cannot be loaded\n",
1079  debugstr_w(wm->ldr.BaseDllName.Buffer) );
1080  return status;
1081  }
1082 
1083  TRACE( "loaded mscoree for %s\n", debugstr_w(wm->ldr.FullDllName.Buffer) );
1084 
1085  if ((exports = RtlImageDirectoryEntryToData( imp->ldr.DllBase, TRUE,
1086  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
1087  {
1088  const char *name = (wm->ldr.Flags & LDR_IMAGE_IS_DLL) ? "_CorDllMain" : "_CorExeMain";
1089  proc = find_named_export( imp->ldr.DllBase, exports, exp_size, name, -1, load_path );
1090  }
1091  if (!proc) return STATUS_PROCEDURE_NOT_FOUND;
1092  *entry = proc;
1093  return STATUS_SUCCESS;
1094 }
1095 
1096 
1097 /****************************************************************
1098  * fixup_imports
1099  *
1100  * Fixup all imports of a given module.
1101  * The loader_section must be locked while calling this function.
1102  */
1104 {
1105  int i, dep, nb_imports;
1107  WINE_MODREF *prev, *imp;
1108  DWORD size;
1109  NTSTATUS status;
1110  ULONG_PTR cookie;
1111 
1112  if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */
1113  wm->ldr.Flags &= ~~LDR_DONT_RESOLVE_REFS;
1114 
1115  wm->ldr.TlsIndex = alloc_tls_slot( &wm->ldr );
1116 
1119  return STATUS_SUCCESS;
1120 
1121  nb_imports = 0;
1122  while (imports[nb_imports].Name && imports[nb_imports].FirstThunk) nb_imports++;
1123 
1124  if (!nb_imports) return STATUS_SUCCESS; /* no imports */
1125  if (!grow_module_deps( wm, nb_imports )) return STATUS_NO_MEMORY;
1126 
1129 
1130  /* load the imported modules. They are automatically
1131  * added to the modref list of the process.
1132  */
1133  prev = current_modref;
1134  current_modref = wm;
1136  for (i = 0; i < nb_imports; i++)
1137  {
1138  dep = wm->nDeps++;
1139 
1140  if (!import_dll( wm->ldr.DllBase, &imports[i], load_path, &imp ))
1141  {
1142  imp = NULL;
1144  }
1145  wm->deps[dep] = imp;
1146  }
1147  current_modref = prev;
1149  return status;
1150 }
1151 
1152 
1153 /*************************************************************************
1154  * alloc_module
1155  *
1156  * Allocate a WINE_MODREF structure and add it to the process list
1157  * The loader_section must be locked while calling this function.
1158  */
1159 static WINE_MODREF *alloc_module( HMODULE hModule, const UNICODE_STRING *nt_name, BOOL builtin )
1160 {
1161  WCHAR *buffer;
1162  WINE_MODREF *wm;
1163  const WCHAR *p;
1165 
1166  if (!(wm = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wm) ))) return NULL;
1167 
1168  wm->ldr.DllBase = hModule;
1170  wm->ldr.Flags = LDR_DONT_RESOLVE_REFS | (builtin ? LDR_WINE_INTERNAL : 0);
1171  wm->ldr.TlsIndex = -1;
1172  wm->ldr.LoadCount = 1;
1173 
1174  if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, nt_name->Length - 3 * sizeof(WCHAR) )))
1175  {
1176  RtlFreeHeap( GetProcessHeap(), 0, wm );
1177  return NULL;
1178  }
1179  memcpy( buffer, nt_name->Buffer + 4 /* \??\ prefix */, nt_name->Length - 4 * sizeof(WCHAR) );
1180  buffer[nt_name->Length/sizeof(WCHAR) - 4] = 0;
1181  if ((p = wcsrchr( buffer, '\\' ))) p++;
1182  else p = buffer;
1185 
1186  if (!is_dll_native_subsystem( &wm->ldr, nt, p ))
1187  {
1189  wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
1192  }
1193 
1194  InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
1195  &wm->ldr.InLoadOrderLinks);
1196  InsertTailList(&NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList,
1197  &wm->ldr.InMemoryOrderLinks);
1198  /* wait until init is called for inserting into InInitializationOrderModuleList */
1199 
1201  {
1203  WARN( "disabling no-exec because of %s\n", debugstr_w(wm->ldr.BaseDllName.Buffer) );
1205  }
1206  return wm;
1207 }
1208 
1209 
1210 /*************************************************************************
1211  * alloc_thread_tls
1212  *
1213  * Allocate the per-thread structure for module TLS storage.
1214  */
1216 {
1217  void **pointers;
1218  UINT i, size;
1219 
1220  if (!tls_module_count) return STATUS_SUCCESS;
1221 
1222  if (!(pointers = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
1223  tls_module_count * sizeof(*pointers) )))
1224  return STATUS_NO_MEMORY;
1225 
1226  for (i = 0; i < tls_module_count; i++)
1227  {
1228  const IMAGE_TLS_DIRECTORY *dir = &tls_dirs[i];
1229 
1230  if (!dir) continue;
1231  size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
1232  if (!size && !dir->SizeOfZeroFill) continue;
1233 
1234  if (!(pointers[i] = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill )))
1235  {
1236  while (i) RtlFreeHeap( GetProcessHeap(), 0, pointers[--i] );
1237  RtlFreeHeap( GetProcessHeap(), 0, pointers );
1238  return STATUS_NO_MEMORY;
1239  }
1240  memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size );
1241  memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill );
1242 
1243  TRACE( "thread %04x slot %u: %u/%u bytes at %p\n",
1244  GetCurrentThreadId(), i, size, dir->SizeOfZeroFill, pointers[i] );
1245  }
1246  NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
1247 #ifdef __x86_64__ /* macOS-specific hack */
1248  if (NtCurrentTeb()->Reserved5[0])
1249  ((TEB *)NtCurrentTeb()->Reserved5[0])->ThreadLocalStoragePointer = pointers;
1250 #endif
1251  return STATUS_SUCCESS;
1252 }
1253 
1254 
1255 /*************************************************************************
1256  * call_tls_callbacks
1257  */
1259 {
1260  const IMAGE_TLS_DIRECTORY *dir;
1262  ULONG dirsize;
1263 
1264  if (reason == DLL_WINE_PREATTACH) return;
1265 
1267  if (!dir || !dir->AddressOfCallBacks) return;
1268 
1269  for (callback = (const PIMAGE_TLS_CALLBACK *)dir->AddressOfCallBacks; *callback; callback++)
1270  {
1271  TRACE_(relay)("\1Call TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
1273  __TRY
1274  {
1276  }
1277  __EXCEPT_ALL
1278  {
1279  TRACE_(relay)("\1exception %08x in TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
1281  return;
1282  }
1283  __ENDTRY
1284  TRACE_(relay)("\1Ret TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
1286  }
1287 }
1288 
1289 /*************************************************************************
1290  * MODULE_InitDLL
1291  */
1293 {
1294  WCHAR mod_name[32];
1297  void *module = wm->ldr.DllBase;
1298  BOOL retv = FALSE;
1299 
1300  /* Skip calls for modules loaded with special load flags */
1301 
1302  if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS;
1303  if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.DllBase, reason );
1306  if (!entry) return STATUS_SUCCESS;
1307 
1308  if (TRACE_ON(relay))
1309  {
1310  size_t len = min( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
1311  memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
1312  mod_name[len / sizeof(WCHAR)] = 0;
1313  TRACE_(relay)("\1Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
1314  entry, module, debugstr_w(mod_name), reason_names[reason], lpReserved );
1315  }
1316  else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
1317  reason_names[reason], lpReserved );
1318 
1319  __TRY
1320  {
1321  retv = call_dll_entry_point( entry, module, reason, lpReserved );
1322  if (!retv)
1324  }
1325  __EXCEPT_ALL
1326  {
1328  TRACE_(relay)("\1exception %08x in PE entry point (proc=%p,module=%p,reason=%s,res=%p)\n",
1329  status, entry, module, reason_names[reason], lpReserved );
1330  }
1331  __ENDTRY
1332 
1333  /* The state of the module list may have changed due to the call
1334  to the dll. We cannot assume that this module has not been
1335  deleted. */
1336  if (TRACE_ON(relay))
1337  TRACE_(relay)("\1Ret PE DLL (proc=%p,module=%p %s,reason=%s,res=%p) retval=%x\n",
1338  entry, module, debugstr_w(mod_name), reason_names[reason], lpReserved, retv );
1339  else
1340  TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
1341 
1342  return status;
1343 }
1344 
1345 
1346 /*************************************************************************
1347  * process_attach
1348  *
1349  * Send the process attach notification to all DLLs the given module
1350  * depends on (recursively). This is somewhat complicated due to the fact that
1351  *
1352  * - we have to respect the module dependencies, i.e. modules implicitly
1353  * referenced by another module have to be initialized before the module
1354  * itself can be initialized
1355  *
1356  * - the initialization routine of a DLL can itself call LoadLibrary,
1357  * thereby introducing a whole new set of dependencies (even involving
1358  * the 'old' modules) at any time during the whole process
1359  *
1360  * (Note that this routine can be recursively entered not only directly
1361  * from itself, but also via LoadLibrary from one of the called initialization
1362  * routines.)
1363  *
1364  * Furthermore, we need to rearrange the main WINE_MODREF list to allow
1365  * the process *detach* notifications to be sent in the correct order.
1366  * This must not only take into account module dependencies, but also
1367  * 'hidden' dependencies created by modules calling LoadLibrary in their
1368  * attach notification routine.
1369  *
1370  * The strategy is rather simple: we move a WINE_MODREF to the head of the
1371  * list after the attach notification has returned. This implies that the
1372  * detach notifications are called in the reverse of the sequence the attach
1373  * notifications *returned*.
1374  *
1375  * The loader_section must be locked while calling this function.
1376  */
1377 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
1378 {
1380  ULONG_PTR cookie;
1381  int i;
1382 
1383  if (process_detaching) return status;
1384 
1385  /* prevent infinite recursion in case of cyclical dependencies */
1386  if ( ( wm->ldr.Flags & LDR_LOAD_IN_PROGRESS )
1387  || ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
1388  return status;
1389 
1390  TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
1391 
1392  /* Tag current MODREF to prevent recursive loop */
1394  if (lpReserved) wm->ldr.LoadCount = -1; /* pin it if imported by the main exe */
1396 
1397  /* Recursively attach all DLLs this one depends on */
1398  for ( i = 0; i < wm->nDeps; i++ )
1399  {
1400  if (!wm->deps[i]) continue;
1401  if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
1402  }
1403 
1405  InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList,
1407 
1408  /* Call DLL entry point */
1409  if (status == STATUS_SUCCESS)
1410  {
1411  WINE_MODREF *prev = current_modref;
1412  current_modref = wm;
1413 
1415  status = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
1416  if (status == STATUS_SUCCESS)
1417  {
1419  }
1420  else
1421  {
1422  MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved );
1424 
1425  /* point to the name so LdrInitializeThunk can print it */
1426  last_failed_modref = wm;
1427  WARN("Initialization of %s failed\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
1428  }
1429  current_modref = prev;
1430  }
1431 
1433  /* Remove recursion flag */
1434  wm->ldr.Flags &= ~~LDR_LOAD_IN_PROGRESS;
1435 
1436  TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
1437  return status;
1438 }
1439 
1440 
1441 /**********************************************************************
1442  * attach_implicitly_loaded_dlls
1443  *
1444  * Attach to the (builtin) dlls that have been implicitly loaded because
1445  * of a dependency at the Unix level, but not imported at the Win32 level.
1446  */
1447 static void attach_implicitly_loaded_dlls( LPVOID reserved )
1448 {
1449  for (;;)
1450  {
1451  PLIST_ENTRY mark, entry;
1452 
1453  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1454  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1455  {
1457 
1458  if (!(mod->Flags & LDR_IMAGE_IS_DLL)) continue;
1459  if (mod->Flags & (LDR_LOAD_IN_PROGRESS | LDR_PROCESS_ATTACHED)) continue;
1460  TRACE( "found implicitly loaded %s, attaching to it\n",
1461  debugstr_w(mod->BaseDllName.Buffer));
1462  process_attach( CONTAINING_RECORD(mod, WINE_MODREF, ldr), reserved );
1463  break; /* restart the search from the start */
1464  }
1465  if (entry == mark) break; /* nothing found */
1466  }
1467 }
1468 
1469 
1470 /*************************************************************************
1471  * process_detach
1472  *
1473  * Send DLL process detach notifications. See the comment about calling
1474  * sequence at process_attach.
1475  */
1476 static void process_detach(void)
1477 {
1478  PLIST_ENTRY mark, entry;
1480 
1481  mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1482  do
1483  {
1484  for (entry = mark->Blink; entry != mark; entry = entry->Blink)
1485  {
1487  InInitializationOrderLinks);
1488  /* Check whether to detach this DLL */
1489  if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1490  continue;
1491  if ( mod->LoadCount && !process_detaching )
1492  continue;
1493 
1494  /* Call detach notification */
1495  mod->Flags &= ~~LDR_PROCESS_ATTACHED;
1499 
1500  /* Restart at head of WINE_MODREF list, as entries might have
1501  been added and/or removed while performing the call ... */
1502  break;
1503  }
1504  } while (entry != mark);
1505 }
1506 
1507 /*************************************************************************
1508  * thread_attach
1509  *
1510  * Send DLL thread attach notifications. These are sent in the
1511  * reverse sequence of process detach notification.
1512  * The loader_section must be locked while calling this function.
1513  */
1514 static void thread_attach(void)
1515 {
1516  PLIST_ENTRY mark, entry;
1518 
1519  mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1520  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1521  {
1523  InInitializationOrderLinks);
1524  if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1525  continue;
1526  if ( mod->Flags & LDR_NO_DLL_CALLS )
1527  continue;
1528 
1530  }
1531 }
1532 
1533 /******************************************************************
1534  * LdrDisableThreadCalloutsForDll (NTDLL.@)
1535  *
1536  */
1538 {
1539  WINE_MODREF *wm;
1540  NTSTATUS ret = STATUS_SUCCESS;
1541 
1543 
1544  wm = get_modref( hModule );
1545  if (!wm || wm->ldr.TlsIndex != -1)
1546  ret = STATUS_DLL_NOT_FOUND;
1547  else
1548  wm->ldr.Flags |= LDR_NO_DLL_CALLS;
1549 
1551 
1552  return ret;
1553 }
1554 
1555 /******************************************************************
1556  * LdrFindEntryForAddress (NTDLL.@)
1557  *
1558  * The loader_section must be locked while calling this function
1559  */
1561 {
1562  PLIST_ENTRY mark, entry;
1564 
1565  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
1566  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1567  {
1568  mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
1569  if (mod->DllBase <= addr &&
1570  (const char *)addr < (char*)mod->DllBase + mod->SizeOfImage)
1571  {
1572  *pmod = mod;
1573  return STATUS_SUCCESS;
1574  }
1575  }
1576  return STATUS_NO_MORE_ENTRIES;
1577 }
1578 
1579 /******************************************************************
1580  * LdrEnumerateLoadedModules (NTDLL.@)
1581  */
1583 {
1584  LIST_ENTRY *mark, *entry;
1585  LDR_DATA_TABLE_ENTRY *mod;
1586  BOOLEAN stop = FALSE;
1587 
1588  TRACE( "(%p, %p, %p)\n", unknown, callback, context );
1589 
1590  if (unknown || !callback)
1591  return STATUS_INVALID_PARAMETER;
1592 
1594 
1595  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
1596  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1597  {
1598  mod = CONTAINING_RECORD( entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );
1599  callback( mod, context, &stop );
1600  if (stop) break;
1601  }
1602 
1604  return STATUS_SUCCESS;
1605 }
1606 
1607 /******************************************************************
1608  * LdrRegisterDllNotification (NTDLL.@)
1609  */
1611  void *context, void **cookie)
1612 {
1613  struct ldr_notification *notify;
1614 
1615  TRACE( "(%x, %p, %p, %p)\n", flags, callback, context, cookie );
1616 
1617  if (!callback || !cookie)
1618  return STATUS_INVALID_PARAMETER;
1619 
1620  if (flags)
1621  FIXME( "ignoring flags %x\n", flags );
1622 
1623  notify = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*notify) );
1624  if (!notify) return STATUS_NO_MEMORY;
1625  notify->callback = callback;
1626  notify->context = context;
1627 
1631 
1632  *cookie = notify;
1633  return STATUS_SUCCESS;
1634 }
1635 
1636 /******************************************************************
1637  * LdrUnregisterDllNotification (NTDLL.@)
1638  */
1640 {
1641  struct ldr_notification *notify = cookie;
1642 
1643  TRACE( "(%p)\n", cookie );
1644 
1645  if (!notify) return STATUS_INVALID_PARAMETER;
1646 
1648  list_remove( &notify->entry );
1650 
1652  return STATUS_SUCCESS;
1653 }
1654 
1655 /******************************************************************
1656  * LdrLockLoaderLock (NTDLL.@)
1657  *
1658  * Note: some flags are not implemented.
1659  * Flag 0x01 is used to raise exceptions on errors.
1660  */
1662 {
1663  if (flags & ~0x2) FIXME( "flags %x not supported\n", flags );
1664 
1665  if (result) *result = 0;
1666  if (magic) *magic = 0;
1667  if (flags & ~0x3) return STATUS_INVALID_PARAMETER_1;
1668  if (!result && (flags & 0x2)) return STATUS_INVALID_PARAMETER_2;
1669  if (!magic) return STATUS_INVALID_PARAMETER_3;
1670 
1671  if (flags & 0x2)
1672  {
1674  {
1675  *result = 2;
1676  return STATUS_SUCCESS;
1677  }
1678  *result = 1;
1679  }
1680  else
1681  {
1683  if (result) *result = 1;
1684  }
1685  *magic = GetCurrentThreadId();
1686  return STATUS_SUCCESS;
1687 }
1688 
1689 
1690 /******************************************************************
1691  * LdrUnlockLoaderUnlock (NTDLL.@)
1692  */
1694 {
1695  if (magic)
1696  {
1697  if (magic != GetCurrentThreadId()) return STATUS_INVALID_PARAMETER_2;
1699  }
1700  return STATUS_SUCCESS;
1701 }
1702 
1703 
1704 /******************************************************************
1705  * LdrGetProcedureAddress (NTDLL.@)
1706  */
1708  ULONG ord, PVOID *address)
1709 {
1710  IMAGE_EXPORT_DIRECTORY *exports;
1711  DWORD exp_size;
1713 
1715 
1716  /* check if the module itself is invalid to return the proper error */
1717  if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND;
1718  else if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
1719  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
1720  {
1721  LPCWSTR load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1722  void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, load_path )
1723  : find_ordinal_export( module, exports, exp_size, ord - exports->Base, load_path );
1724  if (proc)
1725  {
1726  *address = proc;
1727  ret = STATUS_SUCCESS;
1728  }
1729  }
1730 
1732  return ret;
1733 }
1734 
1735 
1736 /***********************************************************************
1737  * set_security_cookie
1738  *
1739  * Create a random security cookie for buffer overflow protection. Make
1740  * sure it does not accidentally match the default cookie value.
1741  */
1742 static void set_security_cookie( void *module, SIZE_T len )
1743 {
1744  static ULONG seed;
1745  IMAGE_LOAD_CONFIG_DIRECTORY *loadcfg;
1746  ULONG loadcfg_size;
1747  ULONG_PTR *cookie;
1748 
1750  if (!loadcfg) return;
1751  if (loadcfg_size < offsetof(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie) + sizeof(loadcfg->SecurityCookie)) return;
1752  if (!loadcfg->SecurityCookie) return;
1753  if (loadcfg->SecurityCookie < (ULONG_PTR)module ||
1754  loadcfg->SecurityCookie > (ULONG_PTR)module + len - sizeof(ULONG_PTR))
1755  {
1756  WARN( "security cookie %p outside of image %p-%p\n",
1757  (void *)loadcfg->SecurityCookie, module, (char *)module + len );
1758  return;
1759  }
1760 
1761  cookie = (ULONG_PTR *)loadcfg->SecurityCookie;
1762  TRACE( "initializing security cookie %p\n", cookie );
1763 
1764  if (!seed) seed = NtGetTickCount() ^ GetCurrentProcessId();
1765  for (;;)
1766  {
1768  *cookie = RtlRandom( &seed ) >> 16; /* leave the high word clear */
1769  else if (*cookie == DEFAULT_SECURITY_COOKIE_32)
1770  *cookie = RtlRandom( &seed );
1771 #ifdef DEFAULT_SECURITY_COOKIE_64
1772  else if (*cookie == DEFAULT_SECURITY_COOKIE_64)
1773  {
1774  *cookie = RtlRandom( &seed );
1775  /* fill up, but keep the highest word clear */
1776  *cookie ^= (ULONG_PTR)RtlRandom( &seed ) << 16;
1777  }
1778 #endif
1779  else
1780  break;
1781  }
1782 }
1783 
1785 {
1786  char *base;
1787  IMAGE_BASE_RELOCATION *rel, *end;
1788  const IMAGE_DATA_DIRECTORY *relocs;
1789  const IMAGE_SECTION_HEADER *sec;
1790  INT_PTR delta;
1791  ULONG protect_old[96], i;
1792 
1793  base = (char *)nt->OptionalHeader.ImageBase;
1794  if (module == base) return STATUS_SUCCESS; /* nothing to do */
1795 
1796  /* no relocations are performed on non page-aligned binaries */
1798  return STATUS_SUCCESS;
1799 
1800  if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL) && NtCurrentTeb()->Peb->ImageBaseAddress)
1801  return STATUS_SUCCESS;
1802 
1804 
1806  {
1807  WARN( "Need to relocate module from %p to %p, but there are no relocation records\n",
1808  base, module );
1810  }
1811 
1812  if (!relocs->Size) return STATUS_SUCCESS;
1813  if (!relocs->VirtualAddress) return STATUS_CONFLICTING_ADDRESSES;
1814 
1815  if (nt->FileHeader.NumberOfSections > ARRAY_SIZE( protect_old ))
1817 
1818  sec = (const IMAGE_SECTION_HEADER *)((const char *)&nt->OptionalHeader +
1820  for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
1821  {
1822  void *addr = get_rva( module, sec[i].VirtualAddress );
1823  SIZE_T size = sec[i].SizeOfRawData;
1825  &size, PAGE_READWRITE, &protect_old[i] );
1826  }
1827 
1828  TRACE( "relocating from %p-%p to %p-%p\n",
1829  base, base + len, module, (char *)module + len );
1830 
1831  rel = get_rva( module, relocs->VirtualAddress );
1832  end = get_rva( module, relocs->VirtualAddress + relocs->Size );
1833  delta = (char *)module - base;
1834 
1835  while (rel < end - 1 && rel->SizeOfBlock)
1836  {
1837  if (rel->VirtualAddress >= len)
1838  {
1839  WARN( "invalid address %p in relocation %p\n", get_rva( module, rel->VirtualAddress ), rel );
1840  return STATUS_ACCESS_VIOLATION;
1841  }
1843  (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
1844  (USHORT *)(rel + 1), delta );
1845  if (!rel) return STATUS_INVALID_IMAGE_FORMAT;
1846  }
1847 
1848  for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
1849  {
1850  void *addr = get_rva( module, sec[i].VirtualAddress );
1851  SIZE_T size = sec[i].SizeOfRawData;
1853  &size, protect_old[i], &protect_old[i] );
1854  }
1855 
1856  return STATUS_SUCCESS;
1857 }
1858 
1859 
1860 /*************************************************************************
1861  * build_module
1862  *
1863  * Build the module data for a mapped dll.
1864  */
1866  const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
1867  DWORD flags, WINE_MODREF **pwm )
1868 {
1870  WINE_MODREF *wm;
1871  NTSTATUS status;
1872  SIZE_T map_size;
1873 
1875 
1876  map_size = (nt->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1);
1877  if ((status = perform_relocations( *module, nt, map_size ))) return status;
1878 
1879  /* create the MODREF */
1880 
1881  if (!(wm = alloc_module( *module, nt_name, (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) )))
1882  return STATUS_NO_MEMORY;
1883 
1884  if (id) wm->id = *id;
1885  if (image_info->LoaderFlags) wm->ldr.Flags |= LDR_COR_IMAGE;
1886  if (image_info->u.ImageFlags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY;
1887 
1888  set_security_cookie( *module, map_size );
1889 
1890  /* fixup imports */
1891 
1895  {
1896  if (wm->ldr.Flags & LDR_COR_ILONLY)
1898  else
1899  status = fixup_imports( wm, load_path );
1900  if (status != STATUS_SUCCESS)
1901  {
1902  /* the module has only be inserted in the load & memory order lists */
1905 
1906  /* FIXME: there are several more dangling references
1907  * left. Including dlls loaded by this dll before the
1908  * failed one. Unrolling is rather difficult with the
1909  * current structure and we can leave them lying
1910  * around with no problems, so we don't care.
1911  * As these might reference our wm, we don't free it.
1912  */
1913  *module = NULL;
1914  return status;
1915  }
1916  }
1917 
1918  TRACE( "loaded %s %p %p\n", debugstr_us(nt_name), wm, module );
1919 
1920  /* send DLL load event */
1921 
1923  {
1924  req->base = wine_server_client_ptr( *module );
1925  req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1926  req->dbg_size = nt->FileHeader.NumberOfSymbols;
1927  req->name = wine_server_client_ptr( &wm->ldr.FullDllName.Buffer );
1929  wine_server_call( req );
1930  }
1932 
1933  if (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin)
1934  {
1935  if (TRACE_ON(relay)) RELAY_SetupDLL( *module );
1936  }
1937  else
1938  {
1939  if ((wm->ldr.Flags & LDR_IMAGE_IS_DLL) && TRACE_ON(snoop)) SNOOP_SetupDLL( *module );
1940  }
1941 
1942  TRACE_(loaddll)( "Loaded %s at %p: %s\n", debugstr_w(wm->ldr.FullDllName.Buffer), *module,
1943  (image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin) ? "builtin" : "native" );
1944 
1945  wm->ldr.LoadCount = 1;
1946  *pwm = wm;
1947  *module = NULL;
1948  return STATUS_SUCCESS;
1949 }
1950 
1951 
1952 /*************************************************************************
1953  * build_builtin_module
1954  *
1955  * Build the module for a builtin library.
1956  */
1958  void *module, DWORD flags, WINE_MODREF **pwm )
1959 {
1960  NTSTATUS status;
1961  SECTION_IMAGE_INFORMATION image_info = { 0 };
1962 
1963  image_info.u.ImageFlags = IMAGE_FLAGS_WineBuiltin;
1964  status = build_module( load_path, nt_name, &module, &image_info, NULL, flags, pwm );
1966  return status;
1967 }
1968 
1969 
1970 #ifdef _WIN64
1971 /* convert PE header to 64-bit when loading a 32-bit IL-only module into a 64-bit process */
1972 static BOOL convert_to_pe64( HMODULE module, const SECTION_IMAGE_INFORMATION *info )
1973 {
1974  static const ULONG copy_dirs[] = { IMAGE_DIRECTORY_ENTRY_RESOURCE,
1982  SIZE_T hdr_size = min( sizeof(hdr32), nt->FileHeader.SizeOfOptionalHeader );
1983  IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + hdr_size);
1985  void *addr = module;
1986  ULONG i, old_prot;
1987 
1988  TRACE( "%p\n", module );
1989 
1990  if (NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &old_prot ))
1991  return FALSE;
1992 
1993  if ((char *)module + size < (char *)(nt + 1) + nt->FileHeader.NumberOfSections * sizeof(*sec))
1994  {
1995  NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, old_prot, &old_prot );
1996  return FALSE;
1997  }
1998 
1999  memcpy( &hdr32, &nt->OptionalHeader, hdr_size );
2000  memcpy( &hdr64, &hdr32, offsetof( IMAGE_OPTIONAL_HEADER64, SizeOfStackReserve ));
2002  hdr64.AddressOfEntryPoint = 0;
2003  hdr64.ImageBase = hdr32.ImageBase;
2004  hdr64.SizeOfStackReserve = hdr32.SizeOfStackReserve;
2005  hdr64.SizeOfStackCommit = hdr32.SizeOfStackCommit;
2006  hdr64.SizeOfHeapReserve = hdr32.SizeOfHeapReserve;
2007  hdr64.SizeOfHeapCommit = hdr32.SizeOfHeapCommit;
2008  hdr64.LoaderFlags = hdr32.LoaderFlags;
2010  for (i = 0; i < ARRAY_SIZE( copy_dirs ); i++)
2011  hdr64.DataDirectory[copy_dirs[i]] = hdr32.DataDirectory[copy_dirs[i]];
2012 
2013  memmove( nt + 1, sec, nt->FileHeader.NumberOfSections * sizeof(*sec) );
2014  nt->FileHeader.SizeOfOptionalHeader = sizeof(hdr64);
2015  nt->OptionalHeader = hdr64;
2016  NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, old_prot, &old_prot );
2017  return TRUE;
2018 }
2019 #endif
2020 
2021 /* On WoW64 setups, an image mapping can also be created for the other 32/64 CPU */
2022 /* but it cannot necessarily be loaded as a dll, so we need some additional checks */
2024 {
2025 #ifdef __i386__
2026  return info->Machine == IMAGE_FILE_MACHINE_I386;
2027 #elif defined(__arm__)
2028  return info->Machine == IMAGE_FILE_MACHINE_ARM ||
2029  info->Machine == IMAGE_FILE_MACHINE_THUMB ||
2030  info->Machine == IMAGE_FILE_MACHINE_ARMNT;
2031 #elif defined(_WIN64) /* support 32-bit IL-only images on 64-bit */
2032 #ifdef __x86_64__
2033  if (info->Machine == IMAGE_FILE_MACHINE_AMD64) return TRUE;
2034 #else
2035  if (info->Machine == IMAGE_FILE_MACHINE_ARM64) return TRUE;
2036 #endif
2037  if (!info->ImageContainsCode) return TRUE;
2038  if (!(info->u.ImageFlags & IMAGE_FLAGS_ComPlusNativeReady))
2039  {
2040  /* check COM header directly, ignoring runtime version */
2041  DWORD size;
2044  if (!cor_header || !(cor_header->Flags & COMIMAGE_FLAGS_ILONLY)) return FALSE;
2045  }
2046  return convert_to_pe64( module, info );
2047 #else
2048  return FALSE; /* no wow64 support on other platforms */
2049 #endif
2050 }
2051 
2052 
2053 /******************************************************************
2054  * get_module_path_end
2055  *
2056  * Returns the end of the directory component of the module path.
2057  */
2058 static inline const WCHAR *get_module_path_end( const WCHAR *module )
2059 {
2060  const WCHAR *p;
2061  const WCHAR *mod_end = module;
2062 
2063  if ((p = wcsrchr( mod_end, '\\' ))) mod_end = p;
2064  if ((p = wcsrchr( mod_end, '/' ))) mod_end = p;
2065  if (mod_end == module + 2 && module[1] == ':') mod_end++;
2066  if (mod_end == module && module[0] && module[1] == ':') mod_end += 2;
2067  return mod_end;
2068 }
2069 
2070 
2071 /******************************************************************
2072  * append_path
2073  *
2074  * Append a counted string to the load path. Helper for get_dll_load_path.
2075  */
2076 static inline WCHAR *append_path( WCHAR *p, const WCHAR *str, int len )
2077 {
2078  if (len == -1) len = wcslen(str);
2079  if (!len) return p;
2080  memcpy( p, str, len * sizeof(WCHAR) );
2081  p[len] = ';';
2082  return p + len + 1;
2083 }
2084 
2085 
2086 /******************************************************************
2087  * get_dll_load_path
2088  */
2090 {
2091  const WCHAR *mod_end = module;
2093  WCHAR *p, *ret;
2094  int len = ARRAY_SIZE(system_path) + 1, path_len = 0;
2095 
2096  if (module)
2097  {
2098  mod_end = get_module_path_end( module );
2099  len += (mod_end - module) + 1;
2100  }
2101 
2102  RtlInitUnicodeString( &name, L"PATH" );
2103  value.Length = 0;
2104  value.MaximumLength = 0;
2105  value.Buffer = NULL;
2107  path_len = value.Length;
2108 
2109  if (dll_dir) len += wcslen( dll_dir ) + 1;
2110  else len += 2; /* current directory */
2111  if (!(p = ret = RtlAllocateHeap( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) )))
2112  return STATUS_NO_MEMORY;
2113 
2114  p = append_path( p, module, mod_end - module );
2115  if (dll_dir) p = append_path( p, dll_dir, -1 );
2116  else if (!safe_mode) p = append_path( p, L".", -1 );
2117  p = append_path( p, system_path, -1 );
2118  if (!dll_dir && safe_mode) p = append_path( p, L".", -1 );
2119 
2120  value.Buffer = p;
2121  value.MaximumLength = path_len;
2122 
2124  {
2125  WCHAR *new_ptr;
2126 
2127  /* grow the buffer and retry */
2128  path_len = value.Length;
2129  if (!(new_ptr = RtlReAllocateHeap( GetProcessHeap(), 0, ret, path_len + len * sizeof(WCHAR) )))
2130  {
2131  RtlFreeHeap( GetProcessHeap(), 0, ret );
2132  return STATUS_NO_MEMORY;
2133  }
2134  value.Buffer = new_ptr + (value.Buffer - ret);
2135  value.MaximumLength = path_len;
2136  ret = new_ptr;
2137  }
2138  value.Buffer[value.Length / sizeof(WCHAR)] = 0;
2139  *path = ret;
2140  return STATUS_SUCCESS;
2141 }
2142 
2143 
2144 /******************************************************************
2145  * get_dll_load_path_search_flags
2146  */
2148 {
2149  const WCHAR *image = NULL, *mod_end, *image_end;
2150  struct dll_dir_entry *dir;
2151  WCHAR *p, *ret;
2152  int len = 1;
2153 
2158 
2160  {
2163  return STATUS_INVALID_PARAMETER;
2164  mod_end = get_module_path_end( module );
2165  len += (mod_end - module) + 1;
2166  }
2167  else module = NULL;
2168 
2170  {
2171  image = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
2172  image_end = get_module_path_end( image );
2173  len += (image_end - image) + 1;
2174  }
2175 
2177  {
2179  len += wcslen( dir->dir + 4 /* \??\ */ ) + 1;
2180  if (dll_directory.Length) len += dll_directory.Length / sizeof(WCHAR) + 1;
2181  }
2182 
2184 
2185  if ((p = ret = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2186  {
2187  if (module) p = append_path( p, module, mod_end - module );
2188  if (image) p = append_path( p, image, image_end - image );
2190  {
2192  p = append_path( p, dir->dir + 4 /* \??\ */, -1 );
2194  }
2196  else
2197  {
2198  if (p > ret) p--;
2199  *p = 0;
2200  }
2201  }
2202  *path = ret;
2203  return STATUS_SUCCESS;
2204 }
2205 
2206 
2207 /***********************************************************************
2208  * open_dll_file
2209  *
2210  * Open a file for a new dll. Helper for find_dll_file.
2211  */
2212 static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module,
2213  SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
2214 {
2217  IO_STATUS_BLOCK io;
2220  SIZE_T len = 0;
2221  NTSTATUS status;
2222  HANDLE handle, mapping;
2223 
2224  if ((*pwm = find_fullname_module( nt_name )))
2225  {
2227  *module = NULL;
2228  return STATUS_SUCCESS;
2229  }
2230 
2231  attr.Length = sizeof(attr);
2232  attr.RootDirectory = 0;
2233  attr.Attributes = OBJ_CASE_INSENSITIVE;
2234  attr.ObjectName = nt_name;
2235  attr.SecurityDescriptor = NULL;
2236  attr.SecurityQualityOfService = NULL;
2237  if ((status = NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io,
2240  {
2244  {
2245  /* if the file exists but failed to open, report the error */
2246  return status;
2247  }
2248  /* otherwise continue searching */
2249  return STATUS_DLL_NOT_FOUND;
2250  }
2251 
2252  if (!NtFsControlFile( handle, 0, NULL, NULL, &io, FSCTL_GET_OBJECT_ID, NULL, 0, &fid, sizeof(fid) ))
2253  {
2254  memcpy( id, fid.ObjectId, sizeof(*id) );
2255  if ((*pwm = find_fileid_module( id )))
2256  {
2257  TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ),
2258  (*pwm)->ldr.DllBase, debugstr_w( (*pwm)->ldr.FullDllName.Buffer ));
2259  NtClose( handle );
2261  *module = NULL;
2262  return STATUS_SUCCESS;
2263  }
2264  }
2265 
2266  size.QuadPart = 0;
2269  NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
2270  NtClose( handle );
2271 
2272  if (!status)
2273  {
2274  if (*module)
2275  {
2277  *module = NULL;
2278  }
2279  NtQuerySection( mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL );
2283  NtClose( mapping );
2284  }
2285  if (!status && !is_valid_binary( *module, image_info ))
2286  {
2287  TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine );
2289  *module = NULL;
2291  }
2292  return status;
2293 }
2294 
2295 
2296 /******************************************************************************
2297  * load_native_dll (internal)
2298  */
2300  const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
2301  DWORD flags, WINE_MODREF** pwm )
2302 {
2303  return build_module( load_path, nt_name, module, image_info, id, flags, pwm );
2304 }
2305 
2306 
2307 /***********************************************************************
2308  * load_so_dll
2309  */
2311  DWORD flags, WINE_MODREF **pwm )
2312 {
2313  void *module;
2314  NTSTATUS status;
2315  WINE_MODREF *wm;
2316  UNICODE_STRING win_name = *nt_name;
2317 
2318  TRACE( "trying %s as so lib\n", debugstr_us(&win_name) );
2319  if (unix_funcs->load_so_dll( &win_name, &module ))
2320  {
2321  WARN( "failed to load .so lib %s\n", debugstr_us(nt_name) );
2323  }
2324 
2325  if ((wm = get_modref( module ))) /* already loaded */
2326  {
2327  TRACE( "Found %s at %p for builtin %s\n",
2328  debugstr_w(wm->ldr.FullDllName.Buffer), wm->ldr.DllBase, debugstr_us(nt_name) );
2329  if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
2330  }
2331  else
2332  {
2333  if ((status = build_builtin_module( load_path, &win_name, module, flags, &wm ))) return status;
2334  TRACE_(loaddll)( "Loaded %s at %p: builtin\n", debugstr_us(nt_name), module );
2335  }
2336  *pwm = wm;
2337  return STATUS_SUCCESS;
2338 }
2339 
2340 
2341 /***********************************************************************
2342  * load_builtin_dll
2343  */
2344 static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module_ptr,
2345  DWORD flags, WINE_MODREF** pwm )
2346 {
2347  const WCHAR *name, *p;
2348  NTSTATUS status;
2349  void *module = NULL, *unix_entry = NULL;
2350  SECTION_IMAGE_INFORMATION image_info;
2351 
2352  /* Fix the name in case we have a full path and extension */
2353  name = nt_name->Buffer;
2354  if ((p = wcsrchr( name, '\\' ))) name = p + 1;
2355  if ((p = wcsrchr( name, '/' ))) name = p + 1;
2356 
2357  TRACE("Trying built-in %s\n", debugstr_w(name));
2358 
2359  if (!module_ptr) module_ptr = &module;
2360 
2361  status = unix_funcs->load_builtin_dll( name, module_ptr, &unix_entry, &image_info );
2362  if (status) return status;
2363 
2364  if ((*pwm = get_modref( *module_ptr ))) /* already loaded */
2365  {
2366  if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
2367  TRACE( "Found %s for %s at %p, count=%d\n",
2368  debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(name),
2369  (*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount);
2370  *module_ptr = NULL;
2371  return STATUS_SUCCESS;
2372  }
2373 
2374  TRACE( "loading %s from %s\n", debugstr_w(name), debugstr_us(nt_name) );
2375  status = build_module( load_path, nt_name, module_ptr, &image_info, NULL, flags, pwm );
2376  if (!status) (*pwm)->unix_entry = unix_entry;
2377  else if (*module_ptr) unix_funcs->unload_builtin_dll( *module_ptr );
2378  return status;
2379 }
2380 
2381 
2382 /***********************************************************************
2383  * find_actctx_dll
2384  *
2385  * Find the full path (if any) of the dll from the activation context.
2386  */
2387 static NTSTATUS find_actctx_dll( LPCWSTR libname, LPWSTR *fullname )
2388 {
2389  static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
2390 
2393  UNICODE_STRING nameW;
2394  NTSTATUS status;
2395  SIZE_T needed, size = 1024;
2396  WCHAR *p;
2397 
2398  RtlInitUnicodeString( &nameW, libname );
2399  data.cbSize = sizeof(data);
2402  &nameW, &data );
2403  if (status != STATUS_SUCCESS) return status;
2404 
2405  for (;;)
2406  {
2407  if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2408  {
2410  goto done;
2411  }
2412  status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
2414  info, size, &needed );
2415  if (status == STATUS_SUCCESS) break;
2416  if (status != STATUS_BUFFER_TOO_SMALL) goto done;
2417  RtlFreeHeap( GetProcessHeap(), 0, info );
2418  size = needed;
2419  /* restart with larger buffer */
2420  }
2421 
2422  if (!info->lpAssemblyManifestPath)
2423  {
2425  goto done;
2426  }
2427 
2428  if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' )))
2429  {
2430  DWORD len, dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
2431  p++;
2432  len = wcslen( p );
2433  if (!dirlen || len <= dirlen ||
2434  RtlCompareUnicodeStrings( p, dirlen, info->lpAssemblyDirectoryName, dirlen, TRUE ) ||
2435  wcsicmp( p + dirlen, L".manifest" ))
2436  {
2437  /* manifest name does not match directory name, so it's not a global
2438  * windows/winsxs manifest; use the manifest directory name instead */
2439  dirlen = p - info->lpAssemblyManifestPath;
2440  needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
2441  if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
2442  {
2444  goto done;
2445  }
2446  memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
2447  p += dirlen;
2448  wcscpy( p, libname );
2449  goto done;
2450  }
2451  }
2452 
2453  if (!info->lpAssemblyDirectoryName)
2454  {
2456  goto done;
2457  }
2458 
2459  needed = (wcslen(windows_dir) * sizeof(WCHAR) +
2460  sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR));
2461 
2462  if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
2463  {
2465  goto done;
2466  }
2467  wcscpy( p, windows_dir );
2468  p += wcslen(p);
2469  memcpy( p, winsxsW, sizeof(winsxsW) );
2470  p += ARRAY_SIZE( winsxsW );
2471  memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
2472  p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
2473  *p++ = '\\';
2474  wcscpy( p, libname );
2475 done:
2476  RtlFreeHeap( GetProcessHeap(), 0, info );
2477  RtlReleaseActivationContext( data.hActCtx );
2478  return status;
2479 }
2480 
2481 
2482 /***********************************************************************
2483  * search_dll_file
2484  *
2485  * Search for dll in the specified paths.
2486  */
2488  WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info,
2489  struct file_id *id )
2490 {
2491  WCHAR *name;
2492  BOOL found_image = FALSE;
2494  ULONG len = wcslen( paths );
2495 
2496  if (len < wcslen( system_dir )) len = wcslen( system_dir );
2497  len += wcslen( search ) + 2;
2498 
2499  if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2500  return STATUS_NO_MEMORY;
2501 
2502  while (*paths)
2503  {
2504  LPCWSTR ptr = paths;
2505 
2506  while (*ptr && *ptr != ';') ptr++;
2507  len = ptr - paths;
2508  if (*ptr == ';') ptr++;
2509  memcpy( name, paths, len * sizeof(WCHAR) );
2510  if (len && name[len - 1] != '\\') name[len++] = '\\';
2511  wcscpy( name + len, search );
2512 
2513  nt_name->Buffer = NULL;
2514  if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) goto done;
2515 
2516  status = open_dll_file( nt_name, pwm, module, image_info, id );
2517  if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
2518  else if (status != STATUS_DLL_NOT_FOUND) goto done;
2519  RtlFreeUnicodeString( nt_name );
2520  paths = ptr;
2521  }
2522 
2523  if (!found_image)
2524  {
2525  /* not found, return file in the system dir to be loaded as builtin */
2526  wcscpy( name, system_dir );
2527  wcscat( name, search );
2529  }
2531 
2532 done:
2533  RtlFreeHeap( GetProcessHeap(), 0, name );
2534  return status;
2535 }
2536 
2537 
2538 /***********************************************************************
2539  * find_dll_file
2540  *
2541  * Find the file (or already loaded module) for a given dll name.
2542  */
2543 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
2544  UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module,
2545  SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
2546 {
2547  WCHAR *ext, *dllname;
2548  NTSTATUS status;
2549  ULONG wow64_old_value = 0;
2550 
2551  *pwm = NULL;
2552  *module = NULL;
2553  dllname = NULL;
2554 
2555  if (default_ext) /* first append default extension */
2556  {
2557  if (!(ext = wcsrchr( libname, '.')) || wcschr( ext, '/' ) || wcschr( ext, '\\'))
2558  {
2559  if (!(dllname = RtlAllocateHeap( GetProcessHeap(), 0,
2560  (wcslen(libname)+wcslen(default_ext)+1) * sizeof(WCHAR))))
2561  return STATUS_NO_MEMORY;
2562  wcscpy( dllname, libname );
2563  wcscat( dllname, default_ext );
2564  libname = dllname;
2565  }
2566  }
2567 
2568  /* Win 7/2008R2 and up seem to re-enable WoW64 FS redirection when loading libraries */
2569  if (is_wow64) RtlWow64EnableFsRedirectionEx( 0, &wow64_old_value );
2570 
2571  nt_name->Buffer = NULL;
2572 
2573  if (!contains_path( libname ))
2574  {
2575  WCHAR *fullname = NULL;
2576 
2577  status = find_actctx_dll( libname, &fullname );
2578  if (status == STATUS_SUCCESS)
2579  {
2580  TRACE ("found %s for %s\n", debugstr_w(fullname), debugstr_w(libname) );
2581  RtlFreeHeap( GetProcessHeap(), 0, dllname );
2582  libname = dllname = fullname;
2583  }
2584  else
2585  {
2586  if (status != STATUS_SXS_KEY_NOT_FOUND) goto done;
2587  if ((*pwm = find_basename_module( libname )) != NULL)
2588  {
2590  goto done;
2591  }
2592  }
2593  }
2594 
2595  if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
2596  status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, id );
2597  else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL )))
2598  status = open_dll_file( nt_name, pwm, module, image_info, id );
2599 
2601 
2602 done:
2603  RtlFreeHeap( GetProcessHeap(), 0, dllname );
2604  if (wow64_old_value) RtlWow64EnableFsRedirectionEx( 1, &wow64_old_value );
2605  return status;
2606 }
2607 
2608 
2609 /***********************************************************************
2610  * load_dll (internal)
2611  *
2612  * Load a PE style module according to the load order.
2613  * The loader_section must be locked while calling this function.
2614  */
2615 static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
2616  DWORD flags, WINE_MODREF** pwm )
2617 {
2618  enum loadorder loadorder;
2620  UNICODE_STRING nt_name;
2621  struct file_id id;
2622  void *module;
2623  SECTION_IMAGE_INFORMATION image_info;
2624  NTSTATUS nts;
2625 
2626  TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
2627 
2628  nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &id );
2629 
2630  if (*pwm) /* found already loaded module */
2631  {
2632  if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
2633 
2634  TRACE("Found %s for %s at %p, count=%d\n",
2635  debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
2636  (*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount);
2637  RtlFreeUnicodeString( &nt_name );
2638  return STATUS_SUCCESS;
2639  }
2640 
2641  if (nts && nts != STATUS_DLL_NOT_FOUND && nts != STATUS_INVALID_IMAGE_NOT_MZ) goto done;
2642 
2643  main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
2644  loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, &nt_name );
2645 
2646  switch (nts)
2647  {
2648  case STATUS_INVALID_IMAGE_NOT_MZ: /* not in PE format, maybe it's a .so file */
2649  switch (loadorder)
2650  {
2651  case LO_NATIVE:
2652  case LO_NATIVE_BUILTIN:
2653  case LO_BUILTIN:
2654  case LO_BUILTIN_NATIVE:
2655  case LO_DEFAULT:
2656  if (!load_so_dll( load_path, &nt_name, flags, pwm )) nts = STATUS_SUCCESS;
2657  break;
2658  default:
2659  nts = STATUS_DLL_NOT_FOUND;
2660  break;
2661  }
2662  break;
2663 
2664  case STATUS_SUCCESS: /* valid PE file */
2665  if (image_info.u.ImageFlags & IMAGE_FLAGS_WineBuiltin)
2666  {
2667  switch (loadorder)
2668  {
2669  case LO_NATIVE_BUILTIN:
2670  case LO_BUILTIN:
2671  case LO_BUILTIN_NATIVE:
2672  case LO_DEFAULT:
2673  nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm );
2674  if (nts == STATUS_DLL_NOT_FOUND)
2675  nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
2676  break;
2677  default:
2678  nts = STATUS_DLL_NOT_FOUND;
2679  break;
2680  }
2682  break;
2683  }
2684  if (!(image_info.u.ImageFlags & IMAGE_FLAGS_WineFakeDll))
2685  {
2686  switch (loadorder)
2687  {
2688  case LO_NATIVE:
2689  case LO_NATIVE_BUILTIN:
2690  nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
2691  break;
2692  case LO_BUILTIN:
2693  nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm );
2694  break;
2695  case LO_BUILTIN_NATIVE:
2696  case LO_DEFAULT:
2697  nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm );
2698  if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
2699  (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
2700  {
2701  /* stub-only dll, try native */
2702  TRACE( "%s pre-attach returned FALSE, preferring native\n", debugstr_us(&nt_name) );
2703  LdrUnloadDll( (*pwm)->ldr.DllBase );
2704  nts = STATUS_DLL_NOT_FOUND;
2705  /* map the dll again if it was unmapped */
2706  if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &id )) break;
2707  }
2708  if (nts == STATUS_DLL_NOT_FOUND)
2709  nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
2710  break;
2711  default:
2712  nts = STATUS_DLL_NOT_FOUND;
2713  break;
2714  }
2716  break;
2717  }
2718  TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) );
2720  /* fall through */
2721 
2722  case STATUS_DLL_NOT_FOUND: /* no file found, try builtin */
2723  switch (loadorder)
2724  {
2725  case LO_NATIVE_BUILTIN:
2726  case LO_BUILTIN:
2727  case LO_BUILTIN_NATIVE:
2728  case LO_DEFAULT:
2729  nts = load_builtin_dll( load_path, &nt_name, NULL, flags, pwm );
2730  break;
2731  default:
2732  nts = STATUS_DLL_NOT_FOUND;
2733  break;
2734  }
2735  break;
2736  }
2737 
2738 done:
2739  if (nts == STATUS_SUCCESS)
2740  TRACE("Loaded module %s at %p\n", debugstr_us(&nt_name), (*pwm)->ldr.DllBase);
2741  else
2742  WARN("Failed to load module %s; status=%x\n", debugstr_w(libname), nts);
2743 
2744  RtlFreeUnicodeString( &nt_name );
2745  return nts;
2746 }
2747 
2748 
2749 /***********************************************************************
2750  * __wine_init_unix_lib
2751  */
2752 NTSTATUS __cdecl __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
2753 {
2754  WINE_MODREF *wm;
2756 
2758 
2759  if ((wm = get_modref( module )))
2760  {
2761  NTSTATUS (CDECL *init_func)( HMODULE, DWORD, const void *, void * ) = wm->unix_entry;
2762  if (init_func) ret = init_func( module, reason, ptr_in, ptr_out );
2763  }
2764  else ret = STATUS_INVALID_HANDLE;
2765 
2767  return ret;
2768 }
2769 
2770 
2771 /******************************************************************
2772  * LdrLoadDll (NTDLL.@)
2773  */
2775  const UNICODE_STRING *libname, HMODULE* hModule)
2776 {
2777  WINE_MODREF *wm;
2778  NTSTATUS nts;
2779 
2781 
2782  if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
2783  nts = load_dll( path_name, libname->Buffer, L".dll", flags, &wm );
2784 
2785  if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
2786  {
2787  nts = process_attach( wm, NULL );
2788  if (nts != STATUS_SUCCESS)
2789  {
2790  LdrUnloadDll(wm->ldr.DllBase);
2791  wm = NULL;
2792  }
2793  }
2794  *hModule = (wm) ? wm->ldr.DllBase : NULL;
2795 
2797  return nts;
2798 }
2799 
2800 
2801 /******************************************************************
2802  * LdrGetDllHandle (NTDLL.@)
2803  */
2805 {
2806  NTSTATUS status;
2807  UNICODE_STRING nt_name;
2808  WINE_MODREF *wm;
2809  void *module;
2810  SECTION_IMAGE_INFORMATION image_info;
2811  struct file_id id;
2812 
2814 
2815  if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
2816 
2817  status = find_dll_file( load_path, name->Buffer, L".dll", &nt_name, &wm, &module, &image_info, &id );
2818 
2819  if (wm) *base = wm->ldr.DllBase;
2820  else
2821  {
2824  }
2825  RtlFreeUnicodeString( &nt_name );
2826 
2828  TRACE( "%s -> %p (load path %s)\n", debugstr_us(name), status ? NULL : *base, debugstr_w(load_path) );
2829  return status;
2830 }
2831 
2832 
2833 /******************************************************************
2834  * LdrAddRefDll (NTDLL.@)
2835  */
2837 {
2838  NTSTATUS ret = STATUS_SUCCESS;
2839  WINE_MODREF *wm;
2840 
2841  if (flags & ~LDR_ADDREF_DLL_PIN) FIXME( "%p flags %x not implemented\n", module, flags );
2842 
2844 
2845  if ((wm = get_modref( module )))
2846  {
2847  if (flags & LDR_ADDREF_DLL_PIN)
2848  wm->ldr.LoadCount = -1;
2849  else
2850  if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
2851  TRACE( "(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
2852  }
2853  else ret = STATUS_INVALID_PARAMETER;
2854 
2856  return ret;
2857 }
2858 
2859 
2860 /***********************************************************************
2861  * LdrProcessRelocationBlock (NTDLL.@)
2862  *
2863  * Apply relocations to a given page of a mapped PE image.
2864  */
2866  USHORT *relocs, INT_PTR delta )
2867 {
2868  while (count--)
2869  {
2870  USHORT offset = *relocs & 0xfff;
2871  int type = *relocs >> 12;
2872  switch(type)
2873  {
2875  break;
2876  case IMAGE_REL_BASED_HIGH:
2877  *(short *)((char *)page + offset) += HIWORD(delta);
2878  break;
2879  case IMAGE_REL_BASED_LOW:
2880  *(short *)((char *)page + offset) += LOWORD(delta);
2881  break;
2883  *(int *)((char *)page + offset) += delta;
2884  break;
2885 #ifdef _WIN64
2886  case IMAGE_REL_BASED_DIR64:
2887  *(INT_PTR *)((char *)page + offset) += delta;
2888  break;
2889 #elif defined(__arm__)
2891  {
2892  DWORD *inst = (DWORD *)((char *)page + offset);
2893  WORD lo = ((inst[0] << 1) & 0x0800) + ((inst[0] << 12) & 0xf000) +
2894  ((inst[0] >> 20) & 0x0700) + ((inst[0] >> 16) & 0x00ff);
2895  WORD hi = ((inst[1] << 1) & 0x0800) + ((inst[1] << 12) & 0xf000) +
2896  ((inst[1] >> 20) & 0x0700) + ((inst[1] >> 16) & 0x00ff);
2897  DWORD imm = MAKELONG( lo, hi ) + delta;
2898 
2899  lo = LOWORD( imm );
2900  hi = HIWORD( imm );
2901 
2902  if ((inst[0] & 0x8000fbf0) != 0x0000f240 || (inst[1] & 0x8000fbf0) != 0x0000f2c0)
2903  ERR("wrong Thumb2 instruction @%p %08x:%08x, expected MOVW/MOVT\n",
2904  inst, inst[0], inst[1] );
2905 
2906  inst[0] = (inst[0] & 0x8f00fbf0) + ((lo >> 1) & 0x0400) + ((lo >> 12) & 0x000f) +
2907  ((lo << 20) & 0x70000000) + ((lo << 16) & 0xff0000);
2908  inst[1] = (inst[1] & 0x8f00fbf0) + ((hi >> 1) & 0x0400) + ((hi >> 12) & 0x000f) +
2909  ((hi << 20) & 0x70000000) + ((hi << 16) & 0xff0000);
2910  break;
2911  }
2912 #endif
2913  default:
2914  FIXME("Unknown/unsupported fixup type %x.\n", type);
2915  return NULL;
2916  }
2917  relocs++;
2918  }
2919  return (IMAGE_BASE_RELOCATION *)relocs; /* return address of next block */
2920 }
2921 
2922 
2923 /******************************************************************
2924  * LdrQueryProcessModuleInformation
2925  *
2926  */
2928  ULONG buf_size, ULONG* req_size)
2929 {
2930  SYSTEM_MODULE* sm = &smi->Modules[0];
2931  ULONG size = sizeof(ULONG);
2932  NTSTATUS nts = STATUS_SUCCESS;
2933  ANSI_STRING str;
2934  char* ptr;
2935  PLIST_ENTRY mark, entry;
2936  LDR_DATA_TABLE_ENTRY *mod;
2937  WORD id = 0;
2938 
2939  smi->ModulesCount = 0;
2940 
2942  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
2943  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
2944  {
2945  mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
2946  size += sizeof(*sm);
2947  if (size <= buf_size)
2948  {
2949  sm->Section = 0; /* FIXME */
2950  sm->MappedBaseAddress = mod->DllBase;
2951  sm->ImageBaseAddress = mod->DllBase;
2952  sm->ImageSize = mod->SizeOfImage;
2953  sm->Flags = mod->Flags;
2954  sm->LoadOrderIndex = id++;
2955  sm->InitOrderIndex = 0; /* FIXME */
2956  sm->LoadCount = mod->LoadCount;
2957  str.Length = 0;
2958  str.MaximumLength = MAXIMUM_FILENAME_LENGTH;
2959  str.Buffer = (char*)sm->Name;
2961  ptr = strrchr(str.Buffer, '\\');
2962  sm->NameOffset = (ptr != NULL) ? (ptr - str.Buffer + 1) : 0;
2963 
2964  smi->ModulesCount++;
2965  sm++;
2966  }
2967  else nts = STATUS_INFO_LENGTH_MISMATCH;
2968  }
2970 
2971  if (req_size) *req_size = size;
2972 
2973  return nts;
2974 }
2975 
2976 
2978 {
2979  NTSTATUS status;
2981  ULONG size;
2982  WCHAR buffer[64];
2984 
2986 
2987  size = sizeof(buffer) - sizeof(WCHAR);
2989  return status;
2990 
2991  if (info->Type != REG_DWORD)
2992  {
2993  buffer[size / sizeof(WCHAR)] = 0;
2994  *value = wcstoul( (WCHAR *)info->Data, 0, 16 );
2995  }
2996  else memcpy( value, info->Data, sizeof(*value) );
2997  return status;
2998 }
2999 
3001  void *data, ULONG in_size, ULONG *out_size )
3002 {
3003  NTSTATUS status;
3005  ULONG size;
3006  char *buffer;
3008  static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
3009 
3011 
3012  size = info_size + in_size;
3013  if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
3017  {
3018  if (out_size) *out_size = info->DataLength;
3019  if (data && !status) memcpy( data, info->Data, info->DataLength );
3020  }
3022  return status;
3023 }
3024 
3025 
3026 /******************************************************************
3027  * LdrQueryImageFileExecutionOptions (NTDLL.@)
3028  */
3030  void *data, ULONG in_size, ULONG *out_size )
3031 {
3032  static const WCHAR optionsW[] = {'M','a','c','h','i','n','e','\\',
3033  'S','o','f','t','w','a','r','e','\\',
3034  'M','i','c','r','o','s','o','f','t','\\',
3035  'W','i','n','d','o','w','s',' ','N','T','\\',
3036  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3037  'I','m','a','g','e',' ','F','i','l','e',' ',
3038  'E','x','e','c','u','t','i','o','n',' ','O','p','t','i','o','n','s','\\'};
3042  HANDLE hkey;
3043  NTSTATUS status;
3044  ULONG len;
3045  WCHAR *p;
3046 
3047  attr.Length = sizeof(attr);
3048  attr.RootDirectory = 0;
3049  attr.ObjectName = &name_str;
3050  attr.Attributes = OBJ_CASE_INSENSITIVE;
3051  attr.SecurityDescriptor = NULL;
3052  attr.SecurityQualityOfService = NULL;
3053 
3054  p = key->Buffer + key->Length / sizeof(WCHAR);
3055  while (p > key->Buffer && p[-1] != '\\') p--;
3056  len = key->Length - (p - key->Buffer) * sizeof(WCHAR);
3057  name_str.Buffer = path;
3058  name_str.Length = sizeof(optionsW) + len;
3059  name_str.MaximumLength = name_str.Length;
3060  memcpy( path, optionsW, sizeof(optionsW) );
3061  memcpy( path + ARRAY_SIZE( optionsW ), p, len );
3062  if ((status = NtOpenKey( &hkey, KEY_QUERY_VALUE, &attr ))) return status;
3063 
3064  if (type == REG_DWORD)
3065  {
3066  if (out_size) *out_size = sizeof(ULONG);
3067  if (in_size >= sizeof(ULONG)) status = query_dword_option( hkey, value, data );
3069  }
3070  else status = query_string_option( hkey, value, type, data, in_size, out_size );
3071 
3072  NtClose( hkey );
3073  return status;
3074 }
3075 
3076 
3077 /******************************************************************
3078  * RtlDllShutdownInProgress (NTDLL.@)
3079  */
3081 {
3082  return process_detaching;
3083 }
3084 
3085 /****************************************************************************
3086  * LdrResolveDelayLoadedAPI (NTDLL.@)
3087  */
3091  IMAGE_THUNK_DATA* addr, ULONG flags )
3092 {
3093  IMAGE_THUNK_DATA *pIAT, *pINT;
3094  DELAYLOAD_INFO delayinfo;
3095  UNICODE_STRING mod;
3096  const CHAR* name;
3097  HMODULE *phmod;
3098  NTSTATUS nts;
3099  FARPROC fp;
3100  DWORD id;
3101 
3102  TRACE( "(%p, %p, %p, %p, %p, 0x%08x)\n", base, desc, dllhook, syshook, addr, flags );
3103 
3104  phmod = get_rva(base, desc->ModuleHandleRVA);
3105  pIAT = get_rva(base, desc->ImportAddressTableRVA);
3106  pINT = get_rva(base, desc->ImportNameTableRVA);
3107  name = get_rva(base, desc->DllNameRVA);
3108  id = addr - pIAT;
3109 
3110  if (!*phmod)
3111  {
3113  {
3114  nts = STATUS_NO_MEMORY;
3115  goto fail;
3116  }
3117  nts = LdrLoadDll(NULL, 0, &mod, phmod);
3118  RtlFreeUnicodeString(&mod);
3119  if (nts) goto fail;
3120  }
3121 
3122  if (IMAGE_SNAP_BY_ORDINAL(pINT[id].u1.Ordinal))
3123  nts = LdrGetProcedureAddress(*phmod, NULL, LOWORD(pINT[id].u1.Ordinal), (void**)&fp);
3124  else
3125  {
3126  const IMAGE_IMPORT_BY_NAME* iibn = get_rva(base, pINT[id].u1.AddressOfData);
3127  ANSI_STRING fnc;
3128 
3129  RtlInitAnsiString(&fnc, (char*)iibn->Name);
3130  nts = LdrGetProcedureAddress(*phmod, &fnc, 0, (void**)&fp);
3131  }
3132  if (!nts)
3133  {
3134  pIAT[id].u1.Function = (ULONG_PTR)fp;
3135  return fp;
3136  }
3137 
3138 fail:
3139  delayinfo.Size = sizeof(delayinfo);
3140  delayinfo.DelayloadDescriptor = desc;
3141  delayinfo.ThunkAddress = addr;
3142  delayinfo.TargetDllName = name;
3144  delayinfo.TargetApiDescriptor.Description.Ordinal = LOWORD(pINT[id].u1.Ordinal);
3145  delayinfo.TargetModuleBase = *phmod;
3146  delayinfo.Unused = NULL;
3147  delayinfo.LastError = nts;
3148 
3149  if (dllhook)
3150  return dllhook(4, &delayinfo);
3151 
3152  if (IMAGE_SNAP_BY_ORDINAL(pINT[id].u1.Ordinal))
3153  {
3154  DWORD_PTR ord = LOWORD(pINT[id].u1.Ordinal);
3155  return syshook(name, (const char *)ord);
3156  }
3157  else
3158  {
3159  const IMAGE_IMPORT_BY_NAME* iibn = get_rva(base, pINT[id].u1.AddressOfData);
3160  return syshook(name, (const char *)iibn->Name);
3161  }
3162 }
3163 
3164 /******************************************************************
3165  * LdrShutdownProcess (NTDLL.@)
3166  *
3167  */
3169 {
3170  BOOL detaching = process_detaching;
3171 
3172  TRACE("()\n");
3173 
3175  if (!detaching)
3176  RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 );
3177 
3178  process_detach();
3179 }
3180 
3181 
3182 /******************************************************************
3183  * RtlExitUserProcess (NTDLL.@)
3184  */
3186 {
3189  NtTerminateProcess( 0, status );
3192 }
3193 
3194 /******************************************************************
3195  * LdrShutdownThread (NTDLL.@)
3196  *
3197  */
3199 {
3200  PLIST_ENTRY mark, entry;
3201  LDR_DATA_TABLE_ENTRY *mod;
3202  WINE_MODREF *wm;
3203  UINT i;
3204  void **pointers;
3205 
3206  TRACE("()\n");
3207 
3208  /* don't do any detach calls if process is exiting */
3209  if (process_detaching) return;
3210 
3211  RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 );
3212 
3214  wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
3215 
3216  mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
3217  for (entry = mark->Blink; entry != mark; entry = entry->Blink)
3218  {
3220  InInitializationOrderLinks);
3221  if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
3222  continue;
3223  if ( mod->Flags & LDR_NO_DLL_CALLS )
3224  continue;
3225 
3228  }
3229 
3231 
3233  RemoveEntryList( &NtCurrentTeb()->TlsLinks );
3234  if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer))
3235  {
3236  for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] );
3237  RtlFreeHeap( GetProcessHeap(), 0, pointers );
3238  }
3239  RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 );
3240  NtCurrentTeb()->FlsSlots = NULL;
3241  RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
3242  NtCurrentTeb()->TlsExpansionSlots = NULL;
3244 
3246 }
3247 
3248 
3249 /***********************************************************************
3250  * free_modref
3251  *
3252  */
3253 static void free_modref( WINE_MODREF *wm )
3254 {
3259 
3260  TRACE(" unloading %s\n", debugstr_w(wm->ldr.FullDllName.Buffer));
3261  if (!TRACE_ON(module))
3262  TRACE_(loaddll)("Unloaded module %s : %s\n",
3263  debugstr_w(wm->ldr.FullDllName.Buffer),
3264  (wm->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native" );
3265 
3266  SERVER_START_REQ( unload_dll )
3267  {
3268  req->base = wine_server_client_ptr( wm->ldr.DllBase );
3269  wine_server_call( req );
3270  }
3272 
3273  free_tls_slot( &wm->ldr );
3277  if (cached_modref == wm) cached_modref = NULL;
3279  RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
3280  RtlFreeHeap( GetProcessHeap(), 0, wm );
3281 }
3282 
3283 /***********************************************************************
3284  * MODULE_FlushModrefs
3285  *
3286  * Remove all unused modrefs and call the internal unloading routines
3287  * for the library type.
3288  *
3289  * The loader_section must be locked while calling this function.
3290  */
3291 static void MODULE_FlushModrefs(void)
3292 {
3293  PLIST_ENTRY mark, entry, prev;
3294  LDR_DATA_TABLE_ENTRY *mod;
3295  WINE_MODREF*wm;
3296 
3297  mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
3298  for (entry = mark->Blink; entry != mark; entry = prev)
3299  {
3300  mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
3301  wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
3302  prev = entry->Blink;
3303  if (!mod->LoadCount) free_modref( wm );
3304  }
3305 
3306  /* check load order list too for modules that haven't been initialized yet */
3307  mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
3308  for (entry = mark->Blink; entry != mark; entry = prev)
3309  {
3310  mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
3311  wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
3312  prev = entry->Blink;
3313  if (!mod->LoadCount) free_modref( wm );
3314  }
3315 }
3316 
3317 /***********************************************************************
3318  * MODULE_DecRefCount
3319  *
3320  * The loader_section must be locked while calling this function.
3321  */
3323 {
3324  int i;
3325 
3326  if ( wm->ldr.Flags & LDR_UNLOAD_IN_PROGRESS )
3327  return;
3328 
3329  if ( wm->ldr.LoadCount <= 0 )
3330  return;
3331 
3332  --wm->ldr.LoadCount;
3333  TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
3334 
3335  if ( wm->ldr.LoadCount == 0 )
3336  {
3338 
3339  for ( i = 0; i < wm->nDeps; i++ )
3340  if ( wm->deps[i] )
3341  MODULE_DecRefCount( wm->deps[i] );
3342 
3343  wm->ldr.Flags &= ~~LDR_UNLOAD_IN_PROGRESS;
3344 
3345  module_push_unload_trace( &wm->ldr );
3346  }
3347 }
3348 
3349 /******************************************************************
3350  * LdrUnloadDll (NTDLL.@)
3351  *
3352  *
3353  */
3355 {
3356  WINE_MODREF *wm;
3357  NTSTATUS retv = STATUS_SUCCESS;
3358 
3359  if (process_detaching) return retv;
3360 
3361  TRACE("(%p)\n", hModule);
3362 
3364 
3365  free_lib_count++;
3366  if ((wm = get_modref( hModule )) != NULL)
3367  {
3368  TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
3369 
3370  /* Recursively decrement reference counts */
3371  MODULE_DecRefCount( wm );
3372 
3373  /* Call process detach notifications */
3374  if ( free_lib_count <= 1 )
3375  {
3376  process_detach();
3378  }
3379 
3380  TRACE("END\n");
3381  }
3382  else
3383  retv = STATUS_DLL_NOT_FOUND;
3384 
3385  free_lib_count--;
3386 
3388 
3389  return retv;
3390 }
3391 
3392 /***********************************************************************
3393  * RtlImageNtHeader (NTDLL.@)
3394  */
3396 {
3397  IMAGE_NT_HEADERS *ret;
3398 
3399  __TRY
3400  {
3402 
3403  ret = NULL;
3404  if (dos->e_magic == IMAGE_DOS_SIGNATURE)
3405  {
3406  ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
3407  if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
3408  }
3409  }
3411  {
3412  return NULL;
3413  }
3414  __ENDTRY
3415  return ret;
3416 }
3417 
3418 /***********************************************************************
3419  * process_breakpoint
3420  *
3421  * Trigger a debug breakpoint if the process is being debugged.
3422  */
3423 static void process_breakpoint(void)
3424 {
3425  DWORD_PTR port = 0;
3426 
3428  if (!port) return;
3429 
3430  __TRY
3431  {
3432  DbgBreakPoint();
3433  }
3434  __EXCEPT_ALL
3435  {
3436  /* do nothing */
3437  }
3438  __ENDTRY
3439 }
3440 
3441 
3442 /******************************************************************
3443  * LdrInitializeThunk (NTDLL.@)
3444  *
3445  * Attach to all the loaded dlls.
3446  * If this is the first time, perform the full process initialization.
3447  */
3448 void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR unknown3, ULONG_PTR unknown4 )
3449 {
3450  static int attach_done;
3451  int i;
3452  NTSTATUS status;
3453  ULONG_PTR cookie;
3454  WINE_MODREF *wm;
3455  void **entry;
3456  LPCWSTR load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
3457 
3458 #ifdef __i386__
3459  entry = (void **)&context->Eax;
3460 #elif defined(__x86_64__)
3461  entry = (void **)&context->Rcx;
3462 #elif defined(__arm__)
3463  entry = (void **)&context->R0;
3464 #elif defined(__aarch64__)
3465  entry = (void **)&context->u.s.X0;
3466 #endif
3467 
3469 
3471 
3472  wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
3473  assert( wm );
3474 
3475  if (!imports_fixup_done)
3476  {
3477  actctx_init();
3478  if (wm->ldr.Flags & LDR_COR_ILONLY)
3479  status = fixup_imports_ilonly( wm, load_path, entry );
3480  else
3481  status = fixup_imports( wm, load_path );
3482 
3483  if (status)
3484  {
3485  ERR( "Importing dlls for %s failed, status %x\n",
3486  debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer), status );
3488  }
3490  }
3491 
3493  InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
3495 
3496  NtCurrentTeb()->FlsSlots = fls_alloc_data();
3497 
3498  if (!attach_done) /* first time around */
3499  {
3500  attach_done = 1;
3501  if ((status = alloc_thread_tls()) != STATUS_SUCCESS)
3502  {
3503  ERR( "TLS init failed when loading %s, status %x\n",
3504  debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer), status );
3506  }
3507  wm->ldr.LoadCount = -1;
3508  wm->ldr.Flags |= LDR_PROCESS_ATTACHED; /* don't try to attach again */
3509  if (wm->ldr.ActivationContext)
3511 
3512  for (i = 0; i < wm->nDeps; i++)
3513  {
3514  if (!wm->deps[i]) continue;
3515  if ((status = process_attach( wm->deps[i], context )) != STATUS_SUCCESS)
3516  {
3517  if (last_failed_modref)
3518  ERR( "%s failed to initialize, aborting\n",
3519  debugstr_w(last_failed_modref->ldr.BaseDllName.Buffer) + 1 );
3520  ERR( "Initializing dlls for %s failed, status %x\n",
3521  debugstr_w(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer), status );
3523  }
3524  }
3531  }
3532  else
3533  {
3534  if ((status = alloc_thread_tls()) != STATUS_SUCCESS)
3536  thread_attach();
3538  }
3539 
3542 }
3543 
3544 
3545 /***********************************************************************
3546  * load_global_options
3547  */
3548 static void load_global_options(void)
3549 {
3552  HANDLE hkey;
3553  ULONG value;
3554 
3555  attr.Length = sizeof(attr);
3556  attr.RootDirectory = 0;
3557  attr.ObjectName = &name_str;
3558  attr.Attributes = OBJ_CASE_INSENSITIVE;
3559  attr.SecurityDescriptor = NULL;
3560  attr.SecurityQualityOfService = NULL;
3561  RtlInitUnicodeString( &name_str, L"Machine\\System\\CurrentControlSet\\Control\\Session Manager" );
3562 
3563  if (!NtOpenKey( &hkey, KEY_QUERY_VALUE, &attr ))
3564  {
3565  query_dword_option( hkey, L"GlobalFlag", &NtCurrentTeb()->Peb->NtGlobalFlag );
3566  query_dword_option( hkey, L"SafeProcessSearchMode", &path_safe_mode );
3567  query_dword_option( hkey, L"SafeDllSearchMode", &dll_safe_mode );
3568 
3569  if (!query_dword_option( hkey, L"CriticalSectionTimeout", &value ))
3570  NtCurrentTeb()->Peb->CriticalSectionTimeout.QuadPart = (ULONGLONG)value * -10000000;
3571 
3572  if (!query_dword_option( hkey, L"HeapSegmentReserve", &value ))
3573  NtCurrentTeb()->Peb->HeapSegmentReserve = value;
3574 
3575  if (!query_dword_option( hkey, L"HeapSegmentCommit", &value ))
3576  NtCurrentTeb()->Peb->HeapSegmentCommit = value;
3577 
3578  if (!query_dword_option( hkey, L"HeapDeCommitTotalFreeThreshold", &value ))
3579  NtCurrentTeb()->Peb->HeapDeCommitTotalFreeThreshold = value;
3580 
3581  if (!query_dword_option( hkey, L"HeapDeCommitFreeBlockThreshold", &value ))
3582  NtCurrentTeb()->Peb->HeapDeCommitFreeBlockThreshold = value;
3583 
3584  NtClose( hkey );
3585  }
3586  LdrQueryImageFileExecutionOptions( &NtCurrentTeb()->Peb->ProcessParameters->ImagePathName,
3587  L"GlobalFlag", REG_DWORD, &NtCurrentTeb()->Peb->NtGlobalFlag,
3588  sizeof(DWORD), NULL );
3590 }
3591 
3592 
3593 /***********************************************************************
3594  * RtlImageDirectoryEntryToData (NTDLL.@)
3595  */
3597 {
3598  const IMAGE_NT_HEADERS *nt;
3599  DWORD addr;
3600 
3601  if ((ULONG_PTR)module & 1) image = FALSE; /* mapped as data file */
3602  module = (HMODULE)((ULONG_PTR)module & ~3);
3603  if (!(nt = RtlImageNtHeader( module ))) return NULL;
3605  {
3606  const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt;
3607 
3608  if (dir >= nt64->OptionalHeader.NumberOfRvaAndSizes) return NULL;
3609  if (!(addr = nt64->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
3611  if (image || addr < nt64->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
3612  }
3614  {
3615  const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt;
3616 
3617  if (dir >= nt32->OptionalHeader.NumberOfRvaAndSizes) return NULL;
3618  if (!(addr = nt32->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
3620  if (image || addr < nt32->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
3621  }
3622  else return NULL;
3623 
3624  /* not mapped as image, need to find the section containing the virtual address */
3625  return RtlImageRvaToVa( nt, module, addr, NULL );
3626 }
3627 
3628 
3629 /***********************************************************************
3630  * RtlImageRvaToSection (NTDLL.@)
3631  */
3633  HMODULE module, DWORD rva )
3634 {
3635  int i;
3636  const IMAGE_SECTION_HEADER *sec;
3637 
3638  sec = (const IMAGE_SECTION_HEADER*)((const char*)&nt->OptionalHeader +
3640  for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
3641  {
3642  if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
3643  return (PIMAGE_SECTION_HEADER)sec;
3644  }
3645  return NULL;
3646 }
3647 
3648 
3649 /***********************************************************************
3650  * RtlImageRvaToVa (NTDLL.@)
3651  */
3654 {
3655  IMAGE_SECTION_HEADER *sec;
3656 
3657  if (section && *section) /* try this section first */
3658  {
3659  sec = *section;
3660  if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
3661  goto found;
3662  }
3663  if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
3664  found:
3665  if (section) *section = sec;
3666  return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
3667 }
3668 
3669 
3670 /***********************************************************************
3671  * RtlPcToFileHeader (NTDLL.@)
3672  */
3674 {
3676  PVOID ret = NULL;
3677 
3679  if (!LdrFindEntryForAddress( pc, &module )) ret = module->DllBase;
3681  *address = ret;
3682  return ret;
3683 }
3684 
3685 
3686 /****************************************************************************
3687  * LdrGetDllDirectory (NTDLL.@)
3688  */
3690 {
3692 
3694  dir->Length = dll_directory.Length + sizeof(WCHAR);
3695  if (dir->MaximumLength >= dir->Length) RtlCopyUnicodeString( dir, &dll_directory );
3696  else
3697  {
3699  if (dir->MaximumLength) dir->Buffer[0] = 0;
3700  }
3702  return status;
3703 }
3704 
3705 
3706 /****************************************************************************
3707  * LdrSetDllDirectory (NTDLL.@)
3708  */
3710 {
3712  UNICODE_STRING new;
3713 
3714  if (!dir->Buffer) RtlInitUnicodeString( &new, NULL );
3715  else if ((status = RtlDuplicateUnicodeString( 1, dir, &new ))) return status;
3716 
3719  dll_directory = new;
3721  return status;
3722 }
3723 
3724 
3725 /****************************************************************************
3726  * LdrAddDllDirectory (NTDLL.@)
3727  */
3729 {
3731  UNICODE_STRING nt_name;
3732  NTSTATUS status;
3734  DWORD len;
3735  struct dll_dir_entry *ptr;
3737 
3739  return STATUS_INVALID_PARAMETER;
3740 
3741  status = RtlDosPathNameToNtPathName_U_WithStatus( dir->Buffer, &nt_name, NULL, NULL );
3742  if (status) return status;
3743  len = nt_name.Length / sizeof(WCHAR);
3744  if (!(ptr = RtlAllocateHeap( GetProcessHeap(), 0, offsetof(struct dll_dir_entry, dir[++len] ))))
3745  return STATUS_NO_MEMORY;
3746  memcpy( ptr->dir, nt_name.Buffer, len * sizeof(WCHAR) );
3747 
3748  attr.Length = sizeof(attr);
3749  attr.RootDirectory = 0;
3750  attr.Attributes = OBJ_CASE_INSENSITIVE;
3751  attr.ObjectName = &nt_name;
3752  attr.SecurityDescriptor = NULL;
3753  attr.SecurityQualityOfService = NULL;
3755  RtlFreeUnicodeString( &nt_name );
3756 
3757  if (!status)
3758  {
3759  TRACE( "%s\n", debugstr_w( ptr->dir ));
3761  list_add_head( &dll_dir_list, &ptr->entry );
3763  *cookie = ptr;
3764  }
3765  else RtlFreeHeap( GetProcessHeap(), 0, ptr );
3766  return status;
3767 }
3768 
3769 
3770 /****************************************************************************
3771  * LdrRemoveDllDirectory (NTDLL.@)
3772  */
3774 {
3775  struct dll_dir_entry *ptr = cookie;
3776 
3777  TRACE( "%s\n", debugstr_w( ptr->dir ));
3778 
3780  list_remove( &ptr->entry );
3781  RtlFreeHeap( GetProcessHeap(), 0, ptr );
3783  return STATUS_SUCCESS;
3784 }
3785 
3786 
3787 /*************************************************************************
3788  * LdrSetDefaultDllDirectories (NTDLL.@)
3789  */
3791 {
3792  /* LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR doesn't make sense in default dirs */
3793  const ULONG load_library_search_flags = (LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
3797 
3798  if (!flags || (flags & ~load_library_search_flags)) return STATUS_INVALID_PARAMETER;
3800  return STATUS_SUCCESS;
3801 }
3802 
3803 
3804 /******************************************************************
3805  * LdrGetDllPath (NTDLL.@)
3806  */
3808 {
3809  NTSTATUS status;
3810  const ULONG load_library_search_flags = (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
3815 
3817  {
3818  if (flags & load_library_search_flags) return STATUS_INVALID_PARAMETER;
3820  }
3821  else if (!(flags & load_library_search_flags)) flags |= default_search_flags;
3822 
3824 
3825  if (flags & load_library_search_flags)
3826  {
3828  }
3829  else
3830  {
3831  const WCHAR *dlldir = dll_directory.Length ? dll_directory.Buffer : NULL;
3833  module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
3835  }
3836 
3838  *unknown = NULL;
3839  return status;
3840 }
3841 
3842 
3843 /*************************************************************************
3844  * RtlSetSearchPathMode (NTDLL.@)
3845  */
3847 {
3848  int val;
3849 
3850  switch (flags)
3851  {
3853  val = 1;
3854  break;
3856  val = 0;
3857  break;
3859  InterlockedExchange( (int *)&path_safe_mode, 2 );
3860  return STATUS_SUCCESS;
3861  default:
3862  return STATUS_INVALID_PARAMETER;
3863  }
3864 
3865  for (;;)
3866  {
3867  int prev = path_safe_mode;
3868  if (prev == 2) break; /* permanently set */
3869  if (InterlockedCompareExchange( (int *)&path_safe_mode, val, prev ) == prev) return STATUS_SUCCESS;
3870  }
3871  return STATUS_ACCESS_DENIED;
3872 }
3873 
3874 
3875 /******************************************************************
3876  * RtlGetExePath (NTDLL.@)
3877  */
3879 {
3880  const WCHAR *dlldir = L".";
3881  const WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
3882 
3883  /* same check as NeedCurrentDirectoryForExePathW */
3884  if (!wcschr( name, '\\' ))
3885  {
3886  UNICODE_STRING name, value = { 0 };
3887 
3888  RtlInitUnicodeString( &name, L"NoDefaultCurrentDirectoryInExePath" );
3890  dlldir = L"";
3891  }
3892  return get_dll_load_path( module, dlldir, FALSE, path );
3893 }
3894 
3895 
3896 /******************************************************************
3897  * RtlGetSearchPath (NTDLL.@)
3898  */
3900 {
3901  const WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
3903 }
3904 
3905 
3906 /******************************************************************
3907  * RtlReleasePath (NTDLL.@)
3908  */
3910 {
3911  RtlFreeHeap( GetProcessHeap(), 0, path );
3912 }
3913 
3914 
3915 /******************************************************************
3916  * DllMain (NTDLL.@)
3917  */
3919 {
3921  return TRUE;
3922 }
3923 
3924 
3925 /***********************************************************************
3926  * restart_winevdm
3927  */
3929 {
3930  DWORD len;
3931  WCHAR *appname, *cmdline;
3932 
3933  len = wcslen(system_dir) + wcslen(L"winevdm.exe") + 1;
3934  appname = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3935  wcscpy( appname, (is_win64 || is_wow64) ? syswow64_dir : system_dir );
3936  wcscat( appname, L"winevdm.exe" );
3937 
3938  len += 16 + wcslen(params->ImagePathName.Buffer) + wcslen(params->CommandLine.Buffer);
3939  cmdline = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3940  swprintf( cmdline, len, L"%s --app-name \"%s\" %s",
3941  appname, params->ImagePathName.Buffer, params->CommandLine.Buffer );
3942 
3943  RtlInitUnicodeString( &params->ImagePathName, appname );
3945 }
3946 
3947 
3948 /***********************************************************************
3949  * process_init
3950  */
3952 {
3954  WINE_MODREF *wm;
3955  NTSTATUS status;
3956  ANSI_STRING func_name;
3957  UNICODE_STRING nt_name;
3958  MEMORY_BASIC_INFORMATION meminfo;
3959  INITIAL_TEB stack;
3960  TEB *teb = NtCurrentTeb();
3961  PEB *peb = teb->Peb;
3962 
3963  peb->LdrData = &ldr;
3964  peb->FastPebLock = &peb_lock;
3965  peb->TlsBitmap = &tls_bitmap;
3967  peb->LoaderLock = &loader_section;
3968  peb->OSMajorVersion = 5;
3969  peb->OSMinorVersion = 1;
3970  peb->OSBuildNumber = 0xA28;
3972  peb->SessionId = 1;
3973  peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL );
3974 
3975  RtlInitializeBitMap( &tls_bitmap, peb->TlsBitmapBits, sizeof(peb->TlsBitmapBits) * 8 );
3977  sizeof(peb->TlsExpansionBitmapBits) * 8 );
3978  RtlSetBits( peb->TlsBitmap, 0, 1 ); /* TLS index 0 is reserved and should be initialized to NULL. */
3980 
3984 
3985 #ifndef _WIN64
3986  is_wow64 = !!NtCurrentTeb64();
3987 #endif
3988 
3990  init_directories();
3992  params = peb->ProcessParameters;
3993 
3995  version_init();
3996 
3997  /* setup the load callback and create ntdll modref */
3998  RtlInitUnicodeString( &nt_name, L"\\??\\C:\\windows\\system32\\ntdll.dll" );
4000  &meminfo, sizeof(meminfo), NULL );
4001  status = build_builtin_module( params->DllPath.Buffer, &nt_name, meminfo.AllocationBase, 0, &wm );
4002  assert( !status );
4003 
4004  if ((status = load_dll( params->DllPath.Buffer, L"C:\\windows\\system32\\kernel32.dll",
4005  NULL, 0, &wm )) != STATUS_SUCCESS)
4006  {
4007  MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
4009  }
4010  RtlInitAnsiString( &func_name, "BaseThreadInitThunk" );
4011  if ((status = LdrGetProcedureAddress( wm->ldr.DllBase, &func_name,
4012  0, (void **)&pBaseThreadInitThunk )) != STATUS_SUCCESS)
4013  {
4014  MESSAGE( "wine: could not find BaseThreadInitThunk in kernel32.dll, status %x\n", status );
4016  }
4017 
4018  init_locale( wm->ldr.DllBase );
4019 
4020  if (!(status = load_dll( params->DllPath.Buffer, params->ImagePathName.Buffer, NULL,
4022  {
4023  peb->ImageBaseAddress = wm->ldr.DllBase;
4024  TRACE( "main exe loaded %s at %p\n", debugstr_us(&params->ImagePathName), peb->ImageBaseAddress );
4025  if (wm->ldr.Flags & LDR_IMAGE_IS_DLL)
4026  {
4027  MESSAGE( "wine: %s is a dll, not an executable\n", debugstr_w(wm->ldr.FullDllName.Buffer) );
4029  }
4030  }
4031  else
4032  {
4033  switch (status)
4034  {
4036  {
4037  WCHAR *p = wcsrchr( params->ImagePathName.Buffer, '.' );
4038  if (p && (!wcsicmp( p, L".com" ) || !wcsicmp( p, L".pif" )))
4039  {
4040  restart_winevdm( params );
4042  }
4043  return status;
4044  }
4048  restart_winevdm( params );
4049  return status;
4051  case STATUS_NO_MEMORY:
4053  return status;
4055  ERR( "%s 64-bit application not supported in 32-bit prefix\n",
4056  debugstr_us(&params->ImagePathName) );
4057  break;
4058  case STATUS_DLL_NOT_FOUND:
4059  ERR( "%s not found\n", debugstr_us(&params->ImagePathName) );
4060  break;
4061  default:
4062  ERR( "failed to load %s, error %x\n", debugstr_us(&params->ImagePathName), status );
4063  break;
4064  }
4066  }
4067 
4068 #ifndef _WIN64
4069  if (NtCurrentTeb64())
4070  {
4071  PEB64 *peb64 = UlongToPtr( NtCurrentTeb64()->Peb );
4072  peb64->ImageBaseAddress = PtrToUlong( peb->ImageBaseAddress );
4073  peb64->OSMajorVersion = peb->OSMajorVersion;
4074  peb64->OSMinorVersion = peb->OSMinorVersion;
4075  peb64->OSBuildNumber = peb->OSBuildNumber;
4076  peb64->OSPlatformId = peb->OSPlatformId;
4077  peb64->SessionId = peb->SessionId;
4078  }
4079 #endif
4080 
4081  /* the main exe needs to be the first in the load order list */
4086 
4087  RtlCreateUserStack( 0, 0, 0, 0x10000, 0x10000, &stack );
4088  teb->Tib.StackBase = stack.StackBase;
4089  teb->Tib.StackLimit = stack.StackLimit;
4090  teb->DeallocationStack = stack.DeallocationStack;
4091  return STATUS_SUCCESS;
4092 }
4093 
4094 /***********************************************************************
4095  * __wine_set_unix_funcs
4096  */
4098 {
4100  unix_funcs = funcs;
4101  return process_init();
4102 }
NTSTATUS RtlQueryInformationActivationContext(ULONG flags, HANDLE handle, PVOID subinst, ULONG class, PVOID buffer, SIZE_T bufsize, SIZE_T *retlen)
Definition: actctx.c:5136
NTSTATUS RtlFindActivationContextSectionString(ULONG flags, const GUID *guid, ULONG section_kind, const UNICODE_STRING *section_name, PVOID ptr)
Definition: actctx.c:5390
NTSTATUS RtlActivateActivationContext(ULONG unknown, HANDLE handle, PULONG_PTR cookie)
Definition: actctx.c:5020
void RtlReleaseActivationContext(HANDLE handle)
Definition: actctx.c:4999
void RtlDeactivateActivationContext(ULONG flags, ULONG_PTR cookie)
Definition: actctx.c:5051
NTSTATUS RtlCreateActivationContext(HANDLE *handle, const void *ptr)
Definition: actctx.c:4849
void actctx_init(void)
Definition: actctx.c:4825
static LPCSTR debugstr_us(const UNICODE_STRING *us)
Definition: lsa.c:47
HMODULE hModule
Definition: animate.c:44
#define __ASM_CFI(str)
Definition: asm.h:41
#define __ASM_GLOBAL_FUNC(name, code)
Definition: asm.h:90
static const WCHAR version[]
Definition: asmname.c:63
#define assert(_expr)
Definition: assert.h:32
#define ULONG
Definition: audiounit.c:23
#define UlongToPtr(ul)
Definition: basetsd.h:261
ULONG_PTR DWORD_PTR
Definition: basetsd.h:131
#define IntToPtr(i)
Definition: basetsd.h:251
#define ULongToPtr(ul)
Definition: basetsd.h:254
#define PtrToUlong(p)
Definition: basetsd.h:245
unsigned long ULONG_PTR
Definition: basetsd.h:130
long INT_PTR
Definition: basetsd.h:127
ULONG_PTR SIZE_T
Definition: basetsd.h:264
LONG NTSTATUS
Definition: bcrypt.h:40
#define WINAPI
Definition: bcrypt.h:23
Definition: type.pm:7
#define ERR(...)
Definition: cocoa_app.h:61
struct IStream LPVOID
Definition: commctrl.h:5192
#define __cdecl
Definition: corecrt.h:100
static int WINAPIV swprintf(wchar_t *buffer, size_t size, const wchar_t *format,...)
NTSTATUS RtlLeaveCriticalSection(RTL_CRITICAL_SECTION *crit)
Definition: critsection.c:526
BOOL RtlTryEnterCriticalSection(RTL_CRITICAL_SECTION *crit)
Definition: critsection.c:453
NTSTATUS RtlEnterCriticalSection(RTL_CRITICAL_SECTION *crit)
Definition: critsection.c:399
static struct unix_funcs funcs
Definition: unixlib.c:631
PVOID(WINAPI * PDELAYLOAD_FAILURE_SYSTEM_ROUTINE)(LPCSTR, LPCSTR)
PVOID(WINAPI * PDELAYLOAD_FAILURE_DLL_CALLBACK)(ULONG, PDELAYLOAD_INFO)
static BOOL notify(const LISTVIEW_INFO *infoPtr, INT code)
Definition: listview.c:840
static WCHAR unknown[128]
Definition: object.c:1644
static WCHAR reason[128]
Definition: object.c:1941
int id
Definition: main.c:4907
size_t strlen(const char *str)
Definition: string.c:1502
void * memcpy(void *dst, const void *src, size_t n)
Definition: string.c:2580
int strcmp(const char *str1, const char *str2)
Definition: string.c:2631
char * strrchr(const char *str, int c)
Definition: string.c:2610
void * memset(void *dst, int c, size_t n)
Definition: string.c:2588
int memcmp(const void *ptr1, const void *ptr2, size_t n)
Definition: string.c:2461
void * memmove(void *dst, const void *src, size_t n)
Definition: string.c:2481
int atoi(const char *str)
Definition: string.c:1650
NTSTATUS RtlWow64EnableFsRedirectionEx(ULONG disable, ULONG *old_value)
Definition: directory.c:102
void init_directories(void)
Definition: directory.c:51
static WINE_MODREF * find_fileid_module(const struct file_id *id)
Definition: loader.c:548
static ULONG_PTR allocate_stub(const char *dll, const char *name)
Definition: loader.c:429
static FARPROC find_ordinal_export(HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, DWORD ordinal, LPCWSTR load_path)
Definition: loader.c:673
NTSTATUS LdrQueryImageFileExecutionOptions(const UNICODE_STRING *key, LPCWSTR value, ULONG type, void *data, ULONG in_size, ULONG *out_size)
Definition: loader.c:3029
NTSTATUS LdrDisableThreadCalloutsForDll(HMODULE hModule)
Definition: loader.c:1537
static void load_global_options(void)
Definition: loader.c:3548
static FARPROC find_forwarded_export(HMODULE module, const char *forward, LPCWSTR load_path)
Definition: loader.c:597
NTSTATUS LdrAddRefDll(ULONG flags, HMODULE module)
Definition: loader.c:2836
static WCHAR * append_path(WCHAR *p, const WCHAR *str, int len)
Definition: loader.c:2076
static WINE_MODREF * get_modref(HMODULE hmod)
Definition: loader.c:462
static BOOL contains_path(LPCWSTR name)
Definition: loader.c:182
static void free_modref(WINE_MODREF *wm)
Definition: loader.c:3253
static void process_breakpoint(void)
Definition: loader.c:3423
static NTSTATUS get_dll_load_path(LPCWSTR module, LPCWSTR dll_dir, ULONG safe_mode, WCHAR **path)
Definition: loader.c:2089
static WINE_MODREF * find_fullname_module(const UNICODE_STRING *nt_name)
Definition: loader.c:516
NTSTATUS RtlGetSearchPath(PWSTR *path)
Definition: loader.c:3899
void(* LDRENUMPROC)(LDR_DATA_TABLE_ENTRY *, void *, BOOLEAN *)
Definition: loader.c:59
NTSTATUS LdrSetDefaultDllDirectories(ULONG flags)
Definition: loader.c:3790
NTSTATUS LdrLoadDll(LPCWSTR path_name, DWORD flags, const UNICODE_STRING *libname, HMODULE *hModule)
Definition: loader.c:2774
PIMAGE_SECTION_HEADER RtlImageRvaToSection(const IMAGE_NT_HEADERS *nt, HMODULE module, DWORD rva)
Definition: loader.c:3632
void * LdrResolveDelayLoadedAPI(void *base, const IMAGE_DELAYLOAD_DESCRIPTOR *desc, PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook, PDELAYLOAD_FAILURE_SYSTEM_ROUTINE syshook, IMAGE_THUNK_DATA *addr, ULONG flags)
Definition: loader.c:3088
static NTSTATUS find_dll_file(const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext, UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info, struct file_id *id)
Definition: loader.c:2543
static NTSTATUS alloc_thread_tls(void)
Definition: loader.c:1215
BOOL DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
Definition: loader.c:3918
NTSTATUS LdrUnloadDll(HMODULE hModule)
Definition: loader.c:3354
static RTL_BITMAP tls_expansion_bitmap
Definition: loader.c:161
static NTSTATUS fixup_imports(WINE_MODREF *wm, LPCWSTR load_path)
Definition: loader.c:1103
static WINE_MODREF * alloc_module(HMODULE hModule, const UNICODE_STRING *nt_name, BOOL builtin)
Definition: loader.c:1159
static RTL_BITMAP tls_bitmap
Definition: loader.c:160
static CRITICAL_SECTION dlldir_section
Definition: loader.c:141
NTSTATUS LdrEnumerateLoadedModules(void *unknown, LDRENUMPROC callback, void *context)
Definition: loader.c:1582
static int free_lib_count
Definition: loader.c:79
static WINE_MODREF * find_basename_module(LPCWSTR name)
Definition: loader.c:486
static NTSTATUS load_dll(const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:2615
static NTSTATUS load_so_dll(LPCWSTR load_path, const UNICODE_STRING *nt_name, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:2310
NTSTATUS LdrGetDllPath(PCWSTR module, ULONG flags, PWSTR *path, PWSTR *unknown)
Definition: loader.c:3807
static NTSTATUS find_actctx_dll(LPCWSTR libname, LPWSTR *fullname)
Definition: loader.c:2387
static NTSTATUS open_dll_file(UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info, struct file_id *id)
Definition: loader.c:2212
static IMAGE_TLS_DIRECTORY * tls_dirs
Definition: loader.c:129
const WCHAR system_dir[]
Definition: loader.c:68
NTSTATUS LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, ULONG buf_size, ULONG *req_size)
Definition: loader.c:2927
NTSTATUS LdrGetDllHandle(LPCWSTR load_path, ULONG flags, const UNICODE_STRING *name, HMODULE *base)
Definition: loader.c:2804
static BOOL process_detaching
Definition: loader.c:78
static ULONG path_safe_mode
Definition: loader.c:80
LIST_ENTRY tls_links
Definition: loader.c:130
struct _RTL_UNLOAD_EVENT_TRACE * PRTL_UNLOAD_EVENT_TRACE
IMAGE_BASE_RELOCATION * LdrProcessRelocationBlock(void *page, UINT count, USHORT *relocs, INT_PTR delta)
Definition: loader.c:2865
NTSTATUS LdrSetDllDirectory(const UNICODE_STRING *dir)
Definition: loader.c:3709
static NTSTATUS process_attach(WINE_MODREF *wm, LPVOID lpReserved)
Definition: loader.c:1377
static void MODULE_DecRefCount(WINE_MODREF *wm)
Definition: loader.c:3322
NTSTATUS LdrAddDllDirectory(const UNICODE_STRING *dir, void **cookie)
Definition: loader.c:3728
static NTSTATUS build_builtin_module(const WCHAR *load_path, const UNICODE_STRING *nt_name, void *module, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:1957
static NTSTATUS query_dword_option(HANDLE hkey, LPCWSTR name, ULONG *value)
Definition: loader.c:2977
DWORD(* DLLENTRYPROC)(HMODULE, DWORD, LPVOID)
Definition: loader.c:58
static BOOL import_dll(HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path, WINE_MODREF **pwm)
Definition: loader.c:749
NTSTATUS LdrRegisterDllNotification(ULONG flags, PLDR_DLL_NOTIFICATION_FUNCTION callback, void *context, void **cookie)
Definition: loader.c:1610
NTSTATUS LdrRemoveDllDirectory(void *cookie)
Definition: loader.c:3773
NTSTATUS LdrUnregisterDllNotification(void *cookie)
Definition: loader.c:1639
BOOLEAN RtlDllShutdownInProgress(void)
Definition: loader.c:3080
static NTSTATUS perform_relocations(void *module, IMAGE_NT_HEADERS *nt, SIZE_T len)
Definition: loader.c:1784
BOOL is_wow64
Definition: loader.c:72
static WINE_MODREF * last_failed_modref
Definition: loader.c:165
PVOID RtlImageDirectoryEntryToData(HMODULE module, BOOL image, WORD dir, ULONG *size)
Definition: loader.c:3596
static BOOL is_valid_binary(HMODULE module, const SECTION_IMAGE_INFORMATION *info)
Definition: loader.c:2023
void LdrShutdownThread(void)
Definition: loader.c:3198
static NTSTATUS load_native_dll(LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:2299
static const BOOL is_win64
Definition: loader.c:71
static RTL_CRITICAL_SECTION peb_lock
Definition: loader.c:150
static RTL_CRITICAL_SECTION_DEBUG critsect_debug
Definition: loader.c:133
static BOOL is_dll_native_subsystem(LDR_DATA_TABLE_ENTRY *mod, const IMAGE_NT_HEADERS *nt, LPCWSTR filename)
Definition: loader.c:923
static void set_security_cookie(void *module, SIZE_T len)
Definition: loader.c:1742
struct _wine_modref WINE_MODREF
static void * get_rva(HMODULE module, DWORD va)
Definition: loader.c:176
void RtlReleasePath(PWSTR path)
Definition: loader.c:3909
NTSTATUS LdrUnlockLoaderLock(ULONG flags, ULONG_PTR magic)
Definition: loader.c:1693
static void MODULE_FlushModrefs(void)
Definition: loader.c:3291
static ULONG dll_safe_mode
Definition: loader.c:81
static NTSTATUS build_module(LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:1865
static CRITICAL_SECTION_DEBUG dlldir_critsect_debug
Definition: loader.c:142
PVOID RtlImageRvaToVa(const IMAGE_NT_HEADERS *nt, HMODULE module, DWORD rva, IMAGE_SECTION_HEADER **section)
Definition: loader.c:3652
static NTSTATUS query_string_option(HANDLE hkey, LPCWSTR name, ULONG type, void *data, ULONG in_size, ULONG *out_size)
Definition: loader.c:3000
static BOOL imports_fixup_done
Definition: loader.c:77
static FARPROC find_named_export(HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, const char *name, int hint, LPCWSTR load_path)
Definition: loader.c:713
NTSTATUS LdrGetDllDirectory(UNICODE_STRING *dir)
Definition: loader.c:3689
static RTL_CRITICAL_SECTION loader_section
Definition: loader.c:132
static PEB_LDR_DATA ldr
Definition: loader.c:159
static void attach_implicitly_loaded_dlls(LPVOID reserved)
Definition: loader.c:1447
static void call_tls_callbacks(HMODULE module, UINT reason)
Definition: loader.c:1258
void RtlGetUnloadEventTraceEx(ULONG **size, ULONG **count, void **trace)
Definition: loader.c:231
PVOID RtlPcToFileHeader(PVOID pc, PVOID *address)
Definition: loader.c:3673
static NTSTATUS search_dll_file(LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info, struct file_id *id)
Definition: loader.c:2487
void RtlExitUserProcess(DWORD status)
Definition: loader.c:3185
const WCHAR syswow64_dir[]
Definition: loader.c:69
void LdrShutdownProcess(void)
Definition: loader.c:3168
NTSTATUS LdrFindEntryForAddress(const void *addr, PLDR_DATA_TABLE_ENTRY *pmod)
Definition: loader.c:1560
static const WCHAR system_path[]
Definition: loader.c:75
static UINT tls_module_count
Definition: loader.c:128
NTSTATUS RtlSetSearchPathMode(ULONG flags)
Definition: loader.c:3846
static BOOL call_dll_entry_point(DLLENTRYPROC proc, void *module, UINT reason, void *reserved)
Definition: loader.c:284
static WINE_MODREF ** grow_module_deps(WINE_MODREF *wm, int count)
Definition: loader.c:573
static void thread_attach(void)
Definition: loader.c:1514
static void module_push_unload_trace(const LDR_DATA_TABLE_ENTRY *ldr)
Definition: loader.c:203
static void restart_winevdm(RTL_USER_PROCESS_PARAMETERS *params)
Definition: loader.c:3928
NTSTATUS __wine_set_unix_funcs(int version, const struct unix_funcs *funcs)
Definition: loader.c:4097
NTSTATUS RtlGetExePath(PCWSTR name, PWSTR *path)
Definition: loader.c:3878
#define DEFAULT_SECURITY_COOKIE_32
Definition: loader.c:51
static NTSTATUS load_builtin_dll(LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module_ptr, DWORD flags, WINE_MODREF **pwm)
Definition: loader.c:2344
static void call_ldr_notifications(ULONG reason, LDR_DATA_TABLE_ENTRY *module)
Definition: loader.c:433
NTSTATUS __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
Definition: loader.c:2752
void(* pBaseThreadInitThunk)(DWORD, LPTHREAD_START_ROUTINE, void *)
Definition: loader.c:61
static NTSTATUS MODULE_InitDLL(WINE_MODREF *wm, UINT reason, LPVOID lpReserved)
Definition: loader.c:1292
PIMAGE_NT_HEADERS RtlImageNtHeader(HMODULE hModule)
Definition: loader.c:3395
static UNICODE_STRING dll_directory
Definition: loader.c:82
static const WCHAR * get_module_path_end(const WCHAR *module)
Definition: loader.c:2058
NTSTATUS LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, ULONG ord, PVOID *address)
Definition: loader.c:1707
static void process_detach(void)
Definition: loader.c:1476
static const char *const reason_names[]
Definition: loader.c:102
static void free_tls_slot(LDR_DATA_TABLE_ENTRY *mod)
Definition: loader.c:1042
static RTL_CRITICAL_SECTION_DEBUG peb_critsect_debug
Definition: loader.c:151
const WCHAR windows_dir[]
Definition: loader.c:66
static NTSTATUS fixup_imports_ilonly(WINE_MODREF *wm, LPCWSTR load_path, void **entry)
Definition: loader.c:1058
#define RT_MANIFEST
Definition: loader.c:55
static DWORD default_search_flags
Definition: loader.c:83
static WINE_MODREF * current_modref
Definition: loader.c:164
NTSTATUS LdrLockLoaderLock(ULONG flags, ULONG *result, ULONG_PTR *magic)
Definition: loader.c:1661
struct _RTL_UNLOAD_EVENT_TRACE RTL_UNLOAD_EVENT_TRACE
static RTL_UNLOAD_EVENT_TRACE * unload_trace_ptr
Definition: loader.c:200
#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID
Definition: loader.c:56
static unsigned int unload_trace_seq
Definition: loader.c:201
static NTSTATUS process_init(void)
Definition: loader.c:3951
static RTL_UNLOAD_EVENT_TRACE unload_traces[64]
Definition: loader.c:199
static struct list dll_dir_list
Definition: loader.c:91
#define DEFAULT_SECURITY_COOKIE_16
Definition: loader.c:52
RTL_UNLOAD_EVENT_TRACE * RtlGetUnloadEventTrace(void)
Definition: loader.c:223
void LdrInitializeThunk(CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR unknown3, ULONG_PTR unknown4)
Definition: loader.c:3448
static NTSTATUS create_module_activation_context(LDR_DATA_TABLE_ENTRY *module)
Definition: loader.c:893
static struct list ldr_notifications
Definition: loader.c:100
static NTSTATUS get_dll_load_path_search_flags(LPCWSTR module, DWORD flags, WCHAR **path)
Definition: loader.c:2147
#define RTL_UNLOAD_EVENT_TRACE_NUMBER
Definition: loader.c:187
static SHORT alloc_tls_slot(LDR_DATA_TABLE_ENTRY *mod)
Definition: loader.c:958