Back to index

lightning-sunbird  0.9+nobinonly
nsXPCDispTestWrappedJS.cpp
Go to the documentation of this file.
00001 // nsXPCDispTestWrappedJS.cpp : Implementation of CXPCIDispatchTestApp and DLL registration.
00002 
00003 #include "stdafx.h"
00004 #include "XPCIDispatchTest.h"
00005 #include "nsXPCDispTestWrappedJS.h"
00006 #include <string>
00007 #include <sstream>
00008 
00010 //
00011 
00012 STDMETHODIMP nsXPCDispTestWrappedJS::InterfaceSupportsErrorInfo(REFIID riid)
00013 {
00014        static const IID* arr[] = 
00015        {
00016               &IID_nsIXPCDispTestWrappedJS,
00017        };
00018 
00019        for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
00020        {
00021               if (InlineIsEqualGUID(*arr[i],riid))
00022                      return S_OK;
00023        }
00024        return S_FALSE;
00025 }
00026 
00027 struct TestData
00028 {
00029     typedef bool (*CompFunc)(const _variant_t & left, const _variant_t & right);
00030     TestData(const char * name, const _variant_t & value, CompFunc cf) : 
00031         mName(name), mValue(value), mCompFunc(cf) {}
00032     const char * mName;
00033     _variant_t mValue;
00034     CompFunc mCompFunc;
00035     
00036 };
00037 
00038 bool CompareVariant(const _variant_t & left, const _variant_t & right)
00039 {
00040     return left == right;
00041 }
00042 
00043 // These should be a template but VC++6 is brain dead in this area
00044 #define CompareFunction(type)                                               \
00045 bool CompareVariant##type(const _variant_t & left, const _variant_t & right)     \
00046 {                                                                           \
00047     return static_cast<type>(left) == static_cast<type>(right);   \
00048 }
00049 
00050 CompareFunction(long);
00051 CompareFunction(float);
00052 CompareFunction(double);
00053 CompareFunction(_bstr_t);
00054 
00055 DISPID GetIDsOfNames(IDispatch * pIDispatch , char const * i_Method)
00056 {
00057     DISPID dispid;
00058     CComBSTR method(i_Method);
00059     OLECHAR * pMethod = method;
00060     HRESULT hresult = pIDispatch->GetIDsOfNames(
00061         IID_NULL,
00062         &pMethod,
00063         1, 
00064         LOCALE_SYSTEM_DEFAULT,
00065         &dispid);
00066     if (!SUCCEEDED(hresult))
00067     {
00068         dispid = 0;
00069     }
00070     return dispid;
00071 }
00072 
00073 namespace
00074 {
00075 
00076 inline
00077 _bstr_t ConvertVariantFromBSTR(_variant_t & variant)
00078 {
00079     VARIANT temp = variant;
00080     if (SUCCEEDED(VariantChangeType(&temp, &temp, 0, VT_BSTR)))
00081     {
00082         variant.Attach(temp);
00083         return static_cast<_bstr_t>(variant);
00084     }
00085     return "**Type Conversion failed";
00086 }
00087 
00088 std::string DispInvoke(IDispatch * obj, const TestData & testData)
00089 {
00090     // Perform a put on the property
00091     ITypeInfo * pTypeInfo;
00092     obj->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &pTypeInfo);
00093     DISPID dispID = ::GetIDsOfNames(obj, testData.mName);
00094     DISPPARAMS dispParams;
00095     dispParams.cArgs = 1;
00096     dispParams.rgvarg = const_cast<VARIANT*>(&reinterpret_cast<const VARIANT&>(testData.mValue));
00097     dispParams.cNamedArgs = 1;
00098     DISPID propPut = DISPID_PROPERTYPUT;
00099     dispParams.rgdispidNamedArgs = &propPut;
00100     _variant_t result1;
00101     HRESULT hResult = obj->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams, &result1, 0, 0);
00102     if (FAILED(hResult))
00103     {
00104         std::ostringstream msg;
00105         msg << "IDispatch::Invoke on " << testData.mName << " failed to set property with result " << hResult;
00106         return msg.str();
00107     }
00108     dispParams.cArgs = 1;
00109     dispParams.rgvarg = const_cast<VARIANT*>(&reinterpret_cast<const VARIANT&>(testData.mValue));
00110     dispParams.cNamedArgs = 0;
00111     dispParams.rgdispidNamedArgs = 0;
00112     _variant_t result2;
00113     hResult = obj->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &result2, 0, 0);
00114     if (FAILED(hResult))
00115     {
00116         std::ostringstream msg;
00117         msg << "IDispatch::Invoke on " << testData.mName << " failed to retrieve property with result " << hResult;
00118         return msg.str();
00119     }
00120     if (!testData.mCompFunc(result2,testData.mValue))
00121     {
00122         std::ostringstream msg;
00123         VARIANT temp = testData.mValue;
00124         char const * const desired = SUCCEEDED(VariantChangeType(&temp, &temp, 0, VT_BSTR)) ? 0 : "**Conversion Failed";
00125         char const * const actual = SUCCEEDED(VariantChangeType(&result2, &result2, 0, VT_BSTR)) ? 0 : "**Conversion Failed";
00126 
00127         msg << testData.mName << " ["
00128             << (desired ? desired : static_cast<char const *>(static_cast<_bstr_t>(testData.mValue))) << "] [" 
00129             << (actual ? actual : static_cast<char const *>(static_cast<_bstr_t>(result2))) << "]";
00130         return msg.str();
00131     }
00132     return std::string();
00133 }
00134 
00135 }
00136 
00137 STDMETHODIMP nsXPCDispTestWrappedJS::TestParamTypes(IDispatch *obj, BSTR *errMsg)
00138 {
00139     CComPtr<IDispatch> ptr;
00140     CComBSTR progID("XPCIDispatchTest.nsXPCDispSimple.1");
00141     ptr.CoCreateInstance(progID);
00142     _variant_t dispatchPtr;
00143     dispatchPtr = static_cast<IDispatch*>(ptr);
00144     CURRENCY currency;
00145     currency.int64 = 55555;
00146     _variant_t date(3000.0, VT_DATE);
00147     _variant_t nullVariant;
00148     nullVariant.ChangeType(VT_NULL);
00149     const TestData tests[] =
00150     {
00151         TestData("Boolean", _variant_t(true), CompareVariant),
00152         TestData("Short", _variant_t(short(4200)), reinterpret_cast<TestData::CompFunc>(CompareVariantlong)),
00153         TestData("Long", _variant_t(long(-42000000)), CompareVariantlong),
00154         TestData("Float", _variant_t(float(4.5)), CompareVariantfloat),
00155         TestData("Double", _variant_t(-11111.11), CompareVariant),
00156 //        TestData("Currency", _variant_t(currency), CompareVariantdouble),
00157         TestData("Date", date, CompareVariant_bstr_t),
00158         TestData("String", _variant_t("A String"), CompareVariant),
00159         TestData("DispatchPtr", dispatchPtr, CompareVariant),
00160 //        TestData("SCode", _variant_t(long(5), VT_ERROR), CompareVariant_bstr_t),
00161         TestData("Variant", nullVariant, CompareVariant),
00162         TestData("Char", _variant_t(BYTE('x')), CompareVariant_bstr_t)
00163     };
00164     std::string errors;
00165     for (size_t index = 0; index < sizeof(tests) / sizeof(TestData); ++index)
00166     {
00167         std::string msg = DispInvoke(obj, tests[index]);
00168         if (!msg.empty())
00169         {
00170             errors += msg;
00171             errors += "\r\n";
00172         }
00173     }
00174     CComBSTR errorMsg(errors.c_str());
00175     *errMsg = errorMsg.Detach();
00176     return S_OK;
00177 }