title: How to pass SAFEARRAY to COM object through IDispatch?
body: <p>i am trying to call a method of COM object, where one of the <strong><em>documented</em></strong> parameters is an <em>"array of bytes</em>". The actual declartion depends on the per-language documentation you're looking at:</p>
  
  <ul>
  <li><p>in <strong>C#</strong> language:</p>
  
  <pre><code>byte[] TransformFinalBlock(
      byte[] inputBuffer,
      int inputOffset,
      int inputCount
  )
  </code></pre></li>
  <li><p>in <strong>C++</strong> language;</p>
  
  <pre><code>array&lt;unsigned char&gt;^ TransformFinalBlock(
      array&lt;unsigned char&gt;^ inputBuffer, 
      int inputOffset, 
      int inputCount
  )
  </code></pre></li>
  <li><p>in <strong>VB</strong> language:</p>
  
  <pre><code>Function TransformFinalBlock ( _
      inputBuffer As Byte(), _
      inputOffset As Integer, _
      inputCount As Integer _
  ) As Byte()
  </code></pre></li>
  <li><p>in <strong>F#</strong> language:</p>
  
  <pre><code>abstract TransformFinalBlock : 
          inputBuffer:byte[] * 
          inputOffset:int * 
          inputCount:int -&gt; byte[] 
  </code></pre></li>
  </ul>
  
  <p>The object i'm using can also be accessed using <strong>COM</strong>. The object provides an early binding interface, <code>ICryptoTransform</code>, which declares the method as using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx" rel="nofollow noreferrer"><strong><code>SAFEARRAY</code></strong></a>. </p>
  
  <p>From the <strong>type library</strong>:</p>
  
  <ul>
  <li><p>using <strong>IDL</strong> syntax</p>
  
  <pre><code>[
    odl,
    uuid(8ABAD867-F515-3CF6-BB62-5F0C88B3BB11),
    version(1.0),
    dual,
    oleautomation,
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "System.Security.Cryptography.ICryptoTransform")    
  ]
  interface ICryptoTransform : IDispatch {
     ...
     [id(0x60020005)]
     HRESULT TransformFinalBlock(
                  [in] SAFEARRAY(unsigned char) inputBuffer, 
                  [in] long inputOffset, 
                  [in] long inputCount, 
                  [out, retval] SAFEARRAY(unsigned char)* pRetVal);
  };
  </code></pre></li>
  <li><p>using <strong>object Pascal</strong> syntax:</p>
  
  <pre><code>ICryptoTransform = interface(IDispatch)
       ['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}']
       ...
       function TransformFinalBlock(inputBuffer: PSafeArray; inputOffset: Integer; inputCount: Integer): PSafeArray; safecall;
  end;
  </code></pre></li>
  </ul>
  
  <p>This means that when using <em>early-binding</em> you must pass the method a <code>SAFEARRAY</code>. The language i use has support for SafeArray APIs, can i can perform the call easily enough:</p>
  
  <pre><code>var
     inputBuffer: PSafeArray;
     xform: ICryptoTransform;
     ...
  begin
     ...
  
     xform.TransformFinalBlock(inputBuffer, ...);
     ...
  end;
  </code></pre>
  
  <p>Here's the same code in a java-like language:</p>
  
  <pre><code>PSafeArray inputBuffer;
  ICryptoTransform xform;
  
  ...
  
  xform.TransformFinalBlock(inputBuffer, ...);
  </code></pre>
  
  <p>And everything works <em>fine</em>; but that's not my question.</p>
  
  <blockquote>
    <p><strong>Note</strong>: i'm trying drive home the point that this is a <strong>language-agnostic</strong> question, as <strong>COM is a language agnostic technology</strong>. But at some point we have to actually <em>use</em> a language that we will demonstrate code in. <a href="https://stackoverflow.com/questions/11972829/how-to-call-use-net-rijndaelmanaged-from-native-com">Some people confuse a language with a technology</a>. If i knew Knuth's invented language, i would have used that.</p>
  </blockquote>
  
  <h2>But what about late-binding <code>IDispatch</code>?</h2>
  
  <p>Now that we know we <em>can</em> pass a <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx" rel="nofollow noreferrer"><code>SAFEARRAY</code></a> to a COM object (when using <strong><em>early-binding</em></strong>), i need to solve the problem of passing an array using <strong><em>late-binding</em></strong>.</p>
  
  <blockquote>
    <p><strong>Note</strong>: The question of how to pass a SAFEARRAY to a COM object through IDispatch is useful me to in circumstances besides <code>ICryptoTransform</code>. </p>
    
    <ul>
    <li><a href="https://stackoverflow.com/questions/489048/net-mshtml-how-to-pass-a-bstr-safearray">passing an array of <code>BSTR</code> to MSHTML control</a></li>
    <li><a href="https://stackoverflow.com/questions/11972829/how-to-call-use-net-rijndaelmanaged-from-native-com">passing an array of byte to other COM objects</a></li>
    </ul>
  </blockquote>
  
  <p>Some languages provide automatic mechanisms to invoke methods through an <code>IDispatch</code> interface at run-time (i.e. <em>late-binding</em>). In fact <code>IDispatch</code> late binding was invented for VBScript:</p>
  
  <pre><code>Dim xform = CreateObject("System.Security.Cryptography.SHA256Managed");
  Dim buffer;
  o.TransformFinalBlock(buffer, 0, 8);
  </code></pre>
  
  <p>And late-binding compiler auto-magic was added in .NET 4.0:</p>
  
  <pre><code>dynamic xform = Activator.CreateInstance(Type.GetTypeFromProgID("System.Security.Cryptography.SHA256Managed", true));
  xform.TransformFinalBlock(buffer, 0, 8);
  </code></pre>
  
  <p>Late-binding compiler magic also existed in Delphi:</p>
  
  <pre><code>xform: OleVariant;
  buffer: OleVariant;
  xform.TransformFinalBlock(buffer, 0, 8);
  </code></pre>
  
  <p>i <em>happen</em> to be using Dephi, and this call fails. </p>
  
  <h2>But it's not really compiler magic</h2>
  
  <p>It's not really magic what VBScript, C# dynamic, and Delphi are doing. They're just calling <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>IDispatch.Invoke</code></a>:</p>
  
  <pre><code>IDispatch = interface(IUnknown)
     ['{00020400-0000-0000-C000-000000000046}']
     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
           Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  end;
  </code></pre>
  
  <p>The mess is setting up these parameters:</p>
  
  <pre><code>xform.Invoke(
        1610743820,      //DispID
        IID_NULL,        //riid (reserved for future use, must be IID_NULL)
        0,               //locale id (lcid)
        DISPATCH_METHOD, //flags
        dispParams,      //Pointer to a DISPPARAMS structure
        null,            //Pointer to the location where the result is to be stored, or NULL if the caller expects no result
        exceptInfo,      //Pointer to a structure that contains exception information
        null);           //This argument can be set to null. 
  </code></pre>
  
  <p>The real trick is the <code>dispParams</code> structure, that contains the arguments.</p>
  
  <h2>The argument will be an variant</h2>
  
  <p>The arguments that get passed through DISPPARAMS are all variants:</p>
  
  <pre><code>typedef struct tagDISPPARAMS {
    VARIANTARG *rgvarg;
    DISPID     *rgdispidNamedArgs;
    UINT       cArgs;
    UINT       cNamedArgs;
  } DISPPARAMS;
  </code></pre>
  
  <p>So no matter what happens, my <em>"array of bytes"</em> is going to be a variant.</p>
  
  <p>A <a href="http://msdn.microsoft.com/en-us/library/aa908601.aspx" rel="nofollow noreferrer"><code>VARIANT</code></a>, in Win32, is simply a union that contains:</p>
  
  <ul>
  <li><code>VARTYPE vt</code>: The type of data in the union.</li>
  <li><p>the appropriate union member, e.g.:</p>
  
  <pre><code>BYTE        bVal;
  IDispatch  *pdispVal;
  SAFEARRAY  *parray;
  BYTE       *pbVal;
  IDispatch  *ppdispVal;
  SAFEARRAY  *pparray;
  VARIANT    *pvarVal;
  PVOID       byref;
  CHAR        cVal;
  </code></pre></li>
  </ul>
  
  <p>Up to now i have been passing a variant of type:</p>
  
  <pre><code>vt = VT_ARRAY | VT_UI1
  </code></pre>
  
  <p>MSDN documents what you must do when you want to use the <strong>parray</strong> union with <code>VT_ARRAY | *</code>:</p>
  
  <blockquote>
    <p><strong>Value</strong>: <code>VT_ARRAY | &lt;anything&gt;</code></p>
    
    <p><strong>Description</strong>: An array of data type  was passed. VT_EMPTY and VT_NULL are invalid types to combine with VT_ARRAY. The pointer in <strong>pbyrefVal</strong> points to an array descriptor, which describes the dimensions, size, and in-memory location of the array.</p>
  </blockquote>
  
  <p>What this means is that using the <strong><code>parray</code></strong> member:</p>
  
  <pre><code>    SAFEARRAY  *parray;
  </code></pre>
  
  <p>You need to set <code>parray</code> member to a pointer to a <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms221482%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>SAFEARRAY</code></a> structure:</p>
  
  <pre><code>typedef struct tagSAFEARRAY {
    USHORT         cDims;
    USHORT         fFeatures;
    ULONG          cbElements;
    ULONG          cLocks;
    PVOID          pvData;
    SAFEARRAYBOUND rgsabound[1];
  } SAFEARRAY, *LPSAFEARRAY;
  </code></pre>
  
  <p>In my case, my <strong><em>array of bytes</em></strong> is actually a <code>SAFEARRAY</code>, which is then being stored in a variant:</p>
  
  <pre><code>VARIANT *inputBuffer;
  SAFEARRAY *safeArray;
  
  //Setup our SAFEARRAY of data
  safeArray.cDims = 1;
  safeArray.fFeatures = FADF_HAVEVARTYPE;
  safeArray.cbElements = 1;
  safeArray.cbLocks = 0;
  safeArray.pvData = pMyData;
  safeArray.rgsabound[0].ElementCount = 1;
  safeArray.rgsabound[0].LowBound = 0;
  
  //Wrap the safearray in a variant
  inputBuffer.vt = VT_ARRAY | VT_UI1; //$2011
  vt.parray = safeArray;
  </code></pre>
  
  <blockquote>
    <p><strong>Note</strong>: Of course i'm not crazy enough to have created this safearray myself; i'm using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms221234%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>SafeArrayCreate</code></a> api function. i'm just demonstrating that it's all knowable, and not magic.</p>
  </blockquote>
  
  <h2>In other words i pass an array variant of bytes</h2>
  
  <p>In other words i <em>am</em> passing an array of bytes, wrapped in a variant, as all calls to:</p>
  
  <pre><code>dispatch.Invoke(...);
  </code></pre>
  
  <p>must be. Except that the <em>late-binding</em> call throws an error:</p>
  
  <pre><code>The parameter is incorrect.
  </code></pre>
  
  <p>So what am i possibly doing wrong?</p>
  
  <p>How does one pass an <strong>array of byte</strong> to a <strong>late-bound</strong> <code>IDispatch</code> call?</p>
  
  <h2>My Question</h2>
  
  <p>How to pass SAFEARRAY to COM object through IDispatch?</p>