summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-21 07:00:22 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-21 07:00:22 +0000
commitb4966382d5d5b72c2fa1ba76aa045128eaf90418 (patch)
treef57004fa72e42181b6e3186528ca331ceb05cfd6 /base
parentf44d1193f728c17cc4fd7adfe11a3fce82cddb9b (diff)
downloadchromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.zip
chromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.tar.gz
chromium_src-b4966382d5d5b72c2fa1ba76aa045128eaf90418.tar.bz2
Move ScopedCoMem to base/win. This is to allow the class to be used from folders that aren't allowed to depend on chrome/common (and besides, ScopedCoMem belongs in base/win anyway).
I'm also adding a DCHECK to ScopedComInitializer that checks if the construction thread is the same as the destruction thread. The reason for this is that I've noticed cases where an instance is created on the heap (as opposed to the usual stack usecase) which could leave the door open to incorrect COM uninitialization. Review URL: http://codereview.chromium.org/8354035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106687 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/base.gypi1
-rw-r--r--base/win/scoped_co_mem.h65
-rw-r--r--base/win/scoped_com_initializer.h26
3 files changed, 89 insertions, 3 deletions
diff --git a/base/base.gypi b/base/base.gypi
index b3a97af..e2f0a7d 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -370,6 +370,7 @@
'win/resource_util.h',
'win/scoped_bstr.cc',
'win/scoped_bstr.h',
+ 'win/scoped_co_mem.h',
'win/scoped_com_initializer.h',
'win/scoped_comptr.h',
'win/scoped_gdi_object.h',
diff --git a/base/win/scoped_co_mem.h b/base/win/scoped_co_mem.h
new file mode 100644
index 0000000..ccbe707
--- /dev/null
+++ b/base/win/scoped_co_mem.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 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 BASE_WIN_SCOPED_CO_MEM_H_
+#define BASE_WIN_SCOPED_CO_MEM_H_
+#pragma once
+
+#include <objbase.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+namespace base {
+namespace win {
+
+// Simple scoped memory releaser class for COM allocated memory.
+// Example:
+// base::win::ScopedCoMem<ITEMIDLIST> file_item;
+// SHGetSomeInfo(&file_item, ...);
+// ...
+// return; <-- memory released
+template<typename T>
+class ScopedCoMem {
+ public:
+ ScopedCoMem() : mem_ptr_(NULL) {}
+ ~ScopedCoMem() {
+ Reset(NULL);
+ }
+
+ T** operator&() { // NOLINT
+ DCHECK(mem_ptr_ == NULL); // To catch memory leaks.
+ return &mem_ptr_;
+ }
+
+ operator T*() {
+ return mem_ptr_;
+ }
+
+ T* operator->() {
+ DCHECK(mem_ptr_ != NULL);
+ return mem_ptr_;
+ }
+
+ const T* operator->() const {
+ DCHECK(mem_ptr_ != NULL);
+ return mem_ptr_;
+ }
+
+ void Reset(T* ptr) {
+ if (mem_ptr_)
+ CoTaskMemFree(mem_ptr_);
+ mem_ptr_ = ptr;
+ }
+
+ private:
+ T* mem_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedCoMem);
+};
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_CO_MEM_H_
diff --git a/base/win/scoped_com_initializer.h b/base/win/scoped_com_initializer.h
index 0ea5199..0cf1ac7 100644
--- a/base/win/scoped_com_initializer.h
+++ b/base/win/scoped_com_initializer.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/basictypes.h"
+#include "base/logging.h"
#include "build/build_config.h"
#if defined(OS_WIN)
@@ -24,15 +25,20 @@ class ScopedCOMInitializer {
enum SelectMTA { kMTA };
// Constructor for STA initialization.
- ScopedCOMInitializer() : hr_(CoInitialize(NULL)) {
+ ScopedCOMInitializer() {
+ Initialize(COINIT_APARTMENTTHREADED);
}
// Constructor for MTA initialization.
- explicit ScopedCOMInitializer(SelectMTA mta)
- : hr_(CoInitializeEx(NULL, COINIT_MULTITHREADED)) {
+ explicit ScopedCOMInitializer(SelectMTA mta) {
+ Initialize(COINIT_MULTITHREADED);
}
ScopedCOMInitializer::~ScopedCOMInitializer() {
+#ifndef NDEBUG
+ // Using the windows API directly to avoid dependency on platform_thread.
+ DCHECK_EQ(GetCurrentThreadId(), thread_id_);
+#endif
if (SUCCEEDED(hr_))
CoUninitialize();
}
@@ -40,7 +46,21 @@ class ScopedCOMInitializer {
bool succeeded() const { return SUCCEEDED(hr_); }
private:
+ void Initialize(COINIT init) {
+#ifndef NDEBUG
+ thread_id_ = GetCurrentThreadId();
+#endif
+ hr_ = CoInitializeEx(NULL, init);
+ }
+
HRESULT hr_;
+#ifndef NDEBUG
+ // In debug builds we use this variable to catch a potential bug where a
+ // ScopedCOMInitializer instance is deleted on a different thread than it
+ // was initially created on. If that ever happens it can have bad
+ // consequences and the cause can be tricky to track down.
+ DWORD thread_id_;
+#endif
DISALLOW_COPY_AND_ASSIGN(ScopedCOMInitializer);
};