Delphi2009 SOAP的bytearray编码错误导致AV错误

时间:2022-01-27 17:36:42

       在Delphi2009(12.0.3300.19037)使用SOAP,总是出现AV错误,跟踪发现是OPToSOAPDomConv这个单元的WriteVarArrayAsB64这个函数的问题。
        首先发现VarArrayLock返回的pointer不能当PWideChar来处理,修改S和Encd的定义为ansistring,并修改SetString(S, PChar(P), VSize) 为SetString(S, PAnsiChar(P), VSize),这样就没有AV错误了。
        但是又发现传回的资料结果不对,因为我的服务器是把ADO资料用ADOStream转成byte array传到客户端的,客户端再用ADOStream读取,但是现在出现“因为流无效,行集不能被加载”的错误。所以判断是SOAP打包或解包不对。再从ReadVariant函数找进去,发现最后是用EncdDecd.pas的DecodeBase64函数来解码,可是编码怎么用EncodeString函数,不用EncodeBase64函数呢?试试修改后,如下,就好了。
OPToSOAPDomConv.pas

procedure TSOAPDomConv.WriteVarArrayAsB64(RootNode, Node: IXMLNode; const Name: InvString; V: Variant);
var
  I, DimCount, VSize: Integer;
  LoDim, HiDim: array of integer;
  P: Pointer;
  //S, Encd: string; // delete by wxh,2009/3/28
  S, Encd: AnsiString; //add by wxh,2009/3/28
  ElemNode: IXMLNode;
begin
  DimCount := VarArrayDimCount(V);
  SetLength(LoDim, DimCount);
  SetLength(HiDim, DimCount);
  for I := 1 to DimCount do
  begin
    LoDim[I - 1] := VarArrayLowBound(V, I);
    HiDim[I - 1] := VarArrayHighBound(V, I);
  end;
  VSize := 0;
  for i := 0 to DimCount - 1 do
    VSize := (HiDim - LoDim + 1);
  P := VarArrayLock(V);
  try
    Encd:=EncodeBase64(P,VSize); //add by wxh,2009/3/28
    //SetString(S, PAnsiChar(P), VSize); //edit by wxh,2009/3/28,必须用AnsiString/PAnsiChar,否则出现AV
  finally
    VarArrayUnlock(V);
  end;
  //Encd := EncodeString(S); //delete by wxh,2009/3/28
  ElemNode := CreateScalarNodeXS(RootNode, Node, Name, XMLSchemaNamespace, 'base64Binary', Encd); { do not localize }
end;