PRB: Use IDispatch for Objects Created by a DataSpace Object

Last reviewed: January 8, 1998
Article ID: Q178845
The information in this article applies to:
  • Remote Data Service for ADO version 1.5

SYMPTOMS

Remote Data Services (RDS) has a DataSpace object that creates COM objects on a remote Internet Information Server (IIS) computer. The DataSpace's CreateObject() call accepts a ProgID as well as the Universal Resource Identifier (URL) for an IIS server. CreateObject() returns a variant that contains the IDispatch * for the created object.

If QueryInterface() is called to get an interface other than IDispatch, E_NOINTERFACE is returned.

CAUSE

All calls to methods of the object created by DataSpace.CreateObject() must be made through IDispatch::Invoke(). Furthermore, you must call GetIDsOfNames() to get the DISPIDs of the methods you want to call because RDS changes the values of the DISPIDs. They may be different from the IDs specified in the typelib.

RESOLUTION

The Visual C++ code sample shown below in the "More Information" section demonstrates how to call methods of a remote object created with RDS. The sample uses the Visual C++ 5.0 #import feature to generate C++ classes for calling methods of the DataSpace object and the remote object, which in this case is an RDS DataFactory.

The sample code shows calling the undocumented function _com_dispatch_method(), which is a function of the C run-time library. As an alternative, IDispatch::Invoke can be called directly without the use of this helper function.

Here is a short description of the function:

   HRESULT  __cdecl _com_dispatch_method(IDispatch * pDisp, DISPID dispid,
            WORD w, VARTYPE vt, void * pResult, const wchar_t * szFormat,
            ...);

   pDisp    - IDispatch of the method's object.
   dispid   - The DISPID of the method to call.
   w        - Always DISPATCH_METHOD.
   vt       - The return type. Must be a Variant type.
   pResult  - Pointer to the memory location to place the return value.
   SzFormat - String where each byte represents the variant type of each
              of the arguments being passed to the method.

The method contains a variable number of arguments because szFormat is followed by the arguments that you are passing to the object's method.

STATUS

This behavior is by design.

MORE INFORMATION

Here is the code:

   //include definitions for DataSpace and DataFactory objects
   #import "c:\program files\common files\system\msadc\msadco.dll"
   #import "c:\program files\common files\system\msadc\msadcf.dll"

   #import "c:\program files\common files\system\ado\msado15.dll" rename
       ("EOF", "ADOEOF")

   void CDlg::OnGetData()
   {
     CoInitialize(NULL);

     RDS::DIDataspacePtr spDSP;
      IDispatchPtr spDF;

   HRESULT hr;
   _variant_t varResult;

   hr = spDSP.CreateInstance(_uuidof(RDS::DataSpace));
   if (FAILED(hr))
   {
     // handle failure
   }

   varResult = spDSP->CreateObject(_bstr_t("RDSSERVER.DataFactory"),
                                   _bstr_t("http://someServer"));

   hr = varResult.pdispVal->QueryInterface(_uuidof(IDispatch),
                                           (LPVOID *)&spDF);
   if ((FAILED(hr))
   {
      // handle error
   }


   // Call the Query method of the DataFactory.
   // First query for the DISPID of the method because RDS
   // modifies the DISPID. It can be different than what the
   // type library states.
   LPOLESTR pszNames[1] = {OLESTR("Query")};
   DISPID dispids[1];
   hr = spDF->GetIDsOfNames(IID_NULL, pszNames, 1, LOCALE_SYSTEM_DEFAULT,
                            dispids);
   if (FAILED(hr)
   {
      //handle error
   }

   try
   {
      ADODB::_RecordsetPtr pRS;
      IDispatch * _result;
      _com_dispatch_method(spDF, dispids[0], DISPATCH_METHOD,
                           VT_DISPATCH, (void*)&_result,
                           L"\x0008\x0008\x0003",
                           (BSTR) _bstr_t("DSN=AdvWorks;UID=Admin;PWD=;"),
                           (BSTR)_bstr_t("Select * from employees"), 0L);
      pRS = _result;
    }
    catch(_com_error e)
    {
      TRACE("Hresult = %x\n", e.Error());
      TRACE("%S\n", e.Description());
      return;
    }


   // Output the results of the returned recordset.
    long lCount = pRS->Fields->Count;

    for (long lIndex = 0; lIndex<lCount; lIndex++)
    {
       _variant_t varField = pRS->Fields->Item[lIndex]->Value;

       if (varField.vt != VT_NULL)
       {
          varField.ChangeType(VT_BSTR);
          // Do something with the BSTR here, for example, put it into a
          // list control.
         }
      }
   }


Additional query words: interface nointerface
Keywords : kbcode
Version : WINDOWS:1.5
Platform : WINDOWS
Issue type : kbprb


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 8, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.