IIS8.0上で動作しているDataSnap(64ビットDLL)のサーバーメソッドを呼び出すと、Internal error(HTTP Staus 500)が発生する

提供: Support
移動先: 案内検索

対象となるIDE製品

  • Delphi XE ~ Delphi XE7

対象となるターゲット環境

  • Windows 2012 Server + IIS 8.0
  • DataSnap(64ビット)

問題

特定の環境(例えば、Windows 2012 Server+IIS8.0)で動作するDataSnapのISAPI形式の DLL(64ビット)を作成し、クライアントからTObjectから派生しているoutパラメータを含むDataSnapのサーバーメソッドを呼び出すと、Internal error(HTTP Staus 500)が発生することがあります。

以下は、TObjectから派生しているoutパラメータを含むサーバーメソッドの定義の例です。

procedure Method(out value: TObject);

なお、本症状は、例えば、以下のようなケースの場合は、同様のエラーは発生しません。

  1. サーバーメソッドでoutパラメータを定義していない
  2. サーバーメソッドのout バラメータをstring型やIntegerなどのプリミティブ型で定義している
  3. DataSnapのISAPI DLLを32ビットとしてビルド
  4. Windows 2008 R2+ IIS7.5の環境へDataSnap ISAPI DLLを配置

解決

Windows 2012+ IIS8 (64bit)のISAPI DLL環境では、 デフォルトでハイメモリアドレシングが要求され、そのアドレス空間を使用する必要があります XE7までのDataSnapの仕様では、サーバーメソッドのパラメータがTObject型の場合、バリアントデータからその参照を持つポインタへキャストしており、、そのポインタのデータ長がInteger型(32ビット)になっているため、32ビットを超える高いメモリ空間へアクセスする実装にはなっていませんでした。

本件は、XE8で修正済みです。

XE8以前のバージョンでこの問題を解決するには、以下のユニットファイルを修正し、自身のプロジェクトへ組み込んでください。

修正するファイル名(Datasnap.DSReflect.pas)

(修正前)

function TDSMethodValues.GetVarObject<T>(Value: Variant): T;
var
  LObject: TObject;
begin
  if TVarData(Value).VType and varByRef <> 0 then
  begin
    LObject := TObject(Integer(TVarData(Value).VPointer^)); 
  end
  else
    LObject := TObject(TVarData(Value).VPointer);
  PObject(@Result)^ := LObject;
end;

(修正後)

function TDSMethodValues.GetVarObject<T>(Value: Variant): T;
var
  LObject: TObject;
begin
  if TVarData(Value).VType and varByRef <> 0 then
  begin
   //LObject := TObject(Integer(TVarData(Value).VPointer^));  
   LObject := TObject(TVarData(Value).VPointer^); // この部分のコードを追加
  end
  else
    LObject := TObject(TVarData(Value).VPointer);
  PObject(@Result)^ := LObject;
end;