I once had to use a C API where you had to guess the size of of the buffer of data you were going to get back, and keep guessing until your number was compatible with the amount of data. So I did what any good CS person would do, and started with a small, reasonable number, then doubled it until the API was happy. Was this documented? No. Everything but how you were supposed to specify the buffer size was documented. However, this code worked in production, and AFAIK, it's still running in production to this day.
To be fair, without knowing what that API does, I could see a situation where it itself doesn't know how long the data would be. Parsing free-form char-terminated data, especially over the network, is one example that comes to mind, and another is decompressing compressed data in a self-delimited stream; in general, data whose length cannot be determined apriori. Furthermore, the API probably doesn't want to allocate and buffer the data itself since it could be very long, nor does it want to impose a fixed limit since the application should decide that.
To be fair, without knowing what that API does, I could see a situation where it itself doesn't know how long the data would be.
This was to get a message out of the API. At the point one is making the call, it does know how long the message is. (Having already gotten a callback.) It looks like the author forgot to write the function that would return the length, then improvised.
Furthermore, the API probably doesn't want to allocate and buffer the data itself since it could be very long, nor does it want to impose a fixed limit since the application should decide that.
Like which one? Pretty much every single one I know, you pass a buffer and a pointer to a buffer size; the first time you call with buffer NULL and the required buffer size is put in the buffer size; then you allocate the buffer and call again with the proper buffer allocated.
QueryDosDevice? You're right that mostly length is passed back, but esp in libs you get this problem you pass memory you own, some underlying function fails with "buffer too small", but buffer length was not in/out in the interface. Places where this can happen are not always obvious from reading the msdn.