Leaked source code of windows server 2003
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.

1276 lines
33 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: 25-Oct-94 KrishnaG appropriated from the ADs project
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "procs.hxx"
  18. #define VT_TYPEMASK 0x3ff
  19. #define BAIL_ON_FAILURE(hr) \
  20. if (FAILED(hr)) { \
  21. goto error; \
  22. }
  23. #define CONTINUE_ON_FAILURE(hr) \
  24. if (FAILED(hr)) { \
  25. continue; \
  26. }
  27. HMODULE g_hActiveDs = NULL; // Module handle of activeds.dll. This should be
  28. // initialized when the provider module is loaded
  29. // into a process' address space. The handle
  30. // is used by FillExcepInfo to retrieve error
  31. // description strings from activeds.dll.
  32. static HRESULT VARIANTARGToCVar(VARIANTARG * pvarg, VARTYPE vt, void* pv);
  33. static void CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg);
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Function: FreeEXCEPINFO
  37. //
  38. // Synopsis: Frees resources in an excepinfo. Does not reinitialize
  39. // these fields.
  40. //
  41. //----------------------------------------------------------------------------
  42. void
  43. FreeEXCEPINFO(EXCEPINFO * pEI)
  44. {
  45. if (pEI)
  46. {
  47. ADsFreeString(pEI->bstrSource);
  48. ADsFreeString(pEI->bstrDescription);
  49. ADsFreeString(pEI->bstrHelpFile);
  50. }
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Function: ValidateInvoke
  55. //
  56. // Synopsis: Validates arguments to a call of IDispatch::Invoke. A call
  57. // to this function takes less space than the function itself.
  58. //
  59. //----------------------------------------------------------------------------
  60. HRESULT
  61. ValidateInvoke(
  62. DISPPARAMS * pdispparams,
  63. VARIANT * pvarResult,
  64. EXCEPINFO * pexcepinfo,
  65. UINT * puArgErr)
  66. {
  67. if (pvarResult)
  68. VariantInit(pvarResult);
  69. if (pexcepinfo)
  70. InitEXCEPINFO(pexcepinfo);
  71. if (puArgErr)
  72. *puArgErr = 0;
  73. if (!pdispparams)
  74. RRETURN(E_INVALIDARG);
  75. return S_OK;
  76. }
  77. //+---------------------------------------------------------------------------
  78. //
  79. // Function: VARIANTARGToCVar
  80. //
  81. // Synopsis: Converts a VARIANT to a C-language variable.
  82. //
  83. // Arguments: [pvarg] -- Variant to convert.
  84. // [vt] -- Type to convert to.
  85. // [pv] -- Location to place C-language variable.
  86. //
  87. // Modifies: [pv].
  88. //
  89. // Returns: HRESULT.
  90. //
  91. // History: 2-23-94 adams Created
  92. //
  93. // Notes: Supports all variant pointer types, VT_I2, VT_I4, VT_R4,
  94. // VT_R8.
  95. //----------------------------------------------------------------------------
  96. static HRESULT
  97. VARIANTARGToCVar(VARIANT * pvarg, VARTYPE vt, void * pv)
  98. {
  99. HRESULT hr = S_OK;
  100. VARIANTARG vargNew; // variant of new type
  101. ADsAssert(pvarg);
  102. ADsAssert(pv);
  103. ADsAssert((vt & ~VT_TYPEMASK) == 0 || (vt & ~VT_TYPEMASK) == VT_BYREF);
  104. if (vt & VT_BYREF)
  105. {
  106. if (V_VT(pvarg) != vt)
  107. {
  108. hr = DISP_E_TYPEMISMATCH;
  109. goto Cleanup;
  110. }
  111. // Use a supported pointer type for derefencing.
  112. vt = VT_UNKNOWN;
  113. vargNew = *pvarg;
  114. }
  115. else
  116. {
  117. VariantInit(&vargNew);
  118. hr = VariantChangeType(&vargNew, pvarg, 0, vt);
  119. if (hr)
  120. goto Cleanup;
  121. }
  122. switch (vt)
  123. {
  124. case VT_BOOL:
  125. if (V_BOOL(&vargNew) != VB_FALSE && V_BOOL(&vargNew) != VB_TRUE)
  126. {
  127. hr = E_FAIL;
  128. goto Cleanup;
  129. }
  130. // convert VT_TRUE to TRUE
  131. *(BOOL *)pv = - V_BOOL(&vargNew);
  132. break;
  133. case VT_I2:
  134. *(short *)pv = V_I2(&vargNew);
  135. break;
  136. case VT_I4:
  137. *(long *)pv = V_I4(&vargNew);
  138. break;
  139. case VT_R4:
  140. *(float *)pv = V_R4(&vargNew);
  141. break;
  142. case VT_R8:
  143. *(double *)pv = V_R8(&vargNew);
  144. break;
  145. //
  146. // All Pointer types.
  147. //
  148. case VT_BSTR:
  149. case VT_LPSTR:
  150. case VT_LPWSTR:
  151. case VT_DISPATCH:
  152. case VT_UNKNOWN:
  153. *(void **)pv = V_BYREF(&vargNew);
  154. break;
  155. default:
  156. ADsAssert(FALSE && "Unknown type in VARIANTARGToCVar().\n");
  157. break;
  158. }
  159. Cleanup:
  160. RRETURN(hr);
  161. }
  162. //+---------------------------------------------------------------------------
  163. //
  164. // Function: CVarToVARIANTARG
  165. //
  166. // Synopsis: Converts a C-language variable to a VARIANT.
  167. //
  168. // Arguments: [pv] -- Pointer to C-language variable.
  169. // [vt] -- Type of C-language variable.
  170. // [pvarg] -- Resulting VARIANT. Must be initialized by caller.
  171. // Any contents will be freed.
  172. //
  173. // Modifies: [pvarg]
  174. //
  175. // History: 2-23-94 adams Created
  176. //
  177. // Notes: Supports all variant pointer types, VT_UI2, VT_I2, VT_UI4,
  178. // VT_I4, VT_R4, VT_R8.
  179. //
  180. //----------------------------------------------------------------------------
  181. static void
  182. CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg)
  183. {
  184. ADsAssert(pv);
  185. ADsAssert(pvarg);
  186. VariantClear(pvarg);
  187. V_VT(pvarg) = vt;
  188. if (V_ISBYREF(pvarg))
  189. {
  190. // Use a supported pointer type for derefencing.
  191. vt = VT_UNKNOWN;
  192. }
  193. switch (vt)
  194. {
  195. case VT_BOOL:
  196. // convert TRUE to VT_TRUE
  197. ADsAssert(*(BOOL *) pv == 1 || *(BOOL *) pv == 0);
  198. V_BOOL(pvarg) = VARIANT_BOOL(-*(BOOL *) pv);
  199. break;
  200. case VT_I2:
  201. V_I2(pvarg) = *(short *) pv;
  202. break;
  203. case VT_I4:
  204. V_I4(pvarg) = *(long *) pv;
  205. break;
  206. case VT_R4:
  207. V_R4(pvarg) = *(float *) pv;
  208. break;
  209. case VT_R8:
  210. V_R8(pvarg) = *(double *) pv;
  211. break;
  212. //
  213. // All Pointer types.
  214. //
  215. case VT_BSTR:
  216. case VT_LPSTR:
  217. case VT_LPWSTR:
  218. case VT_DISPATCH:
  219. case VT_UNKNOWN:
  220. V_BYREF(pvarg) = *(long **)pv;
  221. break;
  222. default:
  223. Assert(FALSE && "Unknown type.");
  224. break;
  225. }
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Function: CParamsToDispParams
  230. //
  231. // Synopsis: Converts a C parameter list to a dispatch parameter list.
  232. //
  233. // Arguments: [pDispParams] -- Resulting dispatch parameter list.
  234. // Note that the rgvarg member of pDispParams
  235. // must be initialized with an array of
  236. // EVENTPARAMS_MAX VARIANTs.
  237. //
  238. // [pvt] -- List of C parameter types. May be NULL.
  239. // If not NULL, Last elem in list MUST be
  240. // VT_EMPTY.
  241. //
  242. // [va] -- List of C arguments.
  243. //
  244. // Modifies: [pDispParams]
  245. //
  246. // History: 05-Jan-94 adams Created
  247. // 23-Feb-94 adams Reversed order of disp arguments, added
  248. // support for VT_R4, VT_R8, and pointer
  249. // types.
  250. //
  251. // Notes: Only types VT_I2,VT_I4, and VT_UNKNOWN are supported.
  252. //
  253. //----------------------------------------------------------------------------
  254. void
  255. CParamsToDispParams(
  256. DISPPARAMS * pDispParams,
  257. VARTYPE * pvt,
  258. va_list va)
  259. {
  260. ADsAssert(pDispParams);
  261. ADsAssert(pDispParams->rgvarg);
  262. VARIANTARG * pvargCur; // current variant
  263. VARTYPE * pvtCur; // current vartype
  264. // Assign vals to dispatch param list.
  265. pDispParams->cNamedArgs = 0;
  266. pDispParams->rgdispidNamedArgs = NULL;
  267. // Get count of arguments.
  268. if (!pvt)
  269. {
  270. pDispParams->cArgs = 0;
  271. return;
  272. }
  273. for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
  274. ;
  275. pDispParams->cArgs = (DWORD)(pvtCur - pvt);
  276. ADsAssert(pDispParams->cArgs < EVENTPARAMS_MAX);
  277. //
  278. // Convert each C-param to a dispparam. Note that the order of dispatch
  279. // parameters is the reverse of the order of c-params.
  280. //
  281. ADsAssert(pDispParams->rgvarg);
  282. pvargCur = pDispParams->rgvarg + pDispParams->cArgs;
  283. for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
  284. {
  285. pvargCur--;
  286. ADsAssert(pvargCur >= pDispParams->rgvarg);
  287. V_VT(pvargCur) = *pvtCur;
  288. if ((*pvtCur & VT_BYREF) == VT_BYREF)
  289. {
  290. V_BYREF(pvargCur) = va_arg(va, long *);
  291. }
  292. else
  293. {
  294. switch (*pvtCur)
  295. {
  296. case VT_BOOL:
  297. // convert TRUE to VT_TRUE
  298. V_BOOL(pvargCur) = VARIANT_BOOL(-va_arg(va, BOOL));
  299. ADsAssert(V_BOOL(pvargCur) == VB_FALSE ||
  300. V_BOOL(pvargCur) == VB_TRUE);
  301. break;
  302. case VT_I2:
  303. V_I2(pvargCur) = va_arg(va, short);
  304. break;
  305. case VT_I4:
  306. V_I4(pvargCur) = va_arg(va, long);
  307. break;
  308. case VT_R4:
  309. V_R4(pvargCur) = va_arg(va, float);
  310. break;
  311. case VT_R8:
  312. V_R8(pvargCur) = va_arg(va, double);
  313. break;
  314. //
  315. // All Pointer types.
  316. //
  317. case VT_BSTR:
  318. case VT_LPSTR:
  319. case VT_LPWSTR:
  320. case VT_DISPATCH:
  321. case VT_UNKNOWN:
  322. V_BYREF(pvargCur) = va_arg(va, long *);
  323. break;
  324. default:
  325. Assert(FALSE && "Unknown type.\n");
  326. }
  327. }
  328. }
  329. }
  330. //+---------------------------------------------------------------------------
  331. //
  332. // Function: DispParamsToCParams
  333. //
  334. // Synopsis: Converts Dispatch::Invoke method params to C-language params.
  335. //
  336. // Arguments: [pDP] -- Dispatch params to be converted.
  337. // [pvt] -- Array of types of C-params. May be NULL. If
  338. // non-NULL, last element must be VT_EMPTY.
  339. // [...] -- List of pointers to c-params to be converted to.
  340. //
  341. // Returns: HRESULT.
  342. //
  343. // History: 2-23-94 adams Created
  344. //
  345. // Notes: Supports types listed in VARIANTToCParam.
  346. //
  347. //----------------------------------------------------------------------------
  348. STDAPI
  349. DispParamsToCParams(
  350. DISPPARAMS * pDP,
  351. UINT * puArgErr,
  352. VARTYPE * pvt,
  353. ...)
  354. {
  355. HRESULT hr;
  356. va_list va; // list of pointers to c-params.
  357. VARTYPE * pvtCur; // current VARTYPE of c-param.
  358. VARIANTARG * pvargCur; // current VARIANT being converted.
  359. void * pv; // current c-param being converted.
  360. int cArgs; // count of arguments.
  361. ADsAssert(pDP);
  362. hr = S_OK;
  363. va_start(va, pvt);
  364. if (!pvt)
  365. {
  366. if (pDP->cArgs > 0)
  367. goto BadParamCountError;
  368. goto Cleanup;
  369. }
  370. pvargCur = pDP->rgvarg + pDP->cArgs - 1;
  371. pvtCur = pvt;
  372. for (cArgs = 0; cArgs < (int)pDP->cArgs; cArgs++)
  373. {
  374. if (*pvtCur == VT_EMPTY)
  375. goto BadParamCountError;
  376. pv = va_arg(va, void *);
  377. hr = VARIANTARGToCVar(pvargCur, *pvtCur, pv);
  378. if (hr)
  379. {
  380. if (puArgErr)
  381. *puArgErr = cArgs;
  382. goto Cleanup;
  383. }
  384. pvargCur--;
  385. pvtCur++;
  386. }
  387. if (*pvtCur != VT_EMPTY)
  388. goto BadParamCountError;
  389. Cleanup:
  390. va_end(va);
  391. RRETURN(hr);
  392. BadParamCountError:
  393. hr = DISP_E_BADPARAMCOUNT;
  394. goto Cleanup;
  395. }
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Function: GetDispProp
  399. //
  400. // Synopsis: Gets a property of an object.
  401. //
  402. // Arguments: [pDisp] -- The object containing the property.
  403. // [dispid] -- The ID of the property.
  404. // [riid] -- interface of object desired
  405. // [lcid] -- The locale of the object.
  406. // [pvar] -- The resulting property. Must be initialized.
  407. //
  408. // Returns: HRESULT.
  409. //
  410. // Modifies: [pvarg].
  411. //
  412. // History: 23-Feb-94 adams Created
  413. // 08-Apr-94 DonCl modified to take REFIID
  414. //
  415. //----------------------------------------------------------------------------
  416. HRESULT
  417. GetDispProp(
  418. IDispatch * pDisp,
  419. DISPID dispid,
  420. REFIID riid,
  421. LCID lcid,
  422. VARIANT * pvar,
  423. EXCEPINFO * pexcepinfo)
  424. {
  425. HRESULT hr;
  426. DISPPARAMS dp; // Params for IDispatch::Invoke.
  427. UINT uiErr; // Argument error.
  428. ADsAssert(pDisp);
  429. ADsAssert(pvar);
  430. dp.rgvarg = NULL;
  431. dp.rgdispidNamedArgs = NULL;
  432. dp.cArgs = 0;
  433. dp.cNamedArgs = 0;
  434. hr = pDisp->Invoke(
  435. dispid,
  436. riid,
  437. lcid,
  438. DISPATCH_PROPERTYGET,
  439. &dp,
  440. pvar,
  441. pexcepinfo,
  442. &uiErr);
  443. RRETURN(hr);
  444. }
  445. //+---------------------------------------------------------------------------
  446. //
  447. // Function: SetDispProp
  448. //
  449. // Synopsis: Sets a property on an object.
  450. //
  451. // Arguments: [pDisp] -- The object to set the property on.
  452. // [dispid] -- The ID of the property.
  453. // [riid] -- interface of object
  454. // [lcid] -- The locale of the property.
  455. // [pvarg] -- The value to set.
  456. //
  457. // Returns: HRESULT.
  458. //
  459. // History: 23-Feb-94 adams Created
  460. // 08-Apr-94 DonCl modified to take REFIID
  461. //
  462. //----------------------------------------------------------------------------
  463. HRESULT
  464. SetDispProp(
  465. IDispatch * pDisp,
  466. DISPID dispid,
  467. REFIID riid,
  468. LCID lcid,
  469. VARIANTARG * pvarg,
  470. EXCEPINFO * pexcepinfo)
  471. {
  472. HRESULT hr;
  473. DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
  474. DISPPARAMS dp; // Params for Invoke
  475. UINT uiErr; // Invoke error param.
  476. ADsAssert(pDisp);
  477. ADsAssert(pvarg);
  478. dp.rgvarg = pvarg;
  479. dp.rgdispidNamedArgs = &dispidPut;
  480. dp.cArgs = 1;
  481. dp.cNamedArgs = 1;
  482. hr = pDisp->Invoke(
  483. dispid,
  484. riid,
  485. lcid,
  486. DISPATCH_PROPERTYPUT,
  487. &dp,
  488. NULL,
  489. pexcepinfo,
  490. &uiErr);
  491. RRETURN(hr);
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Function: GetDispPropOfType
  496. //
  497. // Synopsis: Gets a property from an object, and converts it to a c
  498. // variable.
  499. //
  500. // Arguments: [pDisp] -- The object to retrieve the property from.
  501. // [dispid] -- Property ID.
  502. // [lcid] -- Locale of property.
  503. // [vt] -- Type of c-variable to receive property.
  504. // [pv] -- Pointer to resulting c-variable.
  505. //
  506. // Returns: HRESULT.
  507. //
  508. // Modifies: [pv].
  509. //
  510. // History: 2-23-94 adams Created
  511. //
  512. // Notes: Supports variable types found in VARIANTARGToCVar.
  513. //
  514. //----------------------------------------------------------------------------
  515. HRESULT
  516. GetDispPropOfType(
  517. IDispatch * pDisp,
  518. DISPID dispid,
  519. LCID lcid,
  520. VARTYPE vt,
  521. void * pv)
  522. {
  523. HRESULT hr;
  524. VARIANT varProp; // Property retrieved.
  525. DISPPARAMS dp; // Params for IDispatch::Invoke.
  526. ADsAssert(pDisp);
  527. ADsAssert(pv);
  528. dp.rgvarg = NULL;
  529. dp.rgdispidNamedArgs = NULL;
  530. dp.cArgs = 0;
  531. dp.cNamedArgs = 0;
  532. VariantInit(&varProp);
  533. hr = pDisp->Invoke(
  534. dispid,
  535. IID_NULL,
  536. lcid,
  537. DISPATCH_PROPERTYGET,
  538. &dp,
  539. &varProp,
  540. NULL,
  541. NULL);
  542. if (hr)
  543. goto Cleanup;
  544. hr = VARIANTARGToCVar(&varProp, vt, pv);
  545. Cleanup:
  546. RRETURN(hr);
  547. }
  548. //+---------------------------------------------------------------------------
  549. //
  550. // Function: SetDispPropOfType
  551. //
  552. // Synopsis: Sets a property on an object.
  553. //
  554. // Arguments: [pDisp] -- Object to set property on.
  555. // [dispid] -- Property ID to set.
  556. // [lcid] -- Locale of property.
  557. // [vt] -- Type of property to set.
  558. // [pv] -- Pointer to property value.
  559. //
  560. // Returns: HRESULT.
  561. //
  562. // History: 2-23-94 adams Created
  563. //
  564. // Notes: Supports types found in VARIANTARGToCVar.
  565. //
  566. //----------------------------------------------------------------------------
  567. HRESULT
  568. SetDispPropOfType(
  569. IDispatch * pDisp,
  570. DISPID dispid,
  571. LCID lcid,
  572. VARTYPE vt,
  573. void * pv)
  574. {
  575. HRESULT hr;
  576. VARIANTARG varg; // Variant property to put.
  577. DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
  578. DISPPARAMS dp; // Params for Invoke
  579. ADsAssert(pDisp);
  580. ADsAssert(pv);
  581. VariantInit(&varg);
  582. CVarToVARIANTARG(pv, vt, &varg);
  583. dp.rgvarg = &varg;
  584. dp.rgdispidNamedArgs = &dispidPut;
  585. dp.cArgs = 1;
  586. dp.cNamedArgs = 1;
  587. hr = pDisp->Invoke(
  588. dispid,
  589. IID_NULL,
  590. lcid,
  591. DISPATCH_PROPERTYPUT,
  592. &dp,
  593. NULL,
  594. NULL,
  595. NULL);
  596. RRETURN(hr);
  597. }
  598. //+---------------------------------------------------------------------------
  599. //
  600. // Function: CallDispMethod
  601. //
  602. // Synopsis: Calls a late-bound method on a object via IDispatch::Invoke.
  603. //
  604. // Arguments: [pDisp] -- Object to call method on.
  605. // [dispid] -- Method ID.
  606. // [lcid] -- Locale of method.
  607. // [vtReturn] -- Type of return value. If no return value,
  608. // must be VT_VOID.
  609. // [pvReturn] -- Location of return value. If no return value,
  610. // must be NULL.
  611. // [pvtParams] -- List of param types. May be NULL. If
  612. // non-NULL, last entry must be VT_EMPTY.
  613. // [...] -- List of params.
  614. //
  615. // Returns: HRESULT.
  616. //
  617. // History: 2-23-94 adams Created
  618. //
  619. //----------------------------------------------------------------------------
  620. HRESULT
  621. CallDispMethod(
  622. IDispatch * pDisp,
  623. DISPID dispid,
  624. LCID lcid,
  625. VARTYPE vtReturn,
  626. void * pvReturn,
  627. VARTYPE * pvtParams,
  628. ...)
  629. {
  630. HRESULT hr;
  631. VARIANTARG av[EVENTPARAMS_MAX]; // List of args for Invoke.
  632. DISPPARAMS dp; // Params for Invoke.
  633. VARIANT varReturn; // Return value.
  634. va_list va; // List of C-params.
  635. ADsAssert(pDisp);
  636. ADsAssert((vtReturn != VT_VOID) == (pvReturn != NULL));
  637. va_start(va, pvtParams);
  638. dp.rgvarg = av;
  639. CParamsToDispParams(&dp, pvtParams, va);
  640. va_end(va);
  641. if (pvReturn)
  642. VariantInit(&varReturn);
  643. hr = pDisp->Invoke(
  644. dispid,
  645. IID_NULL,
  646. lcid,
  647. DISPATCH_METHOD,
  648. &dp,
  649. pvReturn ? &varReturn : NULL,
  650. NULL,
  651. NULL);
  652. if (hr)
  653. goto Cleanup;
  654. if (pvReturn)
  655. hr = VARIANTARGToCVar(&varReturn, vtReturn, pvReturn);
  656. Cleanup:
  657. RRETURN(hr);
  658. }
  659. //+------------------------------------------------------------------------
  660. //
  661. // Function: IsVariantEqual, public API
  662. //
  663. // Synopsis: Compares the values of two VARIANTARGs.
  664. //
  665. // Arguments: [pvar1], [pvar2] -- VARIANTARGs to compare.
  666. //
  667. // Returns: TRUE if equal, FALSE if not.
  668. //
  669. // History: 18-Mar-93 SumitC Created.
  670. // 11-May-94 SumitC don't assert for VT_UNKNOWN
  671. //
  672. // Notes: Variant type unequal returns FALSE, even if actual values
  673. // are the same.
  674. // Currently does I2, I4, R4, R8, CY, BSTR, BOOL
  675. // Returns FALSE for all other VariantTypes.
  676. //
  677. //-------------------------------------------------------------------------
  678. BOOL
  679. IsVariantEqual( VARIANTARG FAR* pvar1, VARIANTARG FAR* pvar2 )
  680. {
  681. if( V_VT(pvar1) != V_VT(pvar2) )
  682. return FALSE;
  683. switch (V_VT(pvar1))
  684. {
  685. case VT_EMPTY :
  686. case VT_NULL:
  687. return TRUE; // just the types being equal is good enough
  688. case VT_I2 :
  689. return (V_I2(pvar1) == V_I2(pvar2));
  690. case VT_I4 :
  691. return (V_I4(pvar1) == V_I4(pvar2));
  692. case VT_R4 :
  693. return (V_R4(pvar1) == V_R4(pvar2));
  694. case VT_R8 :
  695. return (V_R8(pvar1) == V_R8(pvar2));
  696. case VT_CY :
  697. return !memcmp(&V_CY(pvar1), &V_CY(pvar2), sizeof(CY));
  698. case VT_BSTR :
  699. return !ADsStringCmp(V_BSTR(pvar1), V_BSTR(pvar2));
  700. case VT_BOOL :
  701. return (V_BOOL(pvar1) == V_BOOL(pvar2));
  702. case VT_UNKNOWN:
  703. // returns FALSE unless the objects are the same
  704. return (V_UNKNOWN(pvar1) == V_UNKNOWN(pvar2));
  705. default:
  706. ADsAssert(0 && "Type not handled");
  707. break;
  708. };
  709. return(FALSE);
  710. }
  711. HRESULT
  712. ConvertSafeArrayToVariantArray(
  713. VARIANT varSafeArray,
  714. PVARIANT * ppVarArray,
  715. PDWORD pdwNumVariants
  716. )
  717. {
  718. HRESULT hr = S_OK;
  719. DWORD dwSLBound = 0;
  720. DWORD dwSUBound = 0;
  721. DWORD dwNumVariants = 0;
  722. DWORD i = 0;
  723. VARIANT * pVarArray = NULL;
  724. SAFEARRAY * pArray = NULL;
  725. VARIANT *pvProp = NULL;
  726. *pdwNumVariants = 0;
  727. *ppVarArray = 0;
  728. //
  729. // It has to be a variant and a safearray. It might
  730. // also be a variant that is byref and safe array
  731. //
  732. //
  733. pvProp = &varSafeArray;
  734. if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
  735. pvProp = V_VARIANTREF(&varSafeArray);
  736. }
  737. if(!(((V_VT(pvProp) & VT_VARIANT)== VT_VARIANT)
  738. && V_ISARRAY(pvProp))) {
  739. //
  740. // We need to make this additional check. This is not really
  741. // legal but it could be that just the tag at this level is wrong.
  742. // This was allowed in older versions of ADSI and therefore needs
  743. // on future versions (backward compatibility).
  744. //
  745. if(!((V_VT(&varSafeArray) & VT_VARIANT) && V_ISARRAY(&varSafeArray)))
  746. RRETURN(E_FAIL);
  747. }
  748. if (V_VT(pvProp) == (VT_BYREF | VT_VARIANT | VT_ARRAY)) {
  749. //
  750. // in this case we need to use the ARRAY_REF.
  751. //
  752. pArray = *(V_ARRAYREF(pvProp));
  753. }
  754. else {
  755. //
  756. // pvProp will always have the correc info, byref or not.
  757. //
  758. pArray = V_ARRAY(pvProp);
  759. }
  760. //
  761. // Check that there is only one dimension in this array
  762. //
  763. if (pArray->cDims != 1) {
  764. hr = E_FAIL;
  765. BAIL_ON_FAILURE(hr);
  766. }
  767. //
  768. // Check that there is at least one element in this array
  769. //
  770. if (pArray->rgsabound[0].cElements == 0){
  771. RRETURN(S_OK); // Return success and null array
  772. }
  773. //
  774. // We know that this is a valid single dimension array
  775. //
  776. hr = SafeArrayGetLBound(pArray,
  777. 1,
  778. (long FAR *)&dwSLBound
  779. );
  780. BAIL_ON_FAILURE(hr);
  781. hr = SafeArrayGetUBound(pArray,
  782. 1,
  783. (long FAR *)&dwSUBound
  784. );
  785. BAIL_ON_FAILURE(hr);
  786. dwNumVariants = dwSUBound - dwSLBound + 1;
  787. pVarArray = (PVARIANT)AllocADsMem(
  788. sizeof(VARIANT)*dwNumVariants
  789. );
  790. if (!pVarArray) {
  791. hr = E_OUTOFMEMORY;
  792. BAIL_ON_FAILURE(hr);
  793. }
  794. for (i = dwSLBound; i <= dwSUBound; i++) {
  795. VariantInit(pVarArray + i);
  796. hr = SafeArrayGetElement(pArray,
  797. (long FAR *)&i,
  798. (pVarArray + i)
  799. );
  800. CONTINUE_ON_FAILURE(hr);
  801. }
  802. *ppVarArray = pVarArray;
  803. *pdwNumVariants = dwNumVariants;
  804. error:
  805. RRETURN(hr);
  806. }
  807. //
  808. // This method should go away. ConvertSafeArrayToVariantArray does the job.
  809. //
  810. HRESULT
  811. ConvertByRefSafeArrayToVariantArray(
  812. VARIANT varSafeArray,
  813. PVARIANT * ppVarArray,
  814. PDWORD pdwNumVariants
  815. )
  816. {
  817. RRETURN(ConvertSafeArrayToVariantArray(
  818. varSafeArray,
  819. ppVarArray,
  820. pdwNumVariants
  821. ));
  822. }
  823. //
  824. // An LDAP query needs a NULL-terminated array of strings.
  825. //
  826. HRESULT
  827. ConvertVariantArrayToLDAPStringArray(
  828. PVARIANT pVarArray,
  829. PWSTR **pppszStringArray,
  830. DWORD dwNumStrings
  831. )
  832. {
  833. HRESULT hr = S_OK;
  834. PWSTR *ppszStringArray = NULL;
  835. DWORD i = 0;
  836. //
  837. // Start off with a zero-length array.
  838. //
  839. *pppszStringArray = NULL;
  840. //
  841. // The LDAP library expects an array terminated with a NULL string.
  842. // So make space for an extra one.
  843. //
  844. dwNumStrings++;
  845. ppszStringArray = (PWSTR *)AllocADsMem(dwNumStrings * sizeof(PWSTR));
  846. if (!ppszStringArray)
  847. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  848. for (i = 0; i < dwNumStrings - 1; i++)
  849. {
  850. if (!(V_VT(pVarArray + i) == VT_BSTR))
  851. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  852. ppszStringArray[i] = AllocADsStr(V_BSTR(pVarArray + i));
  853. if (!ppszStringArray[i])
  854. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  855. }
  856. //
  857. // NULL-terminated for LDAP.
  858. //
  859. ppszStringArray[i] = NULL;
  860. *pppszStringArray = ppszStringArray;
  861. RRETURN(hr);
  862. error:
  863. if (ppszStringArray)
  864. {
  865. for (DWORD j = 0; j < i; j++)
  866. if (ppszStringArray[i])
  867. FreeADsStr(ppszStringArray[i]);
  868. FreeADsMem(ppszStringArray);
  869. }
  870. RRETURN(hr);
  871. }
  872. HRESULT
  873. VariantToBinary(
  874. PVARIANT pVarSrcObject,
  875. DWORD *pdwLength,
  876. BYTE **ppByte
  877. )
  878. {
  879. HRESULT hr = S_OK;
  880. LONG dwSLBound = 0;
  881. LONG dwSUBound = 0;
  882. CHAR HUGEP *pArray = NULL;
  883. BYTE *pByte = NULL;
  884. if( pVarSrcObject->vt != (VT_ARRAY | VT_UI1)) {
  885. RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE);
  886. }
  887. hr = SafeArrayGetLBound(V_ARRAY(pVarSrcObject),
  888. 1,
  889. (long FAR *) &dwSLBound );
  890. BAIL_ON_FAILURE(hr);
  891. hr = SafeArrayGetUBound(V_ARRAY(pVarSrcObject),
  892. 1,
  893. (long FAR *) &dwSUBound );
  894. BAIL_ON_FAILURE(hr);
  895. pByte = (BYTE*)AllocADsMem( dwSUBound - dwSLBound + 1);
  896. if ( pByte == NULL) {
  897. hr = E_OUTOFMEMORY;
  898. BAIL_ON_FAILURE(hr);
  899. }
  900. hr = SafeArrayAccessData( V_ARRAY(pVarSrcObject),
  901. (void HUGEP * FAR *) &pArray );
  902. BAIL_ON_FAILURE(hr);
  903. memcpy( pByte,
  904. pArray,
  905. dwSUBound-dwSLBound+1);
  906. SafeArrayUnaccessData( V_ARRAY(pVarSrcObject) );
  907. *pdwLength = dwSUBound - dwSLBound + 1;
  908. *ppByte = pByte;
  909. RRETURN(hr);
  910. error:
  911. if (pByte) {
  912. FreeADsMem(pByte);
  913. }
  914. RRETURN(hr);
  915. }
  916. HRESULT
  917. BinaryToVariant(
  918. DWORD Length,
  919. BYTE* pByte,
  920. PVARIANT lpVarDestObject
  921. )
  922. {
  923. HRESULT hr = S_OK;
  924. SAFEARRAY *aList = NULL;
  925. SAFEARRAYBOUND aBound;
  926. CHAR HUGEP *pArray = NULL;
  927. aBound.lLbound = 0;
  928. aBound.cElements = Length;
  929. aList = SafeArrayCreate( VT_UI1, 1, &aBound );
  930. if ( aList == NULL ) {
  931. hr = E_OUTOFMEMORY;
  932. BAIL_ON_FAILURE(hr);
  933. }
  934. hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray );
  935. BAIL_ON_FAILURE(hr);
  936. memcpy( pArray, pByte, aBound.cElements );
  937. SafeArrayUnaccessData( aList );
  938. V_VT(lpVarDestObject) = VT_ARRAY | VT_UI1;
  939. V_ARRAY(lpVarDestObject) = aList;
  940. RRETURN(hr);
  941. error:
  942. if ( aList ) {
  943. SafeArrayDestroy( aList );
  944. }
  945. RRETURN(hr);
  946. }
  947. HRESULT
  948. CopyOctetString(
  949. DWORD dwNumBytes,
  950. BYTE *pData,
  951. DWORD *pdwNumBytes,
  952. BYTE **ppByte
  953. )
  954. {
  955. LPBYTE lpByteStream = NULL;
  956. HRESULT hr = S_OK;
  957. if (dwNumBytes) {
  958. lpByteStream = (LPBYTE)AllocADsMem(dwNumBytes);
  959. if (lpByteStream == NULL) {
  960. hr = E_OUTOFMEMORY;
  961. BAIL_ON_FAILURE(hr);
  962. }
  963. memcpy(
  964. lpByteStream,
  965. pData,
  966. dwNumBytes
  967. );
  968. *pdwNumBytes = dwNumBytes;
  969. *ppByte = lpByteStream;
  970. }
  971. else {
  972. *pdwNumBytes = 0;
  973. *ppByte = NULL;
  974. }
  975. error:
  976. RRETURN(hr);
  977. }
  978. //+------------------------------------------------------------------------
  979. //
  980. // Function: RaiseException, public API
  981. //
  982. // Synopsis: Generic function for translating ADS HRESULT codes to an
  983. // OLE error object.
  984. //
  985. // Arguments: [hr] - The HRESULT code to be translated into
  986. // an OLE error object.
  987. //
  988. //
  989. // Returns: Nothing. This function is called when an error occurred.
  990. // There isn't much the caller can do if this function fails.
  991. //
  992. // History: 10-Sep-97 t-rmak Created.
  993. //
  994. //
  995. // Notes: 1) Only ADS error codes are properly translated to
  996. // corresponding OLE error objects.
  997. // 2) This function will ignore the lcid passed into
  998. // ITypeInfo::Invoke and it always passes 0 as the langid
  999. // to FormatMessage.
  1000. // 3) Only the source field and the description field of the
  1001. // error object will be filled by this function.
  1002. // 4) This function does not support inserts in the description
  1003. // string.
  1004. //
  1005. //-------------------------------------------------------------------------
  1006. void
  1007. RaiseException(HRESULT hr)
  1008. {
  1009. DWORD dwStrLen;
  1010. LPTSTR lpszMessage = NULL;
  1011. ICreateErrorInfo *pICreateErrorInfo = NULL;
  1012. IErrorInfo *pIErrorInfo = NULL;
  1013. HRESULT localhr = S_OK;
  1014. if (g_hActiveDs != NULL) {
  1015. //
  1016. // Clear any previously set error object
  1017. //
  1018. SetErrorInfo(0, NULL);
  1019. //
  1020. // Let FormatMessage allocate the message buffer.
  1021. // In a multi-threaded environment, this is the simplest
  1022. // solution.
  1023. //
  1024. dwStrLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1025. FORMAT_MESSAGE_FROM_SYSTEM |
  1026. // Ignore inserts for now.
  1027. FORMAT_MESSAGE_IGNORE_INSERTS |
  1028. FORMAT_MESSAGE_FROM_HMODULE,
  1029. (LPCVOID) g_hActiveDs,
  1030. hr,
  1031. 0,
  1032. (LPTSTR) &lpszMessage,
  1033. 0,
  1034. NULL);
  1035. //
  1036. // We may want to fail with a special error code if the specified
  1037. // lcid is not supported.
  1038. //
  1039. if (dwStrLen == 0) {
  1040. goto error;
  1041. }
  1042. //
  1043. // We may want to add support for help file in the future.
  1044. //
  1045. localhr = CreateErrorInfo(&pICreateErrorInfo);
  1046. BAIL_ON_FAILURE(localhr);
  1047. //
  1048. // Note that we don't care whether the following calls succeed since
  1049. // there is nothing we can if they fail.
  1050. //
  1051. pICreateErrorInfo->SetDescription(lpszMessage);
  1052. pICreateErrorInfo->SetSource(TEXT("Active Directory"));
  1053. //
  1054. // Set the threads error object.
  1055. //
  1056. pICreateErrorInfo->QueryInterface(IID_IErrorInfo, (void **)&pIErrorInfo);
  1057. SetErrorInfo(0, pIErrorInfo);
  1058. }
  1059. error:
  1060. if (lpszMessage != NULL) {
  1061. LocalFree(lpszMessage);
  1062. }
  1063. //
  1064. // Release the error object's interface pointers
  1065. //
  1066. if (pIErrorInfo != NULL) {
  1067. pIErrorInfo->Release();
  1068. }
  1069. if (pICreateErrorInfo != NULL) {
  1070. pICreateErrorInfo->Release();
  1071. }
  1072. }