gecko-dev/xpcom/base/nsWindowsHelpers.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

331 lines
7.9 KiB
C
Raw Normal View History

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 11:12:37 +00:00
/* 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:
explicit AutoCriticalSection(LPCRITICAL_SECTION aSection)
: mSection(aSection) {
::EnterCriticalSection(mSection);
}
~AutoCriticalSection() { ::LeaveCriticalSection(mSection); }
private:
LPCRITICAL_SECTION mSection;
};
class ImpersonationScope {
private:
bool success;
public:
explicit ImpersonationScope(HANDLE token) {
success = token && SetThreadToken(nullptr, token);
}
MOZ_IMPLICIT operator bool() const { return success; }
~ImpersonationScope() {
if (success) {
RevertToSelf();
}
}
private:
ImpersonationScope(const ImpersonationScope&) = delete;
ImpersonationScope& operator=(const ImpersonationScope&) = delete;
ImpersonationScope(ImpersonationScope&&) = delete;
ImpersonationScope& operator=(ImpersonationScope&&) = delete;
};
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) {}
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); }
};
Bug 1458314 - Move the update directory to an installation specific location r=rstrong This change applies to Windows only. Firefox will need to migrate the directory from the old location to the new location. This will be done only once by setting the pref `app.update.migrated.updateDir2.<install path hash>` to `true` once migration has completed. Note: The pref name app.update.migrated.updateDir has already been used, thus the '2' suffix. It can be found in ESR24. This also removes the old handling fallback for generating the update directory path. Since xulrunner is no longer supported, this should no longer be needed. If neither the vendor nor app name are defined, it falls back to the literal string "Mozilla". The code to generate the update directory path and the installation hash have been moved to the updatecommon library. This will allow those functions to be used in Firefox, the Mozilla Maintenance Service, the Mozilla Maintenance Service Installer, and TestAUSHelper. Additionally, the function that generates the update directory path now has extra functionality. It creates the update directory, sets the permissions on it and, optionally, recursively sets the permissions on everything within. This patch adds functionality that allows Firefox to set permissions on the new update directory on write failure. It attempts to set the permissions itself and, if that fails and the maintenance service is enabled, it calls into the maintenance service to try from there. If a write fails and the permissions cannot be fixed, the user is prompted to reinstall. Differential Revision: https://phabricator.services.mozilla.com/D4249 --HG-- rename : toolkit/mozapps/update/updater/win_dirent.cpp => toolkit/mozapps/update/common/win_dirent.cpp rename : toolkit/mozapps/update/tests/unit_aus_update/cleanupSuccessLogMove.js => toolkit/mozapps/update/tests/unit_aus_update/updateDirectoryMigrate.js extra : moz-landing-system : lando
2018-10-23 21:41:04 +00:00
template <>
class nsAutoRefTraits<PSID> {
public:
typedef PSID RawRef;
static RawRef Void() { return nullptr; }
static void Release(RawRef aFD) {
if (aFD != Void()) {
FreeSid(aFD);
}
}
};
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;
Bug 1458314 - Move the update directory to an installation specific location r=rstrong This change applies to Windows only. Firefox will need to migrate the directory from the old location to the new location. This will be done only once by setting the pref `app.update.migrated.updateDir2.<install path hash>` to `true` once migration has completed. Note: The pref name app.update.migrated.updateDir has already been used, thus the '2' suffix. It can be found in ESR24. This also removes the old handling fallback for generating the update directory path. Since xulrunner is no longer supported, this should no longer be needed. If neither the vendor nor app name are defined, it falls back to the literal string "Mozilla". The code to generate the update directory path and the installation hash have been moved to the updatecommon library. This will allow those functions to be used in Firefox, the Mozilla Maintenance Service, the Mozilla Maintenance Service Installer, and TestAUSHelper. Additionally, the function that generates the update directory path now has extra functionality. It creates the update directory, sets the permissions on it and, optionally, recursively sets the permissions on everything within. This patch adds functionality that allows Firefox to set permissions on the new update directory on write failure. It attempts to set the permissions itself and, if that fails and the maintenance service is enabled, it calls into the maintenance service to try from there. If a write fails and the permissions cannot be fixed, the user is prompted to reinstall. Differential Revision: https://phabricator.services.mozilla.com/D4249 --HG-- rename : toolkit/mozapps/update/updater/win_dirent.cpp => toolkit/mozapps/update/common/win_dirent.cpp rename : toolkit/mozapps/update/tests/unit_aus_update/cleanupSuccessLogMove.js => toolkit/mozapps/update/tests/unit_aus_update/updateDirectoryMigrate.js extra : moz-landing-system : lando
2018-10-23 21:41:04 +00:00
typedef nsAutoRef<PSID> nsAutoSid;
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
Bug 1458314 - Move the update directory to an installation specific location r=rstrong This change applies to Windows only. Firefox will need to migrate the directory from the old location to the new location. This will be done only once by setting the pref `app.update.migrated.updateDir2.<install path hash>` to `true` once migration has completed. Note: The pref name app.update.migrated.updateDir has already been used, thus the '2' suffix. It can be found in ESR24. This also removes the old handling fallback for generating the update directory path. Since xulrunner is no longer supported, this should no longer be needed. If neither the vendor nor app name are defined, it falls back to the literal string "Mozilla". The code to generate the update directory path and the installation hash have been moved to the updatecommon library. This will allow those functions to be used in Firefox, the Mozilla Maintenance Service, the Mozilla Maintenance Service Installer, and TestAUSHelper. Additionally, the function that generates the update directory path now has extra functionality. It creates the update directory, sets the permissions on it and, optionally, recursively sets the permissions on everything within. This patch adds functionality that allows Firefox to set permissions on the new update directory on write failure. It attempts to set the permissions itself and, if that fails and the maintenance service is enabled, it calls into the maintenance service to try from there. If a write fails and the permissions cannot be fixed, the user is prompted to reinstall. Differential Revision: https://phabricator.services.mozilla.com/D4249 --HG-- rename : toolkit/mozapps/update/updater/win_dirent.cpp => toolkit/mozapps/update/common/win_dirent.cpp rename : toolkit/mozapps/update/tests/unit_aus_update/cleanupSuccessLogMove.js => toolkit/mozapps/update/tests/unit_aus_update/updateDirectoryMigrate.js extra : moz-landing-system : lando
2018-10-23 21:41:04 +00:00
struct LocalFreeDeleter {
void operator()(void* aPtr) { ::LocalFree(aPtr); }
};
// for UnqiuePtr<_PROC_THREAD_ATTRIBUTE_LIST, ProcThreadAttributeListDeleter>
struct ProcThreadAttributeListDeleter {
void operator()(void* aPtr) {
::DeleteProcThreadAttributeList(
static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(aPtr));
}
};
#endif