scoped_capi_types.h revision cce46a0c214b37e8da48c522c83037e8ffa4f9fd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_
6#define CRYPTO_SCOPED_CAPI_TYPES_H_
7
8#include <windows.h>
9
10#include <algorithm>
11
12#include "base/logging.h"
13#include "base/macros.h"
14#include "crypto/wincrypt_shim.h"
15
16namespace crypto {
17
18// Simple destructor for the Free family of CryptoAPI functions, such as
19// CryptDestroyHash, which take only a single argument to release.
20template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)>
21struct CAPIDestroyer {
22  void operator()(CAPIHandle handle) const {
23    if (handle) {
24      BOOL ok = Destroyer(handle);
25      DCHECK(ok);
26    }
27  }
28};
29
30// Destructor for the Close/Release family of CryptoAPI functions, which take
31// a second DWORD parameter indicating flags to use when closing or releasing.
32// This includes functions like CertCloseStore or CryptReleaseContext.
33template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle, DWORD),
34          DWORD flags>
35struct CAPIDestroyerWithFlags {
36  void operator()(CAPIHandle handle) const {
37    if (handle) {
38      BOOL ok = Destroyer(handle, flags);
39      DCHECK(ok);
40    }
41  }
42};
43
44// scoped_ptr-like class for the CryptoAPI cryptography and certificate
45// handles. Because these handles are defined as integer types, and not
46// pointers, the existing scoped classes, such as scoped_ptr, are insufficient.
47// The semantics are the same as scoped_ptr.
48template <class CAPIHandle, typename FreeProc>
49class ScopedCAPIHandle {
50 public:
51  explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {}
52
53  ~ScopedCAPIHandle() {
54    reset();
55  }
56
57  void reset(CAPIHandle handle = NULL) {
58    if (handle_ != handle) {
59      FreeProc free_proc;
60      free_proc(handle_);
61      handle_ = handle;
62    }
63  }
64
65  operator CAPIHandle() const { return handle_; }
66  CAPIHandle get() const { return handle_; }
67
68  CAPIHandle* receive() {
69    CHECK(handle_ == NULL);
70    return &handle_;
71  }
72
73  bool operator==(CAPIHandle handle) const {
74    return handle_ == handle;
75  }
76
77  bool operator!=(CAPIHandle handle) const {
78    return handle_ != handle;
79  }
80
81  void swap(ScopedCAPIHandle& b) {
82    CAPIHandle tmp = b.handle_;
83    b.handle_ = handle_;
84    handle_ = tmp;
85  }
86
87  CAPIHandle release() {
88    CAPIHandle tmp = handle_;
89    handle_ = NULL;
90    return tmp;
91  }
92
93 private:
94  CAPIHandle handle_;
95
96  DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle);
97};
98
99template<class CH, typename FP> inline
100bool operator==(CH h, const ScopedCAPIHandle<CH, FP>& b) {
101  return h == b.get();
102}
103
104template<class CH, typename FP> inline
105bool operator!=(CH h, const ScopedCAPIHandle<CH, FP>& b) {
106  return h != b.get();
107}
108
109typedef ScopedCAPIHandle<
110    HCRYPTPROV,
111    CAPIDestroyerWithFlags<HCRYPTPROV,
112                           CryptReleaseContext, 0> > ScopedHCRYPTPROV;
113
114typedef ScopedCAPIHandle<
115    HCRYPTKEY, CAPIDestroyer<HCRYPTKEY, CryptDestroyKey> > ScopedHCRYPTKEY;
116
117typedef ScopedCAPIHandle<
118    HCRYPTHASH, CAPIDestroyer<HCRYPTHASH, CryptDestroyHash> > ScopedHCRYPTHASH;
119
120}  // namespace crypto
121
122#endif  // CRYPTO_SCOPED_CAPI_TYPES_H_
123