#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_
#define CRYPTO_SCOPED_CAPI_TYPES_H_
#include <windows.h>
#include <wincrypt.h>
#include <algorithm>
#include "base/logging.h"
namespace crypto {
template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)>
struct CAPIDestroyer {
void operator()(CAPIHandle handle) const {
if (handle) {
BOOL ok = Destroyer(handle);
DCHECK(ok);
}
}
};
template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle, DWORD),
DWORD flags>
struct CAPIDestroyerWithFlags {
void operator()(CAPIHandle handle) const {
if (handle) {
BOOL ok = Destroyer(handle, flags);
DCHECK(ok);
}
}
};
template <class CAPIHandle, typename FreeProc>
class ScopedCAPIHandle {
public:
explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {}
~ScopedCAPIHandle() {
reset();
}
void reset(CAPIHandle handle = NULL) {
if (handle_ != handle) {
FreeProc free_proc;
free_proc(handle_);
handle_ = handle;
}
}
operator CAPIHandle() const { return handle_; }
CAPIHandle get() const { return handle_; }
CAPIHandle* receive() {
CHECK(handle_ == NULL);
return &handle_;
}
bool operator==(CAPIHandle handle) const {
return handle_ == handle;
}
bool operator!=(CAPIHandle handle) const {
return handle_ != handle;
}
void swap(ScopedCAPIHandle& b) {
CAPIHandle tmp = b.handle_;
b.handle_ = handle_;
handle_ = tmp;
}
CAPIHandle release() {
CAPIHandle tmp = handle_;
handle_ = NULL;
return tmp;
}
private:
CAPIHandle handle_;
DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle);
};
template<class CH, typename FP> inline
bool operator==(CH h, const ScopedCAPIHandle<CH, FP>& b) {
return h == b.get();
}
template<class CH, typename FP> inline
bool operator!=(CH h, const ScopedCAPIHandle<CH, FP>& b) {
return h != b.get();
}
typedef ScopedCAPIHandle<
HCRYPTPROV,
CAPIDestroyerWithFlags<HCRYPTPROV,
CryptReleaseContext, 0> > ScopedHCRYPTPROV;
typedef ScopedCAPIHandle<
HCRYPTKEY, CAPIDestroyer<HCRYPTKEY, CryptDestroyKey> > ScopedHCRYPTKEY;
typedef ScopedCAPIHandle<
HCRYPTHASH, CAPIDestroyer<HCRYPTHASH, CryptDestroyHash> > ScopedHCRYPTHASH;
}
#endif