home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / oleaut / dispdemo / crempoly.cpp < prev    next >
C/C++ Source or Header  |  1997-07-31  |  20KB  |  875 lines

  1. /*** 
  2. *crempoly.cpp
  3. *
  4. *  This is a part of the Microsoft Source Code Samples.
  5. *
  6. *  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  7. *
  8. *  This source code is only intended as a supplement to Microsoft Development
  9. *  Tools and/or WinHelp documentation.  See these sources for detailed
  10. *  information regarding the Microsoft samples programs.
  11. *
  12. *Purpose:
  13. *  This file contains the implementation of CRemPoly, the remote polygon
  14. *  class. This class presents a standard C++ vtable interface to the
  15. *  rest of the application, and hides the details of talking to the
  16. *  actual remote CPoly class exposed by the SPoly server. Each of
  17. *  the introduced methods is simply a cover for an IDispatch invocation
  18. *  of the actual method on the remote object.
  19. *
  20. *Implementation Notes:
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "dispdemo.h"
  25. #include "crempoly.h"
  26.  
  27. extern int g_fTrace;
  28.  
  29. // method names on the CPoly class.
  30. //
  31. OLECHAR FAR* CRemPoly::m_rgszMethods[] = {
  32.     OLESTR("draw"),
  33.     OLESTR("dump"),
  34.     OLESTR("reset"),
  35.     OLESTR("addpoint"),
  36.     OLESTR("enumpoints"),
  37.     OLESTR("getxorigin"),
  38.     OLESTR("setxorigin"),
  39.     OLESTR("getyorigin"),
  40.     OLESTR("setyorigin"),
  41.     OLESTR("getwidth"),
  42.     OLESTR("setwidth"),
  43.     OLESTR("get_red"),
  44.     OLESTR("set_red"),
  45.     OLESTR("get_green"),
  46.     OLESTR("set_green"),
  47.     OLESTR("get_blue"),
  48.     OLESTR("set_blue")
  49. };
  50.  
  51. #ifdef _MAC
  52. # define IfMac(X) (X)
  53. # define IfWin(X)
  54. #else
  55. # define IfMac(X)
  56. # define IfWin(X) (X)
  57. #endif
  58.  
  59.  
  60. CRemPoly::CRemPoly()
  61. {
  62.     m_refs = 0;
  63.     m_pdisp = (IDispatch FAR*)NULL;
  64. }
  65.  
  66.  
  67. // A useful pre-initialized DISPATCHPARAMS, used on all the methods that
  68. // take 0 arguments.
  69. //
  70. DISPPARAMS NEAR g_dispparamsNoArgs = {NULL, NULL, 0, 0};
  71.  
  72.  
  73. /***
  74. *HRESULT CRemPoly::Create(clsid, CRemPoly**)
  75. *
  76. *Purpose:
  77. *  This function creates an instance of the CRemPoly class, connects
  78. *  it to the IDispatch interface of the remote CPoly class, and learns
  79. *  the DISPIDs for the members (that we know about) exposed by that
  80. *  class.
  81. *
  82. *Entry:
  83. *  clsid = The CLSID of the CPoly we are to create. (taking this as a
  84. *    param is a bit weird, but allows us to connect to several remote
  85. *    versions.
  86. *
  87. *Exit:
  88. *  return value = HRESULT
  89. *
  90. *  *pprempoly = pointer to the newly created CRemPoly, if successfyl.
  91. *
  92. ***********************************************************************/
  93. HRESULT
  94. CRemPoly::Create(CLSID clsid, CRemPoly FAR* FAR* pprempoly)
  95. {
  96.     int i;
  97.     HRESULT hresult;
  98.     IUnknown FAR* punk;
  99.     CRemPoly FAR* prempoly;
  100.  
  101.  
  102.     prempoly = new FAR CRemPoly();
  103.     if(prempoly == (CRemPoly FAR*)NULL){
  104.       hresult = E_OUTOFMEMORY;
  105.       goto LError;
  106.     }
  107.     prempoly->AddRef();
  108.       
  109.     // create an instance of the remote CPoly class.
  110.     //
  111.     IfMac(DbPrintf("CoCreateInstance(CLSID_CPoly)"));
  112.     hresult = CoCreateInstance(
  113.       clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void FAR* FAR*)&punk);
  114.     if(hresult != NOERROR){
  115.       IfMac(DbPrintf("CoCreateInstance() = 0x%x", hresult));
  116.       IfWin(MessageBox(NULL, TSTR("Unable to create polygon object"), 
  117.                    NULL, MB_OK));
  118.       goto LFreeCRemPoly;
  119.     }
  120.  
  121.     // were going to talk to this remote instance via IDispatch.
  122.     //
  123.     IfMac(DbPrintf("QueryInterface(IID_IDispatch)"));
  124.     hresult = punk->QueryInterface(
  125.       IID_IDispatch, (void FAR* FAR*)&prempoly->m_pdisp);
  126.     if(hresult != NOERROR){
  127.       IfMac(DbPrintf("QueryInterface(IID_IDispatch) = 0x%x", hresult));
  128.       IfWin(MessageBox(NULL, TSTR("Unable to QueryInterface to IDispatch"),
  129.                    NULL, MB_OK));
  130.       goto LReleaseUnk;
  131.     }
  132.  
  133.     // We learn *all* the member IDs up front. A more sophisticated
  134.     // implementation might defer learning about the IDs for a given
  135.     // method until the first time the method is invoked, thereby
  136.     // amortizing the creation costs.
  137.     //
  138.     IfMac(DbPrintf("GetIDsOfNames()"));
  139.     for(i = 0; i < IMETH_CREMPOLY_MAX; ++i){
  140.       hresult = prempoly->m_pdisp->GetIDsOfNames(
  141.     IID_NULL,
  142.         &prempoly->m_rgszMethods[i],
  143.     1, LOCALE_USER_DEFAULT,
  144.     &prempoly->m_rgdispid[i]);
  145.       if(hresult != NOERROR){
  146.     IfMac(DbPrintf("GetIDsOfNames() = 0x%x", hresult));
  147.     IfWin(MessageBox(NULL, TSTR("Unrecognized member name"),
  148.                  NULL, MB_OK));
  149.     goto LReleaseUnk;
  150.       }
  151.     }
  152.  
  153.     punk->Release();
  154.  
  155.     *pprempoly = prempoly;
  156.  
  157.     IfMac(DbPrintf("Object created."));
  158.  
  159.     return NOERROR;
  160.  
  161. LReleaseUnk:;
  162.     punk->Release();
  163.  
  164. LFreeCRemPoly:;
  165.     prempoly->Release();
  166.  
  167. LError:;
  168.     return hresult;
  169. }
  170.  
  171.  
  172. //---------------------------------------------------------------------
  173. //                     IUnknown methods
  174. //---------------------------------------------------------------------
  175.  
  176.  
  177. /***
  178. *HRESULT CRemPoly::QueryInterface(REFIID, void**)
  179. *
  180. *Purpose:
  181. *  Standard Ole2 implementation of QueryInterface. This class
  182. *  supports the IUnknown interface, and introduces a number of
  183. *  nonvirtual members.
  184. *
  185. *Entry:
  186. *  riid = reference to the requested interface id
  187. *
  188. *Exit:
  189. *  return value = HRESULT
  190. *  *ppv = pointer to the requested interface, if successful.
  191. *
  192. ***********************************************************************/
  193. STDMETHODIMP
  194. CRemPoly::QueryInterface(REFIID riid, void FAR* FAR* ppv)
  195. {
  196.     if(IsEqualIID(riid, IID_IUnknown)){
  197.       *ppv = this;
  198.       AddRef();
  199.       return NOERROR;
  200.     }
  201.     *ppv = NULL;
  202.     return E_NOINTERFACE;
  203. }
  204.  
  205.  
  206. /***
  207. *unsigned long CRemPoly::AddRef(void)
  208. *
  209. *Purpose:
  210. *  Add a reference to the instance.
  211. *
  212. *Entry:
  213. *  None
  214. *
  215. *Exit:
  216. *  return value = unsigned long. The resulting reference count.
  217. *
  218. ***********************************************************************/
  219. STDMETHODIMP_(unsigned long)
  220. CRemPoly::AddRef(void)
  221. {
  222.     return ++m_refs;
  223. }
  224.  
  225.  
  226. /***
  227. *unsigned long CRemPoly::Release(void)
  228. *
  229. *Purpose:
  230. *  Release a reference to the instance. If the reference count goes
  231. *  to zero, delete the instance.
  232. *
  233. *Entry:
  234. *  None
  235. *
  236. *Exit:
  237. *  return value = unsigned long. The resulting reference count.
  238. *
  239. ***********************************************************************/
  240. STDMETHODIMP_(unsigned long)
  241. CRemPoly::Release(void)
  242. {
  243.     if(--m_refs == 0){
  244.       if(m_pdisp != (IDispatch FAR*)NULL){
  245.         m_pdisp->Release();
  246.       }
  247.       delete this;
  248.       return 0;
  249.     }
  250.     return m_refs;
  251. }
  252.  
  253.  
  254. //---------------------------------------------------------------------
  255. //                    Introduced methods
  256. //---------------------------------------------------------------------
  257.  
  258.  
  259. /*
  260.  * Each of these methods is simply a cover for an IDispatch Invocation
  261.  * of the actual method on the remote CPoly class. This allows CRemPoly
  262.  * to present an interface that looks and acts just like the CPoly
  263.  * object, even though the actual work is being done in another process.
  264.  *
  265.  */
  266.  
  267. /***
  268. *HRESULT CRemPoly::Draw(void)
  269. *
  270. *Purpose:
  271. *  Invoke the Draw method on the remote CPoly instance.
  272. *
  273. *Entry:
  274. *  None
  275. *
  276. *Exit:
  277. *  return value = HRESULT
  278. *
  279. ***********************************************************************/
  280. HRESULT
  281. CRemPoly::Draw()
  282. {
  283.     return m_pdisp->Invoke(
  284.       m_rgdispid[IMETH_CREMPOLY_DRAW],
  285.       IID_NULL,
  286.       LOCALE_USER_DEFAULT,
  287.       DISPATCH_METHOD,
  288.       &g_dispparamsNoArgs, NULL, NULL, NULL);
  289. }
  290.  
  291.  
  292. /***
  293. *HRESULT CRemPoly::Dump(void)
  294. *
  295. *Purpose:
  296. *  Invoke the Dump() method on the remote CPoly instance. This method
  297. *  dumps the contained CPoints and writes the properties of the remote
  298. *  CPoly instance to the debug window.
  299. *
  300. *Entry:
  301. *  None
  302. *
  303. *Exit:
  304. *  return value = HRESULT
  305. *
  306. ***********************************************************************/
  307. HRESULT
  308. CRemPoly::Dump()
  309. {
  310.     return m_pdisp->Invoke(
  311.       m_rgdispid[IMETH_CREMPOLY_DUMP],
  312.       IID_NULL,
  313.       LOCALE_USER_DEFAULT,
  314.       DISPATCH_METHOD,
  315.       &g_dispparamsNoArgs, NULL, NULL, NULL);
  316. }
  317.  
  318.  
  319. /***
  320. *HRESULT CRemPoly::Reset(void)
  321. *
  322. *Purpose:
  323. *  Invoke the Reset() method on the remote CPoly instance. The Reset()
  324. *  method causes the remote CPoly to release all contained CPoints.
  325. *
  326. *Entry:
  327. *  None
  328. *
  329. *Exit:
  330. *  return value = HRESULT
  331. *
  332. ***********************************************************************/
  333. HRESULT
  334. CRemPoly::Reset()
  335. {
  336.     return m_pdisp->Invoke(
  337.       m_rgdispid[IMETH_CREMPOLY_RESET],
  338.       IID_NULL,
  339.       LOCALE_USER_DEFAULT,
  340.       DISPATCH_METHOD,
  341.       &g_dispparamsNoArgs, NULL, NULL, NULL);
  342. }
  343.  
  344.  
  345. /***
  346. *HRESULT CRemPoly::AddPoint(short, short)
  347. *
  348. *Purpose:
  349. *  Invoke the AddPoint method in the remote CPoly object to add a
  350. *  new point with the given coordinates to this instance.
  351. *
  352. *Entry:
  353. *  x,y = the x and y coordinates of the new point.
  354. *
  355. *Exit:
  356. *  return value = HRESULT
  357. *
  358. ***********************************************************************/
  359. HRESULT
  360. CRemPoly::AddPoint(short x, short y)
  361. {
  362.     HRESULT hresult;
  363.     VARIANTARG varg[2];
  364.     DISPPARAMS dispparams;
  365.  
  366.     V_VT(&varg[0]) = VT_I2;
  367.     V_I2(&varg[0]) = y;
  368.  
  369.     V_VT(&varg[1]) = VT_I2;
  370.     V_I2(&varg[1]) = x;
  371.  
  372.     dispparams.cArgs = 2;
  373.     dispparams.rgvarg = varg;
  374.     dispparams.cNamedArgs = 0;
  375.     dispparams.rgdispidNamedArgs = NULL;
  376.  
  377.     hresult = m_pdisp->Invoke(
  378.       m_rgdispid[IMETH_CREMPOLY_ADDPOINT],
  379.       IID_NULL,
  380.       LOCALE_USER_DEFAULT,
  381.       DISPATCH_METHOD,
  382.       &dispparams, NULL, NULL, NULL);
  383.  
  384.     return hresult;
  385. }
  386.  
  387.  
  388. /***
  389. *HRESULT CRemPoly::EnumPoints(IEnumVARIANT**)
  390. *Purpose:
  391. *  Inoke the EnumPoints() method in the remote object to
  392. *  get a enumerator for the points contained in the current poly.
  393. *
  394. *Entry:
  395. *  None
  396. *
  397. *Exit:
  398. *  return value = HRESULT
  399. *
  400. *  *ppenum = pointer to the point enumerator
  401. *
  402. ***********************************************************************/
  403. HRESULT
  404. CRemPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
  405. {
  406.     HRESULT hresult;
  407.     IEnumVARIANT FAR* penum;
  408.     VARIANT varResult, FAR* pvarResult;
  409.  
  410.  
  411.     pvarResult = &varResult;
  412.     VariantInit(pvarResult);
  413.     hresult = m_pdisp->Invoke(
  414.       m_rgdispid[IMETH_CREMPOLY_ENUMPOINTS],
  415.       IID_NULL,
  416.       LOCALE_USER_DEFAULT,
  417.       DISPATCH_METHOD,
  418.       &g_dispparamsNoArgs, pvarResult, NULL, NULL);
  419.  
  420.     if(hresult != NOERROR)
  421.       return hresult;
  422.  
  423.     if(V_VT(pvarResult) != VT_UNKNOWN)
  424.       return E_FAIL;
  425.  
  426.     hresult = V_UNKNOWN(pvarResult)->QueryInterface(
  427.       IID_IEnumVARIANT, (void FAR* FAR*)&penum);
  428.  
  429.     if(hresult == NOERROR)
  430.       *ppenum = penum;
  431.  
  432.     VariantClear(pvarResult);
  433.  
  434.     return NOERROR;
  435. }
  436.  
  437.  
  438. /***
  439. *HRESULT CRemPoly::GetXOrigin(short*)
  440. *
  441. *Purpose:
  442. *  Invoke the GetXOrigin() method on the remote object to extract
  443. *  the current value of the XOrigin property.
  444. *
  445. *Entry:
  446. *  None
  447. *
  448. *Exit:
  449. *  return value = HRESULT
  450. *
  451. *  *pxorg = the current X origin of the polygon.
  452. *
  453. ***********************************************************************/
  454. HRESULT
  455. CRemPoly::GetXOrigin(short FAR* pxorg)
  456. {
  457.     HRESULT hresult;
  458.     VARIANT varResult;
  459.  
  460.     VariantInit(&varResult);
  461.     hresult = m_pdisp->Invoke(
  462.       m_rgdispid[IMETH_CREMPOLY_GETXORIGIN],
  463.       IID_NULL,
  464.       LOCALE_USER_DEFAULT,
  465.       DISPATCH_METHOD,
  466.       &g_dispparamsNoArgs, &varResult, NULL, NULL);
  467.  
  468.     if(hresult != NOERROR)
  469.       return hresult;
  470.  
  471.     *pxorg = V_I2(&varResult);
  472.     VariantClear(&varResult);
  473.     
  474.     return NOERROR;
  475. }
  476.  
  477.  
  478. /***
  479. *HRESULT CRemPoly::SetXOrigin(short)
  480. *
  481. *Purpose:
  482. *  Invoke the SetXOrigin method on the remote object to set the
  483. *  XOrigin property of the polygon to the given value.
  484. *
  485. *Entry:
  486. *  xorg = the new X origin
  487. *
  488. *Exit:
  489. *  return value = HRESULT
  490. *
  491. ***********************************************************************/
  492. HRESULT
  493. CRemPoly::SetXOrigin(short xorg)
  494. {
  495.     VARIANTARG varg;
  496.     DISPPARAMS dispparams;
  497.  
  498.  
  499.     V_VT(&varg) = VT_I2;
  500.     V_I2(&varg) = xorg;
  501.  
  502.     dispparams.cArgs = 1;
  503.     dispparams.cNamedArgs = 0;
  504.     dispparams.rgvarg = &varg;
  505.  
  506.     return m_pdisp->Invoke(
  507.       m_rgdispid[IMETH_CREMPOLY_SETXORIGIN],
  508.       IID_NULL,
  509.       LOCALE_USER_DEFAULT,
  510.       DISPATCH_METHOD,
  511.       &dispparams, NULL, NULL, NULL);
  512. }
  513.  
  514.  
  515. /***
  516. *HRESULT CRemPoly::GetYOrigin(short*)
  517. *
  518. *Purpose:
  519. *  Invoke the GetYOrigin() method on the remote object to extract
  520. *  the current value of the YOrigin property.
  521. *
  522. *Entry:
  523. *  None
  524. *
  525. *Exit:
  526. *  return value = HRESULT
  527. *
  528. *  *pyorg = the current Y origin of the polygon
  529. *
  530. ***********************************************************************/
  531. HRESULT
  532. CRemPoly::GetYOrigin(short FAR* pyorg)
  533. {
  534.     HRESULT hresult;
  535.     VARIANT varResult;
  536.  
  537.  
  538.     VariantInit(&varResult);
  539.     hresult = m_pdisp->Invoke(
  540.       m_rgdispid[IMETH_CREMPOLY_GETYORIGIN],
  541.       IID_NULL,
  542.       LOCALE_USER_DEFAULT,
  543.       DISPATCH_METHOD,
  544.       &g_dispparamsNoArgs, &varResult, NULL, NULL);
  545.  
  546.     if(hresult != NOERROR)
  547.       return hresult;
  548.  
  549.     *pyorg = V_I2(&varResult);
  550.     VariantClear(&varResult);
  551.     
  552.     return hresult;
  553. }
  554.  
  555.  
  556. /***
  557. *HRESULT CRemPoly::SetYOrigin(short)
  558. *
  559. *Purpose:
  560. *  Invoke the SetYOrigin method on the remote object to set the
  561. *  YOrigin property of the polygon to the given value.
  562. *
  563. *Entry:
  564. *  yorg = the new Y origin
  565. *
  566. *Exit:
  567. *  return value = HRESULT
  568. *
  569. ***********************************************************************/
  570. HRESULT
  571. CRemPoly::SetYOrigin(short yorg)
  572. {
  573.     VARIANTARG varg;
  574.     DISPPARAMS dispparams;
  575.  
  576.     V_VT(&varg) = VT_I2;
  577.     V_I2(&varg) = yorg;
  578.  
  579.     dispparams.cArgs = 1;
  580.     dispparams.cNamedArgs = 0;
  581.     dispparams.rgvarg = &varg;
  582.  
  583.     return m_pdisp->Invoke(
  584.       m_rgdispid[IMETH_CREMPOLY_SETYORIGIN],
  585.       IID_NULL,
  586.       LOCALE_USER_DEFAULT,
  587.       DISPATCH_METHOD,
  588.       &dispparams, NULL, NULL, NULL);
  589. }
  590.  
  591.  
  592. /***
  593. *HRESULT CRemPoly::GetWidth(short*)
  594. *
  595. *Purpose:
  596. *  Invoke the GetWidth() method on the remote object to extract
  597. *  the current value of the line width property.
  598. *
  599. *Entry:
  600. *  None
  601. *
  602. *Exit:
  603. *  return value = HRESULT
  604. *
  605. *  *pwidth = short, the current line width of the polygon
  606. *
  607. ***********************************************************************/
  608. HRESULT
  609. CRemPoly::GetWidth(short FAR* pwidth)
  610. {
  611.     HRESULT hresult;
  612.     VARIANT varResult;
  613.  
  614.     VariantInit(&varResult);
  615.     hresult = m_pdisp->Invoke(
  616.       m_rgdispid[IMETH_CREMPOLY_GETWIDTH],
  617.       IID_NULL,
  618.       LOCALE_USER_DEFAULT,
  619.       DISPATCH_METHOD,
  620.       &g_dispparamsNoArgs, &varResult, NULL, NULL);
  621.  
  622.     if(hresult != NOERROR)
  623.       return hresult;
  624.  
  625.     *pwidth = V_I2(&varResult);
  626.     VariantClear(&varResult);
  627.     return NOERROR;
  628. }
  629.  
  630.  
  631. /***
  632. *HRESULT CRemPoly::SetWidth(short)
  633. *
  634. *Purpose:
  635. *  Invoke the SetWidth method on the remote object to set the
  636. *  line width property of the polygon to the given value.
  637. *
  638. *Entry:
  639. *  width = the new value for the line width property.
  640. *
  641. *Exit:
  642. *  return value = HRESULT
  643. *
  644. ***********************************************************************/
  645. HRESULT
  646. CRemPoly::SetWidth(short width)
  647. {
  648.     VARIANTARG varg;
  649.     DISPPARAMS dispparams;
  650.  
  651.  
  652.     V_VT(&varg) = VT_I2;
  653.     V_I2(&varg) = width;
  654.  
  655.     dispparams.cArgs = 1;
  656.     dispparams.cNamedArgs = 0;
  657.     dispparams.rgvarg = &varg;
  658.  
  659.     return m_pdisp->Invoke(
  660.       m_rgdispid[IMETH_CREMPOLY_SETWIDTH],
  661.       IID_NULL,
  662.       LOCALE_USER_DEFAULT,
  663.       DISPATCH_METHOD,
  664.       &dispparams, NULL, NULL, NULL);
  665. }
  666.  
  667.  
  668. HRESULT CRemPoly::get_red(short FAR* psRed)
  669. {
  670.     return get_i2(m_rgdispid[IMETH_CREMPOLY_GETRED], psRed);
  671. }
  672.  
  673. HRESULT CRemPoly::set_red(short sRed)
  674. {
  675.     return set_i2(m_rgdispid[IMETH_CREMPOLY_SETRED], sRed);
  676. }
  677.  
  678.  
  679. HRESULT CRemPoly::get_green(short FAR* psGreen)
  680. {
  681.     return get_i2(m_rgdispid[IMETH_CREMPOLY_GETGREEN], psGreen);
  682. }
  683.  
  684. HRESULT CRemPoly::set_green(short sGreen)
  685. {
  686.     return set_i2(m_rgdispid[IMETH_CREMPOLY_SETGREEN], sGreen);
  687. }
  688.  
  689.  
  690. HRESULT CRemPoly::get_blue(short FAR* psBlue)
  691. {
  692.     return get_i2(m_rgdispid[IMETH_CREMPOLY_GETBLUE], psBlue);
  693. }
  694.  
  695. HRESULT CRemPoly::set_blue(short sBlue)
  696. {
  697.     return set_i2(m_rgdispid[IMETH_CREMPOLY_SETBLUE], sBlue);
  698. }
  699.  
  700. HRESULT
  701. CRemPoly::get_i2(DISPID dispid, short FAR* ps)
  702. {
  703.     HRESULT hresult;
  704.     VARIANT varResult;
  705.  
  706.     VariantInit(&varResult);
  707.  
  708.     hresult = m_pdisp->Invoke(
  709.       dispid,
  710.       IID_NULL,
  711.       LOCALE_SYSTEM_DEFAULT,
  712.       DISPATCH_METHOD,
  713.       &g_dispparamsNoArgs,
  714.       &varResult, NULL, NULL);
  715.  
  716.     if(hresult != NOERROR)
  717.       return hresult;
  718.  
  719.     hresult = VariantChangeType(&varResult, &varResult, 0, VT_I2);
  720.     if(hresult != NOERROR){
  721.       VariantClear(&varResult);
  722.       return hresult;
  723.     }
  724.  
  725.     *ps = V_I2(&varResult);
  726.     VariantClear(&varResult);
  727.     return NOERROR;
  728. }
  729.  
  730. HRESULT
  731. CRemPoly::set_i2(DISPID dispid, short s)
  732. {
  733.     VARIANTARG varg;
  734.     DISPPARAMS dispparams;
  735.  
  736.     V_VT(&varg) = VT_I2;
  737.     V_I2(&varg) = s;
  738.  
  739.     dispparams.cArgs = 1;
  740.     dispparams.cNamedArgs = 0;
  741.     dispparams.rgvarg = &varg;
  742.  
  743.     return m_pdisp->Invoke(
  744.       dispid,
  745.       IID_NULL,
  746.       LOCALE_SYSTEM_DEFAULT,
  747.       DISPATCH_METHOD,
  748.       &dispparams, NULL, NULL, NULL);
  749. }
  750.  
  751.  
  752. /***
  753. *void DoPoly(CLSID) 
  754. *
  755. *Purpose:
  756. *  This function simply exercises our CRemPoly class by creating an
  757. *  instance and invoking a number of its methods.
  758. *
  759. *Entry:
  760. *  None
  761. *
  762. *Exit:
  763. *  None
  764. *
  765. ***********************************************************************/
  766. STDAPI
  767. DoPoly(CLSID clsid)
  768. {
  769.     HRESULT hr;
  770.     int numpoly, i, j;
  771.  
  772. static struct {
  773.     short x;
  774.     short y;
  775. } rgptPoly[] = {
  776.       { 25,   0}
  777.     , { 75,   0}
  778.     , {100,  25}
  779.     , {100,  75}
  780.     , { 75, 100}
  781.     , { 25, 100}
  782.     , {  0,  75}
  783.     , {  0,  25}
  784. };
  785.  
  786. static struct {
  787.     short red;
  788.     short green;
  789.     short blue;
  790. } rgrgbColors[] = {
  791. #ifdef _MAC
  792.       {     0,      0,      0}
  793.     , {     0,      0, 0x7fff}
  794.     , {     0, 0x7fff,      0}
  795.     , {0x7fff,      0,      0}
  796.     , {0x7fff,      0, 0x7fff}
  797.     , {0x7fff, 0x7fff,      0}
  798.     , {0x7fff, 0x7fff, 0x7fff}
  799. #else
  800.       {  0,   0,   0}
  801.     , {  0,   0, 127}
  802.     , {  0, 127,   0}
  803.     , {127,   0,   0}
  804.     , {127,   0, 127}
  805.     , {127, 127,   0}
  806.     , {127, 127, 127}
  807. #endif
  808. };
  809.  
  810.     CRemPoly FAR* rgprempoly[DIM(rgrgbColors)];
  811.  
  812.     numpoly = DIM(rgprempoly);
  813.  
  814.     // init
  815.     for(i = 0; i < numpoly; ++i)
  816.       rgprempoly[i] = (CRemPoly FAR*)NULL;
  817.  
  818.     for(i = 0; i < numpoly; ++i){
  819.       hr = CRemPoly::Create(clsid, &rgprempoly[i]);
  820.       if(hr != NOERROR)
  821.         goto LError0;
  822.       IfMac(DbPrintf("CRemPoly::Create()"));
  823.  
  824.       for(j = 0; j < DIM(rgptPoly); ++j){
  825.         short x = rgptPoly[j].x;
  826.     short y = rgptPoly[j].y;
  827.         IfMac(DbPrintf("CRemPoly::AddPoint(%d,%d)", x, y));
  828.         hr = rgprempoly[i]->AddPoint(x, y);
  829.     ASSERT(hr == NOERROR);
  830.       }
  831.  
  832.       for(j = 0; j < DIM(rgrgbColors); ++j){
  833.         hr = rgprempoly[i]->SetWidth(i + j);
  834.     ASSERT(hr == NOERROR);
  835.     IfMac(DbPrintf("CRemPoly::SetWidth()"));
  836.  
  837.         hr = rgprempoly[i]->set_red(rgrgbColors[j].red);
  838.     ASSERT(hr == NOERROR);
  839.     IfMac(DbPrintf("CRemPoly::set_red()"));
  840.  
  841.         hr = rgprempoly[i]->set_green(rgrgbColors[j].green);
  842.     ASSERT(hr == NOERROR);
  843.     IfMac(DbPrintf("CRemPoly::set_green()"));
  844.  
  845.         hr = rgprempoly[i]->set_blue(rgrgbColors[j].blue);
  846.     ASSERT(hr == NOERROR);
  847.     IfMac(DbPrintf("CRemPoly::set_blue()"));
  848.  
  849.         hr = rgprempoly[i]->SetXOrigin((2*i) + j << 4);
  850.     ASSERT(hr == NOERROR);
  851.     IfMac(DbPrintf("CRemPoly::SetXOrigin()"));
  852.  
  853.         hr = rgprempoly[i]->SetYOrigin(j << 4);
  854.     ASSERT(hr == NOERROR);
  855.     IfMac(DbPrintf("CRemPoly::SetYOrigin()"));
  856.  
  857.         hr = rgprempoly[i]->Draw();
  858.     ASSERT(hr == NOERROR);
  859.     IfMac(DbPrintf("CRemPoly::Draw()"));
  860.       }
  861.     }
  862.  
  863.     hr = NOERROR;
  864.  
  865. LError0:;
  866.     for(i = 0; i < numpoly; ++i){
  867.       if(rgprempoly[i] != (CRemPoly FAR*)NULL){
  868.     rgprempoly[i]->Release();
  869.       }
  870.     }
  871.  
  872.     return hr;
  873. }
  874.  
  875.