// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_
#define CRYPTO_SCOPED_CAPI_TYPES_H_

#include <windows.h>

#include <algorithm>

#include "base/logging.h"
#include "base/macros.h"
#include "crypto/wincrypt_shim.h"
#include "starboard/types.h"

namespace crypto {

// Simple destructor for the Free family of CryptoAPI functions, such as
// CryptDestroyHash, which take only a single argument to release.
template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)>
struct CAPIDestroyer {
  void operator()(CAPIHandle handle) const {
    if (handle) {
      BOOL ok = Destroyer(handle);
      DCHECK(ok);
    }
  }
};

// Destructor for the Close/Release family of CryptoAPI functions, which take
// a second DWORD parameter indicating flags to use when closing or releasing.
// This includes functions like CertCloseStore or CryptReleaseContext.
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);
    }
  }
};

// scoped_ptr-like class for the CryptoAPI cryptography and certificate
// handles. Because these handles are defined as integer types, and not
// pointers, the existing scoped classes, such as scoped_ptr, are insufficient.
// The semantics are the same as scoped_ptr.
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;

}  // namespace crypto

#endif  // CRYPTO_SCOPED_CAPI_TYPES_H_
