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

ldrinit.c File Reference

#include <ntos.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <heap.h>
#include <apcompat.h>
#include "ldrp.h"
#include <ctype.h>

Go to the source code of this file.

Functions

VOID LdrpRelocateStartContext (IN PCONTEXT Context, IN LONG_PTR Diff)
NTSTATUS LdrpForkProcess (VOID)
VOID LdrpInitializeThread (IN PCONTEXT Context)
BOOLEAN NtdllOkayToLockRoutine (IN PVOID Lock)
VOID RtlpInitDeferedCriticalSection (VOID)
VOID LdrQueryApplicationCompatibilityGoo (IN PUNICODE_STRING UnicodeImageName)
NTSTATUS LdrFindAppCompatVariableInfo (IN ULONG dwTypeSeeking, OUT PAPP_VARIABLE_INFO *AppVariableInfo)
NTSTATUS LdrpSearchResourceSection_U (IN PVOID DllHandle, IN PULONG_PTR ResourceIdPath, IN ULONG ResourceIdPathLength, IN BOOLEAN FindDirectoryEntry, IN BOOLEAN ExactLangMatchOnly, OUT PVOID *ResourceDirectoryOrData)
NTSTATUS LdrpAccessResourceData (IN PVOID DllHandle, IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, OUT PVOID *Address OPTIONAL, OUT PULONG Size OPTIONAL)
PVOID NtdllpAllocateStringRoutine (SIZE_T NumberOfBytes)
VOID NtdllpFreeStringRoutine (PVOID Buffer)
VOID LdrpInitializationFailure (IN NTSTATUS FailureCode)
VOID LdrpInitialize (IN PCONTEXT Context, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
NTSTATUS LdrpInitializeProcess (IN PCONTEXT Context OPTIONAL, IN PVOID SystemDllBase, IN PUNICODE_STRING UnicodeImageName)
VOID LdrShutdownProcess (VOID)
VOID LdrShutdownThread (VOID)
NTSTATUS LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING ImagePathName, IN PWSTR OptionName, IN ULONG Type, OUT PVOID Buffer, IN ULONG BufferSize, OUT PULONG ResultSize OPTIONAL)
NTSTATUS LdrpInitializeTls (VOID)
NTSTATUS LdrpAllocateTls (VOID)
VOID LdrpFreeTls (VOID)
VOID LdrpCallTlsInitializers (PVOID DllBase, ULONG Reason)
ULONG GetNextCommaValue (IN OUT WCHAR **p, IN OUT ULONG *len)

Variables

BOOLEAN LdrpShutdownInProgress = FALSE
BOOLEAN LdrpImageHasTls = FALSE
BOOLEAN LdrpVerifyDlls = FALSE
BOOLEAN LdrpLdrDatabaseIsSetup = FALSE
BOOLEAN LdrpInLdrInit = FALSE
PVOID NtDllBase
ULONG RtlpDisableHeapLookaside
PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine
PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine
RTL_BITMAP TlsBitMap
RTL_BITMAP TlsExpansionBitMap
RTL_CRITICAL_SECTION_DEBUG LoaderLockDebug
RTL_CRITICAL_SECTION LoaderLock
BOOLEAN LoaderLockInitialized


Function Documentation

ULONG GetNextCommaValue IN OUT WCHAR **  p,
IN OUT ULONG *  len
 

Definition at line 2246 of file ldrinit.c.

References L.

Referenced by LdrQueryApplicationCompatibilityGoo().

