Uploaded image for project: 'Core ReactOS'
  1. Core ReactOS
  2. CORE-19508

[RTL / LIBSUPP] Mechwarrior 3 crash

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • Major
    • None
    • None

    Description

      ReactOS 0.4.15-x86-dev (Build 20240406-0.4.15-dev-7860-gb6987d1) (Commit b6987d14632a74aafa71e8289865858c6e714de6)

      It crashes with a nullpointer exception because it tries to use FormatMessageA message to search a string on Mech3Msg and format a message, it does not find it and then try to strcpy the null pointer (that the process is always assuming to find it)

       

      FormatMessageA (FORMAT_MESSAGE_FROM_HANDLE,0x02130000, 4032, *0*, 0x0072d478, 512, 0x0012f9f4)
      

      (0 is the key and it's the dwLanguage )

      The api documentation says: [FormatMessageA function (winbase.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessagea)

      dwLanguageId

      `[in] dwLanguageId`

      The [language identifier](https://learn.microsoft.com/en-us/windows/desktop/Intl/language-identifiers) for the requested message. This parameter is ignored if dwFlags includes {}FORMAT_MESSAGE_FROM_STRING{}.

      If you pass a specific {}LANGID{} in this parameter, {}FormatMessage{} will return a message for that {}LANGID{} only. If the function cannot find a message for that {}LANGID{}, it sets Last-Error to *ERROR_RESOURCE_LANG_NOT_FOUND. If you pass in zero, **FormatMessage* looks for a message for {}LANGIDs{} in the following order:

      1.  Language neutral
      2.  Thread {}LANGID{}, based on the thread's locale value
      3.  User default {}LANGID{}, based on the user's default locale value
      4.  System default {}LANGID{}, based on the system default locale value
      5.  US English

      If {}FormatMessage{} does not locate a message for any of the preceding {}LANGIDs{}, it returns any language message string that is present. If that fails, it returns *ERROR_RESOURCE_LANG_NOT_FOUND*.

       

      Logic for this is present on Wine's implementation: [[dlls/ntdll/resource.c · master · wine / wine · GitLab (winehq.org)](https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/resource.c)(https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/resource.c#L199])

       

      static NTSTATUS find_entry( HMODULE hmod, const LDR_RESOURCE_INFO *info,
                                  ULONG level, const void **ret, int want_dir )
      {
        ...
      /* 1. specified language */
          pos = push_language( list, pos, info->Language );
          /* 2. specified language with neutral sublanguage */
          pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
          /* 3. neutral language with neutral sublanguage */
          pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
          /* if no explicitly specified language, try some defaults */
          if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
          {
              LANGID user_lang, user_neutral_lang, system_lang;
              get_resource_lcids( &user_lang, &user_neutral_lang, &system_lang );
              /* user defaults, unless SYS_DEFAULT sublanguage specified  */
              if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
             
      {             /* 4. current thread locale language */             pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );             /* 5. user locale language */             pos = push_language( list, pos, user_lang );             /* 6. user locale language with neutral sublanguage  */             pos = push_language( list, pos, user_neutral_lang );         }
              /* 7. system locale language */
              pos = push_language( list, pos, system_lang );
              /* 8. system locale language with neutral sublanguage */
              pos = push_language( list, pos, PRIMARYLANGID( system_lang ));
              /* 9. English */
              pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
          }
          resdirptr = *ret;
          for (i = 0; i < pos; i++)
              if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
          /* if no explicitly specified language, return the first entry */
          if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
         
      {         if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;     }
          return STATUS_RESOURCE_LANG_NOT_FOUND;
       
      

      Logic is present but unused:  on the ntdll's libsupp element introduced by learn_more's commit [RTL] Introduce RtlpImageNtHeader, · reactos/reactos@177ae91 · GitHub but since the RtlFindMessage uses LdrFindResource_U (ReactOS: sdk/lib/rtl/message.c File Reference) is using the one of sdk\lib\rtl\res.c that misses the langId = 0 workflow:  reactos/sdk/lib/rtl/res.c at master · reactos/reactos · GitHub  - resulting in a MESSAGE_NOT_FOUND message.

      Attachments

        Activity

          People

            Unassigned Unassigned
            simonelombardo simonelombardo
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: