Ok, here is my first attempt (that fails). Can anyone spot what I'm doing wrong?

[pascal]uses
Variants;

Function GetVariantSize(v : Variant): Integer;
var
vt: TVarType;
Begin
vt := TVarData(v).vtype;
Result := -1;
Case vt Of
varSmallint : Result := Sizeof( SmallInt );
varInteger : Result := Sizeof( Integer );
varSingle : Result := Sizeof( Single );
varDouble : Result := Sizeof( Double );
varCurrency : Result := Sizeof( Currency );
varDate : Result := Sizeof( TDateTime );
//varOleStr : Result := Sizeof( Widestring );
varDispatch : Result := Sizeof( Pointer );
varError : Result := Sizeof( Cardinal );
varBoolean : Result := Sizeof( WordBool );
varVariant : Result := Sizeof( Variant );
varUnknown : Result := Sizeof( Pointer );
varShortInt : Result := Sizeof( ShortInt );
varByte : Result := Sizeof( Byte );
varWord : Result := Sizeof( Word );
varLongWord : Result := Sizeof( LongWord );
varInt64 : Result := Sizeof( Int64 );
varOleStr,// : Result := Sizeof( Widestring );
varString : Result := Length(AnsiString(v));
End; { Case }
End;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
v2,
v : Variant;
vd: TVarData;
vt: tvartype;
i : Integer;
ms: TMemoryStream;
procedure WriteBlock(p : Pointer; siz : Cardinal);
begin
ms.WriteBuffer(siz, sizeof(siz));
ms.WriteBuffer(p, siz);
end;
procedure ReadBlock(p : Pointer);
var
siz : Cardinal;
begin
ms.ReadBuffer(siz, sizeof(siz));
ms.ReadBuffer(p, siz);
end;
procedure WriteString(s:AnsiString);
begin
WriteBlock(@s[1], length(s));
end;
function ReadString : AnsiString;
var
siz : Cardinal;
begin
ms.ReadBuffer(siz, sizeof(siz));
setlength(ReadString, siz);
ms.ReadBuffer(ReadString[1], siz);
end;
begin
v := 'asdf';//123;
vd := TVarData(v);
vt := vd.vtype;

ms := TMemoryStream.Create;
try
WriteBlock(@vt, SizeOf(vt));
case vt of
varString, varOleStr : WriteString(v);
else
WriteBlock(@TVarData(v).vwords[0], GetVariantSize(v));
end;

ms.Position := 0;
ReadBlock(@vt);
case vt of
varString, varOleStr : v2 := ReadString;
else
TVarData(v2).vType := vt;
ReadBlock(@TVarData(v2).vwords[0]);
end;
Memo1.lines.Add(v2);
finally
ms.Free;
end;
end;
[/pascal]