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 / spoly / cpoint.cpp < prev    next >
C/C++ Source or Header  |  1997-08-01  |  9KB  |  396 lines

  1. /*** 
  2. *cpoint.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 module implements the CPoint and CPointCF classes.
  14. *
  15. *  This module is intended as a sample implementation of the IDispatch
  16. *  interface, and its purpose is to demonstrate how an object can
  17. *  expose methods and properties for programatic and cross-process
  18. *  access via the IDispatch interface.
  19. *
  20. *Implementation Notes:
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "spoly.h"
  25. #include "cpoint.h"
  26.  
  27.  
  28. CPoint::CPoint()
  29. {
  30.     m_x = 0;
  31.     m_y = 0;
  32.     m_refs = 0;
  33. }
  34.  
  35. /***
  36. *CPoint::Create(void)
  37. *Purpose:
  38. *  Create an instance of a CPoint object.
  39. *
  40. *Entry:
  41. *  None
  42. *
  43. *Exit:
  44. *  returns a CPoint*, NULL if creation failed.
  45. *
  46. ***********************************************************************/
  47. CPoint FAR*
  48. CPoint::Create()
  49. {
  50.     CPoint FAR* ppoint;
  51.  
  52.     if((ppoint = new FAR CPoint()) == NULL)
  53.       return NULL;
  54.     ppoint->AddRef();
  55.     return ppoint;
  56. }
  57.  
  58.  
  59. //---------------------------------------------------------------------
  60. //                     IUnknown Methods
  61. //---------------------------------------------------------------------
  62.  
  63.  
  64. STDMETHODIMP
  65. CPoint::QueryInterface(REFIID riid, void FAR* FAR* ppv)
  66. {
  67.     if(!IsEqualIID(riid, IID_IUnknown))
  68.       if(!IsEqualIID(riid, IID_IDispatch)) {
  69.         *ppv = NULL;              
  70.         return E_NOINTERFACE;
  71.     }
  72.  
  73.     *ppv = this;
  74.     AddRef();
  75.     return NOERROR;
  76. }
  77.  
  78.  
  79. STDMETHODIMP_(unsigned long)
  80. CPoint::AddRef(void)
  81. {
  82.     return ++m_refs;
  83. }
  84.  
  85.  
  86. STDMETHODIMP_(unsigned long)
  87. CPoint::Release(void)
  88. {
  89.     if(--m_refs == 0){
  90.       delete this;
  91.       return 0;
  92.     }
  93.     return m_refs;
  94. }
  95.  
  96.  
  97. //---------------------------------------------------------------------
  98. //                     IDispatch methods
  99. //---------------------------------------------------------------------
  100.  
  101. /*
  102.  * NOTE: Support for the following two methods is not available
  103.  * in this version.
  104.  *
  105.  */
  106.  
  107. STDMETHODIMP
  108. CPoint::GetTypeInfoCount(unsigned int FAR* pctinfo)
  109. {
  110.     *pctinfo = 0;
  111.     return NOERROR;
  112. }
  113.  
  114.  
  115. STDMETHODIMP
  116. CPoint::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  117. {
  118.     UNUSED(itinfo);
  119.     UNUSED(lcid);
  120.     UNUSED(pptinfo);
  121.  
  122.     return E_NOTIMPL;
  123. }
  124.  
  125.  
  126. /***
  127. *HRESULT CPoint::GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, long*)
  128. *Purpose:
  129. *  This method translates the given array of names to a corresponding
  130. *  array of DISPIDs.
  131. *
  132. *  Index 0 of the name array is the member name, and indices 1-N if
  133. *  present represent named parameters on that member.
  134. *
  135. *  The local ID ('lcid') is unused by this naive implementation. A more
  136. *  sophisticated implementation, sensitive to localization and natural
  137. *  language support would use the locale ID to interpret the given names
  138. *  in a correct locale specific context.
  139. *
  140. *Entry:
  141. *  rgszNames = pointer to an array of names
  142. *  cNames = the number of names in the rgszNames array
  143. *  lcid = the callers locale ID
  144. *
  145. *Exit:
  146. *  return value = HRESULT
  147. *  rgid = array of name IDs corresponding to the rgszNames array
  148. *    this array will contain -1 for each entry that is not known.
  149. *
  150. ***********************************************************************/
  151. STDMETHODIMP
  152. CPoint::GetIDsOfNames(
  153.     REFIID riid,
  154.     OLECHAR FAR* FAR* rgszNames,
  155.     unsigned int cNames,
  156.     LCID lcid,
  157.     DISPID FAR* rgdispid)
  158. {
  159. static MEMBERDESC rgmdCPoint[] = {
  160.     {OLESTR("GETX"),    IDMEMBER_CPOINT_GETX,    NULL,    0},
  161.     {OLESTR("SETX"),    IDMEMBER_CPOINT_SETX,    NULL,    0},
  162.     {OLESTR("GETY"),    IDMEMBER_CPOINT_GETY,    NULL,    0},
  163.     {OLESTR("SETY"),    IDMEMBER_CPOINT_SETY,    NULL,    0}
  164. };
  165.  
  166.     // this object only exposed the "default" interface.
  167.     //
  168.     if(!IsEqualIID(riid, IID_NULL))
  169.       return DISP_E_UNKNOWNINTERFACE;
  170.  
  171.     return SPolyGetIDsOfNames(
  172.       rgmdCPoint, DIM(rgmdCPoint), rgszNames, cNames, lcid, rgdispid);
  173. }
  174.  
  175.  
  176. /***
  177. *HRESULT CPoint::Invoke(...)
  178. *Purpose:
  179. *  Dispatch a method or property request for objects of type CPoint.
  180. *
  181. *  see the IDispatch document for more information, and a general
  182. *  description of this method.
  183. *
  184. *Entry:
  185. *  dispidMember = the DISPID of the member being requested
  186. *
  187. *  riid = reference to the interface ID of the interface on this object
  188. *    that the requested member belongs to. IID_NULL means to interpret
  189. *    the member as belonging to the implementation defined "default"
  190. *    or "primary" interface.
  191. *
  192. *  lcid = the caller's locale ID
  193. *
  194. *  wFlags = flags indicating the type of access being requested
  195. *
  196. *  pdispparams = pointer to the DISPPARAMS struct containing the
  197. *    requested members arguments (if any) and its named parameter
  198. *    DISPIDs (if any).
  199. *
  200. *Exit:
  201. *  return value = HRESULT
  202. *   see the IDispatch spec for a description of possible success codes.
  203. *
  204. *  pvarResult = pointer to a caller allocated VARIANT containing
  205. *    the members return value (if any).
  206. *
  207. *  pexcepinfo = caller allocated exception info structure, this will
  208. *    be filled in only if an exception was raised that must be passed
  209. *    up through Invoke to an enclosing handler.
  210. *
  211. *  puArgErr = pointer to a caller allocated UINT, that will contain the
  212. *    index of the offending argument if a DISP_E_TYPEMISMATCH error
  213. *    was returned indicating that one of the arguments was of an
  214. *    incorrect type and/or could not be reasonably coerced to a proper
  215. *    type.
  216. *
  217. ***********************************************************************/
  218. STDMETHODIMP
  219. CPoint::Invoke(
  220.     DISPID dispidMember,
  221.     REFIID riid,
  222.     LCID lcid,
  223.     unsigned short wFlags,
  224.     DISPPARAMS FAR* pdispparams,
  225.     VARIANT FAR* pvarResult,
  226.     EXCEPINFO FAR* pexcepinfo,
  227.     unsigned int FAR* puArgErr)
  228. {
  229.     unsigned int uArgErr;
  230.     HRESULT hresult;
  231.     VARIANTARG varg0;
  232.     VARIANT varResultDummy;
  233.  
  234.     UNUSED(lcid);
  235.     UNUSED(pexcepinfo);
  236.  
  237.     // make sure the wFlags are legal
  238.     if(wFlags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
  239.       return E_INVALIDARG;
  240.  
  241.     // this object only exposes a "default" interface.
  242.     //
  243.     if(!IsEqualIID(riid, IID_NULL))
  244.       return DISP_E_UNKNOWNINTERFACE;
  245.  
  246.     // this makes the following code a bit simpler
  247.     if(puArgErr == NULL)
  248.       puArgErr = &uArgErr;
  249.     if(pvarResult == NULL)
  250.       pvarResult = &varResultDummy;
  251.  
  252.     VariantInit(&varg0);
  253.  
  254.     // assume the return type is void, unless we find otherwise.
  255.     VariantInit(pvarResult);
  256.  
  257.     switch(dispidMember){
  258.     case IDMEMBER_CPOINT_GETX:
  259.       V_VT(pvarResult) = VT_I2;
  260.       V_I2(pvarResult) = GetX();
  261.       break;
  262.  
  263.     case IDMEMBER_CPOINT_SETX:
  264.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  265.       if(hresult != NOERROR)
  266.         return hresult;
  267.       SetX(V_I2(&varg0));
  268.       break;
  269.  
  270.     case IDMEMBER_CPOINT_GETY:
  271.       V_VT(pvarResult) = VT_I2;
  272.       V_I2(pvarResult) = GetY();
  273.       break;
  274.  
  275.     case IDMEMBER_CPOINT_SETY:
  276.       hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
  277.       if(hresult != NOERROR)
  278.         return hresult;
  279.       SetY(V_I2(&varg0));
  280.       break;
  281.  
  282.     default:
  283.       return DISP_E_MEMBERNOTFOUND;
  284.     }
  285.     return NOERROR;
  286. }
  287.  
  288. short PASCAL
  289. CPoint::GetX()
  290. {
  291.     return m_x;
  292. }
  293.  
  294. void PASCAL
  295. CPoint::SetX(short x)
  296. {
  297.     m_x = x;
  298. }
  299.  
  300. short PASCAL
  301. CPoint::GetY()
  302. {
  303.     return m_y;
  304. }
  305.  
  306. void PASCAL
  307. CPoint::SetY(short y)
  308. {
  309.     m_y = y;
  310. }
  311.  
  312.  
  313. //---------------------------------------------------------------------
  314. //         Implementation of the CPoint Class Factory
  315. //---------------------------------------------------------------------
  316.  
  317. CPointCF::CPointCF()
  318. {
  319.     m_refs = 0;
  320. }
  321.  
  322. IClassFactory FAR*
  323. CPointCF::Create()
  324. {
  325.     CPointCF FAR* pCF;
  326.  
  327.     if((pCF = new FAR CPointCF()) == NULL)
  328.       return NULL;
  329.     pCF->AddRef();
  330.     return pCF;
  331. }
  332.  
  333. STDMETHODIMP
  334. CPointCF::QueryInterface(REFIID riid, void FAR* FAR* ppv) 
  335.  
  336.     if(!IsEqualIID(riid, IID_IUnknown))
  337.       if(!IsEqualIID(riid, IID_IClassFactory)) {
  338.         *ppv = NULL;              
  339.         return E_NOINTERFACE;
  340.     }
  341.     
  342.     *ppv = this;
  343.     ++m_refs;
  344.     return NOERROR;
  345. }
  346.  
  347. STDMETHODIMP_(unsigned long)
  348. CPointCF::AddRef(void)
  349. {
  350.     return ++m_refs;
  351. }
  352.  
  353. STDMETHODIMP_(unsigned long)
  354. CPointCF::Release(void)
  355. {
  356.     if(--m_refs == 0){
  357.       delete this;
  358.       return 0;
  359.     }
  360.     return m_refs;
  361. }
  362.  
  363. STDMETHODIMP
  364. CPointCF::CreateInstance(
  365.     IUnknown FAR* punkOuter,
  366.     REFIID riid,
  367.     void FAR* FAR* ppv)
  368. {
  369.     HRESULT hresult;
  370.     CPoint FAR *ppoint;
  371.  
  372.     UNUSED(punkOuter);
  373.  
  374.     if((ppoint = CPoint::Create()) == NULL){
  375.       *ppv = NULL;
  376.       return E_OUTOFMEMORY;
  377.     }
  378.     hresult = ppoint->QueryInterface(riid, ppv);
  379.     ppoint->Release();
  380.     return hresult;
  381. }
  382.  
  383. STDMETHODIMP
  384. #ifdef _MAC
  385. CPointCF::LockServer(unsigned long fLock)
  386. #else
  387. CPointCF::LockServer(BOOL fLock)
  388. #endif
  389. {
  390.     UNUSED(fLock);
  391.  
  392.     return NOERROR;
  393. }
  394.  
  395.