02247 { 02248 ULONG Number = 0; 02249 02250 while (*len && (UNICODE_NULL != **p) && **p != L',') 02251 { 02252 // Let's ignore spaces 02253 if ( L' ' != **p ) 02254 { 02255 Number = (Number * 10) + ( (ULONG)**p - L'0' ); 02256 } 02257 02258 (*p)++; 02259 (*len)--; 02260 } 02261 02262 // 02263 // If we're at a comma, get past it for the next call 02264 // 02265 if ( L',' == **p ) 02266 { 02267 (*p)++; 02268 (*len)--; 02269 } 02270 02271 return Number; 02272 }

NTSTATUS LdrFindAppCompatVariableInfo IN ULONG  dwTypeSeeking,
OUT PAPP_VARIABLE_INFO *  AppVariableInfo
 

Definition at line 2683 of file ldrinit.c.

Referenced by LdrQueryApplicationCompatibilityGoo().

02690 : 02691 02692 This function is used to find a variable length struct by its type. 02693 The caller specifies what type its looking for and this function chews 02694 thru all the variable length structs to find it. If it does it returns 02695 the pointer and TRUE, else FALSE. 02696 02697 Arguments: 02698 02699 dwTypeSeeking - AVT that you are looking for 02700 02701 AppVariableInfo - pointer to pointer of variable info to be returned 02702 02703 Return Value: 02704 02705 TRUE or FALSE if entry is found 02706 02707 --*/ 02708 02709 { 02710 PPEB Peb; 02711 ULONG TotalSize; 02712 ULONG CurOffset; 02713 PAPP_VARIABLE_INFO pCurrentEntry; 02714 02715 Peb = NtCurrentPeb(); 02716 if (Peb->AppCompatInfo) { 02717 02718 // 02719 // Since we're not dealing with a fixed-size structure, TotalSize 02720 // will keep us from running off the end of the data list 02721 // 02722 TotalSize = ((PAPP_COMPAT_INFO) Peb->AppCompatInfo)->dwTotalSize; 02723 02724 // 02725 // The first variable structure (if there is one) will start 02726 // immediately after the fixed stuff 02727 // 02728 CurOffset = sizeof(APP_COMPAT_INFO); 02729 02730 while (CurOffset < TotalSize) { 02731 02732 pCurrentEntry = (PAPP_VARIABLE_INFO) ((PUCHAR)(Peb->AppCompatInfo) + CurOffset); 02733 02734 // 02735 // Have we found what we're looking for? 02736 // 02737 if (dwTypeSeeking == pCurrentEntry->dwVariableType) { 02738 *AppVariableInfo = pCurrentEntry; 02739 return (STATUS_SUCCESS); 02740 } 02741 02742 // 02743 // Let's go look at the next blob 02744 // 02745 CurOffset += (ULONG)(pCurrentEntry->dwVariableInfoSize); 02746 } 02747 02748 } 02749 02750 return (STATUS_NOT_FOUND); 02751 } }

NTSTATUS LdrpAccessResourceData IN PVOID  DllHandle,
IN PIMAGE_RESOURCE_DATA_ENTRY  ResourceDataEntry,
OUT PVOID *Address  OPTIONAL,
OUT PULONG Size  OPTIONAL
 

Definition at line 96 of file ldrrsrc.c.

00105 : 00106 00107 This function returns the data necessary to actually examine the 00108 contents of a particular resource. 00109 00110 Arguments: 00111 00112 DllHandle - Supplies a handle to the image file that the resource is 00113 contained in. 00114 00115 ResourceDataEntry - Supplies a pointer to the resource data entry in 00116 the resource data directory of the image file specified by the 00117 DllHandle parameter. This pointer should have been one returned 00118 by the LdrFindResource function. 00119 00120 Address - Optional pointer to a variable that will receive the 00121 address of the resource specified by the first two parameters. 00122 00123 Size - Optional pointer to a variable that will receive the size of 00124 the resource specified by the first two parameters. 00125 00126 00127 Return Value: 00128 00129 TBD 00130 00131 --*/ 00132 00133 { 00134 PIMAGE_RESOURCE_DIRECTORY ResourceDirectory; 00135 ULONG ResourceSize; 00136 PIMAGE_NT_HEADERS NtHeaders; 00137 ULONG_PTR VirtualAddressOffset; 00138 PIMAGE_SECTION_HEADER NtSection; 00139 00140 RTL_PAGED_CODE(); 00141 00142 #ifndef NTOS_KERNEL_RUNTIME 00143 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY) 00144 RtlImageDirectoryEntryToData(DllHandle, 00145 TRUE, 00146 IMAGE_DIRECTORY_ENTRY_RESOURCE, 00147 &ResourceSize 00148 ); 00149 if (!ResourceDirectory) { 00150 return( STATUS_RESOURCE_DATA_NOT_FOUND ); 00151 } 00152 00153 if ((ULONG_PTR)ResourceDataEntry < (ULONG_PTR) ResourceDirectory ){ 00154 DllHandle = LdrLoadAlternateResourceModule (DllHandle, NULL); 00155 } else{ 00156 NtHeaders = RtlImageNtHeader( 00157 (PVOID)((ULONG_PTR)DllHandle & ~0x00000001) 00158 ); 00159 if (NtHeaders) { 00160 // Find the bounds of the image so we can see if this resource entry is in an alternate 00161 // resource dll. 00162 00163 ULONG_PTR ImageStart = (ULONG_PTR)DllHandle & ~0x00000001; 00164 SIZE_T ImageSize = 0; 00165 00166 if ((ULONG_PTR)DllHandle & 0x00000001) { 00167 // mapped as datafile. Ask mm for the size 00168 NTSTATUS Status; 00169 MEMORY_BASIC_INFORMATION MemInfo; 00170 00171 Status = NtQueryVirtualMemory( 00172 NtCurrentProcess(), 00173 (PVOID) ImageStart, 00174 MemoryBasicInformation, 00175 (PVOID)&MemInfo, 00176 sizeof(MemInfo), 00177 NULL 00178 ); 00179 00180 if ( !NT_SUCCESS(Status) ) { 00181 ImageSize = 0; 00182 } else { 00183 ImageSize = MemInfo.RegionSize; 00184 } 00185 } else { 00186 ImageSize = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.SizeOfImage; 00187 } 00188 00189 if (!(((ULONG_PTR)ResourceDataEntry >= ImageStart) && ((ULONG_PTR)ResourceDataEntry < (ImageStart + ImageSize)))) { 00190 // Doesn't fall within the specified image. Must be an alternate dll. 00191 DllHandle = LdrLoadAlternateResourceModule (DllHandle, NULL); 00192 } 00193 } 00194 } 00195 00196 if (!DllHandle){ 00197 return ( STATUS_RESOURCE_DATA_NOT_FOUND ); 00198 } 00199 00200 #endif 00201 try { 00202 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY) 00203 RtlImageDirectoryEntryToData(DllHandle, 00204 TRUE, 00205 IMAGE_DIRECTORY_ENTRY_RESOURCE, 00206 &ResourceSize 00207 ); 00208 if (!ResourceDirectory) { 00209 return( STATUS_RESOURCE_DATA_NOT_FOUND ); 00210 } 00211 00212 if ((ULONG_PTR)DllHandle & 0x00000001) { 00213 ULONG ResourceRVA; 00214 DllHandle = (PVOID)((ULONG_PTR)DllHandle & ~0x00000001); 00215 NtHeaders = RtlImageNtHeader( DllHandle ); 00216 if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 00217 ResourceRVA=((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_RESOURCE ].VirtualAddress; 00218 } else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 00219 ResourceRVA=((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_RESOURCE ].VirtualAddress; 00220 } else { 00221 ResourceRVA = 0; 00222 } 00223 00224 if (!ResourceRVA) { 00225 return( STATUS_RESOURCE_DATA_NOT_FOUND ); 00226 } 00227 00228 VirtualAddressOffset = (ULONG_PTR)DllHandle + ResourceRVA - (ULONG_PTR)ResourceDirectory; 00229 00230 // 00231 // Now, we must check to see if the resource is not in the 00232 // same section as the resource table. If it's in .rsrc1, 00233 // we've got to adjust the RVA in the ResourceDataEntry 00234 // to point to the correct place in the non-VA data file. 00235 // 00236 NtSection= RtlSectionTableFromVirtualAddress( NtHeaders, DllHandle, ResourceRVA); 00237 00238 if (!NtSection) { 00239 return( STATUS_RESOURCE_DATA_NOT_FOUND ); 00240 } 00241 00242 if ( ResourceDataEntry->OffsetToData > NtSection->Misc.VirtualSize ) { 00243 ULONG rva; 00244 00245 rva = NtSection->VirtualAddress; 00246 NtSection= RtlSectionTableFromVirtualAddress(NtHeaders, 00247 DllHandle, 00248 ResourceDataEntry->OffsetToData 00249 ); 00250 VirtualAddressOffset += 00251 ((ULONG_PTR)NtSection->VirtualAddress - rva) - 00252 ((ULONG_PTR)RtlAddressInSectionTable ( NtHeaders, DllHandle, NtSection->VirtualAddress ) - (ULONG_PTR)ResourceDirectory); 00253 } 00254 } 00255 else { 00256 VirtualAddressOffset = 0; 00257 } 00258 00259 if (ARGUMENT_PRESENT( Address )) { 00260 *Address = (PVOID)( (PCHAR)DllHandle + 00261 (ResourceDataEntry->OffsetToData - VirtualAddressOffset) 00262 ); 00263 } 00264 00265 if (ARGUMENT_PRESENT( Size )) { 00266 *Size = ResourceDataEntry->Size; 00267 } 00268 } 00269 except (EXCEPTION_EXECUTE_HANDLER) { 00270 return GetExceptionCode(); 00271 } 00272 00273 return( STATUS_SUCCESS ); 00274 }

NTSTATUS LdrpAllocateTls VOID   ) 
 

Definition at line 2071 of file ldrinit.c.

References DbgPrint, LDRP_TLS_ENTRY, LdrpNumberOfTlsEntries, LdrpTlsList, MAKE_TAG, RtlAllocateHeap, ShowSnaps, _LDRP_TLS_ENTRY::Tls, and TLS_TAG.

Referenced by LdrpInitializeThread(), and LdrpInitializeTls().

02074 { 02075 PTEB Teb; 02076 PLIST_ENTRY Head, Next; 02077 PLDRP_TLS_ENTRY TlsEntry; 02078 PVOID *TlsVector; 02079 02080 Teb = NtCurrentTeb(); 02081 02082 // 02083 // Allocate the array of thread local storage pointers 02084 // 02085 02086 if ( LdrpNumberOfTlsEntries ) { 02087 TlsVector = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( TLS_TAG ),sizeof(PVOID)*LdrpNumberOfTlsEntries); 02088 if ( !TlsVector ) { 02089 return STATUS_NO_MEMORY; 02090 } 02091 02092 Teb->ThreadLocalStoragePointer = TlsVector; 02093 Head = &LdrpTlsList; 02094 Next = Head->Flink; 02095 02096 while ( Next != Head ) { 02097 TlsEntry = CONTAINING_RECORD(Next, LDRP_TLS_ENTRY, Links); 02098 Next = Next->Flink; 02099 TlsVector[TlsEntry->Tls.Characteristics] = RtlAllocateHeap( 02100 RtlProcessHeap(), 02101 MAKE_TAG( TLS_TAG ), 02102 TlsEntry->Tls.EndAddressOfRawData - TlsEntry->Tls.StartAddressOfRawData 02103 ); 02104 if (!TlsVector[TlsEntry->Tls.Characteristics] ) { 02105 return STATUS_NO_MEMORY; 02106 } 02107 02108 if (ShowSnaps) { 02109 DbgPrint("LDR: TlsVector %x Index %d = %x copied from %x to %x\n", 02110 TlsVector, 02111 TlsEntry->Tls.Characteristics, 02112 &TlsVector[TlsEntry->Tls.Characteristics], 02113 TlsEntry->Tls.StartAddressOfRawData, 02114 TlsVector[TlsEntry->Tls.Characteristics] 02115 ); 02116 } 02117 02118 RtlCopyMemory( 02119 TlsVector[TlsEntry->Tls.Characteristics], 02120 (PVOID)TlsEntry->Tls.StartAddressOfRawData, 02121 TlsEntry->Tls.EndAddressOfRawData - TlsEntry->Tls.StartAddressOfRawData 02122 ); 02123 02124 // 02125 // Do the TLS Callouts 02126 // 02127 02128 } 02129 } 02130 return STATUS_SUCCESS; 02131 }

VOID LdrpCallTlsInitializers PVOID  DllBase,
ULONG  Reason
 

Definition at line 2178 of file ldrinit.c.

References DbgPrint, EXCEPTION_EXECUTE_HANDLER, LdrpCallInitRoutine, NULL, RtlImageDirectoryEntryToData(), ShowSnaps, and TRUE.

Referenced by LdrpInitializeThread(), LdrpRunInitializeRoutines(), LdrShutdownProcess(), and LdrShutdownThread().

02182 { 02183 PIMAGE_TLS_DIRECTORY TlsImage; 02184 ULONG TlsSize; 02185 PIMAGE_TLS_CALLBACK *CallBackArray; 02186 PIMAGE_TLS_CALLBACK InitRoutine; 02187 02188 TlsImage = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData( 02189 DllBase, 02190 TRUE, 02191 IMAGE_DIRECTORY_ENTRY_TLS, 02192 &TlsSize 02193 ); 02194 02195 02196 try { 02197 if ( TlsImage ) { 02198 CallBackArray = (PIMAGE_TLS_CALLBACK *)TlsImage->AddressOfCallBacks; 02199 if ( CallBackArray ) { 02200 if (ShowSnaps) { 02201 DbgPrint( "LDR: Tls Callbacks Found. Imagebase %lx Tls %lx CallBacks %lx\n", 02202 DllBase, 02203 TlsImage, 02204 CallBackArray 02205 ); 02206 } 02207 02208 while(*CallBackArray){ 02209 InitRoutine = *CallBackArray++; 02210 02211 if (ShowSnaps) { 02212 DbgPrint( "LDR: Calling Tls Callback Imagebase %lx Function %lx\n", 02213 DllBase, 02214 InitRoutine 02215 ); 02216 } 02217 02218 #if defined (WX86) 02219 if (!Wx86ProcessInit || 02220 LdrpRunWx86DllEntryPoint( 02221 (PDLL_INIT_ROUTINE)InitRoutine, 02222 NULL, 02223 DllBase, 02224 Reason, 02225 NULL 02226 ) == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) 02227 #endif 02228 { 02229 LdrpCallInitRoutine((PDLL_INIT_ROUTINE)InitRoutine, 02230 DllBase, 02231 Reason, 02232 0); 02233 } 02234 02235 } 02236 } 02237 } 02238 } 02239 except (EXCEPTION_EXECUTE_HANDLER) { 02240 ; 02241 } 02242 }

NTSTATUS LdrpForkProcess VOID   ) 
 

Definition at line 575 of file ldrinit.c.

References FALSE, FastPebLock, LoaderLock, LoaderLockInitialized, NT_SUCCESS, NTSTATUS(), NULL, RtlCreateHeap(), RtlCriticalSectionList, RtlInitializeCriticalSection(), RtlInitializeHeapManager(), RtlpInitDeferedCriticalSection(), RtlRaiseStatus(), and TRUE.

Referenced by LdrpInitialize().

00576 { 00577 NTSTATUS st; 00578 PPEB Peb; 00579 00580 Peb = NtCurrentPeb(); 00581 00582 // 00583 // Initialize the critical section package. 00584 // 00585 00586 RtlpInitDeferedCriticalSection(); 00587 00588 InsertTailList(&RtlCriticalSectionList, &LoaderLock.DebugInfo->ProcessLocksList); 00589 LoaderLock.DebugInfo->CriticalSection = &LoaderLock; 00590 LoaderLockInitialized = TRUE; 00591 00592 st = RtlInitializeCriticalSection(&FastPebLock); 00593 if ( !NT_SUCCESS(st) ) { 00594 RtlRaiseStatus(st); 00595 } 00596 Peb->FastPebLock = &FastPebLock; 00597 Peb->FastPebLockRoutine = (PVOID)&RtlEnterCriticalSection; 00598 Peb->FastPebUnlockRoutine = (PVOID)&RtlLeaveCriticalSection; 00599 Peb->InheritedAddressSpace = FALSE; 00600 RtlInitializeHeapManager(); 00601 Peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, // Flags 00602 NULL, // HeapBase 00603 64 * 1024, // ReserveSize 00604 4096, // CommitSize 00605 NULL, // Lock to use for serialization 00606 NULL // GrowthThreshold 00607 ); 00608 if (Peb->ProcessHeap == NULL) { 00609 return STATUS_NO_MEMORY; 00610 } 00611 00612 return st; 00613 }

VOID LdrpFreeTls VOID   ) 
 

Definition at line 2134 of file ldrinit.c.

References LdrpTlsList, RtlFreeHeap, and _LDRP_TLS_ENTRY::Tls.

Referenced by LdrShutdownThread().

02137 { 02138 PTEB Teb; 02139 PLIST_ENTRY Head, Next; 02140 PLDRP_TLS_ENTRY TlsEntry; 02141 PVOID *TlsVector; 02142 02143 Teb = NtCurrentTeb(); 02144 02145 TlsVector = Teb->ThreadLocalStoragePointer; 02146 02147 if ( TlsVector ) { 02148 Head = &LdrpTlsList; 02149 Next = Head->Flink; 02150 02151 while ( Next != Head ) { 02152 TlsEntry = CONTAINING_RECORD(Next, LDRP_TLS_ENTRY, Links); 02153 Next = Next->Flink; 02154 02155 // 02156 // Do the TLS callouts 02157 // 02158 02159 if ( TlsVector[TlsEntry->Tls.Characteristics] ) { 02160 RtlFreeHeap( 02161 RtlProcessHeap(), 02162 0, 02163 TlsVector[TlsEntry->Tls.Characteristics] 02164 ); 02165 02166 } 02167 } 02168 02169 RtlFreeHeap( 02170 RtlProcessHeap(), 02171 0, 02172 TlsVector 02173 ); 02174 } 02175 }

VOID LdrpInitializationFailure IN NTSTATUS  FailureCode  ) 
 

Definition at line 157 of file ldrinit.c.

References LdrpFatalHardErrorCount, NtRaiseHardError(), and NTSTATUS().

Referenced by LdrpInitialize(), and LdrpInitializeProcess().

00160 { 00161 00162 NTSTATUS ErrorStatus; 00163 ULONG_PTR ErrorParameter; 00164 ULONG ErrorResponse; 00165 00166 if ( LdrpFatalHardErrorCount ) { 00167 return; 00168 } 00169 00170 // 00171 // Its error time... 00172 // 00173 ErrorParameter = (ULONG_PTR)FailureCode; 00174 ErrorStatus = NtRaiseHardError( 00175 STATUS_APP_INIT_FAILURE, 00176 1, 00177 0, 00178 &ErrorParameter, 00179 OptionOk, 00180 &ErrorResponse 00181 ); 00182 }

VOID LdrpInitialize IN PCONTEXT  Context,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 186 of file ldrinit.c.

References DbgPrint, EXCEPTION_EXECUTE_HANDLER, FALSE, L, LdrpForkProcess(), LdrpInitializationFailure(), LdrpInitializeProcess(), LdrpInitializeThread(), LdrpInLdrInit, LdrQueryImageFileExecutionOptions(), LoaderLock, LoaderLockInitialized, NT_SUCCESS, NtDelayExecution(), NtQueryPerformanceCounter(), NtQueryVirtualMemory(), NTSTATUS(), NtTestAlert(), NULL, RtlImageDirectoryEntryToData(), RtlImageNtHeader(), RtlpDebugPageHeap, RtlpDisableHeapLookaside, RtlpDphDllRangeEnd, RtlpDphDllRangeStart, RtlpDphGlobalFlags, RtlpDphRandomProbability, RtlpDphSizeRangeEnd, RtlpDphSizeRangeStart, RtlpDphTargetDlls, RtlRaiseStatus(), and TRUE.

00194 : 00195 00196 This function is called as a User-Mode APC routine as the first 00197 user-mode code executed by a new thread. It's function is to initialize 00198 loader context, perform module initialization callouts... 00199 00200 Arguments: 00201 00202 Context - Supplies an optional context buffer that will be restore 00203 after all DLL initialization has been completed. If this 00204 parameter is NULL then this is a dynamic snap of this module. 00205 Otherwise this is a static snap prior to the user process 00206 gaining control. 00207 00208 SystemArgument1 - Supplies the base address of the System Dll. 00209 00210 SystemArgument2 - not used. 00211 00212 Return Value: 00213 00214 None. 00215 00216 --*/ 00217 00218 { 00219 NTSTATUS st, InitStatus; 00220 PPEB Peb; 00221 PTEB Teb; 00222 UNICODE_STRING UnicodeImageName; 00223 MEMORY_BASIC_INFORMATION MemInfo; 00224 BOOLEAN AlreadyFailed; 00225 LARGE_INTEGER DelayValue; 00226 #if defined(_WIN64) 00227 PIMAGE_NT_HEADERS NtHeader; 00228 #endif 00229 00230 SystemArgument2; 00231 00232 AlreadyFailed = FALSE; 00233 Peb = NtCurrentPeb(); 00234 Teb = NtCurrentTeb(); 00235 00236 if (!Peb->Ldr) { 00237 #if defined(_ALPHA_) 00238 ULONG temp; 00239 00240 // 00241 // Set GP register 00242 // 00243 00244 LdrpGpValue = (ULONG_PTR)RtlImageDirectoryEntryToData( 00245 Peb->ImageBaseAddress, 00246 TRUE, 00247 IMAGE_DIRECTORY_ENTRY_GLOBALPTR, 00248 &temp 00249 ); 00250 if (Context != NULL) { 00251 LdrpSetGp( LdrpGpValue ); 00252 Context->IntGp = LdrpGpValue; 00253 } 00254 #endif // ALPHA 00255 00256 //#if DBG 00257 if (TRUE) 00258 //#else 00259 // if (Peb->BeingDebugged || Peb->ReadImageFileExecOptions) 00260 //#endif 00261 { 00262 PWSTR pw; 00263 00264 pw = (PWSTR)Peb->ProcessParameters->ImagePathName.Buffer; 00265 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROC_PARAMS_NORMALIZED)) { 00266 pw = (PWSTR)((PCHAR)pw + (ULONG_PTR)(Peb->ProcessParameters)); 00267 } 00268 UnicodeImageName.Buffer = pw; 00269 UnicodeImageName.Length = Peb->ProcessParameters->ImagePathName.Length; 00270 UnicodeImageName.MaximumLength = UnicodeImageName.Length; 00271 00272 // 00273 // Hack for NT4 SP4. So we don't overload another GlobalFlag 00274 // bit that we have to be "compatible" with for NT5, look for 00275 // another value named "DisableHeapLookaside". 00276 // 00277 00278 LdrQueryImageFileExecutionOptions( &UnicodeImageName, 00279 L"DisableHeapLookaside", 00280 REG_DWORD, 00281 &RtlpDisableHeapLookaside, 00282 sizeof( RtlpDisableHeapLookaside ), 00283 NULL 00284 ); 00285 00286 st = LdrQueryImageFileExecutionOptions( &UnicodeImageName, 00287 L"GlobalFlag", 00288 REG_DWORD, 00289 &Peb->NtGlobalFlag, 00290 sizeof( Peb->NtGlobalFlag ), 00291 NULL 00292 ); 00293 if (!NT_SUCCESS( st )) { 00294 00295 if (Peb->BeingDebugged) { 00296 Peb->NtGlobalFlag |= FLG_HEAP_ENABLE_FREE_CHECK | 00297 FLG_HEAP_ENABLE_TAIL_CHECK | 00298 FLG_HEAP_VALIDATE_PARAMETERS; 00299 } 00300 } 00301 00302 #if defined(_WIN64) 00303 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); 00304 if (NtHeader && NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 00305 UseWOW64 = TRUE; 00306 } 00307 #endif 00308 } 00309 00310 if ( Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS ) { 00311 00312 // 00313 // We will enable page heap (RtlpDebugPageHeap) only after 00314 // all other initializations for page heap are finished. 00315 // 00316 00317 // 00318 // If page heap is enabled we need to disable any flag that 00319 // might force creation of debug heaps for normal NT heaps. 00320 // This is due to a dependency between page heap and NT heap 00321 // where the page heap within PageHeapCreate tries to create 00322 // a normal NT heap to accomodate some of the allocations. 00323 // If we do not disable these flags we will get an infinite 00324 // recursion between RtlpDebugPageHeapCreate and RtlCreateHeap. 00325 // 00326 00327 Peb->NtGlobalFlag &= ~( FLG_HEAP_ENABLE_TAGGING | 00328 FLG_HEAP_ENABLE_TAG_BY_DLL | 00329 FLG_HEAP_ENABLE_TAIL_CHECK | 00330 FLG_HEAP_ENABLE_FREE_CHECK | 00331 FLG_HEAP_VALIDATE_PARAMETERS | 00332 FLG_HEAP_VALIDATE_ALL | 00333 FLG_USER_STACK_TRACE_DB ); 00334 00335 // 00336 // Read page heap per process global flags. If we fail 00337 // to read a value, the default ones are kept. 00338 // 00339 00340 LdrQueryImageFileExecutionOptions( 00341 &UnicodeImageName, 00342 L"PageHeapFlags", 00343 REG_DWORD, 00344 &RtlpDphGlobalFlags, 00345 sizeof(RtlpDphGlobalFlags), 00346 NULL 00347 ); 00348 00349 // 00350 // Read several page heap parameters. 00351 // 00352 00353 LdrQueryImageFileExecutionOptions( 00354 &UnicodeImageName, 00355 L"PageHeapSizeRangeStart", 00356 REG_DWORD, 00357 &RtlpDphSizeRangeStart, 00358 sizeof(RtlpDphSizeRangeStart), 00359 NULL 00360 ); 00361 00362 LdrQueryImageFileExecutionOptions( 00363 &UnicodeImageName, 00364 L"PageHeapSizeRangeEnd", 00365 REG_DWORD, 00366 &RtlpDphSizeRangeEnd, 00367 sizeof(RtlpDphSizeRangeEnd), 00368 NULL 00369 ); 00370 00371 LdrQueryImageFileExecutionOptions( 00372 &UnicodeImageName, 00373 L"PageHeapRandomProbability", 00374 REG_DWORD, 00375 &RtlpDphRandomProbability, 00376 sizeof(RtlpDphRandomProbability), 00377 NULL 00378 ); 00379 00380 // 00381 // The two values below should be read as PVOIDs so that 00382 // this works on 64-bit architetures. However since this 00383 // feature relies on good stack traces and since we can get 00384 // reliable stack traces only on X86 architectures we will 00385 // leave it as it is. 00386 // 00387 00388 LdrQueryImageFileExecutionOptions( 00389 &UnicodeImageName, 00390 L"PageHeapDllRangeStart", 00391 REG_DWORD, 00392 &RtlpDphDllRangeStart, 00393 sizeof(RtlpDphDllRangeStart), 00394 NULL 00395 ); 00396 00397 LdrQueryImageFileExecutionOptions( 00398 &UnicodeImageName, 00399 L"PageHeapDllRangeEnd", 00400 REG_DWORD, 00401 &RtlpDphDllRangeEnd, 00402 sizeof(RtlpDphDllRangeEnd), 00403 NULL 00404 ); 00405 00406 LdrQueryImageFileExecutionOptions( 00407 &UnicodeImageName, 00408 L"PageHeapTargetDlls", 00409 REG_SZ, 00410 &RtlpDphTargetDlls, 00411 512, 00412 NULL 00413 ); 00414 00415 // 00416 // Turn on BOOLEAN RtlpDebugPageHeap to indicate that 00417 // new heaps should be created with debug page heap manager 00418 // when possible. 00419 // 00420 00421 RtlpDebugPageHeap = TRUE; 00422 } 00423 } 00424 #if defined(_ALPHA_) 00425 else 00426 if (Context != NULL) { 00427 LdrpSetGp( LdrpGpValue ); 00428 Context->IntGp = LdrpGpValue; 00429 } 00430 #endif // ALPHA 00431 00432 // 00433 // Serialize for here on out 00434 // 00435 00436 Peb->LoaderLock = (PVOID)&LoaderLock; 00437 00438 if ( !RtlTryEnterCriticalSection(&LoaderLock) ) { 00439 if ( LoaderLockInitialized ) { 00440 RtlEnterCriticalSection(&LoaderLock); 00441 } 00442 else { 00443 00444 // 00445 // drop into a 30ms delay loop 00446 // 00447 00448 DelayValue.QuadPart = Int32x32To64( 30, -10000 ); 00449 while ( !LoaderLockInitialized ) { 00450 NtDelayExecution(FALSE,&DelayValue); 00451 } 00452 RtlEnterCriticalSection(&LoaderLock); 00453 } 00454 } 00455 00456 if (Teb->DeallocationStack == NULL) { 00457 st = NtQueryVirtualMemory( 00458 NtCurrentProcess(), 00459 Teb->NtTib.StackLimit, 00460 MemoryBasicInformation, 00461 (PVOID)&MemInfo, 00462 sizeof(MemInfo), 00463 NULL 00464 ); 00465 if ( !NT_SUCCESS(st) ) { 00466 LdrpInitializationFailure(st); 00467 RtlRaiseStatus(st); 00468 return; 00469 } 00470 else { 00471 Teb->DeallocationStack = MemInfo.AllocationBase; 00472 #if defined(_IA64_) 00473 Teb->DeallocationBStore = (PVOID)((ULONG_PTR)MemInfo.AllocationBase + MemInfo.RegionSize); 00474 #endif // defined(_IA64_) 00475 } 00476 } 00477 00478 InitStatus = STATUS_SUCCESS; 00479 try { 00480 if (!Peb->Ldr) { 00481 LdrpInLdrInit = TRUE; 00482 #if DBG 00483 // 00484 // Time the load. 00485 // 00486 00487 if (LdrpDisplayLoadTime) { 00488 NtQueryPerformanceCounter(&BeginTime, NULL); 00489 } 00490 #endif // DBG 00491 00492 try { 00493 InitStatus = LdrpInitializeProcess( Context, 00494 SystemArgument1, 00495 &UnicodeImageName 00496 ); 00497 } 00498 except ( EXCEPTION_EXECUTE_HANDLER ) { 00499 InitStatus = GetExceptionCode(); 00500 AlreadyFailed = TRUE; 00501 LdrpInitializationFailure(GetExceptionCode()); 00502 } 00503 00504 #if DBG 00505 if (LdrpDisplayLoadTime) { 00506 NtQueryPerformanceCounter(&EndTime, NULL); 00507 NtQueryPerformanceCounter(&ElapsedTime, &Interval); 00508 ElapsedTime.QuadPart = EndTime.QuadPart - BeginTime.QuadPart; 00509 DbgPrint("\nLoadTime %ld In units of %ld cycles/second \n", 00510 ElapsedTime.LowPart, 00511 Interval.LowPart 00512 ); 00513 00514 ElapsedTime.QuadPart = EndTime.QuadPart - InitbTime.QuadPart; 00515 DbgPrint("InitTime %ld\n", 00516 ElapsedTime.LowPart 00517 ); 00518 DbgPrint("Compares %d Bypasses %d Normal Snaps %d\nSecOpens %d SecCreates %d Maps %d Relocates %d\n", 00519 LdrpCompareCount, 00520 LdrpSnapBypass, 00521 LdrpNormalSnap, 00522 LdrpSectionOpens, 00523 LdrpSectionCreates, 00524 LdrpSectionMaps, 00525 LdrpSectionRelocates 00526 ); 00527 } 00528 #endif // DBG 00529 00530 00531 } else { 00532 if ( Peb->InheritedAddressSpace ) { 00533 InitStatus = LdrpForkProcess(); 00534 } 00535 else { 00536 00537 #if defined (WX86) 00538 if (Teb->Vdm) { 00539 InitStatus = LdrpInitWx86(Teb->Vdm, Context, TRUE); 00540 } 00541 #endif 00542 00543 #if defined(_WIN64) 00544 // 00545 // Load in WOW64 if the image is supposed to run simulated 00546 // 00547 if (UseWOW64) { 00548 RtlLeaveCriticalSection(&LoaderLock); 00549 (*Wow64LdrpInitialize)(Context); 00550 // This never returns. It will destroy the process. 00551 } 00552 #endif 00553 LdrpInitializeThread(Context); 00554 } 00555 } 00556 } finally { 00557 LdrpInLdrInit = FALSE; 00558 RtlLeaveCriticalSection(&LoaderLock); 00559 } 00560 00561 NtTestAlert(); 00562 00563 if (!NT_SUCCESS(InitStatus)) { 00564 00565 if ( AlreadyFailed == FALSE ) { 00566 LdrpInitializationFailure(InitStatus); 00567 } 00568 RtlRaiseStatus(InitStatus); 00569 } 00570 00571 00572 }

NTSTATUS LdrpInitializeProcess IN PCONTEXT Context  OPTIONAL,
IN PVOID  SystemDllBase,
IN PUNICODE_STRING  UnicodeImageName
 

Definition at line 616 of file ldrinit.c.

References ASSERT, ATOM_TAG, CommandLine, DbgPrint, FALSE, FastPebLock, HeapParameters, InitTableInfo, L, LDR_TAG, LdrGetProcedureAddress(), LdrLoadDll(), LDRP_HASH_TABLE_SIZE, LdrpAllocateDataTableEntry(), LdrpDefaultPath, LdrpFetchAddressOfEntryPoint(), LdrpHashTable, LdrpImageEntry, LdrpInitializationFailure(), LdrpInitializeTls(), LdrpInsertMemoryTableEntry(), LdrpKnownDllObjectDirectory, LdrpKnownDllPath, LdrpKnownDllPathBuffer, LdrpLdrDatabaseIsSetup, LdrpNumberOfProcessors, LdrpReferenceLoadedDll, LdrpRelocateStartContext(), LdrpRunInitializeRoutines(), LdrpSetProtection(), LdrpVerifyDlls, LdrpWalkImportDescriptor(), LdrQueryApplicationCompatibilityGoo(), LdrQueryImageFileExecutionOptions(), LdrRelocateImage(), LoaderLock, LoaderLockInitialized, MAKE_TAG, NATIVE_PAGE_SIZE, NT_SUCCESS, NtAllocateVirtualMemory(), NtClose(), NtDllBase, NtdllBaseTag, NtdllpAllocateStringRoutine(), NtdllpFreeStringRoutine(), NtFreeVirtualMemory(), NtOpenDirectoryObject(), NtOpenSymbolicLinkObject(), NtQueryPerformanceCounter(), NtQuerySymbolicLinkObject(), NtSetInformationProcess(), NTSTATUS(), NtSystemRoot, NULL, PAGE_SIZE, RtlAllocateHeap, RtlAllocateStringRoutine, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCreateHeap(), RtlCreateTagHeap(), RtlCriticalSectionList, RtlFreeStringRoutine, RtlFreeUnicodeString(), RtlImageDirectoryEntryToData(), RtlImageNtHeader(), RtlInitAnsiString(), RtlInitializeAtomPackage(), RtlInitializeBitMap(), RtlInitializeCriticalSection(), RtlInitializeHeapManager(), RtlInitNlsTables(), RtlInitUnicodeString(), RtlNormalizeProcessParams(), RtlpDebugPageHeap, RtlpInitDeferedCriticalSection(), RtlpTimeout, RtlpTimoutDisable, RtlRaiseStatus(), RtlResetRtlTranslations(), RtlSetCurrentDirectory_U(), ShowSnaps, TlsBitMap, TlsExpansionBitMap, TRUE, Unicode, and USHORT.

Referenced by LdrpInitialize().

00624 : 00625 00626 This function initializes the loader for the process. 00627 This includes: 00628 00629 - Initializing the loader data table 00630 00631 - Connecting to the loader subsystem 00632 00633 - Initializing all staticly linked DLLs 00634 00635 Arguments: 00636 00637 Context - Supplies an optional context buffer that will be restore 00638 after all DLL initialization has been completed. If this 00639 parameter is NULL then this is a dynamic snap of this module. 00640 Otherwise this is a static snap prior to the user process 00641 gaining control. 00642 00643 SystemDllBase - Supplies the base address of the system dll. 00644 00645 Return Value: 00646 00647 Status value 00648 00649 --*/ 00650 00651 { 00652 PPEB Peb; 00653 NTSTATUS st; 00654 PWCH p, pp; 00655 UNICODE_STRING CurDir; 00656 UNICODE_STRING FullImageName; 00657 UNICODE_STRING CommandLine; 00658 ULONG DebugProcessHeapOnly = 0 ; 00659 HANDLE LinkHandle; 00660 WCHAR SystemDllPathBuffer[DOS_MAX_PATH_LENGTH]; 00661 UNICODE_STRING SystemDllPath; 00662 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 00663 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 00664 UNICODE_STRING Unicode; 00665 OBJECT_ATTRIBUTES Obja; 00666 BOOLEAN StaticCurDir = FALSE; 00667 ULONG i; 00668 PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader( NtCurrentPeb()->ImageBaseAddress ); 00669 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData; 00670 ULONG ProcessHeapFlags; 00671 RTL_HEAP_PARAMETERS HeapParameters; 00672 NLSTABLEINFO InitTableInfo; 00673 LARGE_INTEGER LongTimeout; 00674 UNICODE_STRING NtSystemRoot; 00675 LONG_PTR Diff; 00676 ULONG_PTR OldBase; 00677 00678 NtDllBase = SystemDllBase; 00679 00680 if ( 00681 #if defined(_WIN64) 00682 NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC && 00683 #endif 00684 NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE ) { 00685 00686 // 00687 // Native subsystems load slower, but validate their DLLs 00688 // This is to help CSR detect bad images faster 00689 // 00690 00691 LdrpVerifyDlls = TRUE; 00692 00693 } 00694 00695 00696 Peb = NtCurrentPeb(); 00697 00698 #if defined(BUILD_WOW6432) 00699 { 00700 // 00701 // The process is running in WOW64. Sort out the optional header 00702 // format and reformat the image if its page size is smaller than 00703 // the native page size. 00704 // 00705 PIMAGE_NT_HEADERS32 NtHeader32 = (PIMAGE_NT_HEADERS32)NtHeader; 00706 00707 if (NtHeader32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 && 00708 NtHeader32->OptionalHeader.SectionAlignment < NATIVE_PAGE_SIZE && 00709 !NT_SUCCESS(st = LdrpWx86FormatVirtualImage(NtHeader32, 00710 NtCurrentPeb()->ImageBaseAddress 00711 //bugbug: should be: (PVOID)NtHeader32->OptionalHeader.ImageBase 00712 ))) { 00713 return st; 00714 } 00715 } 00716 #elif defined (_ALPHA_) && defined (WX86) 00717 // 00718 // Deal with the native page size which is larger than x86 00719 // This needs to be done before any code reads beyond the file headers. 00720 // 00721 if (NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 && 00722 NtHeader->OptionalHeader.SectionAlignment < PAGE_SIZE && 00723 !NT_SUCCESS(st = LdrpWx86FormatVirtualImage((PIMAGE_NT_HEADERS32)NtHeader, 00724 (PVOID)NtHeader->OptionalHeader.ImageBase 00725 ))) 00726 { 00727 return st; 00728 } 00729 #endif 00730 00731 00732 LdrpNumberOfProcessors = Peb->NumberOfProcessors; 00733 RtlpTimeout = Peb->CriticalSectionTimeout; 00734 LongTimeout.QuadPart = Int32x32To64( 3600, -10000000 ); 00735 00736 if (ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters)) { 00737 FullImageName = *(PUNICODE_STRING)&ProcessParameters->ImagePathName; 00738 CommandLine = *(PUNICODE_STRING)&ProcessParameters->CommandLine; 00739 } 00740 else { 00741 RtlInitUnicodeString( &FullImageName, NULL ); 00742 RtlInitUnicodeString( &CommandLine, NULL ); 00743 } 00744 00745 00746 RtlInitNlsTables( 00747 Peb->AnsiCodePageData, 00748 Peb->OemCodePageData, 00749 Peb->UnicodeCaseTableData, 00750 &InitTableInfo 00751 ); 00752 00753 RtlResetRtlTranslations(&InitTableInfo); 00754 00755 #if defined(_WIN64) 00756 if (UseWOW64) { 00757 // 00758 // Ignore image config data when initializing the 64-bit loader. 00759 // The 32-bit loader in ntdll32 will look at the config data 00760 // and do the right thing. 00761 // 00762 ImageConfigData = NULL; 00763 } else 00764 #endif 00765 { 00766 00767 ImageConfigData = RtlImageDirectoryEntryToData( Peb->ImageBaseAddress, 00768 TRUE, 00769 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 00770 &i 00771 ); 00772 } 00773 00774 RtlZeroMemory( &HeapParameters, sizeof( HeapParameters ) ); 00775 ProcessHeapFlags = HEAP_GROWABLE | HEAP_CLASS_0; 00776 HeapParameters.Length = sizeof( HeapParameters ); 00777 if (ImageConfigData != NULL && i == sizeof( *ImageConfigData )) { 00778 Peb->NtGlobalFlag &= ~ImageConfigData->GlobalFlagsClear; 00779 Peb->NtGlobalFlag |= ImageConfigData->GlobalFlagsSet; 00780 00781 if (ImageConfigData->CriticalSectionDefaultTimeout != 0) { 00782 // 00783 // Convert from milliseconds to NT time scale (100ns) 00784 // 00785 RtlpTimeout.QuadPart = Int32x32To64( (LONG)ImageConfigData->CriticalSectionDefaultTimeout, 00786 -10000 00787 ); 00788 00789 } 00790 00791 if (ImageConfigData->ProcessHeapFlags != 0) { 00792 ProcessHeapFlags = ImageConfigData->ProcessHeapFlags; 00793 } 00794 00795 if (ImageConfigData->DeCommitFreeBlockThreshold != 0) { 00796 HeapParameters.DeCommitFreeBlockThreshold = ImageConfigData->DeCommitFreeBlockThreshold; 00797 } 00798 00799 if (ImageConfigData->DeCommitTotalFreeThreshold != 0) { 00800 HeapParameters.DeCommitTotalFreeThreshold = ImageConfigData->DeCommitTotalFreeThreshold; 00801 } 00802 00803 if (ImageConfigData->MaximumAllocationSize != 0) { 00804 HeapParameters.MaximumAllocationSize = ImageConfigData->MaximumAllocationSize; 00805 } 00806 00807 if (ImageConfigData->VirtualMemoryThreshold != 0) { 00808 HeapParameters.VirtualMemoryThreshold = ImageConfigData->VirtualMemoryThreshold; 00809 } 00810 } 00811 00812 // // 00813 // // Check if the image has the fast heap flag set 00814 // // 00815 // 00816 // if (NtHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_FAST_HEAP) { 00817 // RtlpDisableHeapLookaside = 0; 00818 // } else { 00819 // RtlpDisableHeapLookaside = 1; 00820 // } 00821 00822 ShowSnaps = (BOOLEAN)(FLG_SHOW_LDR_SNAPS & Peb->NtGlobalFlag); 00823 00824 00825 00826 // 00827 // This field is non-zero if the image file that was used to create this 00828 // process contained a non-zero value in its image header. If so, then 00829 // set the affinity mask for the process using this value. It could also 00830 // be non-zero if the parent process created us suspended and poked our 00831 // PEB with a non-zero value before resuming. 00832 // 00833 if (Peb->ImageProcessAffinityMask) { 00834 st = NtSetInformationProcess( NtCurrentProcess(), 00835 ProcessAffinityMask, 00836 &Peb->ImageProcessAffinityMask, 00837 sizeof( Peb->ImageProcessAffinityMask ) 00838 ); 00839 if (NT_SUCCESS( st )) { 00840 KdPrint(( "LDR: Using ProcessAffinityMask of 0x%x from image.\n", 00841 Peb->ImageProcessAffinityMask 00842 )); 00843 } 00844 else { 00845 KdPrint(( "LDR: Failed to set ProcessAffinityMask of 0x%x from image (Status == %08x).\n", 00846 Peb->ImageProcessAffinityMask, st 00847 )); 00848 } 00849 } 00850 00851 if (RtlpTimeout.QuadPart < LongTimeout.QuadPart) { 00852 RtlpTimoutDisable = TRUE; 00853 } 00854 00855 if (ShowSnaps) { 00856 DbgPrint( "LDR: PID: 0x%x started - '%wZ'\n", 00857 NtCurrentTeb()->ClientId.UniqueProcess, 00858 &CommandLine 00859 ); 00860 } 00861 00862 for(i=0;i<LDRP_HASH_TABLE_SIZE;i++) { 00863 InitializeListHead(&LdrpHashTable[i]); 00864 } 00865 00866 // 00867 // Initialize the critical section package. 00868 // 00869 00870 RtlpInitDeferedCriticalSection(); 00871 00872 Peb->TlsBitmap = (PVOID)&TlsBitMap; 00873 Peb->TlsExpansionBitmap = (PVOID)&TlsExpansionBitMap; 00874 00875 RtlInitializeBitMap ( 00876 &TlsBitMap, 00877 &Peb->TlsBitmapBits[0], 00878 TLS_MINIMUM_AVAILABLE 00879 ); 00880 00881 RtlInitializeBitMap ( 00882 &TlsExpansionBitMap, 00883 &Peb->TlsExpansionBitmapBits[0], 00884 TLS_EXPANSION_SLOTS 00885 ); 00886 00887 InsertTailList(&RtlCriticalSectionList, &LoaderLock.DebugInfo->ProcessLocksList); 00888 LoaderLock.DebugInfo->CriticalSection = &LoaderLock; 00889 LoaderLockInitialized = TRUE; 00890 00891 // 00892 // Initialize the stack trace data base if requested 00893 // 00894 00895 #if i386 00896 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) { 00897 PVOID BaseAddress = NULL; 00898 ULONG ReserveSize = 2 * 1024 * 1024; 00899 00900 st = NtAllocateVirtualMemory( NtCurrentProcess(), 00901 (PVOID *)&BaseAddress, 00902 0, 00903 &ReserveSize, 00904 MEM_RESERVE, 00905 PAGE_READWRITE 00906 ); 00907 if ( NT_SUCCESS( st ) ) { 00908 st = RtlInitializeStackTraceDataBase( BaseAddress, 00909 0, 00910 ReserveSize 00911 ); 00912 if ( !NT_SUCCESS( st ) ) { 00913 NtFreeVirtualMemory( NtCurrentProcess(), 00914 (PVOID *)&BaseAddress, 00915 &ReserveSize, 00916 MEM_RELEASE 00917 ); 00918 } 00919 else { 00920 Peb->NtGlobalFlag |= FLG_HEAP_VALIDATE_PARAMETERS; 00921 } 00922 } 00923 } 00924 #endif // i386 00925 00926 // 00927 // Initialize the loader data based in the PEB. 00928 // 00929 00930 st = RtlInitializeCriticalSection(&FastPebLock); 00931 if ( !NT_SUCCESS(st) ) { 00932 return st; 00933 } 00934 Peb->FastPebLock = &FastPebLock; 00935 Peb->FastPebLockRoutine = (PVOID)&RtlEnterCriticalSection; 00936 Peb->FastPebUnlockRoutine = (PVOID)&RtlLeaveCriticalSection; 00937 00938 RtlInitializeHeapManager(); 00939 #if defined(_WIN64) 00940 if (UseWOW64) { 00941 // 00942 // Create a heap using all defaults. The 32-bit process heap 00943 // will be created later by ntdll32 using the parameters from the exe. 00944 // 00945 Peb->ProcessHeap = RtlCreateHeap( ProcessHeapFlags, 00946 NULL, 00947 0, 00948 0, 00949 NULL, 00950 &HeapParameters 00951 ); 00952 } else 00953 #endif 00954 { 00955 00956 if (NtHeader->OptionalHeader.MajorSubsystemVersion <= 3 && 00957 NtHeader->OptionalHeader.MinorSubsystemVersion < 51 00958 ) { 00959 ProcessHeapFlags |= HEAP_CREATE_ALIGN_16; 00960 } 00961 00962 Peb->ProcessHeap = RtlCreateHeap( ProcessHeapFlags, 00963 NULL, 00964 NtHeader->OptionalHeader.SizeOfHeapReserve, 00965 NtHeader->OptionalHeader.SizeOfHeapCommit, 00966 NULL, // Lock to use for serialization 00967 &HeapParameters 00968 ); 00969 } 00970 if (Peb->ProcessHeap == NULL) { 00971 return STATUS_NO_MEMORY; 00972 } 00973 00974 NtdllBaseTag = RtlCreateTagHeap( Peb->ProcessHeap, 00975 0, 00976 L"NTDLL!", 00977 L"!Process\0" // Heap Name 00978 L"CSRSS Client\0" 00979 L"LDR Database\0" 00980 L"Current Directory\0" 00981 L"TLS Storage\0" 00982 L"DBGSS Client\0" 00983 L"SE Temporary\0" 00984 L"Temporary\0" 00985 L"LocalAtom\0" 00986 ); 00987 00988 RtlAllocateStringRoutine = NtdllpAllocateStringRoutine; 00989 RtlFreeStringRoutine = NtdllpFreeStringRoutine; 00990 00991 RtlInitializeAtomPackage( MAKE_TAG( ATOM_TAG ) ); 00992 00993 // 00994 // Allow only the process heap to have page allocations turned on 00995 // 00996 00997 st = LdrQueryImageFileExecutionOptions( UnicodeImageName, 00998 L"DebugProcessHeapOnly", 00999 REG_DWORD, 01000 &DebugProcessHeapOnly, 01001 sizeof( DebugProcessHeapOnly ), 01002 NULL 01003 ); 01004 if (NT_SUCCESS( st )) { 01005 01006 if ( RtlpDebugPageHeap && 01007 ( DebugProcessHeapOnly != 0 ) ) { 01008 01009 RtlpDebugPageHeap = FALSE ; 01010 01011 } 01012 01013 } 01014 01015 SystemDllPath.Buffer = SystemDllPathBuffer; 01016 SystemDllPath.Length = 0; 01017 SystemDllPath.MaximumLength = sizeof( SystemDllPathBuffer ); 01018 RtlInitUnicodeString( &NtSystemRoot, USER_SHARED_DATA->NtSystemRoot ); 01019 RtlAppendUnicodeStringToString( &SystemDllPath, &NtSystemRoot ); 01020 RtlAppendUnicodeToString( &SystemDllPath, L"\\System32\\" ); 01021 01022 RtlInitUnicodeString(&Unicode,L"\\KnownDlls"); 01023 InitializeObjectAttributes( &Obja, 01024 &Unicode, 01025 OBJ_CASE_INSENSITIVE, 01026 NULL, 01027 NULL 01028 ); 01029 st = NtOpenDirectoryObject( 01030 &LdrpKnownDllObjectDirectory, 01031 DIRECTORY_QUERY | DIRECTORY_TRAVERSE, 01032 &Obja 01033 ); 01034 if ( !NT_SUCCESS(st) ) { 01035 LdrpKnownDllObjectDirectory = NULL; 01036 // KnownDlls directory doesn't exist - assume it's system32. 01037 RtlInitUnicodeString(&LdrpKnownDllPath, SystemDllPath.Buffer); 01038 LdrpKnownDllPath.Length -= sizeof(WCHAR); // remove trailing '\' 01039 } 01040 else { 01041 01042 // 01043 // Open up the known dll pathname link 01044 // and query its value 01045 // 01046 01047 RtlInitUnicodeString(&Unicode,L"KnownDllPath"); 01048 InitializeObjectAttributes( &Obja, 01049 &Unicode, 01050 OBJ_CASE_INSENSITIVE, 01051 LdrpKnownDllObjectDirectory, 01052 NULL 01053 ); 01054 st = NtOpenSymbolicLinkObject( &LinkHandle, 01055 SYMBOLIC_LINK_QUERY, 01056 &Obja 01057 ); 01058 if (NT_SUCCESS( st )) { 01059 LdrpKnownDllPath.Length = 0; 01060 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer); 01061 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer; 01062 st = NtQuerySymbolicLinkObject( LinkHandle, 01063 &LdrpKnownDllPath, 01064 NULL 01065 ); 01066 NtClose(LinkHandle); 01067 if ( !NT_SUCCESS(st) ) { 01068 return st; 01069 } 01070 } 01071 else { 01072 return st; 01073 } 01074 } 01075 01076 if (ProcessParameters) { 01077 01078 // 01079 // If the process was created with process parameters, 01080 // than extract: 01081 // 01082 // - Library Search Path 01083 // 01084 // - Starting Current Directory 01085 // 01086 01087 if (ProcessParameters->DllPath.Length) { 01088 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath; 01089 } 01090 else { 01091 LdrpInitializationFailure( STATUS_INVALID_PARAMETER ); 01092 } 01093 01094 StaticCurDir = TRUE; 01095 CurDir = ProcessParameters->CurrentDirectory.DosPath; 01096 if (CurDir.Buffer == NULL || CurDir.Buffer[ 0 ] == UNICODE_NULL || CurDir.Length == 0) { 01097 CurDir.Buffer = (RtlAllocateStringRoutine)( (3+1) * sizeof( WCHAR ) ); 01098 ASSERT(CurDir.Buffer != NULL); 01099 RtlMoveMemory( CurDir.Buffer, 01100 USER_SHARED_DATA->NtSystemRoot, 01101 3 * sizeof( WCHAR ) 01102 ); 01103 CurDir.Buffer[ 3 ] = UNICODE_NULL; 01104 } 01105 } 01106 01107 // 01108 // Make sure the module data base is initialized before we take any 01109 // exceptions. 01110 // 01111 01112 Peb->Ldr = RtlAllocateHeap(Peb->ProcessHeap, MAKE_TAG( LDR_TAG ), sizeof(PEB_LDR_DATA)); 01113 if ( !Peb->Ldr ) { 01114 RtlRaiseStatus(STATUS_NO_MEMORY); 01115 } 01116 01117 Peb->Ldr->Length = sizeof(PEB_LDR_DATA); 01118 Peb->Ldr->Initialized = TRUE; 01119 Peb->Ldr->SsHandle = NULL; 01120 InitializeListHead(&Peb->Ldr->InLoadOrderModuleList); 01121 InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList); 01122 InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList); 01123 01124 // 01125 // Allocate the first data table entry for the image. Since we 01126 // have already mapped this one, we need to do the allocation by hand. 01127 // Its characteristics identify it as not a Dll, but it is linked 01128 // into the table so that pc correlation searching doesn't have to 01129 // be special cased. 01130 // 01131 01132 LdrDataTableEntry = LdrpImageEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); 01133 LdrDataTableEntry->LoadCount = (USHORT)0xffff; 01134 LdrDataTableEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrDataTableEntry->DllBase); 01135 LdrDataTableEntry->FullDllName = FullImageName; 01136 LdrDataTableEntry->Flags = 0; 01137 01138 // p = strrchr(FullImageName, '\\'); 01139 pp = UNICODE_NULL; 01140 p = FullImageName.Buffer; 01141 while (*p) { 01142 if (*p++ == (WCHAR)'\\') { 01143 pp = p; 01144 } 01145 } 01146 01147 LdrDataTableEntry->FullDllName.Length = (USHORT)((ULONG_PTR)p - (ULONG_PTR)FullImageName.Buffer); 01148 LdrDataTableEntry->FullDllName.MaximumLength = LdrDataTableEntry->FullDllName.Length + (USHORT)sizeof(UNICODE_NULL); 01149 01150 if (pp) { 01151 LdrDataTableEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)p - (ULONG_PTR)pp); 01152 LdrDataTableEntry->BaseDllName.MaximumLength = LdrDataTableEntry->BaseDllName.Length + (USHORT)sizeof(UNICODE_NULL); 01153 LdrDataTableEntry->BaseDllName.Buffer = RtlAllocateHeap(Peb->ProcessHeap, MAKE_TAG( LDR_TAG ), 01154 LdrDataTableEntry->BaseDllName.MaximumLength 01155 ); 01156 RtlMoveMemory(LdrDataTableEntry->BaseDllName.Buffer, 01157 pp, 01158 LdrDataTableEntry->BaseDllName.MaximumLength 01159 ); 01160 } else { 01161 LdrDataTableEntry->BaseDllName = LdrDataTableEntry->FullDllName; 01162 } 01163 LdrpInsertMemoryTableEntry(LdrDataTableEntry); 01164 LdrDataTableEntry->Flags |= LDRP_ENTRY_PROCESSED; 01165 01166 if (ShowSnaps) { 01167 DbgPrint( "LDR: NEW PROCESS\n" ); 01168 DbgPrint( " Image Path: %wZ (%wZ)\n", 01169 &LdrDataTableEntry->FullDllName, 01170 &LdrDataTableEntry->BaseDllName 01171 ); 01172 DbgPrint( " Current Directory: %wZ\n", &CurDir ); 01173 DbgPrint( " Search Path: %wZ\n", &LdrpDefaultPath ); 01174 } 01175 01176 // 01177 // The process references the system DLL, so map this one next. Since 01178 // we have already mapped this one, we need to do the allocation by 01179 // hand. Since every application will be statically linked to the 01180 // system Dll, we'll keep the LoadCount initialized to 0. 01181 // 01182 01183 LdrDataTableEntry = LdrpAllocateDataTableEntry(SystemDllBase); 01184 LdrDataTableEntry->Flags = (USHORT)LDRP_IMAGE_DLL; 01185 LdrDataTableEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrDataTableEntry->DllBase); 01186 LdrDataTableEntry->LoadCount = (USHORT)0xffff; 01187 01188 LdrDataTableEntry->BaseDllName.Length = SystemDllPath.Length; 01189 RtlAppendUnicodeToString( &SystemDllPath, L"ntdll.dll" ); 01190 LdrDataTableEntry->BaseDllName.Length = SystemDllPath.Length - LdrDataTableEntry->BaseDllName.Length; 01191 LdrDataTableEntry->BaseDllName.MaximumLength = LdrDataTableEntry->BaseDllName.Length + sizeof( UNICODE_NULL ); 01192 01193 LdrDataTableEntry->FullDllName.Buffer = 01194 (RtlAllocateStringRoutine)( SystemDllPath.Length + sizeof( UNICODE_NULL ) ); 01195 ASSERT(LdrDataTableEntry->FullDllName.Buffer != NULL); 01196 RtlMoveMemory( LdrDataTableEntry->FullDllName.Buffer, 01197 SystemDllPath.Buffer, 01198 SystemDllPath.Length 01199 ); 01200 LdrDataTableEntry->FullDllName.Buffer[ SystemDllPath.Length / sizeof( WCHAR ) ] = UNICODE_NULL; 01201 LdrDataTableEntry->FullDllName.Length = SystemDllPath.Length; 01202 LdrDataTableEntry->FullDllName.MaximumLength = SystemDllPath.Length + sizeof( UNICODE_NULL ); 01203 LdrDataTableEntry->BaseDllName.Buffer = (PWSTR) 01204 ((PCHAR)(LdrDataTableEntry->FullDllName.Buffer) + 01205 LdrDataTableEntry->FullDllName.Length - 01206 LdrDataTableEntry->BaseDllName.Length 01207 ); 01208 LdrpInsertMemoryTableEntry(LdrDataTableEntry); 01209 01210 // 01211 // Add init routine to list 01212 // 01213 01214 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, 01215 &LdrDataTableEntry->InInitializationOrderLinks); 01216 01217 // 01218 // Inherit the current directory 01219 // 01220 01221 st = RtlSetCurrentDirectory_U(&CurDir); 01222 if (!NT_SUCCESS(st)) { 01223 if ( !StaticCurDir ) { 01224 RtlFreeUnicodeString(&CurDir); 01225 } 01226 CurDir = NtSystemRoot; 01227 st = RtlSetCurrentDirectory_U(&CurDir); 01228 } 01229 else { 01230 if ( !StaticCurDir ) { 01231 RtlFreeUnicodeString(&CurDir); 01232 } 01233 } 01234 01235 #if defined(WX86) 01236 01237 // 01238 // Load in x86 emulator for risc (Wx86.dll) 01239 // 01240 01241 if (NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { 01242 st = LdrpLoadWx86Dll(Context); 01243 if (!NT_SUCCESS(st)) { 01244 return st; 01245 } 01246 } 01247 01248 #endif 01249 01250 #if defined(_WIN64) 01251 // 01252 // Load in WOW64 if the image is supposed to run simulated 01253 // 01254 if (UseWOW64) { 01255 UNICODE_STRING Wow64Name; 01256 ANSI_STRING ProcName; 01257 RtlInitUnicodeString(&Wow64Name, L"wow64.dll"); 01258 st = LdrLoadDll(NULL, NULL, &Wow64Name, &Wow64Handle); 01259 if (!NT_SUCCESS(st)) { 01260 if (ShowSnaps) { 01261 DbgPrint("wow64.dll not found. Status=%x\n", st); 01262 } 01263 return st; 01264 } 01265 01266 // 01267 // Get the entrypoints. They are roughly cloned from ntos\ps\psinit.c 01268 // PspInitSystemDll(). 01269 // 01270 RtlInitAnsiString(&ProcName, "Wow64LdrpInitialize"); 01271 st = LdrGetProcedureAddress(Wow64Handle, 01272 &ProcName, 01273 0, 01274 (PVOID *)&Wow64LdrpInitialize); 01275 if (!NT_SUCCESS(st)) { 01276 if (ShowSnaps) { 01277 DbgPrint("Wow64LdrpInitialize not found. Status=%x\n", st); 01278 } 01279 return st; 01280 } 01281 01282 RtlInitAnsiString(&ProcName, "Wow64PrepareForException"); 01283 st = LdrGetProcedureAddress(Wow64Handle, 01284 &ProcName, 01285 0, 01286 (PVOID *)&Wow64PrepareForException); 01287 if (!NT_SUCCESS(st)) { 01288 if (ShowSnaps) { 01289 DbgPrint("Wow64PrepareForException not found. Status=%x\n", st); 01290 } 01291 return st; 01292 } 01293 01294 DbgPrint("WARNING: PROCESS HAS BEEN CONVERTED TO WOW64!!!\n"); 01295 if (Peb->ProcessParameters) { 01296 DbgPrint("CommandLine: %wZ\n", &Peb->ProcessParameters->CommandLine); 01297 DbgPrint("ImagePathName: %wZ\n", &Peb->ProcessParameters->ImagePathName); 01298 } 01299 01300 // 01301 // Now that all DLLs are loaded, if the process is being debugged, 01302 // signal the debugger with an exception 01303 // 01304 01305 if ( Peb->BeingDebugged ) { 01306 DbgBreakPoint(); 01307 } 01308 01309 // 01310 // Release the loaderlock now - this thread doesn't need it any more. 01311 // 01312 RtlLeaveCriticalSection(&LoaderLock); 01313 01314 // 01315 // Call wow64 to load and run 32-bit ntdll.dll. 01316 // 01317 (*Wow64LdrpInitialize)(Context); 01318 // This never returns. It will destroy the process. 01319 } 01320 #endif 01321 01322 01323 st = LdrpWalkImportDescriptor( 01324 LdrpDefaultPath.Buffer, 01325 LdrpImageEntry 01326 ); 01327 01328 if ((PVOID)NtHeader->OptionalHeader.ImageBase != NtCurrentPeb()->ImageBaseAddress ) { 01329 01330 // 01331 // The executable is not at its original address. It must be 01332 // relocated now. 01333 // 01334 01335 PVOID ViewBase; 01336 NTSTATUS status; 01337 01338 ViewBase = NtCurrentPeb()->ImageBaseAddress; 01339 01340 status = LdrpSetProtection(ViewBase, FALSE, TRUE); 01341 01342 if (!NT_SUCCESS(status)) { 01343 return status; 01344 } 01345 01346 status = (NTSTATUS)LdrRelocateImage(ViewBase, 01347 "LDR", 01348 (ULONG)STATUS_SUCCESS, 01349 (ULONG)STATUS_CONFLICTING_ADDRESSES, 01350 (ULONG)STATUS_INVALID_IMAGE_FORMAT 01351 ); 01352 01353 if (!NT_SUCCESS(status)) { 01354 return status; 01355 } 01356 01357 // 01358 // Update the initial thread context record as per the relocation. 01359 // 01360 01361 if (Context) { 01362 01363 OldBase = NtHeader->OptionalHeader.ImageBase; 01364 Diff = (PCHAR)ViewBase - (PCHAR)OldBase; 01365 01366 LdrpRelocateStartContext(Context, Diff); 01367 } 01368 01369 status = LdrpSetProtection(ViewBase, TRUE, TRUE); 01370 01371 if (!NT_SUCCESS(status)) { 01372 return status; 01373 } 01374 } 01375 01376 #if defined (_ALPHA_) 01377 01378 // 01379 // Find and apply Alpha architecture fixups for this image 01380 // 01381 01382 AlphaFindArchitectureFixups(NtHeader, NtCurrentPeb()->ImageBaseAddress, TRUE); 01383 #endif 01384 01385 LdrpReferenceLoadedDll(LdrpImageEntry); 01386 01387 // 01388 // Lock the loaded DLLs to prevent dlls that back link to the exe to 01389 // cause problems when they are unloaded. 01390 // 01391 01392 { 01393 PLDR_DATA_TABLE_ENTRY Entry; 01394 PLIST_ENTRY Head,Next; 01395 01396 Head = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 01397 Next = Head->Flink; 01398 01399 while ( Next != Head ) { 01400 Entry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 01401 Entry->LoadCount = 0xffff; 01402 Next = Next->Flink; 01403 } 01404 } 01405 01406 // 01407 // All static DLLs are now pinned in place. No init routines have been run yet 01408 // 01409 01410 LdrpLdrDatabaseIsSetup = TRUE; 01411 01412 01413 if (!NT_SUCCESS(st)) { 01414 #if DBG 01415 DbgPrint("LDR: Initialize of image failed. Returning Error Status\n"); 01416 #endif 01417 return st; 01418 } 01419 01420 if ( !NT_SUCCESS(LdrpInitializeTls()) ) { 01421 return st; 01422 } 01423 01424 // 01425 // Now that all DLLs are loaded, if the process is being debugged, 01426 // signal the debugger with an exception 01427 // 01428 01429 if ( Peb->BeingDebugged ) { 01430 DbgBreakPoint(); 01431 ShowSnaps = (BOOLEAN)(FLG_SHOW_LDR_SNAPS & Peb->NtGlobalFlag); 01432 } 01433 01434 #if defined (_X86_) 01435 if ( LdrpNumberOfProcessors > 1 ) { 01436 LdrpValidateImageForMp(LdrDataTableEntry); 01437 } 01438 #endif 01439 01440 #if DBG 01441 if (LdrpDisplayLoadTime) { 01442 NtQueryPerformanceCounter(&InitbTime, NULL); 01443 } 01444 #endif // DBG 01445 01446 // 01447 // Get all application goo here (hacks, flags, etc.) 01448 // 01449 LdrQueryApplicationCompatibilityGoo(UnicodeImageName); 01450 01451 st = LdrpRunInitializeRoutines(Context); 01452 01453 if ( NT_SUCCESS(st) && Peb->PostProcessInitRoutine ) { 01454 (Peb->PostProcessInitRoutine)(); 01455 } 01456 01457 return st; 01458 }

VOID LdrpInitializeThread IN PCONTEXT  Context  ) 
 

Definition at line 1702 of file ldrinit.c.

References LdrpAllocateTls(), LdrpCallInitRoutine, LdrpCallTlsInitializers(), LdrpImageHasTls, LdrpShutdownInProgress, and NULL.

Referenced by LdrpInitialize().

01708 : 01709 01710 This function is called by a thread that is terminating cleanly. 01711 It's purpose is to call all of the processes DLLs to notify them 01712 that the thread is detaching. 01713 01714 Arguments: 01715 01716 Context - Context that will be restored after loader initializes. 01717 01718 Return Value: 01719 01720 None. 01721 01722 --*/ 01723 01724 { 01725 PPEB Peb; 01726 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 01727 PDLL_INIT_ROUTINE InitRoutine; 01728 PLIST_ENTRY Next; 01729 01730 Peb = NtCurrentPeb(); 01731 01732 if ( LdrpShutdownInProgress ) { 01733 return; 01734 } 01735 01736 LdrpAllocateTls(); 01737 01738 Next = Peb->Ldr->InMemoryOrderModuleList.Flink; 01739 while (Next != &Peb->Ldr->InMemoryOrderModuleList) { 01740 LdrDataTableEntry 01741 = (PLDR_DATA_TABLE_ENTRY) 01742 (CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)); 01743 01744 // 01745 // Walk through the entire list looking for 01746 // entries. For each entry, that has an init 01747 // routine, call it. 01748 // 01749 if (Peb->ImageBaseAddress != LdrDataTableEntry->DllBase) { 01750 if ( !(LdrDataTableEntry->Flags & LDRP_DONT_CALL_FOR_THREADS)) { 01751 InitRoutine = (PDLL_INIT_ROUTINE)LdrDataTableEntry->EntryPoint; 01752 if (InitRoutine && (LdrDataTableEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) ) { 01753 if (LdrDataTableEntry->Flags & LDRP_IMAGE_DLL) { 01754 if ( LdrDataTableEntry->TlsIndex ) { 01755 if ( !LdrpShutdownInProgress ) { 01756 LdrpCallTlsInitializers(LdrDataTableEntry->DllBase,DLL_THREAD_ATTACH); 01757 } 01758 } 01759 01760 #if defined (WX86) 01761 if (!Wx86ProcessInit || 01762 LdrpRunWx86DllEntryPoint(InitRoutine, 01763 NULL, 01764 LdrDataTableEntry->DllBase, 01765 DLL_THREAD_ATTACH, 01766 NULL 01767 ) == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) 01768 #endif 01769 { 01770 if ( !LdrpShutdownInProgress ) { 01771 LdrpCallInitRoutine(InitRoutine, 01772 LdrDataTableEntry->DllBase, 01773 DLL_THREAD_ATTACH, 01774 NULL); 01775 } 01776 } 01777 } 01778 } 01779 } 01780 } 01781 Next = Next->Flink; 01782 } 01783 01784 // 01785 // If the image has tls than call its initializers 01786 // 01787 01788 if ( LdrpImageHasTls && !LdrpShutdownInProgress ) { 01789 LdrpCallTlsInitializers(NtCurrentPeb()->ImageBaseAddress,DLL_THREAD_ATTACH); 01790 } 01791 01792 }

NTSTATUS LdrpInitializeTls VOID   ) 
 

Definition at line 1978 of file ldrinit.c.

References DbgPrint, FALSE, LdrpAllocateTls(), LdrpImageHasTls, LdrpNumberOfTlsEntries, LdrpTlsList, MAKE_TAG, PLDRP_TLS_ENTRY, RtlAllocateHeap, RtlImageDirectoryEntryToData(), RtlpSerializeHeap(), ShowSnaps, TLS_TAG, TRUE, and USHORT.

Referenced by LdrpInitializeProcess().

01981 { 01982 PLDR_DATA_TABLE_ENTRY Entry; 01983 PLIST_ENTRY Head,Next; 01984 PIMAGE_TLS_DIRECTORY TlsImage; 01985 PLDRP_TLS_ENTRY TlsEntry; 01986 ULONG TlsSize; 01987 BOOLEAN FirstTimeThru = TRUE; 01988 01989 InitializeListHead(&LdrpTlsList); 01990 01991 // 01992 // Walk through the loaded modules an look for TLS. If we find TLS, 01993 // lock in the module and add to the TLS chain. 01994 // 01995 01996 Head = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 01997 Next = Head->Flink; 01998 01999 while ( Next != Head ) { 02000 Entry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 02001 Next = Next->Flink; 02002 02003 TlsImage = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData( 02004 Entry->DllBase, 02005 TRUE, 02006 IMAGE_DIRECTORY_ENTRY_TLS, 02007 &TlsSize 02008 ); 02009 02010 // 02011 // mark whether or not the image file has TLS 02012 // 02013 02014 if ( FirstTimeThru ) { 02015 FirstTimeThru = FALSE; 02016 if ( TlsImage && !LdrpImageHasTls) { 02017 RtlpSerializeHeap( RtlProcessHeap() ); 02018 LdrpImageHasTls = TRUE; 02019 } 02020 } 02021 02022 if ( TlsImage ) { 02023 if (ShowSnaps) { 02024 DbgPrint( "LDR: Tls Found in %wZ at %lx\n", 02025 &Entry->BaseDllName, 02026 TlsImage 02027 ); 02028 } 02029 02030 TlsEntry = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( TLS_TAG ),sizeof(*TlsEntry)); 02031 if ( !TlsEntry ) { 02032 return STATUS_NO_MEMORY; 02033 } 02034 02035 // 02036 // Since this DLL has TLS, lock it in 02037 // 02038 02039 Entry->LoadCount = (USHORT)0xffff; 02040 02041 // 02042 // Mark this as having thread local storage 02043 // 02044 02045 Entry->TlsIndex = (USHORT)0xffff; 02046 02047 TlsEntry->Tls = *TlsImage; 02048 InsertTailList(&LdrpTlsList,&TlsEntry->Links); 02049 02050 // 02051 // Update the index for this dll's thread local storage 02052 // 02053 02054 02055 *(PLONG)TlsEntry->Tls.AddressOfIndex = LdrpNumberOfTlsEntries; 02056 TlsEntry->Tls.Characteristics = LdrpNumberOfTlsEntries++; 02057 } 02058 } 02059 02060 // 02061 // We now have walked through all static DLLs and know 02062 // all DLLs that reference thread local storage. Now we 02063 // just have to allocate the thread local storage for the current 02064 // thread and for all subsequent threads 02065 // 02066 02067 return LdrpAllocateTls(); 02068 }

VOID LdrpRelocateStartContext IN PCONTEXT  Context,
IN LONG_PTR  Diff
 

Definition at line 28 of file alpha/ldrctx.c.

Referenced by LdrpInitializeProcess().

00034 : 00035 00036 This routine relocates the start context to mesh with the 00037 executable that has just been relocated. 00038 00039 Arguments: 00040 00041 Context - Supplies a context that needs editing. 00042 00043 Diff - Supplies the difference from the based address to the relocated 00044 address. 00045 00046 Return Value: 00047 00048 None. 00049 00050 --*/ 00051 { 00052 Context->IntA0 += (ULONGLONG)Diff; 00053 Context->IntGp += (ULONGLONG)Diff; 00054 } }

NTSTATUS LdrpSearchResourceSection_U IN PVOID  DllHandle,
IN PULONG_PTR  ResourceIdPath,
IN ULONG  ResourceIdPathLength,
IN BOOLEAN  FindDirectoryEntry,
IN BOOLEAN  ExactLangMatchOnly,
OUT PVOID *  ResourceDirectoryOrData
 

Definition at line 492 of file ldrrsrc.c.

00503 : 00504 00505 This function locates the address of the specified resource in the 00506 specified DLL and returns its address. 00507 00508 Arguments: 00509 00510 DllHandle - Supplies a handle to the image file that the resource is 00511 contained in. 00512 00513 ResourceIdPath - Supplies a pointer to an array of 32-bit resource 00514 identifiers. Each identifier is either an integer or a pointer 00515 to a null terminated string (PSZ) that specifies a resource 00516 name. The array is used to traverse the directory structure 00517 contained in the resource section in the image file specified by 00518 the DllHandle parameter. 00519 00520 ResourceIdPathLength - Supplies the number of elements in the 00521 ResourceIdPath array. 00522 00523 FindDirectoryEntry - Supplies a boolean that is TRUE if caller is 00524 searching for a resource directory, otherwise the caller is 00525 searching for a resource data entry. 00526 00527 ExactLangMatchOnly - Supplies a boolean that is TRUE if caller is 00528 searching for a resource with, and only with, the language id 00529 specified in ResourceIdPath, otherwise the caller wants the routine 00530 to come up with default when specified langid is not found. 00531 00532 ResourceDirectoryOrData - Supplies a pointer to a variable that will 00533 receive the address of the resource directory or data entry in 00534 the resource data section of the image file specified by the 00535 DllHandle parameter. 00536 00537 Return Value: 00538 00539 TBD 00540 00541 --*/ 00542 00543 { 00544 NTSTATUS Status; 00545 PIMAGE_RESOURCE_DIRECTORY LanguageResourceDirectory, ResourceDirectory, TopResourceDirectory; 00546 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntLow; 00547 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntMiddle; 00548 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirEntHigh; 00549 PIMAGE_RESOURCE_DATA_ENTRY ResourceEntry; 00550 USHORT n, half; 00551 LONG dir; 00552 ULONG size; 00553 ULONG_PTR ResourceIdRetry; 00554 ULONG RetryCount; 00555 LANGID NewLangId; 00556 PULONG_PTR IdPath = ResourceIdPath; 00557 ULONG IdPathLength = ResourceIdPathLength; 00558 BOOLEAN fIsNeutral = FALSE; 00559 LANGID GivenLanguage; 00560 #ifndef NTOS_KERNEL_RUNTIME 00561 LCID DefaultThreadLocale, DefaultSystemLocale; 00562 PVOID AltResourceDllHandle = NULL; 00563 ULONG_PTR UIResourceIdPath[3]; 00564 #endif 00565 00566 RTL_PAGED_CODE(); 00567 00568 try { 00569 TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY) 00570 RtlImageDirectoryEntryToData(DllHandle, 00571 TRUE, 00572 IMAGE_DIRECTORY_ENTRY_RESOURCE, 00573 &size 00574 ); 00575 if (!TopResourceDirectory) { 00576 return( STATUS_RESOURCE_DATA_NOT_FOUND ); 00577 } 00578 00579 ResourceDirectory = TopResourceDirectory; 00580 ResourceIdRetry = USE_FIRSTAVAILABLE_LANGID; 00581 RetryCount = 0; 00582 ResourceEntry = NULL; 00583 LanguageResourceDirectory = NULL; 00584 while (ResourceDirectory != NULL && ResourceIdPathLength--) { 00585 // 00586 // If search path includes a language id, then attempt to 00587 // match the following language ids in this order: 00588 // 00589 // (0) use given language id 00590 // (1) use primary language of given language id 00591 // (2) use id 0 (neutral resource) 00592 // (3) use default UI language id 00593 // 00594 // If the PRIMARY language id is ZERO, then ALSO attempt to 00595 // match the following language ids in this order: 00596 // 00597 // (4) use lang id of TEB if different from user locale 00598 // (5) use UI lang from exe resource 00599 // (6) use primary UI lang from exe resource 00600 // (7) use Install Language 00601 // (8) use lang id from user's locale id 00602 // (9) use primary language of user's locale id 00603 // (10) use lang id from system default locale id 00604 // (11) use primary language of system default locale id 00605 // (12) use US English lang id 00606 // (13) use any lang id that matches requested info 00607 // 00608 if (ResourceIdPathLength == 0 && IdPathLength == 3) { 00609 LanguageResourceDirectory = ResourceDirectory; 00610 } 00611 00612 if (LanguageResourceDirectory != NULL) { 00613 GivenLanguage = (LANGID)IdPath[ 2 ]; 00614 fIsNeutral = (PRIMARYLANGID( GivenLanguage ) == LANG_NEUTRAL); 00615 TryNextLangId: 00616 switch( RetryCount++ ) { 00617 #ifdef NTOS_KERNEL_RUNTIME 00618 case 0: // Use given language id 00619 NewLangId = GivenLanguage; 00620 break; 00621 00622 case 1: // Use primary language of given language id 00623 NewLangId = PRIMARYLANGID( GivenLanguage ); 00624 break; 00625 00626 case 2: // Use id 0 (neutral resource) 00627 NewLangId = 0; 00628 break; 00629 00630 case 3: // Use user's default UI language 00631 NewLangId = (LANGID)ResourceIdRetry; 00632 break; 00633 00634 case 4: // Use native UI language 00635 if ( !fIsNeutral ) { 00636 // Stop looking - Not in the neutral case 00637 goto ReturnFailure; 00638 break; 00639 } 00640 NewLangId = PsInstallUILanguageId; 00641 break; 00642 00643 case 5: // Use default system locale 00644 NewLangId = LANGIDFROMLCID(PsDefaultSystemLocaleId); 00645 break; 00646 00647 case 6: 00648 // Use US English language 00649 NewLangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); 00650 break; 00651 00652 case 7: // Take any lang id that matches 00653 NewLangId = USE_FIRSTAVAILABLE_LANGID; 00654 break; 00655 00656 #else 00657 case 0: // Use given language id 00658 NewLangId = GivenLanguage; 00659 break; 00660 00661 case 1: // Use primary language of given language id 00662 if ( ExactLangMatchOnly) { 00663 // 00664 // Did not find an exact language match. 00665 // Stop looking. 00666 // 00667 goto ReturnFailure; 00668 } 00669 NewLangId = PRIMARYLANGID( GivenLanguage ); 00670 break; 00671 00672 case 2: // Use id 0 (neutral resource) 00673 NewLangId = 0; 00674 break; 00675 00676 case 3: // Use user's default UI language 00677 00678 if (!UILangId){ 00679 Status = NtQueryDefaultUILanguage( &UILangId ); 00680 if (!NT_SUCCESS( Status )) { 00681 // 00682 // Failed reading key. Skip this lookup. 00683 // 00684 NewLangId = (LANGID)ResourceIdRetry; 00685 break; 00686 } 00687 } 00688 NewLangId = UILangId; 00689 // 00690 // Arabic/Hebrew MUI files may contain resources with LANG ID different than 401/40d. 00691 // e.g. Comdlg32.dll has two sets of Arabic/Hebrew resources one mirrored (401/40d) 00692 // and one flipped (801/80d). 00693 // 00694 if( !fIsNeutral && 00695 ((PRIMARYLANGID (GivenLanguage) == LANG_ARABIC) || (PRIMARYLANGID (GivenLanguage) == LANG_HEBREW)) && 00696 (PRIMARYLANGID (GivenLanguage) == PRIMARYLANGID (NewLangId)) 00697 ) { 00698 NewLangId = GivenLanguage; 00699 } 00700 00701 if (fIsNeutral || GivenLanguage == NewLangId){ 00702 // 00703 // Load alternate resource dll. 00704 // 00705 AltResourceDllHandle=LdrLoadAlternateResourceModule( 00706 DllHandle, 00707 NULL); 00708 00709 if (!AltResourceDllHandle){ 00710 // 00711 // Alternate resource dll not available. 00712 // Skip this lookup. 00713 // 00714 NewLangId = (LANGID)ResourceIdRetry; 00715 break; 00716 00717 } 00718 00719 // 00720 // Map to alternate resource dll and search 00721 // it instead. 00722 // 00723 00724 UIResourceIdPath[0]=IdPath[0]; 00725 UIResourceIdPath[1]=IdPath[1]; 00726 UIResourceIdPath[2]=NewLangId; 00727 00728 Status = LdrpSearchResourceSection_U( 00729 AltResourceDllHandle, 00730 UIResourceIdPath, 00731 3, 00732 FindDirectoryEntry, 00733 TRUE, 00734 (PVOID *)ResourceDirectoryOrData 00735 ); 00736 00737 if (NT_SUCCESS(Status)){ 00738 // 00739 // We sucessfully found alternate resource, 00740 // return it. 00741 // 00742 return Status; 00743 } 00744 00745 00746 } 00747 // 00748 // Caller does not want alternate resource, or 00749 // alternate resource not found. 00750 // 00751 NewLangId = (LANGID)ResourceIdRetry; 00752 break; 00753 00754 00755 case 4: // Use langid of ThreadLocale if different from user locale 00756 if ( !fIsNeutral ) { 00757 // Stop looking - Not in the neutral case 00758 goto ReturnFailure; 00759 break; 00760 } 00761 00762 // 00763 // Try the thread locale language-id if it is different from 00764 // user locale. 00765 // 00766 if (NtCurrentTeb()){ 00767 Status = NtQueryDefaultLocale( 00768 TRUE, 00769 &DefaultThreadLocale 00770 ); 00771 if (NT_SUCCESS( Status ) && 00772 DefaultThreadLocale != 00773 NtCurrentTeb()->CurrentLocale) { 00774 // 00775 // Thread locale is different from 00776 // default locale. 00777 // 00778 NewLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale); 00779 break; 00780 } 00781 } 00782 00783 NewLangId = (LANGID)ResourceIdRetry; 00784 break; 00785 00786 00787 case 5: // UI language from the executable resource 00788 00789 if (!UILangId){ 00790 NewLangId = (LANGID)ResourceIdRetry; 00791 } else { 00792 NewLangId = UILangId; 00793 } 00794 break; 00795 00796 case 6: // Parimary lang of UI language from the executable resource 00797 00798 if (!UILangId){ 00799 NewLangId = (LANGID)ResourceIdRetry; 00800 } else { 00801 NewLangId = PRIMARYLANGID( (LANGID) UILangId ); 00802 } 00803 break; 00804 00805 case 7: // Use install -native- language 00806 // 00807 // Thread locale is the same as the user locale, then let's 00808 // try loading the native (install) ui language resources. 00809 // 00810 if (!InstallLangId){ 00811 Status = NtQueryInstallUILanguage(&InstallLangId); 00812 if (!NT_SUCCESS( Status )) { 00813 // 00814 // Failed reading key. Skip this lookup. 00815 // 00816 NewLangId = (LANGID)ResourceIdRetry; 00817 break; 00818 00819 } 00820 } 00821 00822 NewLangId = InstallLangId; 00823 break; 00824 00825 case 8: // Use lang id from locale in TEB 00826 if (SUBLANGID( GivenLanguage ) == SUBLANG_SYS_DEFAULT) { 00827 // Skip over all USER locale options 00828 DefaultThreadLocale = 0; 00829 RetryCount += 2; 00830 break; 00831 } 00832 00833 if (NtCurrentTeb() != NULL) { 00834 NewLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale); 00835 } 00836 break; 00837 00838 case 9: // Use User's default locale 00839 Status = NtQueryDefaultLocale( TRUE, &DefaultThreadLocale ); 00840 if (NT_SUCCESS( Status )) { 00841 NewLangId = LANGIDFROMLCID(DefaultThreadLocale); 00842 break; 00843 } 00844 00845 RetryCount++; 00846 break; 00847 00848 case 10: // Use primary language of User's default locale 00849 NewLangId = PRIMARYLANGID( (LANGID)ResourceIdRetry ); 00850 break; 00851 00852 case 11: // Use System default locale 00853 Status = NtQueryDefaultLocale( FALSE, &DefaultSystemLocale ); 00854 if (!NT_SUCCESS( Status )) { 00855 RetryCount++; 00856 break; 00857 } 00858 if (DefaultSystemLocale != DefaultThreadLocale) { 00859 NewLangId = LANGIDFROMLCID(DefaultSystemLocale); 00860 break; 00861 } 00862 00863 RetryCount += 2; 00864 // fall through 00865 00866 case 13: // Use US English language 00867 NewLangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); 00868 break; 00869 00870 case 12: // Use primary language of System default locale 00871 NewLangId = PRIMARYLANGID( (LANGID)ResourceIdRetry ); 00872 break; 00873 00874 case 14: // Take any lang id that matches 00875 NewLangId = USE_FIRSTAVAILABLE_LANGID; 00876 break; 00877 #endif 00878 default: // No lang ids to match 00879 goto ReturnFailure; 00880 break; 00881 } 00882 00883 // 00884 // If looking for a specific language id and same as the 00885 // one we just looked up, then skip it. 00886 // 00887 if (NewLangId != USE_FIRSTAVAILABLE_LANGID && 00888 NewLangId == ResourceIdRetry 00889 ) { 00890 goto TryNextLangId; 00891 } 00892 00893 // 00894 // Try this new language Id 00895 // 00896 ResourceIdRetry = (ULONG_PTR)NewLangId; 00897 ResourceIdPath = &ResourceIdRetry; 00898 ResourceDirectory = LanguageResourceDirectory; 00899 } 00900 00901 n = ResourceDirectory->NumberOfNamedEntries; 00902 ResourceDirEntLow = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1); 00903 if (!(*ResourceIdPath & LDR_RESOURCE_ID_NAME_MASK)) { 00904 ResourceDirEntLow += n; 00905 n = ResourceDirectory->NumberOfIdEntries; 00906 } 00907 00908 if (!n) { 00909 ResourceDirectory = NULL; 00910 goto NotFound; 00911 } 00912 00913 if (LanguageResourceDirectory != NULL && 00914 *ResourceIdPath == USE_FIRSTAVAILABLE_LANGID 00915 ) { 00916 ResourceDirectory = NULL; 00917 ResourceIdRetry = ResourceDirEntLow->Name; 00918 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY) 00919 ((PCHAR)TopResourceDirectory + 00920 ResourceDirEntLow->OffsetToData 00921 ); 00922 00923 break; 00924 } 00925 00926 ResourceDirectory = NULL; 00927 ResourceDirEntHigh = ResourceDirEntLow + n - 1; 00928 while (ResourceDirEntLow <= ResourceDirEntHigh) { 00929 if ((half = (n >> 1)) != 0) { 00930 ResourceDirEntMiddle = ResourceDirEntLow; 00931 if (*(PUCHAR)&n & 1) { 00932 ResourceDirEntMiddle += half; 00933 } 00934 else { 00935 ResourceDirEntMiddle += half - 1; 00936 } 00937 dir = LdrpCompareResourceNames_U( *ResourceIdPath, 00938 TopResourceDirectory, 00939 ResourceDirEntMiddle 00940 ); 00941 if (!dir) { 00942 if (ResourceDirEntMiddle->DataIsDirectory) { 00943 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY) 00944 ((PCHAR)TopResourceDirectory + 00945 ResourceDirEntMiddle->OffsetToDirectory 00946 ); 00947 } 00948 else { 00949 ResourceDirectory = NULL; 00950 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY) 00951 ((PCHAR)TopResourceDirectory + 00952 ResourceDirEntMiddle->OffsetToData 00953 ); 00954 } 00955 00956 break; 00957 } 00958 else { 00959 if (dir < 0) { 00960 ResourceDirEntHigh = ResourceDirEntMiddle - 1; 00961 if (*(PUCHAR)&n & 1) { 00962 n = half; 00963 } 00964 else { 00965 n = half - 1; 00966 } 00967 } 00968 else { 00969 ResourceDirEntLow = ResourceDirEntMiddle + 1; 00970 n = half; 00971 } 00972 } 00973 } 00974 else { 00975 if (n != 0) { 00976 dir = LdrpCompareResourceNames_U( *ResourceIdPath, 00977 TopResourceDirectory, 00978 ResourceDirEntLow 00979 ); 00980 if (!dir) { 00981 if (ResourceDirEntLow->DataIsDirectory) { 00982 ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY) 00983 ((PCHAR)TopResourceDirectory + 00984 ResourceDirEntLow->OffsetToDirectory 00985 ); 00986 } 00987 else { 00988 ResourceEntry = (PIMAGE_RESOURCE_DATA_ENTRY) 00989 ((PCHAR)TopResourceDirectory + 00990 ResourceDirEntLow->OffsetToData 00991 ); 00992 } 00993 } 00994 } 00995 00996 break; 00997 } 00998 } 00999 01000 ResourceIdPath++; 01001 } 01002 01003 if (ResourceEntry != NULL && !FindDirectoryEntry) { 01004 *ResourceDirectoryOrData = (PVOID)ResourceEntry; 01005 Status = STATUS_SUCCESS; 01006 } 01007 else 01008 if (ResourceDirectory != NULL && FindDirectoryEntry) { 01009 *ResourceDirectoryOrData = (PVOID)ResourceDirectory; 01010 Status = STATUS_SUCCESS; 01011 } 01012 else { 01013 NotFound: 01014 switch( IdPathLength - ResourceIdPathLength) { 01015 case 3: Status = STATUS_RESOURCE_LANG_NOT_FOUND; break; 01016 case 2: Status = STATUS_RESOURCE_NAME_NOT_FOUND; break; 01017 case 1: Status = STATUS_RESOURCE_TYPE_NOT_FOUND; break; 01018 default: Status = STATUS_INVALID_PARAMETER; break; 01019 } 01020 } 01021 01022 if (Status == STATUS_RESOURCE_LANG_NOT_FOUND && 01023 LanguageResourceDirectory != NULL 01024 ) { 01025 ResourceEntry = NULL; 01026 goto TryNextLangId; 01027 ReturnFailure: ; 01028 Status = STATUS_RESOURCE_LANG_NOT_FOUND; 01029 } 01030 } 01031 except (EXCEPTION_EXECUTE_HANDLER) { 01032 Status = GetExceptionCode(); 01033 } 01034 01035 return Status; 01036 }

VOID LdrQueryApplicationCompatibilityGoo IN PUNICODE_STRING  UnicodeImageName  ) 
 

Definition at line 2277 of file ldrinit.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, GetNextCommaValue(), L, LdrFindAppCompatVariableInfo(), LdrpAccessResourceData(), LdrpSearchResourceSection_U(), LdrQueryImageFileExecutionOptions(), Name, NT_SUCCESS, NTSTATUS(), NULL, Resource, RtlAllocateHeap, RtlFreeHeap, RtlInitUnicodeString(), RtlQueryEnvironmentVariable_U(), TRUE, and USHORT.

Referenced by LdrpInitializeProcess().

02283 : 02284 02285 This function is called by LdrpInitialize after its initialized the 02286 process. It's purpose is to query any application specific flags, 02287 hacks, etc. If any app specific information is found, its hung off 02288 the PEB for other components to test against. 02289 02290 Besides setting hanging the AppCompatInfo struct off the PEB, the 02291 only other action that will occur in here is setting OS version 02292 numbers in the PEB if the appropriate Version lie app flag is set. 02293 02294 Arguments: 02295 02296 UnicodeImageName - Actual image name (including path) 02297 02298 Return Value: 02299 02300 None. 02301 02302 --*/ 02303 02304 { 02305 02306 PPEB Peb; 02307 PVOID ResourceInfo; 02308 ULONG TotalGooLength; 02309 ULONG AppCompatLength; 02310 ULONG ResultSize; 02311 ULONG ResourceSize; 02312 ULONG InputCompareLength; 02313 ULONG OutputCompareLength; 02314 LANGID LangId; 02315 NTSTATUS st; 02316 BOOLEAN bImageContainsVersionResourceInfo; 02317 ULONG_PTR IdPath[3]; 02318 APP_COMPAT_GOO LocalAppCompatGoo; 02319 PAPP_COMPAT_GOO AppCompatGoo; 02320 PAPP_COMPAT_INFO AppCompatInfo; 02321 PAPP_VARIABLE_INFO AppVariableInfo; 02322 PPRE_APP_COMPAT_INFO AppCompatEntry; 02323 PIMAGE_RESOURCE_DATA_ENTRY DataEntry; 02324 PEFFICIENTOSVERSIONINFOEXW OSVerInfo; 02325 UNICODE_STRING EnvName; 02326 UNICODE_STRING EnvValue; 02327 WCHAR *NewCSDString; 02328 WCHAR TempString[ 128 ]; // is the size of szCSDVersion in OSVERSIONINFOW 02329 BOOLEAN fNewCSDVersionBuffer = FALSE; 02330 02331 struct { 02332 USHORT TotalSize; 02333 USHORT DataSize; 02334 USHORT Type; 02335 WCHAR Name[16]; // L"VS_VERSION_INFO" + unicode nul 02336 } *Resource; 02337 02338 02339 // 02340 // Check execution options to see if there's any Goo for this app. 02341 // We purposely feed a small struct to LdrQueryImageFileExecOptions, 02342 // so that it can come back with success/failure, and if success we see 02343 // how much we need to alloc. As the results coming back will be of 02344 // variable length. 02345 // 02346 Peb = NtCurrentPeb(); 02347 Peb->AppCompatInfo = NULL; 02348 RtlInitUnicodeString(&Peb->CSDVersion, NULL); 02349 02350 st = LdrQueryImageFileExecutionOptions( UnicodeImageName, 02351 L"ApplicationGoo", 02352 REG_BINARY, 02353 &LocalAppCompatGoo, 02354 sizeof(APP_COMPAT_GOO), 02355 &ResultSize 02356 ); 02357 02358 // 02359 // If there's an entry there, we're guaranteed to get overflow error. 02360 // 02361 if (st == STATUS_BUFFER_OVERFLOW) { 02362 02363 // 02364 // Something is there, alloc memory for the "Pre" Goo struct right now 02365 // 02366 AppCompatGoo = \ 02367 RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, ResultSize); 02368 02369 if (!AppCompatGoo) { 02370 return; 02371 } 02372 02373 // 02374 // Now that we've got the memory, hit it again 02375 // 02376 st = LdrQueryImageFileExecutionOptions( UnicodeImageName, 02377 L"ApplicationGoo", 02378 REG_BINARY, 02379 AppCompatGoo, 02380 ResultSize, 02381 &ResultSize 02382 ); 02383 02384 if (!NT_SUCCESS( st )) { 02385 RtlFreeHeap(Peb->ProcessHeap, 0, AppCompatGoo); 02386 return; 02387 } 02388 02389 // 02390 // Got a hit on this key, however we don't know fer sure that its 02391 // an exact match. There could be multiple App Compat entries 02392 // within this Goo. So we get the version resource information out 02393 // of the Image hdr (if avail) and later we compare it against all of 02394 // the entries found within the Goo hoping for a match. 02395 // 02396 // Need Language Id in order to query the resource info 02397 // 02398 bImageContainsVersionResourceInfo = FALSE; 02399 // NtQueryDefaultUILanguage(&LangId); 02400 IdPath[0] = 16; // RT_VERSION 02401 IdPath[1] = 1; // VS_VERSION_INFO 02402 IdPath[2] = 0; // LangId; 02403 02404 // 02405 // Search for version resource information 02406 // 02407 try { 02408 st = LdrpSearchResourceSection_U( 02409 Peb->ImageBaseAddress, 02410 IdPath, 02411 3, 02412 FALSE, 02413 FALSE, // TRUE, 02414 &DataEntry 02415 ); 02416 02417 } except(EXCEPTION_EXECUTE_HANDLER) { 02418 st = STATUS_UNSUCCESSFUL; 02419 } 02420 02421 if (NT_SUCCESS( st )) { 02422 02423 // 02424 // Give us a pointer to the resource information 02425 // 02426 try { 02427 st = LdrpAccessResourceData( 02428 Peb->ImageBaseAddress, 02429 DataEntry, 02430 &Resource, 02431 &ResourceSize 02432 ); 02433 02434 } except(EXCEPTION_EXECUTE_HANDLER) { 02435 st = STATUS_UNSUCCESSFUL; 02436 } 02437 02438 if (NT_SUCCESS( st )) { 02439 bImageContainsVersionResourceInfo = TRUE; 02440 } 02441 02442 } 02443 02444 // 02445 // Now that we either have (or have not) the version resource info, 02446 // bounce down each app compat entry looking for a match. If there 02447 // wasn't any version resource info in the image hdr, its going to be 02448 // an automatic match to an entry that also doesn't have anything for 02449 // its version resource info. Obviously there can be only one of these 02450 // "empty" entries within the Goo (as the first one will always be 02451 // matched first. 02452 // 02453 st = STATUS_SUCCESS; 02454 AppCompatEntry = AppCompatGoo->AppCompatEntry; 02455 TotalGooLength = \ 02456 AppCompatGoo->dwTotalGooSize - sizeof(AppCompatGoo->dwTotalGooSize); 02457 while (TotalGooLength) { 02458 02459 try { 02460 02461 // 02462 // Compare what we're told to by the resource info size. The 02463 // ResourceInfo (if avail) is directly behind the AppCompatEntry 02464 // 02465 InputCompareLength = AppCompatEntry->dwResourceInfoSize; 02466 ResourceInfo = AppCompatEntry + 1; 02467 if (bImageContainsVersionResourceInfo) { 02468 02469 if (InputCompareLength > Resource->TotalSize) { 02470 InputCompareLength = Resource->TotalSize; 02471 } 02472 02473 OutputCompareLength = \ 02474 (ULONG)RtlCompareMemory( 02475 ResourceInfo, 02476 Resource, 02477 InputCompareLength 02478 ); 02479 02480 } 02481 02482 // 02483 // In this case, we don't have any version resource info in 02484 // the image header, so set OutputCompareLength to zero. 02485 // If InputCompareLength was set to zero (above) due to the 02486 // AppCompatEntry also having no version resource info, then 02487 // the test will succeed (below) and we've found our match. 02488 // Otherwise, this is not the same app and it won't be a match. 02489 // 02490 else { 02491 OutputCompareLength = 0; 02492 } 02493 02494 } except(EXCEPTION_EXECUTE_HANDLER) { 02495 st = STATUS_UNSUCCESSFUL; 02496 } 02497 02498 if ((!NT_SUCCESS( st )) || 02499 (InputCompareLength != OutputCompareLength)) { 02500 02501 // 02502 // Wasn't a match for some reason or another, goto next entry 02503 // 02504 TotalGooLength -= AppCompatEntry->dwEntryTotalSize; 02505 (PUCHAR) AppCompatEntry += AppCompatEntry->dwEntryTotalSize; 02506 continue; 02507 } 02508 02509 // 02510 // We're a match!!! Now we have to create the final "Post" 02511 // app compat structure that will be used by everyone to follow. 02512 // This guy hangs off the Peb and it doesn't have the resource 02513 // info still lying around in there. 02514 // 02515 AppCompatLength = AppCompatEntry->dwEntryTotalSize; 02516 AppCompatLength -= AppCompatEntry->dwResourceInfoSize; 02517 Peb->AppCompatInfo = \ 02518 RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, AppCompatLength); 02519 02520 if (!Peb->AppCompatInfo) { 02521 break; 02522 } 02523 02524 AppCompatInfo = Peb->AppCompatInfo; 02525 AppCompatInfo->dwTotalSize = AppCompatLength; 02526 02527 // 02528 // Copy what was beyond the resource info to near the top starting at 02529 // the Application compat flags. 02530 // 02531 RtlMoveMemory( 02532 &AppCompatInfo->CompatibilityFlags, 02533 (PUCHAR) ResourceInfo + AppCompatEntry->dwResourceInfoSize, 02534 AppCompatInfo->dwTotalSize - FIELD_OFFSET(APP_COMPAT_INFO, CompatibilityFlags) 02535 ); 02536 02537 // 02538 // Now that we've created the "Post" app compat info struct to be 02539 // used by everyone, we need to check if version lying for this 02540 // app is requested. If so, we need to stuff the Peb right now. 02541 // 02542 if (AppCompatInfo->CompatibilityFlags.QuadPart & KACF_VERSIONLIE) { 02543 02544 // 02545 // Find the variable version lie struct somwhere within 02546 // 02547 if( STATUS_SUCCESS != LdrFindAppCompatVariableInfo(AVT_OSVERSIONINFO, &AppVariableInfo)) { 02548 break; 02549 } 02550 02551 // 02552 // The variable length information itself comes at the end 02553 // of the normal struct and could be of any aribitrary length 02554 // 02555 AppVariableInfo++; 02556 OSVerInfo = (PEFFICIENTOSVERSIONINFOEXW) AppVariableInfo; 02557 Peb->OSMajorVersion = OSVerInfo->dwMajorVersion; 02558 Peb->OSMinorVersion = OSVerInfo->dwMinorVersion; 02559 Peb->OSBuildNumber = (USHORT) OSVerInfo->dwBuildNumber; 02560 Peb->OSCSDVersion = (OSVerInfo->wServicePackMajor << 8) & 0xFF00; 02561 Peb->OSCSDVersion |= OSVerInfo->wServicePackMinor; 02562 Peb->OSPlatformId = OSVerInfo->dwPlatformId; 02563 02564 Peb->CSDVersion.Length = (USHORT)wcslen(&OSVerInfo->szCSDVersion[0])*sizeof(WCHAR); 02565 Peb->CSDVersion.MaximumLength = Peb->CSDVersion.Length + sizeof(WCHAR); 02566 Peb->CSDVersion.Buffer = \ 02567 RtlAllocateHeap( 02568 Peb->ProcessHeap, 02569 HEAP_ZERO_MEMORY, 02570 Peb->CSDVersion.MaximumLength 02571 ); 02572 02573 if (!Peb->CSDVersion.Buffer) { 02574 break; 02575 } 02576 wcscpy(Peb->CSDVersion.Buffer, &OSVerInfo->szCSDVersion[0]); 02577 fNewCSDVersionBuffer = TRUE; 02578 02579 } 02580 02581 break; 02582 02583 } 02584 02585 RtlFreeHeap(Peb->ProcessHeap, 0, AppCompatGoo); 02586 } 02587 02588 02589 // 02590 // Only look at the ENV stuff if haven't already gotten new version info from the registry 02591 // 02592 if ( FALSE == fNewCSDVersionBuffer ) 02593 { 02594 // 02595 // The format of this string is: 02596 // _COMPAT_VER_NNN = MajOSVer, MinOSVer, OSBldNum, MajCSD, MinCSD, PlatformID, CSDString 02597 // eg: _COMPAT_VER_NNN=4,0,1381,3,0,2,Service Pack 3 02598 // (for NT 4 SP3) 02599 02600 RtlInitUnicodeString(&EnvName, L"_COMPAT_VER_NNN"); 02601 02602 EnvValue.Buffer = TempString; 02603 EnvValue.Length = 0; 02604 EnvValue.MaximumLength = sizeof(TempString); 02605 02606 02607 st = RtlQueryEnvironmentVariable_U( 02608 NULL, 02609 &EnvName, 02610 &EnvValue 02611 ); 02612 02613 // 02614 // One of the possible error codes is BUFFER_TOO_SMALL - this indicates a 02615 // string that's wacko - they should not be larger than the size we define/expect 02616 // In this case, we'll ignore that string 02617 // 02618 if ( STATUS_SUCCESS == st ) 02619 { 02620 WCHAR *p = EnvValue.Buffer; 02621 WCHAR *NewSPString; 02622 ULONG len = EnvValue.Length / sizeof(WCHAR); // (Length is bytes, not chars) 02623 02624 // 02625 // Ok, someone wants different version info. 02626 // 02627 Peb->OSMajorVersion = GetNextCommaValue( &p, &len ); 02628 Peb->OSMinorVersion = GetNextCommaValue( &p, &len ); 02629 Peb->OSBuildNumber = (USHORT)GetNextCommaValue( &p, &len ); 02630 Peb->OSCSDVersion = (USHORT)(GetNextCommaValue( &p, &len )) << 8; 02631 Peb->OSCSDVersion |= (USHORT)GetNextCommaValue( &p, &len ); 02632 Peb->OSPlatformId = GetNextCommaValue( &p, &len ); 02633 02634 02635 // 02636 // Need to free the old buffer if there is one... 02637 // 02638 if ( fNewCSDVersionBuffer ) 02639 { 02640 RtlFreeHeap( Peb->ProcessHeap, 0, Peb->CSDVersion.Buffer ); 02641 Peb->CSDVersion.Buffer = NULL; 02642 } 02643 02644 if ( len ) 02645 { 02646 NewCSDString = \ 02647 RtlAllocateHeap( 02648 Peb->ProcessHeap, 02649 HEAP_ZERO_MEMORY, 02650 ( len + 1 ) * sizeof(WCHAR) 02651 ); 02652 02653 if ( NULL == NewCSDString ) 02654 { 02655 return; 02656 } 02657 02658 // 02659 // Now copy the string to memory that we'll keep 02660 // 02661 // We do a movemem here rather than a string copy because current comments in 02662 // RtlQueryEnvironmentVariable() indicate that in an edge case, we might not 02663 // have a trailing NULL - berniem 7/7/99 02664 // 02665 RtlMoveMemory( NewCSDString, p, len * sizeof(WCHAR) ); 02666 02667 } 02668 else 02669 { 02670 NewCSDString = NULL; 02671 } 02672 02673 RtlInitUnicodeString( &(Peb->CSDVersion), NewCSDString ); 02674 02675 } 02676 } 02677 02678 return; 02679 }

NTSTATUS LdrQueryImageFileExecutionOptions IN PUNICODE_STRING  ImagePathName,
IN PWSTR  OptionName,
IN ULONG  Type,
OUT PVOID  Buffer,
IN ULONG  BufferSize,
OUT PULONG ResultSize  OPTIONAL
 

Definition at line 1796 of file ldrinit.c.

References Buffer, BufferSize, FALSE, KeyPath, KeyPathBuffer, L, MAKE_TAG, NT_SUCCESS, NtClose(), NtOpenKey(), NtQueryValueKey(), NTSTATUS(), NULL, ObjectAttributes, RtlAllocateHeap, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlFreeHeap, RtlInitUnicodeString(), RtlUnicodeStringToInteger(), Status, TEMP_TAG, TRUE, and USHORT.

Referenced by LdrpInitialize(), LdrpInitializeProcess(), LdrpRunInitializeRoutines(), and LdrQueryApplicationCompatibilityGoo().

01804 { 01805 BOOLEAN bNeedToFree=FALSE; 01806 NTSTATUS Status; 01807 UNICODE_STRING UnicodeString; 01808 PWSTR pw; 01809 OBJECT_ATTRIBUTES ObjectAttributes; 01810 HANDLE KeyHandle; 01811 UNICODE_STRING KeyPath; 01812 WCHAR KeyPathBuffer[ DOS_MAX_COMPONENT_LENGTH + 100 ]; 01813 ULONG KeyValueBuffer[ 256 ]; 01814 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 01815 ULONG AllocLength; 01816 ULONG ResultLength; 01817 01818 KeyPath.Buffer = KeyPathBuffer; 01819 KeyPath.Length = 0; 01820 KeyPath.MaximumLength = sizeof( KeyPathBuffer ); 01821 01822 RtlAppendUnicodeToString( &KeyPath, 01823 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" 01824 ); 01825 01826 UnicodeString = *ImagePathName; 01827 pw = (PWSTR)((PCHAR)UnicodeString.Buffer + UnicodeString.Length); 01828 UnicodeString.MaximumLength = UnicodeString.Length; 01829 while (UnicodeString.Length != 0) { 01830 if (pw[ -1 ] == OBJ_NAME_PATH_SEPARATOR) { 01831 break; 01832 } 01833 pw--; 01834 UnicodeString.Length -= sizeof( *pw ); 01835 } 01836 UnicodeString.Buffer = pw; 01837 UnicodeString.Length = UnicodeString.MaximumLength - UnicodeString.Length; 01838 01839 RtlAppendUnicodeStringToString( &KeyPath, &UnicodeString ); 01840 01841 InitializeObjectAttributes( &ObjectAttributes, 01842 &KeyPath, 01843 OBJ_CASE_INSENSITIVE, 01844 NULL, 01845 NULL 01846 ); 01847 01848 Status = NtOpenKey( &KeyHandle, 01849 GENERIC_READ, 01850 &ObjectAttributes 01851 ); 01852 01853 if (!NT_SUCCESS( Status )) { 01854 return Status; 01855 } 01856 01857 RtlInitUnicodeString( &UnicodeString, OptionName ); 01858 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyValueBuffer; 01859 Status = NtQueryValueKey( KeyHandle, 01860 &UnicodeString, 01861 KeyValuePartialInformation, 01862 KeyValueInformation, 01863 sizeof( KeyValueBuffer ), 01864 &ResultLength 01865 ); 01866 if (Status == STATUS_BUFFER_OVERFLOW) { 01867 // 01868 // This function can be called before the process heap gets created 01869 // therefore we need to protect against this case. The majority of the 01870 // code will not hit this code path because they read just strings 01871 // containing hex numbers and for this the size of KeyValueBuffer is 01872 // more than sufficient. 01873 // 01874 01875 if (RtlProcessHeap()) { 01876 01877 AllocLength = sizeof( *KeyValueInformation ) + 01878 KeyValueInformation->DataLength; 01879 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) 01880 RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TEMP_TAG ), AllocLength); 01881 01882 if (KeyValueInformation == NULL) { 01883 Status = STATUS_NO_MEMORY; 01884 } 01885 else { 01886 bNeedToFree = TRUE; 01887 Status = NtQueryValueKey( KeyHandle, 01888 &UnicodeString, 01889 KeyValuePartialInformation, 01890 KeyValueInformation, 01891 AllocLength, 01892 &ResultLength 01893 ); 01894 } 01895 } 01896 else { 01897 01898 Status = STATUS_NO_MEMORY; 01899 } 01900 } 01901 01902 if (NT_SUCCESS( Status )) { 01903 if (KeyValueInformation->Type == REG_BINARY) { 01904 if ((Buffer) && 01905 (KeyValueInformation->DataLength <= BufferSize)) { 01906 RtlMoveMemory( Buffer, &KeyValueInformation->Data, KeyValueInformation->DataLength); 01907 } 01908 else { 01909 Status = STATUS_BUFFER_OVERFLOW; 01910 } 01911 if (ARGUMENT_PRESENT( ResultSize )) { 01912 *ResultSize = KeyValueInformation->DataLength; 01913 } 01914 } 01915 else if (KeyValueInformation->Type == REG_DWORD) { 01916 01917 if (Type != REG_DWORD) { 01918 Status = STATUS_OBJECT_TYPE_MISMATCH; 01919 } 01920 else { 01921 if ((Buffer) 01922 && (BufferSize == sizeof(ULONG)) 01923 && (KeyValueInformation->DataLength == BufferSize)) { 01924 01925 RtlMoveMemory( Buffer, &KeyValueInformation->Data, KeyValueInformation->DataLength); 01926 } 01927 else { 01928 Status = STATUS_BUFFER_OVERFLOW; 01929 } 01930 01931 if (ARGUMENT_PRESENT( ResultSize )) { 01932 *ResultSize = KeyValueInformation->DataLength; 01933 } 01934 } 01935 } 01936 else if (KeyValueInformation->Type != REG_SZ) { 01937 Status = STATUS_OBJECT_TYPE_MISMATCH; 01938 } 01939 else { 01940 if (Type == REG_DWORD) { 01941 if (BufferSize != sizeof( ULONG )) { 01942 BufferSize = 0; 01943 Status = STATUS_INFO_LENGTH_MISMATCH; 01944 } 01945 else { 01946 UnicodeString.Buffer = (PWSTR)&KeyValueInformation->Data; 01947 UnicodeString.Length = (USHORT) 01948 (KeyValueInformation->DataLength - sizeof( UNICODE_NULL )); 01949 UnicodeString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 01950 Status = RtlUnicodeStringToInteger( &UnicodeString, 0, (PULONG)Buffer ); 01951 } 01952 } 01953 else { 01954 if (KeyValueInformation->DataLength > BufferSize) { 01955 Status = STATUS_BUFFER_OVERFLOW; 01956 } 01957 else { 01958 BufferSize = KeyValueInformation->DataLength; 01959 } 01960 01961 RtlMoveMemory( Buffer, &KeyValueInformation->Data, BufferSize ); 01962 } 01963 01964 if (ARGUMENT_PRESENT( ResultSize )) { 01965 *ResultSize = BufferSize; 01966 } 01967 } 01968 } 01969 01970 if (bNeedToFree) 01971 RtlFreeHeap(RtlProcessHeap(), 0, KeyValueInformation); 01972 NtClose( KeyHandle ); 01973 return Status; 01974 }

VOID LdrShutdownProcess VOID   ) 
 

Definition at line 1462 of file ldrinit.c.

References CommandLine, DbgPrint, LdrpCallInitRoutine, LdrpCallTlsInitializers(), LdrpImageHasTls, LdrpShutdownInProgress, LdrpShutdownThreadId, LoaderLock, NULL, RtlpHeapIsLocked(), RtlValidateProcessHeaps(), ShowSnaps, and TRUE.

01468 : 01469 01470 This function is called by a process that is terminating cleanly. 01471 It's purpose is to call all of the processes DLLs to notify them 01472 that the process is detaching. 01473 01474 Arguments: 01475 01476 None 01477 01478 Return Value: 01479 01480 None. 01481 01482 --*/ 01483 01484 { 01485 PPEB Peb; 01486 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 01487 PDLL_INIT_ROUTINE InitRoutine; 01488 PLIST_ENTRY Next; 01489 01490 // 01491 // only unload once ! DllTerm routines might call exit process in fatal situations 01492 // 01493 01494 if ( LdrpShutdownInProgress ) { 01495 return; 01496 } 01497 01498 Peb = NtCurrentPeb(); 01499 01500 if (ShowSnaps) { 01501 UNICODE_STRING CommandLine; 01502 01503 CommandLine = Peb->ProcessParameters->CommandLine; 01504 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROC_PARAMS_NORMALIZED)) { 01505 CommandLine.Buffer = (PWSTR)((PCHAR)CommandLine.Buffer + (ULONG_PTR)(Peb->ProcessParameters)); 01506 } 01507 01508 DbgPrint( "LDR: PID: 0x%x finished - '%wZ'\n", 01509 NtCurrentTeb()->ClientId.UniqueProcess, 01510 &CommandLine 01511 ); 01512 } 01513 01514 LdrpShutdownThreadId = NtCurrentTeb()->ClientId.UniqueThread; 01515 LdrpShutdownInProgress = TRUE; 01516 RtlEnterCriticalSection(&LoaderLock); 01517 01518 try { 01519 01520 // 01521 // check to see if the heap is locked. If so, do not do ANY 01522 // dll processing since it is very likely that a dll will need 01523 // to do heap operations, but that the heap is not in good shape. 01524 // ExitProcess called in a very active app can leave threads terminated 01525 // in the middle of the heap code or in other very bad places. Checking the 01526 // heap lock is a good indication that the process was very active when it 01527 // called ExitProcess 01528 // 01529 01530 if ( RtlpHeapIsLocked( RtlProcessHeap() )) { 01531 ; 01532 } 01533 else { 01534 if ( Peb->BeingDebugged ) { 01535 RtlValidateProcessHeaps(); 01536 } 01537 01538 // 01539 // Go in reverse order initialization order and build 01540 // the unload list 01541 // 01542 01543 Next = Peb->Ldr->InInitializationOrderModuleList.Blink; 01544 while ( Next != &Peb->Ldr->InInitializationOrderModuleList) { 01545 LdrDataTableEntry 01546 = (PLDR_DATA_TABLE_ENTRY) 01547 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InInitializationOrderLinks)); 01548 01549 Next = Next->Blink; 01550 01551 // 01552 // Walk through the entire list looking for 01553 // entries. For each entry, that has an init 01554 // routine, call it. 01555 // 01556 01557 if (Peb->ImageBaseAddress != LdrDataTableEntry->DllBase) { 01558 InitRoutine = (PDLL_INIT_ROUTINE)LdrDataTableEntry->EntryPoint; 01559 if (InitRoutine && (LdrDataTableEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) ) { 01560 if (LdrDataTableEntry->Flags) { 01561 if ( LdrDataTableEntry->TlsIndex ) { 01562 LdrpCallTlsInitializers(LdrDataTableEntry->DllBase,DLL_PROCESS_DETACH); 01563 } 01564 01565 #if defined (WX86) 01566 if (!Wx86ProcessInit || 01567 LdrpRunWx86DllEntryPoint(InitRoutine, 01568 NULL, 01569 LdrDataTableEntry->DllBase, 01570 DLL_PROCESS_DETACH, 01571 (PVOID)1 01572 ) == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) 01573 #endif 01574 { 01575 LdrpCallInitRoutine(InitRoutine, 01576 LdrDataTableEntry->DllBase, 01577 DLL_PROCESS_DETACH, 01578 (PVOID)1); 01579 } 01580 01581 } 01582 } 01583 } 01584 } 01585 01586 // 01587 // If the image has tls than call its initializers 01588 // 01589 01590 if ( LdrpImageHasTls ) { 01591 LdrpCallTlsInitializers(NtCurrentPeb()->ImageBaseAddress,DLL_PROCESS_DETACH); 01592 } 01593 } 01594 01595 } finally { 01596 RtlLeaveCriticalSection(&LoaderLock); 01597 } 01598 01599 }

VOID LdrShutdownThread VOID   ) 
 

Definition at line 1602 of file ldrinit.c.

References LdrpCallInitRoutine, LdrpCallTlsInitializers(), LdrpFreeTls(), LdrpImageHasTls, LoaderLock, and NULL.

01608 : 01609 01610 This function is called by a thread that is terminating cleanly. 01611 It's purpose is to call all of the processes DLLs to notify them 01612 that the thread is detaching. 01613 01614 Arguments: 01615 01616 None 01617 01618 Return Value: 01619 01620 None. 01621 01622 --*/ 01623 01624 { 01625 PPEB Peb; 01626 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 01627 PDLL_INIT_ROUTINE InitRoutine; 01628 PLIST_ENTRY Next; 01629 01630 Peb = NtCurrentPeb(); 01631 01632 RtlEnterCriticalSection(&LoaderLock); 01633 01634 try { 01635 01636 01637 // 01638 // Go in reverse order initialization order and build 01639 // the unload list 01640 // 01641 01642 Next = Peb->Ldr->InInitializationOrderModuleList.Blink; 01643 while ( Next != &Peb->Ldr->InInitializationOrderModuleList) { 01644 LdrDataTableEntry 01645 = (PLDR_DATA_TABLE_ENTRY) 01646 (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InInitializationOrderLinks)); 01647 01648 Next = Next->Blink; 01649 01650 // 01651 // Walk through the entire list looking for 01652 // entries. For each entry, that has an init 01653 // routine, call it. 01654 // 01655 01656 if (Peb->ImageBaseAddress != LdrDataTableEntry->DllBase) { 01657 if ( !(LdrDataTableEntry->Flags & LDRP_DONT_CALL_FOR_THREADS)) { 01658 InitRoutine = (PDLL_INIT_ROUTINE)LdrDataTableEntry->EntryPoint; 01659 if (InitRoutine && (LdrDataTableEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) ) { 01660 if (LdrDataTableEntry->Flags & LDRP_IMAGE_DLL) { 01661 if ( LdrDataTableEntry->TlsIndex ) { 01662 LdrpCallTlsInitializers(LdrDataTableEntry->DllBase,DLL_THREAD_DETACH); 01663 } 01664 01665 #if defined (WX86) 01666 if (!Wx86ProcessInit || 01667 LdrpRunWx86DllEntryPoint(InitRoutine, 01668 NULL, 01669 LdrDataTableEntry->DllBase, 01670 DLL_THREAD_DETACH, 01671 NULL 01672 ) == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) 01673 #endif 01674 { 01675 LdrpCallInitRoutine(InitRoutine, 01676 LdrDataTableEntry->DllBase, 01677 DLL_THREAD_DETACH, 01678 NULL); 01679 } 01680 } 01681 } 01682 } 01683 } 01684 } 01685 01686 // 01687 // If the image has tls than call its initializers 01688 // 01689 01690 if ( LdrpImageHasTls ) { 01691 LdrpCallTlsInitializers(NtCurrentPeb()->ImageBaseAddress,DLL_THREAD_DETACH); 01692 } 01693 LdrpFreeTls(); 01694 01695 } finally { 01696 01697 RtlLeaveCriticalSection(&LoaderLock); 01698 } 01699 }

BOOLEAN NtdllOkayToLockRoutine IN PVOID  Lock  ) 
 

Definition at line 236 of file dll/resource.c.

00239 { 00240 return TRUE; 00241 }

PVOID NtdllpAllocateStringRoutine SIZE_T  NumberOfBytes  ) 
 

Definition at line 121 of file ldrinit.c.

References RtlAllocateHeap.

Referenced by LdrpInitializeProcess().

00124 { 00125 return RtlAllocateHeap(RtlProcessHeap(), 0, NumberOfBytes); 00126 }

VOID NtdllpFreeStringRoutine PVOID  Buffer  ) 
 

Definition at line 129 of file ldrinit.c.

References Buffer, and RtlFreeHeap.

Referenced by LdrpInitializeProcess().

00132 { 00133 RtlFreeHeap(RtlProcessHeap(), 0, Buffer); 00134 }

VOID RtlpInitDeferedCriticalSection VOID   ) 
 

Definition at line 211 of file dll/resource.c.

References DbgPrint, DeferedCriticalSection, RtlCriticalSectionList, RtlCriticalSectionLock, RtlInitializeCriticalSectionAndSpinCount(), RtlpChainDebugInfo(), RtlpCreateCriticalSectionSem(), RtlpCritSectInitialized, RtlpDebugInfoFreeList, RtlpStaticDebugInfo, and TRUE.

00212 { 00213 00214 InitializeListHead( &RtlCriticalSectionList ); 00215 00216 if (sizeof( RTL_CRITICAL_SECTION_DEBUG ) != sizeof( RTL_RESOURCE_DEBUG )) { 00217 DbgPrint( "NTDLL: Critical Section & Resource Debug Info length mismatch.\n" ); 00218 return; 00219 } 00220 00221 RtlpDebugInfoFreeList = RtlpChainDebugInfo( RtlpStaticDebugInfo, 00222 sizeof( RtlpStaticDebugInfo ) 00223 ); 00224 00225 RtlInitializeCriticalSectionAndSpinCount( &RtlCriticalSectionLock, 1000 ); 00226 RtlInitializeCriticalSectionAndSpinCount( &DeferedCriticalSection, 1000 ); 00227 00228 RtlpCreateCriticalSectionSem(&DeferedCriticalSection); 00229 00230 RtlpCritSectInitialized = TRUE; 00231 return; 00232 }


Variable Documentation

BOOLEAN LdrpImageHasTls = FALSE
 

Definition at line 32 of file ldrinit.c.

Referenced by LdrpInitializeThread(), LdrpInitializeTls(), LdrpRunInitializeRoutines(), LdrShutdownProcess(), and LdrShutdownThread().

BOOLEAN LdrpInLdrInit = FALSE
 

Definition at line 35 of file ldrinit.c.

Referenced by LdrDisableThreadCalloutsForDll(), LdrGetDllHandle(), LdrpCreateDllSection(), LdrpGetProcedureAddress(), LdrpInitialize(), LdrpLoadDll(), LdrpMapDll(), LdrpSnapThunk(), LdrQueryProcessModuleInformation(), and LdrUnloadDll().

BOOLEAN LdrpLdrDatabaseIsSetup = FALSE
 

Definition at line 34 of file ldrinit.c.

Referenced by LdrpInitializeProcess(), and LdrpLoadDll().

BOOLEAN LdrpShutdownInProgress = FALSE
 

Definition at line 31 of file ldrinit.c.

Referenced by LdrDisableThreadCalloutsForDll(), LdrpInitializeThread(), LdrShutdownProcess(), LdrUnloadDll(), RtlCheckForOrphanedCriticalSections(), RtlpNotOwnerCriticalSection(), and RtlpWaitForCriticalSection().

BOOLEAN LdrpVerifyDlls = FALSE
 

Definition at line 33 of file ldrinit.c.

Referenced by LdrpInitializeProcess().

RTL_CRITICAL_SECTION LoaderLock
 

Initial value:

{ &LoaderLockDebug, -1 }

Definition at line 142 of file ldrinit.c.

Referenced by LdrDisableThreadCalloutsForDll(), LdrFlushAlternateResourceModules(), LdrGetDllHandle(), LdrLoadAlternateResourceModule(), LdrpForkProcess(), LdrpGetProcedureAddress(), LdrpInitialize(), LdrpInitializeProcess(), LdrpLoadDll(), LdrQueryProcessModuleInformation(), LdrShutdownProcess(), LdrShutdownThread(), LdrUnloadAlternateResourceModule(), LdrUnloadDll(), RtlAddFunctionTable(), RtlDeleteFunctionTable(), RtlLookupDynamicFunctionEntry(), and RtlPcToFileHeader().

RTL_CRITICAL_SECTION_DEBUG LoaderLockDebug
 

Definition at line 141 of file ldrinit.c.

BOOLEAN LoaderLockInitialized
 

Definition at line 146 of file ldrinit.c.

Referenced by LdrpForkProcess(), LdrpInitialize(), and LdrpInitializeProcess().

PVOID NtDllBase
 

Definition at line 45 of file ldrinit.c.

Referenced by CsrClientConnectToServer(), LdrpInitializeProcess(), and RtlPcToFileHeader().

PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine
 

Definition at line 136 of file ldrinit.c.

Referenced by IoInitSystem(), LdrpInitializeProcess(), RtlAnsiStringToUnicodeString(), RtlCreateUnicodeString(), RtlDowncaseUnicodeString(), RtlFormatCurrentUserKeyPath(), RtlOemStringToCountedUnicodeString(), RtlOemStringToUnicodeString(), RtlUnicodeStringToAnsiString(), RtlUnicodeStringToCountedOemString(), RtlUnicodeStringToOemString(), RtlUpcaseUnicodeString(), RtlUpcaseUnicodeStringToAnsiString(), RtlUpcaseUnicodeStringToCountedOemString(), and RtlUpcaseUnicodeStringToOemString().

PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine
 

Definition at line 137 of file ldrinit.c.

Referenced by CmpSetVersionData(), LdrpInitializeProcess(), RtlAnsiStringToUnicodeString(), RtlFreeAnsiString(), RtlFreeOemString(), RtlFreeUnicodeString(), RtlOemStringToCountedUnicodeString(), RtlOemStringToUnicodeString(), RtlUnicodeStringToAnsiString(), RtlUnicodeStringToCountedOemString(), RtlUnicodeStringToOemString(), RtlUpcaseUnicodeStringToAnsiString(), RtlUpcaseUnicodeStringToCountedOemString(), and RtlUpcaseUnicodeStringToOemString().

ULONG RtlpDisableHeapLookaside
 

Definition at line 47 of file ldrinit.c.

Referenced by LdrpInitialize(), and RtlCreateHeap().

RTL_BITMAP TlsBitMap
 

Definition at line 138 of file ldrinit.c.

Referenced by LdrpInitializeProcess().

RTL_BITMAP TlsExpansionBitMap
 

Definition at line 139 of file ldrinit.c.

Referenced by LdrpInitializeProcess().


Generated on Sat May 15 19:44:31 2004 for test by doxygen 1.3.7