home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / INCLUDE / COMIP.H < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-08  |  21.5 KB  |  975 lines

  1. /***
  2. * comip.h - Native C++ compiler COM support - COM interface pointers header
  3. *
  4. *    Copyright (C) 1996-1997 Microsoft Corporation
  5. *    All rights reserved.
  6. *
  7. ****/
  8.  
  9. #if _MSC_VER > 1000
  10. #pragma once
  11. #endif
  12.  
  13. #if !defined(_INC_COMIP)
  14. #define _INC_COMIP
  15.  
  16. #include <ole2.h>
  17. #include <malloc.h>
  18.  
  19. #include <comutil.h>
  20.  
  21. class _com_error;
  22.  
  23. void __stdcall _com_issue_error(HRESULT);
  24. struct __declspec(uuid("00000000-0000-0000-c000-000000000046")) IUnknown;
  25.  
  26. // Provide Interface to IID association
  27. //
  28. template<typename _Interface, const IID* _IID /*= &__uuidof(_Interface)*/> class _com_IIID {
  29. public:
  30.     typedef _Interface Interface;
  31.  
  32.     static _Interface* GetInterfacePtr() throw()
  33.     {
  34.         return NULL;
  35.     }
  36.  
  37.     static _Interface& GetInterface() throw()
  38.     {
  39.         return *GetInterfacePtr();
  40.     }
  41.  
  42.     static const IID& GetIID() throw()
  43.     {
  44.         return *_IID;
  45.     }
  46. };
  47.  
  48. template<typename _IIID> class _com_ptr_t {
  49. public:
  50.     // Declare interface type so that the type may be available outside
  51.     // the scope of this template.
  52.     //
  53.     typedef _IIID ThisIIID;
  54.     typedef typename _IIID::Interface Interface;
  55.  
  56.     // When the compiler supports references in template parameters,
  57.     // _CLSID will be changed to a reference.  To avoid conversion
  58.     // difficulties this function should be used to obtain the
  59.     // CLSID.
  60.     //
  61.     static const IID& GetIID() throw()
  62.     { 
  63.         return ThisIIID::GetIID(); 
  64.     }
  65.  
  66.     // Constructs a smart-pointer from any interface pointer.
  67.     //
  68.     template<typename _InterfacePtr> _com_ptr_t(const _InterfacePtr& p) throw(_com_error)
  69.         : m_pInterface(NULL)
  70.     {
  71.         if (p) {
  72.             HRESULT hr = _QueryInterface(p);
  73.  
  74.             if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  75.                 _com_issue_error(hr);
  76.             }
  77.         }
  78.     }
  79.  
  80.     // Default constructor.
  81.     //
  82.     _com_ptr_t() throw()
  83.         : m_pInterface(NULL)
  84.     {
  85.     }
  86.  
  87.     // This constructor is provided to allow NULL assignment. It will issue
  88.     // an error if any value other than null is assigned to the object.
  89.     //
  90.     _com_ptr_t(int null) throw(_com_error)
  91.         : m_pInterface(NULL)
  92.     {
  93.         if (null != 0) {
  94.             _com_issue_error(E_POINTER);
  95.         }
  96.     }
  97.  
  98.     // Copy the pointer and AddRef().
  99.     //
  100.     template<> _com_ptr_t(const _com_ptr_t& cp) throw()
  101.         : m_pInterface(cp.m_pInterface)
  102.     { 
  103.         _AddRef(); 
  104.     }
  105.  
  106.     // Saves the interface.
  107.     //
  108.     _com_ptr_t(Interface* pInterface) throw()
  109.         : m_pInterface(pInterface)
  110.     { 
  111.         _AddRef(); 
  112.     }
  113.  
  114.     // Copies the pointer. If fAddRef is TRUE, the interface will
  115.     // be AddRef()ed.
  116.     //
  117.     _com_ptr_t(Interface* pInterface, bool fAddRef) throw()
  118.         : m_pInterface(pInterface)
  119.     {
  120.         if (fAddRef) {
  121.             _AddRef();
  122.         }
  123.     }
  124.  
  125.     // Construct a pointer for a _variant_t object.
  126.     //
  127.     template<> _com_ptr_t(const _variant_t& varSrc) throw(_com_error)
  128.         : m_pInterface(NULL)
  129.     {
  130.         HRESULT hr = QueryStdInterfaces(varSrc);
  131.  
  132.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  133.             _com_issue_error(hr);
  134.         }
  135.     }
  136.  
  137.     // Calls CoCreateClass with the provided CLSID.
  138.     //
  139.     explicit _com_ptr_t(const CLSID& clsid, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw(_com_error)
  140.         : m_pInterface(NULL)
  141.     {
  142.         HRESULT hr = CreateInstance(clsid, pOuter, dwClsContext);
  143.  
  144.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  145.             _com_issue_error(hr);
  146.         }
  147.     }
  148.  
  149.     // Calls CoCreateClass with the provided CLSID retrieved from
  150.     // the string.
  151.     //
  152.     explicit _com_ptr_t(LPOLESTR str, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw(_com_error)
  153.         : m_pInterface(NULL)
  154.     {
  155.         HRESULT hr = CreateInstance(str, pOuter, dwClsContext);
  156.  
  157.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  158.             _com_issue_error(hr);
  159.         }
  160.     }
  161.  
  162.     // Calls CoCreateClass with the provided SBCS CLSID retrieved from
  163.     // the string.
  164.     //
  165.     explicit _com_ptr_t(LPCSTR str, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw(_com_error)
  166.         : m_pInterface(NULL)
  167.     {
  168.         HRESULT hr = CreateInstance(str, pOuter, dwClsContext);
  169.  
  170.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  171.             _com_issue_error(hr);
  172.         }
  173.     }
  174.  
  175.     // Queries for interface.
  176.     //
  177.     template<typename _InterfacePtr> _com_ptr_t& operator=(const _InterfacePtr& p) throw(_com_error)
  178.     {
  179.         HRESULT hr = _QueryInterface(p);
  180.  
  181.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  182.             _com_issue_error(hr);
  183.         }
  184.  
  185.         return *this;
  186.     }
  187.  
  188.     // Saves the interface.
  189.     //
  190.     _com_ptr_t& operator=(Interface* pInterface) throw()
  191.     {
  192.         if (m_pInterface != pInterface) {
  193.             Interface* pOldInterface = m_pInterface;
  194.  
  195.             m_pInterface = pInterface;
  196.  
  197.             _AddRef();
  198.  
  199.             if (pOldInterface != NULL) {
  200.                 pOldInterface->Release();
  201.             }
  202.         }
  203.  
  204.         return *this;
  205.     }
  206.  
  207.     // Copies and AddRef()'s the interface.
  208.     //
  209.     template<> _com_ptr_t& operator=(const _com_ptr_t& cp) throw()
  210.     { 
  211.         return operator=(cp.m_pInterface); 
  212.     }
  213.  
  214.     // This operator is provided to permit the assignment of NULL to the class.
  215.     // It will issue an error if any value other than NULL is assigned to it.
  216.     //
  217.     _com_ptr_t& operator=(int null) throw(_com_error)
  218.     {
  219.         if (null != 0) {
  220.             _com_issue_error(E_POINTER);
  221.         }
  222.  
  223.         return operator=(reinterpret_cast<Interface*>(NULL));
  224.     }
  225.  
  226.     // Construct a pointer for a _variant_t object.
  227.     //
  228.     template<> _com_ptr_t& operator=(const _variant_t& varSrc) throw(_com_error)
  229.     {
  230.         Interface* pOldInterface = m_pInterface;
  231.         HRESULT hr = QueryStdInterfaces(varSrc);
  232.  
  233.         if (FAILED(hr) && (hr != E_NOINTERFACE)) {
  234.             _com_issue_error(hr);
  235.         }
  236.  
  237.         _AddRef();
  238.  
  239.         if (pOldInterface != NULL) {
  240.             pOldInterface->Release();
  241.         }
  242.  
  243.         return *this;
  244.     }
  245.  
  246.     // If we still have an interface then Release() it. The interface
  247.     // may be NULL if Detach() has previously been called, or if it was
  248.     // never set.
  249.     //
  250.     ~_com_ptr_t() throw()
  251.     { 
  252.         _Release(); 
  253.     }
  254.  
  255.     // Saves/sets the interface without AddRef()ing. This call
  256.     // will release any previously acquired interface.
  257.     //
  258.     void Attach(Interface* pInterface) throw()
  259.     {
  260.         _Release();
  261.         m_pInterface = pInterface;
  262.     }
  263.  
  264.     // Saves/sets the interface only AddRef()ing if fAddRef is TRUE.
  265.     // This call will release any previously acquired interface.
  266.     //
  267.     void Attach(Interface* pInterface, bool fAddRef) throw()
  268.     {
  269.         _Release();
  270.         m_pInterface = pInterface;
  271.  
  272.         if (fAddRef) {
  273.             if (pInterface != NULL) {
  274.                 pInterface->AddRef();
  275.             }
  276.         }
  277.     }
  278.  
  279.     // Simply NULL the interface pointer so that it isn't Released()'ed.
  280.     //
  281.     Interface* Detach() throw()
  282.     {
  283.         Interface* const old=m_pInterface;
  284.         m_pInterface = NULL;
  285.         return old;
  286.     }
  287.  
  288.     // Return the interface. This value may be NULL.
  289.     //
  290.     operator Interface*() const throw()
  291.     { 
  292.         return m_pInterface; 
  293.     }
  294.  
  295.     // Queries for the unknown and return it
  296.     // Provides minimal level error checking before use.
  297.     //
  298.     operator Interface&() const throw(_com_error)
  299.     { 
  300.         if (m_pInterface == NULL) {
  301.             _com_issue_error(E_POINTER);
  302.         }
  303.  
  304.         return *m_pInterface; 
  305.     }
  306.  
  307.     // Allows an instance of this class to act as though it were the
  308.     // actual interface. Also provides minimal error checking.
  309.     //
  310.     Interface& operator*() const throw(_com_error)
  311.     { 
  312.         if (m_pInterface == NULL) {
  313.             _com_issue_error(E_POINTER);
  314.         }
  315.  
  316.         return *m_pInterface; 
  317.     }
  318.  
  319.     // Returns the address of the interface pointer contained in this
  320.     // class. This is useful when using the COM/OLE interfaces to create
  321.     // this interface.
  322.     //
  323.     Interface** operator&() throw()
  324.     {
  325.         _Release();
  326.         m_pInterface = NULL;
  327.         return &m_pInterface;
  328.     }
  329.  
  330.     // Allows this class to be used as the interface itself.
  331.     // Also provides simple error checking.
  332.     //
  333.     Interface* operator->() const throw(_com_error)
  334.     { 
  335.         if (m_pInterface == NULL) {
  336.             _com_issue_error(E_POINTER);
  337.         }
  338.  
  339.         return m_pInterface; 
  340.     }
  341.  
  342.     // This operator is provided so that simple boolean expressions will
  343.     // work.  For example: "if (p) ...".
  344.     // Returns TRUE if the pointer is not NULL.
  345.     //
  346.     operator bool() const throw()
  347.     { 
  348.         return m_pInterface != NULL; 
  349.     }
  350.  
  351.     // Compare two pointers
  352.     //
  353.     template<typename _InterfacePtr> bool operator==(_InterfacePtr p) throw(_com_error)
  354.     {
  355.         return _CompareUnknown(p) == 0;
  356.     }
  357.  
  358.     // Compare with other interface
  359.     //
  360.     template<> bool operator==(Interface* p) throw(_com_error)
  361.     {
  362.         return (m_pInterface == p) ? true : _CompareUnknown(p) == 0;
  363.     }
  364.  
  365.     // Compares 2 _com_ptr_t's
  366.     //
  367.     template<> bool operator==(_com_ptr_t& p) throw()
  368.     {
  369.         return operator==(p.m_pInterface);
  370.     }
  371.  
  372.     // For comparison to NULL
  373.     //
  374.     template<> bool operator==(int null) throw(_com_error)
  375.     {
  376.         if (null != 0) {
  377.             _com_issue_error(E_POINTER);
  378.         }
  379.  
  380.         return m_pInterface == NULL;
  381.     }
  382.  
  383.     // Compare to pointers
  384.     //
  385.     template<typename _InterfacePtr> bool operator!=(_InterfacePtr p) throw(_com_error)
  386.     {
  387.         return _CompareUnknown(p) != 0;
  388.     }
  389.  
  390.     // Compare with other interface
  391.     //
  392.     template<> bool operator!=(Interface* p) throw(_com_error)
  393.     {
  394.         return (m_pInterface != p) ? true : _CompareUnknown(p) != 0;
  395.     }
  396.  
  397.     // Compares 2 _com_ptr_t's
  398.     //
  399.     template<> bool operator!=(_com_ptr_t& p) throw(_com_error)
  400.     {
  401.         return operator!=(p.m_pInterface);
  402.     }
  403.  
  404.     // For comparison to NULL
  405.     //
  406.     template<> bool operator!=(int null) throw(_com_error)
  407.     {
  408.         if (null != 0) {
  409.             _com_issue_error(E_POINTER);
  410.         }
  411.  
  412.         return m_pInterface != NULL;
  413.     }
  414.  
  415.     // Compare two pointers
  416.     //
  417.     template<typename _InterfacePtr> bool operator<(_InterfacePtr p) throw(_com_error)
  418.     {
  419.         return _CompareUnknown(p) < 0;
  420.     }
  421.  
  422.     // Compare with other interface
  423.     //
  424.     template<> bool operator<(Interface* p) throw(_com_error)
  425.     {
  426.         return (m_pInterface < p) ? true : _CompareUnknown(p) < 0;
  427.     }
  428.  
  429.     // Compares 2 _com_ptr_t's
  430.     //
  431.     template<> bool operator<(_com_ptr_t& p) throw(_com_error)
  432.     {
  433.         return operator<(p.m_pInterface);
  434.     }
  435.  
  436.     // For comparison with NULL
  437.     //
  438.     template<> bool operator<(int null) throw(_com_error)
  439.     {
  440.         if (null != 0) {
  441.             _com_issue_error(E_POINTER);
  442.         }
  443.  
  444.         return m_pInterface < NULL;
  445.     }
  446.  
  447.     // Compare to pointers
  448.     //
  449.     template<typename _InterfacePtr> bool operator>(_InterfacePtr p) throw(_com_error)
  450.     {
  451.         return _CompareUnknown(p) > 0;
  452.     }
  453.  
  454.     // Compare with other interface
  455.     //
  456.     template<> bool operator>(Interface* p) throw()
  457.     {
  458.         return (m_pInterface > p) ? true : _CompareUnknown(p) > 0;
  459.     }
  460.  
  461.     // Compares 2 _com_ptr_t's
  462.     //
  463.     template<> bool operator>(_com_ptr_t& p) throw(_com_error)
  464.     {
  465.         return operator>(p.m_pInterface);
  466.     }
  467.  
  468.     // For comparison with NULL
  469.     //
  470.     template<> bool operator>(int null) throw(_com_error)
  471.     {
  472.         if (null != 0) {
  473.             _com_issue_error(E_POINTER);
  474.         }
  475.  
  476.         return m_pInterface > NULL;
  477.     }
  478.  
  479.     // Compare two pointers
  480.     //
  481.     template<typename _InterfacePtr> bool operator<=(_InterfacePtr p) throw(_com_error)
  482.     {
  483.         return _CompareUnknown(p) <= 0;
  484.     }
  485.  
  486.     // Compare with other interface
  487.     //
  488.     template<> bool operator<=(Interface* p) throw()
  489.     {
  490.         return (m_pInterface <= p) ? true : _CompareUnknown(p) <= 0;
  491.     }
  492.  
  493.     // Compares 2 _com_ptr_t's
  494.     //
  495.     template<> bool operator<=(_com_ptr_t& p) throw(_com_error)
  496.     {
  497.         return operator<=(p.m_pInterface);
  498.     }
  499.  
  500.     // For comparison with NULL
  501.     //
  502.     template<> bool operator<=(int null) throw(_com_error)
  503.     {
  504.         if (null != 0) {
  505.             _com_issue_error(E_POINTER);
  506.         }
  507.  
  508.         return m_pInterface <= NULL;
  509.     }
  510.  
  511.     // Compare two pointers
  512.     //
  513.     template<typename _InterfacePtr> bool operator>=(_InterfacePtr p) throw(_com_error)
  514.     {
  515.         return _CompareUnknown(p) >= 0;
  516.     }
  517.  
  518.     // Compare with other interface
  519.     //
  520.     template<> bool operator>=(Interface* p) throw(_com_error)
  521.     {
  522.         return (m_pInterface >= p) ? true : _CompareUnknown(p) >= 0;
  523.     }
  524.  
  525.     // Compares 2 _com_ptr_t's
  526.     //
  527.     template<> bool operator>=(_com_ptr_t& p) throw(_com_error)
  528.     {
  529.         return operator>=(p.m_pInterface);
  530.     }
  531.  
  532.     // For comparison with NULL
  533.     //
  534.     template<> bool operator>=(int null) throw(_com_error)
  535.     {
  536.         if (null != 0) {
  537.             _com_issue_error(E_POINTER);
  538.         }
  539.  
  540.         return m_pInterface >= NULL;
  541.     }
  542.  
  543.     // Provides error-checking Release()ing of this interface.
  544.     //
  545.     void Release() throw(_com_error)
  546.     {
  547.         if (m_pInterface == NULL) {
  548.             _com_issue_error(E_POINTER);
  549.         }
  550.  
  551.         m_pInterface->Release();
  552.         m_pInterface = NULL;
  553.     }
  554.  
  555.     // Provides error-checking AddRef()ing of this interface.
  556.     //
  557.     void AddRef() throw(_com_error)
  558.     { 
  559.         if (m_pInterface == NULL) {
  560.             _com_issue_error(E_POINTER);
  561.         }
  562.  
  563.         m_pInterface->AddRef(); 
  564.     }
  565.  
  566.     // Another way to get the interface pointer without casting.
  567.     //
  568.     Interface* GetInterfacePtr() const throw()
  569.     { 
  570.         return m_pInterface; 
  571.     }
  572.  
  573.     // Loads an interface for the provided CLSID.
  574.     // Returns an HRESULT.  Any previous interface is released.
  575.     //
  576.     HRESULT CreateInstance(const CLSID& rclsid, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
  577.     {
  578.         HRESULT hr;
  579.  
  580.         _Release();
  581.  
  582.         if (dwClsContext & (CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)) {
  583.             IUnknown* pIUnknown;
  584.  
  585.             hr = CoCreateInstance(rclsid, pOuter, dwClsContext, __uuidof(IUnknown), reinterpret_cast<void**>(&pIUnknown));
  586.  
  587.             if (FAILED(hr)) {
  588.                 return hr;
  589.             }
  590.  
  591.             hr = OleRun(pIUnknown);
  592.  
  593.             if (FAILED(hr)) {
  594.                 return hr;
  595.             }
  596.  
  597.             hr = pIUnknown->QueryInterface(GetIID(), reinterpret_cast<void**>(&m_pInterface));
  598.  
  599.             if (FAILED(hr)) {
  600.                 return hr;
  601.             }
  602.  
  603.             pIUnknown->Release();
  604.         }
  605.         else {
  606.             hr = CoCreateInstance(rclsid, pOuter, dwClsContext, GetIID(), reinterpret_cast<void**>(&m_pInterface));
  607.         }
  608.  
  609.         return hr;
  610.     }
  611.  
  612.     // Creates the class specified by clsidString.  clsidString may
  613.     // contain a class id, or a prog id string.
  614.     //
  615.     HRESULT CreateInstance(LPOLESTR clsidString, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
  616.     {
  617.         if (clsidString == NULL) {
  618.             return E_INVALIDARG;
  619.         }
  620.  
  621.         CLSID clsid;
  622.         HRESULT hr;
  623.  
  624.         if (clsidString[0] == '{') {
  625.             hr = CLSIDFromString(clsidString, &clsid);
  626.         }
  627.         else {
  628.             hr = CLSIDFromProgID(clsidString, &clsid);
  629.         }
  630.  
  631.         if (FAILED(hr)) {
  632.             return hr;
  633.         }
  634.  
  635.         return CreateInstance(clsid, pOuter, dwClsContext);
  636.     }
  637.  
  638.     // Creates the class specified by SBCS clsidString.  clsidString may
  639.     // contain a class id, or a prog id string.
  640.     //
  641.     HRESULT CreateInstance(LPCSTR clsidStringA, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
  642.     {
  643.         if (clsidStringA == NULL) {
  644.             return E_INVALIDARG;
  645.         }
  646.  
  647.         int size = lstrlenA(clsidStringA) + 1;
  648.         LPOLESTR clsidStringW = static_cast<LPOLESTR>(_alloca(size * 2));
  649.  
  650.         clsidStringW[0] = '\0';
  651.  
  652.         if (MultiByteToWideChar(CP_ACP, 0, clsidStringA, -1, clsidStringW, size) == 0) {
  653.             return GetLastError();
  654.         }
  655.  
  656.         return CreateInstance(clsidStringW, pOuter, dwClsContext);
  657.     }
  658.  
  659.     // Attach to the active object specified by rclsid.
  660.     // Any previous interface is released.
  661.     //
  662.     HRESULT GetActiveObject(const CLSID& rclsid) throw()
  663.     {
  664.         _Release();
  665.  
  666.         IUnknown* pIUnknown;
  667.  
  668.         HRESULT hr = ::GetActiveObject(rclsid, NULL, &pIUnknown);
  669.  
  670.         if (FAILED(hr)) {
  671.             return hr;
  672.         }
  673.  
  674.         hr = pIUnknown->QueryInterface(GetIID(), reinterpret_cast<void**>(&m_pInterface));
  675.  
  676.         if (FAILED(hr)) {
  677.             return hr;
  678.         }
  679.  
  680.         pIUnknown->Release();
  681.  
  682.         return hr;
  683.     }
  684.  
  685.     // Attach to the active object specified by clsidString.
  686.     // First convert the LPOLESTR to a CLSID.
  687.     //
  688.     HRESULT GetActiveObject(LPOLESTR clsidString) throw()
  689.     {
  690.         if (clsidString == NULL) {
  691.             return E_INVALIDARG;
  692.         }
  693.  
  694.         CLSID clsid;
  695.         HRESULT hr;
  696.  
  697.         if (clsidString[0] == '{') {
  698.             hr = CLSIDFromString(clsidString, &clsid);
  699.         }
  700.         else {
  701.             hr = CLSIDFromProgID(clsidString, &clsid);
  702.         }
  703.  
  704.         if (FAILED(hr)) {
  705.             return hr;
  706.         }
  707.  
  708.         return GetActiveObject(clsid);
  709.     }
  710.  
  711.     // Attach to the active object specified by clsidStringA.
  712.     // First convert the LPCSTR to a LPOLESTR.
  713.     //
  714.     HRESULT GetActiveObject(LPCSTR clsidStringA) throw()
  715.     {
  716.         if (clsidStringA == NULL) {
  717.             return E_INVALIDARG;
  718.         }
  719.  
  720.         int size = lstrlenA(clsidStringA) + 1;
  721.         LPOLESTR clsidStringW = static_cast<LPOLESTR>(_alloca(size * 2));
  722.  
  723.         clsidStringW[0] = '\0';
  724.  
  725.         if (MultiByteToWideChar(CP_ACP, 0, clsidStringA, -1, clsidStringW, size) == 0) {
  726.             return GetLastError();
  727.         }
  728.  
  729.         return GetActiveObject(clsidStringW);
  730.     }
  731.  
  732.     // Performs the QI for the specified IID and returns it in p.
  733.     // As with all QIs, the interface will be AddRef'd.
  734.     //
  735.     template<typename _InterfaceType> HRESULT QueryInterface(const IID& iid, _InterfaceType*& p) throw ()
  736.     {
  737.         if (m_pInterface != NULL) {
  738.             return m_pInterface->QueryInterface(iid, reinterpret_cast<void**>(&p));
  739.         }
  740.  
  741.         return E_POINTER;
  742.     }
  743.  
  744.     // Performs the QI for the specified IID and returns it in p.
  745.     // As with all QIs, the interface will be AddRef'd.
  746.     //
  747.     template<typename _InterfaceType> HRESULT QueryInterface(const IID& iid, _InterfaceType** p) throw()
  748.     {
  749.         return QueryInterface(iid, *p);
  750.     }
  751.  
  752. private:
  753.     // The Interface.
  754.     //
  755.     Interface* m_pInterface;
  756.  
  757.     // Releases only if the interface is not null.
  758.     // The interface is not set to NULL.
  759.     //
  760.     void _Release() throw()
  761.     {
  762.         if (m_pInterface != NULL) {
  763.             m_pInterface->Release();
  764.         }
  765.     }
  766.  
  767.     // AddRefs only if the interface is not NULL
  768.     //
  769.     void _AddRef() throw()
  770.     {
  771.         if (m_pInterface != NULL) {
  772.             m_pInterface->AddRef();
  773.         }
  774.     }
  775.  
  776.     // Performs a QI on pUnknown for the interface type returned
  777.     // for this class.  The interface is stored.  If pUnknown is
  778.     // NULL, or the QI fails, E_NOINTERFACE is returned and
  779.     // _pInterface is set to NULL.
  780.     //
  781.     template<typename _InterfacePtr> HRESULT _QueryInterface(const _InterfacePtr& p) throw()
  782.     {
  783.         HRESULT hr;
  784.  
  785.         // Can't QI NULL
  786.         //
  787.         if (p) {
  788.             // Query for this interface
  789.             //
  790.             Interface* pInterface;
  791.             hr = p->QueryInterface(GetIID(), reinterpret_cast<void**>(&pInterface));
  792.  
  793.             if (FAILED(hr)) {
  794.                 // If failed initialize interface to NULL and return HRESULT.
  795.                 //
  796.                 Attach(NULL);
  797.                 return hr;
  798.             }
  799.  
  800.             // Save the interface without AddRef()ing.
  801.             //
  802.             Attach(pInterface);
  803.         }
  804.         else {
  805.             operator=(static_cast<Interface*>(NULL));
  806.             hr = E_NOINTERFACE;
  807.         }
  808.  
  809.         return hr;
  810.     }
  811.  
  812.     // Compares the provided pointer with this by obtaining IUnknown interfaces
  813.     // for each pointer and then returning the difference.
  814.     //
  815.     template<typename _InterfacePtr> int _CompareUnknown(_InterfacePtr p) throw(_com_error)
  816.     {
  817.         IUnknown* pu1, *pu2;
  818.  
  819.         if (m_pInterface != NULL) {
  820.             HRESULT hr = m_pInterface->QueryInterface(__uuidof(IUnknown), reinterpret_cast<void**>(&pu1));
  821.  
  822.             if (FAILED(hr)) {
  823.                 _com_issue_error(hr);
  824.             }
  825.  
  826.             pu1->Release();
  827.         }
  828.         else {
  829.             pu1 = NULL;
  830.         }
  831.  
  832.         if (p) {
  833.             HRESULT hr = p->QueryInterface(__uuidof(IUnknown), reinterpret_cast<void**>(&pu2));
  834.  
  835.             if (FAILED(hr)) {
  836.                 _com_issue_error(hr);
  837.             }
  838.  
  839.             pu2->Release();
  840.         }
  841.         else {
  842.             pu2 = NULL;
  843.         }
  844.  
  845.         return pu1 - pu2;
  846.     }
  847.  
  848.     // Try to extract either IDispatch* or an IUnknown* from
  849.     // the VARIANT
  850.     //
  851.     HRESULT QueryStdInterfaces(const _variant_t& varSrc) throw()
  852.     {
  853.         if (V_VT(&varSrc) == VT_DISPATCH) {
  854.             return _QueryInterface(V_DISPATCH(&varSrc));
  855.         }
  856.  
  857.         if (V_VT(&varSrc) == VT_UNKNOWN) {
  858.             return _QueryInterface(V_UNKNOWN(&varSrc));
  859.         }
  860.  
  861.         // We have something other than an IUnknown or an IDispatch.
  862.         // Can we convert it to either one of these?
  863.         // Try IDispatch first
  864.         //
  865.         VARIANT varDest;
  866.         VariantInit(&varDest);
  867.  
  868.         HRESULT hr = VariantChangeType(&varDest, const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc)), 0, VT_DISPATCH);
  869.         if (SUCCEEDED(hr)) {
  870.             hr = _QueryInterface(V_DISPATCH(&varSrc));
  871.         }
  872.  
  873.         if (FAILED(hr) && (hr == E_NOINTERFACE)) {
  874.             // That failed ... so try IUnknown
  875.             //
  876.             VariantInit(&varDest);
  877.             hr = VariantChangeType(&varDest, const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc)), 0, VT_UNKNOWN);
  878.             if (SUCCEEDED(hr)) {
  879.                 hr = _QueryInterface(V_UNKNOWN(&varSrc));
  880.             }
  881.         }
  882.  
  883.         VariantClear(&varDest);
  884.         return hr;
  885.     }
  886. };
  887.  
  888. // Reverse comparison operators for _com_ptr_t
  889. //
  890. template<typename _InterfaceType> bool operator==(int null, _com_ptr_t<_InterfaceType>& p) throw(_com_error)
  891. {
  892.     if (null != 0) {
  893.         _com_issue_error(E_POINTER);
  894.     }
  895.  
  896.     return p == NULL;
  897. }
  898.  
  899. template<typename _Interface, typename _InterfacePtr> bool operator==(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  900. {
  901.     return p == i;
  902. }
  903.  
  904. template<typename _Interface> bool operator!=(int null, _com_ptr_t<_Interface>& p) throw(_com_error)
  905. {
  906.     if (null != 0) {
  907.         _com_issue_error(E_POINTER);
  908.     }
  909.  
  910.     return p != NULL;
  911. }
  912.  
  913. template<typename _Interface, typename _InterfacePtr> bool operator!=(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  914. {
  915.     return p != i;
  916. }
  917.  
  918. template<typename _Interface> bool operator<(int null, _com_ptr_t<_Interface>& p) throw(_com_error)
  919. {
  920.     if (null != 0) {
  921.         _com_issue_error(E_POINTER);
  922.     }
  923.  
  924.     return p < NULL;
  925. }
  926.  
  927. template<typename _Interface, typename _InterfacePtr> bool operator<(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  928. {
  929.     return p < i;
  930. }
  931.  
  932. template<typename _Interface> bool operator>(int null, _com_ptr_t<_Interface>& p) throw(_com_error)
  933. {
  934.     if (null != 0) {
  935.         _com_issue_error(E_POINTER);
  936.     }
  937.  
  938.     return p > NULL;
  939. }
  940.  
  941. template<typename _Interface, typename _InterfacePtr> bool operator>(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  942. {
  943.     return p > i;
  944. }
  945.  
  946. template<typename _Interface> bool operator<=(int null, _com_ptr_t<_Interface>& p) throw(_com_error)
  947. {
  948.     if (null != 0) {
  949.         _com_issue_error(E_POINTER);
  950.     }
  951.  
  952.     return p <= NULL;
  953. }
  954.  
  955. template<typename _Interface, typename _InterfacePtr> bool operator<=(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  956. {
  957.     return p <= i;
  958. }
  959.  
  960. template<typename _Interface> bool operator>=(int null, _com_ptr_t<_Interface>& p) throw(_com_error)
  961. {
  962.     if (null != 0) {
  963.         _com_issue_error(E_POINTER);
  964.     }
  965.  
  966.     return p >= NULL;
  967. }
  968.  
  969. template<typename _Interface, typename _InterfacePtr> bool operator>=(_Interface* i, _com_ptr_t<_InterfacePtr>& p) throw(_com_error)
  970. {
  971.     return p >= i;
  972. }
  973.  
  974. #endif // _INC_COMIP
  975.