Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1035 lines
22 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: disputil.cxx
  7. //
  8. // Contents: Dispatch Utilities.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 21-Feb-94 adams Created
  15. // 08-Apr-94 DonCl modified Set/GetDispProp to take REFIID
  16. // to meet sysmgmt needs
  17. // 25-Oct-94 KrishnaG appropriated from the ADs project
  18. //
  19. //----------------------------------------------------------------------------
  20. #include "procs.hxx"
  21. #define VT_TYPEMASK 0x3ff
  22. static HRESULT VARIANTARGToCVar(VARIANTARG * pvarg, VARTYPE vt, void* pv);
  23. static void CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg);
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: FreeEXCEPINFO
  27. //
  28. // Synopsis: Frees resources in an excepinfo. Does not reinitialize
  29. // these fields.
  30. //
  31. //----------------------------------------------------------------------------
  32. void
  33. FreeEXCEPINFO(EXCEPINFO * pEI)
  34. {
  35. if (pEI)
  36. {
  37. ADsFreeString(pEI->bstrSource);
  38. ADsFreeString(pEI->bstrDescription);
  39. ADsFreeString(pEI->bstrHelpFile);
  40. }
  41. }
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Function: ValidateInvoke
  45. //
  46. // Synopsis: Validates arguments to a call of IDispatch::Invoke. A call
  47. // to this function takes less space than the function itself.
  48. //
  49. //----------------------------------------------------------------------------
  50. HRESULT
  51. ValidateInvoke(
  52. DISPPARAMS * pdispparams,
  53. VARIANT * pvarResult,
  54. EXCEPINFO * pexcepinfo,
  55. UINT * puArgErr)
  56. {
  57. if (pvarResult)
  58. VariantInit(pvarResult);
  59. if (pexcepinfo)
  60. InitEXCEPINFO(pexcepinfo);
  61. if (puArgErr)
  62. *puArgErr = 0;
  63. if (!pdispparams)
  64. RRETURN(E_INVALIDARG);
  65. return S_OK;
  66. }
  67. //+------------------------------------------------------------------------
  68. //
  69. // Function: LoadTypeInfo
  70. //
  71. // Synopsis: Loads a typeinfo from a registered typelib.
  72. //
  73. // Arguments: [clsidTL] -- TypeLib GUID
  74. // [clsidTI] -- TypeInfo GUID
  75. // [ppTI] -- Resulting typeInfo
  76. //
  77. // Returns: HRESULT
  78. //
  79. //-------------------------------------------------------------------------
  80. HRESULT
  81. LoadTypeInfo(CLSID clsidTL, CLSID clsidTI, LPTYPEINFO *ppTI)
  82. {
  83. HRESULT hr;
  84. ITypeLib * pTL;
  85. ADsAssert(ppTI);
  86. *ppTI = NULL;
  87. hr = LoadRegTypeLib(clsidTL, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTL);
  88. if (!SUCCEEDED(hr))
  89. RRETURN(hr);
  90. hr = pTL->GetTypeInfoOfGuid(clsidTI, ppTI);
  91. pTL->Release();
  92. RRETURN(hr);
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Function: VARIANTARGToCVar
  97. //
  98. // Synopsis: Converts a VARIANT to a C-language variable.
  99. //
  100. // Arguments: [pvarg] -- Variant to convert.
  101. // [vt] -- Type to convert to.
  102. // [pv] -- Location to place C-language variable.
  103. //
  104. // Modifies: [pv].
  105. //
  106. // Returns: HRESULT.
  107. //
  108. // History: 2-23-94 adams Created
  109. //
  110. // Notes: Supports all variant pointer types, VT_I2, VT_I4, VT_R4,
  111. // VT_R8.
  112. //----------------------------------------------------------------------------
  113. static HRESULT
  114. VARIANTARGToCVar(VARIANT * pvarg, VARTYPE vt, void * pv)
  115. {
  116. HRESULT hr = S_OK;
  117. VARIANTARG vargNew; // variant of new type
  118. ADsAssert(pvarg);
  119. ADsAssert(pv);
  120. ADsAssert((vt & ~VT_TYPEMASK) == 0 || (vt & ~VT_TYPEMASK) == VT_BYREF);
  121. if (vt & VT_BYREF)
  122. {
  123. if (V_VT(pvarg) != vt)
  124. {
  125. hr = DISP_E_TYPEMISMATCH;
  126. goto Cleanup;
  127. }
  128. // Use a supported pointer type for derefencing.
  129. vt = VT_UNKNOWN;
  130. vargNew = *pvarg;
  131. }
  132. else
  133. {
  134. VariantInit(&vargNew);
  135. hr = VariantChangeType(&vargNew, pvarg, 0, vt);
  136. if (hr)
  137. goto Cleanup;
  138. }
  139. switch (vt)
  140. {
  141. case VT_BOOL:
  142. if (V_BOOL(&vargNew) != VB_FALSE && V_BOOL(&vargNew) != VB_TRUE)
  143. {
  144. hr = E_FAIL; // BUGBUG: scode?
  145. goto Cleanup;
  146. }
  147. // convert VT_TRUE to TRUE
  148. *(BOOL *)pv = - V_BOOL(&vargNew);
  149. break;
  150. case VT_I2:
  151. *(short *)pv = V_I2(&vargNew);
  152. break;
  153. case VT_I4:
  154. *(long *)pv = V_I4(&vargNew);
  155. break;
  156. case VT_R4:
  157. *(float *)pv = V_R4(&vargNew);
  158. break;
  159. case VT_R8:
  160. *(double *)pv = V_R8(&vargNew);
  161. break;
  162. //
  163. // All Pointer types.
  164. //
  165. case VT_BSTR:
  166. case VT_LPSTR:
  167. case VT_LPWSTR:
  168. case VT_DISPATCH:
  169. case VT_UNKNOWN:
  170. *(void **)pv = V_BYREF(&vargNew);
  171. break;
  172. default:
  173. ADsAssert(FALSE && "Unknown type in VARIANTARGToCVar().\n");
  174. break;
  175. }
  176. Cleanup:
  177. RRETURN(hr);
  178. }
  179. //+---------------------------------------------------------------------------
  180. //
  181. // Function: CVarToVARIANTARG
  182. //
  183. // Synopsis: Converts a C-language variable to a VARIANT.
  184. //
  185. // Arguments: [pv] -- Pointer to C-language variable.
  186. // [vt] -- Type of C-language variable.
  187. // [pvarg] -- Resulting VARIANT. Must be initialized by caller.
  188. // Any contents will be freed.
  189. //
  190. // Modifies: [pvarg]
  191. //
  192. // History: 2-23-94 adams Created
  193. //
  194. // Notes: Supports all variant pointer types, VT_UI2, VT_I2, VT_UI4,
  195. // VT_I4, VT_R4, VT_R8.
  196. //
  197. //----------------------------------------------------------------------------
  198. static void
  199. CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg)
  200. {
  201. ADsAssert(pv);
  202. ADsAssert(pvarg);
  203. VariantClear(pvarg);
  204. V_VT(pvarg) = vt;
  205. if (V_ISBYREF(pvarg))
  206. {
  207. // Use a supported pointer type for derefencing.
  208. vt = VT_UNKNOWN;
  209. }
  210. switch (vt)
  211. {
  212. case VT_BOOL:
  213. // convert TRUE to VT_TRUE
  214. ADsAssert(*(BOOL *) pv == 1 || *(BOOL *) pv == 0);
  215. V_BOOL(pvarg) = VARIANT_BOOL(-*(BOOL *) pv);
  216. break;
  217. case VT_I2:
  218. V_I2(pvarg) = *(short *) pv;
  219. break;
  220. case VT_I4:
  221. V_I4(pvarg) = *(long *) pv;
  222. break;
  223. case VT_R4:
  224. V_R4(pvarg) = *(float *) pv;
  225. break;
  226. case VT_R8:
  227. V_R8(pvarg) = *(double *) pv;
  228. break;
  229. //
  230. // All Pointer types.
  231. //
  232. case VT_BSTR:
  233. case VT_LPSTR:
  234. case VT_LPWSTR:
  235. case VT_DISPATCH:
  236. case VT_UNKNOWN:
  237. V_BYREF(pvarg) = *(long **)pv;
  238. break;
  239. default:
  240. Assert(FALSE && "Unknown type.");
  241. break;
  242. }
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Function: CParamsToDispParams
  247. //
  248. // Synopsis: Converts a C parameter list to a dispatch parameter list.
  249. //
  250. // Arguments: [pDispParams] -- Resulting dispatch parameter list.
  251. // Note that the rgvarg member of pDispParams
  252. // must be initialized with an array of
  253. // EVENTPARAMS_MAX VARIANTs.
  254. //
  255. // [pvt] -- List of C parameter types. May be NULL.
  256. // If not NULL, Last elem in list MUST be
  257. // VT_EMPTY.
  258. //
  259. // [va] -- List of C arguments.
  260. //
  261. // Modifies: [pDispParams]
  262. //
  263. // History: 05-Jan-94 adams Created
  264. // 23-Feb-94 adams Reversed order of disp arguments, added
  265. // support for VT_R4, VT_R8, and pointer
  266. // types.
  267. //
  268. // Notes: Only types VT_I2,VT_I4, and VT_UNKNOWN are supported.
  269. //
  270. //----------------------------------------------------------------------------
  271. void
  272. CParamsToDispParams(
  273. DISPPARAMS * pDispParams,
  274. VARTYPE * pvt,
  275. va_list va)
  276. {
  277. ADsAssert(pDispParams);
  278. ADsAssert(pDispParams->rgvarg);
  279. VARIANTARG * pvargCur; // current variant
  280. VARTYPE * pvtCur; // current vartype
  281. // Assign vals to dispatch param list.
  282. pDispParams->cNamedArgs = 0;
  283. pDispParams->rgdispidNamedArgs = NULL;
  284. // Get count of arguments.
  285. if (!pvt)
  286. {
  287. pDispParams->cArgs = 0;
  288. return;
  289. }
  290. for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
  291. ;
  292. pDispParams->cArgs = pvtCur - pvt;
  293. ADsAssert(pDispParams->cArgs < EVENTPARAMS_MAX);
  294. //
  295. // Convert each C-param to a dispparam. Note that the order of dispatch
  296. // parameters is the reverse of the order of c-params.
  297. //
  298. ADsAssert(pDispParams->rgvarg);
  299. pvargCur = pDispParams->rgvarg + pDispParams->cArgs;
  300. for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
  301. {
  302. pvargCur--;
  303. ADsAssert(pvargCur >= pDispParams->rgvarg);
  304. V_VT(pvargCur) = *pvtCur;
  305. if ((*pvtCur & VT_BYREF) == VT_BYREF)
  306. {
  307. V_BYREF(pvargCur) = va_arg(va, long *);
  308. }
  309. else
  310. {
  311. switch (*pvtCur)
  312. {
  313. case VT_BOOL:
  314. // convert TRUE to VT_TRUE
  315. V_BOOL(pvargCur) = VARIANT_BOOL(-va_arg(va, BOOL));
  316. ADsAssert(V_BOOL(pvargCur) == VB_FALSE ||
  317. V_BOOL(pvargCur) == VB_TRUE);
  318. break;
  319. case VT_I2:
  320. V_I2(pvargCur) = va_arg(va, short);
  321. break;
  322. case VT_I4:
  323. V_I4(pvargCur) = va_arg(va, long);
  324. break;
  325. case VT_R4:
  326. V_R4(pvargCur) = va_arg(va, float);
  327. break;
  328. case VT_R8:
  329. V_R8(pvargCur) = va_arg(va, double);
  330. break;
  331. //
  332. // All Pointer types.
  333. //
  334. case VT_BSTR:
  335. case VT_LPSTR:
  336. case VT_LPWSTR:
  337. case VT_DISPATCH:
  338. case VT_UNKNOWN:
  339. V_BYREF(pvargCur) = va_arg(va, long *);
  340. break;
  341. default:
  342. Assert(FALSE && "Unknown type.\n");
  343. }
  344. }
  345. }
  346. }
  347. //+---------------------------------------------------------------------------
  348. //
  349. // Function: DispParamsToCParams
  350. //
  351. // Synopsis: Converts Dispatch::Invoke method params to C-language params.
  352. //
  353. // Arguments: [pDP] -- Dispatch params to be converted.
  354. // [pvt] -- Array of types of C-params. May be NULL. If
  355. // non-NULL, last element must be VT_EMPTY.
  356. // [...] -- List of pointers to c-params to be converted to.
  357. //
  358. // Returns: HRESULT.
  359. //
  360. // History: 2-23-94 adams Created
  361. //
  362. // Notes: Supports types listed in VARIANTToCParam.
  363. //
  364. //----------------------------------------------------------------------------
  365. STDAPI
  366. DispParamsToCParams(
  367. DISPPARAMS * pDP,
  368. UINT * puArgErr,
  369. VARTYPE * pvt,
  370. ...)
  371. {
  372. HRESULT hr;
  373. va_list va; // list of pointers to c-params.
  374. VARTYPE * pvtCur; // current VARTYPE of c-param.
  375. VARIANTARG * pvargCur; // current VARIANT being converted.
  376. void * pv; // current c-param being converted.
  377. int cArgs; // count of arguments.
  378. ADsAssert(pDP);
  379. hr = S_OK;
  380. va_start(va, pvt);
  381. if (!pvt)
  382. {
  383. if (pDP->cArgs > 0)
  384. goto BadParamCountError;
  385. goto Cleanup;
  386. }
  387. pvargCur = pDP->rgvarg + pDP->cArgs - 1;
  388. pvtCur = pvt;
  389. for (cArgs = 0; cArgs < (int)pDP->cArgs; cArgs++)
  390. {
  391. if (*pvtCur == VT_EMPTY)
  392. goto BadParamCountError;
  393. pv = va_arg(va, void *);
  394. hr = VARIANTARGToCVar(pvargCur, *pvtCur, pv);
  395. if (hr)
  396. {
  397. if (puArgErr)
  398. *puArgErr = cArgs;
  399. goto Cleanup;
  400. }
  401. pvargCur--;
  402. pvtCur++;
  403. }
  404. if (*pvtCur != VT_EMPTY)
  405. goto BadParamCountError;
  406. Cleanup:
  407. va_end(va);
  408. RRETURN(hr);
  409. BadParamCountError:
  410. hr = DISP_E_BADPARAMCOUNT;
  411. goto Cleanup;
  412. }
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Function: GetDispProp
  416. //
  417. // Synopsis: Gets a property of an object.
  418. //
  419. // Arguments: [pDisp] -- The object containing the property.
  420. // [dispid] -- The ID of the property.
  421. // [riid] -- interface of object desired
  422. // [lcid] -- The locale of the object.
  423. // [pvar] -- The resulting property. Must be initialized.
  424. //
  425. // Returns: HRESULT.
  426. //
  427. // Modifies: [pvarg].
  428. //
  429. // History: 23-Feb-94 adams Created
  430. // 08-Apr-94 DonCl modified to take REFIID
  431. //
  432. //----------------------------------------------------------------------------
  433. HRESULT
  434. GetDispProp(
  435. IDispatch * pDisp,
  436. DISPID dispid,
  437. REFIID riid,
  438. LCID lcid,
  439. VARIANT * pvar,
  440. EXCEPINFO * pexcepinfo)
  441. {
  442. HRESULT hr;
  443. DISPPARAMS dp; // Params for IDispatch::Invoke.
  444. UINT uiErr; // Argument error.
  445. ADsAssert(pDisp);
  446. ADsAssert(pvar);
  447. dp.rgvarg = NULL;
  448. dp.rgdispidNamedArgs = NULL;
  449. dp.cArgs = 0;
  450. dp.cNamedArgs = 0;
  451. hr = pDisp->Invoke(
  452. dispid,
  453. riid,
  454. lcid,
  455. DISPATCH_PROPERTYGET,
  456. &dp,
  457. pvar,
  458. pexcepinfo,
  459. &uiErr);
  460. RRETURN(hr);
  461. }
  462. //+---------------------------------------------------------------------------
  463. //
  464. // Function: SetDispProp
  465. //
  466. // Synopsis: Sets a property on an object.
  467. //
  468. // Arguments: [pDisp] -- The object to set the property on.
  469. // [dispid] -- The ID of the property.
  470. // [riid] -- interface of object
  471. // [lcid] -- The locale of the property.
  472. // [pvarg] -- The value to set.
  473. //
  474. // Returns: HRESULT.
  475. //
  476. // History: 23-Feb-94 adams Created
  477. // 08-Apr-94 DonCl modified to take REFIID
  478. //
  479. //----------------------------------------------------------------------------
  480. HRESULT
  481. SetDispProp(
  482. IDispatch * pDisp,
  483. DISPID dispid,
  484. REFIID riid,
  485. LCID lcid,
  486. VARIANTARG * pvarg,
  487. EXCEPINFO * pexcepinfo)
  488. {
  489. HRESULT hr;
  490. DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
  491. DISPPARAMS dp; // Params for Invoke
  492. UINT uiErr; // Invoke error param.
  493. ADsAssert(pDisp);
  494. ADsAssert(pvarg);
  495. dp.rgvarg = pvarg;
  496. dp.rgdispidNamedArgs = &dispidPut;
  497. dp.cArgs = 1;
  498. dp.cNamedArgs = 1;
  499. hr = pDisp->Invoke(
  500. dispid,
  501. riid,
  502. lcid,
  503. DISPATCH_PROPERTYPUT,
  504. &dp,
  505. NULL,
  506. pexcepinfo,
  507. &uiErr);
  508. RRETURN(hr);
  509. }
  510. //+---------------------------------------------------------------------------
  511. //
  512. // Function: GetDispPropOfType
  513. //
  514. // Synopsis: Gets a property from an object, and converts it to a c
  515. // variable.
  516. //
  517. // Arguments: [pDisp] -- The object to retrieve the property from.
  518. // [dispid] -- Property ID.
  519. // [lcid] -- Locale of property.
  520. // [vt] -- Type of c-variable to receive property.
  521. // [pv] -- Pointer to resulting c-variable.
  522. //
  523. // Returns: HRESULT.
  524. //
  525. // Modifies: [pv].
  526. //
  527. // History: 2-23-94 adams Created
  528. //
  529. // Notes: Supports variable types found in VARIANTARGToCVar.
  530. //
  531. //----------------------------------------------------------------------------
  532. HRESULT
  533. GetDispPropOfType(
  534. IDispatch * pDisp,
  535. DISPID dispid,
  536. LCID lcid,
  537. VARTYPE vt,
  538. void * pv)
  539. {
  540. HRESULT hr;
  541. VARIANT varProp; // Property retrieved.
  542. DISPPARAMS dp; // Params for IDispatch::Invoke.
  543. ADsAssert(pDisp);
  544. ADsAssert(pv);
  545. dp.rgvarg = NULL;
  546. dp.rgdispidNamedArgs = NULL;
  547. dp.cArgs = 0;
  548. dp.cNamedArgs = 0;
  549. VariantInit(&varProp);
  550. hr = pDisp->Invoke(
  551. dispid,
  552. IID_NULL,
  553. lcid,
  554. DISPATCH_PROPERTYGET,
  555. &dp,
  556. &varProp,
  557. NULL,
  558. NULL);
  559. if (hr)
  560. goto Cleanup;
  561. hr = VARIANTARGToCVar(&varProp, vt, pv);
  562. Cleanup:
  563. RRETURN(hr);
  564. }
  565. //+---------------------------------------------------------------------------
  566. //
  567. // Function: SetDispPropOfType
  568. //
  569. // Synopsis: Sets a property on an object.
  570. //
  571. // Arguments: [pDisp] -- Object to set property on.
  572. // [dispid] -- Property ID to set.
  573. // [lcid] -- Locale of property.
  574. // [vt] -- Type of property to set.
  575. // [pv] -- Pointer to property value.
  576. //
  577. // Returns: HRESULT.
  578. //
  579. // History: 2-23-94 adams Created
  580. //
  581. // Notes: Supports types found in VARIANTARGToCVar.
  582. //
  583. //----------------------------------------------------------------------------
  584. HRESULT
  585. SetDispPropOfType(
  586. IDispatch * pDisp,
  587. DISPID dispid,
  588. LCID lcid,
  589. VARTYPE vt,
  590. void * pv)
  591. {
  592. HRESULT hr;
  593. VARIANTARG varg; // Variant property to put.
  594. DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
  595. DISPPARAMS dp; // Params for Invoke
  596. ADsAssert(pDisp);
  597. ADsAssert(pv);
  598. VariantInit(&varg);
  599. CVarToVARIANTARG(pv, vt, &varg);
  600. dp.rgvarg = &varg;
  601. dp.rgdispidNamedArgs = &dispidPut;
  602. dp.cArgs = 1;
  603. dp.cNamedArgs = 1;
  604. hr = pDisp->Invoke(
  605. dispid,
  606. IID_NULL,
  607. lcid,
  608. DISPATCH_PROPERTYPUT,
  609. &dp,
  610. NULL,
  611. NULL,
  612. NULL);
  613. RRETURN(hr);
  614. }
  615. //+---------------------------------------------------------------------------
  616. //
  617. // Function: CallDispMethod
  618. //
  619. // Synopsis: Calls a late-bound method on a object via IDispatch::Invoke.
  620. //
  621. // Arguments: [pDisp] -- Object to call method on.
  622. // [dispid] -- Method ID.
  623. // [lcid] -- Locale of method.
  624. // [vtReturn] -- Type of return value. If no return value,
  625. // must be VT_VOID.
  626. // [pvReturn] -- Location of return value. If no return value,
  627. // must be NULL.
  628. // [pvtParams] -- List of param types. May be NULL. If
  629. // non-NULL, last entry must be VT_EMPTY.
  630. // [...] -- List of params.
  631. //
  632. // Returns: HRESULT.
  633. //
  634. // History: 2-23-94 adams Created
  635. //
  636. //----------------------------------------------------------------------------
  637. HRESULT
  638. CallDispMethod(
  639. IDispatch * pDisp,
  640. DISPID dispid,
  641. LCID lcid,
  642. VARTYPE vtReturn,
  643. void * pvReturn,
  644. VARTYPE * pvtParams,
  645. ...)
  646. {
  647. HRESULT hr;
  648. VARIANTARG av[EVENTPARAMS_MAX]; // List of args for Invoke.
  649. DISPPARAMS dp; // Params for Invoke.
  650. VARIANT varReturn; // Return value.
  651. va_list va; // List of C-params.
  652. ADsAssert(pDisp);
  653. ADsAssert((vtReturn != VT_VOID) == (pvReturn != NULL));
  654. va_start(va, pvtParams);
  655. dp.rgvarg = av;
  656. CParamsToDispParams(&dp, pvtParams, va);
  657. va_end(va);
  658. if (pvReturn)
  659. VariantInit(&varReturn);
  660. hr = pDisp->Invoke(
  661. dispid,
  662. IID_NULL,
  663. lcid,
  664. DISPATCH_METHOD,
  665. &dp,
  666. pvReturn ? &varReturn : NULL,
  667. NULL,
  668. NULL);
  669. if (hr)
  670. goto Cleanup;
  671. if (pvReturn)
  672. hr = VARIANTARGToCVar(&varReturn, vtReturn, pvReturn);
  673. Cleanup:
  674. RRETURN(hr);
  675. }
  676. //+------------------------------------------------------------------------
  677. //
  678. // Function: IsVariantEqual, public API
  679. //
  680. // Synopsis: Compares the values of two VARIANTARGs.
  681. //
  682. // Arguments: [pvar1], [pvar2] -- VARIANTARGs to compare.
  683. //
  684. // Returns: TRUE if equal, FALSE if not.
  685. //
  686. // History: 18-Mar-93 SumitC Created.
  687. // 11-May-94 SumitC don't assert for VT_UNKNOWN
  688. //
  689. // Notes: Variant type unequal returns FALSE, even if actual values
  690. // are the same.
  691. // Currently does I2, I4, R4, R8, CY, BSTR, BOOL
  692. // Returns FALSE for all other VariantTypes.
  693. //
  694. //-------------------------------------------------------------------------
  695. BOOL
  696. IsVariantEqual( VARIANTARG FAR* pvar1, VARIANTARG FAR* pvar2 )
  697. {
  698. if( V_VT(pvar1) != V_VT(pvar2) )
  699. return FALSE;
  700. switch (V_VT(pvar1))
  701. {
  702. case VT_EMPTY :
  703. case VT_NULL:
  704. return TRUE; // just the types being equal is good enough
  705. case VT_I2 :
  706. return (V_I2(pvar1) == V_I2(pvar2));
  707. case VT_I4 :
  708. return (V_I4(pvar1) == V_I4(pvar2));
  709. case VT_R4 :
  710. return (V_R4(pvar1) == V_R4(pvar2));
  711. case VT_R8 :
  712. return (V_R8(pvar1) == V_R8(pvar2));
  713. case VT_CY :
  714. return !memcmp(&V_CY(pvar1), &V_CY(pvar2), sizeof(CY));
  715. case VT_BSTR :
  716. return !ADsStringCmp(V_BSTR(pvar1), V_BSTR(pvar2));
  717. case VT_BOOL :
  718. return (V_BOOL(pvar1) == V_BOOL(pvar2));
  719. case VT_UNKNOWN:
  720. // returns FALSE unless the objects are the same
  721. return (V_UNKNOWN(pvar1) == V_UNKNOWN(pvar2));
  722. default:
  723. ADsAssert(0 && "Type not handled");
  724. break;
  725. };
  726. return(FALSE);
  727. }