ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ldrinit.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.