blob: 153d2172a14b6cc80860069fbf6b995885b6feee [file] [log] [blame]
/*
Copyright 2014 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef GOOPY_BASE_SCOPED_HANDLE_WIN_H__
#define GOOPY_BASE_SCOPED_HANDLE_WIN_H__
#include <windows.h>
#include <commctrl.h>
#include "base/basictypes.h"
#include "base/logging.h"
// Used so we always remember to close the handle.
// The class interface matches that of ScopedStdioHandle in addition to an
// IsValid() method since invalid handles on windows can be either NULL or
// INVALID_HANDLE_VALUE (-1).
//
// Example:
// ScopedHandle hfile(CreateFile(...));
// if (!hfile.Get())
// ...process error
// ReadFile(hfile.Get(), ...);
//
// To sqirrel the handle away somewhere else:
// secret_handle_ = hfile.Detach();
//
// To explicitly close the handle:
// hfile.Close();
template <class Handle, class ClosePolicy>
class GenericScopedHandle {
public:
GenericScopedHandle() : handle_(NULL) {
}
explicit GenericScopedHandle(Handle h) : handle_(NULL) {
Reset(h);
}
~GenericScopedHandle() {
Close();
}
// Use this instead of comparing to INVALID_HANDLE_VALUE to pick up our NULL
// usage for errors.
bool IsValid() const {
return handle_ != NULL;
}
void Reset(Handle new_handle) {
Close();
// Windows is inconsistent about invalid handles, so we always use NULL
if (new_handle != INVALID_HANDLE_VALUE)
handle_ = new_handle;
}
Handle Get() const {
return handle_;
}
operator Handle() { return handle_; }
Handle Detach() {
// transfers ownership away from this object
Handle h = handle_;
handle_ = NULL;
return h;
}
void Close() {
if (handle_) {
ClosePolicy::Do(handle_);
handle_ = NULL;
}
}
protected:
Handle handle_;
DISALLOW_COPY_AND_ASSIGN(GenericScopedHandle);
};
#define DEFINE_SCOPED_HANDLE(Name, Handle, CloseFunction) \
class Name##ClosePolicy { \
public: \
static void Do(Handle handle) { \
CloseFunction(handle); \
} \
}; \
typedef GenericScopedHandle<Handle, Name##ClosePolicy> Name;
// Common handles.
DEFINE_SCOPED_HANDLE(ScopedHandle, HANDLE, CloseHandle);
DEFINE_SCOPED_HANDLE(ScopedFindFileHandle, HANDLE, FindClose);
DEFINE_SCOPED_HANDLE(ScopedDCHandle, HDC, DeleteDC);
DEFINE_SCOPED_HANDLE(ScopedGlobalHandle, HGLOBAL, GlobalFree);
DEFINE_SCOPED_HANDLE(ScopedLibrary, HMODULE, FreeLibrary);
DEFINE_SCOPED_HANDLE(ScopedImageList, HIMAGELIST, ImageList_Destroy);
// Scoped GDI objects.
template <class Handle>
class ScopedGDIObjectClosePolicy {
public:
static void Do(Handle handle) {
DeleteObject(handle);
}
};
template <class Handle>
class ScopedGDIObject
: public GenericScopedHandle<Handle,
ScopedGDIObjectClosePolicy<Handle> > {
public:
ScopedGDIObject() {}
explicit ScopedGDIObject(Handle h) {
Reset(h);
}
};
// Typedefs for some common use cases.
typedef ScopedGDIObject<HBITMAP> ScopedBitmap;
typedef ScopedGDIObject<HBRUSH> ScopedBrush;
typedef ScopedGDIObject<HFONT> ScopedFont;
typedef ScopedGDIObject<HPEN> ScopedPen;
typedef ScopedGDIObject<HRGN> ScopedRegion;
// Data locker for an HGLOBAL.
template<class T = void>
class ScopedGlobalHandleLocker {
public:
explicit ScopedGlobalHandleLocker(HGLOBAL glob) : glob_(glob) {
data_ = reinterpret_cast<T*>(GlobalLock(glob_));
}
~ScopedGlobalHandleLocker() {
GlobalUnlock(glob_);
}
T* data() { return data_; }
size_t size() const { return GlobalSize(glob_); }
T* operator->() const {
assert(data_ != 0);
return data_;
}
private:
HGLOBAL glob_;
T* data_;
DISALLOW_COPY_AND_ASSIGN(ScopedGlobalHandleLocker);
};
#endif // GOOPY_BASE_SCOPED_HANDLE_WIN_H__