| Index: installer/src/installer-lib/handle.h |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/installer/src/installer-lib/handle.h |
| @@ -0,0 +1,203 @@ |
| +/** |
| + * \file handle.h The "install session" is the context for all custom installation behavior. |
| + */ |
| + |
| +#ifndef HANDLE_H |
| +#define HANDLE_H |
| + |
| +#include "windows.h" |
| +#include "msi.h" |
| + |
| +//------------------------------------------------------- |
| +// msi_handle |
| +//------------------------------------------------------- |
| +/** |
| + * Disambiguation class holding an MSIHANDLE. |
| + * |
| + * We need constructors for Record that accept both handles and record counts. |
| + * Since the underlying type of a handle is integral, without its own type these constructors are ambiguous. |
| + */ |
| +class msi_handle |
| +{ |
| + MSIHANDLE _handle ; |
| + |
| +public: |
| + /** |
| + * Ordinary constructor is explicit to avoid inadvertent conversions. |
| + */ |
| + explicit msi_handle( MSIHANDLE handle ) |
| + : _handle( handle ) |
| + {} |
| + |
| + operator MSIHANDLE() |
| + { |
| + return _handle ; |
| + } |
| +} ; |
| + |
| +//------------------------------------------------------- |
| +// Handle Policies |
| +//------------------------------------------------------- |
| +/** |
| + * Policy class that indicates that a raw handle may not be zero. |
| + */ |
| +template< class T > |
| +struct Disallow_Null |
| +{ |
| + inline static bool prohibited_always() { return true ; } |
| + inline static bool prohibited_from_outside() { return true ; } |
| +} ; |
| + |
| +/** |
| + * Policy class that indicates that a raw handle may be zero only when constructed internally. |
| + */ |
| +template< class T > |
| +struct Special_Null |
| +{ |
| + inline static bool prohibited_always() { return false ; } |
| + inline static bool prohibited_from_outside() { return true ; } |
| +} ; |
| + |
| +/** |
| + * Policy class that indicates that a raw handle is permitted to be zero. |
| + */ |
| +template< class T > |
| +struct Allow_Null |
| +{ |
| + inline static bool prohibited_always() { return false ; } |
| + inline static bool prohibited_from_outside() { return false ; } |
| +} ; |
| + |
| +/** |
| + * Policy class that does not close a file handle when it goes out of scope |
| + */ |
| +template< class T > |
| +class No_Destruction |
| +{ |
| +public: |
| + inline static void close( T handle ) {} ; |
| +} ; |
| + |
| +/** |
| + * Policy class that does not close a file handle when it goes out of scope |
| + */ |
| +template< class T > |
| +class MSI_Generic_Destruction |
| +{ |
| +public: |
| + inline static void close( T handle ) |
| + { |
| + MsiCloseHandle( handle ) ; |
| + } ; |
| +} ; |
| + |
| + |
| +//------------------------------------------------------- |
| +// Handle |
| +//------------------------------------------------------- |
| +/** |
| + * Raw handle is the base class for the generic handle. |
| + * |
| + * Raw handles always allow null, so that generic handles may allow or disallow them as they please. |
| + */ |
| +template< class T > |
| +class handle_raw |
| +{ |
| +protected: |
| + /** |
| + * The underlying handle. |
| + * |
| + * This is the only data member of the class. |
| + * Everything else is for life cycle and type conversion. |
| + */ |
| + T _handle ; |
| + |
| + /** |
| + * Basic constructor is protected to cede creation policy entirely to subclasses. |
| + */ |
| + handle_raw( T _handle ) |
| + : _handle( _handle ) |
| + {} |
| + |
| +public: |
| + /** |
| + * Conversion operator to underlying handle type. |
| + */ |
| + operator T() |
| + { |
| + return _handle ; |
| + } |
| + |
| + struct null_handle_error |
| + : public std::runtime_error |
| + { |
| + null_handle_error() |
| + : std::runtime_error( "May not initialize with null handle" ) |
| + {} |
| + } ; |
| +} ; |
| + |
| +/* |
| + * Handle class |
| + */ |
| +template< |
| + class T, |
| + template <class> class Null_Policy, |
| + template <class> class Destruction_Policy = No_Destruction |
| +> |
| +class handle |
| + : public handle_raw< T > |
| +{ |
| +protected: |
| + /** |
| + * Tag class for null record constructor |
| + */ |
| + class null_t {} ; |
| + |
| + /** |
| + * Null handle constructor initializes its handle to zero. |
| + * |
| + * The null record constructor avoids the ordinary check that an external handle not be zero. |
| + * It's declared protected so that it's not ordinarily visible. |
| + * To use this constructor, derive from it and add a friend declaration. |
| + */ |
| + handle( null_t ) |
| + : handle_raw( 0 ) |
| + { |
| + if ( Null_Policy< T >::prohibited_always() ) |
| + { |
| + throw null_handle_error() ; |
| + } |
| + } |
| + |
| +public: |
| + /** |
| + * Ordinary constructor. |
| + * |
| + * A check for a non-zero handle compiles in conditionally based on the Null_Policy. |
| + */ |
| + handle( T _handle ) |
| + : handle_raw( _handle ) |
| + { |
| + if ( Null_Policy< T >::prohibited_from_outside() && _handle == 0 ) |
| + { |
| + throw null_handle_error() ; |
| + } |
| + } |
| + |
| + /** |
| + * Destructor |
| + * |
| + * The check for a non-zero handle compiles out conditionally based on Null_Policy. |
| + * The specific function used to close the handle is given by the Destruction_Policy. |
| + */ |
| + ~handle() |
| + { |
| + if ( Null_Policy< T >::prohibited_always() || ( _handle != 0 ) ) { |
| + Destruction_Policy< T >::close( _handle ) ; |
| + } |
| + } |
| + |
| +} ; |
| + |
| +#endif |