OLD | NEW |
(Empty) | |
| 1 /** |
| 2 * \file handle.h The "install session" is the context for all custom installatio
n behavior. |
| 3 */ |
| 4 |
| 5 #ifndef HANDLE_H |
| 6 #define HANDLE_H |
| 7 |
| 8 #include "windows.h" |
| 9 #include "msi.h" |
| 10 |
| 11 //------------------------------------------------------- |
| 12 // msi_handle |
| 13 //------------------------------------------------------- |
| 14 /** |
| 15 * Disambiguation class holding an MSIHANDLE. |
| 16 * |
| 17 * We need constructors for Record that accept both handles and record counts. |
| 18 * Since the underlying type of a handle is integral, without its own type these
constructors are ambiguous. |
| 19 */ |
| 20 class msi_handle |
| 21 { |
| 22 MSIHANDLE _handle ; |
| 23 |
| 24 public: |
| 25 /** |
| 26 * Ordinary constructor is explicit to avoid inadvertent conversions. |
| 27 */ |
| 28 explicit msi_handle( MSIHANDLE handle ) |
| 29 : _handle( handle ) |
| 30 {} |
| 31 |
| 32 operator MSIHANDLE() |
| 33 { |
| 34 return _handle ; |
| 35 } |
| 36 } ; |
| 37 |
| 38 //------------------------------------------------------- |
| 39 // Handle Policies |
| 40 //------------------------------------------------------- |
| 41 /** |
| 42 * Policy class that indicates that a raw handle may not be zero. |
| 43 */ |
| 44 template< class T > |
| 45 struct Disallow_Null |
| 46 { |
| 47 inline static bool prohibited_always() { return true ; } |
| 48 inline static bool prohibited_from_outside() { return true ; } |
| 49 } ; |
| 50 |
| 51 /** |
| 52 * Policy class that indicates that a raw handle may be zero only when constructe
d internally. |
| 53 */ |
| 54 template< class T > |
| 55 struct Special_Null |
| 56 { |
| 57 inline static bool prohibited_always() { return false ; } |
| 58 inline static bool prohibited_from_outside() { return true ; } |
| 59 } ; |
| 60 |
| 61 /** |
| 62 * Policy class that indicates that a raw handle is permitted to be zero. |
| 63 */ |
| 64 template< class T > |
| 65 struct Allow_Null |
| 66 { |
| 67 inline static bool prohibited_always() { return false ; } |
| 68 inline static bool prohibited_from_outside() { return false ; } |
| 69 } ; |
| 70 |
| 71 /** |
| 72 * Policy class that does not close a handle at all. |
| 73 */ |
| 74 template< class T > |
| 75 class No_Destruction |
| 76 { |
| 77 public: |
| 78 inline static void close( T handle ) {} ; |
| 79 } ; |
| 80 |
| 81 /** |
| 82 * Policy class that closes an MSI handle when it goes out of scope. |
| 83 */ |
| 84 template< class T > |
| 85 class MSI_Generic_Destruction |
| 86 { |
| 87 public: |
| 88 inline static void close( T handle ) |
| 89 { |
| 90 MsiCloseHandle( handle ) ; |
| 91 } ; |
| 92 } ; |
| 93 |
| 94 /** |
| 95 * Policy class that closes a Windows handle when it goes out of scope. |
| 96 */ |
| 97 template< class T > |
| 98 class Windows_Generic_Destruction |
| 99 { |
| 100 public: |
| 101 inline static void close( T handle ) |
| 102 { |
| 103 CloseHandle( handle ) ; |
| 104 } ; |
| 105 } ; |
| 106 |
| 107 |
| 108 //------------------------------------------------------- |
| 109 // Handle |
| 110 //------------------------------------------------------- |
| 111 /** |
| 112 * Raw handle is the base class for the generic handle. |
| 113 * |
| 114 * Raw handles always allow null, so that generic handles may allow or disallow t
hem as they please. |
| 115 */ |
| 116 template< class T > |
| 117 class handle_raw |
| 118 { |
| 119 protected: |
| 120 /** |
| 121 * The underlying handle. |
| 122 * |
| 123 * This is the only data member of the class. |
| 124 * Everything else is for life cycle and type conversion. |
| 125 */ |
| 126 T _handle ; |
| 127 |
| 128 /** |
| 129 * Basic constructor is protected to cede creation policy entirely to subclasse
s. |
| 130 */ |
| 131 handle_raw( T _handle ) |
| 132 : _handle( _handle ) |
| 133 {} |
| 134 |
| 135 public: |
| 136 /** |
| 137 * Conversion operator to underlying handle type. |
| 138 */ |
| 139 operator T() |
| 140 { |
| 141 return _handle ; |
| 142 } |
| 143 |
| 144 /** |
| 145 * Error thrown when initialize or assigning a null handle against policy. |
| 146 * |
| 147 * Note that this error is a logic_error, not a runtime error. |
| 148 * If it's against policy for a handle to be null, it's an error for the caller
to try to make it null. |
| 149 * Policy enforcment here is not a substitute for good error handling by the ca
ller. |
| 150 * In many cases, the caller ought to be throwing windows_api_error. |
| 151 */ |
| 152 struct null_handle_error |
| 153 : public std::logic_error |
| 154 { |
| 155 null_handle_error() |
| 156 : std::logic_error( "May not initialize with null handle" ) |
| 157 {} |
| 158 } ; |
| 159 } ; |
| 160 |
| 161 /* |
| 162 * Handle class |
| 163 */ |
| 164 template< |
| 165 class T, |
| 166 template <class> class Null_Policy, |
| 167 template <class> class Destruction_Policy = No_Destruction |
| 168 > |
| 169 class handle |
| 170 : public handle_raw< T > |
| 171 { |
| 172 /** |
| 173 * Copy constructor prohibited. |
| 174 * |
| 175 * This class represents an external resource and is responsible for its lifecy
cle. |
| 176 * As such, the semantics here require a one-to-one match between instances and
resource. |
| 177 * Copy construction violates these semantics. |
| 178 * |
| 179 * \par Implementation |
| 180 * Currently, declared private and not defined. |
| 181 * Add "= delete" for C++11. |
| 182 */ |
| 183 handle( handle & ) ; |
| 184 |
| 185 /** |
| 186 * Copy assignment not implemented. |
| 187 * |
| 188 * It's not used anywhere yet. |
| 189 * |
| 190 * \par Implementation |
| 191 * Currently, declared private and not defined. |
| 192 */ |
| 193 handle operator=( const handle & ) ; |
| 194 |
| 195 /** |
| 196 * Validate initial handle values, both for construction and reinitialization a
ssignment. |
| 197 */ |
| 198 T validate_handle( T handle ) |
| 199 { |
| 200 if ( Null_Policy< T >::prohibited_from_outside() && handle == 0 ) |
| 201 { |
| 202 throw null_handle_error() ; |
| 203 } |
| 204 return handle ; |
| 205 } |
| 206 |
| 207 protected: |
| 208 /** |
| 209 * Tag class for null record constructor |
| 210 */ |
| 211 class null_t {} ; |
| 212 |
| 213 /** |
| 214 * Null handle constructor initializes its handle to zero. |
| 215 * |
| 216 * The null record constructor avoids the ordinary check that an external handl
e not be zero. |
| 217 * It's declared protected so that it's not ordinarily visible. |
| 218 * To use this constructor, derive from it and add a friend declaration. |
| 219 */ |
| 220 handle( null_t ) |
| 221 : handle_raw( 0 ) |
| 222 { |
| 223 if ( Null_Policy< T >::prohibited_always() ) |
| 224 { |
| 225 throw null_handle_error() ; |
| 226 } |
| 227 } |
| 228 |
| 229 public: |
| 230 /** |
| 231 * Ordinary constructor. |
| 232 * |
| 233 * A check for a non-zero handle compiles in conditionally based on the Null_Po
licy. |
| 234 */ |
| 235 handle( T handle ) |
| 236 : handle_raw( validate_handle( handle ) ) |
| 237 {} |
| 238 |
| 239 /** |
| 240 * Reinitialization Assignment. |
| 241 * |
| 242 * If we had C++11 move constructors, we wouldn't need this, since this acts ex
actly as construct-plus-move would. |
| 243 */ |
| 244 handle & operator=( T handle ) |
| 245 { |
| 246 validate_handle( handle ) ; |
| 247 this -> ~handle() ; |
| 248 _handle = handle ; |
| 249 return * this ; |
| 250 } |
| 251 |
| 252 /** |
| 253 * Destructor |
| 254 * |
| 255 * The check for a non-zero handle compiles out conditionally based on Null_Pol
icy. |
| 256 * The specific function used to close the handle is given by the Destruction_P
olicy. |
| 257 */ |
| 258 ~handle() |
| 259 { |
| 260 if ( Null_Policy< T >::prohibited_always() || ( _handle != 0 ) ) { |
| 261 Destruction_Policy< T >::close( _handle ) ; |
| 262 } |
| 263 } |
| 264 |
| 265 /** |
| 266 * Expose the underlying handle type. |
| 267 */ |
| 268 typedef T handle_type ; |
| 269 } ; |
| 270 |
| 271 //------------------------------------------------------- |
| 272 // Common instantiations of handle |
| 273 //------------------------------------------------------- |
| 274 typedef handle< HANDLE, Disallow_Null, Windows_Generic_Destruction > Windows_Han
dle ; |
| 275 |
| 276 #endif |
OLD | NEW |