197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project
297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner//
397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public
497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and
597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// may be copied, distributed, and modified under those terms.
697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner//
797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// This program is distributed in the hope that it will be useful,
897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of
997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// GNU General Public License for more details.
1197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#ifndef ANDROID_BASE_FILES_SCOPED_HANDLE_H
1397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#define ANDROID_BASE_FILES_SCOPED_HANDLE_H
1497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#if !defined(_WIN32) && !defined(_WIN64)
1697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#error "Only compile this file when targetting Windows!"
1797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#endif
1897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#include "android/base/Compiler.h"
2097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
2197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#define WIN32_LEAN_AND_MEAN 1
2297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#include <windows.h>
2397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
2497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnernamespace android {
2597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnernamespace base {
2697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
2797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// Helper class used to wrap a Win32 HANDLE that will be closed when
2897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// the instance is destroyed, unless the release() method was called
2997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// before that.
3097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerclass ScopedHandle {
3197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerpublic:
3297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Default destructor is used to wrap an invalid handle value.
3397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    ScopedHandle() : handle_(INVALID_HANDLE_VALUE) {}
3497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
3597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Constructor takes ownership of |handle|.
3697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    explicit ScopedHandle(HANDLE handle) : handle_(handle) {}
3797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
3897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Destructor calls close() method.
3997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    ~ScopedHandle() { close(); }
4097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
4197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Returns true iff the wrapped HANDLE value is valid.
4297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    bool valid() const { return handle_ != INVALID_HANDLE_VALUE; }
4397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
4497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Return current HANDLE value. Does _not_ transfer ownership.
4597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    HANDLE get() const { return handle_; }
4697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
4797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Return current HANDLE value, transferring ownership to the caller.
4897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    HANDLE release() {
4997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        HANDLE h = handle_;
5097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        handle_ = INVALID_HANDLE_VALUE;
5197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        return h;
5297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
5397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
5497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Close handle if it is not invalid.
5597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    void close() {
5697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        if (handle_ != INVALID_HANDLE_VALUE) {
5797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            ::CloseHandle(handle_);
5897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            handle_ = INVALID_HANDLE_VALUE;
5997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        }
6097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
6197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
6297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Swap the content of two ScopedHandle instances.
6397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    void swap(ScopedHandle* other) {
6497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        HANDLE handle = handle_;
6597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        handle_ = other->handle_;
6697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        other->handle_ = handle;
6797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
6897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
6997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerprivate:
7097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    DISALLOW_COPY_AND_ASSIGN(ScopedHandle);
7197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    HANDLE handle_;
7397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner};
7497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner}  // namespace base
7697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner}  // namespace android
7797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#endif  // ANDROID_BASE_FILES_SCOPED_HANDLE_H
79