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