00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
#include "ntos.h"
00033
#include "ldrp.h"
00034
00035 #define PAGE_SIZE_X86 (0x1000)
00036
00037
#if defined (WX86)
00038
00039 BOOLEAN (*Wx86ProcessInit)(PVOID, BOOLEAN) =
NULL;
00040 BOOLEAN (*Wx86DllMapNotify)(PVOID, BOOLEAN) =
NULL;
00041 BOOLEAN (*Wx86DllEntryPoint)(PDLL_INIT_ROUTINE, PVOID, ULONG, PCONTEXT) =
NULL;
00042 ULONG (*Wx86ProcessStartRoutine)(
VOID) =
NULL;
00043 ULONG (*Wx86ThreadStartRoutine)(PVOID) =
NULL;
00044 BOOLEAN (*Wx86KnownDllName)(PUNICODE_STRING, PUNICODE_STRING) =
NULL;
00045 BOOLEAN (*Wx86KnownNativeDll)(PUNICODE_STRING) =
NULL;
00046 BOOLEAN (*Wx86KnownRedistDll)(PUNICODE_STRING) =
NULL;
00047
00048 BOOLEAN Wx86OnTheFly=
FALSE;
00049 ULONG Wx86ProviderUnloadCount = 0;
00050
00051 WCHAR Wx86Dir[]=
L"\\sys32x86";
00052 UNICODE_STRING Wx86SystemDir={0,0,
NULL};
00053 UNICODE_STRING
NtSystemRoot={0,0,
NULL};
00054
00055
#if defined(BUILD_WOW6432)
00056
00057
00058
00059
00060
#define IsNativeMachineType(m) \
00061
((m) == IMAGE_FILE_MACHINE_ALPHA)
00062
#else
00063
#define IsNativeMachineType(m) \
00064
((m) >= USER_SHARED_DATA->ImageNumberLow && \
00065
(m) <= USER_SHARED_DATA->ImageNumberHigh)
00066
#endif
00067
00068
00069
00070
00071
00072
00073
typedef struct _Wx86Plugin {
00074 LIST_ENTRY Links;
00075 PVOID DllBase;
00076 ULONG
Count;
00077 PVOID Provider[WX86PLUGIN_MAXPROVIDER];
00078 } WX86PLUGIN, *PWX86PLUGIN;
00079
00080 LIST_ENTRY Wx86PluginList= {
00081 &Wx86PluginList,
00082 &Wx86PluginList
00083 };
00084
00085
00086
00087
typedef BOOLEAN (*WX86IDENTIFYPLUGIN)(PVOID PluginDll,
00088 WCHAR *FullFileName,
00089 BOOLEAN NativeToX86
00090 );
00091
00092
typedef BOOLEAN (*WX86THUNKEXPORT)(PVOID PluginDll,
00093 PCHAR ExportName,
00094 ULONG Ordinal,
00095 PVOID ExportAddress,
00096 PVOID *ExportThunk,
00097 BOOLEAN NativeToX86
00098 );
00099
00100 BOOLEAN
00101 DllHasExports(
00102 PVOID DllBase
00103 )
00104 {
00105 ULONG ExportSize;
00106 PIMAGE_EXPORT_DIRECTORY ExportDir;
00107
00108
00109 ExportDir =
RtlImageDirectoryEntryToData(DllBase,
00110 TRUE,
00111 IMAGE_DIRECTORY_ENTRY_EXPORT,
00112 &ExportSize
00113 );
00114
00115
return ExportDir && ExportSize &&
00116 (ExportDir->NumberOfFunctions || ExportDir->NumberOfNames);
00117
00118 }
00119
00120 BOOLEAN
00121 DllNameMatchesLdrEntry(
00122 PUNICODE_STRING BaseDllName,
00123 PUNICODE_STRING FullDllName,
00124 PLDR_DATA_TABLE_ENTRY LdrEntry,
00125 BOOLEAN ImporterX86
00126 )
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 {
00155
USHORT MachineType;
00156 BOOLEAN FullNameMatches =
FALSE;
00157 PIMAGE_NT_HEADERS NtHeaders;
00158
00159
00160
00161
00162
00163
00164
if (!
RtlEqualUnicodeString(BaseDllName, &LdrEntry->BaseDllName, TRUE)) {
00165
return FALSE;
00166 }
00167
00168
00169
if (!FullDllName->Length ||
00170 (FullDllName->Length &&
00171
RtlEqualUnicodeString(FullDllName, &LdrEntry->FullDllName, TRUE)))
00172 {
00173 FullNameMatches =
TRUE;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
if ((LdrEntry->Flags & LDRP_WX86_IGNORE_MACHINETYPE) ||
00185 (LdrEntry->Flags & LDRP_WX86_PLUGIN) ) {
00186
return FullNameMatches;
00187 }
00188
00189 NtHeaders =
RtlImageNtHeader(LdrEntry->DllBase);
00190 MachineType = NtHeaders->FileHeader.Machine;
00191
00192
if (ImporterX86) {
00193
if (MachineType == IMAGE_FILE_MACHINE_I386) {
00194
return FullNameMatches;
00195 }
00196
00197
00198
00199
00200
00201
00202
if (FullNameMatches) {
00203
return (NtHeaders->OptionalHeader.DllCharacteristics
00204 & IMAGE_DLLCHARACTERISTICS_X86_THUNK) != 0;
00205 }
00206
00207
00208
00209
00210
00211
00212
else {
00213
00214 UNICODE_STRING PathPart;
00215
00216 PathPart = LdrEntry->FullDllName;
00217 PathPart.Length = LdrEntry->FullDllName.Length - LdrEntry->BaseDllName.Length -
sizeof(WCHAR);
00218
if (!
RtlEqualUnicodeString(&PathPart, &Wx86SystemDir, TRUE)) {
00219
return FALSE;
00220 }
00221
00222 PathPart = *FullDllName;
00223 PathPart.Length = FullDllName->Length - BaseDllName->Length -
sizeof(WCHAR);
00224
if (!
RtlEqualUnicodeString(&PathPart, &LdrpKnownDllPath, TRUE)) {
00225
return FALSE;
00226 }
00227
00228
RtlCopyUnicodeString(FullDllName, &LdrEntry->FullDllName);
00229
00230
return TRUE;
00231 }
00232
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
if (IsNativeMachineType(MachineType))
00242 {
00243
return FullNameMatches;
00244 }
00245
00246
return FALSE;
00247 }
00248
00249
00250
00251 BOOLEAN
00252 SearchWx86Dll(
00253 IN PWSTR DllPath,
00254 IN PUNICODE_STRING BaseName,
00255 OUT PUNICODE_STRING FileName,
00256 OUT PWSTR *pNextDllPath
00257 )
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 {
00280 PWCHAR pwch;
00281 ULONG Length;
00282
00283
00284
00285
00286
00287
00288 Length =
BaseName->Length + 2*
sizeof(WCHAR);
00289
00290
do {
00291 pwch =
FileName->Buffer;
00292
00293
00294
00295
00296
FileName->Length = 0;
00297
00298
while (*DllPath) {
00299
if (
FileName->MaximumLength <=
FileName->Length + Length) {
00300
return FALSE;
00301 }
00302
00303
00304
if (*DllPath == (WCHAR)
';') {
00305 DllPath++;
00306
break;
00307 }
00308
00309 *pwch++ = *DllPath++;
00310
FileName->Length +=
sizeof(WCHAR);
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
if (
FileName->Length) {
00320
if (*(pwch -1) !=
L'\\') {
00321 *pwch =
L'\\';
00322
FileName->Length +=
sizeof(WCHAR);
00323 }
00324 }
00325
00326
RtlAppendUnicodeStringToString(FileName, BaseName);
00327
00328
if (
RtlDoesFileExists_U(
FileName->Buffer)) {
00329 *pNextDllPath = DllPath;
00330
return TRUE;
00331 }
00332
00333 }
while (*DllPath);
00334
00335 *pNextDllPath = DllPath;
00336
00337
return FALSE;
00338 }
00339
00340
00341
00342 BOOLEAN
00343 LdrpWx86DllMapNotify(
00344 PVOID DllBase,
00345 BOOLEAN Mapped
00346 )
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 {
00368
return Wx86DllMapNotify && (*Wx86DllMapNotify)(DllBase, Mapped);
00369 }
00370
00371
00372
00373
00374
NTSTATUS
00375 LdrpWx86MapDll(
00376 IN PWSTR DllPath OPTIONAL,
00377 IN PULONG DllCharacteristics OPTIONAL,
00378 IN BOOLEAN Wx86KnownDll,
00379 IN BOOLEAN StaticLink,
00380 OUT PUNICODE_STRING DllName,
00381 OUT PLDR_DATA_TABLE_ENTRY *pEntry,
00382 OUT ULONG_PTR *pViewSize,
00383 OUT HANDLE *pSection
00384 )
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 {
00421
NTSTATUS st;
00422
NTSTATUS stMapSection;
00423 PWCHAR pwch;
00424 PVOID ViewBase =
NULL;
00425 PTEB Teb = NtCurrentTeb();
00426 PIMAGE_NT_HEADERS NtHeaders;
00427 PVOID ArbitraryUserPointer;
00428 PLDR_DATA_TABLE_ENTRY Entry;
00429 BOOLEAN Wx86DirOverride=
FALSE;
00430 BOOLEAN Wx86DirUndone=
FALSE;
00431 BOOLEAN ContainsNoExports =
FALSE;
00432 UNICODE_STRING NameUnicode;
00433 UNICODE_STRING FreeUnicode;
00434 UNICODE_STRING FullNameUnicode;
00435 UNICODE_STRING BaseNameUnicode;
00436 UNICODE_STRING FullName;
00437 HANDLE MismatchSection;
00438 WCHAR FullNameBuffer[((DOS_MAX_PATH_LENGTH*2+20)+
sizeof(UNICODE_NULL))/2];
00439 BOOLEAN Wx86Plugin;
00440 BOOLEAN MismatchEncountered;
00441 UNICODE_STRING ThunkDllName;
00442 SECTION_IMAGE_INFORMATION SectionInfo;
00443
00444 UNICODE_STRING LocalDllName;
00445 PUNICODE_STRING pLocalDllName;
00446 PWSTR DllSearchPath;
00447 PUNICODE_STRING ForcedDllName =
NULL;
00448 PUNICODE_STRING ForcedDllPath =
NULL;
00449
00450 MismatchEncountered =
FALSE;
00451 FullName.Buffer =
NULL;
00452 Wx86Plugin =
FALSE;
00453 Entry =
NULL;
00454
00455 FullNameUnicode.Buffer = FullNameBuffer;
00456 FullNameUnicode.MaximumLength =
sizeof(FullNameBuffer);
00457 FullNameUnicode.Length = 0;
00458
00459
00460
00461
00462
00463
00464
if (!DllPath) {
00465 DllPath =
LdrpDefaultPath.Buffer;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
if (!*DllPath ||
00475
RtlDetermineDosPathNameType_U(DllName->Buffer) != RtlPathTypeRelative)
00476 {
00477 DllPath =
NULL;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 FreeUnicode.Length = 0;
00490 FreeUnicode.MaximumLength = (DOS_MAX_PATH_LENGTH*2+20) +
sizeof(UNICODE_NULL);
00491
if (DllPath) {
00492 FreeUnicode.MaximumLength += wcslen(DllPath) *
sizeof(WCHAR);
00493 }
00494
00495 FreeUnicode.Buffer =
RtlAllocateHeap(RtlProcessHeap(),
00496
MAKE_TAG( TEMP_TAG ),
00497 FreeUnicode.MaximumLength
00498 );
00499
if (!FreeUnicode.Buffer) {
00500
return STATUS_NO_MEMORY;
00501 }
00502
00503
00504 *pSection =
NULL;
00505 MismatchSection =
NULL;
00506
00507 pLocalDllName = &LocalDllName;
00508 DllSearchPath = DllPath;
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 LocalDllName.Buffer = wcsrchr(DllName->Buffer, L
'\\');
00519 LocalDllName.Buffer = LocalDllName.Buffer ? &LocalDllName.Buffer[1] : DllName->Buffer;
00520
00521 LocalDllName.Length = wcslen(LocalDllName.Buffer) *
sizeof(WCHAR);
00522 LocalDllName.MaximumLength = LocalDllName.Length +
sizeof(WCHAR);
00523
00524 pLocalDllName = DllName;
00525
00526
if (Wx86KnownDll) {
00527
00528
00529
if (Wx86KnownDllName(&LocalDllName, &ThunkDllName)) {
00530
00531 ForcedDllPath = &
LdrpKnownDllPath;
00532 ForcedDllName = &ThunkDllName;
00533
00534 }
else if (Wx86KnownRedistDll(&LocalDllName)) {
00535
00536 ForcedDllPath = &Wx86SystemDir;
00537 ForcedDllName = &LocalDllName;
00538
00539 }
00540 }
00541
00542
00543
00544
if (ForcedDllPath) {
00545
if (
ShowSnaps) {
00546
DbgPrint(
"LDRWX86: %s %wZ - force load from %wZ\\%wZ\n",
00547 Wx86KnownDll?
"x86" :
"native", DllName, ForcedDllPath, ForcedDllName );
00548 }
00549
00550
RtlCopyUnicodeString(&FreeUnicode, ForcedDllPath);
00551 FreeUnicode.Buffer[FreeUnicode.Length>>1] =
L'\\';
00552 FreeUnicode.Length +=
sizeof(WCHAR);
00553
RtlAppendUnicodeStringToString(&FreeUnicode, ForcedDllName);
00554 pLocalDllName = &FreeUnicode;
00555 DllSearchPath =
NULL;
00556 Wx86DirOverride =
TRUE;
00557 }
00558
00559
00560
00561
00562
while (
TRUE) {
00563
00564
00565
00566
00567
if (DllSearchPath) {
00568
if (!SearchWx86Dll(DllSearchPath,
00569 pLocalDllName,
00570 &FreeUnicode,
00571 &DllSearchPath
00572 ))
00573 {
00574 st = STATUS_DLL_NOT_FOUND;
00575
break;
00576 }
00577
00578 pwch = FreeUnicode.Buffer;
00579 }
00580
else {
00581 pwch = pLocalDllName->Buffer;
00582 }
00583
00584
00585
00586
00587
00588 FullNameUnicode.Length = (
USHORT)
RtlGetFullPathName_U(
00589 pwch,
00590 FullNameUnicode.MaximumLength,
00591 FullNameUnicode.Buffer,
00592 &BaseNameUnicode.Buffer
00593 );
00594
00595
if (!FullNameUnicode.Length ||
00596 FullNameUnicode.Length >= FullNameUnicode.MaximumLength)
00597 {
00598 st = STATUS_OBJECT_PATH_SYNTAX_BAD;
00599
break;
00600 }
00601
00602
00603 BaseNameUnicode.Length = FullNameUnicode.Length -
00604 (
USHORT)((ULONG_PTR)BaseNameUnicode.Buffer -
00605 (ULONG_PTR)FullNameUnicode.Buffer);
00606
00607 BaseNameUnicode.MaximumLength = BaseNameUnicode.Length +
sizeof(WCHAR);
00608
00609
if (DllSearchPath && Wx86KnownDll && !Wx86DirOverride) {
00610 NameUnicode = FullNameUnicode;
00611 NameUnicode.Length -= BaseNameUnicode.Length +
sizeof(WCHAR);
00612
if (
RtlEqualUnicodeString(&NameUnicode, &LdrpKnownDllPath, TRUE)) {
00613
RtlCopyUnicodeString(&FreeUnicode, &Wx86SystemDir);
00614 FreeUnicode.Buffer[FreeUnicode.Length >> 1] =
L'\\';
00615 FreeUnicode.Length +=
sizeof(WCHAR);
00616 pwch = &FullNameUnicode.Buffer[FreeUnicode.Length >> 1];
00617
RtlAppendUnicodeStringToString(&FreeUnicode, &BaseNameUnicode);
00618 Wx86DirOverride =
TRUE;
00619
00620
if (
RtlDoesFileExists_U(FreeUnicode.Buffer)) {
00621
RtlCopyUnicodeString(&FullNameUnicode, &FreeUnicode);
00622 BaseNameUnicode.Buffer = pwch;
00623 }
00624
else {
00625 Wx86DirUndone =
TRUE;
00626 }
00627 }
00628 }
00629
00630
00631 RetryWx86SystemDir:
00632
00633
00634
00635
00636
00637
00638
00639
if (!
RtlDosPathNameToNtPathName_U(FullNameUnicode.Buffer,
00640 &NameUnicode,
00641 NULL,
00642 NULL
00643 ))
00644 {
00645 st = STATUS_OBJECT_PATH_SYNTAX_BAD;
00646
break;
00647 }
00648
00649
if (
ShowSnaps) {
00650
DbgPrint(
"LDR: Loading (%s) %wZ\n",
00651 StaticLink ?
"STATIC" :
"DYNAMIC",
00652 &FullNameUnicode
00653 );
00654 }
00655
00656 st =
LdrpCreateDllSection(&NameUnicode,
00657 NULL,
00658 pLocalDllName,
00659 DllCharacteristics,
00660 pSection
00661 );
00662
00663
RtlFreeHeap(RtlProcessHeap(), 0, NameUnicode.Buffer);
00664
00665
if (!
NT_SUCCESS(st)) {
00666
break;
00667 }
00668
00669
00670
00671
00672 st =
NtQuerySection(*pSection,
00673 SectionImageInformation,
00674 &SectionInfo,
00675
sizeof(SectionInfo),
00676 NULL);
00677
if (!
NT_SUCCESS(st)) {
00678
break;
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
if (IsNativeMachineType(SectionInfo.Machine)) {
00691
00692
if (!Wx86KnownDll ||
00693 (SectionInfo.DllCharacteristics
00694 & IMAGE_DLLCHARACTERISTICS_X86_THUNK)) {
00695
break;
00696 }
00697
00698
00699
if (!SectionInfo.ImageContainsCode) {
00700 ContainsNoExports =
TRUE;
00701
break;
00702 }
00703
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
else {
00715
00716
if (SectionInfo.Machine == IMAGE_FILE_MACHINE_I386) {
00717
if (Wx86KnownDll) {
00718
break;
00719 }
00720 }
00721
00722
00723
if (!SectionInfo.ImageContainsCode) {
00724 ContainsNoExports =
TRUE;
00725
break;
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
if (!MismatchEncountered) {
00737 FullName.MaximumLength = FullNameUnicode.MaximumLength;
00738 FullName.Buffer =
RtlAllocateHeap(RtlProcessHeap(),
00739
MAKE_TAG(TEMP_TAG),
00740 FullName.MaximumLength
00741 );
00742
if (!FullName.Buffer) {
00743 st = STATUS_NO_MEMORY;
00744
break;
00745 }
00746 st =
NtDuplicateObject(NtCurrentProcess(),
00747 *pSection,
00748 NtCurrentProcess(),
00749 &MismatchSection,
00750 0,
00751 FALSE,
00752 DUPLICATE_SAME_ACCESS);
00753
if (!
NT_SUCCESS(st)) {
00754
break;
00755 }
00756
RtlCopyUnicodeString(&FullName, &FullNameUnicode);
00757 st = STATUS_INVALID_IMAGE_FORMAT;
00758 MismatchEncountered =
TRUE;
00759 }
00760
00761
NtClose(*pSection);
00762 *pSection =
NULL;
00763
00764
00765
00766
00767
00768
00769
if (DllSearchPath) {
00770
if (Wx86DirOverride && !Wx86DirUndone) {
00771
RtlCopyUnicodeString(&FullNameUnicode, &LdrpKnownDllPath);
00772 FullNameUnicode.Buffer[FullNameUnicode.Length >> 1] =
L'\\';
00773 FullNameUnicode.Length +=
sizeof(WCHAR);
00774 pwch = &FullNameUnicode.Buffer[FullNameUnicode.Length >> 1];
00775
RtlAppendUnicodeStringToString(&FullNameUnicode, &BaseNameUnicode);
00776 BaseNameUnicode.Buffer = pwch;
00777 Wx86DirUndone =
TRUE;
00778
goto RetryWx86SystemDir;
00779 }
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
else if (Wx86KnownDll && !Wx86DirOverride) {
00790 NameUnicode = FullNameUnicode;
00791 NameUnicode.Length -= BaseNameUnicode.Length +
sizeof(WCHAR);
00792
if (
RtlEqualUnicodeString(&NameUnicode, &LdrpKnownDllPath, TRUE)) {
00793
RtlCopyUnicodeString(&FreeUnicode, &BaseNameUnicode);
00794
RtlCopyUnicodeString(&FullNameUnicode, &Wx86SystemDir);
00795 FullNameUnicode.Buffer[FullNameUnicode.Length >> 1] =
L'\\';
00796 FullNameUnicode.Length +=
sizeof(WCHAR);
00797 BaseNameUnicode.Buffer = &FullNameUnicode.Buffer[FullNameUnicode.Length >> 1];
00798
RtlAppendUnicodeStringToString(&FullNameUnicode, &FreeUnicode);
00799 Wx86DirUndone = Wx86DirOverride =
TRUE;
00800
goto RetryWx86SystemDir;
00801 }
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
if (!DllSearchPath || !*DllSearchPath) {
00812
break;
00813 }
00814
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
if (FreeUnicode.Buffer) {
00824
RtlFreeHeap(RtlProcessHeap(), 0, FreeUnicode.Buffer);
00825 }
00826
00827
if (MismatchEncountered && !StaticLink) {
00828
if (
NT_SUCCESS(st)) {
00829
00830
00831
00832
00833
NtClose(MismatchSection);
00834 MismatchSection =
NULL;
00835 MismatchEncountered =
FALSE;
00836 }
else {
00837
00838
00839
00840
00841
if (pSection)
NtClose(*pSection);
00842 *pSection = MismatchSection;
00843 MismatchSection =
NULL;
00844 st = STATUS_SUCCESS;
00845 }
00846 }
00847
00848
if (
NT_SUCCESS(st)) {
00849
00850
00851
00852 *pViewSize = 0;
00853 ViewBase =
NULL;
00854 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer;
00855 Teb->NtTib.ArbitraryUserPointer = FullNameUnicode.Buffer;
00856 st =
NtMapViewOfSection(*pSection,
00857 NtCurrentProcess(),
00858 &ViewBase,
00859 0L,
00860 0L,
00861 NULL,
00862 pViewSize,
00863 ViewShare,
00864 0L,
00865 PAGE_READWRITE
00866 );
00867
00868
00869 stMapSection = st;
00870 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer;
00871
if (!
NT_SUCCESS(st)) {
00872
goto LWMDGiveUp;
00873 }
00874
00875 NtHeaders =
RtlImageNtHeader(ViewBase);
00876
if (NtHeaders ==
NULL) {
00877 st = STATUS_INVALID_IMAGE_FORMAT;
00878
goto LWMDGiveUp;
00879 }
00880
00881
#if defined (_ALPHA_)
00882
00883
00884
00885
00886
if (NtHeaders->OptionalHeader.SectionAlignment <
PAGE_SIZE) {
00887
NTSTATUS formatStatus = LdrpWx86FormatVirtualImage((PIMAGE_NT_HEADERS32)NtHeaders, ViewBase);
00888
if (!
NT_SUCCESS(formatStatus)) {
00889 st = formatStatus;
00890
goto LWMDGiveUp;
00891 }
00892 }
00893
#endif
00894
}
00895
00896
if (MismatchEncountered) {
00897
00898
#if defined (_ALPHA_)
00899
00900
if (!StaticLink) {
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 PLDR_DATA_TABLE_ENTRY Temp;
00911
00912
00913
00914 Temp =
LdrpAllocateDataTableEntry(ViewBase);
00915
if (!Temp) {
00916 st = STATUS_NO_MEMORY;
00917 }
else {
00918 Temp->Flags = 0;
00919 Temp->LoadCount = 0;
00920 Temp->FullDllName = FullNameUnicode;
00921 Temp->BaseDllName = BaseNameUnicode;
00922 Temp->EntryPoint =
LdrpFetchAddressOfEntryPoint(Temp->DllBase);
00923
LdrpInsertMemoryTableEntry(Temp);
00924
00925
00926
00927 st = Wx86IdentifyPlugin(ViewBase, &FullNameUnicode );
00928
00929
00930
00931
00932 RemoveEntryList(&Temp->InLoadOrderLinks);
00933 RemoveEntryList(&Temp->InMemoryOrderLinks);
00934 RemoveEntryList(&Temp->HashLinks);
00935
RtlFreeHeap(RtlProcessHeap(), 0, Temp);
00936 Temp =
NULL;
00937
00938
if (
ShowSnaps) {
00939 PCHAR
Action;
00940
00941
if (st == STATUS_SUCCESS) {
00942
Action =
"Loaded";
00943 }
else if (st == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) {
00944
Action =
"Unsupported";
00945 }
else {
00946
Action =
"Failed";
00947 }
00948
00949
DbgPrint(
"LDRWx86: Plugin: %wZ %s.\n",
00950 &FullNameUnicode, Action
00951 );
00952 }
00953
00954
00955
00956
00957
00958
00959
if (st == STATUS_SUCCESS) {
00960 Wx86Plugin =
TRUE;
00961
if (stMapSection != STATUS_IMAGE_MACHINE_TYPE_MISMATCH) {
00962 st = stMapSection;
00963 }
00964 }
00965 }
00966 }
00967
#endif
00968
if (st == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) {
00969
00970
00971
00972
00973
if (
ShowSnaps) {
00974
DbgPrint(
"Wx86 image type mismatch loading %ws (expected %s)\n",
00975 FullName.Buffer,
00976 Wx86KnownDll?
"x86" :
"RISC"
00977 );
00978 }
00979
00980
if ( NtHeaders->OptionalHeader.MajorSubsystemVersion <= 3 ) {
00981
00982 ULONG_PTR ErrorParameters[2];
00983 ULONG ErrorResponse;
00984
00985 ErrorResponse = ResponseOk;
00986
00987 ErrorParameters[0] = (ULONG_PTR)&FullName;
00988
00989
NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
00990 1,
00991 1,
00992 ErrorParameters,
00993 OptionOk,
00994 &ErrorResponse
00995 );
00996
00997 }
00998
00999 st = STATUS_INVALID_IMAGE_FORMAT;
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008
if (
NT_SUCCESS(st)) {
01009 PUNICODE_STRING
Unicode;
01010
01011
01012
if (st == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) {
01013 st = NtHeaders->OptionalHeader.ImageBase == (ULONG_PTR)ViewBase
01014 ? STATUS_SUCCESS : STATUS_IMAGE_NOT_AT_BASE;
01015 }
01016
01017 *pEntry = Entry =
LdrpAllocateDataTableEntry(ViewBase);
01018
if (!Entry) {
01019 st = STATUS_NO_MEMORY;
01020
goto LWMDGiveUp;
01021 }
01022
01023
01024
01025
01026
01027 Entry->Flags = StaticLink ? LDRP_STATIC_LINK : 0;
01028
if (ContainsNoExports) {
01029 Entry->Flags |= LDRP_WX86_IGNORE_MACHINETYPE;
01030 }
01031
if (Wx86Plugin) {
01032 Entry->Flags |= LDRP_WX86_PLUGIN;
01033 }
01034
01035 Entry->LoadCount = 0;
01036 Entry->EntryPoint =
LdrpFetchAddressOfEntryPoint(ViewBase);
01037 Entry->FullDllName.Buffer =
NULL;
01038 Entry->BaseDllName.Buffer =
NULL;
01039
01040
01041
01042
01043
01044
01045
Unicode = &Entry->FullDllName;
01046
Unicode->Length = FullNameUnicode.Length;
01047
Unicode->MaximumLength =
Unicode->Length +
sizeof(UNICODE_NULL);
01048
Unicode->Buffer =
RtlAllocateHeap(RtlProcessHeap(),
01049
MAKE_TAG( LDR_TAG ),
01050
Unicode->MaximumLength
01051 );
01052
if (!
Unicode->Buffer) {
01053 st = STATUS_NO_MEMORY;
01054
goto LWMDGiveUp;
01055 }
01056
01057 RtlCopyMemory(
Unicode->Buffer,
01058 FullNameUnicode.Buffer,
01059
Unicode->MaximumLength
01060 );
01061
01062
01063
01064
01065
01066
01067
Unicode = &Entry->BaseDllName;
01068
Unicode->Length = BaseNameUnicode.Length;
01069
Unicode->MaximumLength =
Unicode->Length +
sizeof(UNICODE_NULL);
01070
Unicode->Buffer =
RtlAllocateHeap(RtlProcessHeap(),
01071
MAKE_TAG( LDR_TAG ),
01072
Unicode->MaximumLength
01073 );
01074
01075
if (
Unicode->Buffer) {
01076 RtlCopyMemory(
Unicode->Buffer,
01077 BaseNameUnicode.Buffer,
01078
Unicode->MaximumLength
01079 );
01080 }
01081
else {
01082 st = STATUS_NO_MEMORY;
01083 }
01084
01085
01086 }
01087
01088
01089 LWMDGiveUp:
01090
01091
01092
01093
if (MismatchSection) {
01094
NtClose(MismatchSection);
01095 }
01096
01097
if (FullName.Buffer) {
01098
RtlFreeHeap(RtlProcessHeap(), 0, FullName.Buffer);
01099 }
01100
01101
01102
01103
01104
01105
if (!
NT_SUCCESS(st)) {
01106
01107
if (ViewBase) {
01108
NtUnmapViewOfSection( NtCurrentProcess(), ViewBase);
01109 }
01110
01111
if (*pSection) {
01112
NtClose(*pSection);
01113 }
01114
01115
if (Entry) {
01116
if (Entry->FullDllName.Buffer) {
01117
RtlFreeHeap(RtlProcessHeap(), 0, Entry->FullDllName.Buffer);
01118 }
01119
01120
if (Entry->BaseDllName.Buffer) {
01121
RtlFreeHeap(RtlProcessHeap(), 0, Entry->BaseDllName.Buffer);
01122 }
01123
01124
RtlFreeHeap(RtlProcessHeap(), 0, Entry);
01125
01126 *pEntry =
NULL;
01127
01128 }
01129
01130 }
01131
return st;
01132 }
01133
01134
01135
01136
01137 PLDR_DATA_TABLE_ENTRY
01138 LdrpWx86CheckForLoadedDll(
01139 IN PWSTR DllPath OPTIONAL,
01140 IN PUNICODE_STRING DllName,
01141 IN BOOLEAN Wx86KnownDll,
01142 OUT PUNICODE_STRING FullDllName
01143 )
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 {
01168
NTSTATUS Status;
01169
int Index, Length;
01170 PWCHAR pwch;
01171 PLIST_ENTRY Head, Next;
01172 PLDR_DATA_TABLE_ENTRY LdrEntry;
01173 BOOLEAN HardCodedPath=
FALSE;
01174 UNICODE_STRING BaseDllName;
01175 UNICODE_STRING FreeUnicode;
01176 UNICODE_STRING ThunkDllName;
01177 UNICODE_STRING LocalDllName;
01178 PUNICODE_STRING ForcedDllPath;
01179 PUNICODE_STRING ForcedDllName;
01180
01181
01182
01183
01184
01185
if (!DllPath) {
01186 DllPath =
LdrpDefaultPath.Buffer;
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
if ((UINT_PTR)DllPath == 1 || !*DllPath ||
01197
RtlDetermineDosPathNameType_U(DllName->Buffer) != RtlPathTypeRelative)
01198 {
01199 DllPath =
NULL;
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209 FreeUnicode.Length = 0;
01210 FreeUnicode.MaximumLength = (DOS_MAX_PATH_LENGTH*2+20)*
sizeof(UNICODE_NULL);
01211
if (DllPath) {
01212 FreeUnicode.MaximumLength = wcslen(DllPath) *
sizeof(WCHAR);
01213 }
01214
01215 FreeUnicode.Buffer =
RtlAllocateHeap(RtlProcessHeap(),
01216
MAKE_TAG( TEMP_TAG ),
01217 FreeUnicode.MaximumLength
01218 );
01219
if (!FreeUnicode.Buffer) {
01220
return NULL;
01221 }
01222
01223
01224
01225 FullDllName->Length = 0;
01226 BaseDllName = *DllName;
01227
01228 LocalDllName.Buffer = wcsrchr(BaseDllName.Buffer, L
'\\');
01229 LocalDllName.Buffer = LocalDllName.Buffer ? &LocalDllName.Buffer[1] : BaseDllName.Buffer;
01230
01231 LocalDllName.Length = wcslen(LocalDllName.Buffer) *
sizeof(WCHAR);
01232 LocalDllName.MaximumLength = LocalDllName.Length +
sizeof(WCHAR);
01233 ForcedDllPath =
NULL;
01234 ForcedDllName =
NULL;
01235
01236
if (Wx86KnownDll) {
01237
01238
01239
if (Wx86KnownDllName(&LocalDllName, &ThunkDllName)) {
01240
01241 ForcedDllPath = &
LdrpKnownDllPath;
01242 ForcedDllName = &ThunkDllName;
01243
01244 }
else if (Wx86KnownRedistDll(&LocalDllName)) {
01245
01246 ForcedDllPath = &Wx86SystemDir;
01247 ForcedDllName = &LocalDllName;
01248
01249 }
01250
01251 }
else if (Wx86KnownNativeDll(&LocalDllName)) {
01252
01253 ForcedDllPath = &
LdrpKnownDllPath;
01254 ForcedDllName = &LocalDllName;
01255 }
01256
01257
01258
01259
01260
if (ForcedDllPath) {
01261
RtlCopyUnicodeString(FullDllName, ForcedDllPath );
01262 FullDllName->Buffer[FullDllName->Length/2] =
L'\\';
01263 FullDllName->Length +=
sizeof(WCHAR);
01264 BaseDllName.Buffer = &FullDllName->Buffer[FullDllName->Length/2];
01265 BaseDllName.Length = ForcedDllName->Length;
01266 BaseDllName.MaximumLength = BaseDllName.Length +
sizeof(WCHAR);
01267
RtlAppendUnicodeStringToString(FullDllName, ForcedDllName);
01268
01269
Index =
LDRP_COMPUTE_HASH_INDEX(BaseDllName.Buffer[0]);
01270 Head = &
LdrpHashTable[
Index];
01271 Next = Head->Flink;
01272
while ( Next != Head ) {
01273 LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, HashLinks);
01274
if (DllNameMatchesLdrEntry(&BaseDllName,
01275 FullDllName,
01276 LdrEntry,
01277 Wx86KnownDll
01278 ))
01279 {
01280
goto FoundMatch;
01281 }
01282 Next = Next->Flink;
01283
01284 }
01285
01286
return NULL;
01287 }
01288
01289
01290
01291
01292
01293
do {
01294
if (DllPath) {
01295
if (!SearchWx86Dll(DllPath,
01296 DllName,
01297 &FreeUnicode,
01298 &DllPath
01299 ))
01300 {
01301 FullDllName->Length = 0;
01302 FullDllName->Buffer[0] =
L'\0';
01303 BaseDllName = *DllName;
01304
01305
Index =
LDRP_COMPUTE_HASH_INDEX(BaseDllName.Buffer[0]);
01306 Head = &
LdrpHashTable[
Index];
01307 Next = Head->Flink;
01308
while ( Next != Head ) {
01309 LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, HashLinks);
01310
if (DllNameMatchesLdrEntry(&BaseDllName,
01311 FullDllName,
01312 LdrEntry,
01313 Wx86KnownDll
01314 ))
01315 {
01316
goto FoundMatch;
01317 }
01318 Next = Next->Flink;
01319 }
01320
01321
break;
01322 }
01323
01324 pwch = FreeUnicode.Buffer;
01325 }
01326
else {
01327 pwch = DllName->Buffer;
01328 }
01329
01330
01331
01332
01333
01334 FullDllName->Length = 0;
01335 Length =
RtlGetFullPathName_U(pwch,
01336 FullDllName->MaximumLength,
01337 FullDllName->Buffer,
01338 &pwch
01339 );
01340
01341
if (Length && Length < FullDllName->MaximumLength) {
01342 UNICODE_STRING PathPart;
01343
01344
01345
01346 FullDllName->Length = (
USHORT)Length;
01347
RtlInitUnicodeString(&BaseDllName, pwch);
01348
01349
01350
01351 PathPart = *FullDllName;
01352 PathPart.Length = (
USHORT)((ULONG_PTR)BaseDllName.Buffer -
01353 (ULONG_PTR)FullDllName->Buffer -
01354
sizeof(WCHAR)
01355 );
01356
01357
01358
01359
01360
01361
Index =
LDRP_COMPUTE_HASH_INDEX(BaseDllName.Buffer[0]);
01362 Head = &
LdrpHashTable[
Index];
01363 Next = Head->Flink;
01364
while ( Next != Head ) {
01365 LdrEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, HashLinks);
01366
if (DllNameMatchesLdrEntry(&BaseDllName,
01367 FullDllName,
01368 LdrEntry,
01369 Wx86KnownDll
01370 ))
01371 {
01372
goto FoundMatch;
01373 }
01374 Next = Next->Flink;
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 }
01389
01390
01391 }
while (DllPath && *DllPath);
01392
01393 LdrEntry =
NULL;
01394
01395 FoundMatch:
01396
RtlFreeHeap(RtlProcessHeap(), 0, FreeUnicode.Buffer);
01397
return LdrEntry;
01398 }
01399
01400
01401
01402
01403
01404
VOID
01405 LdrpWx86DllProcessDetach(
01406 IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry
01407 )
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 {
01426 PIMAGE_NT_HEADERS NtHeader;
01427 PDLL_INIT_ROUTINE InitRoutine;
01428
01429
01430
01431
01432
01433
01434 NtHeader =
RtlImageNtHeader(LdrDataTableEntry->DllBase);
01435 InitRoutine = (PDLL_INIT_ROUTINE)LdrDataTableEntry->EntryPoint;
01436
if (InitRoutine && (LdrDataTableEntry->Flags & LDRP_PROCESS_ATTACH_CALLED)) {
01437
if (
ShowSnaps) {
01438
DbgPrint(
"WX86LDR: Calling deinit %lx\n", InitRoutine);
01439 }
01440
01441
if (NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
01442 (Wx86DllEntryPoint)(InitRoutine,
01443 LdrDataTableEntry->DllBase,
01444 DLL_PROCESS_DETACH,
01445
NULL
01446 );
01447
01448 }
01449
else {
01450
LdrpCallInitRoutine(InitRoutine,
01451 LdrDataTableEntry->DllBase,
01452 DLL_PROCESS_DETACH,
01453 NULL);
01454 }
01455
01456 }
01457 }
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
NTSTATUS
01468 LdrpRunWx86DllEntryPoint(
01469 IN PDLL_INIT_ROUTINE InitRoutine,
01470 OUT BOOLEAN *pInitStatus,
01471 IN PVOID DllBase,
01472 IN ULONG Reason,
01473 IN PCONTEXT Context
01474 )
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 {
01499 PIMAGE_NT_HEADERS NtHeader =
NULL;
01500 BOOLEAN InitStatus;
01501 PWX86TIB Wx86Tib;
01502
01503 NtHeader =
RtlImageNtHeader(DllBase);
01504
if (NtHeader && NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
01505
01506 InitStatus = (Wx86DllEntryPoint)(InitRoutine,
01507 DllBase,
01508 Reason,
01509 Context
01510 );
01511
01512
if (pInitStatus) {
01513 *pInitStatus = InitStatus;
01514 }
01515
01516
return STATUS_SUCCESS;
01517
01518 }
01519
01520
return STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
01521 }
01522
01523
01524
01525
NTSTATUS
01526 LoaderWx86Unload(
01527 VOID
01528 )
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547 {
01548 Wx86ProcessInit =
NULL;
01549 Wx86DllMapNotify =
NULL;
01550 Wx86DllEntryPoint =
NULL;
01551 Wx86ProcessStartRoutine=
NULL;
01552 Wx86ThreadStartRoutine=
NULL;
01553 Wx86KnownDllName =
NULL;
01554 Wx86KnownNativeDll =
NULL;
01555 Wx86KnownRedistDll =
NULL;
01556 Wx86OnTheFly=
FALSE;
01557
01558
01559
if (Wx86SystemDir.Buffer) {
01560
RtlFreeHeap(RtlProcessHeap(), 0, Wx86SystemDir.Buffer);
01561 Wx86SystemDir.Buffer =
NULL;
01562 }
01563
01564
return STATUS_SUCCESS;
01565
01566 }
01567
01568
01569
01570
01571
01572
01573
NTSTATUS
01574 LdrpLoadWx86Dll(
01575 PCONTEXT Context
01576 )
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 {
01596
NTSTATUS st;
01597 ULONG Length;
01598 PVOID DllHandle;
01599 ANSI_STRING ProcName;
01600 UNICODE_STRING DllName;
01601 WCHAR
Buffer[STATIC_UNICODE_BUFFER_LENGTH];
01602
01603
01604
01605
01606
01607 DllHandle = (PVOID)((UINT_PTR)Context & ~0x80000000);
01608
01609
if (DllHandle != Context) {
01610 Context =
NULL;
01611 }
01612
else {
01613 DllHandle =
NULL;
01614 }
01615
01616
01617
01618
01619
01620
RtlInitUnicodeString( &NtSystemRoot, USER_SHARED_DATA->NtSystemRoot );
01621 Wx86SystemDir.MaximumLength =
NtSystemRoot.Length +
sizeof(Wx86Dir);
01622 Wx86SystemDir.Buffer =
RtlAllocateHeap(RtlProcessHeap(),
01623
MAKE_TAG( LDR_TAG ),
01624 Wx86SystemDir.MaximumLength
01625 );
01626
if (!Wx86SystemDir.Buffer) {
01627 st = STATUS_NO_MEMORY;
01628
goto LWx86DllError;
01629 }
01630
01631
RtlCopyUnicodeString(&Wx86SystemDir, &NtSystemRoot);
01632 st =
RtlAppendUnicodeToString(&Wx86SystemDir, Wx86Dir);
01633
if (!
NT_SUCCESS(st)) {
01634
goto LWx86DllError;
01635 }
01636
01637
01638
01639
01640
01641
01642
01643
01644
if (!DllHandle) {
01645 DllName.Buffer =
Buffer;
01646 DllName.MaximumLength =
sizeof(
Buffer);
01647
RtlCopyUnicodeString(&DllName, &LdrpKnownDllPath);
01648 DllName.Buffer[DllName.Length /
sizeof(WCHAR)] =
L'\\';
01649 DllName.Length +=
sizeof(WCHAR);
01650
RtlAppendUnicodeToString(&DllName, L
"wx86.dll");
01651
01652 st =
LdrpLoadDll(NULL, NULL, &DllName, &DllHandle, TRUE);
01653
if (!
NT_SUCCESS(st)) {
01654
goto LWx86DllError;
01655 }
01656 }
01657
01658
01659
01660
01661
01662
RtlInitAnsiString (&ProcName,
"Wx86KnownDllName");
01663 st =
LdrGetProcedureAddress(DllHandle,
01664 &ProcName,
01665 0,
01666 (PVOID *)&Wx86KnownDllName
01667 );
01668
if (!
NT_SUCCESS(st)) {
01669
goto LWx86DllError;
01670 }
01671
01672
01673
RtlInitAnsiString (&ProcName,
"Wx86KnownNativeDll");
01674 st =
LdrGetProcedureAddress(DllHandle,
01675 &ProcName,
01676 0,
01677 (PVOID *)&Wx86KnownNativeDll
01678 );
01679
if (!
NT_SUCCESS(st)) {
01680
goto LWx86DllError;
01681 }
01682
01683
RtlInitAnsiString (&ProcName,
"Wx86KnownRedistDll");
01684 st =
LdrGetProcedureAddress(DllHandle,
01685 &ProcName,
01686 0,
01687 (PVOID *)&Wx86KnownRedistDll
01688 );
01689
if (!
NT_SUCCESS(st)) {
01690
goto LWx86DllError;
01691 }
01692
01693
RtlInitAnsiString (&ProcName,
"RunWx86DllEntryPoint");
01694 st =
LdrGetProcedureAddress(DllHandle,
01695 &ProcName,
01696 0,
01697 (PVOID *)&Wx86DllEntryPoint
01698 );
01699
if (!
NT_SUCCESS(st)) {
01700
goto LWx86DllError;
01701 }
01702
01703
RtlInitAnsiString (&ProcName,
"Wx86ThreadStartRoutine");
01704 st =
LdrGetProcedureAddress(DllHandle,
01705 &ProcName,
01706 0,
01707 (PVOID *)&Wx86ThreadStartRoutine
01708 );
01709
if (!
NT_SUCCESS(st)) {
01710
goto LWx86DllError;
01711 }
01712
01713
RtlInitAnsiString (&ProcName,
"Wx86ProcessStartRoutine");
01714 st =
LdrGetProcedureAddress(DllHandle,
01715 &ProcName,
01716 0,
01717 (PVOID *)&Wx86ProcessStartRoutine
01718 );
01719
if (!
NT_SUCCESS(st)) {
01720
goto LWx86DllError;
01721 }
01722
01723
RtlInitAnsiString (&ProcName,
"Wx86DllMapNotify");
01724 st =
LdrGetProcedureAddress(DllHandle,
01725 &ProcName,
01726 0,
01727 (PVOID *)&Wx86DllMapNotify
01728 );
01729
if (!
NT_SUCCESS(st)) {
01730
goto LWx86DllError;
01731 }
01732
01733
01734
RtlInitAnsiString (&ProcName,
"Wx86ProcessInit");
01735 st =
LdrGetProcedureAddress(DllHandle,
01736 &ProcName,
01737 0,
01738 (PVOID *)&Wx86ProcessInit
01739 );
01740
if (!
NT_SUCCESS(st)) {
01741
goto LWx86DllError;
01742 }
01743
01744
01745
if (Context) {
01746 st = LdrpInitWx86(NtCurrentTeb()->Vdm, Context, FALSE);
01747
if (!
NT_SUCCESS(st)) {
01748
goto LWx86DllError;
01749 }
01750 }
01751
else {
01752 Wx86OnTheFly=
TRUE;
01753 }
01754
01755
01756
01757
if (!(*Wx86ProcessInit)(LoaderWx86Unload, Wx86OnTheFly)) {
01758 st = STATUS_ENTRYPOINT_NOT_FOUND;
01759 }
01760
01761
01762 LWx86DllError:
01763
01764
if (!
NT_SUCCESS(st)) {
01765
01766 LoaderWx86Unload();
01767 }
01768
01769
return st;
01770 }
01771
01772
01773
01774
NTSTATUS
01775 LdrpInitWx86(
01776 PWX86TIB Wx86Tib,
01777 PCONTEXT Context,
01778 BOOLEAN NewThread
01779 )
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793 {
01794 PTEB Teb;
01795 MEMORY_BASIC_INFORMATION MemBasicInfo;
01796
01797
if (Wx86Tib != Wx86CurrentTib()) {
01798
return STATUS_APP_INIT_FAILURE;
01799 }
01800
01801
if (
ShowSnaps) {
01802
DbgPrint(
"LDRWX86: %x Pc %x Base %x Limit %x DeallocationStack %x\n",
01803 Wx86Tib,
01804 Wx86Tib->InitialPc,
01805 Wx86Tib->StackBase,
01806 Wx86Tib->StackLimit,
01807 Wx86Tib->DeallocationStack
01808 );
01809 }
01810
01811
01812
if (Wx86Tib->EmulateInitialPc) {
01813 Wx86Tib->EmulateInitialPc =
FALSE;
01814
01815
if (NewThread) {
01816
01817
#if defined(_MIPS_)
01818
Context->XIntA0 = (LONG)Wx86ThreadStartRoutine;
01819
#elif defined(_ALPHA_)
01820
Context->IntA0 = (ULONG_PTR)Wx86ThreadStartRoutine;
01821
#elif defined(_PPC_)
01822
Context->Gpr3 = (ULONG)Wx86ThreadStartRoutine;
01823
#elif defined(_IA64_)
01824
Context->IntS0 = Context->StIIP = (ULONG_PTR)Wx86ThreadStartRoutine;
01825
#else
01826
#error Need to set instruction pointer to Wx86ThreadStartRoutine
01827
#endif
01828
}
01829
else {
01830
01831
#if defined(_MIPS_)
01832
Context->XIntA1 = (LONG)Wx86ProcessStartRoutine;
01833
#elif defined(_ALPHA_)
01834
Context->IntA0 = (ULONG_PTR)Wx86ProcessStartRoutine;
01835
#elif defined(_PPC_)
01836
Context->Gpr3 = (ULONG)Wx86ProcessStartRoutine;
01837
#elif defined(_IA64_)
01838
Context->IntS0 = Context->StIIP = (ULONG_PTR)Wx86ProcessStartRoutine;
01839
#else
01840
#error Need to set instruction pointer to Wx86ProcessStartRoutine
01841
#endif
01842
01843 }
01844
01845 }
01846
01847
01848
return STATUS_SUCCESS;
01849 }
01850
#endif
01851
01852
01853
01854
#if defined (_ALPHA_) || defined(BUILD_WOW6432)
01855
01856
01857
01858
#define MI_ROUND_TO_SIZE(LENGTH,ALIGNMENT) \
01859
(((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1))
01860
01861
NTSTATUS
01862 Wx86SetRelocatedSharedProtection (
01863 IN PVOID Base,
01864 IN BOOLEAN Reset
01865 )
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 {
01891 HANDLE CurrentProcessHandle;
01892 SIZE_T RegionSize;
01893 ULONG NewProtect, OldProtect;
01894 PVOID VirtualAddress;
01895 ULONG i;
01896 PIMAGE_NT_HEADERS NtHeaders;
01897 PIMAGE_SECTION_HEADER SectionHeader;
01898
NTSTATUS st;
01899 ULONG NumberOfSharedDataPages;
01900 SIZE_T NumberOfNativePagesForImage;
01901
01902 CurrentProcessHandle = NtCurrentProcess();
01903
01904 NtHeaders =
RtlImageNtHeader(Base);
01905
01906 SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders +
sizeof(ULONG) +
01907
sizeof(IMAGE_FILE_HEADER) +
01908 NtHeaders->FileHeader.SizeOfOptionalHeader
01909 );
01910
01911 NumberOfSharedDataPages = 0;
01912 NumberOfNativePagesForImage =
01913
NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
01914
01915
for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++) {
01916
if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
01917 (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
01918 (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
01919 RegionSize = SectionHeader->SizeOfRawData;
01920 VirtualAddress = (PVOID)((ULONG_PTR)Base +
01921 ((NumberOfNativePagesForImage + NumberOfSharedDataPages) <<
NATIVE_PAGE_SHIFT));
01922 NumberOfNativePagesForImage +=
MI_ROUND_TO_SIZE (RegionSize, NATIVE_PAGE_SIZE) >>
NATIVE_PAGE_SHIFT;
01923
01924
if (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) {
01925
01926
01927
01928
if (Reset) {
01929
if (SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
01930 NewProtect = PAGE_EXECUTE;
01931 }
01932
else {
01933 NewProtect = PAGE_READONLY;
01934 }
01935 NewProtect |= (SectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) ? PAGE_NOCACHE : 0;
01936 }
01937
else {
01938 NewProtect = PAGE_READWRITE;
01939 }
01940
01941 st =
NtProtectVirtualMemory(CurrentProcessHandle, &VirtualAddress,
01942 &RegionSize, NewProtect, &OldProtect);
01943
01944
if (!
NT_SUCCESS(st)) {
01945
return st;
01946 }
01947 }
01948 }
01949 }
01950
01951
if (Reset) {
01952
NtFlushInstructionCache(NtCurrentProcess(), NULL, 0);
01953 }
01954
01955
return STATUS_SUCCESS;
01956 }
01957
01958
01959 PIMAGE_BASE_RELOCATION LdrpWx86ProcessRelocationBlock(
01960 IN ULONG_PTR VA,
01961 IN PUCHAR ImageBase,
01962 IN ULONG SizeOfBlock,
01963 IN PUSHORT NextOffset,
01964 IN ULONG Diff,
01965 IN ULONG_PTR SectionStartVA,
01966 IN ULONG_PTR SectionEndVA);
01967
01968
NTSTATUS
01969 FixupBlockList(
01970 IN PUCHAR ImageBase);
01971
01972
VOID
01973 FixupSectionHeader(
01974 IN PUCHAR ImageBase);
01975
01976
NTSTATUS
01977 LdrpWx86FormatVirtualImage(
01978 IN PIMAGE_NT_HEADERS32 NtHeaders,
01979 IN PVOID DllBase
01980 )
01981 {
01982 PIMAGE_SECTION_HEADER SectionTable, Section, LastSection, FirstSection;
01983 ULONG VirtualImageSize;
01984 PUCHAR NextVirtualAddress, SrcVirtualAddress, DestVirtualAddress;
01985 PUCHAR ImageBase= DllBase;
01986 LONG
Size;
01987 ULONG NumberOfSharedDataPages;
01988 ULONG NumberOfNativePagesForImage;
01989 ULONG NumberOfExtraPagesForImage;
01990 ULONG_PTR PreferredImageBase;
01991 BOOLEAN ImageHasRelocatedSharedSection =
FALSE;
01992 ULONG SubSectionSize;
01993
01994
NTSTATUS st = Wx86SetRelocatedSharedProtection(DllBase, FALSE);
01995
if (!
NT_SUCCESS(st)) {
01996
DbgPrint(
"Wx86SetRelocatedSharedProtection failed with return status %x\n", st);
01997 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
01998
return st;
01999 }
02000
02001
02002
02003
02004
02005 SectionTable = IMAGE_FIRST_SECTION(NtHeaders);
02006 LastSection = SectionTable + NtHeaders->FileHeader.NumberOfSections;
02007
02008
if (SectionTable->PointerToRawData == SectionTable->VirtualAddress) {
02009
02010
02011 FirstSection = SectionTable + 1;
02012 }
02013
else {
02014 FirstSection = SectionTable;
02015 }
02016
02017
02018
02019
02020
02021 Section = FirstSection;
02022
while (Section < LastSection) {
02023 SrcVirtualAddress = ImageBase + Section->PointerToRawData;
02024 DestVirtualAddress = Section->VirtualAddress + ImageBase;
02025
02026
if (DestVirtualAddress > SrcVirtualAddress) {
02027
02028
break;
02029 }
02030
02031
02032
if (Section->SizeOfRawData != 0) {
02033
if (Section->PointerToRawData != 0) {
02034 RtlMoveMemory(DestVirtualAddress,
02035 SrcVirtualAddress,
02036 Section->SizeOfRawData);
02037 }
02038 }
02039
else {
02040 Section->PointerToRawData = 0;
02041 }
02042
02043 Section++;
02044 }
02045
02046
02047
02048
02049
02050 Section = --LastSection;
02051 NextVirtualAddress = ImageBase + NtHeaders->OptionalHeader.SizeOfImage;
02052
02053
while (Section >= FirstSection) {
02054 SrcVirtualAddress = ImageBase + Section->PointerToRawData;
02055 DestVirtualAddress = Section->VirtualAddress + ImageBase;
02056
02057
02058
02059
02060
02061
02062
02063 SubSectionSize = Section->SizeOfRawData;
02064
if (Section->Misc.VirtualSize &&
02065 SubSectionSize >
MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86)) {
02066 SubSectionSize =
MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86);
02067 }
02068
02069
02070
02071
02072
if (DestVirtualAddress + SubSectionSize > NextVirtualAddress) {
02073 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
02074
return STATUS_INVALID_IMAGE_FORMAT;
02075 }
02076
02077
if (DestVirtualAddress < SrcVirtualAddress) {
02078
02079
break;
02080 }
02081
02082
02083
if (Section->SizeOfRawData != 0) {
02084
if (Section->PointerToRawData != 0) {
02085 RtlMoveMemory(DestVirtualAddress,
02086 SrcVirtualAddress,
02087 SubSectionSize);
02088 }
02089 }
02090
else {
02091 Section->PointerToRawData = 0;
02092 }
02093
02094 NextVirtualAddress = DestVirtualAddress;
02095 Section--;
02096 }
02097
02098
02099
02100
02101
02102 Section = LastSection;
02103 NextVirtualAddress = ImageBase + NtHeaders->OptionalHeader.SizeOfImage;
02104
02105 NumberOfSharedDataPages = 0;
02106
while (Section >= SectionTable) {
02107 DestVirtualAddress = Section->VirtualAddress + ImageBase;
02108
02109
02110
02111
02112
02113
if ((Section->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02114 (!(Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02115 (Section->Characteristics & IMAGE_SCN_MEM_WRITE))) {
02116 ImageHasRelocatedSharedSection =
TRUE;
02117
#if 0
02118
DbgPrint(
"Unsuported IMAGE_SCN_MEM_SHARED %x\n",
02119 Section->Characteristics
02120 );
02121
#endif
02122
}
02123
02124
02125
02126
02127
if (Section->SizeOfRawData != 0) {
02128
if (Section->PointerToRawData == 0) {
02129 RtlZeroMemory(DestVirtualAddress,
02130 Section->SizeOfRawData
02131 );
02132 }
02133 }
02134
02135
02136
02137
02138 RtlZeroMemory(DestVirtualAddress + Section->SizeOfRawData,
02139 (ULONG)(NextVirtualAddress - DestVirtualAddress - Section->SizeOfRawData)
02140 );
02141
02142 NextVirtualAddress = DestVirtualAddress;
02143 Section--;
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
if (!ImageHasRelocatedSharedSection) {
02155
goto LdrwWx86FormatVirtualImageDone;
02156 }
02157
02158 st = FixupBlockList(DllBase);
02159
if (!
NT_SUCCESS(st)) {
02160 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
02161
return st;
02162 }
02163
02164 NumberOfNativePagesForImage =
02165
NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
02166 NumberOfExtraPagesForImage = 0;
02167
02168
02169
02170
for (Section = SectionTable; Section <= LastSection; Section++)
02171 {
02172 ULONG EndOfSection;
02173 ULONG ExtraPages;
02174
02175 EndOfSection = Section->PointerToRawData + Section->SizeOfRawData;
02176
02177
if (EndOfSection > NtHeaders->OptionalHeader.SizeOfImage) {
02178
02179 ExtraPages =
NATIVE_BYTES_TO_PAGES(EndOfSection - NtHeaders->OptionalHeader.SizeOfImage);
02180
if (ExtraPages > NumberOfExtraPagesForImage) {
02181 NumberOfExtraPagesForImage = ExtraPages;
02182 }
02183 }
02184 }
02185
02186 PreferredImageBase = NtHeaders->OptionalHeader.ImageBase;
02187
02188 NumberOfNativePagesForImage += NumberOfExtraPagesForImage;
02189 NumberOfSharedDataPages = 0;
02190
for (Section = SectionTable; Section <= LastSection; Section++)
02191 {
02192 ULONG bFirst = 1;
02193
02194
if ((Section->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02195 (!(Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02196 (Section->Characteristics & IMAGE_SCN_MEM_WRITE)))
02197 {
02198 PIMAGE_BASE_RELOCATION NextBlock;
02199
PUSHORT NextOffset;
02200 ULONG TotalBytes;
02201 ULONG SizeOfBlock;
02202 ULONG_PTR VA;
02203 ULONG_PTR SectionStartVA;
02204 ULONG_PTR SectionEndVA;
02205 ULONG SectionVirtualSize;
02206 ULONG Diff;
02207
02208 SectionVirtualSize = Section->Misc.VirtualSize;
02209
if (SectionVirtualSize == 0)
02210 {
02211 SectionVirtualSize = Section->SizeOfRawData;
02212 }
02213
02214 SectionStartVA = PreferredImageBase + Section->VirtualAddress;
02215 SectionEndVA = SectionStartVA + SectionVirtualSize;
02216
02217
02218 NextBlock =
RtlImageDirectoryEntryToData(DllBase, TRUE,
02219 IMAGE_DIRECTORY_ENTRY_BASERELOC,
02220 &TotalBytes);
02221
if (!NextBlock || !TotalBytes)
02222 {
02223
02224
02225
02226
if (!bFirst)
02227 {
02228
02229
if (
ShowSnaps)
02230 {
02231
DbgPrint(
"LdrpWx86FormatVirtualImage: failure "
02232
"after relocating some sections for image at %x\n",
02233 DllBase);
02234 }
02235 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
02236
return STATUS_INVALID_IMAGE_FORMAT;
02237 }
02238
02239
if (
ShowSnaps)
02240 {
02241
DbgPrint(
"LdrpWx86FormatVirtualImage: No fixup info "
02242
"for image at %x; private sections will be "
02243
"used for shared data sections.\n",
02244 DllBase);
02245 }
02246
break;
02247 }
02248
02249 bFirst = 0;
02250
02251 Diff = (NumberOfNativePagesForImage +
02252 NumberOfSharedDataPages) <<
NATIVE_PAGE_SHIFT;
02253 Diff -= (ULONG) (SectionStartVA - PreferredImageBase);
02254
02255
if (
ShowSnaps)
02256 {
02257
DbgPrint(
"LdrpWx86FormatVirtualImage: Relocating shared "
02258
"data for shared data section 0x%x of image "
02259
"at %x by 0x%lx bytes\n",
02260 Section - SectionTable + 1, DllBase, Diff);
02261 }
02262
02263
while (TotalBytes)
02264 {
02265 SizeOfBlock = NextBlock->SizeOfBlock;
02266 TotalBytes -= SizeOfBlock;
02267 SizeOfBlock -=
sizeof(IMAGE_BASE_RELOCATION);
02268 SizeOfBlock /=
sizeof(
USHORT);
02269 NextOffset = (
PUSHORT) ((PCHAR)NextBlock +
02270
sizeof(IMAGE_BASE_RELOCATION));
02271 VA = (ULONG_PTR) DllBase + NextBlock->VirtualAddress;
02272
02273 NextBlock = LdrpWx86ProcessRelocationBlock(VA, DllBase, SizeOfBlock,
02274 NextOffset,
02275 Diff,
02276 SectionStartVA,
02277 SectionEndVA);
02278
if (NextBlock ==
NULL)
02279 {
02280
02281
if (
ShowSnaps)
02282 {
02283
DbgPrint(
"LdrpWx86FormatVirtualImage: failure "
02284
"after relocating some sections for image at %x; "
02285
"Relocation information invalid\n",
02286 DllBase);
02287 }
02288 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
02289
return STATUS_INVALID_IMAGE_FORMAT;
02290 }
02291 }
02292 NumberOfSharedDataPages +=
MI_ROUND_TO_SIZE (SectionVirtualSize,
02293 NATIVE_PAGE_SIZE) >>
02294
NATIVE_PAGE_SHIFT;
02295
02296 }
02297 }
02298
02299 LdrwWx86FormatVirtualImageDone:
02300
02301
02302
02303
if (SectionTable->PointerToRawData != 0) {
02304 DestVirtualAddress = SectionTable->PointerToRawData + ImageBase;
02305
Size = (LONG)(NextVirtualAddress - DestVirtualAddress);
02306
if (
Size > 0) {
02307 RtlZeroMemory(DestVirtualAddress,
02308 (ULONG)Size
02309 );
02310 }
02311 }
02312
02313 Wx86SetRelocatedSharedProtection(DllBase, TRUE);
02314
return STATUS_SUCCESS;
02315
02316 }
02317
02318
02320
02321 ULONG
02322 LdrpWx86RelocatedFixupDiff(
02323 IN PUCHAR ImageBase,
02324 IN ULONG Offset
02325 )
02326 {
02327 PIMAGE_SECTION_HEADER SectionHeader;
02328 ULONG i;
02329 ULONG NumberOfSharedDataPages;
02330 ULONG NumberOfNativePagesForImage;
02331 PIMAGE_NT_HEADERS32 NtHeaders = (PIMAGE_NT_HEADERS32)
RtlImageNtHeader(ImageBase);
02332 ULONG Diff = 0;
02333 ULONG_PTR FixupAddr = (ULONG_PTR)(ImageBase +
Offset);
02334
02335 SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders +
sizeof(ULONG) +
02336
sizeof(IMAGE_FILE_HEADER) +
02337 NtHeaders->FileHeader.SizeOfOptionalHeader
02338 );
02339
02340 NumberOfNativePagesForImage =
02341
NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
02342 NumberOfSharedDataPages = 0;
02343
02344
for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
02345 {
02346 ULONG_PTR SectionStartVA;
02347 ULONG_PTR SectionEndVA;
02348 ULONG SectionVirtualSize;
02349
02350 SectionVirtualSize = SectionHeader->Misc.VirtualSize;
02351
if (SectionVirtualSize == 0) {
02352 SectionVirtualSize = SectionHeader->SizeOfRawData;
02353 }
02354
02355 SectionStartVA = (ULONG_PTR)ImageBase + SectionHeader->VirtualAddress;
02356 SectionEndVA = SectionStartVA + SectionVirtualSize;
02357
02358
if (((ULONG_PTR)FixupAddr >= SectionStartVA) && ((ULONG_PTR)FixupAddr <= SectionEndVA)) {
02359
if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02360 (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02361 (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
02362 Diff = (NumberOfNativePagesForImage +
02363 NumberOfSharedDataPages) <<
NATIVE_PAGE_SHIFT;
02364 Diff -= (ULONG)SectionHeader->VirtualAddress;
02365 }
02366
break;
02367 }
02368
02369
if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02370 (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02371 (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
02372 NumberOfSharedDataPages +=
MI_ROUND_TO_SIZE (SectionVirtualSize,
02373 NATIVE_PAGE_SIZE) >>
02374
NATIVE_PAGE_SHIFT;
02375 }
02376 }
02377
02378
return Diff;
02379 }
02380
02381
02382
NTSTATUS
02383 FixupBlockList(
02384 IN PUCHAR ImageBase)
02385 {
02386 PIMAGE_BASE_RELOCATION NextBlock;
02387
PUSHORT NextOffset;
02388 ULONG TotalBytes;
02389 ULONG SizeOfBlock;
02390
02391
NTSTATUS st;
02392
02393 NextBlock =
RtlImageDirectoryEntryToData(ImageBase, TRUE,
02394 IMAGE_DIRECTORY_ENTRY_BASERELOC,
02395 &TotalBytes);
02396
02397
if (!NextBlock || !TotalBytes) {
02398
if (
ShowSnaps) {
02399
DbgPrint(
"LdrpWx86FixupBlockList: No fixup info "
02400
"for image at %x; private sections will be "
02401
"used for shared data sections.\n",
02402 ImageBase);
02403 }
02404
return STATUS_SUCCESS;
02405 }
02406
02407
02408
while (TotalBytes) {
02409 SizeOfBlock = NextBlock->SizeOfBlock;
02410 TotalBytes -= SizeOfBlock;
02411 SizeOfBlock -=
sizeof(IMAGE_BASE_RELOCATION);
02412 SizeOfBlock /=
sizeof(
USHORT);
02413 NextOffset = (
PUSHORT) ((PCHAR)NextBlock +
02414
sizeof(IMAGE_BASE_RELOCATION));
02415
02416 NextBlock->VirtualAddress += LdrpWx86RelocatedFixupDiff(ImageBase, NextBlock->VirtualAddress);
02417
02418
while (SizeOfBlock--) {
02419
switch ((*NextOffset) >> 12) {
02420
case IMAGE_REL_BASED_HIGHLOW :
02421
case IMAGE_REL_BASED_HIGH :
02422
case IMAGE_REL_BASED_LOW :
02423
break;
02424
02425
case IMAGE_REL_BASED_HIGHADJ :
02426 ++NextOffset;
02427 --SizeOfBlock;
02428
break;
02429
02430
case IMAGE_REL_BASED_IA64_IMM64:
02431
case IMAGE_REL_BASED_DIR64:
02432
case IMAGE_REL_BASED_MIPS_JMPADDR :
02433
case IMAGE_REL_BASED_ABSOLUTE :
02434
case IMAGE_REL_BASED_SECTION :
02435
case IMAGE_REL_BASED_REL32 :
02436
break;
02437
02438
case IMAGE_REL_BASED_HIGH3ADJ :
02439 ++NextOffset;
02440 --SizeOfBlock;
02441 ++NextOffset;
02442 --SizeOfBlock;
02443
break;
02444
02445
default :
02446
return STATUS_INVALID_IMAGE_FORMAT;
02447 }
02448 ++NextOffset;
02449 }
02450
02451 NextBlock = (PIMAGE_BASE_RELOCATION)NextOffset;
02452
02453
if (NextBlock ==
NULL) {
02454
02455
if (
ShowSnaps) {
02456
DbgPrint(
"LdrpWx86FixupBlockList: failure "
02457
"after relocating some sections for image at %x; "
02458
"Relocation information invalid\n",
02459 ImageBase);
02460 }
02461
return STATUS_INVALID_IMAGE_FORMAT;
02462 }
02463 }
02464
02465
return STATUS_SUCCESS;
02466 }
02467
02468
02469 BOOLEAN
02470 LdrpWx86DllHasRelocatedSharedSection(
02471 IN PUCHAR ImageBase)
02472 {
02473 PIMAGE_SECTION_HEADER SectionHeader;
02474 ULONG i;
02475 PIMAGE_NT_HEADERS32 NtHeaders = (PIMAGE_NT_HEADERS32)
RtlImageNtHeader(ImageBase);
02476
02477 SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders +
sizeof(ULONG) +
02478
sizeof(IMAGE_FILE_HEADER) +
02479 NtHeaders->FileHeader.SizeOfOptionalHeader
02480 );
02481
02482
for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
02483 {
02484
if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02485 (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02486 (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
02487
return TRUE;
02488 }
02489 }
02490
02491
return FALSE;
02492 }
02493
02494
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509 PIMAGE_BASE_RELOCATION LdrpWx86ProcessRelocationBlock(
02510 IN ULONG_PTR VA,
02511 IN PUCHAR ImageBase,
02512 IN ULONG SizeOfBlock,
02513 IN PUSHORT NextOffset,
02514 IN ULONG Diff,
02515 IN ULONG_PTR SectionStartVA,
02516 IN ULONG_PTR SectionEndVA)
02517 {
02518 PUCHAR FixupVA;
02519
USHORT Offset;
02520 LONG Temp;
02521 ULONG_PTR DataVA;
02522
02523
02524
while (SizeOfBlock--) {
02525
02526
Offset = *NextOffset & (
USHORT)0xfff;
02527 FixupVA = (PUCHAR)(VA +
Offset);
02528
02529
02530
02531
02532
switch ((*NextOffset) >> 12) {
02533
02534
case IMAGE_REL_BASED_HIGHLOW :
02535
02536
02537
02538
02539 Temp = *(LONG UNALIGNED *)FixupVA;
02540 DataVA = (ULONG_PTR) Temp;
02541
if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
02542 {
02543 Temp += (ULONG) Diff;
02544 *(LONG UNALIGNED *)FixupVA = Temp;
02545 }
02546
02547
break;
02548
02549
case IMAGE_REL_BASED_HIGH :
02550
02551
02552
02553 Temp = *(
PUSHORT)FixupVA << 16;
02554 DataVA = (ULONG_PTR) Temp;
02555
if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
02556 {
02557 Temp += (ULONG) Diff;
02558 *(
PUSHORT)FixupVA = (
USHORT)(Temp >> 16);
02559 }
02560
break;
02561
02562
case IMAGE_REL_BASED_HIGHADJ :
02563
02564
02565
02566
02567 Temp = *(
PUSHORT)FixupVA << 16;
02568 ++NextOffset;
02569 --SizeOfBlock;
02570 Temp += (LONG)(*(
PSHORT)NextOffset);
02571 DataVA = (ULONG_PTR) Temp;
02572
if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
02573 {
02574 Temp += (ULONG) Diff;
02575 Temp += 0x8000;
02576 *(
PUSHORT)FixupVA = (
USHORT)(Temp >> 16);
02577 }
02578
break;
02579
02580
case IMAGE_REL_BASED_LOW :
02581
02582
02583
02584 Temp = *(
PSHORT)FixupVA;
02585 DataVA = (ULONG_PTR) Temp;
02586
if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
02587 {
02588 Temp += (ULONG) Diff;
02589 *(
PUSHORT)FixupVA = (
USHORT)Temp;
02590 }
02591
break;
02592
02593
case IMAGE_REL_BASED_IA64_IMM64:
02594
02595
02596
02597
02598
02599
02600
02601
02602
break;
02603
02604
case IMAGE_REL_BASED_DIR64:
02605
02606
02607
02608
02609
02610
02611
02612
break;
02613
02614
case IMAGE_REL_BASED_MIPS_JMPADDR :
02615
02616
02617
02618
02619
02620
break;
02621
02622
case IMAGE_REL_BASED_ABSOLUTE :
02623
02624
02625
02626
break;
02627
02628
case IMAGE_REL_BASED_SECTION :
02629
02630
02631
02632
break;
02633
02634
case IMAGE_REL_BASED_REL32 :
02635
02636
02637
02638
break;
02639
02640
case IMAGE_REL_BASED_HIGH3ADJ :
02641
02642
02643
02644
02645
02646
02647
02648 ++NextOffset;
02649 --SizeOfBlock;
02650 ++NextOffset;
02651 --SizeOfBlock;
02652
02653
break;
02654
02655
default :
02656
02657
02658
02659
02660
return (PIMAGE_BASE_RELOCATION)
NULL;
02661 }
02662 ++NextOffset;
02663 }
02664
return (PIMAGE_BASE_RELOCATION)NextOffset;
02665 }
02666
02667
#endif // ALPHA or BUILD_WOW6432
02668
02669
#if defined (_ALPHA_) && defined (WX86)
02670
NTSTATUS
02671 Wx86IdentifyPlugin(
02672 IN PVOID DllBase,
02673 IN PUNICODE_STRING FullDllName
02674 )
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696 {
02697
NTSTATUS st;
02698 PVOID Provider[WX86PLUGIN_MAXPROVIDER];
02699 ULONG
Count;
02700 ULONG Length;
02701 ULONG
Index;
02702 ULONG NumProviders;
02703 ULONG Disposition;
02704 HANDLE hProviderKey =
NULL;
02705 HANDLE hProviderIdKey =
NULL;
02706
USHORT ProviderLength;
02707
USHORT MachineType;
02708 BOOLEAN CanThunk;
02709 UNICODE_STRING
KeyName;
02710 UNICODE_STRING DllName;
02711 UNICODE_STRING ProviderName;
02712 ANSI_STRING ProcName;
02713 OBJECT_ATTRIBUTES Obja;
02714 PKEY_VALUE_PARTIAL_INFORMATION ValPartInfo;
02715 PKEY_FULL_INFORMATION KeyFullInfo;
02716 PKEY_BASIC_INFORMATION KeyBasicInfo;
02717 WCHAR ProviderPath[DOS_MAX_PATH_LENGTH];
02718 WCHAR DataBuffer[STATIC_UNICODE_BUFFER_LENGTH];
02719 WX86IDENTIFYPLUGIN IdentifyPlugin =
NULL;
02720 PIMAGE_NT_HEADERS NtHeaders;
02721
02722 NtHeaders =
RtlImageNtHeader(DllBase);
02723
if (NtHeaders ==
NULL) {
02724
return STATUS_INVALID_IMAGE_FORMAT;
02725 }
02726 MachineType = NtHeaders->FileHeader.Machine;
02727
02728
02729
02730
02731
Count = 0;
02732
RtlInitUnicodeString ( &KeyName, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Wx86\\Provider" );
02733 InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
02734 st =
NtOpenKey (&hProviderKey, KEY_READ | KEY_WRITE, &Obja);
02735
if (st == STATUS_OBJECT_NAME_NOT_FOUND) {
02736 st = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
02737
goto Wx86IdentifyDone;
02738 }
02739
if (
NT_ERROR(st)) {
02740
goto Wx86IdentifyDone;
02741 }
02742
02743 ValPartInfo = (PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer;
02744 KeyFullInfo = (PKEY_FULL_INFORMATION)DataBuffer;
02745 st =
NtQueryKey(hProviderKey,
02746 KeyFullInformation,
02747 KeyFullInfo,
02748
sizeof(DataBuffer),
02749 &Length
02750 );
02751
if (
NT_ERROR(st)) {
02752
goto Wx86IdentifyDone;
02753 }
02754
02755 NumProviders = KeyFullInfo->SubKeys;
02756
02757
02758
02759 ProviderName.Buffer = ProviderPath;
02760 ProviderName.MaximumLength =
sizeof(ProviderPath);
02761 ProviderName.Length = 0;
02762
RtlAppendUnicodeToString(&ProviderName, USER_SHARED_DATA->NtSystemRoot );
02763
if (
NT_SUCCESS(st)) {
02764 st =
RtlAppendUnicodeToString(&ProviderName, Wx86Dir);
02765 }
02766
if (
NT_SUCCESS(st)) {
02767 st =
RtlAppendUnicodeToString( &ProviderName, L
"\\Provider\\");
02768 }
02769
if (
NT_ERROR(st)) {
02770
goto Wx86IdentifyDone;
02771 }
02772 ProviderLength = ProviderName.Length;
02773
02774
Index = 0;
02775 st = STATUS_SUCCESS;
02776 KeyBasicInfo = (PKEY_BASIC_INFORMATION)DataBuffer;
02777
do {
02778 st =
NtEnumerateKey( hProviderKey, Index, KeyBasicInformation, DataBuffer,
sizeof(DataBuffer)-2, &Length );
02779
if (st == STATUS_NO_MORE_ENTRIES) {
02780 st = STATUS_SUCCESS;
02781
break;
02782 }
02783
if (
NT_ERROR(st)) {
02784
goto Wx86IdentifyDone;
02785 }
02786
02787
02788
02789 KeyBasicInfo->Name[KeyBasicInfo->NameLength/2] = UNICODE_NULL;
02790
RtlInitUnicodeString( &KeyName, KeyBasicInfo->Name );
02791 InitializeObjectAttributes (&Obja, &KeyName, OBJ_CASE_INSENSITIVE, hProviderKey, NULL );
02792 st =
NtOpenKey (&hProviderIdKey, KEY_READ, &Obja);
02793
if (st == STATUS_OBJECT_NAME_NOT_FOUND) {
02794
goto Wx86IdentifyDone;
02795 }
02796
02797
RtlInitUnicodeString ( &KeyName, L
"DllName" );
02798 st =
NtQueryValueKey( hProviderIdKey, &KeyName, KeyValuePartialInformation, DataBuffer,
sizeof(DataBuffer)-2, &Length );
02799
if (st == STATUS_SUCCESS) {
02800
02801
02802
02803 *(PWCHAR)(&ValPartInfo->Data[ValPartInfo->DataLength]) = UNICODE_NULL;
02804 ProviderName.Length = ProviderLength;
02805
if (
NT_SUCCESS(st)) {
02806 st =
RtlAppendUnicodeToString( &ProviderName, (PWSTR)ValPartInfo->Data);
02807 }
02808
if (
NT_ERROR(st)) {
02809
goto Wx86IdentifyDone;
02810 }
02811
02812
02813
02814
02815
02816
RtlInitUnicodeString ( &KeyName, L
"Export" );
02817 st =
NtQueryValueKey( hProviderIdKey, &KeyName, KeyValuePartialInformation, DataBuffer,
sizeof(DataBuffer)-2, &Length );
02818
if (st == STATUS_SUCCESS) {
02819 ANSI_STRING ExportName;
02820 UNICODE_STRING UnicodeExportName;
02821 PVOID ExportAddress;
02822
CHAR ExportNameBuffer[64];
02823
02824 ExportName.Buffer = ExportNameBuffer;
02825 ExportName.MaximumLength =
sizeof(ExportNameBuffer);
02826 ExportName.Length = 0;
02827
02828 *(PWCHAR)(&ValPartInfo->Data[ValPartInfo->DataLength]) = UNICODE_NULL;
02829
RtlInitUnicodeString( &UnicodeExportName, (PWCHAR)(ValPartInfo->Data) );
02830 st =
RtlUnicodeStringToAnsiString( &ExportName, &UnicodeExportName, FALSE );
02831
if (
NT_ERROR(st)) {
02832
goto Wx86IdentifyDone;
02833 }
02834 st =
LdrGetProcedureAddress( DllBase, &ExportName, 0, &ExportAddress );
02835
if (
NT_ERROR(st)) {
02836 st = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
02837
continue;
02838 }
02839 }
02840
02841
02842
02843
02844 st =
LdrpLoadDll( NULL, NULL, &ProviderName, &Provider[Count], TRUE );
02845
02846
if (
NT_SUCCESS(st)) {
02847
RtlInitAnsiString(&ProcName,
"Wx86IdentifyPlugin");
02848 st =
LdrGetProcedureAddress( Provider[Count], &ProcName, 0, (PVOID *)&IdentifyPlugin);
02849 CanThunk =
FALSE;
02850
if (
NT_SUCCESS(st) && IdentifyPlugin) {
02851
try {
02852 CanThunk = IdentifyPlugin(DllBase,
02853 FullDllName->Buffer,
02854 MachineType == IMAGE_FILE_MACHINE_I386
02855 );
02856 } except(EXCEPTION_EXECUTE_HANDLER) {
02857 }
02858 }
02859
02860
if (CanThunk) {
02861
Count++;
02862 }
else {
02863
LdrUnloadDll( Provider[Count] );
02864 Provider[
Count] =
NULL;
02865 }
02866 }
02867 }
02868 }
while ((++
Index < NumProviders) && (
Count < WX86PLUGIN_MAXPROVIDER));
02869
02870
02871
02872
02873
if (
Count) {
02874 PWX86PLUGIN Wx86Plugin;
02875
02876 Wx86Plugin =
RtlAllocateHeap(RtlProcessHeap(),
MAKE_TAG( LDR_TAG ),
sizeof(WX86PLUGIN));
02877
if ( !Wx86Plugin ) {
02878 st = STATUS_NO_MEMORY;
02879
goto Wx86IdentifyDone;
02880 }
02881 Wx86Plugin->DllBase = DllBase;
02882 Wx86Plugin->Count =
Count;
02883 RtlMoveMemory( Wx86Plugin->Provider, Provider, Count*
sizeof(PVOID) );
02884 InsertTailList( &Wx86PluginList, &Wx86Plugin->Links );
02885
02886 st = STATUS_SUCCESS;
02887 }
else {
02888 st = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
02889 }
02890 st =
Count? STATUS_SUCCESS : STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
02891
02892 Wx86IdentifyDone:
02893
02894
02895
02896
if (
NT_ERROR(st)) {
02897
for (
Index = 0;
Index <
Count;
Index++) {
02898
LdrUnloadDll( Provider[Count] );
02899 }
02900 }
02901
02902
if (hProviderKey) {
02903
NtClose(hProviderKey);
02904 }
02905
if (hProviderIdKey) {
02906
NtClose(hProviderIdKey);
02907 }
02908
02909
return st;
02910 }
02911
02912
NTSTATUS
02913 Wx86ThunkPluginExport(
02914 IN PVOID DllBase,
02915 IN PCHAR ExportName,
02916 IN ULONG Ordinal,
02917 IN PVOID ExportAddress,
02918 OUT PVOID *ExportThunk
02919 )
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941 {
02942 PLIST_ENTRY Head, Next;
02943 PWX86PLUGIN Wx86Plugin;
02944 ULONG
Index;
02945 WX86THUNKEXPORT ThunkExport;
02946 ANSI_STRING ProcName;
02947 PIMAGE_NT_HEADERS NtHeaders;
02948
USHORT MachineType;
02949 BOOLEAN Thunked;
02950
NTSTATUS st;
02951
02952 NtHeaders =
RtlImageNtHeader(DllBase);
02953
if (NtHeaders ==
NULL) {
02954
return STATUS_INVALID_IMAGE_FORMAT;
02955 }
02956 MachineType = NtHeaders->FileHeader.Machine;
02957
02958
02959
02960 Head = &Wx86PluginList;
02961 Next = Head->Flink;
02962
while ( Next != Head ) {
02963 Wx86Plugin = CONTAINING_RECORD(Next, WX86PLUGIN, Links);
02964
if (Wx86Plugin->DllBase == DllBase) {
02965
break;
02966 }
02967 Next = Next->Flink;
02968 }
02969
02970
02971
02972
if (Next == Head) {
02973
return STATUS_PROCEDURE_NOT_FOUND;
02974 }
02975
02976
02977
02978
RtlInitAnsiString(&ProcName,
"Wx86ThunkExport");
02979
for (
Index = 0;
Index < Wx86Plugin->Count;
Index++) {
02980 st =
LdrGetProcedureAddress(Wx86Plugin->Provider[Index],
02981 &ProcName,
02982 0,
02983 (PVOID *)&ThunkExport
02984 );
02985
if (
NT_SUCCESS(st) && ThunkExport !=
NULL) {
02986
try {
02987 Thunked = ThunkExport(DllBase,
02988 ExportName,
02989 Ordinal,
02990 ExportAddress,
02991 ExportThunk,
02992 MachineType == IMAGE_FILE_MACHINE_I386
02993 );
02994 } except (EXCEPTION_EXECUTE_HANDLER) {
02995 Thunked =
FALSE;
02996 }
02997
02998
if (Thunked) {
02999
if (
ShowSnaps) {
03000
DbgPrint(
"LDRWx86: thunk export for %08X Ord=%04X Addr=%08X Name=%s Thunk=%08X\n",
03001 DllBase, Ordinal, ExportAddress,
03002 ExportName? ExportName :
"<noname>", *ExportThunk );
03003
break;
03004 }
03005 }
03006 }
03007 }
03008
03009
return st;
03010 }
03011
03012 BOOLEAN
03013 Wx86UnloadProviders(
03014 IN PVOID DllBase
03015 )
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030 {
03031 PLDR_DATA_TABLE_ENTRY PluginEntry;
03032
NTSTATUS Status = STATUS_SUCCESS;
03033 PLIST_ENTRY Head, Next;
03034 PWX86PLUGIN Wx86Plugin;
03035 ULONG
Index;
03036
03037
03038
03039
03040
if (Wx86ProviderUnloadCount == 0) {
03041
try {
03042 Wx86ProviderUnloadCount++;
03043
03044
03045
03046 Head = &Wx86PluginList;
03047 Next = Head->Flink;
03048
while ( Next != Head ) {
03049 Wx86Plugin = CONTAINING_RECORD(Next, WX86PLUGIN, Links);
03050
if (Wx86Plugin->DllBase == DllBase) {
03051
03052
03053
03054
03055
if (!
LdrpCheckForLoadedDllHandle( DllBase, &PluginEntry )) {
03056
for (
Index = 0;
Index < Wx86Plugin->Count;
Index++) {
03057
Status =
LdrUnloadDll( Wx86Plugin->Provider[Index] );
03058 }
03059 RemoveEntryList( &Wx86Plugin->Links );
03060
RtlFreeHeap(RtlProcessHeap(), 0, Wx86Plugin );
03061
break;
03062 }
03063 }
03064 Next = Next->Flink;
03065 }
03066 } finally {
03067 Wx86ProviderUnloadCount--;
03068 }
03069 }
03070
03071
return NT_SUCCESS(Status);
03072 }
03073
03074
#endif