What does “size_is” mean in an IDL file?

My boss (who has spent a really long time working on RPC) and I got into a discussion the other day about the “size_is” IDL attribute (yeah, that’s what Microsoft developers chat about when they’re bored).

For context, there are two related attributes which are applied to an array in IDL files.  size_is(xxx) and length_is(xxx).  They both relate to the amount of memory which is marshaled in a COM or RPC interface, but we were wondering the exact semantics of the parameter.

The documentation for “size_is” says:

Use the [size_is] attribute to specify the size of memory allocated for sized pointers, sized pointers to sized pointers, and single- or multidimensional arrays.

The documentation for “length_is” says:

The [ length_is ] attribute specifies the number of array elements to be transmitted. You must specify a non-negative value.

So the length_is attribute clearly refers to the number of elements in the array to be transmitted.  But what are the units for the size_is attribute?  The MSDN documentation doesn’t say – all you see is that it “specif[ies] the size of memory allocated for … single- or multidimentional arrays”.  Typically memory allocations are specified in bytes, so this implies that the size_is attribute measures the number of bytes transferred.

And that’s what I’ve thought for years and years.  length_is was the number of elements and size_is was the number of bytes.

But my boss thought that size_is referred to a number of elements.  And since he’s worked on RPC for years, I figured he’d know best since he actually worked on RPC.

 

To see if the problem was just that the current MSDN documentation was incorrect, I dug into the oldest RPC documentation I have – from the original Win32 SDK that was shipped with Windows NT 3.1 way back in 1993 (I have my own personal wayback machine in my office).

The old SDK documentation says:

“the size_is attribute is used to specify an expression or identifier that designates the maximum allocation size of the array”

Well, allocation sizes are always in bytes, so size_is is in bytes, right?

Well maybe not.  It further goes on to say:

“the values specified by the size_is, max_is and min_is attributes have the following relationship: size_is = max_is – 1.  The size_is attribute provides an alternative to max_is for specifying the maximum amount of data”

So what is “max_is”?  Maybe there’s a clue there…

Go to max_is and it says “designates the maximum value for a valid array index” – so clearly it is a count of elements.  And thus by induction, size_is must be in number of elements and not number of bytes… 

Ok, so the old documentation is ambiguous but it implies that both length_is and size_is refer to a count of elements.

 

To confirm, I went to the current owner of the MIDL compiler for the definitive word on this and he said:

Always in elements for all the XXX_is attributes.  And everything else except allocation routines IIRC.

<Your boss> is correct that we allocate the buffer based on size_is, but we transmit elements based on length_is if they’re both present.  BTW, [string] is basically [length_is(<w>strlen(…))].

So that’s the definitive answer:

size_is and length_is both refer to a count of elements.  size_is defines the size of the buffer allocated for the transfer and length_is specifies the number of elements transferred within that buffer.

 

 

And yes, I’ve asked the documentation folks to update the documentation to correct this.

 

EDIT: Oops, fixed a typo.  Thanks Sys64738:)