Bug 1910362 - Create new Nimbus helper r=aaronmt,ohorvath
[gecko.git] / xpcom / base / nsWindowsHelpers.h
blob7c9127580371b1c9b765a8dc9c724f70ece01765
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // NB: This code may be used from non-XPCOM code, in particular, the
8 // Windows Default Browser Agent.
10 #ifndef nsWindowsHelpers_h
11 #define nsWindowsHelpers_h
13 #include <windows.h>
14 #include <msi.h>
15 #include "nsAutoRef.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/UniquePtr.h"
19 // ----------------------------------------------------------------------------
20 // Critical Section helper class
21 // ----------------------------------------------------------------------------
23 class AutoCriticalSection {
24 public:
25 explicit AutoCriticalSection(LPCRITICAL_SECTION aSection)
26 : mSection(aSection) {
27 ::EnterCriticalSection(mSection);
29 ~AutoCriticalSection() { ::LeaveCriticalSection(mSection); }
31 private:
32 LPCRITICAL_SECTION mSection;
35 template <>
36 class nsAutoRefTraits<HKEY> {
37 public:
38 typedef HKEY RawRef;
39 static HKEY Void() { return nullptr; }
41 static void Release(RawRef aFD) {
42 if (aFD != Void()) {
43 RegCloseKey(aFD);
48 template <>
49 class nsAutoRefTraits<HDC> {
50 public:
51 typedef HDC RawRef;
52 static HDC Void() { return nullptr; }
54 static void Release(RawRef aFD) {
55 if (aFD != Void()) {
56 ::DeleteDC(aFD);
61 template <>
62 class nsAutoRefTraits<HFONT> {
63 public:
64 typedef HFONT RawRef;
65 static HFONT Void() { return nullptr; }
67 static void Release(RawRef aFD) {
68 if (aFD != Void()) {
69 ::DeleteObject(aFD);
74 template <>
75 class nsAutoRefTraits<HBRUSH> {
76 public:
77 typedef HBRUSH RawRef;
78 static HBRUSH Void() { return nullptr; }
80 static void Release(RawRef aFD) {
81 if (aFD != Void()) {
82 ::DeleteObject(aFD);
87 template <>
88 class nsAutoRefTraits<HRGN> {
89 public:
90 typedef HRGN RawRef;
91 static HRGN Void() { return nullptr; }
93 static void Release(RawRef aFD) {
94 if (aFD != Void()) {
95 ::DeleteObject(aFD);
100 template <>
101 class nsAutoRefTraits<HBITMAP> {
102 public:
103 typedef HBITMAP RawRef;
104 static HBITMAP Void() { return nullptr; }
106 static void Release(RawRef aFD) {
107 if (aFD != Void()) {
108 ::DeleteObject(aFD);
113 template <>
114 class nsAutoRefTraits<SC_HANDLE> {
115 public:
116 typedef SC_HANDLE RawRef;
117 static SC_HANDLE Void() { return nullptr; }
119 static void Release(RawRef aFD) {
120 if (aFD != Void()) {
121 CloseServiceHandle(aFD);
126 template <>
127 class nsSimpleRef<HANDLE> {
128 protected:
129 typedef HANDLE RawRef;
131 nsSimpleRef() : mRawRef(nullptr) {}
133 explicit nsSimpleRef(RawRef aRawRef) : mRawRef(aRawRef) {}
135 bool HaveResource() const {
136 return mRawRef && mRawRef != INVALID_HANDLE_VALUE;
139 public:
140 RawRef get() const { return mRawRef; }
142 static void Release(RawRef aRawRef) {
143 if (aRawRef && aRawRef != INVALID_HANDLE_VALUE) {
144 CloseHandle(aRawRef);
147 RawRef mRawRef;
150 template <>
151 class nsAutoRefTraits<HMODULE> {
152 public:
153 typedef HMODULE RawRef;
154 static RawRef Void() { return nullptr; }
156 static void Release(RawRef aFD) {
157 if (aFD != Void()) {
158 FreeLibrary(aFD);
163 template <>
164 class nsAutoRefTraits<DEVMODEW*> {
165 public:
166 typedef DEVMODEW* RawRef;
167 static RawRef Void() { return nullptr; }
169 static void Release(RawRef aDevMode) {
170 if (aDevMode != Void()) {
171 ::HeapFree(::GetProcessHeap(), 0, aDevMode);
176 template <>
177 class nsAutoRefTraits<MSIHANDLE> {
178 public:
179 typedef MSIHANDLE RawRef;
180 static RawRef Void() { return 0; }
182 static void Release(RawRef aHandle) {
183 if (aHandle != Void()) {
184 ::MsiCloseHandle(aHandle);
189 // HGLOBAL is just a typedef of HANDLE which nsSimpleRef has a specialization
190 // of, that means having a nsAutoRefTraits specialization for HGLOBAL is
191 // useless. Therefore we create a wrapper class for HGLOBAL to make
192 // nsAutoRefTraits and nsAutoRef work as intention.
193 class nsHGLOBAL {
194 public:
195 MOZ_IMPLICIT nsHGLOBAL(HGLOBAL hGlobal) : m_hGlobal(hGlobal) {}
197 operator HGLOBAL() const { return m_hGlobal; }
199 private:
200 HGLOBAL m_hGlobal;
203 template <>
204 class nsAutoRefTraits<nsHGLOBAL> {
205 public:
206 typedef nsHGLOBAL RawRef;
207 static RawRef Void() { return nullptr; }
209 static void Release(RawRef hGlobal) { ::GlobalFree(hGlobal); }
212 // Because Printer's HANDLE uses ClosePrinter and we already have
213 // nsAutoRef<HANDLE> which uses CloseHandle so we need to create a wrapper class
214 // for HANDLE to have another specialization for nsAutoRefTraits.
215 class nsHPRINTER {
216 public:
217 MOZ_IMPLICIT nsHPRINTER(HANDLE hPrinter) : m_hPrinter(hPrinter) {}
219 operator HANDLE() const { return m_hPrinter; }
221 HANDLE* operator&() { return &m_hPrinter; }
223 private:
224 HANDLE m_hPrinter;
227 // winspool.h header has AddMonitor macro, it conflicts with AddMonitor member
228 // function in TaskbarPreview.cpp and TaskbarTabPreview.cpp. Beside, we only
229 // need ClosePrinter here for Release function, so having its prototype is
230 // enough.
231 extern "C" BOOL WINAPI ClosePrinter(HANDLE hPrinter);
233 template <>
234 class nsAutoRefTraits<nsHPRINTER> {
235 public:
236 typedef nsHPRINTER RawRef;
237 static RawRef Void() { return nullptr; }
239 static void Release(RawRef hPrinter) { ::ClosePrinter(hPrinter); }
242 typedef nsAutoRef<HKEY> nsAutoRegKey;
243 typedef nsAutoRef<HDC> nsAutoHDC;
244 typedef nsAutoRef<HFONT> nsAutoFont;
245 typedef nsAutoRef<HBRUSH> nsAutoBrush;
246 typedef nsAutoRef<HRGN> nsAutoRegion;
247 typedef nsAutoRef<HBITMAP> nsAutoBitmap;
248 typedef nsAutoRef<SC_HANDLE> nsAutoServiceHandle;
249 typedef nsAutoRef<HANDLE> nsAutoHandle;
250 typedef nsAutoRef<HMODULE> nsModuleHandle;
251 typedef nsAutoRef<DEVMODEW*> nsAutoDevMode;
252 typedef nsAutoRef<nsHGLOBAL> nsAutoGlobalMem;
253 typedef nsAutoRef<nsHPRINTER> nsAutoPrinter;
254 typedef nsAutoRef<MSIHANDLE> nsAutoMsiHandle;
256 // Construct a path "<system32>\<aModule>". return false if the output buffer
257 // is too small.
258 // Note: If the system path cannot be found, or doesn't fit in the output buffer
259 // with the module name, we will just ignore the system path and output the
260 // module name alone;
261 // this may mean using a normal search path wherever the output is used.
262 bool inline ConstructSystem32Path(LPCWSTR aModule, WCHAR* aSystemPath,
263 UINT aSize) {
264 MOZ_ASSERT(aSystemPath);
266 size_t fileLen = wcslen(aModule);
267 if (fileLen >= aSize) {
268 // The module name alone cannot even fit!
269 return false;
272 size_t systemDirLen = GetSystemDirectoryW(aSystemPath, aSize);
274 if (systemDirLen) {
275 if (systemDirLen < aSize - fileLen) {
276 // Make the system directory path terminate with a slash.
277 if (aSystemPath[systemDirLen - 1] != L'\\') {
278 if (systemDirLen + 1 < aSize - fileLen) {
279 aSystemPath[systemDirLen] = L'\\';
280 ++systemDirLen;
281 // No need to re-nullptr terminate.
282 } else {
283 // Couldn't fit the system path with added slash.
284 systemDirLen = 0;
287 } else {
288 // Couldn't fit the system path.
289 systemDirLen = 0;
293 MOZ_ASSERT(systemDirLen + fileLen < aSize);
295 wcsncpy(aSystemPath + systemDirLen, aModule, fileLen);
296 aSystemPath[systemDirLen + fileLen] = L'\0';
297 return true;
300 HMODULE inline LoadLibrarySystem32(LPCWSTR aModule) {
301 return LoadLibraryExW(aModule, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
304 // for UniquePtr
305 struct LocalFreeDeleter {
306 void operator()(void* aPtr) { ::LocalFree(aPtr); }
309 struct VirtualFreeDeleter {
310 void operator()(void* aPtr) { ::VirtualFree(aPtr, 0, MEM_RELEASE); }
313 // for UniquePtr to store a PSID
314 struct FreeSidDeleter {
315 void operator()(void* aPtr) { ::FreeSid(aPtr); }
317 // Unfortunately, although SID is a struct, PSID is a void*
318 // This typedef will work for storing a PSID in a UniquePtr and should make
319 // things a bit more readable.
320 typedef mozilla::UniquePtr<void, FreeSidDeleter> UniqueSidPtr;
322 struct CloseHandleDeleter {
323 typedef HANDLE pointer;
324 void operator()(pointer aHandle) {
325 if (aHandle != INVALID_HANDLE_VALUE) {
326 ::CloseHandle(aHandle);
331 // One caller of this function is early in startup and several others are not,
332 // so they have different ways of determining the two parameters. This function
333 // exists just so any future code that needs to determine whether the dynamic
334 // blocklist is disabled remembers to check whether safe mode is active.
335 inline bool IsDynamicBlocklistDisabled(bool isSafeMode,
336 bool hasCommandLineDisableArgument) {
337 return isSafeMode || hasCommandLineDisableArgument;
339 #endif