You need a couple of extra "^", this is working:

[pascal]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(Result, siz);
ms.ReadBuffer(Result[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;
Button1.Caption := v2;
finally
ms.Free;
end;
end;
[/pascal]