Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Windows Development
  4. LoadString with cchBufferMax == 0

LoadString with cchBufferMax == 0

Scheduled Pinned Locked Moved Windows Development
questioncomjsonhelpannouncement
6 Posts 5 Posters 24 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Brian Knittel
    wrote on last edited by
    #1

    Hi, The current Microsoft version of the Win32 documentation says that LoadString, LoadStringW, and LoadStringA will pass back a pointer to a read-only copy of a string resource, if the buffer size passed to the routine is 0. In which universe does this happen? This is what I see:

    LoadString(hModule, valid\_string\_id, buf, buflen)       returns length of string
    LoadString(hModule, invalid\_string\_id, buf, buflen)     returns 0
    LoadString(hModule, valid\_string\_id, buf, 0)            returns -1
    LoadString(hModule, valid\_string\_id, NULL, buflen)      throws an exception
    LoadString(hModule, valid\_string\_id, NULL, 0)           throws an exception
    

    I always look at the source code of Wine when I encounter stuff like this, as a first approximation of what might actually be going on internally, and it would appear that Wine would do the same, except for the last case where it would return -1. I can work around this, no problem. The question is more about the mismatch between the documentation and the behavior. Does anyone have any insight on this? sample code below. You need to attach a resource file with a valid string defined

    #include #include #include "test.h" // resource include file

    #define ARRAYLENGTH(a) (sizeof(a)/sizeof((a)[0]))

    int main (int argc, char **argv)
    {
    char buf[300];
    int len;
    HMODULE hModule = GetModuleHandle(NULL);

    #define TEST_FUNC_CALL(expression) \
    buf[0] = '?'; \
    buf[1] = 0; \
    printf("%s\n", #expression); \
    __try { \
    len = expression; \
    printf("... returned %d; buf: %s\n\n", len, buf); \
    } \
    __except(EXCEPTION_EXECUTE_HANDLER) { \
    printf("... threw an exception\n\n"); \
    }

    TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  ARRAYLENGTH(buf))  ) // valid string ID
    TEST\_FUNC\_CALL(  LoadString(hModule, 9999,        buf,  ARRAYLENGTH(buf))  ) // invalid ID
    TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  0)                 ) // zero size
    TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, ARRAYLENGTH(buf))  ) // null buffer
    TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, 0)
    
    L J B D 4 Replies Last reply
    0
    • B Brian Knittel

      Hi, The current Microsoft version of the Win32 documentation says that LoadString, LoadStringW, and LoadStringA will pass back a pointer to a read-only copy of a string resource, if the buffer size passed to the routine is 0. In which universe does this happen? This is what I see:

      LoadString(hModule, valid\_string\_id, buf, buflen)       returns length of string
      LoadString(hModule, invalid\_string\_id, buf, buflen)     returns 0
      LoadString(hModule, valid\_string\_id, buf, 0)            returns -1
      LoadString(hModule, valid\_string\_id, NULL, buflen)      throws an exception
      LoadString(hModule, valid\_string\_id, NULL, 0)           throws an exception
      

      I always look at the source code of Wine when I encounter stuff like this, as a first approximation of what might actually be going on internally, and it would appear that Wine would do the same, except for the last case where it would return -1. I can work around this, no problem. The question is more about the mismatch between the documentation and the behavior. Does anyone have any insight on this? sample code below. You need to attach a resource file with a valid string defined

      #include #include #include "test.h" // resource include file

      #define ARRAYLENGTH(a) (sizeof(a)/sizeof((a)[0]))

      int main (int argc, char **argv)
      {
      char buf[300];
      int len;
      HMODULE hModule = GetModuleHandle(NULL);

      #define TEST_FUNC_CALL(expression) \
      buf[0] = '?'; \
      buf[1] = 0; \
      printf("%s\n", #expression); \
      __try { \
      len = expression; \
      printf("... returned %d; buf: %s\n\n", len, buf); \
      } \
      __except(EXCEPTION_EXECUTE_HANDLER) { \
      printf("... threw an exception\n\n"); \
      }

      TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  ARRAYLENGTH(buf))  ) // valid string ID
      TEST\_FUNC\_CALL(  LoadString(hModule, 9999,        buf,  ARRAYLENGTH(buf))  ) // invalid ID
      TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  0)                 ) // zero size
      TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, ARRAYLENGTH(buf))  ) // null buffer
      TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, 0)
      
      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      I just tried that and it does indeed return the length of the string, and set the buffer address to point to the string itself. In your call with a buffer length of zero, you need to pass the address of a pointer, where Windows will store the address of the string. Something like:

      char* pString;
      TEST_FUNC_CALL( LoadString(hModule, IDS_STRING1, (char*)&pString, 0) ) // zero size

      1 Reply Last reply
      0
      • B Brian Knittel

        Hi, The current Microsoft version of the Win32 documentation says that LoadString, LoadStringW, and LoadStringA will pass back a pointer to a read-only copy of a string resource, if the buffer size passed to the routine is 0. In which universe does this happen? This is what I see:

        LoadString(hModule, valid\_string\_id, buf, buflen)       returns length of string
        LoadString(hModule, invalid\_string\_id, buf, buflen)     returns 0
        LoadString(hModule, valid\_string\_id, buf, 0)            returns -1
        LoadString(hModule, valid\_string\_id, NULL, buflen)      throws an exception
        LoadString(hModule, valid\_string\_id, NULL, 0)           throws an exception
        

        I always look at the source code of Wine when I encounter stuff like this, as a first approximation of what might actually be going on internally, and it would appear that Wine would do the same, except for the last case where it would return -1. I can work around this, no problem. The question is more about the mismatch between the documentation and the behavior. Does anyone have any insight on this? sample code below. You need to attach a resource file with a valid string defined

        #include #include #include "test.h" // resource include file

        #define ARRAYLENGTH(a) (sizeof(a)/sizeof((a)[0]))

        int main (int argc, char **argv)
        {
        char buf[300];
        int len;
        HMODULE hModule = GetModuleHandle(NULL);

        #define TEST_FUNC_CALL(expression) \
        buf[0] = '?'; \
        buf[1] = 0; \
        printf("%s\n", #expression); \
        __try { \
        len = expression; \
        printf("... returned %d; buf: %s\n\n", len, buf); \
        } \
        __except(EXCEPTION_EXECUTE_HANDLER) { \
        printf("... threw an exception\n\n"); \
        }

        TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  ARRAYLENGTH(buf))  ) // valid string ID
        TEST\_FUNC\_CALL(  LoadString(hModule, 9999,        buf,  ARRAYLENGTH(buf))  ) // invalid ID
        TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  0)                 ) // zero size
        TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, ARRAYLENGTH(buf))  ) // null buffer
        TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, 0)
        
        J Offline
        J Offline
        jschell
        wrote on last edited by
        #3

        So the documentation is wrong. For example it doesn't document '-1' at all. You might get some more information by doing what it says.... "To get extended error information, call GetLastError."

        1 Reply Last reply
        0
        • B Brian Knittel

          Hi, The current Microsoft version of the Win32 documentation says that LoadString, LoadStringW, and LoadStringA will pass back a pointer to a read-only copy of a string resource, if the buffer size passed to the routine is 0. In which universe does this happen? This is what I see:

          LoadString(hModule, valid\_string\_id, buf, buflen)       returns length of string
          LoadString(hModule, invalid\_string\_id, buf, buflen)     returns 0
          LoadString(hModule, valid\_string\_id, buf, 0)            returns -1
          LoadString(hModule, valid\_string\_id, NULL, buflen)      throws an exception
          LoadString(hModule, valid\_string\_id, NULL, 0)           throws an exception
          

          I always look at the source code of Wine when I encounter stuff like this, as a first approximation of what might actually be going on internally, and it would appear that Wine would do the same, except for the last case where it would return -1. I can work around this, no problem. The question is more about the mismatch between the documentation and the behavior. Does anyone have any insight on this? sample code below. You need to attach a resource file with a valid string defined

          #include #include #include "test.h" // resource include file

          #define ARRAYLENGTH(a) (sizeof(a)/sizeof((a)[0]))

          int main (int argc, char **argv)
          {
          char buf[300];
          int len;
          HMODULE hModule = GetModuleHandle(NULL);

          #define TEST_FUNC_CALL(expression) \
          buf[0] = '?'; \
          buf[1] = 0; \
          printf("%s\n", #expression); \
          __try { \
          len = expression; \
          printf("... returned %d; buf: %s\n\n", len, buf); \
          } \
          __except(EXCEPTION_EXECUTE_HANDLER) { \
          printf("... threw an exception\n\n"); \
          }

          TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  ARRAYLENGTH(buf))  ) // valid string ID
          TEST\_FUNC\_CALL(  LoadString(hModule, 9999,        buf,  ARRAYLENGTH(buf))  ) // invalid ID
          TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  0)                 ) // zero size
          TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, ARRAYLENGTH(buf))  ) // null buffer
          TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, 0)
          
          B Offline
          B Offline
          Brian Knittel
          wrote on last edited by
          #4

          Solved: receiving a pointer to the string when cchBufferMax == 0 happens in the Unicode universe (LoadStringW), not the MBCS universe (LoadStringA). Duh! Of course. String resource data is Unicode. If I'd looked at Wine's LoadStringW instead of LoadStringA I'd have seen that yesterday. (And in case anyone stumbles on this discussion for info about this feature, note that the string in the resource is likely not null terminated.). I'll post feedback for the documentation. It was an error that the same copy got pasted into both LoadString descriptions. LoadStringA needs to have the part about cchBufferMax == 0 deleted. The -1 return value should also be documented. (Also, LoadStringW does not throw exceptions with a NULL buffer pointer, it returns 0, but that doesn't need to be documented.)

          R 1 Reply Last reply
          0
          • B Brian Knittel

            Hi, The current Microsoft version of the Win32 documentation says that LoadString, LoadStringW, and LoadStringA will pass back a pointer to a read-only copy of a string resource, if the buffer size passed to the routine is 0. In which universe does this happen? This is what I see:

            LoadString(hModule, valid\_string\_id, buf, buflen)       returns length of string
            LoadString(hModule, invalid\_string\_id, buf, buflen)     returns 0
            LoadString(hModule, valid\_string\_id, buf, 0)            returns -1
            LoadString(hModule, valid\_string\_id, NULL, buflen)      throws an exception
            LoadString(hModule, valid\_string\_id, NULL, 0)           throws an exception
            

            I always look at the source code of Wine when I encounter stuff like this, as a first approximation of what might actually be going on internally, and it would appear that Wine would do the same, except for the last case where it would return -1. I can work around this, no problem. The question is more about the mismatch between the documentation and the behavior. Does anyone have any insight on this? sample code below. You need to attach a resource file with a valid string defined

            #include #include #include "test.h" // resource include file

            #define ARRAYLENGTH(a) (sizeof(a)/sizeof((a)[0]))

            int main (int argc, char **argv)
            {
            char buf[300];
            int len;
            HMODULE hModule = GetModuleHandle(NULL);

            #define TEST_FUNC_CALL(expression) \
            buf[0] = '?'; \
            buf[1] = 0; \
            printf("%s\n", #expression); \
            __try { \
            len = expression; \
            printf("... returned %d; buf: %s\n\n", len, buf); \
            } \
            __except(EXCEPTION_EXECUTE_HANDLER) { \
            printf("... threw an exception\n\n"); \
            }

            TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  ARRAYLENGTH(buf))  ) // valid string ID
            TEST\_FUNC\_CALL(  LoadString(hModule, 9999,        buf,  ARRAYLENGTH(buf))  ) // invalid ID
            TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, buf,  0)                 ) // zero size
            TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, ARRAYLENGTH(buf))  ) // null buffer
            TEST\_FUNC\_CALL(  LoadString(hModule, IDS\_STRING1, NULL, 0)
            
            D Offline
            D Offline
            Davidd Warrnerr
            wrote on last edited by
            #5

            Hello I need some more detailed coding. Regards David Warner Purva Aerocity

            1 Reply Last reply
            0
            • B Brian Knittel

              Solved: receiving a pointer to the string when cchBufferMax == 0 happens in the Unicode universe (LoadStringW), not the MBCS universe (LoadStringA). Duh! Of course. String resource data is Unicode. If I'd looked at Wine's LoadStringW instead of LoadStringA I'd have seen that yesterday. (And in case anyone stumbles on this discussion for info about this feature, note that the string in the resource is likely not null terminated.). I'll post feedback for the documentation. It was an error that the same copy got pasted into both LoadString descriptions. LoadStringA needs to have the part about cchBufferMax == 0 deleted. The -1 return value should also be documented. (Also, LoadStringW does not throw exceptions with a NULL buffer pointer, it returns 0, but that doesn't need to be documented.)

              R Offline
              R Offline
              RedDk
              wrote on last edited by
              #6

              Brian Knittel wrote:

              stumbles

              In the event that you are a spammer (not BK of course) or are experienced in successfully loading hidden links and payloads (again, not BK), please ignore this action verb reference and move :cool:n.

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups