summaryrefslogtreecommitdiff
path: root/xpcom/base/nsWindowsHelpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/base/nsWindowsHelpers.h')
-rw-r--r--xpcom/base/nsWindowsHelpers.h371
1 files changed, 371 insertions, 0 deletions
diff --git a/xpcom/base/nsWindowsHelpers.h b/xpcom/base/nsWindowsHelpers.h
new file mode 100644
index 0000000000..66505b3458
--- /dev/null
+++ b/xpcom/base/nsWindowsHelpers.h
@@ -0,0 +1,371 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsWindowsHelpers_h
+#define nsWindowsHelpers_h
+
+#include <windows.h>
+#include "nsAutoRef.h"
+#include "nscore.h"
+#include "mozilla/Assertions.h"
+
+// ----------------------------------------------------------------------------
+// Critical Section helper class
+// ----------------------------------------------------------------------------
+
+class AutoCriticalSection
+{
+public:
+ AutoCriticalSection(LPCRITICAL_SECTION aSection)
+ : mSection(aSection)
+ {
+ ::EnterCriticalSection(mSection);
+ }
+ ~AutoCriticalSection()
+ {
+ ::LeaveCriticalSection(mSection);
+ }
+private:
+ LPCRITICAL_SECTION mSection;
+};
+
+template<>
+class nsAutoRefTraits<HKEY>
+{
+public:
+ typedef HKEY RawRef;
+ static HKEY Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ RegCloseKey(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<HDC>
+{
+public:
+ typedef HDC RawRef;
+ static HDC Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ ::DeleteDC(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<HBRUSH>
+{
+public:
+ typedef HBRUSH RawRef;
+ static HBRUSH Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ ::DeleteObject(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<HRGN>
+{
+public:
+ typedef HRGN RawRef;
+ static HRGN Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ ::DeleteObject(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<HBITMAP>
+{
+public:
+ typedef HBITMAP RawRef;
+ static HBITMAP Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ ::DeleteObject(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<SC_HANDLE>
+{
+public:
+ typedef SC_HANDLE RawRef;
+ static SC_HANDLE Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ CloseServiceHandle(aFD);
+ }
+ }
+};
+
+template<>
+class nsSimpleRef<HANDLE>
+{
+protected:
+ typedef HANDLE RawRef;
+
+ nsSimpleRef() : mRawRef(nullptr)
+ {
+ }
+
+ nsSimpleRef(RawRef aRawRef) : mRawRef(aRawRef)
+ {
+ }
+
+ bool HaveResource() const
+ {
+ return mRawRef && mRawRef != INVALID_HANDLE_VALUE;
+ }
+
+public:
+ RawRef get() const
+ {
+ return mRawRef;
+ }
+
+ static void Release(RawRef aRawRef)
+ {
+ if (aRawRef && aRawRef != INVALID_HANDLE_VALUE) {
+ CloseHandle(aRawRef);
+ }
+ }
+ RawRef mRawRef;
+};
+
+
+template<>
+class nsAutoRefTraits<HMODULE>
+{
+public:
+ typedef HMODULE RawRef;
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ FreeLibrary(aFD);
+ }
+ }
+};
+
+
+template<>
+class nsAutoRefTraits<DEVMODEW*>
+{
+public:
+ typedef DEVMODEW* RawRef;
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aDevMode)
+ {
+ if (aDevMode != Void()) {
+ ::HeapFree(::GetProcessHeap(), 0, aDevMode);
+ }
+ }
+};
+
+
+// HGLOBAL is just a typedef of HANDLE which nsSimpleRef has a specialization of,
+// that means having a nsAutoRefTraits specialization for HGLOBAL is useless.
+// Therefore we create a wrapper class for HGLOBAL to make nsAutoRefTraits and
+// nsAutoRef work as intention.
+class nsHGLOBAL {
+public:
+ nsHGLOBAL(HGLOBAL hGlobal) : m_hGlobal(hGlobal)
+ {
+ }
+
+ operator HGLOBAL() const
+ {
+ return m_hGlobal;
+ }
+
+private:
+ HGLOBAL m_hGlobal;
+};
+
+
+template<>
+class nsAutoRefTraits<nsHGLOBAL>
+{
+public:
+ typedef nsHGLOBAL RawRef;
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef hGlobal)
+ {
+ ::GlobalFree(hGlobal);
+ }
+};
+
+
+// Because Printer's HANDLE uses ClosePrinter and we already have nsAutoRef<HANDLE>
+// which uses CloseHandle so we need to create a wrapper class for HANDLE to have
+// another specialization for nsAutoRefTraits.
+class nsHPRINTER {
+public:
+ nsHPRINTER(HANDLE hPrinter) : m_hPrinter(hPrinter)
+ {
+ }
+
+ operator HANDLE() const
+ {
+ return m_hPrinter;
+ }
+
+ HANDLE* operator&()
+ {
+ return &m_hPrinter;
+ }
+
+private:
+ HANDLE m_hPrinter;
+};
+
+
+// winspool.h header has AddMonitor macro, it conflicts with AddMonitor member
+// function in TaskbarPreview.cpp and TaskbarTabPreview.cpp. Beside, we only
+// need ClosePrinter here for Release function, so having its prototype is enough.
+extern "C" BOOL WINAPI ClosePrinter(HANDLE hPrinter);
+
+
+template<>
+class nsAutoRefTraits<nsHPRINTER>
+{
+public:
+ typedef nsHPRINTER RawRef;
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef hPrinter)
+ {
+ ::ClosePrinter(hPrinter);
+ }
+};
+
+
+typedef nsAutoRef<HKEY> nsAutoRegKey;
+typedef nsAutoRef<HDC> nsAutoHDC;
+typedef nsAutoRef<HBRUSH> nsAutoBrush;
+typedef nsAutoRef<HRGN> nsAutoRegion;
+typedef nsAutoRef<HBITMAP> nsAutoBitmap;
+typedef nsAutoRef<SC_HANDLE> nsAutoServiceHandle;
+typedef nsAutoRef<HANDLE> nsAutoHandle;
+typedef nsAutoRef<HMODULE> nsModuleHandle;
+typedef nsAutoRef<DEVMODEW*> nsAutoDevMode;
+typedef nsAutoRef<nsHGLOBAL> nsAutoGlobalMem;
+typedef nsAutoRef<nsHPRINTER> nsAutoPrinter;
+
+namespace {
+
+// Construct a path "<system32>\<aModule>". return false if the output buffer
+// is too small.
+// Note: If the system path cannot be found, or doesn't fit in the output buffer
+// with the module name, we will just ignore the system path and output the
+// module name alone;
+// this may mean using a normal search path wherever the output is used.
+bool inline
+ConstructSystem32Path(LPCWSTR aModule, WCHAR* aSystemPath, UINT aSize)
+{
+ MOZ_ASSERT(aSystemPath);
+
+ size_t fileLen = wcslen(aModule);
+ if (fileLen >= aSize) {
+ // The module name alone cannot even fit!
+ return false;
+ }
+
+ size_t systemDirLen = GetSystemDirectoryW(aSystemPath, aSize);
+
+ if (systemDirLen) {
+ if (systemDirLen < aSize - fileLen) {
+ // Make the system directory path terminate with a slash.
+ if (aSystemPath[systemDirLen - 1] != L'\\') {
+ if (systemDirLen + 1 < aSize - fileLen) {
+ aSystemPath[systemDirLen] = L'\\';
+ ++systemDirLen;
+ // No need to re-nullptr terminate.
+ } else {
+ // Couldn't fit the system path with added slash.
+ systemDirLen = 0;
+ }
+ }
+ } else {
+ // Couldn't fit the system path.
+ systemDirLen = 0;
+ }
+ }
+
+ MOZ_ASSERT(systemDirLen + fileLen < aSize);
+
+ wcsncpy(aSystemPath + systemDirLen, aModule, fileLen);
+ aSystemPath[systemDirLen + fileLen] = L'\0';
+ return true;
+}
+
+HMODULE inline
+LoadLibrarySystem32(LPCWSTR aModule)
+{
+ WCHAR systemPath[MAX_PATH + 1];
+ if (!ConstructSystem32Path(aModule, systemPath, MAX_PATH + 1)) {
+ return NULL;
+ }
+ return LoadLibraryW(systemPath);
+}
+
+}
+
+#endif