소스 검색

* ported mechanism from unit activex to deal with ansi/unicode -> widestring conversion.
* 2nd attempt, now under $IFDEF MSWINDOWS

marcoonthegit 1 개월 전
부모
커밋
134e964514
1개의 변경된 파일68개의 추가작업 그리고 1개의 파일을 삭제
  1. 68 1
      packages/rtl-objpas/src/inc/variants.pp

+ 68 - 1
packages/rtl-objpas/src/inc/variants.pp

@@ -376,6 +376,10 @@ uses
   VarUtils;
 {$ENDIF FPC_DOTTEDUNITS}
 
+{$IFDEF MSWINDOWS}
+procedure SysFreeString(bstr:pointer); stdcall; external 'oleaut32.dll' name 'SysFreeString';
+{$ENDIF}
+
 var
   customvarianttypes    : array of TCustomVariantType;
   customvarianttypelock : trtlcriticalsection;
@@ -4103,7 +4107,11 @@ var
   arg_data: PVarData;
   dummy_data: TVarData;
   arg_advanced: boolean;
-
+{$IFDEF MSWINDOWS}
+  i : integer;
+  nextstring: integer;
+  StringMap : array[0..255] of record passtr : pansistring; paswstr : punicodestring; comstr : pwidechar; end;
+{$ENDIF}
 const
   argtype_mask = $7F;
   argref_mask = $80;
@@ -4111,6 +4119,10 @@ begin
   arg_count := CallDesc^.ArgCount;
   method_name := ansistring(PAnsiChar(@CallDesc^.ArgTypes[arg_count]));
   setLength(args, arg_count);
+  {$IFDEF MSWINDOWS}
+  nextstring:=0;
+  try
+  {$ENDIF}
   if arg_count > 0 then
   begin
     arg_ptr := Params;
@@ -4127,8 +4139,34 @@ begin
       end;
       if arg_byref then
       begin
+      {$IFDEF MSWINDOWS}
+        case arg_type of
+          varStrArg:  begin
+                       StringMap[NextString].ComStr:=StringToOleStr(PAnsiString(ppointer(arg_ptr)^)^);
+                       StringMap[NextString].PasStr:=PAnsiString(ppointer(arg_ptr)^);
+                       StringMap[NextString].PasWStr:=nil;
+                       arg_data^.vType := arg_data^.vType or varByRef;
+                       arg_data^.volestr:=StringMap[NextString].ComStr;
+                       inc(NextString);
+                      end;
+          varUStrArg:  begin
+                       StringMap[NextString].ComStr:=StringToOleStr(PUnicodeString(ppointer(arg_ptr)^)^);
+                       StringMap[NextString].PasStr:=nil;
+                       StringMap[NextString].PasWStr:=PUnicodeString(ppointer(arg_ptr)^);
+                       arg_data^.vType := arg_data^.vType or varByRef;
+                       arg_data^.volestr:=StringMap[NextString].ComStr;
+                       inc(NextString);
+                      end;
+          else
+             begin
+               arg_data^.vType := arg_data^.vType or varByRef;
+               arg_data^.vPointer := PPointer(arg_ptr)^;
+             end;
+          end;
+      {$ELSE}
         arg_data^.vType := arg_data^.vType or varByRef;
         arg_data^.vPointer := PPointer(arg_ptr)^;
+      {$ENDIF}
         Inc(arg_ptr,sizeof(Pointer));
       end
       else
@@ -4167,6 +4205,22 @@ begin
               arg_data^.vByte := PLongint(arg_ptr)^;
             varWord:
               arg_data^.vWord := PLongint(arg_ptr)^;
+{$IFDEF MSWINDOWS}
+            varStrArg:  begin
+                         StringMap[NextString].ComStr:=StringToOleStr(PAnsiString(arg_ptr)^);
+                         StringMap[NextString].PasStr:=nil;
+                         StringMap[NextString].PasWStr:=Nil;
+                         arg_data^.volestr:=StringMap[NextString].ComStr;
+                         inc(NextString);
+                        end;
+            varUStrArg:  begin
+                         StringMap[NextString].ComStr:=StringToOleStr(PunicodeString(arg_ptr)^);
+                         StringMap[NextString].PasStr:=nil;
+                         StringMap[NextString].PasWStr:=Nil;
+                         arg_data^.volestr:=StringMap[NextString].ComStr;
+                         inc(NextString);
+                        end;
+{$ENDIF}
             else
               arg_data^.vAny := PPointer(arg_ptr)^; // 32 or 64bit
           end;
@@ -4227,6 +4281,19 @@ begin
   else
     RaiseDispError;
   end;
+  {$IFDEF MSWINDOWS}
+    { translate strings back }
+    for i:=0 to NextString-1 do begin
+      if assigned(StringMap[i].passtr) then
+        OleStrToStrVar(StringMap[i].comstr,StringMap[i].passtr^)
+      else if assigned(StringMap[i].paswstr) then
+        OleStrToStrVar(StringMap[i].comstr,StringMap[i].paswstr^);
+    end;
+ finally
+    for i:=0 to NextString-1 do
+      SysFreeString(StringMap[i].ComStr);
+    end;
+  {$ENDIF}
 end;
 
 function TInvokeableVariantType.DoFunction(var Dest: TVarData; const V: TVarData; const Name: AnsiString; const Arguments: TVarDataArray): Boolean;