Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

OLE.cpp

Go to the documentation of this file.
00001 #include "OSDependent/OLE.h"
00002 
00003 /*
00004  * CreateObject
00005  *
00006  * Purpose:
00007  *  Creates an instance of the Automation object and obtains it's IDispatch interface.
00008  *  Uses Unicode with OLE.
00009  *
00010  * Parameters:
00011  *  pszProgID         ProgID of Automation object
00012  *  ppdisp             Returns IDispatch of Automation object
00013  *
00014  * Return Value:
00015  *  HRESULT indicating success or failure 
00016  */
00017 HRESULT 
00018 OLE::createObject(LPOLESTR pszProgID, IDispatch FAR* FAR* ppdisp)
00019 {
00020     CLSID clsid;                   // CLSID of automation object
00021     HRESULT hr;
00022     LPUNKNOWN punk = NULL;         // IUnknown of automation object
00023     LPDISPATCH pdisp = NULL;       // IDispatch of automation object
00024     
00025     *ppdisp = NULL;
00026     
00027     // Retrieve CLSID from the progID that the user specified
00028     hr = CLSIDFromProgID(pszProgID, &clsid);
00029     if (FAILED(hr))
00030         goto error;
00031     
00032     // Create an instance of the automation object and ask for the IDispatch interface
00033     hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, 
00034                           IID_IUnknown, (void FAR* FAR*)&punk);
00035     if (FAILED(hr))
00036         goto error;
00037                    
00038     hr = punk->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp);
00039     if (FAILED(hr))
00040         goto error;
00041 
00042     *ppdisp = pdisp;
00043     punk->Release();
00044     return NOERROR;
00045      
00046 error:
00047     if (punk) punk->Release();
00048     if (pdisp) pdisp->Release();
00049     return hr;
00050 }  
00051 
00052 /*
00053  * Invoke
00054  *
00055  * Purpose:
00056  *  Invokes a property accessor function or method of an automation object. Uses Unicode with OLE.
00057  *
00058  * Parameters:
00059  *  pdisp         IDispatch* of automation object.
00060  *  wFlags        Specfies if property is to be accessed or method to be invoked.
00061  *                Can hold DISPATCH_PROPERTYGET, DISPATCH_PROPERTYPUT, DISPATCH_METHOD,
00062  *                DISPATCH_PROPERTYPUTREF or DISPATCH_PROPERTYGET|DISPATCH_METHOD.   
00063  *  pvRet         NULL if caller excepts no result. Otherwise returns result.
00064  *  pexcepinfo    Returns exception info if DISP_E_EXCEPTION is returned. Can be NULL if
00065  *                caller is not interested in exception information. 
00066  *  pnArgErr      If return is DISP_E_TYPEMISMATCH, this returns the index (in reverse
00067  *                order) of argument with incorrect type. Can be NULL if caller is not interested
00068  *                in this information. 
00069  *  pszName       Name of property or method.
00070  *  pszFmt        Format string that describes the variable list of parameters that 
00071  *                follows. The format string can contain the follwoing characters.
00072  *                & = mark the following format character as VT_BYREF 
00073  *                b = VT_BOOL
00074  *                i = VT_I2
00075  *                I = VT_I4
00076  *                r = VT_R2
00077  *                R = VT_R4
00078  *                c = VT_CY 
00079  *                s = VT_BSTR (far string pointer can be passed, BSTR will be allocated by this function).
00080  *                e = VT_ERROR
00081  *                d = VT_DATE
00082  *                v = VT_VARIANT. Use this to pass data types that are not described in 
00083  *                                the format string. (For example SafeArrays).
00084  *                D = VT_DISPATCH
00085  *                U = VT_UNKNOWN
00086  *    
00087  *  ...           Arguments of the property or method. Arguments are described by pszFmt.  
00088  *                ****FAR POINTERS MUST BE PASSED FOR POINTER ARGUMENTS in Win16.****
00089  * Return Value:
00090  *  HRESULT indicating success or failure        
00091  *
00092  * Usage examples:
00093  *
00094  *  HRESULT hr;  
00095  *  LPDISPATCH pdisp;   
00096  *  BSTR bstr;
00097  *  short i;
00098  *  BOOL b;   
00099  *  VARIANT v, v2;
00100  *
00101  *1. bstr = SysAllocString(OLESTR(""));
00102  *   hr = Invoke(pdisp, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("method1"), 
00103  *        TEXT("bis&b&i&s"), TRUE, 2, (LPOLESTR)OLESTR("param"), (BOOL FAR*)&b, (short FAR*)&i, (BSTR FAR*)&bstr);   
00104  *
00105  *2. VariantInit(&v);
00106  *   V_VT(&v) = VT_R8;
00107  *   V_R8(&v) = 12345.6789; 
00108  *   VariantInit(&v2);
00109  *   hr = Invoke(pdisp, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("method2"), 
00110  *         TEXT("v&v"), v, (VARIANT FAR*)&v2);
00111  */
00112 HRESULT 
00113 OLE::invoke(LPDISPATCH pdisp, 
00114     WORD wFlags,
00115     LPVARIANT pvRet,
00116     EXCEPINFO FAR* pexcepinfo,
00117     UINT FAR* pnArgErr, 
00118     LPOLESTR pszName,
00119     LPCTSTR pszFmt, 
00120     ...)
00121 {
00122     va_list argList;
00123     va_start(argList, pszFmt);  
00124     DISPID dispid;
00125     HRESULT hr;
00126     VARIANTARG* pvarg = NULL;
00127   
00128     if (pdisp == NULL)
00129         return ResultFromScode(E_INVALIDARG);
00130     
00131     // Get DISPID of property/method
00132     hr = pdisp->GetIDsOfNames(IID_NULL, &pszName, 1, LOCALE_USER_DEFAULT, &dispid);
00133     if(FAILED(hr))
00134         return hr;
00135                
00136     DISPPARAMS dispparams;
00137     _fmemset(&dispparams, 0, sizeof dispparams);
00138 
00139     // determine number of arguments
00140     if (pszFmt != NULL)
00141         countArgsInFormat(pszFmt, &dispparams.cArgs);
00142     
00143     // Property puts have a named argument that represents the value that the property is
00144     // being assigned.
00145     DISPID dispidNamed = DISPID_PROPERTYPUT;
00146     if (wFlags & DISPATCH_PROPERTYPUT)
00147     {
00148         if (dispparams.cArgs == 0)
00149             return ResultFromScode(E_INVALIDARG);
00150         dispparams.cNamedArgs = 1;
00151         dispparams.rgdispidNamedArgs = &dispidNamed;
00152     }
00153 
00154     if (dispparams.cArgs != 0)
00155     {
00156         // allocate memory for all VARIANTARG parameters
00157         pvarg = new VARIANTARG[dispparams.cArgs];
00158         if(pvarg == NULL)
00159             return ResultFromScode(E_OUTOFMEMORY);   
00160         dispparams.rgvarg = pvarg;
00161         _fmemset(pvarg, 0, sizeof(VARIANTARG) * dispparams.cArgs);
00162 
00163         // get ready to walk vararg list
00164         LPCTSTR psz = pszFmt;
00165         pvarg += dispparams.cArgs - 1;   // params go in opposite order
00166         
00167         while (psz = getNextVarType(psz, &pvarg->vt))
00168         {
00169             if (pvarg < dispparams.rgvarg)
00170             {
00171                 hr = ResultFromScode(E_INVALIDARG);
00172                 goto cleanup;  
00173             }
00174             switch (pvarg->vt)
00175             {
00176             case VT_I2:
00177                 V_I2(pvarg) = va_arg(argList, short);
00178                 break;
00179             case VT_I4:
00180                 V_I4(pvarg) = va_arg(argList, long);
00181                 break;
00182             case VT_R4:
00183                 V_R4(pvarg) = va_arg(argList, float);
00184                 break; 
00185             case VT_DATE:
00186             case VT_R8:
00187                 V_R8(pvarg) = va_arg(argList, double);
00188                 break;
00189             case VT_CY:
00190                 V_CY(pvarg) = va_arg(argList, CY);
00191                 break;
00192             case VT_BSTR:
00193                 V_BSTR(pvarg) = SysAllocString(va_arg(argList, OLECHAR FAR*));
00194                 if (pvarg->bstrVal == NULL) 
00195                 {
00196                     hr = ResultFromScode(E_OUTOFMEMORY);  
00197                     pvarg->vt = VT_EMPTY;
00198                     goto cleanup;  
00199                 }
00200                 break;
00201             case VT_DISPATCH:
00202                 V_DISPATCH(pvarg) = va_arg(argList, LPDISPATCH);
00203                 break;
00204             case VT_ERROR:
00205                 V_ERROR(pvarg) = va_arg(argList, SCODE);
00206                 break;
00207             case VT_BOOL:
00208                 V_BOOL(pvarg) = va_arg(argList, BOOL) ? -1 : 0;
00209                 break;
00210             case VT_VARIANT:
00211                 *pvarg = va_arg(argList, VARIANTARG); 
00212                 break;
00213             case VT_UNKNOWN:
00214                 V_UNKNOWN(pvarg) = va_arg(argList, LPUNKNOWN);
00215                 break;
00216 
00217             case VT_I2|VT_BYREF:
00218                 V_I2REF(pvarg) = va_arg(argList, short FAR*);
00219                 break;
00220             case VT_I4|VT_BYREF:
00221                 V_I4REF(pvarg) = va_arg(argList, long FAR*);
00222                 break;
00223             case VT_R4|VT_BYREF:
00224                 V_R4REF(pvarg) = va_arg(argList, float FAR*);
00225                 break;
00226             case VT_R8|VT_BYREF:
00227                 V_R8REF(pvarg) = va_arg(argList, double FAR*);
00228                 break;
00229             case VT_DATE|VT_BYREF:
00230                 V_DATEREF(pvarg) = va_arg(argList, DATE FAR*);
00231                 break;
00232             case VT_CY|VT_BYREF:
00233                 V_CYREF(pvarg) = va_arg(argList, CY FAR*);
00234                 break;
00235             case VT_BSTR|VT_BYREF:
00236                 V_BSTRREF(pvarg) = va_arg(argList, BSTR FAR*);
00237                 break;
00238             case VT_DISPATCH|VT_BYREF:
00239                 V_DISPATCHREF(pvarg) = va_arg(argList, LPDISPATCH FAR*);
00240                 break;
00241             case VT_ERROR|VT_BYREF:
00242                 V_ERRORREF(pvarg) = va_arg(argList, SCODE FAR*);
00243                 break;
00244             case VT_BOOL|VT_BYREF: 
00245                 {
00246                     BOOL FAR* pbool = va_arg(argList, BOOL FAR*);
00247                     *pbool = 0;
00248                     V_BOOLREF(pvarg) = (VARIANT_BOOL FAR*)pbool;
00249                 } 
00250                 break;              
00251             case VT_VARIANT|VT_BYREF: 
00252                 V_VARIANTREF(pvarg) = va_arg(argList, VARIANTARG FAR*);
00253                 break;
00254             case VT_UNKNOWN|VT_BYREF:
00255                 V_UNKNOWNREF(pvarg) = va_arg(argList, LPUNKNOWN FAR*);
00256                 break;
00257 
00258             default:
00259                 {
00260                     hr = ResultFromScode(E_INVALIDARG);
00261                     goto cleanup;  
00262                 }
00263                 break;
00264             }
00265 
00266             --pvarg; // get ready to fill next argument
00267         } //while
00268     } //if
00269     
00270     // Initialize return variant, in case caller forgot. Caller can pass NULL if return
00271     // value is not expected.
00272     if (pvRet)
00273         VariantInit(pvRet); 
00274     // make the call 
00275         try {
00276                 hr = pdisp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, wFlags,
00277                         &dispparams, pvRet, pexcepinfo, pnArgErr);
00278         }
00279         catch (...) {
00280                 hr = E_FAIL;
00281         }
00282 
00283 cleanup:
00284     // cleanup any arguments that need cleanup
00285     if (dispparams.cArgs != 0)
00286     {
00287         VARIANTARG FAR* pvarg = dispparams.rgvarg;
00288         UINT cArgs = dispparams.cArgs;   
00289         
00290         while (cArgs--)
00291         {
00292             switch (pvarg->vt)
00293             {
00294             case VT_BSTR:
00295                 VariantClear(pvarg);
00296                 break;
00297             }
00298             ++pvarg;
00299         }
00300     }
00301 //    delete dispparams.rgvarg;
00302     va_end(argList);
00303     return hr;   
00304 }   
00305 
00306 HRESULT 
00307 OLE::countArgsInFormat(LPCTSTR pszFmt, UINT FAR *pn)
00308 {
00309     *pn = 0;
00310 
00311     if(pszFmt == NULL)
00312       return NOERROR;
00313     
00314     while (*pszFmt)  
00315     {
00316        if (*pszFmt == '&')
00317            pszFmt++;
00318 
00319        switch(*pszFmt)
00320        {
00321            case 'b':
00322            case 'i': 
00323            case 'I':
00324            case 'r': 
00325            case 'R':
00326            case 'c':
00327            case 's':
00328            case 'e':
00329            case 'd':
00330            case 'v':
00331            case 'D':
00332            case 'U':
00333                ++*pn; 
00334                pszFmt++;
00335                break;
00336            case '\0':  
00337            default:
00338                return ResultFromScode(E_INVALIDARG);   
00339         }
00340     }
00341     return NOERROR;
00342 }
00343 
00344 
00345 LPCTSTR 
00346 OLE::getNextVarType(LPCTSTR pszFmt, VARTYPE FAR* pvt)
00347 {   
00348     *pvt = 0;
00349     if (*pszFmt == '&') 
00350     {
00351          *pvt = VT_BYREF; 
00352          pszFmt++;    
00353          if (!*pszFmt)
00354              return NULL;    
00355     } 
00356     switch(*pszFmt)
00357     {
00358         case 'b':
00359             *pvt |= VT_BOOL;
00360             break;
00361         case 'i': 
00362             *pvt |= VT_I2;
00363             break;
00364         case 'I': 
00365             *pvt |= VT_I4;
00366             break;
00367         case 'r': 
00368             *pvt |= VT_R4;
00369             break;
00370         case 'R': 
00371             *pvt |= VT_R8;
00372             break;
00373         case 'c':
00374             *pvt |= VT_CY;
00375             break;
00376         case 's': 
00377             *pvt |= VT_BSTR;
00378             break;
00379         case 'e': 
00380             *pvt |= VT_ERROR;
00381             break;
00382         case 'd': 
00383             *pvt |= VT_DATE; 
00384             break;
00385         case 'v': 
00386             *pvt |= VT_VARIANT;
00387             break;
00388         case 'U': 
00389             *pvt |= VT_UNKNOWN; 
00390             break;
00391         case 'D': 
00392             *pvt |= VT_DISPATCH;
00393             break;  
00394         case '\0':
00395              return NULL;     // End of Format string
00396         default:
00397             return NULL;
00398     } 
00399     return ++pszFmt;  
00400 }
00401 

Generated on Mon Oct 7 09:33:29 2002 for Gaia by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001