LoadString



  • In win32 API there is a function to load a string from the resources. It takes as argument a handle to the module (dll or exe file), a pointer to a buffer, the size of the buffer and the ID number of the string. So far so good. The return value however is described as such:
    "If the function succeeds, the return value is the number of TCHARs copied into the buffer, not including the terminating NULL character, or zero if the string resource does not exist."

    Now you might imagine that they have an excuse, such as for some technical reason the return type of this function must be unsigned? Nope, it's just an int.



  • what's wrong with that?   That way you can go like this.

     

    if (function(args,  ...) { /* do stuff */ }

     



  • It's also useful in case you want the resource string to have a negative number of characters (e.g.: to remove data [i]from[/i] your program instead of adding data into it).



  • The real WTF could be that you are still using functions like LoadString from the win32 API...

    But I think the real WTF might be more that you think you have some kind of superior knowledge to the people who wrote the win32 API... Pretty sure they knew what they were doing!

    When you are using such a large and powerful API, you cannot expect for every function to be personalized to your needs/wants/styles... that is the basis of API programming... One size fits all.

     



  • I'm just wondering why you needed a string resource with more then 2147483647 character?

    2nd wondering: Why not return -1 on "not found", because you cannot see the difference between not found and empty string? Or can empty resources not exists in the first place? (embedded linux developers don't know such things, ok?)



  • @boxed said:

    In win32 API there is a function to load a string from the resources. It takes as argument a handle to the module (dll or exe file), a pointer to a buffer, the size of the buffer and the ID number of the string. So far so good. The return value however is described as such: "If the function succeeds, the return value is the number of TCHARs copied into the buffer, not including the terminating NULL character, or zero if the string resource does not exist." Now you might imagine that they have an excuse, such as for some technical reason the return type of this function must be unsigned? Nope, it's just an int.

    Actually the return type should be size_t, which can hold the size of any array.  The size of an int is not specified by the C language.  Usually the size of int is 16 bits for 16-bit target architectures like Intel 8086, 32 bits for 32-bit targets and 64 bits for 64-bit targets, so usually unsigned int and size_t are the same, but not always.

    Win32 is tied down to a specific architecture, so it can get away with assumptions.  (Remember when the architecture changed and we had to write all those "message cracker" macros?  Now that was fun.  Even more fun was writing source code that could be compiled for Win16, Win32 and OS/2.)

    But most of these Win32 functions put null in the buffer and return the buffer size needed if the buffer is too small (so you call the function twice; once with size = 0 just to find out how big to make the buffer).  LoadString() doesn't tell you the buffer was too small; it just truncates and null-terminates the string.

     

     



  • @MasterPlanSoftware said:

    Pretty sure they knew what they were doing!

    Personally, I'm pretty sure that they were copying an equivalent function in either the OS/2 (which was copied from IBM mainframe systems) or VMS standard libraries (offhand, I can't recall which one this comes from).

    Most of the win32 API was written without any thinking at all - it is largely copied from those two. As such, most of the things in it are done that way because it made sense to do things that way back in the 1970s when computers weighed twelve tons, were mounted on concrete foundations, and software was written in an unholy mixture of assembly, PL/I, and FORTRAN.

    That alone is responsible for the vast majority of the weird and annoying things in it, and almost all of the cases where functions behave in ways that are just plain inconvenient in C.



  • @MasterPlanSoftware said:

    But I think the real WTF might be more that you think you have some kind of superior knowledge to the people who wrote the win32 API... Pretty sure they knew what they were doing!

    Apparently you've never looked at the Win32 API.  There are plenty of reified bad ideas there.

    The OP's example is minor, but it's perfectly apt.  0 is a dumb choice for an error indicator, since it's a valid response as well; and since there are no valid negative return values, and the return type is signed, there's an obvious alternative.

    --
    Michael Wojcik 



  • Yes, this is dumb. But the names of the structures to store various printer information in are yet better. Guess how they are called? Of course, PRINTER_INFO_1, PRINTER_INFO_2, PRINTER_INFO_3, PRINTER_INFO_4, PRINTER_INFO_5 and PRINTER_INFO_6. Each of these structures stores completely different information. They are all handled by the same function, GetPrinter. There are a few similar examples, but fortunately most people aren't forced to use them much.

    Anyway, I don't think anybody would need empty string resources.

    BTW, LoadString returns the number of characters COPIED, not the length of the complete string. So you can't know in advance how big the buffer should be. This makes sense, since it is a low-level function that loads the string from the executable file. You can't determine the length of a string stored on the hard drive if you don't load it into memory first, and you don't know how much memory to use if you don't know the length. So it's a chicken-and-the-egg problem.
     



  • The ugly details of why LoadString can't tell you the difference between empty and missing string resources, as well as a workaround can be found at http://blogs.msdn.com/oldnewthing/archive/2004/01/30/65013.aspx

     

     


Log in to reply