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