Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenldrinit.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS NT User-Mode Library 00004 * FILE: dll/ntdll/ldr/ldrinit.c 00005 * PURPOSE: User-Mode Process/Thread Startup 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 * Aleksey Bragin (aleksey@reactos.org) 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntdll.h> 00013 #include <callback.h> 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 00019 /* GLOBALS *******************************************************************/ 00020 00021 HANDLE ImageExecOptionsKey; 00022 HANDLE Wow64ExecOptionsKey; 00023 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"); 00024 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L""); 00025 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll"); 00026 00027 BOOLEAN LdrpInLdrInit; 00028 LONG LdrpProcessInitialized; 00029 BOOLEAN LdrpLoaderLockInit; 00030 BOOLEAN LdrpLdrDatabaseIsSetup; 00031 BOOLEAN LdrpShutdownInProgress; 00032 HANDLE LdrpShutdownThreadId; 00033 00034 BOOLEAN LdrpDllValidation; 00035 00036 PLDR_DATA_TABLE_ENTRY LdrpImageEntry; 00037 PUNICODE_STRING LdrpTopLevelDllBeingLoaded; 00038 WCHAR StringBuffer[156]; 00039 extern PTEB LdrpTopLevelDllBeingLoadedTeb; // defined in rtlsupp.c! 00040 PLDR_DATA_TABLE_ENTRY LdrpCurrentDllInitializer; 00041 PLDR_DATA_TABLE_ENTRY LdrpNtDllDataTableEntry; 00042 00043 RTL_BITMAP TlsBitMap; 00044 RTL_BITMAP TlsExpansionBitMap; 00045 RTL_BITMAP FlsBitMap; 00046 BOOLEAN LdrpImageHasTls; 00047 LIST_ENTRY LdrpTlsList; 00048 ULONG LdrpNumberOfTlsEntries; 00049 ULONG LdrpNumberOfProcessors; 00050 PVOID NtDllBase; 00051 LARGE_INTEGER RtlpTimeout; 00052 BOOLEAN RtlpTimeoutDisable; 00053 LIST_ENTRY LdrpHashTable[LDR_HASH_TABLE_ENTRIES]; 00054 LIST_ENTRY LdrpDllNotificationList; 00055 HANDLE LdrpKnownDllObjectDirectory; 00056 UNICODE_STRING LdrpKnownDllPath; 00057 WCHAR LdrpKnownDllPathBuffer[128]; 00058 UNICODE_STRING LdrpDefaultPath; 00059 00060 PEB_LDR_DATA PebLdr; 00061 00062 RTL_CRITICAL_SECTION_DEBUG LdrpLoaderLockDebug; 00063 RTL_CRITICAL_SECTION LdrpLoaderLock = 00064 { 00065 &LdrpLoaderLockDebug, 00066 -1, 00067 0, 00068 0, 00069 0, 00070 0 00071 }; 00072 RTL_CRITICAL_SECTION FastPebLock; 00073 00074 BOOLEAN ShowSnaps; 00075 00076 ULONG LdrpFatalHardErrorCount; 00077 ULONG LdrpActiveUnloadCount; 00078 00079 //extern LIST_ENTRY RtlCriticalSectionList; 00080 00081 VOID RtlpInitializeVectoredExceptionHandling(VOID); 00082 VOID NTAPI RtlpInitDeferedCriticalSection(VOID); 00083 VOID RtlInitializeHeapManager(VOID); 00084 extern BOOLEAN RtlpPageHeapEnabled; 00085 00086 ULONG RtlpDisableHeapLookaside; // TODO: Move to heap.c 00087 ULONG RtlpShutdownProcessFlags; // TODO: Use it 00088 00089 NTSTATUS LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, PVOID ImageBase); 00090 void actctx_init(void); 00091 00092 #ifdef _WIN64 00093 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232ll 00094 #else 00095 #define DEFAULT_SECURITY_COOKIE 0xBB40E64E 00096 #endif 00097 00098 /* FUNCTIONS *****************************************************************/ 00099 00100 /* 00101 * @implemented 00102 */ 00103 NTSTATUS 00104 NTAPI 00105 LdrOpenImageFileOptionsKey(IN PUNICODE_STRING SubKey, 00106 IN BOOLEAN Wow64, 00107 OUT PHANDLE NewKeyHandle) 00108 { 00109 PHANDLE RootKeyLocation; 00110 HANDLE RootKey; 00111 UNICODE_STRING SubKeyString; 00112 OBJECT_ATTRIBUTES ObjectAttributes; 00113 NTSTATUS Status; 00114 PWCHAR p1; 00115 00116 /* Check which root key to open */ 00117 if (Wow64) 00118 RootKeyLocation = &Wow64ExecOptionsKey; 00119 else 00120 RootKeyLocation = &ImageExecOptionsKey; 00121 00122 /* Get the current key */ 00123 RootKey = *RootKeyLocation; 00124 00125 /* Setup the object attributes */ 00126 InitializeObjectAttributes(&ObjectAttributes, 00127 Wow64 ? 00128 &Wow64OptionsString : &ImageExecOptionsString, 00129 OBJ_CASE_INSENSITIVE, 00130 NULL, 00131 NULL); 00132 00133 /* Open the root key */ 00134 Status = ZwOpenKey(&RootKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); 00135 if (NT_SUCCESS(Status)) 00136 { 00137 /* Write the key handle */ 00138 if (_InterlockedCompareExchange((LONG*)RootKeyLocation, (LONG)RootKey, 0) != 0) 00139 { 00140 /* Someone already opened it, use it instead */ 00141 NtClose(RootKey); 00142 RootKey = *RootKeyLocation; 00143 } 00144 00145 /* Extract the name */ 00146 SubKeyString = *SubKey; 00147 p1 = (PWCHAR)((ULONG_PTR)SubKeyString.Buffer + SubKeyString.Length); 00148 while (SubKeyString.Length) 00149 { 00150 if (p1[-1] == L'\\') break; 00151 p1--; 00152 SubKeyString.Length -= sizeof(*p1); 00153 } 00154 SubKeyString.Buffer = p1; 00155 SubKeyString.Length = SubKey->Length - SubKeyString.Length; 00156 00157 /* Setup the object attributes */ 00158 InitializeObjectAttributes(&ObjectAttributes, 00159 &SubKeyString, 00160 OBJ_CASE_INSENSITIVE, 00161 RootKey, 00162 NULL); 00163 00164 /* Open the setting key */ 00165 Status = ZwOpenKey((PHANDLE)NewKeyHandle, GENERIC_READ, &ObjectAttributes); 00166 } 00167 00168 /* Return to caller */ 00169 return Status; 00170 } 00171 00172 /* 00173 * @implemented 00174 */ 00175 NTSTATUS 00176 NTAPI 00177 LdrQueryImageFileKeyOption(IN HANDLE KeyHandle, 00178 IN PCWSTR ValueName, 00179 IN ULONG Type, 00180 OUT PVOID Buffer, 00181 IN ULONG BufferSize, 00182 OUT PULONG ReturnedLength OPTIONAL) 00183 { 00184 ULONG KeyInfo[256]; 00185 UNICODE_STRING ValueNameString, IntegerString; 00186 ULONG KeyInfoSize, ResultSize; 00187 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyInfo; 00188 BOOLEAN FreeHeap = FALSE; 00189 NTSTATUS Status; 00190 00191 /* Build a string for the value name */ 00192 Status = RtlInitUnicodeStringEx(&ValueNameString, ValueName); 00193 if (!NT_SUCCESS(Status)) return Status; 00194 00195 /* Query the value */ 00196 Status = ZwQueryValueKey(KeyHandle, 00197 &ValueNameString, 00198 KeyValuePartialInformation, 00199 KeyValueInformation, 00200 sizeof(KeyInfo), 00201 &ResultSize); 00202 if (Status == STATUS_BUFFER_OVERFLOW) 00203 { 00204 /* Our local buffer wasn't enough, allocate one */ 00205 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 00206 KeyValueInformation->DataLength; 00207 KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 00208 0, 00209 KeyInfoSize); 00210 if (KeyValueInformation != NULL) 00211 { 00212 /* Try again */ 00213 Status = ZwQueryValueKey(KeyHandle, 00214 &ValueNameString, 00215 KeyValuePartialInformation, 00216 KeyValueInformation, 00217 KeyInfoSize, 00218 &ResultSize); 00219 FreeHeap = TRUE; 00220 } 00221 else 00222 { 00223 /* Give up this time */ 00224 Status = STATUS_NO_MEMORY; 00225 } 00226 } 00227 00228 /* Check for success */ 00229 if (NT_SUCCESS(Status)) 00230 { 00231 /* Handle binary data */ 00232 if (KeyValueInformation->Type == REG_BINARY) 00233 { 00234 /* Check validity */ 00235 if ((Buffer) && (KeyValueInformation->DataLength <= BufferSize)) 00236 { 00237 /* Copy into buffer */ 00238 RtlMoveMemory(Buffer, 00239 &KeyValueInformation->Data, 00240 KeyValueInformation->DataLength); 00241 } 00242 else 00243 { 00244 Status = STATUS_BUFFER_OVERFLOW; 00245 } 00246 00247 /* Copy the result length */ 00248 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 00249 } 00250 else if (KeyValueInformation->Type == REG_DWORD) 00251 { 00252 /* Check for valid type */ 00253 if (KeyValueInformation->Type != Type) 00254 { 00255 /* Error */ 00256 Status = STATUS_OBJECT_TYPE_MISMATCH; 00257 } 00258 else 00259 { 00260 /* Check validity */ 00261 if ((Buffer) && 00262 (BufferSize == sizeof(ULONG)) && 00263 (KeyValueInformation->DataLength <= BufferSize)) 00264 { 00265 /* Copy into buffer */ 00266 RtlMoveMemory(Buffer, 00267 &KeyValueInformation->Data, 00268 KeyValueInformation->DataLength); 00269 } 00270 else 00271 { 00272 Status = STATUS_BUFFER_OVERFLOW; 00273 } 00274 00275 /* Copy the result length */ 00276 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 00277 } 00278 } 00279 else if (KeyValueInformation->Type != REG_SZ) 00280 { 00281 /* We got something weird */ 00282 Status = STATUS_OBJECT_TYPE_MISMATCH; 00283 } 00284 else 00285 { 00286 /* String, check what you requested */ 00287 if (Type == REG_DWORD) 00288 { 00289 /* Validate */ 00290 if (BufferSize != sizeof(ULONG)) 00291 { 00292 /* Invalid size */ 00293 BufferSize = 0; 00294 Status = STATUS_INFO_LENGTH_MISMATCH; 00295 } 00296 else 00297 { 00298 /* OK, we know what you want... */ 00299 IntegerString.Buffer = (PWSTR)KeyValueInformation->Data; 00300 IntegerString.Length = (USHORT)KeyValueInformation->DataLength - 00301 sizeof(WCHAR); 00302 IntegerString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 00303 Status = RtlUnicodeStringToInteger(&IntegerString, 0, (PULONG)Buffer); 00304 } 00305 } 00306 else 00307 { 00308 /* Validate */ 00309 if (KeyValueInformation->DataLength > BufferSize) 00310 { 00311 /* Invalid */ 00312 Status = STATUS_BUFFER_OVERFLOW; 00313 } 00314 else 00315 { 00316 /* Set the size */ 00317 BufferSize = KeyValueInformation->DataLength; 00318 } 00319 00320 /* Copy the string */ 00321 RtlMoveMemory(Buffer, &KeyValueInformation->Data, BufferSize); 00322 } 00323 00324 /* Copy the result length */ 00325 if (ReturnedLength) *ReturnedLength = KeyValueInformation->DataLength; 00326 } 00327 } 00328 00329 /* Check if buffer was in heap */ 00330 if (FreeHeap) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); 00331 00332 /* Return status */ 00333 return Status; 00334 } 00335 00336 /* 00337 * @implemented 00338 */ 00339 NTSTATUS 00340 NTAPI 00341 LdrQueryImageFileExecutionOptionsEx(IN PUNICODE_STRING SubKey, 00342 IN PCWSTR ValueName, 00343 IN ULONG Type, 00344 OUT PVOID Buffer, 00345 IN ULONG BufferSize, 00346 OUT PULONG ReturnedLength OPTIONAL, 00347 IN BOOLEAN Wow64) 00348 { 00349 NTSTATUS Status; 00350 HANDLE KeyHandle; 00351 00352 /* Open a handle to the key */ 00353 Status = LdrOpenImageFileOptionsKey(SubKey, Wow64, &KeyHandle); 00354 00355 /* Check for success */ 00356 if (NT_SUCCESS(Status)) 00357 { 00358 /* Query the data */ 00359 Status = LdrQueryImageFileKeyOption(KeyHandle, 00360 ValueName, 00361 Type, 00362 Buffer, 00363 BufferSize, 00364 ReturnedLength); 00365 00366 /* Close the key */ 00367 NtClose(KeyHandle); 00368 } 00369 00370 /* Return to caller */ 00371 return Status; 00372 } 00373 00374 /* 00375 * @implemented 00376 */ 00377 NTSTATUS 00378 NTAPI 00379 LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey, 00380 IN PCWSTR ValueName, 00381 IN ULONG Type, 00382 OUT PVOID Buffer, 00383 IN ULONG BufferSize, 00384 OUT PULONG ReturnedLength OPTIONAL) 00385 { 00386 /* Call the newer function */ 00387 return LdrQueryImageFileExecutionOptionsEx(SubKey, 00388 ValueName, 00389 Type, 00390 Buffer, 00391 BufferSize, 00392 ReturnedLength, 00393 FALSE); 00394 } 00395 00396 VOID 00397 NTAPI 00398 LdrpEnsureLoaderLockIsHeld() 00399 { 00400 // Ignored atm 00401 } 00402 00403 PVOID 00404 NTAPI 00405 LdrpFetchAddressOfSecurityCookie(PVOID BaseAddress, ULONG SizeOfImage) 00406 { 00407 PIMAGE_LOAD_CONFIG_DIRECTORY ConfigDir; 00408 ULONG DirSize; 00409 PVOID Cookie = NULL; 00410 00411 /* Check NT header first */ 00412 if (!RtlImageNtHeader(BaseAddress)) return NULL; 00413 00414 /* Get the pointer to the config directory */ 00415 ConfigDir = RtlImageDirectoryEntryToData(BaseAddress, 00416 TRUE, 00417 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 00418 &DirSize); 00419 00420 /* Check for sanity */ 00421 if (!ConfigDir || 00422 (DirSize != 64 && ConfigDir->Size != DirSize) || 00423 (ConfigDir->Size < 0x48)) 00424 return NULL; 00425 00426 /* Now get the cookie */ 00427 Cookie = (PVOID)ConfigDir->SecurityCookie; 00428 00429 /* Check this cookie */ 00430 if ((PCHAR)Cookie <= (PCHAR)BaseAddress || 00431 (PCHAR)Cookie >= (PCHAR)BaseAddress + SizeOfImage) 00432 { 00433 Cookie = NULL; 00434 } 00435 00436 /* Return validated security cookie */ 00437 return Cookie; 00438 } 00439 00440 PVOID 00441 NTAPI 00442 LdrpInitSecurityCookie(PLDR_DATA_TABLE_ENTRY LdrEntry) 00443 { 00444 PULONG_PTR Cookie; 00445 LARGE_INTEGER Counter; 00446 ULONG_PTR NewCookie; 00447 00448 /* Fetch address of the cookie */ 00449 Cookie = LdrpFetchAddressOfSecurityCookie(LdrEntry->DllBase, LdrEntry->SizeOfImage); 00450 00451 if (Cookie) 00452 { 00453 /* Check if it's a default one */ 00454 if ((*Cookie == DEFAULT_SECURITY_COOKIE) || 00455 (*Cookie == 0xBB40)) 00456 { 00457 /* Make up a cookie from a bunch of values which may uniquely represent 00458 current moment of time, environment, etc */ 00459 NtQueryPerformanceCounter(&Counter, NULL); 00460 00461 NewCookie = Counter.LowPart ^ Counter.HighPart; 00462 NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueProcess; 00463 NewCookie ^= (ULONG)NtCurrentTeb()->ClientId.UniqueThread; 00464 00465 /* Loop like it's done in KeQueryTickCount(). We don't want to call it directly. */ 00466 while (SharedUserData->SystemTime.High1Time != SharedUserData->SystemTime.High2Time) 00467 { 00468 YieldProcessor(); 00469 }; 00470 00471 /* Calculate the milliseconds value and xor it to the cookie */ 00472 NewCookie ^= Int64ShrlMod32(UInt32x32To64(SharedUserData->TickCountMultiplier, SharedUserData->TickCount.LowPart), 24) + 00473 (SharedUserData->TickCountMultiplier * (SharedUserData->TickCount.High1Time << 8)); 00474 00475 /* Make the cookie 16bit if necessary */ 00476 if (*Cookie == 0xBB40) NewCookie &= 0xFFFF; 00477 00478 /* If the result is 0 or the same as we got, just subtract one from the existing value 00479 and that's it */ 00480 if ((NewCookie == 0) || (NewCookie == *Cookie)) 00481 { 00482 NewCookie = *Cookie - 1; 00483 } 00484 00485 /* Set the new cookie value */ 00486 *Cookie = NewCookie; 00487 } 00488 } 00489 00490 return Cookie; 00491 } 00492 00493 VOID 00494 NTAPI 00495 LdrpInitializeThread(IN PCONTEXT Context) 00496 { 00497 PPEB Peb = NtCurrentPeb(); 00498 PLDR_DATA_TABLE_ENTRY LdrEntry; 00499 PLIST_ENTRY NextEntry, ListHead; 00500 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 00501 NTSTATUS Status; 00502 PVOID EntryPoint; 00503 00504 DPRINT("LdrpInitializeThread() called for %wZ (%lx/%lx)\n", 00505 &LdrpImageEntry->BaseDllName, 00506 NtCurrentTeb()->RealClientId.UniqueProcess, 00507 NtCurrentTeb()->RealClientId.UniqueThread); 00508 00509 /* Allocate an Activation Context Stack */ 00510 DPRINT("ActivationContextStack %p\n", NtCurrentTeb()->ActivationContextStackPointer); 00511 Status = RtlAllocateActivationContextStack((PVOID*)&NtCurrentTeb()->ActivationContextStackPointer); 00512 if (!NT_SUCCESS(Status)) 00513 { 00514 DPRINT1("Warning: Unable to allocate ActivationContextStack\n"); 00515 } 00516 00517 /* Make sure we are not shutting down */ 00518 if (LdrpShutdownInProgress) return; 00519 00520 /* Allocate TLS */ 00521 LdrpAllocateTls(); 00522 00523 /* Start at the beginning */ 00524 ListHead = &Peb->Ldr->InMemoryOrderModuleList; 00525 NextEntry = ListHead->Flink; 00526 while (NextEntry != ListHead) 00527 { 00528 /* Get the current entry */ 00529 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); 00530 00531 /* Make sure it's not ourselves */ 00532 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 00533 { 00534 /* Check if we should call */ 00535 if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS)) 00536 { 00537 /* Get the entrypoint */ 00538 EntryPoint = LdrEntry->EntryPoint; 00539 00540 /* Check if we are ready to call it */ 00541 if ((EntryPoint) && 00542 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 00543 (LdrEntry->Flags & LDRP_IMAGE_DLL)) 00544 { 00545 /* Set up the Act Ctx */ 00546 ActCtx.Size = sizeof(ActCtx); 00547 ActCtx.Format = 1; 00548 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00549 00550 /* Activate the ActCtx */ 00551 RtlActivateActivationContextUnsafeFast(&ActCtx, 00552 LdrEntry->EntryPointActivationContext); 00553 00554 /* Check if it has TLS */ 00555 if (LdrEntry->TlsIndex) 00556 { 00557 /* Make sure we're not shutting down */ 00558 if (!LdrpShutdownInProgress) 00559 { 00560 /* Call TLS */ 00561 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_ATTACH); 00562 } 00563 } 00564 00565 /* Make sure we're not shutting down */ 00566 if (!LdrpShutdownInProgress) 00567 { 00568 /* Call the Entrypoint */ 00569 DPRINT("%wZ - Calling entry point at %p for thread attaching, %lx/%lx\n", 00570 &LdrEntry->BaseDllName, LdrEntry->EntryPoint, 00571 NtCurrentTeb()->RealClientId.UniqueProcess, 00572 NtCurrentTeb()->RealClientId.UniqueThread); 00573 LdrpCallInitRoutine(LdrEntry->EntryPoint, 00574 LdrEntry->DllBase, 00575 DLL_THREAD_ATTACH, 00576 NULL); 00577 } 00578 00579 /* Deactivate the ActCtx */ 00580 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00581 } 00582 } 00583 } 00584 00585 /* Next entry */ 00586 NextEntry = NextEntry->Flink; 00587 } 00588 00589 /* Check for TLS */ 00590 if (LdrpImageHasTls && !LdrpShutdownInProgress) 00591 { 00592 /* Set up the Act Ctx */ 00593 ActCtx.Size = sizeof(ActCtx); 00594 ActCtx.Format = 1; 00595 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00596 00597 /* Activate the ActCtx */ 00598 RtlActivateActivationContextUnsafeFast(&ActCtx, 00599 LdrpImageEntry->EntryPointActivationContext); 00600 00601 /* Do TLS callbacks */ 00602 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); 00603 00604 /* Deactivate the ActCtx */ 00605 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00606 } 00607 00608 DPRINT("LdrpInitializeThread() done\n"); 00609 } 00610 00611 NTSTATUS 00612 NTAPI 00613 LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) 00614 { 00615 PLDR_DATA_TABLE_ENTRY LocalArray[16]; 00616 PLIST_ENTRY ListHead; 00617 PLIST_ENTRY NextEntry; 00618 PLDR_DATA_TABLE_ENTRY LdrEntry, *LdrRootEntry, OldInitializer; 00619 PVOID EntryPoint; 00620 ULONG Count, i; 00621 //ULONG BreakOnInit; 00622 NTSTATUS Status = STATUS_SUCCESS; 00623 PPEB Peb = NtCurrentPeb(); 00624 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 00625 ULONG BreakOnDllLoad; 00626 PTEB OldTldTeb; 00627 BOOLEAN DllStatus; 00628 00629 DPRINT("LdrpRunInitializeRoutines() called for %wZ (%lx/%lx)\n", 00630 &LdrpImageEntry->BaseDllName, 00631 NtCurrentTeb()->RealClientId.UniqueProcess, 00632 NtCurrentTeb()->RealClientId.UniqueThread); 00633 00634 /* Check the Loader Lock */ 00635 LdrpEnsureLoaderLockIsHeld(); 00636 00637 /* Get the number of entries to call */ 00638 if ((Count = LdrpClearLoadInProgress())) 00639 { 00640 /* Check if we can use our local buffer */ 00641 if (Count > 16) 00642 { 00643 /* Allocate space for all the entries */ 00644 LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(), 00645 0, 00646 Count * sizeof(*LdrRootEntry)); 00647 if (!LdrRootEntry) return STATUS_NO_MEMORY; 00648 } 00649 else 00650 { 00651 /* Use our local array */ 00652 LdrRootEntry = LocalArray; 00653 } 00654 } 00655 else 00656 { 00657 /* Don't need one */ 00658 LdrRootEntry = NULL; 00659 } 00660 00661 /* Show debug message */ 00662 if (ShowSnaps) 00663 { 00664 DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ\n", 00665 NtCurrentTeb()->RealClientId.UniqueThread, 00666 NtCurrentTeb()->RealClientId.UniqueProcess, 00667 &Peb->ProcessParameters->ImagePathName); 00668 } 00669 00670 /* Loop in order */ 00671 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 00672 NextEntry = ListHead->Flink; 00673 i = 0; 00674 while (NextEntry != ListHead) 00675 { 00676 /* Get the Data Entry */ 00677 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); 00678 00679 /* Check if we have a Root Entry */ 00680 if (LdrRootEntry) 00681 { 00682 /* Check flags */ 00683 if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED)) 00684 { 00685 /* Setup the Cookie for the DLL */ 00686 LdrpInitSecurityCookie(LdrEntry); 00687 00688 /* Check for valid entrypoint */ 00689 if (LdrEntry->EntryPoint) 00690 { 00691 /* Write in array */ 00692 ASSERT(i < Count); 00693 LdrRootEntry[i] = LdrEntry; 00694 00695 /* Display debug message */ 00696 if (ShowSnaps) 00697 { 00698 DPRINT1("[%x,%x] LDR: %wZ init routine %p\n", 00699 NtCurrentTeb()->RealClientId.UniqueThread, 00700 NtCurrentTeb()->RealClientId.UniqueProcess, 00701 &LdrEntry->FullDllName, 00702 LdrEntry->EntryPoint); 00703 } 00704 i++; 00705 } 00706 } 00707 } 00708 00709 /* Set the flag */ 00710 LdrEntry->Flags |= LDRP_ENTRY_PROCESSED; 00711 NextEntry = NextEntry->Flink; 00712 } 00713 00714 /* If we got a context, then we have to call Kernel32 for TS support */ 00715 if (Context) 00716 { 00717 /* Check if we have one */ 00718 //if (Kernel32ProcessInitPostImportfunction) 00719 //{ 00720 /* Call it */ 00721 //Kernel32ProcessInitPostImportfunction(); 00722 //} 00723 00724 /* Clear it */ 00725 //Kernel32ProcessInitPostImportfunction = NULL; 00726 //UNIMPLEMENTED; 00727 } 00728 00729 /* No root entry? return */ 00730 if (!LdrRootEntry) return STATUS_SUCCESS; 00731 00732 /* Set the TLD TEB */ 00733 OldTldTeb = LdrpTopLevelDllBeingLoadedTeb; 00734 LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb(); 00735 00736 /* Loop */ 00737 i = 0; 00738 while (i < Count) 00739 { 00740 /* Get an entry */ 00741 LdrEntry = LdrRootEntry[i]; 00742 00743 /* FIXME: Verify NX Compat */ 00744 00745 /* Move to next entry */ 00746 i++; 00747 00748 /* Get its entrypoint */ 00749 EntryPoint = LdrEntry->EntryPoint; 00750 00751 /* Are we being debugged? */ 00752 BreakOnDllLoad = 0; 00753 if (Peb->BeingDebugged || Peb->ReadImageFileExecOptions) 00754 { 00755 /* Check if we should break on load */ 00756 Status = LdrQueryImageFileExecutionOptions(&LdrEntry->BaseDllName, 00757 L"BreakOnDllLoad", 00758 REG_DWORD, 00759 &BreakOnDllLoad, 00760 sizeof(ULONG), 00761 NULL); 00762 if (!NT_SUCCESS(Status)) BreakOnDllLoad = 0; 00763 00764 /* Reset status back to STATUS_SUCCESS */ 00765 Status = STATUS_SUCCESS; 00766 } 00767 00768 /* Break if aksed */ 00769 if (BreakOnDllLoad) 00770 { 00771 /* Check if we should show a message */ 00772 if (ShowSnaps) 00773 { 00774 DPRINT1("LDR: %wZ loaded.", &LdrEntry->BaseDllName); 00775 DPRINT1(" - About to call init routine at %p\n", EntryPoint); 00776 } 00777 00778 /* Break in debugger */ 00779 DbgBreakPoint(); 00780 } 00781 00782 /* Make sure we have an entrypoint */ 00783 if (EntryPoint) 00784 { 00785 /* Save the old Dll Initializer and write the current one */ 00786 OldInitializer = LdrpCurrentDllInitializer; 00787 LdrpCurrentDllInitializer = LdrEntry; 00788 00789 /* Set up the Act Ctx */ 00790 ActCtx.Size = sizeof(ActCtx); 00791 ActCtx.Format = 1; 00792 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00793 00794 /* Activate the ActCtx */ 00795 RtlActivateActivationContextUnsafeFast(&ActCtx, 00796 LdrEntry->EntryPointActivationContext); 00797 00798 /* Check if it has TLS */ 00799 if (LdrEntry->TlsIndex && Context) 00800 { 00801 /* Call TLS */ 00802 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_ATTACH); 00803 } 00804 00805 /* Call the Entrypoint */ 00806 if (ShowSnaps) 00807 { 00808 DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n", 00809 &LdrEntry->BaseDllName, EntryPoint); 00810 } 00811 DllStatus = LdrpCallInitRoutine(EntryPoint, 00812 LdrEntry->DllBase, 00813 DLL_PROCESS_ATTACH, 00814 Context); 00815 00816 /* Deactivate the ActCtx */ 00817 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00818 00819 /* Save the Current DLL Initializer */ 00820 LdrpCurrentDllInitializer = OldInitializer; 00821 00822 /* Mark the entry as processed */ 00823 LdrEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED; 00824 00825 /* Fail if DLL init failed */ 00826 if (!DllStatus) 00827 { 00828 DPRINT1("LDR: DLL_PROCESS_ATTACH for dll \"%wZ\" (InitRoutine: %p) failed\n", 00829 &LdrEntry->BaseDllName, EntryPoint); 00830 00831 Status = STATUS_DLL_INIT_FAILED; 00832 goto Quickie; 00833 } 00834 } 00835 } 00836 00837 /* Loop in order */ 00838 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 00839 NextEntry = NextEntry->Flink; 00840 while (NextEntry != ListHead) 00841 { 00842 /* Get the Data Entrry */ 00843 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); 00844 00845 /* FIXME: Verify NX Compat */ 00846 // LdrpCheckNXCompatibility() 00847 00848 /* Next entry */ 00849 NextEntry = NextEntry->Flink; 00850 } 00851 00852 /* Check for TLS */ 00853 if (LdrpImageHasTls && Context) 00854 { 00855 /* Set up the Act Ctx */ 00856 ActCtx.Size = sizeof(ActCtx); 00857 ActCtx.Format = 1; 00858 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00859 00860 /* Activate the ActCtx */ 00861 RtlActivateActivationContextUnsafeFast(&ActCtx, 00862 LdrpImageEntry->EntryPointActivationContext); 00863 00864 /* Do TLS callbacks */ 00865 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH); 00866 00867 /* Deactivate the ActCtx */ 00868 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00869 } 00870 00871 Quickie: 00872 /* Restore old TEB */ 00873 LdrpTopLevelDllBeingLoadedTeb = OldTldTeb; 00874 00875 /* Check if the array is in the heap */ 00876 if (LdrRootEntry != LocalArray) 00877 { 00878 /* Free the array */ 00879 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry); 00880 } 00881 00882 /* Return to caller */ 00883 DPRINT("LdrpRunInitializeRoutines() done\n"); 00884 return Status; 00885 } 00886 00887 /* 00888 * @implemented 00889 */ 00890 NTSTATUS 00891 NTAPI 00892 LdrShutdownProcess(VOID) 00893 { 00894 PPEB Peb = NtCurrentPeb(); 00895 PLDR_DATA_TABLE_ENTRY LdrEntry; 00896 PLIST_ENTRY NextEntry, ListHead; 00897 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 00898 PVOID EntryPoint; 00899 00900 DPRINT("LdrShutdownProcess() called for %wZ\n", &LdrpImageEntry->BaseDllName); 00901 if (LdrpShutdownInProgress) return STATUS_SUCCESS; 00902 00903 /* Tell the Shim Engine */ 00904 //if (ShimsEnabled) 00905 //{ 00906 /* FIXME */ 00907 //} 00908 00909 /* Tell the world */ 00910 if (ShowSnaps) 00911 { 00912 DPRINT1("\n"); 00913 } 00914 00915 /* Set the shutdown variables */ 00916 LdrpShutdownThreadId = NtCurrentTeb()->RealClientId.UniqueThread; 00917 LdrpShutdownInProgress = TRUE; 00918 00919 /* Enter the Loader Lock */ 00920 RtlEnterCriticalSection(&LdrpLoaderLock); 00921 00922 /* Cleanup trace logging data (Etw) */ 00923 if (SharedUserData->TraceLogging) 00924 { 00925 /* FIXME */ 00926 DPRINT1("We don't support Etw yet.\n"); 00927 } 00928 00929 /* Start at the end */ 00930 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 00931 NextEntry = ListHead->Blink; 00932 while (NextEntry != ListHead) 00933 { 00934 /* Get the current entry */ 00935 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); 00936 NextEntry = NextEntry->Blink; 00937 00938 /* Make sure it's not ourselves */ 00939 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 00940 { 00941 /* Get the entrypoint */ 00942 EntryPoint = LdrEntry->EntryPoint; 00943 00944 /* Check if we are ready to call it */ 00945 if (EntryPoint && 00946 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 00947 LdrEntry->Flags) 00948 { 00949 /* Set up the Act Ctx */ 00950 ActCtx.Size = sizeof(ActCtx); 00951 ActCtx.Format = 1; 00952 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00953 00954 /* Activate the ActCtx */ 00955 RtlActivateActivationContextUnsafeFast(&ActCtx, 00956 LdrEntry->EntryPointActivationContext); 00957 00958 /* Check if it has TLS */ 00959 if (LdrEntry->TlsIndex) 00960 { 00961 /* Call TLS */ 00962 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH); 00963 } 00964 00965 /* Call the Entrypoint */ 00966 DPRINT("%wZ - Calling entry point at %x for thread detaching\n", 00967 &LdrEntry->BaseDllName, LdrEntry->EntryPoint); 00968 LdrpCallInitRoutine(EntryPoint, 00969 LdrEntry->DllBase, 00970 DLL_PROCESS_DETACH, 00971 (PVOID)1); 00972 00973 /* Deactivate the ActCtx */ 00974 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00975 } 00976 } 00977 } 00978 00979 /* Check for TLS */ 00980 if (LdrpImageHasTls) 00981 { 00982 /* Set up the Act Ctx */ 00983 ActCtx.Size = sizeof(ActCtx); 00984 ActCtx.Format = 1; 00985 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 00986 00987 /* Activate the ActCtx */ 00988 RtlActivateActivationContextUnsafeFast(&ActCtx, 00989 LdrpImageEntry->EntryPointActivationContext); 00990 00991 /* Do TLS callbacks */ 00992 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); 00993 00994 /* Deactivate the ActCtx */ 00995 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 00996 } 00997 00998 /* FIXME: Do Heap detection and Etw final shutdown */ 00999 01000 /* Release the lock */ 01001 RtlLeaveCriticalSection(&LdrpLoaderLock); 01002 DPRINT("LdrpShutdownProcess() done\n"); 01003 01004 return STATUS_SUCCESS; 01005 } 01006 01007 /* 01008 * @implemented 01009 */ 01010 NTSTATUS 01011 NTAPI 01012 LdrShutdownThread(VOID) 01013 { 01014 PPEB Peb = NtCurrentPeb(); 01015 PTEB Teb = NtCurrentTeb(); 01016 PLDR_DATA_TABLE_ENTRY LdrEntry; 01017 PLIST_ENTRY NextEntry, ListHead; 01018 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; 01019 PVOID EntryPoint; 01020 01021 DPRINT("LdrShutdownThread() called for %wZ\n", 01022 &LdrpImageEntry->BaseDllName); 01023 01024 /* Cleanup trace logging data (Etw) */ 01025 if (SharedUserData->TraceLogging) 01026 { 01027 /* FIXME */ 01028 DPRINT1("We don't support Etw yet.\n"); 01029 } 01030 01031 /* Get the Ldr Lock */ 01032 RtlEnterCriticalSection(&LdrpLoaderLock); 01033 01034 /* Start at the end */ 01035 ListHead = &Peb->Ldr->InInitializationOrderModuleList; 01036 NextEntry = ListHead->Blink; 01037 while (NextEntry != ListHead) 01038 { 01039 /* Get the current entry */ 01040 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); 01041 NextEntry = NextEntry->Blink; 01042 01043 /* Make sure it's not ourselves */ 01044 if (Peb->ImageBaseAddress != LdrEntry->DllBase) 01045 { 01046 /* Check if we should call */ 01047 if (!(LdrEntry->Flags & LDRP_DONT_CALL_FOR_THREADS) && 01048 (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED) && 01049 (LdrEntry->Flags & LDRP_IMAGE_DLL)) 01050 { 01051 /* Get the entrypoint */ 01052 EntryPoint = LdrEntry->EntryPoint; 01053 01054 /* Check if we are ready to call it */ 01055 if (EntryPoint) 01056 { 01057 /* Set up the Act Ctx */ 01058 ActCtx.Size = sizeof(ActCtx); 01059 ActCtx.Format = 1; 01060 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 01061 01062 /* Activate the ActCtx */ 01063 RtlActivateActivationContextUnsafeFast(&ActCtx, 01064 LdrEntry->EntryPointActivationContext); 01065 01066 /* Check if it has TLS */ 01067 if (LdrEntry->TlsIndex) 01068 { 01069 /* Make sure we're not shutting down */ 01070 if (!LdrpShutdownInProgress) 01071 { 01072 /* Call TLS */ 01073 LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH); 01074 } 01075 } 01076 01077 /* Make sure we're not shutting down */ 01078 if (!LdrpShutdownInProgress) 01079 { 01080 /* Call the Entrypoint */ 01081 DPRINT("%wZ - Calling entry point at %x for thread detaching\n", 01082 &LdrEntry->BaseDllName, LdrEntry->EntryPoint); 01083 LdrpCallInitRoutine(EntryPoint, 01084 LdrEntry->DllBase, 01085 DLL_THREAD_DETACH, 01086 NULL); 01087 } 01088 01089 /* Deactivate the ActCtx */ 01090 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 01091 } 01092 } 01093 } 01094 } 01095 01096 /* Check for TLS */ 01097 if (LdrpImageHasTls) 01098 { 01099 /* Set up the Act Ctx */ 01100 ActCtx.Size = sizeof(ActCtx); 01101 ActCtx.Format = 1; 01102 RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); 01103 01104 /* Activate the ActCtx */ 01105 RtlActivateActivationContextUnsafeFast(&ActCtx, 01106 LdrpImageEntry->EntryPointActivationContext); 01107 01108 /* Do TLS callbacks */ 01109 LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_DETACH); 01110 01111 /* Deactivate the ActCtx */ 01112 RtlDeactivateActivationContextUnsafeFast(&ActCtx); 01113 } 01114 01115 /* Free TLS */ 01116 LdrpFreeTls(); 01117 RtlLeaveCriticalSection(&LdrpLoaderLock); 01118 01119 /* Check for expansion slots */ 01120 if (Teb->TlsExpansionSlots) 01121 { 01122 /* Free expansion slots */ 01123 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->TlsExpansionSlots); 01124 } 01125 01126 /* Check for FLS Data */ 01127 if (Teb->FlsData) 01128 { 01129 /* FIXME */ 01130 DPRINT1("We don't support FLS Data yet\n"); 01131 } 01132 01133 /* Check for Fiber data */ 01134 if (Teb->HasFiberData) 01135 { 01136 /* Free Fiber data*/ 01137 RtlFreeHeap(RtlGetProcessHeap(), 0, Teb->NtTib.FiberData); 01138 Teb->NtTib.FiberData = NULL; 01139 } 01140 01141 /* Free the activation context stack */ 01142 RtlFreeThreadActivationContextStack(); 01143 DPRINT("LdrShutdownThread() done\n"); 01144 01145 return STATUS_SUCCESS; 01146 } 01147 01148 NTSTATUS 01149 NTAPI 01150 LdrpInitializeTls(VOID) 01151 { 01152 PLIST_ENTRY NextEntry, ListHead; 01153 PLDR_DATA_TABLE_ENTRY LdrEntry; 01154 PIMAGE_TLS_DIRECTORY TlsDirectory; 01155 PLDRP_TLS_DATA TlsData; 01156 ULONG Size; 01157 01158 /* Initialize the TLS List */ 01159 InitializeListHead(&LdrpTlsList); 01160 01161 /* Loop all the modules */ 01162 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 01163 NextEntry = ListHead->Flink; 01164 while (ListHead != NextEntry) 01165 { 01166 /* Get the entry */ 01167 LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 01168 NextEntry = NextEntry->Flink; 01169 01170 /* Get the TLS directory */ 01171 TlsDirectory = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 01172 TRUE, 01173 IMAGE_DIRECTORY_ENTRY_TLS, 01174 &Size); 01175 01176 /* Check if we have a directory */ 01177 if (!TlsDirectory) continue; 01178 01179 /* Check if the image has TLS */ 01180 if (!LdrpImageHasTls) LdrpImageHasTls = TRUE; 01181 01182 /* Show debug message */ 01183 if (ShowSnaps) 01184 { 01185 DPRINT1("LDR: Tls Found in %wZ at %p\n", 01186 &LdrEntry->BaseDllName, 01187 TlsDirectory); 01188 } 01189 01190 /* Allocate an entry */ 01191 TlsData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(LDRP_TLS_DATA)); 01192 if (!TlsData) return STATUS_NO_MEMORY; 01193 01194 /* Lock the DLL and mark it for TLS Usage */ 01195 LdrEntry->LoadCount = -1; 01196 LdrEntry->TlsIndex = -1; 01197 01198 /* Save the cached TLS data */ 01199 TlsData->TlsDirectory = *TlsDirectory; 01200 InsertTailList(&LdrpTlsList, &TlsData->TlsLinks); 01201 01202 /* Update the index */ 01203 *(PLONG)TlsData->TlsDirectory.AddressOfIndex = LdrpNumberOfTlsEntries; 01204 TlsData->TlsDirectory.Characteristics = LdrpNumberOfTlsEntries++; 01205 } 01206 01207 /* Done setting up TLS, allocate entries */ 01208 return LdrpAllocateTls(); 01209 } 01210 01211 NTSTATUS 01212 NTAPI 01213 LdrpAllocateTls(VOID) 01214 { 01215 PTEB Teb = NtCurrentTeb(); 01216 PLIST_ENTRY NextEntry, ListHead; 01217 PLDRP_TLS_DATA TlsData; 01218 SIZE_T TlsDataSize; 01219 PVOID *TlsVector; 01220 01221 /* Check if we have any entries */ 01222 if (!LdrpNumberOfTlsEntries) 01223 return STATUS_SUCCESS; 01224 01225 /* Allocate the vector array */ 01226 TlsVector = RtlAllocateHeap(RtlGetProcessHeap(), 01227 0, 01228 LdrpNumberOfTlsEntries * sizeof(PVOID)); 01229 if (!TlsVector) return STATUS_NO_MEMORY; 01230 Teb->ThreadLocalStoragePointer = TlsVector; 01231 01232 /* Loop the TLS Array */ 01233 ListHead = &LdrpTlsList; 01234 NextEntry = ListHead->Flink; 01235 while (NextEntry != ListHead) 01236 { 01237 /* Get the entry */ 01238 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks); 01239 NextEntry = NextEntry->Flink; 01240 01241 /* Allocate this vector */ 01242 TlsDataSize = TlsData->TlsDirectory.EndAddressOfRawData - 01243 TlsData->TlsDirectory.StartAddressOfRawData; 01244 TlsVector[TlsData->TlsDirectory.Characteristics] = RtlAllocateHeap(RtlGetProcessHeap(), 01245 0, 01246 TlsDataSize); 01247 if (!TlsVector[TlsData->TlsDirectory.Characteristics]) 01248 { 01249 /* Out of memory */ 01250 return STATUS_NO_MEMORY; 01251 } 01252 01253 /* Show debug message */ 01254 if (ShowSnaps) 01255 { 01256 DPRINT1("LDR: TlsVector %x Index %d = %x copied from %x to %x\n", 01257 TlsVector, 01258 TlsData->TlsDirectory.Characteristics, 01259 &TlsVector[TlsData->TlsDirectory.Characteristics], 01260 TlsData->TlsDirectory.StartAddressOfRawData, 01261 TlsVector[TlsData->TlsDirectory.Characteristics]); 01262 } 01263 01264 /* Copy the data */ 01265 RtlCopyMemory(TlsVector[TlsData->TlsDirectory.Characteristics], 01266 (PVOID)TlsData->TlsDirectory.StartAddressOfRawData, 01267 TlsDataSize); 01268 } 01269 01270 /* Done */ 01271 return STATUS_SUCCESS; 01272 } 01273 01274 VOID 01275 NTAPI 01276 LdrpFreeTls(VOID) 01277 { 01278 PLIST_ENTRY ListHead, NextEntry; 01279 PLDRP_TLS_DATA TlsData; 01280 PVOID *TlsVector; 01281 PTEB Teb = NtCurrentTeb(); 01282 01283 /* Get a pointer to the vector array */ 01284 TlsVector = Teb->ThreadLocalStoragePointer; 01285 if (!TlsVector) return; 01286 01287 /* Loop through it */ 01288 ListHead = &LdrpTlsList; 01289 NextEntry = ListHead->Flink; 01290 while (NextEntry != ListHead) 01291 { 01292 TlsData = CONTAINING_RECORD(NextEntry, LDRP_TLS_DATA, TlsLinks); 01293 NextEntry = NextEntry->Flink; 01294 01295 /* Free each entry */ 01296 if (TlsVector[TlsData->TlsDirectory.Characteristics]) 01297 { 01298 RtlFreeHeap(RtlGetProcessHeap(), 01299 0, 01300 TlsVector[TlsData->TlsDirectory.Characteristics]); 01301 } 01302 } 01303 01304 /* Free the array itself */ 01305 RtlFreeHeap(RtlGetProcessHeap(), 01306 0, 01307 TlsVector); 01308 } 01309 01310 NTSTATUS 01311 NTAPI 01312 LdrpInitializeApplicationVerifierPackage(PUNICODE_STRING ImagePathName, PPEB Peb, BOOLEAN SystemWide, BOOLEAN ReadAdvancedOptions) 01313 { 01314 /* If global flags request DPH, perform some additional actions */ 01315 if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) 01316 { 01317 // TODO: Read advanced DPH flags from the registry if requested 01318 if (ReadAdvancedOptions) 01319 { 01320 UNIMPLEMENTED; 01321 } 01322 01323 /* Enable page heap */ 01324 RtlpPageHeapEnabled = TRUE; 01325 } 01326 01327 return STATUS_SUCCESS; 01328 } 01329 01330 NTSTATUS 01331 NTAPI 01332 LdrpInitializeExecutionOptions(PUNICODE_STRING ImagePathName, PPEB Peb, PHANDLE OptionsKey) 01333 { 01334 NTSTATUS Status; 01335 HANDLE KeyHandle; 01336 ULONG ExecuteOptions, MinimumStackCommit = 0, GlobalFlag; 01337 01338 /* Return error if we were not provided a pointer where to save the options key handle */ 01339 if (!OptionsKey) return STATUS_INVALID_HANDLE; 01340 01341 /* Zero initialize the optinos key pointer */ 01342 *OptionsKey = NULL; 01343 01344 /* Open the options key */ 01345 Status = LdrOpenImageFileOptionsKey(ImagePathName, 0, &KeyHandle); 01346 01347 /* Save it if it was opened successfully */ 01348 if (NT_SUCCESS(Status)) 01349 *OptionsKey = KeyHandle; 01350 01351 if (KeyHandle) 01352 { 01353 /* There are image specific options, read them starting with NXCOMPAT */ 01354 Status = LdrQueryImageFileKeyOption(KeyHandle, 01355 L"ExecuteOptions", 01356 4, 01357 &ExecuteOptions, 01358 sizeof(ExecuteOptions), 01359 0); 01360 01361 if (NT_SUCCESS(Status)) 01362 { 01363 /* TODO: Set execution options for the process */ 01364 /* 01365 if (ExecuteOptions == 0) 01366 ExecuteOptions = 1; 01367 else 01368 ExecuteOptions = 2; 01369 ZwSetInformationProcess(NtCurrentProcess(), 01370 ProcessExecuteFlags, 01371 &ExecuteOptions, 01372 sizeof(ULONG));*/ 01373 01374 } 01375 01376 /* Check if this image uses large pages */ 01377 if (Peb->ImageUsesLargePages) 01378 { 01379 /* TODO: If it does, open large page key */ 01380 UNIMPLEMENTED; 01381 } 01382 01383 /* Get various option values */ 01384 LdrQueryImageFileKeyOption(KeyHandle, 01385 L"DisableHeapLookaside", 01386 REG_DWORD, 01387 &RtlpDisableHeapLookaside, 01388 sizeof(RtlpDisableHeapLookaside), 01389 NULL); 01390 01391 LdrQueryImageFileKeyOption(KeyHandle, 01392 L"ShutdownFlags", 01393 REG_DWORD, 01394 &RtlpShutdownProcessFlags, 01395 sizeof(RtlpShutdownProcessFlags), 01396 NULL); 01397 01398 LdrQueryImageFileKeyOption(KeyHandle, 01399 L"MinimumStackCommitInBytes", 01400 REG_DWORD, 01401 &MinimumStackCommit, 01402 sizeof(MinimumStackCommit), 01403 NULL); 01404 01405 /* Update PEB's minimum stack commit if it's lower */ 01406 if (Peb->MinimumStackCommit < MinimumStackCommit) 01407 Peb->MinimumStackCommit = MinimumStackCommit; 01408 01409 /* Set the global flag */ 01410 Status = LdrQueryImageFileKeyOption(KeyHandle, 01411 L"GlobalFlag", 01412 REG_DWORD, 01413 &GlobalFlag, 01414 sizeof(GlobalFlag), 01415 NULL); 01416 01417 if (NT_SUCCESS(Status)) 01418 Peb->NtGlobalFlag = GlobalFlag; 01419 else 01420 GlobalFlag = 0; 01421 01422 /* Call AVRF if necessary */ 01423 if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS)) 01424 { 01425 Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE); 01426 if (!NT_SUCCESS(Status)) 01427 { 01428 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); 01429 } 01430 } 01431 } 01432 else 01433 { 01434 /* There are no image-specific options, so perform global initialization */ 01435 if (Peb->NtGlobalFlag & (FLG_POOL_ENABLE_TAIL_CHECK | FLG_HEAP_PAGE_ALLOCS)) 01436 { 01437 /* Initialize app verifier package */ 01438 Status = LdrpInitializeApplicationVerifierPackage(ImagePathName, Peb, TRUE, FALSE); 01439 if (!NT_SUCCESS(Status)) 01440 { 01441 DPRINT1("AVRF: LdrpInitializeApplicationVerifierPackage failed with %08X\n", Status); 01442 } 01443 } 01444 } 01445 01446 return STATUS_SUCCESS; 01447 } 01448 01449 VOID 01450 NTAPI 01451 LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry) 01452 { 01453 UNIMPLEMENTED; 01454 } 01455 01456 NTSTATUS 01457 NTAPI 01458 LdrpInitializeProcess(IN PCONTEXT Context, 01459 IN PVOID SystemArgument1) 01460 { 01461 RTL_HEAP_PARAMETERS HeapParameters; 01462 ULONG ComSectionSize; 01463 //ANSI_STRING FunctionName = RTL_CONSTANT_STRING("BaseQueryModuleData"); 01464 PVOID OldShimData; 01465 OBJECT_ATTRIBUTES ObjectAttributes; 01466 //UNICODE_STRING LocalFileName, FullImageName; 01467 HANDLE SymLinkHandle; 01468 //ULONG DebugHeapOnly; 01469 UNICODE_STRING CommandLine, NtSystemRoot, ImagePathName, FullPath, ImageFileName, KnownDllString; 01470 PPEB Peb = NtCurrentPeb(); 01471 BOOLEAN IsDotNetImage = FALSE; 01472 BOOLEAN FreeCurDir = FALSE; 01473 //HANDLE CompatKey; 01474 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 01475 //LPWSTR ImagePathBuffer; 01476 ULONG ConfigSize; 01477 UNICODE_STRING CurrentDirectory; 01478 HANDLE OptionsKey; 01479 ULONG HeapFlags; 01480 PIMAGE_NT_HEADERS NtHeader; 01481 LPWSTR NtDllName = NULL; 01482 NTSTATUS Status; 01483 NLSTABLEINFO NlsTable; 01484 PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig; 01485 PTEB Teb = NtCurrentTeb(); 01486 PLIST_ENTRY ListHead; 01487 PLIST_ENTRY NextEntry; 01488 ULONG i; 01489 PWSTR ImagePath; 01490 ULONG DebugProcessHeapOnly = 0; 01491 PLDR_DATA_TABLE_ENTRY NtLdrEntry; 01492 PWCHAR Current; 01493 ULONG ExecuteOptions = 0; 01494 PVOID ViewBase; 01495 01496 /* Set a NULL SEH Filter */ 01497 RtlSetUnhandledExceptionFilter(NULL); 01498 01499 /* Get the image path */ 01500 ImagePath = Peb->ProcessParameters->ImagePathName.Buffer; 01501 01502 /* Check if it's not normalized */ 01503 if (!(Peb->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED)) 01504 { 01505 /* Normalize it*/ 01506 ImagePath = (PWSTR)((ULONG_PTR)ImagePath + (ULONG_PTR)Peb->ProcessParameters); 01507 } 01508 01509 /* Create a unicode string for the Image Path */ 01510 ImagePathName.Length = Peb->ProcessParameters->ImagePathName.Length; 01511 ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR); 01512 ImagePathName.Buffer = ImagePath; 01513 01514 /* Get the NT Headers */ 01515 NtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); 01516 01517 /* Get the execution options */ 01518 Status = LdrpInitializeExecutionOptions(&ImagePathName, Peb, &OptionsKey); 01519 01520 /* Check if this is a .NET executable */ 01521 if (RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 01522 TRUE, 01523 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, 01524 &ComSectionSize)) 01525 { 01526 /* Remeber this for later */ 01527 IsDotNetImage = TRUE; 01528 } 01529 01530 /* Save the NTDLL Base address */ 01531 NtDllBase = SystemArgument1; 01532 01533 /* If this is a Native Image */ 01534 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) 01535 { 01536 /* Then do DLL Validation */ 01537 LdrpDllValidation = TRUE; 01538 } 01539 01540 /* Save the old Shim Data */ 01541 OldShimData = Peb->pShimData; 01542 01543 /* Clear it */ 01544 Peb->pShimData = NULL; 01545 01546 /* Save the number of processors and CS Timeout */ 01547 LdrpNumberOfProcessors = Peb->NumberOfProcessors; 01548 RtlpTimeout = Peb->CriticalSectionTimeout; 01549 01550 /* Normalize the parameters */ 01551 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters); 01552 if (ProcessParameters) 01553 { 01554 /* Save the Image and Command Line Names */ 01555 ImageFileName = ProcessParameters->ImagePathName; 01556 CommandLine = ProcessParameters->CommandLine; 01557 } 01558 else 01559 { 01560 /* It failed, initialize empty strings */ 01561 RtlInitUnicodeString(&ImageFileName, NULL); 01562 RtlInitUnicodeString(&CommandLine, NULL); 01563 } 01564 01565 /* Initialize NLS data */ 01566 RtlInitNlsTables(Peb->AnsiCodePageData, 01567 Peb->OemCodePageData, 01568 Peb->UnicodeCaseTableData, 01569 &NlsTable); 01570 01571 /* Reset NLS Translations */ 01572 RtlResetRtlTranslations(&NlsTable); 01573 01574 /* Get the Image Config Directory */ 01575 LoadConfig = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, 01576 TRUE, 01577 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 01578 &ConfigSize); 01579 01580 /* Setup the Heap Parameters */ 01581 RtlZeroMemory(&HeapParameters, sizeof(RTL_HEAP_PARAMETERS)); 01582 HeapFlags = HEAP_GROWABLE; 01583 HeapParameters.Length = sizeof(RTL_HEAP_PARAMETERS); 01584 01585 /* Check if we have Configuration Data */ 01586 if ((LoadConfig) && (ConfigSize == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY))) 01587 { 01588 /* FIXME: Custom heap settings and misc. */ 01589 DPRINT1("We don't support LOAD_CONFIG data yet\n"); 01590 } 01591 01592 /* Check for custom affinity mask */ 01593 if (Peb->ImageProcessAffinityMask) 01594 { 01595 /* Set it */ 01596 Status = NtSetInformationProcess(NtCurrentProcess(), 01597 ProcessAffinityMask, 01598 &Peb->ImageProcessAffinityMask, 01599 sizeof(Peb->ImageProcessAffinityMask)); 01600 } 01601 01602 /* Check if verbose debugging (ShowSnaps) was requested */ 01603 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 01604 01605 /* Start verbose debugging messages right now if they were requested */ 01606 if (ShowSnaps) 01607 { 01608 DPRINT1("LDR: PID: 0x%x started - '%wZ'\n", 01609 Teb->ClientId.UniqueProcess, 01610 &CommandLine); 01611 } 01612 01613 /* If the timeout is too long */ 01614 if (RtlpTimeout.QuadPart < Int32x32To64(3600, -10000000)) 01615 { 01616 /* Then disable CS Timeout */ 01617 RtlpTimeoutDisable = TRUE; 01618 } 01619 01620 /* Initialize Critical Section Data */ 01621 RtlpInitDeferedCriticalSection(); 01622 01623 /* Initialize VEH Call lists */ 01624 RtlpInitializeVectoredExceptionHandling(); 01625 01626 /* Set TLS/FLS Bitmap data */ 01627 Peb->FlsBitmap = &FlsBitMap; 01628 Peb->TlsBitmap = &TlsBitMap; 01629 Peb->TlsExpansionBitmap = &TlsExpansionBitMap; 01630 01631 /* Initialize FLS Bitmap */ 01632 RtlInitializeBitMap(&FlsBitMap, 01633 Peb->FlsBitmapBits, 01634 FLS_MAXIMUM_AVAILABLE); 01635 RtlSetBit(&FlsBitMap, 0); 01636 01637 /* Initialize TLS Bitmap */ 01638 RtlInitializeBitMap(&TlsBitMap, 01639 Peb->TlsBitmapBits, 01640 TLS_MINIMUM_AVAILABLE); 01641 RtlSetBit(&TlsBitMap, 0); 01642 RtlInitializeBitMap(&TlsExpansionBitMap, 01643 Peb->TlsExpansionBitmapBits, 01644 TLS_EXPANSION_SLOTS); 01645 RtlSetBit(&TlsExpansionBitMap, 0); 01646 01647 /* Initialize the Hash Table */ 01648 for (i = 0; i < LDR_HASH_TABLE_ENTRIES; i++) 01649 { 01650 InitializeListHead(&LdrpHashTable[i]); 01651 } 01652 01653 /* Initialize the Loader Lock */ 01654 // FIXME: What's the point of initing it manually, if two lines lower 01655 // a call to RtlInitializeCriticalSection() is being made anyway? 01656 //InsertTailList(&RtlCriticalSectionList, &LdrpLoaderLock.DebugInfo->ProcessLocksList); 01657 //LdrpLoaderLock.DebugInfo->CriticalSection = &LdrpLoaderLock; 01658 RtlInitializeCriticalSection(&LdrpLoaderLock); 01659 LdrpLoaderLockInit = TRUE; 01660 01661 /* Check if User Stack Trace Database support was requested */ 01662 if (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) 01663 { 01664 DPRINT1("We don't support user stack trace databases yet\n"); 01665 } 01666 01667 /* Setup Fast PEB Lock */ 01668 RtlInitializeCriticalSection(&FastPebLock); 01669 Peb->FastPebLock = &FastPebLock; 01670 //Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; 01671 //Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; 01672 01673 /* Setup Callout Lock and Notification list */ 01674 //RtlInitializeCriticalSection(&RtlpCalloutEntryLock); 01675 InitializeListHead(&LdrpDllNotificationList); 01676 01677 /* For old executables, use 16-byte aligned heap */ 01678 if ((NtHeader->OptionalHeader.MajorSubsystemVersion <= 3) && 01679 (NtHeader->OptionalHeader.MinorSubsystemVersion < 51)) 01680 { 01681 HeapFlags |= HEAP_CREATE_ALIGN_16; 01682 } 01683 01684 /* Setup the Heap */ 01685 RtlInitializeHeapManager(); 01686 Peb->ProcessHeap = RtlCreateHeap(HeapFlags, 01687 NULL, 01688 NtHeader->OptionalHeader.SizeOfHeapReserve, 01689 NtHeader->OptionalHeader.SizeOfHeapCommit, 01690 NULL, 01691 &HeapParameters); 01692 01693 if (!Peb->ProcessHeap) 01694 { 01695 DPRINT1("Failed to create process heap\n"); 01696 return STATUS_NO_MEMORY; 01697 } 01698 01699 // FIXME: Is it located properly? 01700 /* Initialize table of callbacks for the kernel. */ 01701 Peb->KernelCallbackTable = RtlAllocateHeap(RtlGetProcessHeap(), 01702 0, 01703 sizeof(PVOID) * 01704 (USER32_CALLBACK_MAXIMUM + 1)); 01705 if (!Peb->KernelCallbackTable) 01706 { 01707 DPRINT1("Failed to create callback table\n"); 01708 ZwTerminateProcess(NtCurrentProcess(), STATUS_INSUFFICIENT_RESOURCES); 01709 } 01710 01711 /* Allocate an Activation Context Stack */ 01712 Status = RtlAllocateActivationContextStack((PVOID *)&Teb->ActivationContextStackPointer); 01713 if (!NT_SUCCESS(Status)) return Status; 01714 01715 // FIXME: Loader private heap is missing 01716 //DPRINT1("Loader private heap is missing\n"); 01717 01718 /* Check for Debug Heap */ 01719 if (OptionsKey) 01720 { 01721 /* Query the setting */ 01722 Status = LdrQueryImageFileKeyOption(OptionsKey, 01723 L"DebugProcessHeapOnly", 01724 REG_DWORD, 01725 &DebugProcessHeapOnly, 01726 sizeof(ULONG), 01727 NULL); 01728 01729 if (NT_SUCCESS(Status)) 01730 { 01731 /* Reset DPH if requested */ 01732 if (RtlpPageHeapEnabled && DebugProcessHeapOnly) 01733 { 01734 RtlpDphGlobalFlags &= ~DPH_FLAG_DLL_NOTIFY; 01735 RtlpPageHeapEnabled = FALSE; 01736 } 01737 } 01738 } 01739 01740 /* Build the NTDLL Path */ 01741 FullPath.Buffer = StringBuffer; 01742 FullPath.Length = 0; 01743 FullPath.MaximumLength = sizeof(StringBuffer); 01744 RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot); 01745 RtlAppendUnicodeStringToString(&FullPath, &NtSystemRoot); 01746 RtlAppendUnicodeToString(&FullPath, L"\\System32\\"); 01747 01748 /* Open the Known DLLs directory */ 01749 RtlInitUnicodeString(&KnownDllString, L"\\KnownDlls"); 01750 InitializeObjectAttributes(&ObjectAttributes, 01751 &KnownDllString, 01752 OBJ_CASE_INSENSITIVE, 01753 NULL, 01754 NULL); 01755 Status = ZwOpenDirectoryObject(&LdrpKnownDllObjectDirectory, 01756 DIRECTORY_QUERY | DIRECTORY_TRAVERSE, 01757 &ObjectAttributes); 01758 01759 /* Check if it exists */ 01760 if (NT_SUCCESS(Status)) 01761 { 01762 /* Open the Known DLLs Path */ 01763 RtlInitUnicodeString(&KnownDllString, L"KnownDllPath"); 01764 InitializeObjectAttributes(&ObjectAttributes, 01765 &KnownDllString, 01766 OBJ_CASE_INSENSITIVE, 01767 LdrpKnownDllObjectDirectory, 01768 NULL); 01769 Status = NtOpenSymbolicLinkObject(&SymLinkHandle, 01770 SYMBOLIC_LINK_QUERY, 01771 &ObjectAttributes); 01772 if (NT_SUCCESS(Status)) 01773 { 01774 /* Query the path */ 01775 LdrpKnownDllPath.Length = 0; 01776 LdrpKnownDllPath.MaximumLength = sizeof(LdrpKnownDllPathBuffer); 01777 LdrpKnownDllPath.Buffer = LdrpKnownDllPathBuffer; 01778 Status = ZwQuerySymbolicLinkObject(SymLinkHandle, &LdrpKnownDllPath, NULL); 01779 NtClose(SymLinkHandle); 01780 if (!NT_SUCCESS(Status)) 01781 { 01782 DPRINT1("LDR: %s - failed call to ZwQuerySymbolicLinkObject with status %x\n", "", Status); 01783 return Status; 01784 } 01785 } 01786 } 01787 01788 /* Check if we failed */ 01789 if (!NT_SUCCESS(Status)) 01790 { 01791 /* Aassume System32 */ 01792 LdrpKnownDllObjectDirectory = NULL; 01793 RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); 01794 LdrpKnownDllPath.Length -= sizeof(WCHAR); 01795 } 01796 01797 /* If we have process parameters, get the default path and current path */ 01798 if (ProcessParameters) 01799 { 01800 /* Check if we have a Dll Path */ 01801 if (ProcessParameters->DllPath.Length) 01802 { 01803 /* Get the path */ 01804 LdrpDefaultPath = *(PUNICODE_STRING)&ProcessParameters->DllPath; 01805 } 01806 else 01807 { 01808 /* We need a valid path */ 01809 DPRINT1("No valid DllPath was given!\n"); 01810 LdrpInitFailure(STATUS_INVALID_PARAMETER); 01811 } 01812 01813 /* Set the current directory */ 01814 CurrentDirectory = ProcessParameters->CurrentDirectory.DosPath; 01815 01816 /* Check if it's empty or invalid */ 01817 if ((!CurrentDirectory.Buffer) || 01818 (CurrentDirectory.Buffer[0] == UNICODE_NULL) || 01819 (!CurrentDirectory.Length)) 01820 { 01821 /* Allocate space for the buffer */ 01822 CurrentDirectory.Buffer = RtlAllocateHeap(Peb->ProcessHeap, 01823 0, 01824 3 * sizeof(WCHAR) + 01825 sizeof(UNICODE_NULL)); 01826 if (!CurrentDirectory.Buffer) 01827 { 01828 DPRINT1("LDR: LdrpInitializeProcess - unable to allocate current working directory buffer\n"); 01829 // FIXME: And what? 01830 } 01831 01832 /* Copy the drive of the system root */ 01833 RtlMoveMemory(CurrentDirectory.Buffer, 01834 SharedUserData->NtSystemRoot, 01835 3 * sizeof(WCHAR)); 01836 CurrentDirectory.Buffer[3] = UNICODE_NULL; 01837 CurrentDirectory.Length = 3 * sizeof(WCHAR); 01838 CurrentDirectory.MaximumLength = CurrentDirectory.Length + sizeof(WCHAR); 01839 01840 FreeCurDir = TRUE; 01841 DPRINT("Using dynamically allocd curdir\n"); 01842 } 01843 else 01844 { 01845 /* Use the local buffer */ 01846 DPRINT("Using local system root\n"); 01847 } 01848 } 01849 01850 /* Setup Loader Data */ 01851 Peb->Ldr = &PebLdr; 01852 InitializeListHead(&PebLdr.InLoadOrderModuleList); 01853 InitializeListHead(&PebLdr.InMemoryOrderModuleList); 01854 InitializeListHead(&PebLdr.InInitializationOrderModuleList); 01855 PebLdr.Length = sizeof(PEB_LDR_DATA); 01856 PebLdr.Initialized = TRUE; 01857 01858 /* Allocate a data entry for the Image */ 01859 LdrpImageEntry = NtLdrEntry = LdrpAllocateDataTableEntry(Peb->ImageBaseAddress); 01860 01861 /* Set it up */ 01862 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); 01863 NtLdrEntry->LoadCount = -1; 01864 NtLdrEntry->EntryPointActivationContext = 0; 01865 NtLdrEntry->FullDllName = ImageFileName; 01866 01867 if (IsDotNetImage) 01868 NtLdrEntry->Flags = LDRP_COR_IMAGE; 01869 else 01870 NtLdrEntry->Flags = 0; 01871 01872 /* Check if the name is empty */ 01873 if (!ImageFileName.Buffer[0]) 01874 { 01875 /* Use the same Base name */ 01876 NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName; 01877 } 01878 else 01879 { 01880 /* Find the last slash */ 01881 Current = ImageFileName.Buffer; 01882 while (*Current) 01883 { 01884 if (*Current++ == '\\') 01885 { 01886 /* Set this path */ 01887 NtDllName = Current; 01888 } 01889 } 01890 01891 /* Did we find anything? */ 01892 if (!NtDllName) 01893 { 01894 /* Use the same Base name */ 01895 NtLdrEntry->BaseDllName = NtLdrEntry->FullDllName; 01896 } 01897 else 01898 { 01899 /* Setup the name */ 01900 NtLdrEntry->BaseDllName.Length = (USHORT)((ULONG_PTR)ImageFileName.Buffer + ImageFileName.Length - (ULONG_PTR)NtDllName); 01901 NtLdrEntry->BaseDllName.MaximumLength = NtLdrEntry->BaseDllName.Length + sizeof(WCHAR); 01902 NtLdrEntry->BaseDllName.Buffer = (PWSTR)((ULONG_PTR)ImageFileName.Buffer + 01903 (ImageFileName.Length - NtLdrEntry->BaseDllName.Length)); 01904 } 01905 } 01906 01907 /* Processing done, insert it */ 01908 LdrpInsertMemoryTableEntry(NtLdrEntry); 01909 NtLdrEntry->Flags |= LDRP_ENTRY_PROCESSED; 01910 01911 /* Now add an entry for NTDLL */ 01912 NtLdrEntry = LdrpAllocateDataTableEntry(SystemArgument1); 01913 NtLdrEntry->Flags = LDRP_IMAGE_DLL; 01914 NtLdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(NtLdrEntry->DllBase); 01915 NtLdrEntry->LoadCount = -1; 01916 NtLdrEntry->EntryPointActivationContext = 0; 01917 01918 NtLdrEntry->FullDllName.Length = FullPath.Length; 01919 NtLdrEntry->FullDllName.MaximumLength = FullPath.MaximumLength; 01920 NtLdrEntry->FullDllName.Buffer = StringBuffer; 01921 RtlAppendUnicodeStringToString(&NtLdrEntry->FullDllName, &NtDllString); 01922 01923 NtLdrEntry->BaseDllName.Length = NtDllString.Length; 01924 NtLdrEntry->BaseDllName.MaximumLength = NtDllString.MaximumLength; 01925 NtLdrEntry->BaseDllName.Buffer = NtDllString.Buffer; 01926 01927 /* Processing done, insert it */ 01928 LdrpNtDllDataTableEntry = NtLdrEntry; 01929 LdrpInsertMemoryTableEntry(NtLdrEntry); 01930 01931 /* Let the world know */ 01932 if (ShowSnaps) 01933 { 01934 DPRINT1("LDR: NEW PROCESS\n"); 01935 DPRINT1(" Image Path: %wZ (%wZ)\n", &LdrpImageEntry->FullDllName, &LdrpImageEntry->BaseDllName); 01936 DPRINT1(" Current Directory: %wZ\n", &CurrentDirectory); 01937 DPRINT1(" Search Path: %wZ\n", &LdrpDefaultPath); 01938 } 01939 01940 /* Link the Init Order List */ 01941 InsertHeadList(&Peb->Ldr->InInitializationOrderModuleList, 01942 &LdrpNtDllDataTableEntry->InInitializationOrderModuleList); 01943 01944 /* Initialize Wine's active context implementation for the current process */ 01945 actctx_init(); 01946 01947 /* Set the current directory */ 01948 Status = RtlSetCurrentDirectory_U(&CurrentDirectory); 01949 if (!NT_SUCCESS(Status)) 01950 { 01951 /* We failed, check if we should free it */ 01952 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 01953 01954 /* Set it to the NT Root */ 01955 CurrentDirectory = NtSystemRoot; 01956 RtlSetCurrentDirectory_U(&CurrentDirectory); 01957 } 01958 else 01959 { 01960 /* We're done with it, free it */ 01961 if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory); 01962 } 01963 01964 /* Check if we should look for a .local file */ 01965 if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH) 01966 { 01967 /* FIXME */ 01968 DPRINT1("We don't support .local overrides yet\n"); 01969 } 01970 01971 /* Check if the Application Verifier was enabled */ 01972 if (Peb->NtGlobalFlag & FLG_POOL_ENABLE_TAIL_CHECK) 01973 { 01974 /* FIXME */ 01975 DPRINT1("We don't support Application Verifier yet\n"); 01976 } 01977 01978 if (IsDotNetImage) 01979 { 01980 /* FIXME */ 01981 DPRINT1("We don't support .NET applications yet\n"); 01982 } 01983 01984 /* FIXME: Load support for Terminal Services */ 01985 if (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) 01986 { 01987 /* Load kernel32 and call BasePostImportInit... */ 01988 DPRINT("Unimplemented codepath!\n"); 01989 } 01990 01991 /* Walk the IAT and load all the DLLs */ 01992 LdrpWalkImportDescriptor(LdrpDefaultPath.Buffer, LdrpImageEntry); 01993 01994 /* Check if relocation is needed */ 01995 if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase) 01996 { 01997 DPRINT1("LDR: Performing EXE relocation\n"); 01998 01999 /* Change the protection to prepare for relocation */ 02000 ViewBase = Peb->ImageBaseAddress; 02001 Status = LdrpSetProtection(ViewBase, FALSE); 02002 if (!NT_SUCCESS(Status)) return Status; 02003 02004 /* Do the relocation */ 02005 Status = LdrRelocateImageWithBias(ViewBase, 02006 0LL, 02007 NULL, 02008 STATUS_SUCCESS, 02009 STATUS_CONFLICTING_ADDRESSES, 02010 STATUS_INVALID_IMAGE_FORMAT); 02011 if (!NT_SUCCESS(Status)) 02012 { 02013 DPRINT1("LdrRelocateImageWithBias() failed\n"); 02014 return Status; 02015 } 02016 02017 /* Check if a start context was provided */ 02018 if (Context) 02019 { 02020 DPRINT1("WARNING: Relocated EXE Context"); 02021 UNIMPLEMENTED; // We should support this 02022 return STATUS_INVALID_IMAGE_FORMAT; 02023 } 02024 02025 /* Restore the protection */ 02026 Status = LdrpSetProtection(ViewBase, TRUE); 02027 if (!NT_SUCCESS(Status)) return Status; 02028 } 02029 02030 /* Lock the DLLs */ 02031 ListHead = &Peb->Ldr->InLoadOrderModuleList; 02032 NextEntry = ListHead->Flink; 02033 while (ListHead != NextEntry) 02034 { 02035 NtLdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 02036 NtLdrEntry->LoadCount = -1; 02037 NextEntry = NextEntry->Flink; 02038 } 02039 02040 /* Phase 0 is done */ 02041 LdrpLdrDatabaseIsSetup = TRUE; 02042 02043 /* Initialize TLS */ 02044 Status = LdrpInitializeTls(); 02045 if (!NT_SUCCESS(Status)) 02046 { 02047 DPRINT1("LDR: LdrpProcessInitialization failed to initialize TLS slots; status %x\n", 02048 Status); 02049 return Status; 02050 } 02051 02052 /* FIXME Mark the DLL Ranges for Stack Traces later */ 02053 02054 /* Notify the debugger now */ 02055 if (Peb->BeingDebugged) 02056 { 02057 /* Break */ 02058 DbgBreakPoint(); 02059 02060 /* Update show snaps again */ 02061 ShowSnaps = Peb->NtGlobalFlag & FLG_SHOW_LDR_SNAPS; 02062 } 02063 02064 /* Validate the Image for MP Usage */ 02065 if (LdrpNumberOfProcessors > 1) LdrpValidateImageForMp(LdrpImageEntry); 02066 02067 /* Check NX Options */ 02068 if (SharedUserData->NXSupportPolicy == 1) 02069 { 02070 ExecuteOptions = 0xD; 02071 } 02072 else if (!SharedUserData->NXSupportPolicy) 02073 { 02074 ExecuteOptions = 0xA; 02075 } 02076 02077 /* Let Mm know */ 02078 ZwSetInformationProcess(NtCurrentProcess(), 02079 ProcessExecuteFlags, 02080 &ExecuteOptions, 02081 sizeof(ULONG)); 02082 02083 /* Check if we had Shim Data */ 02084 if (OldShimData) 02085 { 02086 /* Load the Shim Engine */ 02087 Peb->AppCompatInfo = NULL; 02088 //LdrpLoadShimEngine(OldShimData, ImagePathName, OldShimData); 02089 DPRINT1("We do not support shims yet\n"); 02090 } 02091 else 02092 { 02093 /* Check for Application Compatibility Goo */ 02094 //LdrQueryApplicationCompatibilityGoo(hKey); 02095 DPRINT("Querying app compat hacks is missing!\n"); 02096 } 02097 02098 /* 02099 * FIXME: Check for special images, SecuROM, SafeDisc and other NX- 02100 * incompatible images. 02101 */ 02102 02103 /* Now call the Init Routines */ 02104 Status = LdrpRunInitializeRoutines(Context); 02105 if (!NT_SUCCESS(Status)) 02106 { 02107 DPRINT1("LDR: LdrpProcessInitialization failed running initialization routines; status %x\n", 02108 Status); 02109 return Status; 02110 } 02111 02112 /* FIXME: Unload the Shim Engine if it was loaded */ 02113 02114 /* Check if we have a user-defined Post Process Routine */ 02115 if (NT_SUCCESS(Status) && Peb->PostProcessInitRoutine) 02116 { 02117 /* Call it */ 02118 Peb->PostProcessInitRoutine(); 02119 } 02120 02121 /* Close the key if we have one opened */ 02122 if (OptionsKey) NtClose(OptionsKey); 02123 02124 /* Return status */ 02125 return Status; 02126 } 02127 02128 VOID 02129 NTAPI 02130 LdrpInitFailure(NTSTATUS Status) 02131 { 02132 ULONG Response; 02133 PPEB Peb = NtCurrentPeb(); 02134 02135 /* Print a debug message */ 02136 DPRINT1("LDR: Process initialization failure for %wZ; NTSTATUS = %08lx\n", 02137 &Peb->ProcessParameters->ImagePathName, Status); 02138 02139 /* Raise a hard error */ 02140 if (!LdrpFatalHardErrorCount) 02141 { 02142 ZwRaiseHardError(STATUS_APP_INIT_FAILURE, 1, 0, (PULONG_PTR)&Status, OptionOk, &Response); 02143 } 02144 } 02145 02146 VOID 02147 NTAPI 02148 LdrpInit(PCONTEXT Context, 02149 PVOID SystemArgument1, 02150 PVOID SystemArgument2) 02151 { 02152 LARGE_INTEGER Timeout; 02153 PTEB Teb = NtCurrentTeb(); 02154 NTSTATUS Status, LoaderStatus = STATUS_SUCCESS; 02155 MEMORY_BASIC_INFORMATION MemoryBasicInfo; 02156 PPEB Peb = NtCurrentPeb(); 02157 02158 DPRINT("LdrpInit() %lx/%lx\n", 02159 NtCurrentTeb()->RealClientId.UniqueProcess, 02160 NtCurrentTeb()->RealClientId.UniqueThread); 02161 02162 /* Check if we have a deallocation stack */ 02163 if (!Teb->DeallocationStack) 02164 { 02165 /* We don't, set one */ 02166 Status = NtQueryVirtualMemory(NtCurrentProcess(), 02167 Teb->NtTib.StackLimit, 02168 MemoryBasicInformation, 02169 &MemoryBasicInfo, 02170 sizeof(MEMORY_BASIC_INFORMATION), 02171 NULL); 02172 if (!NT_SUCCESS(Status)) 02173 { 02174 /* Fail */ 02175 LdrpInitFailure(Status); 02176 RtlRaiseStatus(Status); 02177 return; 02178 } 02179 02180 /* Set the stack */ 02181 Teb->DeallocationStack = MemoryBasicInfo.AllocationBase; 02182 } 02183 02184 /* Now check if the process is already being initialized */ 02185 while (_InterlockedCompareExchange(&LdrpProcessInitialized, 02186 1, 02187 0) == 1) 02188 { 02189 /* Set the timeout to 30 seconds */ 02190 Timeout.QuadPart = Int32x32To64(30, -10000); 02191 02192 /* Make sure the status hasn't changed */ 02193 while (!LdrpProcessInitialized) 02194 { 02195 /* Do the wait */ 02196 ZwDelayExecution(FALSE, &Timeout); 02197 } 02198 } 02199 02200 /* Check if we have already setup LDR data */ 02201 if (!Peb->Ldr) 02202 { 02203 /* Setup the Loader Lock */ 02204 Peb->LoaderLock = &LdrpLoaderLock; 02205 02206 /* Let other code know we're initializing */ 02207 LdrpInLdrInit = TRUE; 02208 02209 /* Protect with SEH */ 02210 _SEH2_TRY 02211 { 02212 /* Initialize the Process */ 02213 LoaderStatus = LdrpInitializeProcess(Context, 02214 SystemArgument1); 02215 02216 /* Check for success and if MinimumStackCommit was requested */ 02217 if (NT_SUCCESS(LoaderStatus) && Peb->MinimumStackCommit) 02218 { 02219 /* Enforce the limit */ 02220 //LdrpTouchThreadStack(Peb->MinimumStackCommit); 02221 UNIMPLEMENTED; 02222 } 02223 } 02224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02225 { 02226 /* Fail with the SEH error */ 02227 LoaderStatus = _SEH2_GetExceptionCode(); 02228 } 02229 _SEH2_END; 02230 02231 /* We're not initializing anymore */ 02232 LdrpInLdrInit = FALSE; 02233 02234 /* Check if init worked */ 02235 if (NT_SUCCESS(LoaderStatus)) 02236 { 02237 /* Set the process as Initialized */ 02238 _InterlockedIncrement(&LdrpProcessInitialized); 02239 } 02240 } 02241 else 02242 { 02243 /* Loader data is there... is this a fork() ? */ 02244 if(Peb->InheritedAddressSpace) 02245 { 02246 /* Handle the fork() */ 02247 //LoaderStatus = LdrpForkProcess(); 02248 LoaderStatus = STATUS_NOT_IMPLEMENTED; 02249 UNIMPLEMENTED; 02250 } 02251 else 02252 { 02253 /* This is a new thread initializing */ 02254 LdrpInitializeThread(Context); 02255 } 02256 } 02257 02258 /* All done, test alert the thread */ 02259 NtTestAlert(); 02260 02261 /* Return */ 02262 if (!NT_SUCCESS(LoaderStatus)) 02263 { 02264 /* Fail */ 02265 LdrpInitFailure(LoaderStatus); 02266 RtlRaiseStatus(LoaderStatus); 02267 } 02268 } 02269 02270 /* EOF */ Generated on Sun May 27 2012 04:22:34 for ReactOS by
1.7.6.1
|