update for HEAD-2003091401
[reactos.git] / lib / ntdll / ldr / startup.c
index 845a334..2ec2072 100644 (file)
@@ -24,6 +24,8 @@
 
 
 VOID RtlInitializeHeapManager (VOID);
+VOID LdrpInitLoader(VOID);
+
 
 /* GLOBALS *******************************************************************/
 
@@ -36,11 +38,155 @@ static RTL_BITMAP TlsBitMap;
 
 ULONG NtGlobalFlag = 0;
 
+#define VALUE_BUFFER_SIZE 256
+
+BOOL FASTCALL
+ReadCompatibilitySetting(HANDLE Key, LPWSTR Value, PKEY_VALUE_PARTIAL_INFORMATION ValueInfo, DWORD *Buffer)
+{
+       UNICODE_STRING ValueName;
+       NTSTATUS Status;
+       ULONG Length;
+
+       RtlInitUnicodeString(&ValueName, Value);
+       Status = NtQueryValueKey(Key,
+               &ValueName,
+               KeyValuePartialInformation,
+               ValueInfo,
+               VALUE_BUFFER_SIZE,
+               &Length);
+
+       if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_DWORD))
+       {
+               RtlFreeUnicodeString(&ValueName);
+               return FALSE;
+       }
+       RtlCopyMemory(Buffer, &ValueInfo->Data[0], sizeof(DWORD));
+       RtlFreeUnicodeString(&ValueName);
+       return TRUE;
+}
+
+BOOL FASTCALL
+LoadCompatibilitySettings(PPEB Peb)
+{
+       NTSTATUS Status;
+       HANDLE UserKey = NULL;
+       HANDLE KeyHandle;
+       HANDLE SubKeyHandle;
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       UNICODE_STRING KeyName;
+       UNICODE_STRING ValueName;
+       UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
+       PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+       ULONG Length;
+       DWORD MajorVersion, MinorVersion, BuildNumber, PlatformId,
+                 SPMajorVersion, SPMinorVersion= 0;
+
+       if(Peb->ProcessParameters &&
+               (Peb->ProcessParameters->ImagePathName.Length > 0))
+       {
+               Status = RtlOpenCurrentUser(KEY_READ,
+                                   &UserKey);
+               if (!NT_SUCCESS(Status))
+               {
+                       return FALSE;
+               }
+
+               RtlInitUnicodeStringFromLiteral(&KeyName, 
+                       L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
+
+               InitializeObjectAttributes(&ObjectAttributes,
+                       &KeyName,
+                       OBJ_CASE_INSENSITIVE,
+                       UserKey,
+                       NULL);
+
+               Status = NtOpenKey(&KeyHandle,
+                                       KEY_QUERY_VALUE,
+                                       &ObjectAttributes);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       if (UserKey) NtClose(UserKey);
+                       return FALSE;
+               }
+
+               /* query version name for application */
+               ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
+               Status = NtQueryValueKey(KeyHandle,
+                       &Peb->ProcessParameters->ImagePathName,
+                       KeyValuePartialInformation,
+                       ValueBuffer,
+                       VALUE_BUFFER_SIZE,
+                       &Length);
+
+               if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_SZ))
+               {
+                       NtClose(KeyHandle);
+                       if (UserKey) NtClose(UserKey);
+                       return FALSE;
+               }
+
+               ValueName.Length = ValueInfo->DataLength;
+               ValueName.MaximumLength = ValueInfo->DataLength;
+               ValueName.Buffer = (PWSTR)ValueInfo->Data;
+
+               /* load version info */
+               InitializeObjectAttributes(&ObjectAttributes,
+                       &ValueName,
+                       OBJ_CASE_INSENSITIVE,
+                       KeyHandle,
+                       NULL);
+
+               Status = NtOpenKey(&SubKeyHandle,
+                                       KEY_QUERY_VALUE,
+                                       &ObjectAttributes);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       NtClose(KeyHandle);
+                       if (UserKey) NtClose(UserKey);
+                       return FALSE;
+               }
+
+               DPRINT("Loading version information for: %wZ\n", &ValueName);
+
+               /* read settings from registry */
+               if(!ReadCompatibilitySetting(SubKeyHandle, L"MajorVersion", ValueInfo, &MajorVersion))
+                       goto finish;
+               if(!ReadCompatibilitySetting(SubKeyHandle, L"MinorVersion", ValueInfo, &MinorVersion))
+                       goto finish;
+               if(!ReadCompatibilitySetting(SubKeyHandle, L"BuildNumber", ValueInfo, &BuildNumber))
+                       goto finish;
+               if(!ReadCompatibilitySetting(SubKeyHandle, L"PlatformId", ValueInfo, &PlatformId))
+                       goto finish;
+
+               /* now assign the settings */
+               Peb->OSMajorVersion = (ULONG)MajorVersion;
+               Peb->OSMinorVersion = (ULONG)MinorVersion;
+               Peb->OSBuildNumber = (USHORT)BuildNumber;
+               Peb->OSPlatformId = (ULONG)PlatformId;
+
+               /* optional service pack version numbers */
+               if(ReadCompatibilitySetting(SubKeyHandle, L"SPMajorVersion", ValueInfo, &SPMajorVersion))
+                       Peb->SPMajorVersion = (UCHAR)SPMajorVersion;
+               if(ReadCompatibilitySetting(SubKeyHandle, L"SPMinorVersion", ValueInfo, &SPMinorVersion))
+                       Peb->SPMinorVersion = (UCHAR)SPMinorVersion;
+
+finish:
+               /* we're finished */
+               NtClose(SubKeyHandle);
+               NtClose(KeyHandle);
+               if (UserKey) NtClose(UserKey);
+               return TRUE;
+       }
+       return FALSE;
+}
+
 
 /* FUNCTIONS *****************************************************************/
 
 VOID STDCALL
