Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

ldrwx86.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 ldrwx86.c 00008 00009 Abstract: 00010 00011 This module implements the wx86 specific ldr functions. 00012 00013 Author: 00014 00015 13-Jan-1995 Jonle , created 00016 00017 Revision History: 00018 00019 15-Oct-1998 CBiks Modified the code that throws the architecture 00020 mismatch exception so the exception is only 00021 thrown for NT 3,0 and lower executables. This was 00022 changed to make the Wx86 loader behave like the 00023 real loader, which does not throw this exception. 00024 00025 Also added a call to the cleanup function when 00026 LdrpWx86LoadDll() fails. There were cases where the 00027 CPU failed to initialize but the Wx86 global pointers 00028 were not cleared and pointed to a invalid memory because 00029 wx86.dll was unloaded. 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 // We want to accept only Alpha32 images as native. USER_SHARED_DATA 00058 // will only include AXP64. 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 // Wx86 plugin support 00071 // 00072 00073 typedef struct _Wx86Plugin { 00074 LIST_ENTRY Links; // plugin list links 00075 PVOID DllBase; // plugin dll base 00076 ULONG Count; // number of providers 00077 PVOID Provider[WX86PLUGIN_MAXPROVIDER]; // dll base of providers for this plugin 00078 } WX86PLUGIN, *PWX86PLUGIN; // plugin list entry 00079 00080 LIST_ENTRY Wx86PluginList= { // plugin list head 00081 &Wx86PluginList, 00082 &Wx86PluginList 00083 }; 00084 00085 // Prototypes for plugin provider interfaces 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 Routine Description: 00130 00131 Verifies that the LdrEntry matches the specifed dll. 00132 00133 Arguments: 00134 00135 BaseDllName - Unicode string describing Base Name of the Dll. 00136 00137 FullDllName - Unicode string describing full path Name of the Dll. 00138 Set FullDllName length to zero for no full path matching. 00139 00140 LdrEntry - loader information for dll found by basename compare. 00141 00142 ImporterX86 - TRUE if Importer is X86. 00143 00144 00145 Return Value: 00146 00147 TRUE if any of the following conditions are met. 00148 - FullDllName is same as LdrEntry FullDllName. 00149 - Machine Type is the same. 00150 - x86 importer AND LdrEntry is a Wx86 Risc thunk dll. 00151 00152 --*/ 00153 00154 { 00155 USHORT MachineType; 00156 BOOLEAN FullNameMatches = FALSE; 00157 PIMAGE_NT_HEADERS NtHeaders; 00158 00159 00160 // 00161 // The Base name must match. 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 // if we are not checking Machine Type, return based 00178 // on FullName matching. 00179 // LDRP_WX86_IGNORE_MACHINETYPE is used for images with no exports 00180 // LDRP_WX86_PLUGIN is used when there's a plug provider that will 00181 // dynamically generate thunks when GetProcAddress() is called. 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 // Allow cross platform linking for x86 to risc Wx86 thunk 00199 // dlls. All risc Wx86 Thunk dlls are marked as Wx86 Thunk dlls 00200 // in the ntheader. 00201 // 00202 if (FullNameMatches) { 00203 return (NtHeaders->OptionalHeader.DllCharacteristics 00204 & IMAGE_DLLCHARACTERISTICS_X86_THUNK) != 0; 00205 } 00206 00207 // 00208 // The full name doesn't match, we can still allow matches 00209 // for loads which were redirected from system32 to wx86 00210 // system dir (See LdrpWx86MapDll). 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 // Importer is Risc. 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 Routine Description: 00262 00263 Search the path for a dll, based on Wx86 altered search path rules. 00264 00265 Arguments: 00266 00267 DllPath - search path to use. 00268 00269 BaseName - Name of dll to search for. 00270 00271 FileName - addr of Unicode string to fill in the found dll path name. 00272 00273 pNextDllPath - addr to fill in next path component to be searched. 00274 00275 Return Value: 00276 00277 --*/ 00278 00279 { 00280 PWCHAR pwch; 00281 ULONG Length; 00282 00283 // 00284 // formulate the name for each path component, 00285 // and see if it exists. 00286 // 00287 00288 Length = BaseName->Length + 2*sizeof(WCHAR); 00289 00290 do { 00291 pwch = FileName->Buffer; 00292 00293 // 00294 // copy up till next semicolon 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 // if we got a path component, append the basename 00316 // and return if it exists. 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 Routine Description: 00350 00351 Invoked by the nt loader immediately after an x86 Dll is Mapped or 00352 unmapped from memory. This routine is not called at a point where 00353 it is safe to load other dlls. That work should be deferred till 00354 as late as possible before the x86 code is actually going to be executed. 00355 00356 Arguments: 00357 00358 DllBase - Base address of the DLL 00359 00360 Mapped - TRUE if the DLL is being mapped, FALSE if it is being unmapped. 00361 00362 Return Value: 00363 00364 FALSE on failure, TRUE on success. 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 Routine Description: 00388 00389 Resolves dll name, creates image section and maps image into memory. 00390 00391 00392 Arguments: 00393 00394 DllPath - Supplies the DLL search path. 00395 00396 DllCharacteristics - Supplies an optional DLL characteristics flag, 00397 that if specified is used to match against the dll being loaded. 00398 (IMAGE_FILE_HEADER Characteristics) 00399 00400 Wx86KnownDll - if true, Importer is x86. 00401 00402 StaticLink - TRUE, if static link and not dynamic. 00403 00404 DllName - Name of Dll to map. 00405 00406 pEntry - returns filled LdrEntry allocated off of the process heap. 00407 00408 pViewSize - returns the View Size of mapped image. 00409 00410 pSection - returns the section handle. 00411 00412 00413 00414 Return Value: 00415 00416 Status 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 // If DllPath is not supplied, use the loader's default path 00462 // 00463 00464 if (!DllPath) { 00465 DllPath = LdrpDefaultPath.Buffer; 00466 } 00467 00468 // 00469 // DllPath can be ignored if: 00470 // 1) DllPath is the null string 00471 // or 2) DllName contains a hard coded path 00472 // 00473 00474 if (!*DllPath || 00475 RtlDetermineDosPathNameType_U(DllName->Buffer) != RtlPathTypeRelative) 00476 { 00477 DllPath = NULL; 00478 } 00479 00480 00481 00482 // 00483 // Alloc a chunk of memory to use in constructing the full 00484 // dll name from the path and file name. Note that because 00485 // a path component may contain relative references, it may 00486 // exceed MAX_PATH. 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 // If we are looking for an x86 dll and it's base name is one of the 00512 // Wx86 thunk dlls, map the Wx86 thunk dll instead 00513 // 00514 // 00515 // X86 importers: force Wx86 system32 path before NtSystem32 path. 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 // Looking for x86 dll ... 00528 00529 if (Wx86KnownDllName(&LocalDllName, &ThunkDllName)) { 00530 // It's a thunked dll. Redirect to system32<thunk dll> 00531 ForcedDllPath = &LdrpKnownDllPath; 00532 ForcedDllName = &ThunkDllName; // use the thunked dll 00533 00534 } else if (Wx86KnownRedistDll(&LocalDllName)) { 00535 // It's a redistributed x86 dll. Redirect to sys32x86<dll name> 00536 ForcedDllPath = &Wx86SystemDir; 00537 ForcedDllName = &LocalDllName; // use the input dll name 00538 00539 } 00540 } 00541 00542 // if ForcedDllPath is not NULL, disable path searching and retries. 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; // disable path searching 00556 Wx86DirOverride = TRUE; // don't retry the load 00557 } 00558 00559 // Loop as long as there are more directories in DllSearchPath 00560 // or at least once if path searching is disabled. 00561 00562 while (TRUE) { 00563 00564 // Find the next occurance of the dll in the DllPath directories. 00565 // If no DllPath then use DllName as provided 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 // Setup FullNameUnicode, BaseNameUnicode strings 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 // Create the image section. 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 // Query the section info to discover its attributes 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 // MachineType is native type, allow: 00684 // - if risc importer 00685 // - if Wx86 thunk dlls 00686 // - if image contains no exports, 00687 // since Wx86 thunk dll not required (richedt32.dll). 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 // Machine Type is not native, allow: 00709 // - if x86 importer, and machine type is x86 00710 // - if image doesn't contain code, 00711 // since its probably a resource\data dll only. 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 // Failure because of an image machine mismatch. 00732 // Save the mapped dll information for plugin processing or a hard 00733 // error in case we can't find an image with matching machine type. 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 // If we previously overid system32 with wx86 sys dir 00766 // undo the override by retrying with system32. 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 // if x86 Importer, with hardcoded path to system32, retry with 00784 // the Wx86 system directory. This is because some apps, erroneously 00785 // derive the system32 path by appending system32 to WinDir, instead 00786 // of calling GetSystemDir(). 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 // Try further down the path, for a matching machine type 00808 // if no more path to search, we fail. 00809 // 00810 00811 if (!DllSearchPath || !*DllSearchPath) { 00812 break; 00813 } 00814 00815 } // while (TRUE) 00816 00817 00818 00819 // 00820 // Cleanup the temporary allocated buffers. 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 // Mismatch was encountered, but a DLL further along the path 00831 // did match. Cleanup the mismatch stuff. 00832 // 00833 NtClose(MismatchSection); 00834 MismatchSection = NULL; 00835 MismatchEncountered = FALSE; 00836 } else { 00837 // 00838 // No matching DLL found. Revert back to the image that gave the 00839 // image type mismatch. 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 // Map the section into memory 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 // Save this return code because it may be STATUS_IMAGE_NOT_AT_BASE. 00868 // This status must be returned so the dll will be relocated by the caller. 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 // Fix up non alpha compatible images 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 // Encountered a mismatch image type and didn't find another 00903 // that matches. Attempt to find a plugin provider dll that 00904 // can thunk this interface. 00905 // If there are no errors in plugin processing: 00906 // st = STATUS_SUCCESS if plugin was thunked 00907 // st = STATUS_IMAGE_MACHINE_TYPE_MISMATCH if not thunked 00908 // Otherwise st will contain the error from the plugin code 00909 00910 PLDR_DATA_TABLE_ENTRY Temp; 00911 00912 // temporarily insert the image in the loaded-module-list 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 // Determine if this dll can be thunked using a plugin 00926 00927 st = Wx86IdentifyPlugin(ViewBase, &FullNameUnicode ); 00928 00929 // remove the image from the loaded-module-list. 00930 // It will be added again in the main-line path. 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 // If plug provider supports this dll flag it and restore 00955 // status to the return code from original NtMapViewOfSection. 00956 // Howver, don't revert to STATUS_IMAGE_MACHINE_TYPE_MISMATCH - 00957 // that's what we just fixed up. 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 // Encountered a mismatch image type. 00971 // Raise a Hard Error for the machine mismatch. 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 // if we were successfull, 01005 // allocate and fill FullDllName, BaseDllName for the caller. 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 // Fil in loader entry 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 // Copy in the full dll name 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 // Copy in the basename 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 // cleanup items saved from mismatched images 01092 01093 if (MismatchSection) { 01094 NtClose(MismatchSection); 01095 } 01096 01097 if (FullName.Buffer) { 01098 RtlFreeHeap(RtlProcessHeap(), 0, FullName.Buffer); 01099 } 01100 01101 // 01102 // If failure, cleanup mapview and section. 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 Routine Description: 01147 01148 Checks for loaded dlls, ensuring that duplicate module 01149 base names are resolved correctly 01150 01151 Arguments: 01152 01153 DllPath - optional search path used to locate the DLL. 01154 01155 DllName - Name of Dll 01156 01157 Wx86KnownDll - if true, Importer is x86. 01158 01159 FullDllName - buffer to receive full path name, 01160 assumes STATIC_UNICODE_BUFFER_LENGTH 01161 01162 Return Value: 01163 01164 LdrEntry for dllname if found, otherwise NULL. 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 // If DllPath is not supplied, use the loader's default path 01183 // 01184 01185 if (!DllPath) { 01186 DllPath = LdrpDefaultPath.Buffer; 01187 } 01188 01189 // 01190 // DllPath can be ignored if: 01191 // 1) DllPath is unusable (=1) 01192 // or 2) DllPath is the null string 01193 // or 3) DllName contains a hard coded path 01194 // 01195 01196 if ((UINT_PTR)DllPath == 1 || !*DllPath || 01197 RtlDetermineDosPathNameType_U(DllName->Buffer) != RtlPathTypeRelative) 01198 { 01199 DllPath = NULL; 01200 } 01201 01202 // 01203 // Alloc a chunk of memory to use in constructing the full 01204 // dll name from the path and file name. Note that because 01205 // a path component may contain relative references, it may 01206 // exceed MAX_PATH. 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 // Checking for known dlls before searching for the file improves performance 01224 // This code was moved from the do loop. 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) { // if the call is from x86 apps 01237 // Looking for x86 dll ... 01238 01239 if (Wx86KnownDllName(&LocalDllName, &ThunkDllName)) { 01240 // It's a thunked dll. Redirect to system32<thunk dll> 01241 ForcedDllPath = &LdrpKnownDllPath; 01242 ForcedDllName = &ThunkDllName; // use the thunked dll 01243 01244 } else if (Wx86KnownRedistDll(&LocalDllName)) { 01245 // It's a redistributed x86 dll. Redirect to sys32x86<dll name> 01246 ForcedDllPath = &Wx86SystemDir; 01247 ForcedDllName = &LocalDllName; // use the input dll name 01248 01249 } 01250 01251 } else if (Wx86KnownNativeDll(&LocalDllName)) { 01252 // It's a native known dll. Redirect to system32<dll name> 01253 ForcedDllPath = &LdrpKnownDllPath; 01254 ForcedDllName = &LocalDllName; 01255 } 01256 01257 // If ForcedDllPath is not null, then we either need to find the dll at the 01258 // predetermined path or we return failed. 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 // not a Wx86 Known dll or Wx86 Known dll is not loaded. 01284 } 01285 01286 return NULL; 01287 } 01288 01289 // 01290 // Search the DllPath, and verify that fullpath and machine type match. 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 // Form the fullpathname 01332 // 01333 01334 FullDllName->Length = 0; 01335 Length = RtlGetFullPathName_U(pwch, 01336 FullDllName->MaximumLength, 01337 FullDllName->Buffer, 01338 &pwch // receives address of file name portion 01339 ); 01340 01341 if (Length && Length < FullDllName->MaximumLength) { 01342 UNICODE_STRING PathPart; 01343 01344 // Setup BaseDllName as the file name portion of FullDllName 01345 01346 FullDllName->Length = (USHORT)Length; 01347 RtlInitUnicodeString(&BaseDllName, pwch); 01348 01349 // Setup PathPart as the path portion of FullDllName 01350 01351 PathPart = *FullDllName; 01352 PathPart.Length = (USHORT)((ULONG_PTR)BaseDllName.Buffer - 01353 (ULONG_PTR)FullDllName->Buffer - 01354 sizeof(WCHAR) 01355 ); 01356 // 01357 // Search Loader HashTable by BaseName. 01358 // For each matching basename, verify the full path and machine type. 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 // TBD: need to add code from LdrpCheckForLoadedDll 01380 // 01381 // no names matched. This might be a long short name mismatch or 01382 // any kind of alias pathname. Deal with this by opening and mapping 01383 // full dll name and then repeat the scan this time checking for 01384 // timedatestamp matches 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 Routine Description: 01411 01412 Handles process detach for LdrUnload 01413 01414 Arguments: 01415 01416 InitRoutine - address of i386 dll entry point 01417 DllBase - standard dll entry point parameters 01418 01419 01420 Return Value: 01421 01422 SUCCESS or reason 01423 01424 --*/ 01425 { 01426 PIMAGE_NT_HEADERS NtHeader; 01427 PDLL_INIT_ROUTINE InitRoutine; 01428 01429 01430 // 01431 // check for all x86dlls unloaded 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 Routine Description: 01478 01479 Invokes the i386 emulator (wx86.dll) to run dll entry points. 01480 01481 Arguments: 01482 01483 InitRoutine - address of i386 dll entry point 01484 01485 pInitStatus - receives return code from the InitRoutine 01486 01487 DllBase - standard dll entry point parameters 01488 Reason 01489 Context 01490 01491 01492 Return Value: 01493 01494 SUCCESS or reason 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 Routine Description: 01532 01533 When Wx86.dll process detach routine executes, Wx86.dll invokes this routine 01534 so that the loader can cleanup Wx86 specific stuff. 01535 01536 01537 Arguments: 01538 01539 none 01540 01541 Return Value: 01542 01543 SUCCESS or reason 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 Routine Description: 01580 01581 Loads in the i386 emulator (wx86.dll) and performs process initialization 01582 for wx86 specific ldr code. 01583 01584 Arguments: 01585 01586 Context, initial process context, 01587 if hibit set this is ofly init after process initialzation is complete 01588 (Wx86 on the fly), and the PCONTEXT == Wx86DllHandle | 0x80000000 01589 01590 Return Value: 01591 01592 SUCCESS or reason 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 // Retrieve the dll handle for the ofly case 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 // initialize Wx86SystemDir 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 // Load Wx86.dll, wintdll.dll. This must be done before the app binary is 01641 // snapped to ensure wx86.dll is ready for emulation. 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 // Get fn address from Wx86.dll 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 // If the load failed make sure we clean-up. 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 Routine Description: 01783 01784 Per thread wx86 specific initialization. 01785 01786 Arguments: 01787 01788 Return Value: 01789 01790 SUCCESS or reason 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 // From mi\mi.h: 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 Routine Description: 01870 01871 01872 This function loops thru the images sections/objects, setting 01873 all relocated shared sections/objects marked r/o to r/w. It also resets the 01874 original section/object protections. 01875 01876 Arguments: 01877 01878 Base - Base of image. 01879 01880 Reset - If TRUE, reset section/object protection to original 01881 protection described by the section/object headers. 01882 If FALSE, then set all sections/objects to r/w. 01883 01884 Return Value: 01885 01886 SUCCESS or reason NtProtectVirtualMemory failed. 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 // Object isn't writeable, so change it. 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 // Copy each section from its raw file address to its virtual address 02003 // 02004 02005 SectionTable = IMAGE_FIRST_SECTION(NtHeaders); 02006 LastSection = SectionTable + NtHeaders->FileHeader.NumberOfSections; 02007 02008 if (SectionTable->PointerToRawData == SectionTable->VirtualAddress) { 02009 // If the first section does not need to be moved then we exclude it 02010 // from condideration in passes 1 and 2 02011 FirstSection = SectionTable + 1; 02012 } 02013 else { 02014 FirstSection = SectionTable; 02015 } 02016 02017 // 02018 // First pass starts at the top and works down moving up each section that 02019 // is to be moved up. 02020 // 02021 Section = FirstSection; 02022 while (Section < LastSection) { 02023 SrcVirtualAddress = ImageBase + Section->PointerToRawData; 02024 DestVirtualAddress = Section->VirtualAddress + ImageBase; 02025 02026 if (DestVirtualAddress > SrcVirtualAddress) { 02027 // Section needs to be moved down 02028 break; 02029 } 02030 02031 // Section needs to be moved up 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 // Second pass is from the end of the image and work backwards since src and 02048 // dst overlap 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 // Compute the subsection size. The mm is really flexible here... 02059 // it will allow a SizeOfRawData that far exceeds the virtual size, 02060 // so we can't trust that. If that happens, just use the page-aligned 02061 // virtual size, since that is all that the mm will map in. 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 // ensure Virtual section doesn't overlap the next section 02071 // 02072 if (DestVirtualAddress + SubSectionSize > NextVirtualAddress) { 02073 Wx86SetRelocatedSharedProtection(DllBase, TRUE); 02074 return STATUS_INVALID_IMAGE_FORMAT; 02075 } 02076 02077 if (DestVirtualAddress < SrcVirtualAddress) { 02078 // Section needs to be moved up 02079 break; 02080 } 02081 02082 // Section needs to be moved down 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 // Third pass is for zeroing out any memory left between the end of a 02100 // section and the end of the page. We'll do this from end to top 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 // Shared Data sections cannot be shared, because of 02111 // page misalignment, and are treated as Exec- Copy on Write. 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 // If section was empty zero it out 02126 // 02127 if (Section->SizeOfRawData != 0) { 02128 if (Section->PointerToRawData == 0) { 02129 RtlZeroMemory(DestVirtualAddress, 02130 Section->SizeOfRawData 02131 ); 02132 } 02133 } 02134 02135 // 02136 // Zero out remaining bytes up to the next section 02137 // 02138 RtlZeroMemory(DestVirtualAddress + Section->SizeOfRawData, 02139 (ULONG)(NextVirtualAddress - DestVirtualAddress - Section->SizeOfRawData) 02140 ); 02141 02142 NextVirtualAddress = DestVirtualAddress; 02143 Section--; 02144 } 02145 02146 // Pass 4: if the dll has any shared sections, change the shared data 02147 // references to point to additional shared pages at the end of the image. 02148 // 02149 // Note that our fixups are applied assuming that the dll is loaded at 02150 // its preferred base; if it is loaded at some other address, it will 02151 // be relocated again along will al other addresses. 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 // Account for raw data that extends beyond SizeOfImage 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 // Note that if this fails, it should fail in the very 02224 // first iteration and no fixups would have been performed 02225 02226 if (!bFirst) 02227 { 02228 // Trouble 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 // Trouble 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 // Zero out first section's Raw Data up to its VirtualAddress 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 // Trouble 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 // Following fn is adapted from rtl\ldrreloc.c; it should be updated when 02498 // that function changes. Eliminated 64 bit address relocations. 02499 // 02500 // Note: Instead of calling this routine, we could call 02501 // LdrpProcessRelocationBlock(VA, 1, NextOffset, Diff) 02502 // 02503 // but we should do that only if the address to be relocated is between 02504 // SectionStartVA and SectionEndVA. So we would have to replicate all the 02505 // code in the switch stmt below that computes the address of the data item - 02506 // which is pretty much the entire function. So we chose to replicate the 02507 // function as it was and change it to make the test. 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 // Apply the fixups. 02530 // 02531 02532 switch ((*NextOffset) >> 12) { 02533 02534 case IMAGE_REL_BASED_HIGHLOW : 02535 // 02536 // HighLow - (32-bits) relocate the high and low half 02537 // of an address. 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 // High - (16-bits) relocate the high half of an address. 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 // Adjust high - (16-bits) relocate the high half of an 02565 // address and adjust for sign extension of low half. 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 // Low - (16-bit) relocate the low half of an address. 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 // Align it to bundle address before fixing up the 02597 // 64-bit immediate value of the movl instruction. 02598 // 02599 02600 // No need to support 02601 02602 break; 02603 02604 case IMAGE_REL_BASED_DIR64: 02605 02606 // 02607 // Update 32-bit address 02608 // 02609 02610 // No need to support 02611 02612 break; 02613 02614 case IMAGE_REL_BASED_MIPS_JMPADDR : 02615 // 02616 // JumpAddress - (32-bits) relocate a MIPS jump address. 02617 // 02618 02619 // No need to support 02620 break; 02621 02622 case IMAGE_REL_BASED_ABSOLUTE : 02623 // 02624 // Absolute - no fixup required. 02625 // 02626 break; 02627 02628 case IMAGE_REL_BASED_SECTION : 02629 // 02630 // Section Relative reloc. Ignore for now. 02631 // 02632 break; 02633 02634 case IMAGE_REL_BASED_REL32 : 02635 // 02636 // Relative intrasection. Ignore for now. 02637 // 02638 break; 02639 02640 case IMAGE_REL_BASED_HIGH3ADJ : 02641 // 02642 // Similar to HIGHADJ except this is the third word. 02643 // Adjust low half of high dword of an address and adjust for 02644 // sign extension of the low dword. 02645 // 02646 02647 // No need to support 02648 ++NextOffset; 02649 --SizeOfBlock; 02650 ++NextOffset; 02651 --SizeOfBlock; 02652 02653 break; 02654 02655 default : 02656 // 02657 // Illegal - illegal relocation type. 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 Routine Description: 02678 02679 Determine which (if any) plugin provider dlls support this plugin. 02680 02681 All registered plugin provider dlls are loaded sequentially and given 02682 an opportunity to examine the the plugin dll. Provider dlls that support 02683 the plugin are stored in a WX86PLUGIN object and linked into Wx86PluginList. 02684 02685 Note: This routine may be invoked before Wx86 has been loaded so the 02686 global values initialized by LdrpLoadWx86 cannot be used. 02687 02688 Return Value: 02689 02690 STATUS_SUCCESS - The dll is supported by at least one plugin provider. 02691 02692 STATUS_IMAGE_MACHINE_TYPE_MISMATCH - There are no plugin providers that support this dll. 02693 02694 Other - failure in Wx86IdentifyPlugIn 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 // Identify the plugin by trying each plugin provider in turn. 02729 // The absence of the Provider registry key is a switch to turn off plugin support. 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 // Initialize the base path of the provider dlls 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 // Get the name of the next plugin provider dll 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 // Get the full provider dll path by appending the name to the base provider path 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 // Get the name of an export this provider requires (if any). If the plugin dll doesn't 02813 // have this export then it's not possible for this provider to support it. This 02814 // is a quick check which excludes most false tests for plug providers. 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 // The required export exists so it's time to load the provider and do the full check 02842 // On error skip to the next provider 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 } // loaded provder dll 02867 } // opened provider key 02868 } while ((++Index < NumProviders) && (Count < WX86PLUGIN_MAXPROVIDER)); 02869 02870 // Return success if we found at least on plugin provider. Allocate a WX86PLUGIN 02871 // list entry to keep track of which provders were loaded for this plugin 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 // On error exit release any provider dlls that were loaded 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 Routine Description: 02923 02924 This procedure is called during GetProcAddress() processing when 02925 the request if for a cross-architecure procedure address in an 02926 image which was loaded as a plugin dll (LDRP_WX86_PLUGIN flag). 02927 02928 The providers associated with this plugin dll are called in order 02929 to provide a thunk for the specified plugin export. The thunk attempt 02930 stops when a provider successfully thunks the export. 02931 02932 Return Value: 02933 02934 STATUS_SUCCESS - if export is successfully thunked 02935 02936 STATUS_PROCEDURE_NOT_FOUND - if export cannot be thunked 02937 02938 STATUS_INVALID_IMAGE_FORMAT - DllBase is invalid 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 // Find the Wx86Plugin entry with a matching DllBase 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 // No Wx86Plugin entry for this Dll 02971 02972 if (Next == Head) { 02973 return STATUS_PROCEDURE_NOT_FOUND; 02974 } 02975 02976 // Get the address of the routine to thunk exports for each provider 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 Routine Description: 03019 03020 Handle unloading of plugin dlls. 03021 03022 The DllBase passed in may have already been unloaded. However, it is used here 03023 only to find the associated plugin provider dll. 03024 03025 Return Value: 03026 03027 FALSE on failure, TRUE on success. 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 // Prevent recursion - Only perform this at the top level. 03038 // This is relevant when being called from LdrUnloadDll 03039 03040 if (Wx86ProviderUnloadCount == 0) { 03041 try { 03042 Wx86ProviderUnloadCount++; 03043 03044 // Find the the entry for this plugin dll 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 // If the plugin dll is no longer mapped then unload the providers 03053 // and free the Wx86PluginList entry 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

Generated on Sat May 15 19:40:38 2004 for test by doxygen 1.3.7