What is the correct way of using the string buffer returned by the WindowsPreallocateStringBuffer function?


The most common way of creating an HSTRING is to call Windows­Create­String, but there is also a two-phase creation pattern: First you call Windows­Preallocate­String­Buffer to create a buffer for a future string. You then fill the buffer with stringy goodness and then call Windows­Promote­String­Buffer to convert it to a real HSTRING. (Or you can call Windows­Delete­String­Buffer to change your mind and pretend it never happened.)

The rule for managing the buffer returned by Windows­Preallocate­String­Buffer is that you are expected to write exactly length code units into the buffer. No more. No less. The system already put a terminating null after the end of the buffer; your job is to fill the buffer with the string contents.

For example, if you want to use two-phase creation to create the string hello, you would call Windows­Preallocate­String­Buffer and pass length = 5. Into the resulting buffer, you write the characters h, e, l, l, and o, and that's all. The system already stored the terminating null.

This particular formulation of the rules is important in the case that length = 0.¹ Since the representation of an HSTRING of length zero is the null pointer, there is no actual buffer. What happens is that the system uses a single preallocated buffer (consisting of just a null terminator) to represent the buffer for all zero-length strings. If you call Windows­Preallocate­String­Buffer, you get a pointer to that preallocated buffer.² Since you passed a length of zero, you are expected to write zero characters to the buffer; in other words, you are expected to do nothing at all with the buffer.

And of course since HSTRINGs are immutable, your permission to modify the buffer ends once you promote the buffer to a string. Once it's been promoted to a string, the entire buffer becomes read-only.

¹ Another way of interpreting this corner case is to say "Don't bother calling Windows­Preallocate­String­Buffer with a string of length zero. Otherwise, go ahead and call it, and you can write that null terminator if you like."

² Arguably, to accommodate the possibiltiy of somebody writing that null terminator, it should return a preallocated writable buffer just large enough to hold that null terminator. It could be the high 16 bits of the length field itself!

Comments (13)

  1. skSdnW says:

    No more. No less? WindowsPreallocateStringBuffer’s example code on MSDN asks for 10 characters and writes noting. The page itself also says “You must write exactly length characters into the buffer.” so the interns writing the example code don’t even read the documentation for the function they are writing the example for?

    1. I am the intern in question. What you’re seeing is the absence of a time machine. The “exactly length characters” text was added several years after the sample was written. When the text was updated, the sample wasn’t.

      1. skSdnW says:

        It creates a string with undefined contents. The additional documentation made the example worse by not following the requirements but the example never made any sense.

      2. Rick C says:

        By contrast, WindowsPromoteStringBuffer has a “fill in the buffer” comment.

      3. Antonio Rodríguez says:

        Why did the rules get changed after the API was created? Maybe because of mixed-language projects, when mixing null-terminated runtimes with length-content runtimes caused the garbage after the first null come afloat and cause bugs?

        Anyway, it could be easily solved: just fill with nulls the unused part of the string. You get a “normalized” string which is equally valid as null-terminated and length-content (albeit a bit strange in the later case).

        1. skSdnW says:

          Filling with null messes up things that verify and reject based on WindowsStringHasEmbeddedNull.

        2. The rules didn’t change. The documentation stated the pre-existing rules incorrectly.

          1. 640k says:

            Please replace the msdn docs with a link to your post above, it’s 1000x better.

  2. Paul Topping says:

    So what’s the typical use case for WindowsPreallocateStringBuffer?

    1. Antonio Rodríguez says:

      Performance. Let’s say you have an algorithm that generates a 100-point string. You could allocate a temporary buffer, generate the string into the buffer, call WindowsCreateString() to create the actual string, and finally free the temporary buffer. WindowsPreallocateStringBuffer(), on the other hand, avoids allocating/freeing the temporary buffer and copying its contents to the final buffer. If you create a lot of strings, or they are large, it can make a big difference.

  3. mikeb says:

    I am confused by these two statements (but that might be because I haven’t looked into HSTRINGs at all, really) which don’t seem to agree with each other:

    – “Since the representation of an HSTRING of length zero is the null pointer”
    – “the system uses a single preallocated buffer (consisting of just a null terminator) to represent all zero-length strings”

    1. “the system uses a single preallocated buffer (consisting of just a null terminator) to represent the buffer for all zero-length strings”. Will fix.

      1. Ted M says:

        Raymond, I sent a ping to the good people at the @docsmsft twitter account, they can take care of any MSDN inconsistencies your other readers may find. Just wanted to pass that on to you and anybody interested.

Skip to main content