wave-windows.h

Go to the documentation of this file.
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