00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "ntrtlp.h"
00022
00023
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
00024
#pragma alloc_text(PAGE,LdrAccessResource)
00025
#pragma alloc_text(PAGE,LdrpAccessResourceData)
00026
#pragma alloc_text(PAGE,LdrFindEntryForAddress)
00027
#pragma alloc_text(PAGE,LdrFindResource_U)
00028
#pragma alloc_text(PAGE,LdrFindResourceDirectory_U)
00029
#pragma alloc_text(PAGE,LdrpCompareResourceNames_U)
00030
#pragma alloc_text(PAGE,LdrpSearchResourceSection_U)
00031
#pragma alloc_text(PAGE,LdrEnumResources)
00032
#endif
00033
00034
#ifndef NTOS_KERNEL_RUNTIME
00035
00036 PALT_RESOURCE_MODULE AlternateResourceModules;
00037 ULONG
AlternateResourceModuleCount;
00038 ULONG
AltResMemBlockCount;
00039 LANGID
UILangId,
InstallLangId;
00040
00041 #define MEMBLOCKSIZE 16
00042 #define RESMODSIZE sizeof(ALT_RESOURCE_MODULE)
00043
00044
#endif
00045
00046
NTSTATUS
00047 LdrAccessResource(
00048 IN PVOID DllHandle,
00049 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
00050 OUT PVOID *Address OPTIONAL,
00051 OUT PULONG Size OPTIONAL
00052 )
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 {
00084
RTL_PAGED_CODE();
00085
00086
return LdrpAccessResourceData(
00087 DllHandle,
00088 ResourceDataEntry,
00089 Address,
00090
Size
00091 );
00092 }
00093
00094
00095
NTSTATUS
00096 LdrpAccessResourceData(
00097 IN PVOID DllHandle,
00098 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
00099 OUT PVOID *Address OPTIONAL,
00100 OUT PULONG Size OPTIONAL
00101 )
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 {
00134 PIMAGE_RESOURCE_DIRECTORY ResourceDirectory;
00135 ULONG ResourceSize;
00136 PIMAGE_NT_HEADERS NtHeaders;
00137 ULONG_PTR VirtualAddressOffset;
00138 PIMAGE_SECTION_HEADER NtSection;
00139
00140
RTL_PAGED_CODE();
00141
00142
#ifndef NTOS_KERNEL_RUNTIME
00143
ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
00144
RtlImageDirectoryEntryToData(DllHandle,
00145
TRUE,
00146 IMAGE_DIRECTORY_ENTRY_RESOURCE,
00147 &ResourceSize
00148 );
00149
if (!ResourceDirectory) {
00150
return( STATUS_RESOURCE_DATA_NOT_FOUND );
00151 }
00152
00153
if ((ULONG_PTR)ResourceDataEntry < (ULONG_PTR) ResourceDirectory ){
00154 DllHandle =
LdrLoadAlternateResourceModule (DllHandle,
NULL);
00155 }
else{
00156 NtHeaders =
RtlImageNtHeader(
00157 (PVOID)((ULONG_PTR)DllHandle & ~0x00000001)
00158 );
00159
if (NtHeaders) {
00160
00161
00162
00163 ULONG_PTR ImageStart = (ULONG_PTR)DllHandle & ~0x00000001;
00164 SIZE_T ImageSize = 0;
00165
00166
if ((ULONG_PTR)DllHandle & 0x00000001) {
00167
00168
NTSTATUS Status;
00169 MEMORY_BASIC_INFORMATION MemInfo;
00170
00171
Status =
NtQueryVirtualMemory(
00172 NtCurrentProcess(),
00173 (PVOID) ImageStart,
00174 MemoryBasicInformation,
00175 (PVOID)&MemInfo,
00176
sizeof(MemInfo),
00177
NULL
00178 );
00179
00180
if ( !
NT_SUCCESS(
Status) ) {
00181 ImageSize = 0;
00182 }
else {
00183 ImageSize = MemInfo.RegionSize;
00184 }
00185 }
else {
00186 ImageSize = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.SizeOfImage;
00187 }
00188
00189
if (!(((ULONG_PTR)ResourceDataEntry >= ImageStart) && ((ULONG_PTR)ResourceDataEntry < (ImageStart + ImageSize)))) {
00190
00191 DllHandle =
LdrLoadAlternateResourceModule (DllHandle,
NULL);
00192 }
00193 }
00194 }
00195
00196
if (!DllHandle){
00197
return ( STATUS_RESOURCE_DATA_NOT_FOUND );
00198 }
00199
00200
#endif
00201
try {
00202 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
00203
RtlImageDirectoryEntryToData(DllHandle,
00204
TRUE,
00205 IMAGE_DIRECTORY_ENTRY_RESOURCE,
00206 &ResourceSize
00207 );
00208
if (!ResourceDirectory) {
00209
return( STATUS_RESOURCE_DATA_NOT_FOUND );
00210 }
00211
00212
if ((ULONG_PTR)DllHandle & 0x00000001) {
00213 ULONG ResourceRVA;
00214 DllHandle = (PVOID)((ULONG_PTR)DllHandle & ~0x00000001);
00215 NtHeaders =
RtlImageNtHeader( DllHandle );
00216
if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
00217 ResourceRVA=((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_RESOURCE ].VirtualAddress;
00218 }
else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
00219 ResourceRVA=((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_RESOURCE ].VirtualAddress;
00220 }
else {
00221 ResourceRVA = 0;
00222 }
00223
00224
if (!ResourceRVA) {
00225
return( STATUS_RESOURCE_DATA_NOT_FOUND );
00226 }
00227
00228 VirtualAddressOffset = (ULONG_PTR)DllHandle + ResourceRVA - (ULONG_PTR)ResourceDirectory;
00229
00230
00231
00232
00233
00234
00235
00236 NtSection=
RtlSectionTableFromVirtualAddress( NtHeaders, DllHandle, ResourceRVA);
00237
00238
if (!NtSection) {
00239
return( STATUS_RESOURCE_DATA_NOT_FOUND );
00240 }
00241
00242
if ( ResourceDataEntry->OffsetToData > NtSection->Misc.VirtualSize ) {
00243 ULONG rva;
00244
00245 rva = NtSection->VirtualAddress;
00246 NtSection=
RtlSectionTableFromVirtualAddress(NtHeaders,
00247 DllHandle,
00248 ResourceDataEntry->OffsetToData
00249 );
00250 VirtualAddressOffset +=
00251 ((ULONG_PTR)NtSection->VirtualAddress - rva) -
00252 ((ULONG_PTR)
RtlAddressInSectionTable ( NtHeaders, DllHandle, NtSection->VirtualAddress ) - (ULONG_PTR)ResourceDirectory);
00253 }
00254 }
00255
else {
00256 VirtualAddressOffset = 0;
00257 }
00258
00259
if (ARGUMENT_PRESENT( Address )) {
00260 *Address = (PVOID)( (PCHAR)DllHandle +
00261 (ResourceDataEntry->OffsetToData - VirtualAddressOffset)
00262 );
00263 }
00264
00265
if (ARGUMENT_PRESENT(
Size )) {
00266 *
Size = ResourceDataEntry->Size;
00267 }
00268 }
00269 except (
EXCEPTION_EXECUTE_HANDLER) {
00270
return GetExceptionCode();
00271 }
00272
00273
return( STATUS_SUCCESS );
00274 }
00275
00276
00277
NTSTATUS
00278 LdrFindEntryForAddress(
00279 IN PVOID Address,
00280 OUT PLDR_DATA_TABLE_ENTRY *TableEntry
00281 )
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 {
00303 PPEB_LDR_DATA Ldr;
00304 PLIST_ENTRY Head, Next;
00305 PLDR_DATA_TABLE_ENTRY Entry;
00306 PIMAGE_NT_HEADERS NtHeaders;
00307 PVOID ImageBase;
00308 PVOID EndOfImage;
00309
00310 Ldr = NtCurrentPeb()->Ldr;
00311
if (Ldr ==
NULL) {
00312
return( STATUS_NO_MORE_ENTRIES );
00313 }
00314
00315 Head = &Ldr->InMemoryOrderModuleList;
00316 Next = Head->Flink;
00317
while ( Next != Head ) {
00318 Entry = CONTAINING_RECORD( Next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );
00319
00320 NtHeaders =
RtlImageNtHeader( Entry->DllBase );
00321
if (NtHeaders !=
NULL) {
00322 ImageBase = (PVOID)Entry->DllBase;
00323
00324 EndOfImage = (PVOID)
00325 ((ULONG_PTR)ImageBase + NtHeaders->OptionalHeader.SizeOfImage);
00326
00327
if ((ULONG_PTR)Address >= (ULONG_PTR)ImageBase && (ULONG_PTR)Address < (ULONG_PTR)EndOfImage) {
00328 *TableEntry = Entry;
00329
return( STATUS_SUCCESS );
00330 }
00331 }
00332
00333 Next = Next->Flink;
00334 }
00335
00336
return( STATUS_NO_MORE_ENTRIES );
00337 }
00338
00339
00340
NTSTATUS
00341 LdrFindResource_U(
00342 IN PVOID DllHandle,
00343 IN PULONG_PTR ResourceIdPath,
00344 IN ULONG ResourceIdPathLength,
00345 OUT PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry
00346 )
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 {
00382
RTL_PAGED_CODE();
00383
00384
return LdrpSearchResourceSection_U(
00385 DllHandle,
00386 ResourceIdPath,
00387 ResourceIdPathLength,
00388
FALSE,
00389
FALSE,
00390 (PVOID *)ResourceDataEntry
00391 );
00392 }
00393
00394
00395
NTSTATUS
00396 LdrFindResourceDirectory_U(
00397 IN PVOID DllHandle,
00398 IN PULONG_PTR ResourceIdPath,
00399 IN ULONG ResourceIdPathLength,
00400 OUT PIMAGE_RESOURCE_DIRECTORY *ResourceDirectory
00401 )
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 {
00437
RTL_PAGED_CODE();
00438
00439
return LdrpSearchResourceSection_U(
00440 DllHandle,
00441 ResourceIdPath,
00442 ResourceIdPathLength,
00443
TRUE,
00444
FALSE,
00445 (PVOID *)ResourceDirectory
00446 );
00447 }
00448
00449
00450 LONG
00451 LdrpCompareResourceNames_U(
00452 IN ULONG_PTR ResourceName,
00453 IN PIMAGE_RESOURCE_DIRECTORY ResourceDirectory,
00454 IN PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry
00455 )
00456 {
00457 LONG li;
00458 PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
00459
00460
if (ResourceName & LDR_RESOURCE_ID_NAME_MASK) {
00461
if (!ResourceDirectoryEntry->NameIsString) {
00462
return( -1 );
00463 }
00464
00465 ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
00466 ((PCHAR)ResourceDirectory + ResourceDirectoryEntry->NameOffset);
00467
00468 li = wcsncmp( (LPWSTR)ResourceName,
00469 ResourceNameString->NameString,
00470 ResourceNameString->Length
00471 );
00472
00473
if (!li && wcslen((PWSTR)ResourceName) != ResourceNameString->Length) {
00474
return( 1 );
00475 }
00476
00477
return(li);
00478 }
00479
else {
00480
if (ResourceDirectoryEntry->NameIsString) {
00481
return( 1 );
00482 }
00483
00484
return( (ULONG)(ResourceName - ResourceDirectoryEntry->Name) );
00485 }
00486 }
00487
00488
00489 #define USE_FIRSTAVAILABLE_LANGID (0xFFFFFFFF & ~LDR_RESOURCE_ID_NAME_MASK)
00490
00491
NTSTATUS
00492 LdrpSearchResourceSection_U(
00493 IN PVOID DllHandle,
00494 IN PULONG_PTR ResourceIdPath,
00495 IN ULONG ResourceIdPathLength,
00496 IN BOOLEAN FindDirectoryEntry,
00497 IN BOOLEAN ExactLangMatchOnly,
00498 OUT PVOID *ResourceDirectoryOrData
00499 )
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 {
00544
NTSTATUS Status;
00545 PIMAGE_RESOURCE_DIRECTORY LanguageResourceDirectory, ResourceDirectory, TopResourceDirectory;
00546 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntLow;
00547 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntMiddle;
00548 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntHigh;
00549 PIMAGE_RESOURCE_DATA_ENTRY ResourceEntry;
00550
USHORT n, half;
00551 LONG
dir;
00552 ULONG size;
00553 ULONG_PTR ResourceIdRetry;
00554 ULONG RetryCount;
00555 LANGID NewLangId;
00556 PULONG_PTR IdPath = ResourceIdPath;
00557 ULONG IdPathLength = ResourceIdPathLength;
00558 BOOLEAN fIsNeutral =
FALSE;
00559 LANGID GivenLanguage;
00560
#ifndef NTOS_KERNEL_RUNTIME
00561
LCID DefaultThreadLocale, DefaultSystemLocale;
00562 PVOID AltResourceDllHandle =
NULL;
00563 ULONG_PTR UIResourceIdPath[3];
00564
#endif
00565
00566
RTL_PAGED_CODE();
00567
00568
try {
00569 TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
00570
RtlImageDirectoryEntryToData(DllHandle,
00571
TRUE,
00572 IMAGE_DIRECTORY_ENTRY_RESOURCE,
00573 &size
00574 );
00575
if (!TopResourceDirectory) {
00576
return( STATUS_RESOURCE_DATA_NOT_FOUND );
00577 }
00578
00579 ResourceDirectory = TopResourceDirectory;
00580 ResourceIdRetry =
USE_FIRSTAVAILABLE_LANGID;
00581 RetryCount = 0;
00582 ResourceEntry =
NULL;
00583 LanguageResourceDirectory =
NULL;
00584
while (ResourceDirectory !=
NULL && ResourceIdPathLength--) {
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
if (ResourceIdPathLength == 0 && IdPathLength == 3) {
00609 LanguageResourceDirectory = ResourceDirectory;
00610 }
00611
00612
if (LanguageResourceDirectory !=
NULL) {
00613 GivenLanguage = (LANGID)IdPath[ 2 ];
00614 fIsNeutral = (PRIMARYLANGID( GivenLanguage ) == LANG_NEUTRAL);
00615 TryNextLangId:
00616
switch( RetryCount++ ) {
00617
#ifdef NTOS_KERNEL_RUNTIME
00618
case 0:
00619 NewLangId = GivenLanguage;
00620
break;
00621
00622
case 1:
00623 NewLangId = PRIMARYLANGID( GivenLanguage );
00624
break;
00625
00626
case 2:
00627 NewLangId = 0;
00628
break;
00629
00630
case 3:
00631 NewLangId = (LANGID)ResourceIdRetry;
00632
break;
00633
00634
case 4:
00635
if ( !fIsNeutral ) {
00636
00637
goto ReturnFailure;
00638
break;
00639 }
00640 NewLangId =
PsInstallUILanguageId;
00641
break;
00642
00643
case 5:
00644 NewLangId = LANGIDFROMLCID(
PsDefaultSystemLocaleId);
00645
break;
00646
00647
case 6:
00648
00649 NewLangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
00650
break;
00651
00652
case 7:
00653 NewLangId =
USE_FIRSTAVAILABLE_LANGID;
00654
break;
00655
00656
#else
00657
case 0:
00658 NewLangId = GivenLanguage;
00659
break;
00660
00661
case 1:
00662
if ( ExactLangMatchOnly) {
00663
00664
00665
00666
00667
goto ReturnFailure;
00668 }
00669 NewLangId = PRIMARYLANGID( GivenLanguage );
00670
break;
00671
00672
case 2:
00673 NewLangId = 0;
00674
break;
00675
00676
case 3:
00677
00678
if (!
UILangId){
00679
Status =
NtQueryDefaultUILanguage( &
UILangId );
00680
if (!
NT_SUCCESS(
Status )) {
00681
00682
00683
00684 NewLangId = (LANGID)ResourceIdRetry;
00685
break;
00686 }
00687 }
00688 NewLangId =
UILangId;
00689
00690
00691
00692
00693
00694
if( !fIsNeutral &&
00695 ((PRIMARYLANGID (GivenLanguage) == LANG_ARABIC) || (PRIMARYLANGID (GivenLanguage) == LANG_HEBREW)) &&
00696 (PRIMARYLANGID (GivenLanguage) == PRIMARYLANGID (NewLangId))
00697 ) {
00698 NewLangId = GivenLanguage;
00699 }
00700
00701
if (fIsNeutral || GivenLanguage == NewLangId){
00702
00703
00704
00705 AltResourceDllHandle=
LdrLoadAlternateResourceModule(
00706 DllHandle,
00707
NULL);
00708
00709
if (!AltResourceDllHandle){
00710
00711
00712
00713
00714 NewLangId = (LANGID)ResourceIdRetry;
00715
break;
00716
00717 }
00718
00719
00720
00721
00722
00723
00724 UIResourceIdPath[0]=IdPath[0];
00725 UIResourceIdPath[1]=IdPath[1];
00726 UIResourceIdPath[2]=NewLangId;
00727
00728
Status =
LdrpSearchResourceSection_U(
00729 AltResourceDllHandle,
00730 UIResourceIdPath,
00731 3,
00732 FindDirectoryEntry,
00733
TRUE,
00734 (PVOID *)ResourceDirectoryOrData
00735 );
00736
00737
if (
NT_SUCCESS(
Status)){
00738
00739
00740
00741
00742
return Status;
00743 }
00744
00745
00746 }
00747
00748
00749
00750
00751 NewLangId = (LANGID)ResourceIdRetry;
00752
break;
00753
00754
00755
case 4:
00756
if ( !fIsNeutral ) {
00757
00758
goto ReturnFailure;
00759
break;
00760 }
00761
00762
00763
00764
00765
00766
if (NtCurrentTeb()){
00767
Status =
NtQueryDefaultLocale(
00768
TRUE,
00769 &DefaultThreadLocale
00770 );
00771
if (
NT_SUCCESS(
Status ) &&
00772 DefaultThreadLocale !=
00773 NtCurrentTeb()->CurrentLocale) {
00774
00775
00776
00777
00778 NewLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale);
00779
break;
00780 }
00781 }
00782
00783 NewLangId = (LANGID)ResourceIdRetry;
00784
break;
00785
00786
00787
case 5:
00788
00789
if (!
UILangId){
00790 NewLangId = (LANGID)ResourceIdRetry;
00791 }
else {
00792 NewLangId =
UILangId;
00793 }
00794
break;
00795
00796
case 6:
00797
00798
if (!
UILangId){
00799 NewLangId = (LANGID)ResourceIdRetry;
00800 }
else {
00801 NewLangId = PRIMARYLANGID( (LANGID)
UILangId );
00802 }
00803
break;
00804
00805
case 7:
00806
00807
00808
00809
00810
if (!
InstallLangId){
00811
Status =
NtQueryInstallUILanguage(&
InstallLangId);
00812
if (!
NT_SUCCESS(
Status )) {
00813
00814
00815
00816 NewLangId = (LANGID)ResourceIdRetry;
00817
break;
00818
00819 }
00820 }
00821
00822 NewLangId =
InstallLangId;
00823
break;
00824
00825
case 8:
00826
if (SUBLANGID( GivenLanguage ) == SUBLANG_SYS_DEFAULT) {
00827
00828 DefaultThreadLocale = 0;
00829 RetryCount += 2;
00830
break;
00831 }
00832
00833
if (NtCurrentTeb() !=
NULL) {
00834 NewLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale);
00835 }
00836
break;
00837
00838
case 9:
00839
Status =
NtQueryDefaultLocale(
TRUE, &DefaultThreadLocale );
00840
if (
NT_SUCCESS(
Status )) {
00841 NewLangId = LANGIDFROMLCID(DefaultThreadLocale);
00842
break;
00843 }
00844
00845 RetryCount++;
00846
break;
00847
00848
case 10:
00849 NewLangId = PRIMARYLANGID( (LANGID)ResourceIdRetry );
00850
break;
00851
00852
case 11:
00853
Status =
NtQueryDefaultLocale(
FALSE, &DefaultSystemLocale );
00854
if (!
NT_SUCCESS(
Status )) {
00855 RetryCount++;
00856
break;
00857 }
00858
if (DefaultSystemLocale != DefaultThreadLocale) {
00859 NewLangId = LANGIDFROMLCID(DefaultSystemLocale);
00860
break;
00861 }
00862
00863 RetryCount += 2;
00864
00865
00866
case 13:
00867 NewLangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
00868
break;
00869
00870
case 12:
00871 NewLangId = PRIMARYLANGID( (LANGID)ResourceIdRetry );
00872
break;
00873
00874
case 14:
00875 NewLangId =
USE_FIRSTAVAILABLE_LANGID;
00876
break;
00877
#endif
00878
default:
00879
goto ReturnFailure;
00880
break;
00881 }
00882
00883
00884
00885
00886
00887
if (NewLangId !=
USE_FIRSTAVAILABLE_LANGID &&
00888 NewLangId == ResourceIdRetry
00889 ) {
00890
goto TryNextLangId;
00891 }
00892
00893
00894
00895
00896 ResourceIdRetry = (ULONG_PTR)NewLangId;
00897 ResourceIdPath = &ResourceIdRetry;
00898 ResourceDirectory = LanguageResourceDirectory;
00899 }
00900
00901
n = ResourceDirectory->NumberOfNamedEntries;
00902 ResourceDirEntLow = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
00903
if (!(*ResourceIdPath & LDR_RESOURCE_ID_NAME_MASK)) {
00904 ResourceDirEntLow +=
n;
00905
n = ResourceDirectory->NumberOfIdEntries;
00906 }
00907
00908
if (!
n) {
00909 ResourceDirectory =
NULL;
00910
goto NotFound;
00911 }
00912
00913
if (LanguageResourceDirectory !=
NULL &&
00914 *ResourceIdPath ==
USE_FIRSTAVAILABLE_LANGID
00915 ) {
00916 ResourceDirectory =
NULL;
00917 ResourceIdRetry = ResourceDirEntLow->Name;
00918 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY)
00919 ((PCHAR)TopResourceDirectory +
00920 ResourceDirEntLow->OffsetToData
00921 );
00922
00923
break;
00924 }
00925
00926 ResourceDirectory =
NULL;
00927 ResourceDirEntHigh = ResourceDirEntLow +
n - 1;
00928
while (ResourceDirEntLow <= ResourceDirEntHigh) {
00929
if ((half = (
n >> 1)) != 0) {
00930 ResourceDirEntMiddle = ResourceDirEntLow;
00931
if (*(PUCHAR)&
n & 1) {
00932 ResourceDirEntMiddle += half;
00933 }
00934
else {
00935 ResourceDirEntMiddle += half - 1;
00936 }
00937
dir =
LdrpCompareResourceNames_U( *ResourceIdPath,
00938 TopResourceDirectory,
00939 ResourceDirEntMiddle
00940 );
00941
if (!
dir) {
00942
if (ResourceDirEntMiddle->DataIsDirectory) {
00943 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
00944 ((PCHAR)TopResourceDirectory +
00945 ResourceDirEntMiddle->OffsetToDirectory
00946 );
00947 }
00948
else {
00949 ResourceDirectory =
NULL;
00950 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY)
00951 ((PCHAR)TopResourceDirectory +
00952 ResourceDirEntMiddle->OffsetToData
00953 );
00954 }
00955
00956
break;
00957 }
00958
else {
00959
if (
dir < 0) {
00960 ResourceDirEntHigh = ResourceDirEntMiddle - 1;
00961
if (*(PUCHAR)&
n & 1) {
00962
n = half;
00963 }
00964
else {
00965
n = half - 1;
00966 }
00967 }
00968
else {
00969 ResourceDirEntLow = ResourceDirEntMiddle + 1;
00970
n = half;
00971 }
00972 }
00973 }
00974
else {
00975
if (
n != 0) {
00976
dir =
LdrpCompareResourceNames_U( *ResourceIdPath,
00977 TopResourceDirectory,
00978 ResourceDirEntLow
00979 );
00980
if (!
dir) {
00981
if (ResourceDirEntLow->DataIsDirectory) {
00982 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
00983 ((PCHAR)TopResourceDirectory +
00984 ResourceDirEntLow->OffsetToDirectory
00985 );
00986 }
00987
else {
00988 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY)
00989 ((PCHAR)TopResourceDirectory +
00990 ResourceDirEntLow->OffsetToData
00991 );
00992 }
00993 }
00994 }
00995
00996
break;
00997 }
00998 }
00999
01000 ResourceIdPath++;
01001 }
01002
01003
if (ResourceEntry !=
NULL && !FindDirectoryEntry) {
01004 *ResourceDirectoryOrData = (PVOID)ResourceEntry;
01005
Status = STATUS_SUCCESS;
01006 }
01007
else
01008
if (ResourceDirectory !=
NULL && FindDirectoryEntry) {
01009 *ResourceDirectoryOrData = (PVOID)ResourceDirectory;
01010
Status = STATUS_SUCCESS;
01011 }
01012
else {
01013 NotFound:
01014
switch( IdPathLength - ResourceIdPathLength) {
01015
case 3:
Status = STATUS_RESOURCE_LANG_NOT_FOUND;
break;
01016
case 2:
Status = STATUS_RESOURCE_NAME_NOT_FOUND;
break;
01017
case 1:
Status = STATUS_RESOURCE_TYPE_NOT_FOUND;
break;
01018
default:
Status = STATUS_INVALID_PARAMETER;
break;
01019 }
01020 }
01021
01022
if (
Status == STATUS_RESOURCE_LANG_NOT_FOUND &&
01023 LanguageResourceDirectory !=
NULL
01024 ) {
01025 ResourceEntry =
NULL;
01026
goto TryNextLangId;
01027 ReturnFailure: ;
01028
Status = STATUS_RESOURCE_LANG_NOT_FOUND;
01029 }
01030 }
01031 except (
EXCEPTION_EXECUTE_HANDLER) {
01032
Status = GetExceptionCode();
01033 }
01034
01035
return Status;
01036 }
01037
01038
NTSTATUS
01039 LdrEnumResources(
01040 IN PVOID DllHandle,
01041 IN PULONG_PTR ResourceIdPath,
01042 IN ULONG ResourceIdPathLength,
01043 IN OUT PULONG NumberOfResources,
01044 OUT PLDR_ENUM_RESOURCE_ENTRY Resources OPTIONAL
01045 )
01046 {
01047
NTSTATUS Status;
01048 PIMAGE_RESOURCE_DIRECTORY TopResourceDirectory;
01049 PIMAGE_RESOURCE_DIRECTORY TypeResourceDirectory;
01050 PIMAGE_RESOURCE_DIRECTORY NameResourceDirectory;
01051 PIMAGE_RESOURCE_DIRECTORY LangResourceDirectory;
01052 PIMAGE_RESOURCE_DIRECTORY_ENTRY TypeResourceDirectoryEntry;
01053 PIMAGE_RESOURCE_DIRECTORY_ENTRY NameResourceDirectoryEntry;
01054 PIMAGE_RESOURCE_DIRECTORY_ENTRY LangResourceDirectoryEntry;
01055 ULONG TypeDirectoryIndex, NumberOfTypeDirectoryEntries;
01056 ULONG NameDirectoryIndex, NumberOfNameDirectoryEntries;
01057 ULONG LangDirectoryIndex, NumberOfLangDirectoryEntries;
01058 BOOLEAN ScanTypeDirectory;
01059 BOOLEAN ScanNameDirectory;
01060 BOOLEAN ReturnThisResource;
01061 PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
01062 ULONG_PTR TypeResourceNameOrId;
01063 ULONG_PTR NameResourceNameOrId;
01064 ULONG_PTR LangResourceNameOrId;
01065 PLDR_ENUM_RESOURCE_ENTRY ResourceInfo;
01066 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
01067 ULONG ResourceIndex, MaxResourceIndex;
01068 ULONG
Size;
01069
01070 ResourceIndex = 0;
01071
if (!ARGUMENT_PRESENT( Resources )) {
01072 MaxResourceIndex = 0;
01073 }
01074
else {
01075 MaxResourceIndex = *NumberOfResources;
01076 }
01077 *NumberOfResources = 0;
01078
01079 TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
01080
RtlImageDirectoryEntryToData( DllHandle,
01081
TRUE,
01082 IMAGE_DIRECTORY_ENTRY_RESOURCE,
01083 &
Size
01084 );
01085
if (!TopResourceDirectory) {
01086
return STATUS_RESOURCE_DATA_NOT_FOUND;
01087 }
01088
01089 TypeResourceDirectory = TopResourceDirectory;
01090 TypeResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(TypeResourceDirectory+1);
01091 NumberOfTypeDirectoryEntries = TypeResourceDirectory->NumberOfNamedEntries +
01092 TypeResourceDirectory->NumberOfIdEntries;
01093 TypeDirectoryIndex = 0;
01094
Status = STATUS_SUCCESS;
01095
for (TypeDirectoryIndex=0;
01096 TypeDirectoryIndex<NumberOfTypeDirectoryEntries;
01097 TypeDirectoryIndex++, TypeResourceDirectoryEntry++
01098 ) {
01099
if (ResourceIdPathLength > 0) {
01100 ScanTypeDirectory =
LdrpCompareResourceNames_U( ResourceIdPath[ 0 ],
01101 TopResourceDirectory,
01102 TypeResourceDirectoryEntry
01103 ) == 0;
01104 }
01105
else {
01106 ScanTypeDirectory =
TRUE;
01107 }
01108
if (ScanTypeDirectory) {
01109
if (!TypeResourceDirectoryEntry->DataIsDirectory) {
01110
return STATUS_INVALID_IMAGE_FORMAT;
01111 }
01112
if (TypeResourceDirectoryEntry->NameIsString) {
01113 ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
01114 ((PCHAR)TopResourceDirectory + TypeResourceDirectoryEntry->NameOffset);
01115
01116 TypeResourceNameOrId = (ULONG_PTR)ResourceNameString;
01117 }
01118
else {
01119 TypeResourceNameOrId = (ULONG_PTR)TypeResourceDirectoryEntry->Id;
01120 }
01121
01122 NameResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
01123 ((PCHAR)TopResourceDirectory + TypeResourceDirectoryEntry->OffsetToDirectory);
01124 NameResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(NameResourceDirectory+1);
01125 NumberOfNameDirectoryEntries = NameResourceDirectory->NumberOfNamedEntries +
01126 NameResourceDirectory->NumberOfIdEntries;
01127 NameDirectoryIndex = 0;
01128
for (NameDirectoryIndex=0;
01129 NameDirectoryIndex<NumberOfNameDirectoryEntries;
01130 NameDirectoryIndex++, NameResourceDirectoryEntry++
01131 ) {
01132
if (ResourceIdPathLength > 1) {
01133 ScanNameDirectory =
LdrpCompareResourceNames_U( ResourceIdPath[ 1 ],
01134 TopResourceDirectory,
01135 NameResourceDirectoryEntry
01136 ) == 0;
01137 }
01138
else {
01139 ScanNameDirectory =
TRUE;
01140 }
01141
if (ScanNameDirectory) {
01142
if (!NameResourceDirectoryEntry->DataIsDirectory) {
01143
return STATUS_INVALID_IMAGE_FORMAT;
01144 }
01145
01146
if (NameResourceDirectoryEntry->NameIsString) {
01147 ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
01148 ((PCHAR)TopResourceDirectory + NameResourceDirectoryEntry->NameOffset);
01149
01150 NameResourceNameOrId = (ULONG_PTR)ResourceNameString;
01151 }
01152
else {
01153 NameResourceNameOrId = (ULONG_PTR)NameResourceDirectoryEntry->Id;
01154 }
01155
01156 LangResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
01157 ((PCHAR)TopResourceDirectory + NameResourceDirectoryEntry->OffsetToDirectory);
01158
01159 LangResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(LangResourceDirectory+1);
01160 NumberOfLangDirectoryEntries = LangResourceDirectory->NumberOfNamedEntries +
01161 LangResourceDirectory->NumberOfIdEntries;
01162 LangDirectoryIndex = 0;
01163
for (LangDirectoryIndex=0;
01164 LangDirectoryIndex<NumberOfLangDirectoryEntries;
01165 LangDirectoryIndex++, LangResourceDirectoryEntry++
01166 ) {
01167
if (ResourceIdPathLength > 2) {
01168 ReturnThisResource =
LdrpCompareResourceNames_U( ResourceIdPath[ 2 ],
01169 TopResourceDirectory,
01170 LangResourceDirectoryEntry
01171 ) == 0;
01172 }
01173
else {
01174 ReturnThisResource =
TRUE;
01175 }
01176
if (ReturnThisResource) {
01177
if (LangResourceDirectoryEntry->DataIsDirectory) {
01178
return STATUS_INVALID_IMAGE_FORMAT;
01179 }
01180
01181
if (LangResourceDirectoryEntry->NameIsString) {
01182 ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
01183 ((PCHAR)TopResourceDirectory + LangResourceDirectoryEntry->NameOffset);
01184
01185 LangResourceNameOrId = (ULONG_PTR)ResourceNameString;
01186 }
01187
else {
01188 LangResourceNameOrId = (ULONG_PTR)LangResourceDirectoryEntry->Id;
01189 }
01190
01191 ResourceDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)
01192 ((PCHAR)TopResourceDirectory + LangResourceDirectoryEntry->OffsetToData);
01193
01194 ResourceInfo = &Resources[ ResourceIndex++ ];
01195
if (ResourceIndex <= MaxResourceIndex) {
01196 ResourceInfo->Path[ 0 ].NameOrId = TypeResourceNameOrId;
01197 ResourceInfo->Path[ 1 ].NameOrId = NameResourceNameOrId;
01198 ResourceInfo->Path[ 2 ].NameOrId = LangResourceNameOrId;
01199 ResourceInfo->Data = (PVOID)((ULONG_PTR)DllHandle + ResourceDataEntry->OffsetToData);
01200 ResourceInfo->Size = ResourceDataEntry->Size;
01201 ResourceInfo->Reserved = 0;
01202 }
01203
else {
01204
Status = STATUS_INFO_LENGTH_MISMATCH;
01205 }
01206 }
01207 }
01208 }
01209 }
01210 }
01211 }
01212
01213 *NumberOfResources = ResourceIndex;
01214
return Status;
01215 }
01216
01217
#ifndef NTOS_KERNEL_RUNTIME
01218
01219 BOOLEAN
01220 LdrAlternateResourcesEnabled(
01221 VOID
01222 )
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 {
01242
NTSTATUS Status;
01243
01244
if (!
UILangId){
01245
Status =
NtQueryDefaultUILanguage( &
UILangId );
01246
01247
if (!
NT_SUCCESS(
Status )) {
01248
01249
01250
01251
return FALSE;
01252 }
01253 }
01254
01255
if (!
InstallLangId){
01256
Status =
NtQueryInstallUILanguage( &
InstallLangId);
01257
01258
if (!
NT_SUCCESS(
Status )) {
01259
01260
01261
01262
return FALSE;
01263 }
01264 }
01265
01266
if (
UILangId ==
InstallLangId) {
01267
01268
01269
01270
return FALSE;
01271 }
01272
01273
return TRUE;
01274 }
01275
01276 PVOID
01277 LdrGetAlternateResourceModuleHandle(
01278 IN PVOID Module
01279 )
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 {
01298 ULONG ModuleIndex;
01299
01300
for (ModuleIndex = 0;
01301 ModuleIndex <
AlternateResourceModuleCount;
01302 ModuleIndex++ ){
01303
if (
AlternateResourceModules[ModuleIndex].
ModuleBase ==
01304 Module){
01305
return AlternateResourceModules[ModuleIndex].
AlternateModule;
01306 }
01307 }
01308
return NULL;
01309 }
01310
01311 BOOLEAN
01312 LdrpGetFileVersion(
01313 IN PVOID ImageBase,
01314 IN LANGID LangId,
01315 OUT PULONGLONG Version
01316 )
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 {
01339 PIMAGE_RESOURCE_DATA_ENTRY DataEntry;
01340
NTSTATUS Status;
01341 ULONG_PTR IdPath[3];
01342 ULONG ResourceSize;
01343
01344
01345
typedef struct tagVS_FIXEDFILEINFO
01346 {
01347 LONG dwSignature;
01348 LONG dwStrucVersion;
01349 LONG dwFileVersionMS;
01350 LONG dwFileVersionLS;
01351 LONG dwProductVersionMS;
01352 LONG dwProductVersionLS;
01353 LONG dwFileFlagsMask;
01354 LONG dwFileFlags;
01355 LONG dwFileOS;
01356 LONG dwFileType;
01357 LONG dwFileSubtype;
01358 LONG dwFileDateMS;
01359 LONG dwFileDateLS;
01360 } VS_FIXEDFILEINFO;
01361
01362
struct {
01363
USHORT TotalSize;
01364
USHORT DataSize;
01365
USHORT Type;
01366 WCHAR
Name[16];
01367 VS_FIXEDFILEINFO FixedFileInfo;
01368 } *
Resource;
01369
01370 *
Version = 0;
01371
01372
01373 IdPath[0] = 16;
01374 IdPath[1] = 1;
01375 IdPath[2] = LangId;
01376
01377
try {
01378
Status =
LdrpSearchResourceSection_U(
01379 ImageBase,
01380 IdPath,
01381 3,
01382
FALSE,
01383
TRUE,
01384 &DataEntry);
01385 } except(
EXCEPTION_EXECUTE_HANDLER) {
01386
Status = STATUS_UNSUCCESSFUL;
01387 }
01388
01389
if(!
NT_SUCCESS(
Status)) {
01390
return FALSE;
01391 }
01392
01393
try {
01394
Status =
LdrpAccessResourceData(
01395 ImageBase,
01396 DataEntry,
01397 &
Resource,
01398 &ResourceSize);
01399 } except(
EXCEPTION_EXECUTE_HANDLER) {
01400
Status = STATUS_UNSUCCESSFUL;
01401 }
01402
01403
if(!
NT_SUCCESS(
Status)) {
01404
return FALSE;
01405 }
01406
01407
try {
01408
if((ResourceSize >=
sizeof(*Resource))
01409 && !_wcsicmp(
Resource->Name,
L"VS_VERSION_INFO")) {
01410
01411 *
Version = ((ULONGLONG)
Resource->FixedFileInfo.dwFileVersionMS << 32
01412 )
01413 | (ULONGLONG)
Resource->FixedFileInfo.dwFileVersionLS;
01414
01415 }
else {
01416
DbgPrint((
"LDR: Warning: invalid version resource\n"));
01417
return FALSE;
01418 }
01419 } except(
EXCEPTION_EXECUTE_HANDLER) {
01420
DbgPrint((
"LDR: Exception encountered processing bogus version resource\n"));
01421
return FALSE;
01422 }
01423
return TRUE;
01424 }
01425
01426 BOOLEAN
01427 LdrpVerifyAlternateResourceModule(
01428 IN PVOID Module,
01429 IN PVOID AlternateModule
01430 )
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450 {
01451 ULONGLONG ModuleVersion;
01452 ULONGLONG AltModuleVersion;
01453
NTSTATUS Status;
01454
01455
if (!
UILangId){
01456
Status =
NtQueryDefaultUILanguage( &
UILangId);
01457
if (!
NT_SUCCESS(
Status )) {
01458
01459
01460
01461
return FALSE;
01462 }
01463 }
01464
01465
if (!
LdrpGetFileVersion(AlternateModule,
UILangId, &AltModuleVersion)){
01466
return FALSE;
01467 }
01468
01469
if (!
InstallLangId){
01470
Status =
NtQueryInstallUILanguage (&
InstallLangId);
01471
if (!
NT_SUCCESS(
Status )) {
01472
01473
01474
01475
return FALSE;
01476 }
01477 }
01478
01479
if (!
LdrpGetFileVersion(Module,
InstallLangId, &ModuleVersion)){
01480
return FALSE;
01481 }
01482
01483
if (ModuleVersion == AltModuleVersion){
01484
return TRUE;
01485 }
01486
else{
01487
return FALSE;
01488 }
01489 }
01490
01491 BOOLEAN
01492 LdrpSetAlternateResourceModuleHandle(
01493 IN PVOID Module,
01494 IN PVOID AlternateModule
01495 )
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 {
01516
PALT_RESOURCE_MODULE NewModules;
01517
01518
if (
AlternateResourceModules ==
NULL){
01519
01520
01521
01522 NewModules =
RtlAllocateHeap(
01523 RtlProcessHeap(),
01524 HEAP_ZERO_MEMORY,
01525
RESMODSIZE *
MEMBLOCKSIZE);
01526
if (!NewModules){
01527
return FALSE;
01528 }
01529
AlternateResourceModules = NewModules;
01530
AltResMemBlockCount =
MEMBLOCKSIZE;
01531 }
01532
else
01533
if (
AlternateResourceModuleCount >=
AltResMemBlockCount ){
01534
01535
01536
01537 NewModules =
RtlReAllocateHeap(
01538 RtlProcessHeap(),
01539 0,
01540
AlternateResourceModules,
01541 (
AltResMemBlockCount +
MEMBLOCKSIZE) *
RESMODSIZE
01542 );
01543
01544
if (!NewModules){
01545
return FALSE;
01546 }
01547
AlternateResourceModules = NewModules;
01548
AltResMemBlockCount +=
MEMBLOCKSIZE;
01549 }
01550
01551
AlternateResourceModules[
AlternateResourceModuleCount].
ModuleBase = Module;
01552
AlternateResourceModules[
AlternateResourceModuleCount].
AlternateModule = AlternateModule;
01553
01554
01555
01556
AlternateResourceModuleCount++;
01557
01558
return TRUE;
01559
01560 }
01561
01562 PVOID
01563 LdrLoadAlternateResourceModule(
01564 IN PVOID Module,
01565 IN LPCWSTR PathToAlternateModule OPTIONAL
01566 )
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586 {
01587 PVOID AlternateModule, DllBase;
01588 PLDR_DATA_TABLE_ENTRY Entry;
01589 HANDLE FileHandle, MappingHandle;
01590 PIMAGE_NT_HEADERS NtHeaders;
01591
NTSTATUS Status;
01592 OBJECT_ATTRIBUTES
ObjectAttributes;
01593 UNICODE_STRING AltDllName;
01594 PVOID FreeBuffer;
01595 LPWSTR BaseDllName, p;
01596 WCHAR DllPathName[DOS_MAX_PATH_LENGTH];
01597 ULONG DllPathNameLength, BaseDllNameLength, CopyCount;
01598 ULONG Digit;
01599
int i, RetryCount;
01600 WCHAR AltModulePath[DOS_MAX_PATH_LENGTH];
01601 WCHAR AltModulePathMUI[DOS_MAX_PATH_LENGTH];
01602 WCHAR AltModulePathFallback[DOS_MAX_PATH_LENGTH];
01603 IO_STATUS_BLOCK IoStatusBlock;
01604 RTL_RELATIVE_NAME
RelativeName;
01605 SIZE_T ViewSize;
01606 LARGE_INTEGER SectionOffset;
01607 WCHAR LangIdDir[6];
01608 UNICODE_STRING AltModulePathList[3];
01609 UNICODE_STRING
NtSystemRoot;
01610
01611
01612
if (!
LdrAlternateResourcesEnabled()) {
01613
return NULL;
01614 }
01615
01616 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01617
01618 AlternateModule =
LdrGetAlternateResourceModuleHandle(Module);
01619
if (AlternateModule ==
NO_ALTERNATE_RESOURCE_MODULE){
01620
01621
01622
01623
01624 RtlLeaveCriticalSection(
01625 (PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01626
return NULL;
01627 }
01628
else if (AlternateModule > 0){
01629
01630
01631
01632 RtlLeaveCriticalSection(
01633 (PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01634
return AlternateModule;
01635 }
01636
01637
if (ARGUMENT_PRESENT(PathToAlternateModule)){
01638
01639
01640
01641
01642 CopyCount = wcslen(PathToAlternateModule);
01643
01644
for (p = (LPWSTR) PathToAlternateModule + CopyCount;
01645 p > PathToAlternateModule;
01646 p--){
01647
if (*(p-1) ==
L'\\'){
01648
break;
01649 }
01650 }
01651
01652
if (p == PathToAlternateModule){
01653
goto error_exit;
01654 }
01655
01656 DllPathNameLength = (ULONG)(p - PathToAlternateModule) *
sizeof(WCHAR);
01657
01658 RtlCopyMemory(
01659 DllPathName,
01660 PathToAlternateModule,
01661 DllPathNameLength
01662 );
01663
01664 BaseDllName = p ;
01665 BaseDllNameLength = CopyCount *
sizeof(WCHAR) - DllPathNameLength;
01666
01667 }
01668
else{
01669
01670
01671
01672
Status =
LdrFindEntryForAddress(Module, &Entry);
01673
if (!
NT_SUCCESS(
Status )){
01674
goto error_exit;
01675 }
01676
01677 DllPathNameLength = Entry->FullDllName.Length -
01678 Entry->BaseDllName.Length;
01679
01680 RtlCopyMemory(
01681 DllPathName,
01682 Entry->FullDllName.Buffer,
01683 DllPathNameLength);
01684
01685 BaseDllName = Entry->BaseDllName.Buffer;
01686 BaseDllNameLength = Entry->BaseDllName.Length;
01687 }
01688
01689 DllPathName[DllPathNameLength /
sizeof(WCHAR)] = UNICODE_NULL;
01690
01691
01692
01693
01694
if (!
UILangId){
01695
Status =
NtQueryDefaultUILanguage( &
UILangId );
01696
if (!
NT_SUCCESS(
Status )) {
01697
goto error_exit;
01698 }
01699 }
01700
01701 CopyCount = 0;
01702
for (i = 12; i >= 0; i -= 4){
01703 Digit = ((
UILangId >> i) & 0xF);
01704
if (Digit >= 10){
01705 LangIdDir[CopyCount++] = (WCHAR) (Digit - 10 +
L'A');
01706 }
01707
else{
01708 LangIdDir[CopyCount++] = (WCHAR) (Digit +
L'0');
01709 }
01710 }
01711
01712 LangIdDir[CopyCount++] =
L'\\';
01713 LangIdDir[CopyCount++] = UNICODE_NULL;
01714
01715
01716
01717
01718 AltModulePathList[1].Buffer = AltModulePath;
01719 AltModulePathList[1].Length = 0;
01720 AltModulePathList[1].MaximumLength =
sizeof(AltModulePath);
01721
01722
RtlAppendUnicodeToString(&AltModulePathList[1], DllPathName);
01723
RtlAppendUnicodeToString(&AltModulePathList[1],
L"mui\\");
01724
RtlAppendUnicodeToString(&AltModulePathList[1], LangIdDir);
01725
RtlAppendUnicodeToString(&AltModulePathList[1], BaseDllName);
01726
01727
01728
01729
01730 AltModulePathList[0].Buffer = AltModulePathMUI;
01731 AltModulePathList[0].Length = 0;
01732 AltModulePathList[0].MaximumLength =
sizeof(AltModulePathMUI);
01733
01734
RtlCopyUnicodeString(&AltModulePathList[0], &AltModulePathList[1]);
01735
RtlAppendUnicodeToString(&AltModulePathList[0],
L".mui");
01736
01737
01738
01739
01740 AltModulePathList[2].Buffer = AltModulePathFallback;
01741 AltModulePathList[2].Length = 0;
01742 AltModulePathList[2].MaximumLength =
sizeof(AltModulePathFallback);
01743
01744
RtlInitUnicodeString(&
NtSystemRoot, USER_SHARED_DATA->NtSystemRoot);
01745
RtlAppendUnicodeStringToString(&AltModulePathList[2], &
NtSystemRoot);
01746
RtlAppendUnicodeToString(&AltModulePathList[2],
L"\\mui\\fallback\\");
01747
RtlAppendUnicodeToString(&AltModulePathList[2], LangIdDir);
01748
RtlAppendUnicodeToString(&AltModulePathList[2], BaseDllName);
01749
RtlAppendUnicodeToString(&AltModulePathList[2],
L".mui");
01750
01751
01752
01753
01754 RetryCount = 0;
01755
while (RetryCount <
sizeof(AltModulePathList)/
sizeof(UNICODE_STRING)){
01756
if (!
RtlDosPathNameToNtPathName_U(
01757 AltModulePathList[RetryCount].
Buffer,
01758 &AltDllName,
01759
NULL,
01760 &
RelativeName
01761 )){
01762
goto error_exit;
01763 }
01764
01765 FreeBuffer = AltDllName.Buffer;
01766
if (
RelativeName.RelativeName.Length ) {
01767 AltDllName = *(PUNICODE_STRING)&
RelativeName.RelativeName;
01768 }
01769
else {
01770
RelativeName.ContainingDirectory =
NULL;
01771 }
01772
01773 InitializeObjectAttributes(
01774 &
ObjectAttributes,
01775 &AltDllName,
01776 OBJ_CASE_INSENSITIVE,
01777
RelativeName.ContainingDirectory,
01778
NULL
01779 );
01780
01781
01782
Status =
NtCreateFile(
01783 &FileHandle,
01784 (ACCESS_MASK) GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
01785 &
ObjectAttributes,
01786 &IoStatusBlock,
01787
NULL,
01788 0
L,
01789 FILE_SHARE_READ | FILE_SHARE_DELETE,
01790 FILE_OPEN,
01791 0
L,
01792
NULL,
01793 0
L
01794 );
01795
01796
RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
01797
01798
if (
NT_SUCCESS(
Status )){
01799
break;
01800 }
01801
if (
Status != STATUS_OBJECT_NAME_NOT_FOUND && RetryCount == 0) {
01802
01803
01804
01805
01806
01807 RetryCount++;
01808 }
01809
01810 RetryCount++;
01811 }
01812
01813
Status =
NtCreateSection(
01814 &MappingHandle,
01815 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
01816
NULL,
01817
NULL,
01818 PAGE_WRITECOPY,
01819 SEC_COMMIT,
01820 FileHandle
01821 );
01822
01823
if (!
NT_SUCCESS(
Status )){
01824
goto error_exit;
01825 }
01826
01827
NtClose( FileHandle );
01828
01829 SectionOffset.LowPart = 0;
01830 SectionOffset.HighPart = 0;
01831 ViewSize = 0;
01832 DllBase =
NULL;
01833
01834
Status =
NtMapViewOfSection(
01835 MappingHandle,
01836 NtCurrentProcess(),
01837 &DllBase,
01838 0
L,
01839 0
L,
01840 &SectionOffset,
01841 &ViewSize,
01842 ViewShare,
01843 0
L,
01844 PAGE_WRITECOPY
01845 );
01846
01847
NtClose( MappingHandle );
01848
01849
if (!
NT_SUCCESS(
Status )){
01850
goto error_exit;
01851 }
01852
01853 NtHeaders =
RtlImageNtHeader( DllBase );
01854
if (!NtHeaders) {
01855
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID) DllBase);
01856
goto error_exit;
01857 }
01858
01859 AlternateModule = (HANDLE)((ULONG_PTR)DllBase | 0x00000001);
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
LdrpSetAlternateResourceModuleHandle(Module, AlternateModule);
01872 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01873
return AlternateModule;
01874
01875 error_exit:
01876
LdrpSetAlternateResourceModuleHandle(Module,
NO_ALTERNATE_RESOURCE_MODULE);
01877 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01878
return NULL;
01879 }
01880
01881 BOOLEAN
01882 LdrUnloadAlternateResourceModule(
01883 IN PVOID Module
01884 )
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903 {
01904 ULONG ModuleIndex;
01905
PALT_RESOURCE_MODULE AltModule;
01906
01907 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01908
if (
AlternateResourceModuleCount == 0){
01909 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01910
return TRUE;
01911 }
01912
01913
for (ModuleIndex =
AlternateResourceModuleCount;
01914 ModuleIndex > 0;
01915 ModuleIndex--){
01916
if (
AlternateResourceModules[ModuleIndex-1].
ModuleBase == Module){
01917
break;
01918 }
01919 }
01920
01921
if (ModuleIndex == 0){
01922 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01923
return FALSE;
01924 }
01925
01926
01927
01928 ModuleIndex --;
01929
01930 AltModule = &
AlternateResourceModules[ModuleIndex];
01931
if (AltModule->
AlternateModule !=
NO_ALTERNATE_RESOURCE_MODULE) {
01932
NtUnmapViewOfSection(
01933 NtCurrentProcess(),
01934 (PVOID)((ULONG_PTR)AltModule->
AlternateModule & ~0x00000001)
01935 );
01936 }
01937
01938 __try {
01939
if (ModuleIndex !=
AlternateResourceModuleCount - 1){
01940
01941
01942
01943
01944 RtlMoveMemory(
01945 AltModule,
01946 AltModule + 1,
01947 (
AlternateResourceModuleCount - ModuleIndex - 1) *
RESMODSIZE
01948 );
01949 }
01950 }
01951 __except (
EXCEPTION_EXECUTE_HANDLER) {
01952 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01953
return FALSE;
01954 }
01955
01956
AlternateResourceModuleCount --;
01957
01958
if (
AlternateResourceModuleCount == 0){
01959
RtlFreeHeap(
01960 RtlProcessHeap(),
01961 0,
01962
AlternateResourceModules
01963 );
01964
AlternateResourceModules =
NULL;
01965
AltResMemBlockCount = 0;
01966 }
01967
else
01968
if (
AlternateResourceModuleCount <
AltResMemBlockCount -
MEMBLOCKSIZE){
01969 AltModule =
RtlReAllocateHeap(
01970 RtlProcessHeap(),
01971 0,
01972
AlternateResourceModules,
01973 (
AltResMemBlockCount -
MEMBLOCKSIZE) *
RESMODSIZE);
01974
01975
if (!AltModule){
01976 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01977
return FALSE;
01978 }
01979
01980
AlternateResourceModules = AltModule;
01981
AltResMemBlockCount -=
MEMBLOCKSIZE;
01982 }
01983 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01984
return TRUE;
01985 }
01986
01987
01988 BOOLEAN
01989 LdrFlushAlternateResourceModules(
01990 VOID
01991 )
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014 {
02015 ULONG ModuleIndex;
02016
PALT_RESOURCE_MODULE AltModule;
02017
02018
02019
02020
02021 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
02022
02023
if (
AlternateResourceModuleCount > 0) {
02024
02025
02026
02027
02028
for (ModuleIndex=0;
02029 ModuleIndex<
AlternateResourceModuleCount;
02030 ModuleIndex++) {
02031
02032 AltModule = &
AlternateResourceModules[ModuleIndex];
02033
02034
if (AltModule->
AlternateModule !=
NO_ALTERNATE_RESOURCE_MODULE) {
02035
NtUnmapViewOfSection(NtCurrentProcess(),
02036 (PVOID)((ULONG_PTR)AltModule->
AlternateModule & ~0x00000001));
02037 }
02038 }
02039
02040
02041
02042
02043
RtlFreeHeap(RtlProcessHeap(), 0,
AlternateResourceModules);
02044
AlternateResourceModules =
NULL;
02045
AlternateResourceModuleCount = 0;
02046
AltResMemBlockCount = 0;
02047
02048 }
02049
02050
02051
02052
02053
02054
UILangId = 0;
02055 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
02056
02057
return TRUE;
02058 }
02059
02060
#endif