@@ -126,6 +126,7 @@   TNamedParamDesc = record
126126
127127{ $IFDEF DELPHIXE2_OR_HIGHER} 
128128  { $DEFINE USESYSTEMDISPINVOKE} // Delphi 2010 DispInvoke is buggy
129+   { $DEFINE PATCHEDSYSTEMDISPINVOKE} // To correct memory leaks
129130{ $ENDIF} 
130131{ .$IF DEFINED(FPC_FULLVERSION) and (FPC_FULLVERSION >= 20500)} 
131132  { .$DEFINE USESYSTEMDISPINVOKE} 
@@ -944,17 +945,40 @@ procedure TPythonVariantType.DispInvoke(Dest: PVarData;
944945   var  Source: TVarData; CallDesc: PCallDesc; Params: Pointer);
945946{ $ENDIF} 
946947{ $IFDEF USESYSTEMDISPINVOKE} 
947- { $IFDEF DELPHIXE2_OR_HIGHER} 
948-   //   Modified to correct memory leak QC102387
948+ { $IFDEF PATCHEDSYSTEMDISPINVOKE} 
949+   //   Modified to correct memory leak QC102387 / RSP-23093
950+   procedure  PatchedFinalizeDispatchInvokeArgs (CallDesc: PCallDesc; const  Args: TVarDataArray; OrderLTR : Boolean);
951+   const 
952+     atByRef    = $80 ;
953+   var 
954+     I: Integer;
955+     ArgType: Byte;
956+     PVarParm: PVarData;
957+     VType: TVarType;
958+   begin 
959+     for  I := 0  to  CallDesc^.ArgCount-1  do 
960+     begin 
961+       ArgType := CallDesc^.ArgTypes[I];
962+ 
963+       if  OrderLTR then 
964+         PVarParm := @Args[I]
965+       else 
966+         PVarParm := @Args[CallDesc^.ArgCount-I-1 ];
967+ 
968+       VType := PVarParm.VType;
969+ 
970+       //  Only ByVal Variant or Array parameters have been copied and need to be released
971+       //  Strings have been released via the use of the TStringRefList parameter to GetDispatchInvokeArgs
972+       //  !!Modified to prevent memory leaks!! RSP-23093
973+       if  ((ArgType and  atByRef) <> atByRef) and  ((ArgType = varVariant) or  ((VType and  varArray) = varArray)) then 
974+         VarClear(PVariant(PVarParm)^);
975+     end ;
976+   end ;
977+ 
949978  procedure  PatchedDispInvoke (Dest: PVarData;
950979    const  Source: TVarData; CallDesc: PCallDesc; Params: Pointer);
951980  type 
952-     PParamRec = ^TParamRec;
953-     TParamRec = array [0 ..3 ] of  LongInt;
954-     TStringDesc = record 
955-       BStr: WideString;
956-       PStr: PAnsiString;
957-     end ;
981+     PStringRefList = ^TStringRefList;
958982  const 
959983    CDoMethod    = $01 ;
960984    CPropertyGet = $02 ;
@@ -964,67 +988,75 @@     TStringDesc = record
964988    LIdent: string;
965989    LTemp: TVarData;
966990    VarParams : TVarDataArray;
967-     Strings: TStringRefList;
991+     Strings: array  of  TStringRef;
992+     PIdent: PByte;
968993  begin 
969994    //  Grab the identifier
970995    LArgCount := CallDesc^.ArgCount;
971-     LIdent := FixupIdent(string(AnsiString(PAnsiChar(@CallDesc^.ArgTypes[LArgCount]))));
972- 
973-     FillChar(Strings, SizeOf(Strings), 0 );
974-     VarParams := GetDispatchInvokeArgs(CallDesc, Params, Strings, true);
975- 
976-     //  What type of invoke is this?
977-     case  CallDesc^.CallType of 
978-       CDoMethod:
979-         //  procedure with N arguments
980-         if  Dest = nil  then 
981-         begin 
982-           if  not  DoProcedure(Source, LIdent, VarParams) then 
996+     PIdent := @CallDesc^.ArgTypes[LArgCount];
997+     LIdent := FixupIdent( UTF8ToString(MarshaledAString(PIdent)) );
998+     if  LArgCount > 0  then  begin 
999+       SetLength(Strings, LArgCount);
1000+       FillChar(Strings[0 ], SizeOf(TStringRef)*LArgCount, 0 );
1001+       VarParams := GetDispatchInvokeArgs(CallDesc, Params, PStringRefList(Strings)^, true);
1002+     end ;
1003+     try 
1004+       //  What type of invoke is this?
1005+       case  CallDesc^.CallType of 
1006+         CDoMethod:
1007+           //  procedure with N arguments
1008+           if  Dest = nil  then 
9831009          begin 
1010+             if  not  DoProcedure(Source, LIdent, VarParams) then 
1011+             begin 
1012+ 
1013+               //  ok maybe its a function but first we must make room for a result
1014+               VarDataInit(LTemp);
1015+               try 
1016+ 
1017+                 //  notate that the destination shouldn't be bothered with
1018+                 //  functions can still return stuff, we just do this so they
1019+                 //   can tell that they don't need to if they don't want to
1020+                 SetClearVarToEmptyParam(LTemp);
1021+ 
1022+                 //  ok lets try for that function
1023+                 if  not  DoFunction(LTemp, Source, LIdent, VarParams) then 
1024+                   RaiseDispError;
1025+               finally 
1026+                 VarDataClear(LTemp);
1027+               end ;
1028+             end 
1029+           end 
9841030
985-             //  ok maybe its a function but first we must make room for a result
986-             VarDataInit(LTemp);
987-             try 
988- 
989-               //  notate that the destination shouldn't be bothered with
990-               //  functions can still return stuff, we just do this so they
991-               //   can tell that they don't need to if they don't want to
992-               SetClearVarToEmptyParam(LTemp);
993- 
994-               //  ok lets try for that function
995-               if  not  DoFunction(LTemp, Source, LIdent, VarParams) then 
996-                 RaiseDispError;
997-             finally 
998-               VarDataClear(LTemp);
999-             end ;
1031+           //  property get or function with 0 argument
1032+           else  if  LArgCount = 0  then 
1033+           begin 
1034+             if  not  GetProperty(Dest^, Source, LIdent) and 
1035+                not  DoFunction(Dest^, Source, LIdent, VarParams) then 
1036+               RaiseDispError;
10001037          end 
1001-         end 
10021038
1003-         //  property get or function with 0 argument
1004-         else  if  LArgCount = 0  then 
1005-         begin 
1006-           if  not  GetProperty(Dest^, Source, LIdent) and 
1007-              not  DoFunction(Dest^, Source, LIdent, VarParams) then 
1039+           //  function with N arguments
1040+           else  if  not  DoFunction(Dest^, Source, LIdent, VarParams) then 
10081041            RaiseDispError;
1009-         end 
10101042
1011-         //  function with N arguments
1012-         else  if  not  DoFunction(Dest^, Source, LIdent, VarParams) then 
1013-           RaiseDispError;
1043+         CPropertyGet:
1044+           if  not  ((Dest <> nil ) and                          //  there must be a dest
1045+                   (LArgCount = 0 ) and                        //  only no args
1046+                   GetProperty(Dest^, Source, LIdent)) then   //  get op be valid
1047+             RaiseDispError;
10141048
1015-       CPropertyGet:
1016-         if  not  ((Dest <> nil ) and                          //  there must be a dest
1017-                 (LArgCount = 0 ) and                        //  only no args
1018-                 GetProperty(Dest^, Source, LIdent)) then   //  get op be valid
1019-           RaiseDispError;
1049+         CPropertySet:
1050+           if  not  ((Dest = nil ) and                           //  there can't be a dest
1051+                   (LArgCount = 1 ) and                        //  can only be one arg
1052+                   SetProperty(Source, LIdent, VarParams[0 ])) then  //  set op be valid
1053+             RaiseDispError;
1054+       else 
1055+         RaiseDispError;
1056+       end ;
10201057
1021-       CPropertySet:
1022-         if  not  ((Dest = nil ) and                           //  there can't be a dest
1023-                 (LArgCount = 1 ) and                        //  can only be one arg
1024-                 SetProperty(Source, LIdent, VarParams[0 ])) then  //  set op be valid
1025-           RaiseDispError;
1026-     else 
1027-       RaiseDispError;
1058+     finally 
1059+       PatchedFinalizeDispatchInvokeArgs(CallDesc, VarParams, true);
10281060    end ;
10291061
10301062    for  I := 0  to  Length(Strings) - 1  do 
@@ -1033,13 +1065,12 @@     TStringDesc = record
10331065        Break;
10341066      if  Strings[I].Ansi <> nil  then 
10351067        Strings[I].Ansi^ := AnsiString(Strings[I].Wide)
1036-       else  if  Strings[I].Unicode <> nil  then 
1037-         Strings[I].Unicode^ := UnicodeString(Strings[I].Wide)
1068+       else 
1069+         if  Strings[I].Unicode <> nil  then 
1070+           Strings[I].Unicode^ := UnicodeString(Strings[I].Wide)
10381071    end ;
1039-     for  I := Low(VarParams) to  High(VarParams) do 
1040-       VarDataClear(VarParams[I]);
10411072  end ;
1042- { $ENDIF DELPHIXE2_OR_HIGHER } 
1073+ { $ENDIF PATCHEDSYSTEMDISPINVOKE } 
10431074
10441075  procedure  GetNamedParams ;
10451076  var 
@@ -1066,17 +1097,17 @@     TStringDesc = record
10661097    if  (CallDesc^.CallType = CPropertyGet) and  (CallDesc^.ArgCount = 1 ) then  begin 
10671098      NewCallDesc := CallDesc^;
10681099      NewCallDesc.CallType := CDoMethod;
1069-     { $IFDEF DELPHIXE2_OR_HIGHER } 
1100+     { $IFDEF PATCHEDSYSTEMDISPINVOKE } 
10701101      PatchedDispInvoke(Dest, Source, @NewCallDesc, Params);
1071-     { $ELSE DELPHIXE2_OR_HIGHER } 
1102+     { $ELSE PATCHEDSYSTEMDISPINVOKE } 
10721103      inherited  DispInvoke(Dest, Source, @NewCallDesc, Params);
1073-     { $ENDIF DELPHIXE2_OR_HIGHER } 
1104+     { $ENDIF PATCHEDSYSTEMDISPINVOKE } 
10741105    end  else 
1075-       { $IFDEF DELPHIXE2_OR_HIGHER } 
1106+       { $IFDEF PATCHEDSYSTEMDISPINVOKE } 
10761107      PatchedDispInvoke(Dest, Source, CallDesc, Params);
1077-       { $ELSE DELPHIXE2_OR_HIGHER } 
1108+       { $ELSE PATCHEDSYSTEMDISPINVOKE } 
10781109      inherited ;
1079-       { $ENDIF DELPHIXE2_OR_HIGHER } 
1110+       { $ENDIF PATCHEDSYSTEMDISPINVOKE } 
10801111  finally 
10811112    if  CallDesc^.NamedArgCount > 0  then  SetLength(fNamedParams, 0 );
10821113  end ;
0 commit comments