strings holding these names and values are allocated once, never initialized, and never modified outside of API calls.
MSDN calls for an "address of a pointer to a null-terminated string" in the case of &val
How do these functions know the size of the buffer I'm passing?
For example, say we first read the gender attribute of a voice. val now holds "Male\0". Why doesn't the subsequent call querying the name -"Microsoft David" - fail due to apparently insufficient buffer size (i.e. wcslen(val) returning 4)?
If CoTaskMemAlloc stores the size internally, why does it need to be passed for ISpDataKey::GetData (essentially the same as GetStringValue, just writing to a BYTE* buffer instead of LPWSTR* and requiring a size parameter)?
When a function asks for a pointer to a pointer it is a sign that the function wants to modify the pointer. I think the string data that val is pointing to before you pass it to GetStringValue is left unchanged but instead val will be set to point to a different string.