Why isn't a string with ID 65535 not valid in MFC?

RDH 41 Reputation points
2021-09-16T18:34:42.427+00:00

We have a resource file that has a string in the string table with a value of 65535. The Windows API ::LoadString will load the string with no problem. However, StringTraits::FindStringResourceInstance( 65535 ) fails to find the instance handle. The string is built into our string table with no error. We set the res handle in the MFC module state data. I see FindStringResourceInstance fails to find the handle to the resource in our resource module.

I have failed to find some documentation that says no string in the string table should have an ID of 65535. Is this some limit imposed by MFC's approach to loading string resources?

Well I'll post this as soon as I can figure out what "Tags" to add. So far nothing I have guessed at looks appropriate. MFC would be my choice. Especially since I was on that forum when I went to post my question. Visual Studio? Not there either. LoadString. Nope. Atl. Nope ... I give. dotnet-visual-basic it is. Sorry but that Tags guessing is not a great UX.

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,662 questions
{count} votes

Accepted answer
  1. Michael Taylor 51,341 Reputation points
    2021-09-16T19:11:46.203+00:00

    There is nothing special about that value other than it could conflict with MFC strings that are that high. However a quick test indicates that this isn't an issue.

    CString str;
    BOOL success = str.LoadString(65535);  //Works
    

    The assumption here is the string resource is in the correct binary such that the handle being used for the lookup is correct.

    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. RLWA32 43,051 Reputation points
    2021-09-16T19:53:20.163+00:00

    Following is a small test that successfully loaded a string from a resource dll into an MFC dialog-based application -

        HINSTANCE hOld = AfxGetResourceHandle();  // Save resource handle of exe
        HMODULE hResource = LoadLibrary(_T("ResLib.dll"));
        AfxSetResourceHandle(hResource);  // Set resource handle to dll for string resource load
        CString str;
        BOOL bLoaded = str.LoadString(65535);
        AfxSetResourceHandle(hOld);  // Restore handle
        if (bLoaded)
            TRACE(_T("String is %s\n"), str);
        else
            TRACE(_T("CString::LoadString failed\n"));
    
    0 comments No comments

  2. RDH 41 Reputation points
    2021-09-16T22:34:06.547+00:00

    Thanks for the reply.

    My module is set correctly. Your code works because you hard-coded 65535 which is converted by the compiler to 0x0000ffff. My code is actually getting a menu entry from CMenu and it returns a UNIT. The menu item is a submenu and so its menu ID is actually 0xffffffff (not 0x0000ffff). That is making the difference. I now see that the code that calls FindResourceW in ATL::AtlGetStringResourceImage is doing this to the ID:

    MAKEINTRESOURCEW(((id>>4)+1) & static_cast<WORD>(~0)) )

    If I call with the hard coded 65536, the result is 0x1000 and that is a valid resource handle. Hence, MFC continues on an can load the string from the handle.

    But the system is running on UINTS (menu IDs that are essentially command IDs). But this is for a submenu entry in my case. So, what is actually getting passed in is the ID of a submenu - 0xffffffff.

    0xffffffff >> 4 = 0x0fffffff

    0x0fffffff+1 = 0x10000000
    0x10000000 & 0x0FFFF = 0x00000000

    So, FindResourceW is passed 0x0 and fails to find the string.

    Quite revealing as I originally examined the string table for the module handle in question and found in the table (resource editor) the value is 65535. But by the time it actually works its way to the CString code, it is not 0x0000ffff but rather 0xffffffff. I am actually using the Windows LoadString API and was looking at CStringT and found it failed to find a string in this case.

    Basically we are getting menu entries from a menu resource and looking up the command string using the menu entry. Looks like we should be masking off the upper 16 bits. This isn't a menu we are eventually showing. It's a menu converted to a set of controls for all that fancy ribbon stuff apps now use in place of the old menus and toolbars. All the code is using UINTS. If I don't use MFC and instead use the OS LoadString API and pass in 0xffffffff, the string is returned. Apparently LoadString is more forgiving that the code CString is using.

    0 comments No comments

  3. RDH 41 Reputation points
    2021-09-16T22:38:15.057+00:00

    Sorry guys. I can only mark one as the answer. So I chose the first one. Both showed me it can be done and led me to why in my case it wasn't working in our system.

    0 comments No comments