-LdrInitializeThunk (ULONG Unknown1,
+__true_LdrInitializeThunk (ULONG Unknown1,
                     ULONG Unknown2,
                     ULONG Unknown3,
                     ULONG Unknown4)
@@ -48,11 +194,11 @@ LdrInitializeThunk (ULONG Unknown1,
    PIMAGE_NT_HEADERS NTHeaders;
    PEPFUNC EntryPoint;
    PIMAGE_DOS_HEADER PEDosHeader;
-   NTSTATUS Status;
    PVOID ImageBase;
    PPEB Peb;
    PLDR_MODULE NtModule;  // ntdll
    PLDR_MODULE ExeModule; // executable
+   NLSTABLEINFO NlsTable;
    WCHAR FullNtDllPath[MAX_PATH];
 
    DPRINT("LdrInitializeThunk()\n");
@@ -108,14 +254,12 @@ LdrInitializeThunk (ULONG Unknown1,
    /* normalize process parameters */
    RtlNormalizeProcessParams (Peb->ProcessParameters);
 
-#if 0
-   /* initialize NLS data */
+   /* Initialize NLS data */
    RtlInitNlsTables (Peb->AnsiCodePageData,
                      Peb->OemCodePageData,
                      Peb->UnicodeCaseTableData,
-                     &TranslationTable);
-   RtlResetRtlTranslations (&TranslationTable);
-#endif
+                     &NlsTable);
+   RtlResetRtlTranslations (&NlsTable);
 
    NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew);
 
@@ -150,7 +294,7 @@ LdrInitializeThunk (ULONG Unknown1,
    Peb->KernelCallbackTable = 
      RtlAllocateHeap(RtlGetProcessHeap(),
                      0,
-                     sizeof(PVOID) * USER32_CALLBACK_MAXIMUM);
+                     sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1));
 
    /* initalize loader lock */
    RtlInitializeCriticalSection (&LoaderLock);
@@ -172,6 +316,9 @@ LdrInitializeThunk (ULONG Unknown1,
    InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList);
    InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList);
 
+   /* Load compatibility settings */
+   LoadCompatibilitySettings(Peb);
+
    /* build full ntdll path */
    wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot);
    wcscat (FullNtDllPath, L"\\system32\\ntdll.dll");
@@ -254,6 +401,8 @@ LdrInitializeThunk (ULONG Unknown1,
    InsertHeadList(&Peb->Ldr->InLoadOrderModuleList,
                   &ExeModule->InLoadOrderModuleList);
 
+  LdrpInitLoader();
+
 #ifdef DBG
 
   LdrpLoadUserModuleSymbols(ExeModule);