I think it's the read/write string part. Would you try this code instead? I know it works, and it'll narrow down your problem possibilities:

[pascal]procedure TxnStream.WriteString(const Value: String);
var
l: integer;
begin
l := length(Value);
write(l,sizeof(l));
write(pchar(Value)^,l);
end;

procedure TxnStream.ReadString(var Value: String);
var
l: integer;
begin
read(l,sizeof(l));
setlength(Value,l);
read(pchar(Value)^,l);
end; [/pascal]

I think that the loop that looks for the #0 character is what's killing your code. On top of that, it could be error prone due to the char by char read/write... I'm no pro though.