Win32 API FindResource

-4

(EDIT#2) // RC file:

    STRINGTABLE
    BEGIN
    ...
    MY_ID "text text text"
    ...
    END

Source:

    hrsrc = FindResource(NULL, MAKEINTRESOURCE(MY_ID), RT_STRING);
    // hrsrc is NULL on output`

I read this FindResource() function fails although resource exists and few other posts as well, but none gave me an answer.

My issue was FindResource of RT_STRING type (win32 api). Struggling with it 2nd day now. No matter what, it simply returns NULL for provided string resource IDs and following it, GetLastError returns 1814. Fun part is LoadStringW has nothing against and loads the strings. Head aching...

My test case. Set string resource id to 1 and make sure it's 1st in the stringtable (or #define MY_ID 1).

// RC file:

    STRINGTABLE
    BEGIN
    1 "text text text"
    ...
    END

Next call:

    hrsrc = FindResource(NULL, MAKEINTRESOURCE(1), RT_STRING);
    // hrsrc is 0xdeadbeef on output

Before editing I stated following strings should be 2..N which is wrong and will further lead FindResource to fail again.

I found (or actually overlooked) remarks section of STRINGTABLE resource man page. It states:

RC allocates 16 strings per section and uses the identifier value to determine which section is to contain the string. Strings whose identifiers differ only in the bottom 4 bits are placed in the same section.

So it appears to be "slotted".

MY_ID  1  =  STRINGTABLE entry 1 // FindResource(NULL, MAKEINTRESOURCE(1), RT_STRING);
MY_ID 16  =  STRINGTABLE entry 16 // FindResource(NULL, MAKEINTRESOURCE(2), RT_STRING);
MY_ID 32  =  STRINGTABLE entry 32 // FindResource(NULL, MAKEINTRESOURCE(3), RT_STRING);

But how to reach the string with id 2?

(EDIT#3) Not a new land discovery but here's what I came up with, and what actually sums what Inspectable stated in own post.

const wchar_t * GetStringResource(int id){
  union {
    int slot;
    int pick;
  };
  union {
    HRSRC h;
    wchar_t* entry;
  };

  slot = 1 + id / 16; // +1; FindResource(NULL, MAKEINTRESOURCE(0)... fails
  h = FindResource(NULL, MAKEINTRESOURCE(slot), RT_STRING);
  entry = (wchar_t*) LoadResource(NULL, h);

  pick = id % 16;
  for(int i=0 ; i < pick ; i++){
    if(*entry==0) entry += 2; // 2 words, 1st size, 2nd empty string entry.
    else entry += 1+ (unsigned short) *entry; // 1 word of length + length itself
  }

  return entry; // add +1 to skip the size...
}

Another issue is the string's are not NULL terminated. There's no direct use of them. Yes, LoadStringW is the answer. But...

Here is a rhetorical question. How is it any better than

std::map<unsigned short, const char *> myStringMap;

which already is cross-platform?

winapi
asked on Stack Overflow Mar 12, 2020 by pawel • edited Mar 16, 2020 by pawel

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0