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.

801 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: Comdthk.c (16 bit target)
  7. //
  8. // Contents: CompObj Directly Thunked APIs
  9. //
  10. // Functions:
  11. //
  12. // History: 16-Dec-93 JohannP Created
  13. // 07-Mar-94 BobDay Moved into COMTHUNK.C from COMAPI.CXX
  14. //
  15. //--------------------------------------------------------------------------
  16. #include <headers.cxx>
  17. #pragma hdrstop
  18. #include <call32.hxx>
  19. #include <apilist.hxx>
  20. STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid);
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Function: Straight thunk routines
  24. //
  25. // Synopsis: The following routines do not need to do any special
  26. // processing on the 16-bit side so they thunk straight
  27. // through
  28. //
  29. // History: 18-Feb-94 JohannP Created
  30. //
  31. // Notes: "Review to ensure these don't have to do any work"
  32. // 15-Feb-2000 I'm pretty sure they don't. JohnDoty
  33. //
  34. //----------------------------------------------------------------------------
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Function: CLSIDFromString, Remote
  38. //
  39. // History: Straight from OLE2 sources
  40. //
  41. //----------------------------------------------------------------------------
  42. STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid)
  43. {
  44. HRESULT hr;
  45. thkDebugOut((DEB_ITRACE, "CLSIDFromString\n"));
  46. //
  47. // The 16-bit OLE2 application "Family Tree Maker" always passes a bad
  48. // string to CLSIDFromString. We need to make sure we fail in the exact
  49. // same way with the interop layer. This will also provide a speed
  50. // improvement since we only need to remote to the 32bit version of
  51. // CLSIDFromString when the string provided does not start with '{'.
  52. //
  53. if (lpsz[0] == '{')
  54. return GUIDFromString(lpsz, pclsid)
  55. ? NOERROR : ResultFromScode(CO_E_CLASSSTRING);
  56. // Note: Corel calls this function prior to calling
  57. // CoInitialize so use CheckInit
  58. return (HRESULT)CallObjectInWOWCheckInit(THK_API_METHOD(THK_API_CLSIDFromString),
  59. PASCAL_STACK_PTR(lpsz));
  60. }
  61. //+---------------------------------------------------------------------------
  62. //
  63. // Function: CoGetClassObject, Remote
  64. //
  65. // Synopsis:
  66. //
  67. // Effects:
  68. //
  69. // Arguments: [rclsid] --
  70. // [dwClsContext] --
  71. // [pvReserved] --
  72. // [riid] --
  73. // [ppv] --
  74. //
  75. // Requires:
  76. //
  77. // Returns:
  78. //
  79. // Signals:
  80. //
  81. // Modifies:
  82. //
  83. // Algorithm:
  84. //
  85. // History: 2-28-94 kevinro Created
  86. //
  87. // Notes:
  88. //
  89. //----------------------------------------------------------------------------
  90. STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
  91. REFIID riid, LPVOID FAR* ppv)
  92. {
  93. thkDebugOut((DEB_ITRACE, " CoGetClassObject\n"));
  94. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetClassObject),
  95. PASCAL_STACK_PTR(rclsid) );
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Function: CoRegisterClassObject, Remote
  100. //
  101. // Synopsis:
  102. //
  103. // Effects:
  104. //
  105. // Arguments: [rclsid] --
  106. // [pUnk] --
  107. // [dwClsContext] --
  108. // [flags] --
  109. // [lpdwRegister] --
  110. //
  111. // Requires:
  112. //
  113. // Returns:
  114. //
  115. // Signals:
  116. //
  117. // Modifies:
  118. //
  119. // Algorithm:
  120. //
  121. // History: 2-28-94 kevinro Created
  122. //
  123. // Notes:
  124. //
  125. //----------------------------------------------------------------------------
  126. STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
  127. DWORD dwClsContext, DWORD flags,
  128. LPDWORD lpdwRegister)
  129. {
  130. thkDebugOut((DEB_ITRACE, " CoRegisterClassObject\n"));
  131. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRegisterClassObject),
  132. PASCAL_STACK_PTR(rclsid));
  133. }
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Function: CoRevokeClassObject, Remote
  137. //
  138. // Synopsis:
  139. //
  140. // Effects:
  141. //
  142. // Arguments: [dwRegister] --
  143. //
  144. // Requires:
  145. //
  146. // Returns:
  147. //
  148. // Signals:
  149. //
  150. // Modifies:
  151. //
  152. // Algorithm:
  153. //
  154. // History: 2-28-94 kevinro Created
  155. //
  156. // Notes:
  157. //
  158. //----------------------------------------------------------------------------
  159. STDAPI CoRevokeClassObject(DWORD dwRegister)
  160. {
  161. thkDebugOut((DEB_ITRACE, " CoRevokeClassObject\n"));
  162. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRevokeClassObject),
  163. PASCAL_STACK_PTR(dwRegister) );
  164. }
  165. //+---------------------------------------------------------------------------
  166. //
  167. // Function: CoMarshalInterface, Unknown
  168. //
  169. // Synopsis:
  170. //
  171. // Effects:
  172. //
  173. // Arguments: [pStm] --
  174. // [riid] --
  175. // [pUnk] --
  176. // [dwDestContext] --
  177. // [pvDestContext] --
  178. // [mshlflags] --
  179. //
  180. // Requires:
  181. //
  182. // Returns:
  183. //
  184. // Signals:
  185. //
  186. // Modifies:
  187. //
  188. // Algorithm:
  189. //
  190. // History: 2-28-94 kevinro Created
  191. //
  192. // Notes:
  193. //
  194. //----------------------------------------------------------------------------
  195. STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
  196. DWORD dwDestContext, LPVOID pvDestContext,
  197. DWORD mshlflags)
  198. {
  199. thkDebugOut((DEB_ITRACE, " CoMarshalInterface\n"));
  200. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoMarshalInterface),
  201. PASCAL_STACK_PTR(pStm));
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Function: CoUnmarshalInterface, Unknown
  206. //
  207. // Synopsis:
  208. //
  209. // Effects:
  210. //
  211. // Arguments: [pStm] --
  212. // [riid] --
  213. // [ppv] --
  214. //
  215. // Requires:
  216. //
  217. // Returns:
  218. //
  219. // Signals:
  220. //
  221. // Modifies:
  222. //
  223. // Algorithm:
  224. //
  225. // History: 2-28-94 kevinro Created
  226. //
  227. // Notes:
  228. //
  229. //----------------------------------------------------------------------------
  230. STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv)
  231. {
  232. thkDebugOut((DEB_ITRACE, "CoUnmarshalInterface\n"));
  233. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoUnmarshalInterface),
  234. PASCAL_STACK_PTR(pStm));
  235. }
  236. //+---------------------------------------------------------------------------
  237. //
  238. // Function: CoReleaseMarshalData, Unknown
  239. //
  240. // Synopsis:
  241. //
  242. // Effects:
  243. //
  244. // Arguments: [pStm] --
  245. //
  246. // Requires:
  247. //
  248. // Returns:
  249. //
  250. // Signals:
  251. //
  252. // Modifies:
  253. //
  254. // Algorithm:
  255. //
  256. // History: 2-28-94 kevinro Created
  257. //
  258. // Notes:
  259. //
  260. //----------------------------------------------------------------------------
  261. STDAPI CoReleaseMarshalData(LPSTREAM pStm)
  262. {
  263. thkDebugOut((DEB_ITRACE, "CoReleaseMarshalData\n"));
  264. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoReleaseMarshalData),
  265. PASCAL_STACK_PTR(pStm));
  266. }
  267. //+---------------------------------------------------------------------------
  268. //
  269. // Function: CoDisconnectObject, Remote
  270. //
  271. // Synopsis:
  272. //
  273. // Effects:
  274. //
  275. // Arguments: [pUnk] --
  276. // [dwReserved] --
  277. //
  278. // Requires:
  279. //
  280. // Returns:
  281. //
  282. // Signals:
  283. //
  284. // Modifies:
  285. //
  286. // Algorithm:
  287. //
  288. // History: 2-28-94 kevinro Created
  289. //
  290. // Notes:
  291. //
  292. //----------------------------------------------------------------------------
  293. STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved)
  294. {
  295. thkDebugOut((DEB_ITRACE, "CoDisconnectObject\n"));
  296. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoDisconnectObject),
  297. PASCAL_STACK_PTR(pUnk));
  298. }
  299. //+---------------------------------------------------------------------------
  300. //
  301. // Function: CoLockObjectExternal, Remote
  302. //
  303. // Synopsis:
  304. //
  305. // Effects:
  306. //
  307. // Arguments: [pUnk] --
  308. // [fLock] --
  309. // [fLastUnlockReleases] --
  310. //
  311. // Requires:
  312. //
  313. // Returns:
  314. //
  315. // Signals:
  316. //
  317. // Modifies:
  318. //
  319. // Algorithm:
  320. //
  321. // History: 2-28-94 kevinro Created
  322. //
  323. // Notes:
  324. //
  325. //----------------------------------------------------------------------------
  326. STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock,
  327. BOOL fLastUnlockReleases)
  328. {
  329. thkDebugOut((DEB_ITRACE, "CoLockObjectExternal\n"));
  330. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoLockObjectExternal),
  331. PASCAL_STACK_PTR(pUnk));
  332. }
  333. //+---------------------------------------------------------------------------
  334. //
  335. // Function: CoGetStandardMarshal, Remote
  336. //
  337. // Synopsis:
  338. //
  339. // Effects:
  340. //
  341. // Arguments: [riid] --
  342. // [pUnk] --
  343. // [dwDestContext] --
  344. // [pvDestContext] --
  345. // [mshlflags] --
  346. // [ppMarshal] --
  347. //
  348. // Requires:
  349. //
  350. // Returns:
  351. //
  352. // Signals:
  353. //
  354. // Modifies:
  355. //
  356. // Algorithm:
  357. //
  358. // History: 2-28-94 kevinro Created
  359. //
  360. // Notes:
  361. //
  362. //----------------------------------------------------------------------------
  363. STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
  364. DWORD dwDestContext, LPVOID pvDestContext,
  365. DWORD mshlflags,
  366. LPMARSHAL FAR* ppMarshal)
  367. {
  368. thkDebugOut((DEB_ITRACE, "CoGetStandardMarshal\n"));
  369. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetStandardMarshal),
  370. PASCAL_STACK_PTR(riid));
  371. }
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Function: CoIsHandlerConnected, Remote
  375. //
  376. // Synopsis:
  377. //
  378. // Effects:
  379. //
  380. // Arguments: [pUnk] --
  381. //
  382. // Requires:
  383. //
  384. // Returns:
  385. //
  386. // Signals:
  387. //
  388. // Modifies:
  389. //
  390. // Algorithm:
  391. //
  392. // History: 2-28-94 kevinro Created
  393. //
  394. // Notes:
  395. //
  396. //----------------------------------------------------------------------------
  397. STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk)
  398. {
  399. thkDebugOut((DEB_ITRACE, "CoIsHandlerConnected\n"));
  400. return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoIsHandlerConnected),
  401. PASCAL_STACK_PTR(pUnk));
  402. }
  403. //+---------------------------------------------------------------------------
  404. //
  405. // Function: CoCreateInstance, Remote
  406. //
  407. // Synopsis:
  408. //
  409. // Effects:
  410. //
  411. // Arguments: [rclsid] --
  412. // [pUnkOuter] --
  413. // [dwClsContext] --
  414. // [riid] --
  415. // [ppv] --
  416. //
  417. // Requires:
  418. //
  419. // Returns:
  420. //
  421. // Signals:
  422. //
  423. // Modifies:
  424. //
  425. // Algorithm:
  426. //
  427. // History: 2-28-94 kevinro Created
  428. //
  429. // Notes:
  430. //
  431. //----------------------------------------------------------------------------
  432. STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
  433. DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv)
  434. {
  435. thkDebugOut((DEB_ITRACE, "CoCreateInstance\n"));
  436. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoCreateInstance),
  437. PASCAL_STACK_PTR(rclsid) );
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: CoIsOle1Class, Remote
  442. //
  443. // Synopsis:
  444. //
  445. // Effects:
  446. //
  447. // Arguments: [rclsid] --
  448. //
  449. // Requires:
  450. //
  451. // Returns:
  452. //
  453. // Signals:
  454. //
  455. // Modifies:
  456. //
  457. // Algorithm:
  458. //
  459. // History: 2-28-94 kevinro Created
  460. //
  461. // Notes:
  462. //
  463. //----------------------------------------------------------------------------
  464. STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid)
  465. {
  466. thkDebugOut((DEB_ITRACE, "CoIsOle1Class\n"));
  467. return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoIsOle1Class),
  468. PASCAL_STACK_PTR(rclsid) );
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Function: ProgIDFromCLSID, Remote
  473. //
  474. // Synopsis:
  475. //
  476. // Effects:
  477. //
  478. // Arguments: [clsid] --
  479. // [lplpszProgID] --
  480. //
  481. // Requires:
  482. //
  483. // Returns:
  484. //
  485. // Signals:
  486. //
  487. // Modifies:
  488. //
  489. // Algorithm:
  490. //
  491. // History: 2-28-94 kevinro Created
  492. //
  493. // Notes:
  494. //
  495. //----------------------------------------------------------------------------
  496. STDAPI ProgIDFromCLSID(REFCLSID clsid, LPSTR FAR* lplpszProgID)
  497. {
  498. thkDebugOut((DEB_ITRACE, "ProgIDFromCLSID\n"));
  499. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ProgIDFromCLSID),
  500. PASCAL_STACK_PTR(clsid) );
  501. }
  502. //+---------------------------------------------------------------------------
  503. //
  504. // Function: CLSIDFromProgID, Remote
  505. //
  506. // Synopsis:
  507. //
  508. // Effects:
  509. //
  510. // Arguments: [lpszProgID] --
  511. // [lpclsid] --
  512. //
  513. // Requires:
  514. //
  515. // Returns:
  516. //
  517. // Signals:
  518. //
  519. // Modifies:
  520. //
  521. // Algorithm:
  522. //
  523. // History: 2-28-94 kevinro Created
  524. //
  525. // Notes:
  526. //
  527. //----------------------------------------------------------------------------
  528. STDAPI CLSIDFromProgID(LPCSTR lpszProgID, LPCLSID lpclsid)
  529. {
  530. thkDebugOut((DEB_ITRACE, "CLSIDFromProgID\n"));
  531. // Note: Word 6 calls this function prior to calling
  532. // CoInitialize so use CheckInit
  533. return (HRESULT)CallObjectInWOWCheckInit(THK_API_METHOD(THK_API_CLSIDFromProgID),
  534. PASCAL_STACK_PTR(lpszProgID) );
  535. }
  536. //+---------------------------------------------------------------------------
  537. //
  538. // Function: CoCreateGuid, Remote
  539. //
  540. // Synopsis:
  541. //
  542. // Effects:
  543. //
  544. // Arguments: [pguid] --
  545. //
  546. // Requires:
  547. //
  548. // Returns:
  549. //
  550. // Signals:
  551. //
  552. // Modifies:
  553. //
  554. // Algorithm:
  555. //
  556. // History: 2-28-94 kevinro Created
  557. //
  558. // Notes:
  559. //
  560. //----------------------------------------------------------------------------
  561. STDAPI CoCreateGuid(GUID FAR *pguid)
  562. {
  563. thkDebugOut((DEB_ITRACE, "CoCreateGuid\n"));
  564. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoCreateGuid),
  565. PASCAL_STACK_PTR(pguid));
  566. }
  567. //+---------------------------------------------------------------------------
  568. //
  569. // Function: CoFileTimeToDosDateTime, Remote
  570. //
  571. // Synopsis:
  572. //
  573. // Effects:
  574. //
  575. // Arguments: [lpFileTime] --
  576. // [lpDosDate] --
  577. // [lpDosTime] --
  578. //
  579. // Requires:
  580. //
  581. // Returns:
  582. //
  583. // Signals:
  584. //
  585. // Modifies:
  586. //
  587. // Algorithm:
  588. //
  589. // History: 2-28-94 kevinro Created
  590. //
  591. // Notes:
  592. //
  593. //----------------------------------------------------------------------------
  594. STDAPI_(BOOL) CoFileTimeToDosDateTime(FILETIME FAR* lpFileTime,
  595. LPWORD lpDosDate, LPWORD lpDosTime)
  596. {
  597. thkDebugOut((DEB_ITRACE, "CoFileTimeToDosDateTime\n"));
  598. return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoFileTimeToDosDateTime),
  599. PASCAL_STACK_PTR(lpFileTime));
  600. }
  601. //+---------------------------------------------------------------------------
  602. //
  603. // Function: CoDosDateTimeToFileTime, Remote
  604. //
  605. // Synopsis:
  606. //
  607. // Effects:
  608. //
  609. // Arguments: [nDosDate] --
  610. // [nDosTime] --
  611. // [lpFileTime] --
  612. //
  613. // Requires:
  614. //
  615. // Returns:
  616. //
  617. // Signals:
  618. //
  619. // Modifies:
  620. //
  621. // Algorithm:
  622. //
  623. // History: 2-28-94 kevinro Created
  624. //
  625. // Notes:
  626. //
  627. //----------------------------------------------------------------------------
  628. STDAPI_(BOOL) CoDosDateTimeToFileTime(WORD nDosDate, WORD nDosTime,
  629. FILETIME FAR* lpFileTime)
  630. {
  631. thkDebugOut((DEB_ITRACE, "CoDosDateTimeToFileTime\n"));
  632. return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoDosDateTimeToFileTime),
  633. PASCAL_STACK_PTR(nDosDate));
  634. }
  635. //+---------------------------------------------------------------------------
  636. //
  637. // Function: CoFileTimeNow, Remote
  638. //
  639. // Synopsis:
  640. //
  641. // Effects:
  642. //
  643. // Arguments: [lpFileTime] --
  644. //
  645. // Requires:
  646. //
  647. // Returns:
  648. //
  649. // Signals:
  650. //
  651. // Modifies:
  652. //
  653. // Algorithm:
  654. //
  655. // History: 2-28-94 kevinro Created
  656. //
  657. // Notes:
  658. //
  659. //----------------------------------------------------------------------------
  660. STDAPI CoFileTimeNow(FILETIME FAR* lpFileTime)
  661. {
  662. thkDebugOut((DEB_ITRACE, "CoFileTimeNow\n"));
  663. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoFileTimeNow),
  664. PASCAL_STACK_PTR(lpFileTime));
  665. }
  666. //+---------------------------------------------------------------------------
  667. //
  668. // Function: CoRegisterMessageFilter, Remote
  669. //
  670. // Synopsis:
  671. //
  672. // Effects:
  673. //
  674. // Arguments: [lpMessageFilter] --
  675. // [lplpMessageFilter] --
  676. //
  677. // Requires:
  678. //
  679. // Returns:
  680. //
  681. // Signals:
  682. //
  683. // Modifies:
  684. //
  685. // Algorithm:
  686. //
  687. // History: 2-28-94 kevinro Created
  688. //
  689. // Notes:
  690. //
  691. //----------------------------------------------------------------------------
  692. STDAPI CoRegisterMessageFilter(LPMESSAGEFILTER lpMessageFilter,
  693. LPMESSAGEFILTER FAR* lplpMessageFilter)
  694. {
  695. thkDebugOut((DEB_ITRACE, "CoRegisterMessageFilter\n"));
  696. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRegisterMessageFilter),
  697. PASCAL_STACK_PTR(lpMessageFilter) );
  698. }
  699. //+---------------------------------------------------------------------------
  700. //
  701. // Function: CoGetTreatAsClass, Remote
  702. //
  703. // Synopsis:
  704. //
  705. // Effects:
  706. //
  707. // Arguments: [clsidOld] --
  708. // [pClsidNew] --
  709. //
  710. // Requires:
  711. //
  712. // Returns:
  713. //
  714. // Signals:
  715. //
  716. // Modifies:
  717. //
  718. // Algorithm:
  719. //
  720. // History: 2-28-94 kevinro Created
  721. //
  722. // Notes:
  723. //
  724. //----------------------------------------------------------------------------
  725. STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew)
  726. {
  727. thkDebugOut((DEB_ITRACE, "CoGetTreatAsClass\n"));
  728. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetTreatAsClass),
  729. PASCAL_STACK_PTR(clsidOld) );
  730. }
  731. //+---------------------------------------------------------------------------
  732. //
  733. // Function: CoTreatAsClass, Remote
  734. //
  735. // Synopsis:
  736. //
  737. // Effects:
  738. //
  739. // Arguments: [clsidOld] --
  740. // [clsidNew] --
  741. //
  742. // Requires:
  743. //
  744. // Returns:
  745. //
  746. // Signals:
  747. //
  748. // Modifies:
  749. //
  750. // Algorithm:
  751. //
  752. // History: 2-28-94 kevinro Created
  753. //
  754. // Notes:
  755. //
  756. //----------------------------------------------------------------------------
  757. STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
  758. {
  759. thkDebugOut((DEB_ITRACE, "CoTreatAsClass\n"));
  760. return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoTreatAsClass),
  761. PASCAL_STACK_PTR(clsidOld) );
  762. }