michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_SCOPED_HANDLE_WIN_H_ michael@0: #define BASE_SCOPED_HANDLE_WIN_H_ michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "base/logging.h" michael@0: michael@0: // Used so we always remember to close the handle. michael@0: // The class interface matches that of ScopedStdioHandle in addition to an michael@0: // IsValid() method since invalid handles on windows can be either NULL or michael@0: // INVALID_HANDLE_VALUE (-1). michael@0: // michael@0: // Example: michael@0: // ScopedHandle hfile(CreateFile(...)); michael@0: // if (!hfile.Get()) michael@0: // ...process error michael@0: // ReadFile(hfile.Get(), ...); michael@0: // michael@0: // To sqirrel the handle away somewhere else: michael@0: // secret_handle_ = hfile.Take(); michael@0: // michael@0: // To explicitly close the handle: michael@0: // hfile.Close(); michael@0: class ScopedHandle { michael@0: public: michael@0: ScopedHandle() : handle_(NULL) { michael@0: } michael@0: michael@0: explicit ScopedHandle(HANDLE h) : handle_(NULL) { michael@0: Set(h); michael@0: } michael@0: michael@0: ~ScopedHandle() { michael@0: Close(); michael@0: } michael@0: michael@0: // Use this instead of comparing to INVALID_HANDLE_VALUE to pick up our NULL michael@0: // usage for errors. michael@0: bool IsValid() const { michael@0: return handle_ != NULL; michael@0: } michael@0: michael@0: void Set(HANDLE new_handle) { michael@0: Close(); michael@0: michael@0: // Windows is inconsistent about invalid handles, so we always use NULL michael@0: if (new_handle != INVALID_HANDLE_VALUE) michael@0: handle_ = new_handle; michael@0: } michael@0: michael@0: HANDLE Get() { michael@0: return handle_; michael@0: } michael@0: michael@0: operator HANDLE() { return handle_; } michael@0: michael@0: HANDLE Take() { michael@0: // transfers ownership away from this object michael@0: HANDLE h = handle_; michael@0: handle_ = NULL; michael@0: return h; michael@0: } michael@0: michael@0: void Close() { michael@0: if (handle_) { michael@0: if (!::CloseHandle(handle_)) { michael@0: NOTREACHED(); michael@0: } michael@0: handle_ = NULL; michael@0: } michael@0: } michael@0: michael@0: private: michael@0: HANDLE handle_; michael@0: DISALLOW_EVIL_CONSTRUCTORS(ScopedHandle); michael@0: }; michael@0: michael@0: // Like ScopedHandle, but for HANDLEs returned from FindFile(). michael@0: class ScopedFindFileHandle { michael@0: public: michael@0: explicit ScopedFindFileHandle(HANDLE handle) : handle_(handle) { michael@0: // Windows is inconsistent about invalid handles, so we always use NULL michael@0: if (handle_ == INVALID_HANDLE_VALUE) michael@0: handle_ = NULL; michael@0: } michael@0: michael@0: ~ScopedFindFileHandle() { michael@0: if (handle_) michael@0: FindClose(handle_); michael@0: } michael@0: michael@0: // Use this instead of comparing to INVALID_HANDLE_VALUE to pick up our NULL michael@0: // usage for errors. michael@0: bool IsValid() const { return handle_ != NULL; } michael@0: michael@0: operator HANDLE() { return handle_; } michael@0: michael@0: private: michael@0: HANDLE handle_; michael@0: michael@0: DISALLOW_EVIL_CONSTRUCTORS(ScopedFindFileHandle); michael@0: }; michael@0: michael@0: // Like ScopedHandle but for HDC. Only use this on HDCs returned from michael@0: // CreateCompatibleDC. For an HDC returned by GetDC, use ReleaseDC instead. michael@0: class ScopedHDC { michael@0: public: michael@0: ScopedHDC() : hdc_(NULL) { } michael@0: explicit ScopedHDC(HDC h) : hdc_(h) { } michael@0: michael@0: ~ScopedHDC() { michael@0: Close(); michael@0: } michael@0: michael@0: HDC Get() { michael@0: return hdc_; michael@0: } michael@0: michael@0: void Set(HDC h) { michael@0: Close(); michael@0: hdc_ = h; michael@0: } michael@0: michael@0: operator HDC() { return hdc_; } michael@0: michael@0: private: michael@0: void Close() { michael@0: #ifdef NOGDI michael@0: assert(false); michael@0: #else michael@0: if (hdc_) michael@0: DeleteDC(hdc_); michael@0: #endif // NOGDI michael@0: } michael@0: michael@0: HDC hdc_; michael@0: DISALLOW_EVIL_CONSTRUCTORS(ScopedHDC); michael@0: }; michael@0: michael@0: // Like ScopedHandle but for GDI objects. michael@0: template michael@0: class ScopedGDIObject { michael@0: public: michael@0: ScopedGDIObject() : object_(NULL) {} michael@0: explicit ScopedGDIObject(T object) : object_(object) {} michael@0: michael@0: ~ScopedGDIObject() { michael@0: Close(); michael@0: } michael@0: michael@0: T Get() { michael@0: return object_; michael@0: } michael@0: michael@0: void Set(T object) { michael@0: if (object_ && object != object_) michael@0: Close(); michael@0: object_ = object; michael@0: } michael@0: michael@0: ScopedGDIObject& operator=(T object) { michael@0: Set(object); michael@0: return *this; michael@0: } michael@0: michael@0: operator T() { return object_; } michael@0: michael@0: private: michael@0: void Close() { michael@0: if (object_) michael@0: DeleteObject(object_); michael@0: } michael@0: michael@0: T object_; michael@0: DISALLOW_COPY_AND_ASSIGN(ScopedGDIObject); michael@0: }; michael@0: michael@0: // Typedefs for some common use cases. michael@0: typedef ScopedGDIObject ScopedBitmap; michael@0: typedef ScopedGDIObject ScopedHRGN; michael@0: typedef ScopedGDIObject ScopedHFONT; michael@0: michael@0: michael@0: // Like ScopedHandle except for HGLOBAL. michael@0: template michael@0: class ScopedHGlobal { michael@0: public: michael@0: explicit ScopedHGlobal(HGLOBAL glob) : glob_(glob) { michael@0: data_ = static_cast(GlobalLock(glob_)); michael@0: } michael@0: ~ScopedHGlobal() { michael@0: GlobalUnlock(glob_); michael@0: } michael@0: michael@0: T* get() { return data_; } michael@0: michael@0: size_t Size() const { return GlobalSize(glob_); } michael@0: michael@0: T* operator->() const { michael@0: assert(data_ != 0); michael@0: return data_; michael@0: } michael@0: michael@0: private: michael@0: HGLOBAL glob_; michael@0: michael@0: T* data_; michael@0: michael@0: DISALLOW_EVIL_CONSTRUCTORS(ScopedHGlobal); michael@0: }; michael@0: michael@0: #endif // BASE_SCOPED_HANDLE_WIN_H_