The problem is that the serialization of Image class treats it as a contiguous block of memory. Since BSTR is really a pointer only the pointer value is serialized and the BSTR payload is lost.
Instead you should write all fields except BSTRs as binary and process BSTRs separately. For example, you can write BSTR length as integer first, then its payload. When reading you will read length first, call SysAllocStringLen() to allocate a buffer, then read the payload.
Leave serialization of simple fields as it is (the IPersistStreamInit::Save() ):
pStm->Write(&(img.color), (ULONG)sizeof(float), &cb);
For BSTRs do this:
int length = SysStringLen( img.uname );
pStm->Write(&length, (ULONG)sizeof(int), &cb);
if( length > 0 ) {
pStm->Write( img.uname, (ULONG)(length * sizeof(WCHAR) ), &cb);
}
Similar for reading (the IPersistStreamInit::Load()):
int length;
pStm->Read(&length, (ULONG)sizeof(int), &cb);
if( length > 0 ) {
img.uname = SysAllocStringLen( 0, length );
pStm->Read( img.uname, (ULONG)( length * sizeof( WCHAR) ), &cb);
} else {
img.uname = 0;
}
Note that this code writes/reads string length and then writes/reads the payload that consists of Unicode characters. Unicode characters occupy more than one bytes each - hence the multiplication in IStream Read/Write methods call.