00001 /* 00002 * wave-windows.h 00003 * 00004 * Copyright (C) 2010 Thomas A. Vaughan 00005 * All rights reserved. 00006 * 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * * Neither the name of the <organization> nor the 00016 * names of its contributors may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY 00020 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY 00023 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00026 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 * 00031 * Very basic helper routines and classes for working with Windows APIs. 00032 */ 00033 00034 #ifndef WAVEPACKET_WINDOWS_H__ 00035 #define WAVEPACKET_WINDOWS_H__ 00036 00037 // includes -------------------------------------------------------------------- 00038 #include "common/common.h" 00039 00040 #ifndef WIN32_LEAN_AND_MEAN 00041 #define WIN32_LEAN_AND_MEAN 1 00042 #endif // WIN32_LEAN_AND_MEAN 00043 00044 #include <rpc.h> // windows remote procedure calls 00045 00046 00047 /// \ingroup wavepacket_lib 00048 /*@{*/ 00049 00050 //////////////////////////////////////////////////////////////////////////////// 00051 /// 00052 /// \defgroup wave_windows Microsoft Windows Helper Library 00053 /// 00054 /// Very basic routines and classes for working with Windows APIs. 00055 /// 00056 //////////////////////////////////////////////////////////////////////////////// 00057 /*@{*/ 00058 00059 /// helper method to print out information about a particular RPC_STATUS code. 00060 void checkRpcStatus(IN RPC_STATUS rpc_status) throw(); 00061 00062 #define RPC_VERIFY(exp, rpc_status, msg) \ 00063 if (!(exp)) { \ 00064 DPRINTF("Windows RPC call failed!"); \ 00065 checkRpcStatus(rpc_status); \ 00066 ASSERT_THROW(false && (exp), msg); \ 00067 } 00068 00069 00070 /// helper method to print out information about a particular HRESULT code. 00071 /// Note that this method is often useless since most Windows APIs also 00072 /// define their own (usually redundant) error codes. So you will have 00073 /// to build your own API-specific error code inspection routine, on top of 00074 /// this generic one. 00075 void checkHresult(IN HRESULT hr) throw(); 00076 00077 #define HRESULT_VERIFY(exp, hr, msg) \ 00078 if (!(exp)) { \ 00079 DPRINTF("Failed windows hresult check!"); \ 00080 checkHresult(hr); \ 00081 ASSERT_THROW(false && (exp), msg); \ 00082 } 00083 00084 00085 00086 /// writes an ANSI version of the GUID to the given stream 00087 void writeGuid(IO std::ostream& stream, 00088 IN const GUID& guid); 00089 00090 inline std::ostream& operator << (IO std::ostream& stream, 00091 IN const GUID& guid) { 00092 writeGuid(stream, guid); 00093 return stream; 00094 } 00095 00096 00097 00098 /// gets GUID as a string and copies as much of it as will fit into the 00099 /// specified buffer. Use 32+ chars to be safe. Returns a pointer to 00100 /// the buffer as a convenience. 00101 const char * getGuidString(IN const GUID& guid, 00102 IO char * buffer, 00103 IN int bufsize); 00104 00105 00106 /// COM_ptr<T>: smart pointer to automatically de-reference COM objects. 00107 /// This object is NOT (automatically) threadsafe. We are calling 00108 /// IUnknown::AddRef()/Release() on an 00109 /// object, so this pointer is only as threadsafe as the underlying COM object. 00110 /// However, because the object maintains its own count, this pointer is safe 00111 /// to use in collections. 00112 /// \n 00113 /// <b>Semantics of this pointer:</b> 00114 /// - Any raw interface pointer passed will be assumed to already have a 00115 /// reference taken, so AddRef() will not be called again. 00116 /// - Assigning from another COM_ptr<T> will take another AddRef() 00117 /// 00118 template <class T> 00119 class COM_ptr { 00120 public: 00121 // constructor, destructor --------------------------------------------- 00122 COM_ptr(IN T * pT = NULL) throw() : m_pT(NULL) { this->assign(pT); } 00123 00124 template <class X> 00125 COM_ptr(IN const COM_ptr<X>& from) throw() : m_pT(NULL) 00126 { this->assign(from); } 00127 00128 ~COM_ptr(void) throw() { this->release(); } 00129 00130 // public class methods ------------------------------------------------ 00131 T* operator -> (void) throw() { 00132 ASSERT(m_pT, "null COM object"); 00133 return m_pT; 00134 } 00135 00136 const T * operator -> (void) const throw() { 00137 ASSERT(m_pT, "null COM object"); 00138 return m_pT; 00139 } 00140 00141 operator T* (void) throw() { 00142 return m_pT; 00143 } 00144 00145 operator const T* (void) const throw() { 00146 return m_pT; 00147 } 00148 00149 // VisualStudio barfs without a non-const bool() operator (!?) 00150 operator bool (void) throw() { 00151 return !!m_pT; 00152 } 00153 00154 operator bool (void) const throw() { 00155 return !!m_pT; 00156 } 00157 00158 bool operator ! (void) const throw() { 00159 return !m_pT; 00160 } 00161 00162 operator LPVOID * (void) throw() { 00163 ASSERT(!m_pT, "assigning to non-NULL COM ptr"); 00164 return (LPVOID *) &m_pT; 00165 } 00166 00167 const COM_ptr<T>& operator = (IN T * pT) throw() { 00168 this->assign(pT); 00169 return *this; 00170 } 00171 00172 template <class X> 00173 const COM_ptr<T>& operator = (IN COM_ptr<X>& from) throw() { 00174 this->assign(from); 00175 return *this; 00176 } 00177 00178 private: 00179 // hidden methods ------------------------------------------------------ 00180 // private helper methods ---------------------------------------------- 00181 void assign(IN T * pT) throw() { 00182 // NOTE: assumes that a non-null pointer has already had 00183 // a reference taken! 00184 // ASSERT(pT) -- can be null! 00185 this->release(); 00186 m_pT = pT; 00187 } 00188 00189 template <class X> 00190 void assign(IN const COM_ptr<X>& from) throw() { 00191 // when copying from another COM ptr, we call AddRef 00192 this->release(); 00193 if (from) { 00194 // hack cast to avoid constness problems 00195 COM_ptr<X> * px = (COM_ptr<X> *) &from; 00196 T * pT = dynamic_cast<T *>(px->m_pT); 00197 ASSERT(pT, "failed to cast COM object"); 00198 pT->AddRef(); // take an additional reference 00199 this->assign(pT); 00200 } 00201 } 00202 00203 void release(void) throw() { 00204 if (m_pT) { 00205 T * pT = m_pT; 00206 m_pT = NULL; 00207 pT->Release(); 00208 } 00209 } 00210 00211 // private data members ------------------------------------------------ 00212 T * m_pT; // actual pointer to COM object 00213 }; 00214 00215 00216 #endif // WAVEPACKET_WINDOWS_H__ 00217