/* -*- 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 #include "nsAutoRef.h" #include "nscore.h" #include "mozilla/Assertions.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 { public: typedef HKEY RawRef; static HKEY Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { RegCloseKey(aFD); } } }; template<> class nsAutoRefTraits { public: typedef HDC RawRef; static HDC Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { ::DeleteDC(aFD); } } }; template<> class nsAutoRefTraits { public: typedef HBRUSH RawRef; static HBRUSH Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { ::DeleteObject(aFD); } } }; template<> class nsAutoRefTraits { public: typedef HRGN RawRef; static HRGN Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { ::DeleteObject(aFD); } } }; template<> class nsAutoRefTraits { public: typedef HBITMAP RawRef; static HBITMAP Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { ::DeleteObject(aFD); } } }; template<> class nsAutoRefTraits { public: typedef SC_HANDLE RawRef; static SC_HANDLE Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { CloseServiceHandle(aFD); } } }; template<> class nsSimpleRef { 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 { public: typedef HMODULE RawRef; static RawRef Void() { return nullptr; } static void Release(RawRef aFD) { if (aFD != Void()) { FreeLibrary(aFD); } } }; template<> class nsAutoRefTraits { 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 { 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 // 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 { public: typedef nsHPRINTER RawRef; static RawRef Void() { return nullptr; } static void Release(RawRef hPrinter) { ::ClosePrinter(hPrinter); } }; typedef nsAutoRef nsAutoRegKey; typedef nsAutoRef nsAutoHDC; typedef nsAutoRef nsAutoBrush; typedef nsAutoRef nsAutoRegion; typedef nsAutoRef nsAutoBitmap; typedef nsAutoRef nsAutoServiceHandle; typedef nsAutoRef nsAutoHandle; typedef nsAutoRef nsModuleHandle; typedef nsAutoRef nsAutoDevMode; typedef nsAutoRef nsAutoGlobalMem; typedef nsAutoRef nsAutoPrinter; namespace { // Construct a path "\". 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); } } // How long to wait for a created process to become available for input, // to prevent that process's windows being forced to the background. // This is used across update, restart, and the launcher. const DWORD kWaitForInputIdleTimeoutMS = 10*1000; #endif