summaryrefslogtreecommitdiffstats
path: root/xpcom/base/nsWindowsHelpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/base/nsWindowsHelpers.h')
-rw-r--r--xpcom/base/nsWindowsHelpers.h310
1 files changed, 310 insertions, 0 deletions
diff --git a/xpcom/base/nsWindowsHelpers.h b/xpcom/base/nsWindowsHelpers.h
new file mode 100644
index 0000000000..6f4e7db761
--- /dev/null
+++ b/xpcom/base/nsWindowsHelpers.h
@@ -0,0 +1,310 @@
+/* -*- 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/. */
+
+// NB: This code may be used from non-XPCOM code, in particular, the
+// Windows Default Browser Agent.
+
+#ifndef nsWindowsHelpers_h
+#define nsWindowsHelpers_h
+
+#include <windows.h>
+#include "nsAutoRef.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/UniquePtr.h"
+
+// ----------------------------------------------------------------------------
+// Critical Section helper class
+// ----------------------------------------------------------------------------
+
+class AutoCriticalSection {
+ public:
+ explicit 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<HFONT> {
+ public:
+ typedef HFONT RawRef;
+ static HFONT Void() { return nullptr; }
+
+ static void Release(RawRef aFD) {
+ if (aFD != Void()) {
+ ::DeleteObject(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) {}
+
+ explicit 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:
+ MOZ_IMPLICIT 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:
+ MOZ_IMPLICIT 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<HFONT> nsAutoFont;
+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);
+}
+
+} // namespace
+
+// for UniquePtr
+struct LocalFreeDeleter {
+ void operator()(void* aPtr) { ::LocalFree(aPtr); }
+};
+
+// for UniquePtr to store a PSID
+struct FreeSidDeleter {
+ void operator()(void* aPtr) { ::FreeSid(aPtr); }
+};
+// Unfortunately, although SID is a struct, PSID is a void*
+// This typedef will work for storing a PSID in a UniquePtr and should make
+// things a bit more readable.
+typedef mozilla::UniquePtr<void, FreeSidDeleter> UniqueSidPtr;
+#endif