blob: 154fe046ef9f0d13e819f88def21f28848f4913d [file] [log] [blame]
// Copyright 2004-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
//
// Classes for automatically closing handles.
#ifndef OMAHA_COMMON_SMART_HANDLE_H_
#define OMAHA_COMMON_SMART_HANDLE_H_
#include <wincrypt.h>
namespace omaha {
/**
* Base traits class for handles.
* This base class provides default implementation for InvalidValue and IsValid
* @param T The handle type to be wrapped.
*/
template<class T>
class BaseHandleTraitsT {
public:
// Typedef that is used by this class and derived classes
typedef T HandleType;
// Returns the invalid handle value
static HandleType InvalidValue() {
return NULL;
}
// Returns true only if the given handle h is invalid
static bool IsValid(const HandleType& h) {
return h != InvalidValue();
}
private:
DISALLOW_EVIL_CONSTRUCTORS(BaseHandleTraitsT);
};
/**
* Smart handle class.
* Offers basic HANDLE functionality such as cast, attach/detach and automatic Close().
*/
template<class T, class Traits, class AlternateType = T>
class HandleT {
public:
// Default constructor.
HandleT() : h_(Traits::InvalidValue()) {
}
// Constructor that assumes ownership of the supplied handle
explicit HandleT(T h) : h_(h) {
}
// Destructor calls @ref Close()
~HandleT() {
Close();
}
// Assumes ownership of the supplied handle,
// potentially closing an already held handle.
void Attach(T h) {
Close();
h_ = h;
}
// Transfers ownership to the caller and sets the internal
// state to InvalidValue().
T Detach() {
T h = h_;
h_ = Traits::InvalidValue();
return h;
}
// Handle accessor
T handle() {
return h_;
}
// An alternate cast for the handle.
// This can be useful for GDI objects that are used
// in functions that e.g. accept both HGDIOBJ and HBITMAP.
AlternateType alt_type() {
return reinterpret_cast<AlternateType>(h_);
}
// Accesses the contained handle
operator T() {
return h_;
}
T& receive() {
ASSERT(!IsValid(), (L"Should only be used for out arguments"));
return h_;
}
// @returns true only if the handle is valid as depicted
// by the traits class.
bool IsValid() {
return Traits::IsValid(h_);
}
// Closes the handle
void Close() {
if (Traits::IsValid(h_)) {
Traits::Close(h_);
h_ = Traits::InvalidValue();
}
}
protected:
T h_;
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleT);
};
/*
* Traits class for a regular Win32 HANDLE.
*/
class HandleTraitsWin32Handle : public BaseHandleTraitsT<HANDLE> {
public:
// Calls FindClose to close the handle.
static bool Close(HandleType h) {
return (::CloseHandle(h) != false);
}
// Returns the invalid handle value
static HandleType InvalidValue() {
return NULL; // note that INVALID_HANDLE_VALUE is also an invalid handle
}
// Returns true only if the given handle h is invalid
static bool IsValid(const HandleType& h) {
return h != InvalidValue() && h != INVALID_HANDLE_VALUE;
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsWin32Handle);
};
/*
* Traits class for FindXXXFile handles.
*/
class HandleTraitsFindHandle : public BaseHandleTraitsT<HANDLE> {
public:
// Calls FindClose to close the handle.
static bool Close(HandleType h) {
return (::FindClose(h) != false);
}
// Returns the invalid handle value
static HandleType InvalidValue() {
return INVALID_HANDLE_VALUE;
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsFindHandle);
};
/*
* Traits for an HMENU.
*/
class HandleTraitsHMenu : public BaseHandleTraitsT<HMENU> {
public:
// Calls DestroyMenu to destroy the menu.
static bool Close(HandleType h) {
return (::DestroyMenu(h) != FALSE);
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsHMenu);
};
/*
* Traits for an HCRYPTKEY.
*/
class HandleTraitsHCryptKey : public BaseHandleTraitsT<HCRYPTKEY> {
public:
static bool Close(HandleType h) {
return (::CryptDestroyKey(h) != FALSE);
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsHCryptKey);
};
/*
* Traits for an HCRYPTHASH.
*/
class HandleTraitsHCryptHash : public BaseHandleTraitsT<HCRYPTHASH> {
public:
static bool Close(HandleType h) {
return (::CryptDestroyHash(h) != FALSE);
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsHCryptHash);
};
/*
* Traits for LoadLibrary/FreeLibrary.
*/
class HandleTraitsLibrary : public BaseHandleTraitsT<HMODULE> {
public:
static bool Close(HandleType h) {
return (::FreeLibrary(h) != FALSE);
}
private:
DISALLOW_EVIL_CONSTRUCTORS(HandleTraitsLibrary);
};
/*
* Win32 handle types. Add new ones here as you need them.
* Note that GDI handle types should be kept in common/gdi_smart_ptr.h
* rather than here.
*/
typedef HandleT<HANDLE, HandleTraitsWin32Handle> AutoHandle;
typedef HandleT<HANDLE, HandleTraitsFindHandle> AutoFindHandle;
typedef HandleT<HMENU, HandleTraitsHMenu> AutoHMenu;
typedef HandleT<HCRYPTHASH, HandleTraitsHCryptHash> AutoHCryptHash;
typedef HandleT<HCRYPTKEY, HandleTraitsHCryptKey> AutoHCryptKey;
typedef HandleT<HINSTANCE, HandleTraitsLibrary> AutoLibrary;
} // namespace omaha
#endif // OMAHA_COMMON_SMART_HANDLE_H_