-
Notifications
You must be signed in to change notification settings - Fork 9
/
d3d9-helper.patch
1029 lines (977 loc) · 37.7 KB
/
d3d9-helper.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
From bb6e2b7f609fda55b58dfe05a74f16d69ab65bc8 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <[email protected]>
Date: Mon, 18 Feb 2019 10:00:15 -0500
Subject: [PATCH] D3D9 Helper
Signed-off-by: Nick Sarnie <[email protected]>
---
dlls/ntdll/loader.c | 205 ++++++++++++++++++++----
dlls/ntdll/loadorder.c | 298 ++++++++++++++++++++++++++---------
dlls/ntdll/ntdll_misc.h | 1 +
programs/winecfg/Makefile.in | 1 +
programs/winecfg/main.c | 12 +-
programs/winecfg/resource.h | 5 +
programs/winecfg/staging.c | 93 +++++++++++
programs/winecfg/winecfg.h | 1 +
programs/winecfg/winecfg.rc | 10 ++
9 files changed, 522 insertions(+), 104 deletions(-)
create mode 100644 programs/winecfg/staging.c
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index a47dfe0aa1..fe3edb569c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -110,6 +110,7 @@ struct builtin_load_info
{
const WCHAR *load_path;
const WCHAR *filename;
+ const WCHAR *fakemodule;
NTSTATUS status;
WINE_MODREF *wm;
};
@@ -134,7 +135,8 @@ static WINE_MODREF *cached_modref;
static WINE_MODREF *current_modref;
static WINE_MODREF *last_failed_modref;
-static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
+static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, LPCWSTR fakemodule,
+ DWORD flags, WINE_MODREF** pwm );
static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved );
static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
@@ -510,7 +512,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
if (!(wm = find_basename_module( mod_name )))
{
TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
- if (load_dll( load_path, mod_name, 0, &wm ) == STATUS_SUCCESS &&
+ if (load_dll( load_path, mod_name, NULL, 0, &wm ) == STATUS_SUCCESS &&
!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
{
if (!imports_fixup_done && current_modref)
@@ -681,7 +683,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP
{
ascii_to_unicode( buffer, name, len );
buffer[len] = 0;
- status = load_dll( load_path, buffer, 0, &wmImp );
+ status = load_dll( load_path, buffer, NULL, 0, &wmImp );
}
else /* need to allocate a larger buffer */
{
@@ -689,7 +691,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP
if (!ptr) return FALSE;
ascii_to_unicode( ptr, name, len );
ptr[len] = 0;
- status = load_dll( load_path, ptr, 0, &wmImp );
+ status = load_dll( load_path, ptr, NULL, 0, &wmImp );
RtlFreeHeap( GetProcessHeap(), 0, ptr );
}
@@ -975,7 +977,7 @@ static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void *
prev = current_modref;
current_modref = wm;
- if (!(status = load_dll( load_path, mscoreeW, 0, &imp ))) wm->deps[0] = imp;
+ if (!(status = load_dll( load_path, mscoreeW, NULL, 0, &imp ))) wm->deps[0] = imp;
current_modref = prev;
if (status)
{
@@ -1063,7 +1065,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
* Allocate a WINE_MODREF structure and add it to the process list
* The loader_section must be locked while calling this function.
*/
-static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
+static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename, LPCWSTR fakemodule )
{
WINE_MODREF *wm;
const WCHAR *p;
@@ -1077,7 +1079,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
wm->ldr.TlsIndex = -1;
wm->ldr.LoadCount = 1;
- RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
+ RtlCreateUnicodeString( &wm->ldr.FullDllName, fakemodule ? fakemodule : filename );
if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
else p = wm->ldr.FullDllName.Buffer;
RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
@@ -1744,7 +1746,7 @@ static void load_builtin_callback( void *module, const char *filename )
return;
}
- wm = alloc_module( module, fullname );
+ wm = alloc_module( module, fullname, builtin_load_info->fakemodule );
RtlFreeHeap( GetProcessHeap(), 0, fullname );
if (!wm)
{
@@ -2007,8 +2009,8 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info )
/******************************************************************************
* load_native_dll (internal)
*/
-static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
- DWORD flags, WINE_MODREF** pwm, struct stat *st )
+static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, LPCWSTR fakemodule,
+ HANDLE file, DWORD flags, WINE_MODREF** pwm, struct stat *st )
{
void *module;
HANDLE mapping;
@@ -2051,7 +2053,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
/* create the MODREF */
- if (!(wm = alloc_module( module, name )))
+ if (!(wm = alloc_module( module, name, fakemodule )))
{
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
return STATUS_NO_MEMORY;
@@ -2119,8 +2121,8 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
/***********************************************************************
* load_builtin_dll
*/
-static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
- DWORD flags, WINE_MODREF** pwm )
+static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, LPCWSTR fakemodule,
+ HANDLE file, DWORD flags, WINE_MODREF** pwm )
{
char error[256], dllname[MAX_PATH];
const WCHAR *name, *p;
@@ -2140,6 +2142,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
*/
info.load_path = load_path;
info.filename = NULL;
+ info.fakemodule = fakemodule;
info.status = STATUS_SUCCESS;
info.wm = NULL;
@@ -2338,6 +2341,108 @@ done:
return status;
}
+#if defined(__i386__)
+#define CURRENT_ARCH IMAGE_FILE_MACHINE_I386
+#elif defined(__x86_64__)
+#define CURRENT_ARCH IMAGE_FILE_MACHINE_AMD64
+#elif defined(__arm__)
+#define CURRENT_ARCH IMAGE_FILE_MACHINE_ARM
+#elif defined(__aarch64__)
+#define CURRENT_ARCH IMAGE_FILE_MACHINE_ARM64
+#endif
+
+/***********************************************************************
+ * get_machine_type (internal)
+ *
+ * Determines the machine type of a module. Based on the code in
+ * dlls/kernel32/module.c.
+ */
+static WORD get_machine_type( HANDLE hfile )
+{
+ union
+ {
+ struct
+ {
+ unsigned char magic[4];
+ unsigned char class;
+ unsigned char data;
+ unsigned char version;
+ unsigned char ignored[9];
+ unsigned short type;
+ unsigned short machine;
+ } elf;
+ struct
+ {
+ unsigned int magic;
+ unsigned int cputype;
+ unsigned int cpusubtype;
+ unsigned int filetype;
+ } macho;
+ IMAGE_DOS_HEADER mz;
+ } header;
+
+ IO_STATUS_BLOCK io;
+ LARGE_INTEGER offset;
+
+ /* Seek to the start of the file and read the header information. */
+ offset.QuadPart = 0;
+ if (NtReadFile( hfile, 0, NULL, 0, &io, &header, sizeof(header), &offset, NULL )) return 0;
+ if (io.Information < sizeof(header)) return 0;
+
+ if (!memcmp( header.elf.magic, "\177ELF", 4 ))
+ {
+#ifdef WORDS_BIGENDIAN
+ if (header.elf.data == 1)
+#else
+ if (header.elf.data == 2)
+#endif
+ {
+ header.elf.machine = RtlUshortByteSwap( header.elf.machine );
+ }
+
+ switch(header.elf.machine)
+ {
+ case 3: return IMAGE_FILE_MACHINE_I386;
+ case 20: return IMAGE_FILE_MACHINE_POWERPC;
+ case 40: return IMAGE_FILE_MACHINE_ARMNT;
+ case 50: return IMAGE_FILE_MACHINE_IA64;
+ case 62: return IMAGE_FILE_MACHINE_AMD64;
+ case 183: return IMAGE_FILE_MACHINE_ARM64;
+ default: return 0;
+ }
+ }
+ /* Mach-o File with Endian set to Big Endian or Little Endian */
+ else if (header.macho.magic == 0xfeedface || header.macho.magic == 0xcefaedfe ||
+ header.macho.magic == 0xfeedfacf || header.macho.magic == 0xcffaedfe)
+ {
+ if (header.macho.magic == 0xcefaedfe || header.macho.magic == 0xcffaedfe)
+ header.macho.cputype = RtlUlongByteSwap( header.macho.cputype );
+
+ switch(header.macho.cputype)
+ {
+ case 0x00000007: return IMAGE_FILE_MACHINE_I386;
+ case 0x01000007: return IMAGE_FILE_MACHINE_AMD64;
+ case 0x0000000c: return IMAGE_FILE_MACHINE_ARMNT;
+ case 0x0100000c: return IMAGE_FILE_MACHINE_ARM64;
+ case 0x00000012: return IMAGE_FILE_MACHINE_POWERPC;
+ default: return 0;
+ }
+ }
+ /* Not ELF, try DOS */
+ else if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
+ {
+ IMAGE_NT_HEADERS32 ext_header;
+
+ offset.QuadPart = header.mz.e_lfanew;
+ if (NtReadFile( hfile, 0, NULL, 0, &io, &ext_header, sizeof(ext_header), &offset, NULL )) return 0;
+ if (io.Information < sizeof(ext_header)) return 0;
+
+ if (!memcmp( &ext_header.Signature, "PE\0\0", 4 ))
+ return ext_header.FileHeader.Machine;
+ }
+
+ return 0;
+}
/***********************************************************************
* open_dll_file
@@ -2384,7 +2489,7 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct
*/
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
WCHAR *filename, ULONG *size, WINE_MODREF **pwm,
- HANDLE *handle, struct stat *st )
+ HANDLE *handle, struct stat *st, BOOL check_arch )
{
UNICODE_STRING nt_name;
WCHAR *file_part, *ext, *dllname;
@@ -2429,20 +2534,41 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
{
- /* we need to search for it */
- len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part );
- if (len)
+ while (load_path)
{
+ /* we need to search for it */
+ len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part );
+ if (!len) break;
+
if (len >= *size) goto overflow;
if ((*pwm = find_fullname_module( filename ))) goto found;
+ if (!handle) goto next;
if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL ))
{
RtlFreeHeap( GetProcessHeap(), 0, dllname );
return STATUS_NO_MEMORY;
}
+
*handle = open_dll_file( &nt_name, pwm, st );
- goto found;
+
+ #ifdef CURRENT_ARCH
+ if (*handle && check_arch)
+ {
+ WORD machine_type = get_machine_type( *handle );
+ if (machine_type && machine_type != CURRENT_ARCH)
+ {
+ FIXME( "skipping %s because of wrong architecture\n", debugstr_w(filename) );
+ NtClose( *handle );
+ *handle = 0;
+ }
+ }
+ #endif
+ if (*handle) goto found;
+
+ next:
+ load_path = strchrW(load_path, ';');
+ if (load_path) load_path++;
}
/* not found */
@@ -2490,8 +2616,10 @@ overflow:
* Load a PE style module according to the load order.
* The loader_section must be locked while calling this function.
*/
-static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
+static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, LPCWSTR fakemodule,
+ DWORD flags, WINE_MODREF** pwm )
{
+ BOOL data = flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE);
enum loadorder loadorder;
WCHAR buffer[64];
WCHAR *filename;
@@ -2508,7 +2636,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
size = sizeof(buffer);
for (;;)
{
- nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle, &st );
+ nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle, &st, !data );
if (nts == STATUS_SUCCESS) break;
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
if (nts != STATUS_BUFFER_TOO_SMALL) return nts;
@@ -2528,6 +2656,25 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
}
main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
+
+ /* handle dll redirection */
+ if (!fakemodule)
+ {
+ BYTE buffer2[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
+ WCHAR *redirect = get_redirect( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL,
+ filename, buffer2, sizeof(buffer2) );
+ if (redirect)
+ {
+ FIXME("Loader redirect from %s to %s\n", debugstr_w(libname), debugstr_w(redirect));
+
+ nts = load_dll( load_path, redirect, filename, flags, pwm );
+
+ if (handle) NtClose( handle );
+ if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
+ return nts;
+ }
+ }
+
loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename );
if (handle && is_fake_dll( handle ))
@@ -2550,22 +2697,22 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
if (!handle) nts = STATUS_DLL_NOT_FOUND;
else
{
- nts = load_native_dll( load_path, filename, handle, flags, pwm, &st );
+ nts = load_native_dll( load_path, filename, fakemodule, handle, flags, pwm, &st );
if (nts == STATUS_INVALID_IMAGE_NOT_MZ)
/* not in PE format, maybe it's a builtin */
- nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
+ nts = load_builtin_dll( load_path, filename, fakemodule, handle, flags, pwm );
}
if (nts == STATUS_DLL_NOT_FOUND && loadorder == LO_NATIVE_BUILTIN)
- nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
+ nts = load_builtin_dll( load_path, filename, fakemodule, 0, flags, pwm );
break;
case LO_BUILTIN:
case LO_BUILTIN_NATIVE:
case LO_DEFAULT: /* default is builtin,native */
- nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
+ nts = load_builtin_dll( load_path, filename, fakemodule, handle, flags, pwm );
if (!handle) break; /* nothing else we can try */
/* file is not a builtin library, try without using the specified file */
if (nts != STATUS_SUCCESS)
- nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
+ nts = load_builtin_dll( load_path, filename, fakemodule, 0, flags, pwm );
if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
(MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
{
@@ -2575,7 +2722,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
nts = STATUS_DLL_NOT_FOUND;
}
if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN)
- nts = load_native_dll( load_path, filename, handle, flags, pwm, &st );
+ nts = load_native_dll( load_path, filename, fakemodule, handle, flags, pwm, &st );
break;
}
@@ -2608,7 +2755,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags,
RtlEnterCriticalSection( &loader_section );
if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
- nts = load_dll( path_name, libname->Buffer, flags, &wm );
+ nts = load_dll( path_name, libname->Buffer, NULL, flags, &wm );
if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
{
@@ -2647,7 +2794,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
size = sizeof(buffer);
for (;;)
{
- status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, &handle, &st );
+ status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, &handle, &st, TRUE );
if (handle) NtClose( handle );
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
if (status != STATUS_BUFFER_TOO_SMALL) break;
@@ -3582,7 +3729,7 @@ void __wine_process_init(void)
/* setup the load callback and create ntdll modref */
wine_dll_set_callback( load_builtin_callback );
- if ((status = load_builtin_dll( NULL, kernel32W, 0, 0, &wm )) != STATUS_SUCCESS)
+ if ((status = load_builtin_dll( NULL, kernel32W, NULL, 0, 0, &wm )) != STATUS_SUCCESS)
{
MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
exit(1);
diff --git a/dlls/ntdll/loadorder.c b/dlls/ntdll/loadorder.c
index c6c0245931..c247a50380 100644
--- a/dlls/ntdll/loadorder.c
+++ b/dlls/ntdll/loadorder.c
@@ -290,102 +290,165 @@ static inline enum loadorder get_env_load_order( const WCHAR *module )
/***************************************************************************
- * get_standard_key
+ * open_user_reg_key
+ *
+ * Return a handle to a registry key under HKCU.
+ */
+static HANDLE open_user_reg_key(const WCHAR *key_name)
+{
+ HANDLE hkey, root;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+
+ RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = root;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &nameW, key_name );
+
+ if (NtOpenKey( &hkey, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr )) hkey = 0;
+ NtClose( root );
+
+ return hkey;
+}
+
+
+/***************************************************************************
+ * open_app_reg_key
+ *
+ * Return a handle to an app-specific registry key.
+ */
+static HANDLE open_app_reg_key( const WCHAR *sub_key, const WCHAR *app_name )
+{
+ static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
+ 'A','p','p','D','e','f','a','u','l','t','s','\\',0};
+ WCHAR *str;
+ HANDLE hkey;
+
+ str = RtlAllocateHeap( GetProcessHeap(), 0,
+ sizeof(AppDefaultsW) +
+ strlenW(sub_key) * sizeof(WCHAR) +
+ strlenW(app_name) * sizeof(WCHAR) );
+ if (!str) return 0;
+ strcpyW( str, AppDefaultsW );
+ strcatW( str, app_name );
+ strcatW( str, sub_key );
+
+ hkey = open_user_reg_key( str );
+ RtlFreeHeap( GetProcessHeap(), 0, str );
+ return hkey;
+}
+
+
+/***************************************************************************
+ * get_override_standard_key
*
* Return a handle to the standard DllOverrides registry section.
*/
-static HANDLE get_standard_key(void)
+static HANDLE get_override_standard_key(void)
{
static const WCHAR DllOverridesW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
'D','l','l','O','v','e','r','r','i','d','e','s',0};
static HANDLE std_key = (HANDLE)-1;
if (std_key == (HANDLE)-1)
- {
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING nameW;
- HANDLE root;
-
- RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
- attr.Length = sizeof(attr);
- attr.RootDirectory = root;
- attr.ObjectName = &nameW;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &nameW, DllOverridesW );
-
- /* @@ Wine registry key: HKCU\Software\Wine\DllOverrides */
- if (NtOpenKey( &std_key, KEY_ALL_ACCESS, &attr )) std_key = 0;
- NtClose( root );
- }
+ std_key = open_user_reg_key( DllOverridesW );
+
return std_key;
}
/***************************************************************************
- * get_app_key
+ * get_override_app_key
*
* Get the registry key for the app-specific DllOverrides list.
*/
-static HANDLE get_app_key( const WCHAR *app_name )
+static HANDLE get_override_app_key( const WCHAR *app_name )
{
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING nameW;
- HANDLE root;
- WCHAR *str;
- static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
- 'A','p','p','D','e','f','a','u','l','t','s','\\',0};
static const WCHAR DllOverridesW[] = {'\\','D','l','l','O','v','e','r','r','i','d','e','s',0};
static HANDLE app_key = (HANDLE)-1;
- if (app_key != (HANDLE)-1) return app_key;
+ if (app_key == (HANDLE)-1)
+ app_key = open_app_reg_key( DllOverridesW, app_name );
- str = RtlAllocateHeap( GetProcessHeap(), 0,
- sizeof(AppDefaultsW) + sizeof(DllOverridesW) +
- strlenW(app_name) * sizeof(WCHAR) );
- if (!str) return 0;
- strcpyW( str, AppDefaultsW );
- strcatW( str, app_name );
- strcatW( str, DllOverridesW );
+ return app_key;
+}
- RtlOpenCurrentUser( KEY_ALL_ACCESS, &root );
- attr.Length = sizeof(attr);
- attr.RootDirectory = root;
- attr.ObjectName = &nameW;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &nameW, str );
- /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DllOverrides */
- if (NtOpenKey( &app_key, KEY_ALL_ACCESS, &attr )) app_key = 0;
- NtClose( root );
- RtlFreeHeap( GetProcessHeap(), 0, str );
+/***************************************************************************
+ * get_redirect_standard_key
+ *
+ * Return a handle to the standard DllRedirects registry section.
+ */
+static HANDLE get_redirect_standard_key(void)
+{
+ static const WCHAR DllRedirectsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
+ 'D','l','l','R','e','d','i','r','e','c','t','s',0};
+ static HANDLE std_key = (HANDLE)-1;
+
+ if (std_key == (HANDLE)-1)
+ std_key = open_user_reg_key( DllRedirectsW );
+
+ return std_key;
+}
+
+
+/***************************************************************************
+ * get_redirect_app_key
+ *
+ * Get the registry key for the app-specific DllRedirects list.
+ */
+static HANDLE get_redirect_app_key( const WCHAR *app_name )
+{
+ static const WCHAR DllRedirectsW[] = {'\\','D','l','l','R','e','d','i','r','e','c','t','s',0};
+ static HANDLE app_key = (HANDLE)-1;
+
+ if (app_key == (HANDLE)-1)
+ app_key = open_app_reg_key( DllRedirectsW, app_name );
+
return app_key;
}
/***************************************************************************
- * get_registry_value
+ * get_registry_string
*
- * Load the registry loadorder value for a given module.
+ * Load a registry string for a given module.
*/
-static enum loadorder get_registry_value( HANDLE hkey, const WCHAR *module )
+static WCHAR* get_registry_string( HANDLE hkey, const WCHAR *module, BYTE *buffer,
+ ULONG size )
{
UNICODE_STRING valueW;
- char buffer[80];
DWORD count;
+ WCHAR *ret = NULL;
RtlInitUnicodeString( &valueW, module );
-
- if (!NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation,
- buffer, sizeof(buffer), &count ))
+ if (size >= sizeof(WCHAR) &&
+ !NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation,
+ buffer, size - sizeof(WCHAR), &count ))
{
- WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)buffer)->Data;
- return parse_load_order( str );
+ KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buffer;
+ ret = (WCHAR *)info->Data;
+ ret[info->DataLength / sizeof(WCHAR)] = 0;
}
- return LO_INVALID;
+
+ return ret;
+}
+
+
+/***************************************************************************
+ * get_registry_load_order
+ *
+ * Load the registry loadorder value for a given module.
+ */
+static enum loadorder get_registry_load_order( HANDLE hkey, const WCHAR *module )
+{
+ BYTE buffer[81];
+ WCHAR *str = get_registry_string( hkey, module, buffer, sizeof(buffer) );
+ return str ? parse_load_order( str ) : LO_INVALID;
}
@@ -407,13 +470,13 @@ static enum loadorder get_load_order_value( HANDLE std_key, HANDLE app_key, cons
return ret;
}
- if (app_key && ((ret = get_registry_value( app_key, module )) != LO_INVALID))
+ if (app_key && ((ret = get_registry_load_order( app_key, module )) != LO_INVALID))
{
TRACE( "got app defaults %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
return ret;
}
- if (std_key && ((ret = get_registry_value( std_key, module )) != LO_INVALID))
+ if (std_key && ((ret = get_registry_load_order( std_key, module )) != LO_INVALID))
{
TRACE( "got standard key %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
return ret;
@@ -422,25 +485,43 @@ static enum loadorder get_load_order_value( HANDLE std_key, HANDLE app_key, cons
return ret;
}
+ /***************************************************************************
+ * get_redirect_value
+ *
+ * Get the redirect value for the exact specified module string, looking in:
+ * 1. The per-application DllRedirects key
+ * 2. The standard DllRedirects key
+ */
+static WCHAR* get_redirect_value( HANDLE std_key, HANDLE app_key, const WCHAR *module,
+ BYTE *buffer, ULONG size )
+{
+ WCHAR *ret = NULL;
+
+ if (app_key && (ret = get_registry_string( app_key, module, buffer, size )))
+ {
+ TRACE( "got app defaults %s for %s\n", debugstr_w(ret), debugstr_w(module) );
+ return ret;
+ }
+
+ if (std_key && (ret = get_registry_string( std_key, module, buffer, size )))
+ {
+ TRACE( "got standard key %s for %s\n", debugstr_w(ret), debugstr_w(module) );
+ return ret;
+ }
+
+ return ret;
+}
/***************************************************************************
- * get_load_order (internal)
+ * get_module_basename (internal)
*
* Return the loadorder of a module.
* The system directory and '.dll' extension is stripped from the path.
*/
-enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
+static WCHAR* get_module_basename( const WCHAR *path, WCHAR **basename )
{
- enum loadorder ret = LO_INVALID;
- HANDLE std_key, app_key = 0;
- WCHAR *module, *basename;
int len;
-
- if (!init_done) init_load_order();
- std_key = get_standard_key();
- if (app_name) app_key = get_app_key( app_name );
-
- TRACE("looking for %s\n", debugstr_w(path));
+ WCHAR *module;
/* Strip path information if the module resides in the system directory
*/
@@ -451,12 +532,36 @@ enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
if (!strchrW( p, '\\' ) && !strchrW( p, '/' )) path = p;
}
- if (!(len = strlenW(path))) return ret;
- if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return ret;
+ if (!(len = strlenW(path))) return NULL;
+ if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return NULL;
strcpyW( module+1, path ); /* reserve module[0] for the wildcard char */
- basename = (WCHAR *)get_basename( module+1 );
+ *basename = (WCHAR *)get_basename( module+1 );
if (len >= 4) remove_dll_ext( module + 1 + len - 4 );
+ return module;
+}
+
+
+/***************************************************************************
+ * get_load_order (internal)
+ *
+ * Return the loadorder of a module.
+ * The system directory and '.dll' extension is stripped from the path.
+ */
+enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
+{
+ enum loadorder ret = LO_INVALID;
+ HANDLE std_key, app_key = 0;
+ WCHAR *module, *basename;
+
+ if (!init_done) init_load_order();
+ std_key = get_override_standard_key();
+ if (app_name) app_key = get_override_app_key( app_name );
+
+ TRACE("looking up loadorder for %s\n", debugstr_w(path));
+
+ if (!(module = get_module_basename(path, &basename)))
+ return ret;
/* first explicit module name */
if ((ret = get_load_order_value( std_key, app_key, module+1 )) != LO_INVALID)
@@ -487,3 +592,48 @@ enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
RtlFreeHeap( GetProcessHeap(), 0, module );
return ret;
}
+
+
+/***************************************************************************
+ * get_redirect (internal)
+ *
+ * Return the redirect value of a module.
+ * The system directory and '.dll' extension is stripped from the path.
+ */
+WCHAR* get_redirect( const WCHAR *app_name, const WCHAR *path, BYTE *buffer, ULONG size )
+{
+ WCHAR *ret = NULL;
+ HANDLE std_key, app_key = 0;
+ WCHAR *module, *basename;
+
+ std_key = get_redirect_standard_key();
+ if (app_name) app_key = get_redirect_app_key( app_name );
+
+ TRACE("looking up redirection for %s\n", debugstr_w(path));
+
+ if (!(module = get_module_basename(path, &basename)))
+ return ret;
+
+ /* first explicit module name */
+ if ((ret = get_redirect_value( std_key, app_key, module+1, buffer, size )))
+ goto done;
+
+ /* then module basename preceded by '*' */
+ basename[-1] = '*';
+ if ((ret = get_redirect_value( std_key, app_key, basename-1, buffer, size )))
+ goto done;
+
+ /* then module basename without '*' (only if explicit path) */
+ /*
+ if (basename != module+1 && (ret = get_redirect_value( std_key, app_key, basename, buffer, size )))
+ goto done;
+ */
+
+ /* and last the hard-coded default */
+ ret = NULL;
+ TRACE( "no redirection found for %s\n", debugstr_w(path) );
+
+ done:
+ RtlFreeHeap( GetProcessHeap(), 0, module );
+ return ret;
+}
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 1630978f0a..b24b39a8b3 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -217,6 +217,7 @@ enum loadorder
};
extern enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path ) DECLSPEC_HIDDEN;
+extern WCHAR* get_redirect( const WCHAR *app_name, const WCHAR *path, BYTE *buffer, ULONG size ) DECLSPEC_HIDDEN;
struct debug_info
{
diff --git a/programs/winecfg/Makefile.in b/programs/winecfg/Makefile.in
index 4e66e04e31..1cf70310d5 100644
--- a/programs/winecfg/Makefile.in
+++ b/programs/winecfg/Makefile.in
@@ -11,6 +11,7 @@ C_SRCS = \
driveui.c \
libraries.c \
main.c \
+ staging.c \
theme.c \
winecfg.c \
x11drvdlg.c
diff --git a/programs/winecfg/main.c b/programs/winecfg/main.c
index b8a85fe717..de209a925c 100644
--- a/programs/winecfg/main.c
+++ b/programs/winecfg/main.c
@@ -58,7 +58,7 @@ PropSheetCallback (HWND hWnd, UINT uMsg, LPARAM lParam)
return 0;
}
-#define NUM_PROPERTY_PAGES 7
+#define NUM_PROPERTY_PAGES 8
static INT_PTR
doPropertySheet (HINSTANCE hInstance, HWND hOwner)
@@ -139,6 +139,16 @@ doPropertySheet (HINSTANCE hInstance, HWND hOwner)
psp[pg].lParam = 0;
pg++;
+ psp[pg].dwSize = sizeof (PROPSHEETPAGEW);
+ psp[pg].dwFlags = PSP_USETITLE;
+ psp[pg].hInstance = hInstance;
+ psp[pg].u.pszTemplate = MAKEINTRESOURCEW (IDD_STAGING);
+ psp[pg].u2.pszIcon = NULL;
+ psp[pg].pfnDlgProc = StagingDlgProc;
+ psp[pg].pszTitle = load_string (IDS_TAB_STAGING);
+ psp[pg].lParam = 0;
+ pg++;
+
/*
* Fill out the (General) PROPSHEETPAGE data structure
* for the property sheet
diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
index 2760e92c00..0584422ab5 100644
--- a/programs/winecfg/resource.h
+++ b/programs/winecfg/resource.h
@@ -45,6 +45,7 @@
#define IDS_SHELL_FOLDER 16
#define IDS_LINKS_TO 17
#define IDS_WINECFG_TITLE_APP 18 /* App specific title */
+#define IDS_TAB_STAGING 19
#define IDI_WINECFG 100
#define IDI_LOGO 102
#define IDD_ABOUTCFG 107
@@ -54,6 +55,7 @@
#define IDD_DLLCFG 111
#define IDD_DRIVECFG 112
#define IDD_DESKTOP_INTEGRATION 115
+#define IDD_STAGING 116
#define IDC_WINVER 1012
#define IDC_DESKTOP_WIDTH 1023
#define IDC_DESKTOP_HEIGHT 1024
@@ -219,3 +221,6 @@
#define IDC_ABT_TITLE_TEXT 8436
#define IDC_ABT_WEB_LINK 8437
#define IDC_ABT_LICENSE_TEXT 8438
+
+/* Staging tab */
+#define IDC_ENABLE_NATIVE_D3D9 9001
diff --git a/programs/winecfg/staging.c b/programs/winecfg/staging.c
new file mode 100644
index 0000000000..ddad850bf0
--- /dev/null
+++ b/programs/winecfg/staging.c
@@ -0,0 +1,93 @@
+/*
+ * WineCfg Staging panel
+ *
+ * Copyright 2014 Michael Müller
+ * Copyright 2015 Sebastian Lackner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+
+#include <windows.h>
+#include <wine/unicode.h>
+#include <wine/debug.h>
+
+#include "resource.h"
+#include "winecfg.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
+
+/*
+ * Gallium nine
+ */
+static BOOL nine_get(void)
+{
+ BOOL ret;
+ char *value = get_reg_key(config_key, keypath("DllRedirects"), "d3d9", NULL);
+ ret = (value && !strcmp(value, "d3d9-nine.dll"));
+ HeapFree(GetProcessHeap(), 0, value);
+ return ret;
+}
+
+static void nine_set(BOOL status)
+{
+ set_reg_key(config_key, keypath("DllRedirects"), "d3d9", status ? "d3d9-nine.dll" : NULL);
+}
+
+
+static void load_staging_settings(HWND dialog)
+{
+ CheckDlgButton(dialog, IDC_ENABLE_NATIVE_D3D9, nine_get() ? BST_CHECKED : BST_UNCHECKED);
+#if !defined(HAVE_D3D9NINE)
+ disable(IDC_ENABLE_NATIVE_D3D9);
+#endif
+}
+
+INT_PTR CALLBACK StagingDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_SETACTIVE)
+ load_staging_settings(hDlg);
+ break;
+
+ case WM_SHOWWINDOW:
+ set_window_title(hDlg);
+ break;
+
+ case WM_DESTROY:
+ break;
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) != BN_CLICKED) break;
+ switch (LOWORD(wParam))
+ {
+ case IDC_ENABLE_NATIVE_D3D9:
+ nine_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_NATIVE_D3D9) == BST_CHECKED);
+ SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/programs/winecfg/winecfg.h b/programs/winecfg/winecfg.h
index 110856a536..a94947439c 100644
--- a/programs/winecfg/winecfg.h
+++ b/programs/winecfg/winecfg.h
@@ -87,6 +87,7 @@ INT_PTR CALLBACK AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
INT_PTR CALLBACK LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK ThemeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK StagingDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
/* Drive management */
diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc
index 33f54d43b2..d12522e758 100644