00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "ldrp.h"
00025
00026 #define DLLEXTENSION ((PWSTR)".\0d\0l\0l\0\0") // .dll
00027
00028
00029 ULONG
00030
LdrpClearLoadInProgress(
00031 VOID
00032 );
00033
00034
NTSTATUS
00035 LdrLoadDll (
00036 IN PWSTR DllPath OPTIONAL,
00037 IN PULONG DllCharacteristics OPTIONAL,
00038 IN PUNICODE_STRING DllName,
00039 OUT PVOID *DllHandle
00040 )
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 {
00065
return LdrpLoadDll(DllPath,DllCharacteristics,DllName,DllHandle,
TRUE);
00066 }
00067
00068
NTSTATUS
00069 NTAPI
00070 LdrpLoadDll(
00071 IN PWSTR DllPath OPTIONAL,
00072 IN PULONG DllCharacteristics OPTIONAL,
00073 IN PUNICODE_STRING DllName,
00074 OUT PVOID *DllHandle,
00075 IN BOOLEAN RunInitRoutines
00076 )
00077
00078 {
00079 PPEB Peb;
00080 PTEB Teb;
00081
NTSTATUS st;
00082 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
00083 PWSTR ActualDllName;
00084 PWCH p, pp;
00085 UNICODE_STRING ActualDllNameStr;
00086 BOOLEAN Wx86KnownDll =
FALSE;
00087 WCHAR FreeBuffer[266];
00088
00089 Peb = NtCurrentPeb();
00090 Teb = NtCurrentTeb();
00091
00092 st = STATUS_SUCCESS;
00093
00094
try {
00095
00096
00097
00098
00099
00100
if (
LdrpInLdrInit ==
FALSE ) {
00101 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00102 }
00103
00104
00105
00106
#if defined (WX86)
00107
00108
if (Teb->Wx86Thread.UseKnownWx86Dll) {
00109 Wx86KnownDll = Teb->Wx86Thread.UseKnownWx86Dll;
00110 Teb->Wx86Thread.UseKnownWx86Dll =
FALSE;
00111 }
00112
#endif
00113
00114
00115
00116 p = DllName->Buffer;
00117 pp =
NULL;
00118
while (*p) {
00119
if (*p++ == (WCHAR)
'.') {
00120
00121
00122
00123 pp = p;
00124 }
00125 }
00126
00127
00128 ActualDllName = FreeBuffer;
00129
if ( DllName->Length >=
sizeof(FreeBuffer)) {
00130
return STATUS_NAME_TOO_LONG;
00131 }
00132 RtlMoveMemory(ActualDllName, DllName->Buffer, DllName->Length);
00133
00134
00135
if (!pp || *pp == (WCHAR)
'\\') {
00136
00137
00138
00139
if ( DllName->Length+10 >=
sizeof(FreeBuffer) ) {
00140
return STATUS_NAME_TOO_LONG;
00141 }
00142
00143 RtlMoveMemory((PCHAR)ActualDllName+DllName->Length,
DLLEXTENSION, 10);
00144 }
00145
else {
00146 ActualDllName[DllName->Length >> 1] = UNICODE_NULL;
00147 }
00148
00149
if (
ShowSnaps) {
00150
DbgPrint(
"LDR: LdrLoadDll, loading %ws from %ws\n",
00151 ActualDllName,
00152 ARGUMENT_PRESENT(DllPath) ? DllPath :
L""
00153 );
00154 }
00155
00156
00157
RtlInitUnicodeString(&ActualDllNameStr,ActualDllName);
00158 ActualDllNameStr.MaximumLength =
sizeof(FreeBuffer);
00159
00160
if (!
LdrpCheckForLoadedDll( DllPath,
00161 &ActualDllNameStr,
00162
FALSE,
00163 Wx86KnownDll,
00164 &LdrDataTableEntry
00165 )
00166 ) {
00167 st =
LdrpMapDll(DllPath,
00168 ActualDllName,
00169 DllCharacteristics,
00170
FALSE,
00171 Wx86KnownDll,
00172 &LdrDataTableEntry
00173 );
00174
00175
if (!
NT_SUCCESS(st)) {
00176
return st;
00177 }
00178
00179
if (ARGUMENT_PRESENT( DllCharacteristics ) &&
00180 *DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE
00181 ) {
00182 LdrDataTableEntry->EntryPoint = 0;
00183 LdrDataTableEntry->Flags &= ~LDRP_IMAGE_DLL;
00184 }
00185
00186
00187
00188
00189
00190
if (LdrDataTableEntry->Flags & LDRP_IMAGE_DLL) {
00191
00192
try {
00193 st =
LdrpWalkImportDescriptor(
00194 DllPath,
00195 LdrDataTableEntry
00196 );
00197 }
00198 except(
EXCEPTION_EXECUTE_HANDLER) {
00199 st = GetExceptionCode();
00200 }
00201
if ( LdrDataTableEntry->LoadCount != 0xffff ) {
00202 LdrDataTableEntry->LoadCount++;
00203 }
00204
LdrpReferenceLoadedDll(LdrDataTableEntry);
00205
if (!
NT_SUCCESS(st)) {
00206 LdrDataTableEntry->EntryPoint =
NULL;
00207 InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
00208 &LdrDataTableEntry->InInitializationOrderLinks);
00209
LdrpClearLoadInProgress();
00210
LdrUnloadDll((PVOID)LdrDataTableEntry->DllBase);
00211
return st;
00212 }
00213 }
00214
else {
00215
if ( LdrDataTableEntry->LoadCount != 0xffff ) {
00216 LdrDataTableEntry->LoadCount++;
00217 }
00218 }
00219
00220
00221
00222
00223
00224 InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
00225 &LdrDataTableEntry->InInitializationOrderLinks);
00226
00227
00228
00229
00230
00231
00232
00233
00234
if ( RunInitRoutines &&
LdrpLdrDatabaseIsSetup ) {
00235
00236
try {
00237 st =
LdrpRunInitializeRoutines(
NULL);
00238
if ( !
NT_SUCCESS(st) ) {
00239
LdrUnloadDll((PVOID)LdrDataTableEntry->DllBase);
00240 }
00241 }
00242 except(
EXCEPTION_EXECUTE_HANDLER ) {
00243
LdrUnloadDll((PVOID)LdrDataTableEntry->DllBase);
00244
return GetExceptionCode();
00245 }
00246 }
00247
else {
00248 st = STATUS_SUCCESS;
00249 }
00250
00251 }
00252
else {
00253
00254
00255
00256
00257
00258
if ( LdrDataTableEntry->Flags & LDRP_IMAGE_DLL &&
00259 LdrDataTableEntry->LoadCount != 0xffff ) {
00260
00261 LdrDataTableEntry->LoadCount++;
00262
00263
LdrpReferenceLoadedDll(LdrDataTableEntry);
00264
00265
00266
00267
00268
00269
LdrpClearLoadInProgress();
00270
00271 }
00272
else {
00273
if ( LdrDataTableEntry->LoadCount != 0xffff ) {
00274 LdrDataTableEntry->LoadCount++;
00275 }
00276 }
00277 }
00278 }
00279 finally {
00280
if (
LdrpInLdrInit ==
FALSE ) {
00281 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00282 }
00283
00284 }
00285
if (
NT_SUCCESS(st) ) {
00286 *DllHandle = (PVOID)LdrDataTableEntry->DllBase;
00287 }
00288
else {
00289 *DllHandle =
NULL;
00290 }
00291
return st;
00292 }
00293
00294
NTSTATUS
00295 LdrGetDllHandle (
00296 IN PWSTR DllPath OPTIONAL,
00297 IN PULONG DllCharacteristics OPTIONAL,
00298 IN PUNICODE_STRING DllName,
00299 OUT PVOID *DllHandle
00300 )
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 {
00326
NTSTATUS st;
00327 PPEB Peb;
00328 PTEB Teb;
00329 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
00330 PWSTR ActualDllName;
00331 PWCH p, pp;
00332 UNICODE_STRING ActualDllNameStr;
00333 BOOLEAN Wx86KnownDll =
FALSE;
00334 WCHAR FreeBuffer[266];
00335
00336
00337 DllCharacteristics;
00338
00339 Peb = NtCurrentPeb();
00340 Teb = NtCurrentTeb();
00341
00342 st = STATUS_DLL_NOT_FOUND;
00343
00344
try {
00345
00346
00347
00348
00349
00350
if (
LdrpInLdrInit ==
FALSE ) {
00351 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00352 }
00353
00354
#if defined (WX86)
00355
00356
00357
if (Teb->Wx86Thread.UseKnownWx86Dll) {
00358 Wx86KnownDll = Teb->Wx86Thread.UseKnownWx86Dll;
00359 Teb->Wx86Thread.UseKnownWx86Dll =
FALSE;
00360 }
00361
00362
00363
00364
00365
00366
if (Wx86ProcessInit) {
00367
LdrpGetModuleHandleCache =
NULL;
00368 }
00369
00370
#endif
00371
00372
00373
if (
LdrpGetModuleHandleCache ) {
00374
if (
RtlEqualUnicodeString(DllName,
00375 &
LdrpGetModuleHandleCache->BaseDllName,
00376
TRUE
00377 )) {
00378 *DllHandle = (PVOID)
LdrpGetModuleHandleCache->DllBase;
00379 st = STATUS_SUCCESS;
00380 leave;
00381 }
00382 }
00383
00384
00385
00386 p = DllName->Buffer;
00387 pp =
NULL;
00388
while (*p) {
00389
if (*p++ == (WCHAR)
'.') {
00390
00391
00392
00393 pp = p;
00394 }
00395 }
00396
00397 ActualDllName = FreeBuffer;
00398
if ( DllName->Length >=
sizeof(FreeBuffer)) {
00399
return STATUS_NAME_TOO_LONG;
00400 }
00401 RtlMoveMemory(ActualDllName, DllName->Buffer, DllName->Length);
00402
00403
if (!pp || *pp == (WCHAR)
'\\') {
00404
00405
00406
00407
if ( DllName->Length+10 >=
sizeof(FreeBuffer) ) {
00408
return STATUS_NAME_TOO_LONG;
00409 }
00410
00411 RtlMoveMemory((PCHAR)ActualDllName+DllName->Length,
DLLEXTENSION, 10);
00412 }
00413
00414
else {
00415
00416
00417
00418
00419
00420
00421
if ( ActualDllName[ (DllName->Length-2) >> 1] ==
L'.' ) {
00422 DllName->Length -= 2;
00423 }
00424
00425 ActualDllName[DllName->Length >> 1] = UNICODE_NULL;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
RtlInitUnicodeString(&ActualDllNameStr,ActualDllName);
00436 ActualDllNameStr.MaximumLength =
sizeof(FreeBuffer);
00437
00438
if (
ShowSnaps) {
00439
DbgPrint(
"LDR: LdrGetDllHandle, searching for %ws from %ws\n",
00440 ActualDllName,
00441 ARGUMENT_PRESENT(DllPath) ? (DllPath == (PWSTR)1 ?
L"" : DllPath) :
L""
00442 );
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
if (
LdrpCheckForLoadedDll( DllPath,
00454 &ActualDllNameStr,
00455 (BOOLEAN)(DllPath == (PWSTR)1 ?
TRUE :
FALSE),
00456 Wx86KnownDll,
00457 &LdrDataTableEntry
00458 )
00459 ) {
00460 *DllHandle = (PVOID)LdrDataTableEntry->DllBase;
00461
LdrpGetModuleHandleCache = LdrDataTableEntry;
00462 st = STATUS_SUCCESS;
00463
00464 }
00465 } finally {
00466
if (
LdrpInLdrInit ==
FALSE ) {
00467 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00468 }
00469 }
00470
return st;
00471 }
00472
00473
NTSTATUS
00474 LdrDisableThreadCalloutsForDll (
00475 IN PVOID DllHandle
00476 )
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 {
00496
NTSTATUS st;
00497 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
00498
00499 st = STATUS_SUCCESS;
00500
00501
try {
00502
00503
if (
LdrpInLdrInit ==
FALSE ) {
00504 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00505 }
00506
if (
LdrpShutdownInProgress ) {
00507
return STATUS_SUCCESS;
00508 }
00509
00510
if (
LdrpCheckForLoadedDllHandle(DllHandle, &LdrDataTableEntry)) {
00511
if ( LdrDataTableEntry->TlsIndex ) {
00512 st = STATUS_DLL_NOT_FOUND;
00513 }
00514
else {
00515 LdrDataTableEntry->Flags |= LDRP_DONT_CALL_FOR_THREADS;
00516 }
00517 }
00518 }
00519 finally {
00520
if (
LdrpInLdrInit ==
FALSE ) {
00521 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00522 }
00523 }
00524
return st;
00525 }
00526
00527
NTSTATUS
00528 LdrUnloadDll (
00529 IN PVOID DllHandle
00530 )
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 {
00549
NTSTATUS st;
00550 PPEB Peb;
00551 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
00552 PLDR_DATA_TABLE_ENTRY Entry;
00553 PDLL_INIT_ROUTINE InitRoutine;
00554 LIST_ENTRY LocalUnloadHead;
00555 PLIST_ENTRY Next;
00556
#if defined (WX86)
00557
PVOID Wx86Plugin =
NULL;
00558
#endif
00559
00560 Peb = NtCurrentPeb();
00561 st = STATUS_SUCCESS;
00562
00563
try {
00564
00565
00566
00567
00568
00569
00570
if (
LdrpInLdrInit ==
FALSE ) {
00571 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00572 }
00573
00574
LdrpActiveUnloadCount++;
00575
00576
if (
LdrpShutdownInProgress ) {
00577
goto leave_finally;
00578 }
00579
00580
if (!
LdrpCheckForLoadedDllHandle(DllHandle, &LdrDataTableEntry)) {
00581 st = STATUS_DLL_NOT_FOUND;
00582
goto leave_finally;
00583 }
00584
00585
00586
00587
00588
00589
if ( LdrDataTableEntry->LoadCount != 0xffff ) {
00590 LdrDataTableEntry->LoadCount--;
00591
if ( LdrDataTableEntry->Flags & LDRP_IMAGE_DLL ) {
00592
LdrpDereferenceLoadedDll(LdrDataTableEntry);
00593 }
00594 }
else {
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
goto leave_finally;
00605 }
00606
00607
00608
00609
00610
00611
00612
if (
ShowSnaps) {
00613
DbgPrint(
"LDR: UNINIT LIST\n");
00614 }
00615
00616
if (
LdrpActiveUnloadCount == 1 ) {
00617 InitializeListHead(&
LdrpUnloadHead);
00618 }
00619
00620
00621
00622
00623
00624
00625 Next = Peb->Ldr->InInitializationOrderModuleList.Blink;
00626
while ( Next != &Peb->Ldr->InInitializationOrderModuleList) {
00627 LdrDataTableEntry
00628 = (PLDR_DATA_TABLE_ENTRY)
00629 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InInitializationOrderLinks));
00630
00631 Next = Next->Blink;
00632 LdrDataTableEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS;
00633
00634
if (LdrDataTableEntry->LoadCount == 0) {
00635
00636
if (
ShowSnaps) {
00637
DbgPrint(
" (%d) [%ws] %ws (%lx) deinit %lx\n",
00638
LdrpActiveUnloadCount,
00639 LdrDataTableEntry->BaseDllName.Buffer,
00640 LdrDataTableEntry->FullDllName.Buffer,
00641 (ULONG)LdrDataTableEntry->LoadCount,
00642 LdrDataTableEntry->EntryPoint
00643 );
00644 }
00645
00646 Entry = LdrDataTableEntry;
00647
00648 RemoveEntryList(&Entry->InInitializationOrderLinks);
00649 RemoveEntryList(&Entry->InMemoryOrderLinks);
00650 RemoveEntryList(&Entry->HashLinks);
00651
00652
if (
LdrpActiveUnloadCount > 1 ) {
00653
LdrpLoadedDllHandleCache =
NULL;
00654 Entry->InMemoryOrderLinks.Flink =
NULL;
00655 }
00656 InsertTailList(&
LdrpUnloadHead,&Entry->HashLinks);
00657 }
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
if (
LdrpActiveUnloadCount > 1 ) {
00669
goto leave_finally;
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 InitializeListHead(&LocalUnloadHead);
00680 Entry =
NULL;
00681 Next =
LdrpUnloadHead.Flink;
00682
while ( Next != &
LdrpUnloadHead ) {
00683 top:
00684
if ( Entry ) {
00685 RemoveEntryList(&(Entry->InLoadOrderLinks));
00686 Entry =
NULL;
00687 Next =
LdrpUnloadHead.Flink;
00688
if (Next == &
LdrpUnloadHead ) {
00689
goto bottom;
00690 }
00691 }
00692 LdrDataTableEntry
00693 = (PLDR_DATA_TABLE_ENTRY)
00694 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,HashLinks));
00695
00696
00697
00698
00699
00700
00701
00702 Entry = LdrDataTableEntry;
00703
LdrpLoadedDllHandleCache =
NULL;
00704 Entry->InMemoryOrderLinks.Flink =
NULL;
00705
00706 RemoveEntryList(&Entry->HashLinks);
00707 InsertTailList(&LocalUnloadHead,&Entry->HashLinks);
00708
00709
00710
00711
00712
00713 InitRoutine = (PDLL_INIT_ROUTINE)LdrDataTableEntry->EntryPoint;
00714
00715
#if defined (WX86)
00716
if (Wx86ProcessInit) {
00717
try {
00718 LdrpWx86DllProcessDetach(LdrDataTableEntry);
00719 RemoveEntryList(&Entry->InLoadOrderLinks);
00720 Entry =
NULL;
00721 Next =
LdrpUnloadHead.Flink;
00722 }
00723 except(
EXCEPTION_EXECUTE_HANDLER){
00724
goto top;
00725 }
00726 }
00727
else
00728
#endif
00729
if (InitRoutine && (LdrDataTableEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) ) {
00730
try {
00731
if (
ShowSnaps) {
00732
DbgPrint(
"LDR: Calling deinit %lx\n",InitRoutine);
00733 }
00734
00735
LdrpCallInitRoutine(InitRoutine,
00736 LdrDataTableEntry->DllBase,
00737 DLL_PROCESS_DETACH,
00738
NULL);
00739
00740 RemoveEntryList(&Entry->InLoadOrderLinks);
00741 Entry =
NULL;
00742 Next =
LdrpUnloadHead.Flink;
00743 }
00744 except(
EXCEPTION_EXECUTE_HANDLER){
00745
goto top;
00746 }
00747 }
else {
00748 RemoveEntryList(&(Entry->InLoadOrderLinks));
00749 Entry =
NULL;
00750 Next =
LdrpUnloadHead.Flink;
00751 }
00752 }
00753 bottom:
00754
00755
#if defined (WX86)
00756
if (Wx86ProcessInit) {
00757
00758
00759
00760
00761
00762
00763 Next = LocalUnloadHead.Flink;
00764
while ( Next != &LocalUnloadHead ) {
00765 LdrDataTableEntry
00766 = (PLDR_DATA_TABLE_ENTRY)
00767 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,HashLinks));
00768
00769 Next = Next->Flink;
00770
00771 LdrpWx86DllMapNotify(LdrDataTableEntry->DllBase,
FALSE);
00772
00773
00774
00775
if ((LdrDataTableEntry->DllBase == DllHandle) &&
00776 (LdrDataTableEntry->Flags & LDRP_WX86_PLUGIN)) {
00777 Wx86Plugin = DllHandle;
00778 }
00779 }
00780 }
00781
#endif
00782
00783
00784
00785
00786
00787 Next = LocalUnloadHead.Flink;
00788
while ( Next != &LocalUnloadHead ) {
00789 LdrDataTableEntry
00790 = (PLDR_DATA_TABLE_ENTRY)
00791 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,HashLinks));
00792
00793 Next = Next->Flink;
00794 Entry = LdrDataTableEntry;
00795
00796
if (
ShowSnaps) {
00797
DbgPrint(
"LDR: Unmapping [%ws]\n",
00798 LdrDataTableEntry->BaseDllName.Buffer
00799 );
00800 }
00801 st =
NtUnmapViewOfSection(NtCurrentProcess(),Entry->DllBase);
00802
ASSERT(
NT_SUCCESS(st));
00803
00804
LdrUnloadAlternateResourceModule(Entry->DllBase);
00805
00806
if (Entry->FullDllName.Buffer) {
00807
RtlFreeUnicodeString(&Entry->FullDllName);
00808 }
00809
if (Entry->BaseDllName.Buffer) {
00810
RtlFreeUnicodeString(&Entry->BaseDllName);
00811 }
00812
00813
if ( Entry ==
LdrpGetModuleHandleCache ) {
00814
LdrpGetModuleHandleCache =
NULL;
00815 }
00816
00817
RtlFreeHeap(Peb->ProcessHeap, 0,Entry);
00818 }
00819
00820 leave_finally:;
00821 }
00822 finally {
00823
LdrpActiveUnloadCount--;
00824
if (
LdrpInLdrInit ==
FALSE ) {
00825
00826
#if defined (WX86)
00827
if (Wx86ProcessInit && Wx86Plugin) {
00828 Wx86UnloadProviders( Wx86Plugin );
00829 }
00830
#endif
00831
RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00832 }
00833 }
00834
return st;
00835 }
00836
00837
NTSTATUS
00838 LdrGetProcedureAddress (
00839 IN PVOID DllHandle,
00840 IN PANSI_STRING ProcedureName OPTIONAL,
00841 IN ULONG ProcedureNumber OPTIONAL,
00842 OUT PVOID *ProcedureAddress
00843 )
00844 {
00845
00846
return LdrpGetProcedureAddress(DllHandle,ProcedureName,ProcedureNumber,ProcedureAddress,
TRUE);
00847
00848 }
00849
00850
NTSTATUS
00851 LdrpGetProcedureAddress (
00852 IN PVOID DllHandle,
00853 IN PANSI_STRING ProcedureName OPTIONAL,
00854 IN ULONG ProcedureNumber OPTIONAL,
00855 OUT PVOID *ProcedureAddress,
00856 IN BOOLEAN RunInitRoutines
00857 )
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 {
00890
NTSTATUS st;
00891 UCHAR FunctionNameBuffer[64];
00892 PUCHAR src, dst;
00893 ULONG cb, ExportSize;
00894 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
00895 IMAGE_THUNK_DATA Thunk;
00896 PVOID ImageBase;
00897 PIMAGE_IMPORT_BY_NAME FunctionName;
00898 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
00899 PLIST_ENTRY Next;
00900
#if defined (WX86)
00901
PTEB Teb;
00902 BOOLEAN Wx86KnownDll =
FALSE;
00903
#endif
00904
00905
if (
ShowSnaps) {
00906
DbgPrint(
"LDR: LdrGetProcedureAddress by ");
00907 }
00908
00909
#if defined (WX86)
00910
Teb = NtCurrentTeb();
00911
if (Teb->Wx86Thread.UseKnownWx86Dll) {
00912 Wx86KnownDll = Teb->Wx86Thread.UseKnownWx86Dll;
00913 Teb->Wx86Thread.UseKnownWx86Dll =
FALSE;
00914 }
00915
#endif
00916
00917 FunctionName =
NULL;
00918
if ( ARGUMENT_PRESENT(ProcedureName) ) {
00919
00920
if (
ShowSnaps) {
00921
DbgPrint(
"NAME - %s\n", ProcedureName->Buffer);
00922 }
00923
00924
00925
00926
00927
00928
00929
if (ProcedureName->Length >=
sizeof( FunctionNameBuffer )-1 ) {
00930 FunctionName =
RtlAllocateHeap(RtlProcessHeap(),
MAKE_TAG(
TEMP_TAG ),ProcedureName->Length+1+
sizeof(
USHORT));
00931
if ( !FunctionName ) {
00932
return STATUS_INVALID_PARAMETER;
00933 }
00934 }
else {
00935 FunctionName = (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer;
00936 }
00937
00938 FunctionName->Hint = 0;
00939
00940 cb = ProcedureName->Length;
00941 src = ProcedureName->Buffer;
00942 dst = FunctionName->Name;
00943
00944
while (cb--) {
00945 *dst++ = *src++;
00946 }
00947 *dst =
'\0';
00948
00949
00950
00951
00952
00953
00954 ImageBase = FunctionName;
00955 Thunk.u1.AddressOfData = 0;
00956
00957 }
else {
00958 ImageBase =
NULL;
00959
if (
ShowSnaps) {
00960
DbgPrint(
"ORDINAL - %lx\n", ProcedureNumber);
00961 }
00962
00963
if (ProcedureNumber) {
00964 Thunk.u1.Ordinal = ProcedureNumber | IMAGE_ORDINAL_FLAG;
00965 }
else {
00966
return STATUS_INVALID_PARAMETER;
00967 }
00968 }
00969
00970
if (
LdrpInLdrInit ==
FALSE ) {
00971 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
00972 }
00973
try {
00974
00975
if (!
LdrpCheckForLoadedDllHandle(DllHandle, &LdrDataTableEntry)) {
00976 st = STATUS_DLL_NOT_FOUND;
00977
return st;
00978 }
00979
00980 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData(
00981 LdrDataTableEntry->DllBase,
00982
TRUE,
00983 IMAGE_DIRECTORY_ENTRY_EXPORT,
00984 &ExportSize
00985 );
00986
00987
if (!ExportDirectory) {
00988
return STATUS_PROCEDURE_NOT_FOUND;
00989 }
00990
00991 st =
LdrpSnapThunk(LdrDataTableEntry->DllBase,
00992 ImageBase,
00993 &Thunk,
00994 &Thunk,
00995 ExportDirectory,
00996 ExportSize,
00997
FALSE,
00998
NULL
00999 );
01000
01001
if ( RunInitRoutines ) {
01002 PLDR_DATA_TABLE_ENTRY LdrInitEntry;
01003
01004
01005
01006
01007
01008
01009
01010 Next = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
01011 LdrInitEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
01012
if ( !(LdrInitEntry->Flags & LDRP_ENTRY_PROCESSED) ) {
01013
try {
01014 st =
LdrpRunInitializeRoutines(
NULL);
01015 }
01016 except(
EXCEPTION_EXECUTE_HANDLER ) {
01017 st = GetExceptionCode();
01018 }
01019
01020 }
01021 }
01022
01023
if (
NT_SUCCESS(st) ) {
01024 *ProcedureAddress = (PVOID)Thunk.u1.Function;
01025
#if defined (WX86)
01026
01027
01028
if (Wx86ProcessInit && (LdrDataTableEntry->Flags & LDRP_WX86_PLUGIN)) {
01029 PVOID ExportThunk =
NULL;
01030
USHORT MachineType =
RtlImageNtHeader(LdrDataTableEntry->DllBase)->FileHeader.Machine;
01031
01032
01033
01034
if ((!Wx86KnownDll && (MachineType == IMAGE_FILE_MACHINE_I386))
01035 || (Wx86KnownDll && (MachineType != IMAGE_FILE_MACHINE_I386))) {
01036
01037
01038
01039 st = Wx86ThunkPluginExport(LdrDataTableEntry->DllBase,
01040 FunctionName? FunctionName->Name :
NULL,
01041 ProcedureNumber,
01042 (PVOID)(Thunk.u1.Function),
01043 &ExportThunk
01044 );
01045
if (
NT_SUCCESS(st) && ExportThunk) {
01046 *ProcedureAddress = ExportThunk;
01047 }
else {
01048
01049 *ProcedureAddress =
NULL;
01050 st = STATUS_INVALID_IMAGE_FORMAT;
01051 }
01052 }
01053 }
01054
#endif
01055
}
01056 } finally {
01057
if ( FunctionName && (FunctionName != (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer) ) {
01058
RtlFreeHeap(RtlProcessHeap(),0,FunctionName);
01059 }
01060
if (
LdrpInLdrInit ==
FALSE ) {
01061 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01062 }
01063 }
01064
return st;
01065 }
01066
01067
NTSTATUS
01068 NTAPI
01069 LdrVerifyImageMatchesChecksum (
01070 IN HANDLE ImageFileHandle,
01071 IN PLDR_IMPORT_MODULE_CALLBACK ImportCallbackRoutine OPTIONAL,
01072 IN PVOID ImportCallbackParameter,
01073 OUT PUSHORT ImageCharacteristics OPTIONAL
01074 )
01075 {
01076
01077
NTSTATUS Status;
01078 HANDLE Section;
01079 PVOID ViewBase;
01080 SIZE_T ViewSize;
01081 IO_STATUS_BLOCK IoStatusBlock;
01082 FILE_STANDARD_INFORMATION StandardInfo;
01083 PIMAGE_SECTION_HEADER LastRvaSection;
01084 BOOLEAN b;
01085 BOOLEAN JustDoSideEffects;
01086
01087
01088
01089
01090
01091
01092
01093
if ( (UINT_PTR) ImageFileHandle & 1 ) {
01094 JustDoSideEffects =
TRUE;
01095 }
01096
else {
01097 JustDoSideEffects =
FALSE;
01098 }
01099
01100
Status =
NtCreateSection(
01101 &Section,
01102 SECTION_MAP_EXECUTE,
01103
NULL,
01104
NULL,
01105 PAGE_EXECUTE,
01106 SEC_COMMIT,
01107 ImageFileHandle
01108 );
01109
if ( !
NT_SUCCESS(
Status) ) {
01110
return Status;
01111 }
01112
01113 ViewBase =
NULL;
01114 ViewSize = 0;
01115
01116
Status =
NtMapViewOfSection(
01117 Section,
01118 NtCurrentProcess(),
01119 (PVOID *)&ViewBase,
01120 0
L,
01121 0
L,
01122
NULL,
01123 &ViewSize,
01124 ViewShare,
01125 0
L,
01126 PAGE_EXECUTE
01127 );
01128
01129
if ( !
NT_SUCCESS(
Status) ) {
01130
NtClose(Section);
01131
return Status;
01132 }
01133
01134
01135
01136
01137
01138
01139
Status =
NtQueryInformationFile(
01140 ImageFileHandle,
01141 &IoStatusBlock,
01142 &StandardInfo,
01143
sizeof(StandardInfo),
01144 FileStandardInformation
01145 );
01146
01147
if ( !
NT_SUCCESS(
Status) ) {
01148
NtUnmapViewOfSection(NtCurrentProcess(),ViewBase);
01149
NtClose(Section);
01150
return Status;
01151 }
01152
01153
try {
01154
if ( JustDoSideEffects ) {
01155 b =
TRUE;
01156 }
01157
else {
01158 b =
LdrVerifyMappedImageMatchesChecksum(ViewBase,StandardInfo.EndOfFile.LowPart);
01159 }
01160
if (b && ARGUMENT_PRESENT( ImportCallbackRoutine )) {
01161 PIMAGE_NT_HEADERS NtHeaders;
01162 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
01163 ULONG ImportSize;
01164 PCHAR ImportName;
01165
01166
01167
01168
01169
01170
01171 LastRvaSection =
NULL;
01172 NtHeaders =
RtlImageNtHeader( ViewBase );
01173
if (ARGUMENT_PRESENT( ImageCharacteristics )) {
01174 *ImageCharacteristics = NtHeaders->FileHeader.Characteristics;
01175 }
01176
01177 ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)
01178
RtlImageDirectoryEntryToData( ViewBase,
01179
FALSE,
01180 IMAGE_DIRECTORY_ENTRY_IMPORT,
01181 &ImportSize
01182 );
01183
if (ImportDescriptor !=
NULL) {
01184
while (ImportDescriptor->Name) {
01185 ImportName = (PSZ)
RtlImageRvaToVa( NtHeaders,
01186 ViewBase,
01187 ImportDescriptor->Name,
01188 &LastRvaSection
01189 );
01190 (*ImportCallbackRoutine)( ImportCallbackParameter, ImportName );
01191 ImportDescriptor += 1;
01192 }
01193 }
01194 }
01195 }
01196 except (
EXCEPTION_EXECUTE_HANDLER) {
01197
NtUnmapViewOfSection(NtCurrentProcess(),ViewBase);
01198
NtClose(Section);
01199
return STATUS_IMAGE_CHECKSUM_MISMATCH;
01200 }
01201
NtUnmapViewOfSection(NtCurrentProcess(),ViewBase);
01202
NtClose(Section);
01203
if ( !b ) {
01204
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
01205 }
01206
return Status;
01207 }
01208
01209
NTSTATUS
01210 LdrQueryProcessModuleInformation(
01211 OUT PRTL_PROCESS_MODULES ModuleInformation,
01212 IN ULONG ModuleInformationLength,
01213 OUT PULONG ReturnLength OPTIONAL
01214 )
01215 {
01216
NTSTATUS Status;
01217 PPEB Peb;
01218 PLIST_ENTRY LoadOrderListHead;
01219 PLIST_ENTRY InitOrderListHead;
01220 ULONG RequiredLength;
01221 PLIST_ENTRY Next;
01222 PLIST_ENTRY Next1;
01223 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
01224 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
01225 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry1;
01226 ANSI_STRING AnsiString;
01227 PUCHAR s;
01228
01229 Peb = NtCurrentPeb();
01230
01231
01232
01233
01234
01235
if (
LdrpInLdrInit ==
FALSE ) {
01236 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01237 }
01238
01239
try {
01240 RequiredLength = FIELD_OFFSET( RTL_PROCESS_MODULES, Modules );
01241
if (ModuleInformationLength < RequiredLength) {
01242
Status = STATUS_INFO_LENGTH_MISMATCH;
01243 ModuleInfo =
NULL;
01244 }
01245
else {
01246 ModuleInformation->NumberOfModules = 0;
01247 ModuleInfo = &ModuleInformation->Modules[ 0 ];
01248
Status = STATUS_SUCCESS;
01249 }
01250
01251 LoadOrderListHead = &Peb->Ldr->InLoadOrderModuleList;
01252 InitOrderListHead = &Peb->Ldr->InInitializationOrderModuleList;
01253 Next = LoadOrderListHead->Flink;
01254
while ( Next != LoadOrderListHead ) {
01255 LdrDataTableEntry = CONTAINING_RECORD( Next,
01256 LDR_DATA_TABLE_ENTRY,
01257 InLoadOrderLinks
01258 );
01259
01260 RequiredLength +=
sizeof( RTL_PROCESS_MODULE_INFORMATION );
01261
if (ModuleInformationLength < RequiredLength) {
01262
Status = STATUS_INFO_LENGTH_MISMATCH;
01263 }
01264
else {
01265 ModuleInfo->MappedBase =
NULL;
01266 ModuleInfo->ImageBase = LdrDataTableEntry->DllBase;
01267 ModuleInfo->ImageSize = LdrDataTableEntry->SizeOfImage;
01268 ModuleInfo->Flags = LdrDataTableEntry->Flags;
01269 ModuleInfo->LoadCount = LdrDataTableEntry->LoadCount;
01270
01271 ModuleInfo->LoadOrderIndex = (
USHORT)(ModuleInformation->NumberOfModules);
01272
01273 ModuleInfo->InitOrderIndex = 0;
01274 Next1 = InitOrderListHead->Flink;
01275
while ( Next1 != InitOrderListHead ) {
01276 LdrDataTableEntry1 = CONTAINING_RECORD( Next1,
01277 LDR_DATA_TABLE_ENTRY,
01278 InInitializationOrderLinks
01279 );
01280
01281 ModuleInfo->InitOrderIndex++;
01282
if (LdrDataTableEntry1 == LdrDataTableEntry) {
01283
break;
01284 }
01285
01286 Next1 = Next1->Flink;
01287 }
01288
01289 AnsiString.Buffer = ModuleInfo->FullPathName;
01290 AnsiString.Length = 0;
01291 AnsiString.MaximumLength =
sizeof( ModuleInfo->FullPathName );
01292
RtlUnicodeStringToAnsiString( &AnsiString,
01293 &LdrDataTableEntry->FullDllName,
01294
FALSE
01295 );
01296 s = AnsiString.Buffer + AnsiString.Length;
01297
while (s > AnsiString.Buffer && *--s) {
01298
if (*s == (UCHAR)OBJ_NAME_PATH_SEPARATOR) {
01299 s++;
01300
break;
01301 }
01302 }
01303 ModuleInfo->OffsetToFileName = (
USHORT)(s - AnsiString.Buffer);
01304
01305 ModuleInfo++;
01306 }
01307
01308
if (ModuleInformation !=
NULL) {
01309 ModuleInformation->NumberOfModules++;
01310 }
01311
01312 Next = Next->Flink;
01313 }
01314
01315
if (ARGUMENT_PRESENT( ReturnLength )) {
01316 *ReturnLength = RequiredLength;
01317 }
01318 }
01319 finally {
01320
if (
LdrpInLdrInit ==
FALSE ) {
01321 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
01322 }
01323 }
01324
01325
return(
Status );
01326 }
01327
01328
#if defined(MIPS)
01329
VOID
01330 LdrProcessStarterHelper(
01331 IN PPROCESS_STARTER_ROUTINE ProcessStarter,
01332 IN PVOID RealStartAddress
01333 )
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 {
01359 (ProcessStarter)(RealStartAddress);
01360
NtTerminateProcess(NtCurrentProcess(),0);
01361 }
01362
01363
#endif