mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-23 04:41:54 +00:00
Bug 692255 - Get rid of prefetch files on Windows for faster startup. r=rstrong
This commit is contained in:
parent
2d2e1e01d3
commit
4ae600a9d9
@ -26,6 +26,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIWinTaskbar.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "windows.h"
|
||||
#include "shellapi.h"
|
||||
@ -52,6 +53,11 @@
|
||||
|
||||
#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
|
||||
|
||||
// We clear the prefetch files one time after the browser is started after
|
||||
// 60 seconds. After this is done once we set a pref so this will never happen
|
||||
// again except in updater code.
|
||||
#define CLEAR_PREFETCH_TIMEOUT_MS 60000
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
|
||||
|
||||
static nsresult
|
||||
@ -189,6 +195,16 @@ static SETTING gDDESettings[] = {
|
||||
{ MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
|
||||
};
|
||||
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
|
||||
#define ONLY_SERVICE_LAUNCHING
|
||||
#include "updatehelper.h"
|
||||
#include "updatehelper.cpp"
|
||||
|
||||
static const char kPrefetchClearedPref[] = "app.update.service.prefetchCleared";
|
||||
static nsCOMPtr<nsIThread> sThread;
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
GetHelperPath(nsAutoString& aPath)
|
||||
{
|
||||
@ -908,6 +924,123 @@ nsWindowsShellService::SetDesktopBackgroundColor(PRUint32 aColor)
|
||||
return regKey->Close();
|
||||
}
|
||||
|
||||
nsWindowsShellService::nsWindowsShellService() :
|
||||
mCheckedThisSession(false)
|
||||
{
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
|
||||
// Check to make sure the service is installed
|
||||
PRUint32 installed = 0;
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey ||
|
||||
NS_FAILED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
||||
NS_LITERAL_STRING(
|
||||
"SOFTWARE\\Mozilla\\MaintenanceService"),
|
||||
nsIWindowsRegKey::ACCESS_READ |
|
||||
nsIWindowsRegKey::WOW64_64)) ||
|
||||
NS_FAILED(regKey->ReadIntValue(NS_LITERAL_STRING("Installed"),
|
||||
&installed)) ||
|
||||
!installed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check to see if we have attempted to do the one time operation of clearing
|
||||
// the prefetch.
|
||||
bool prefetchCleared;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (!prefs ||
|
||||
NS_FAILED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch))) ||
|
||||
(NS_SUCCEEDED(prefBranch->GetBoolPref(kPrefetchClearedPref,
|
||||
&prefetchCleared)) &&
|
||||
prefetchCleared)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In a minute after startup is definitely complete, launch the
|
||||
// service command.
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (mTimer) {
|
||||
mTimer->InitWithFuncCallback(
|
||||
nsWindowsShellService::LaunchPrefetchClearCommand,
|
||||
nsnull, CLEAR_PREFETCH_TIMEOUT_MS, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsWindowsShellService::~nsWindowsShellService()
|
||||
{
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
mTimer = nsnull;
|
||||
}
|
||||
if (sThread) {
|
||||
sThread->Shutdown();
|
||||
sThread = nsnull;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
|
||||
class ClearPrefetchEvent : public nsRunnable {
|
||||
public:
|
||||
ClearPrefetchEvent()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// Start the service command
|
||||
LPCWSTR updaterServiceArgv[2];
|
||||
updaterServiceArgv[0] = L"MozillaMaintenance";
|
||||
updaterServiceArgv[1] = L"clear-prefetch";
|
||||
// If this command fails, it is not critical as prefetch will be cleared
|
||||
// on the next software update.
|
||||
StartServiceCommand(NS_ARRAY_LENGTH(updaterServiceArgv),
|
||||
updaterServiceArgv);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* For faster startup we attempt to clear the prefetch if the maintenance
|
||||
* service is installed. Please see the definition of ClearPrefetch()
|
||||
* in toolkit/components/maintenanceservice/prefetch.cpp for more info.
|
||||
* For now the only application that gets prefetch cleaned is Firefox
|
||||
* since we have not done performance checking for other applications.
|
||||
* This is done on every update but also there is a one time operation done
|
||||
* from within the program for first time installs.
|
||||
*/
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
void
|
||||
nsWindowsShellService::LaunchPrefetchClearCommand(nsITimer *aTimer, void*)
|
||||
{
|
||||
// Make sure we don't call this again from the application, it will be
|
||||
// called on each application update instead.
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
if (NS_SUCCEEDED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch)))) {
|
||||
prefBranch->SetBoolPref(kPrefetchClearedPref, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Starting the sevice can take a bit of time and we don't want to block the
|
||||
// main thread, so start an event on another thread to handle the operation
|
||||
NS_NewThread(getter_AddRefs(sThread));
|
||||
if (sThread) {
|
||||
nsCOMPtr<nsIRunnable> prefetchEvent = new ClearPrefetchEvent();
|
||||
sThread->Dispatch(prefetchEvent, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowsShellService::OpenApplicationWithURI(nsILocalFile* aApplication,
|
||||
const nsACString& aURI)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "nscore.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "nsIWindowsShellService.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <ole2.h>
|
||||
@ -16,8 +17,8 @@
|
||||
class nsWindowsShellService : public nsIWindowsShellService
|
||||
{
|
||||
public:
|
||||
nsWindowsShellService() : mCheckedThisSession(false) {};
|
||||
virtual ~nsWindowsShellService() {};
|
||||
nsWindowsShellService();
|
||||
virtual ~nsWindowsShellService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISHELLSERVICE
|
||||
@ -27,6 +28,10 @@ protected:
|
||||
bool IsDefaultBrowserVista(bool* aIsDefaultBrowser);
|
||||
|
||||
private:
|
||||
#if defined(MOZ_MAINTENANCE_SERVICE)
|
||||
static void LaunchPrefetchClearCommand(nsITimer *aTimer, void*);
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
#endif
|
||||
bool mCheckedThisSession;
|
||||
};
|
||||
|
||||
|
@ -587,6 +587,7 @@
|
||||
SetRegView 64
|
||||
${EndIf}
|
||||
DeleteRegKey HKLM "$R0"
|
||||
WriteRegStr HKLM "$R0" "prefetchProcessName" "FIREFOX"
|
||||
WriteRegStr HKLM "$R0\0" "name" "${CERTIFICATE_NAME}"
|
||||
WriteRegStr HKLM "$R0\0" "issuer" "${CERTIFICATE_ISSUER}"
|
||||
${If} ${RunningX64}
|
||||
|
@ -16,6 +16,7 @@ CPPSRCS = \
|
||||
certificatecheck.cpp \
|
||||
servicebase.cpp \
|
||||
registrycertificates.cpp \
|
||||
prefetch.cpp \
|
||||
$(NULL)
|
||||
|
||||
# For debugging purposes only
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "workmonitor.h"
|
||||
#include "uachelper.h"
|
||||
#include "updatehelper.h"
|
||||
#include "prefetch.h"
|
||||
|
||||
SERVICE_STATUS gSvcStatus = { 0 };
|
||||
SERVICE_STATUS_HANDLE gSvcStatusHandle = NULL;
|
||||
@ -26,6 +27,18 @@ bool gServiceControlStopping = false;
|
||||
|
||||
BOOL GetLogDirectoryPath(WCHAR *path);
|
||||
|
||||
/**
|
||||
* Wraps all commands that should be executed by the service on each install
|
||||
* and upgrade.
|
||||
*/
|
||||
void
|
||||
RunCommandsForEachInstallAndUpgrade()
|
||||
{
|
||||
LOG(("Running install/upgrade commands...\n"));
|
||||
ClearKnownPrefetch();
|
||||
LOG(("Finished install/upgrade commands\n"));
|
||||
}
|
||||
|
||||
int
|
||||
wmain(int argc, WCHAR **argv)
|
||||
{
|
||||
@ -52,7 +65,9 @@ wmain(int argc, WCHAR **argv)
|
||||
}
|
||||
LOG(("...\n"));
|
||||
|
||||
if (!SvcInstall(action)) {
|
||||
bool ret = SvcInstall(action);
|
||||
RunCommandsForEachInstallAndUpgrade();
|
||||
if (!ret) {
|
||||
LOG(("Could not install service (%d)\n", GetLastError()));
|
||||
LogFinish();
|
||||
return 1;
|
||||
@ -69,7 +84,10 @@ wmain(int argc, WCHAR **argv)
|
||||
LogInit(updatePath, L"maintenanceservice-install.log");
|
||||
}
|
||||
LOG(("Upgrading service if installed...\n"));
|
||||
if (!SvcInstall(UpgradeSvc)) {
|
||||
|
||||
bool ret = SvcInstall(UpgradeSvc);
|
||||
RunCommandsForEachInstallAndUpgrade();
|
||||
if (!ret) {
|
||||
LOG(("Could not upgrade service (%d)\n", GetLastError()));
|
||||
LogFinish();
|
||||
return 1;
|
||||
|
255
toolkit/components/maintenanceservice/prefetch.cpp
Normal file
255
toolkit/components/maintenanceservice/prefetch.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Maintenance service prefetch cleaning.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include "servicebase.h"
|
||||
#include "updatehelper.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#define MAX_KEY_LENGTH 255
|
||||
|
||||
/**
|
||||
* We found that prefetch actually causes large applications like Firefox
|
||||
* to startup slower. This will get rid of the Windows prefetch files for
|
||||
* applications like firefox (FIREFOX-*.pf files) and instead replace them
|
||||
* with 0 byte files which are read only. Windows will not use prefetch
|
||||
* if the associated prefetch file is a 0 byte read only file.
|
||||
* Some of the problems with prefetch relating to Windows and Firefox:
|
||||
* - Prefetch reads in a lot before we even run (fonts, plugins, etc...)
|
||||
* - Prefetch happens before our code runs, so it delays UI showing.
|
||||
* - Prefetch does not use windows readahead.
|
||||
* Previous test data on an acer i7 laptop with a 5400rpm HD showed startup
|
||||
* time difference was 1.6s (without prefetch) vs 2.6s+ with prefetch.
|
||||
* The "Windows Internals" book mentions that prefetch can be disabled for
|
||||
* the whole system only, so there is no other application specific way to
|
||||
* disable it.
|
||||
*
|
||||
* @param prefetchProcessName The name of the process who's prefetch files
|
||||
* should be cleared.
|
||||
* @return TRUE if no errors occurred during the clear operation.
|
||||
*/
|
||||
BOOL
|
||||
ClearPrefetch(LPCWSTR prefetchProcessName)
|
||||
{
|
||||
LOG(("Clearing prefetch files...\n"));
|
||||
size_t prefetchProcessNameLength = wcslen(prefetchProcessName);
|
||||
|
||||
// Make sure we were passed in a safe value for the prefetch process name
|
||||
// because it will be appended to a filepath and deleted.
|
||||
// We check for < 2 to avoid things like "." as the path
|
||||
// We check for a max path of MAX_PATH - 10 because we add \\ and '.EXE-*.pf'
|
||||
if (wcsstr(prefetchProcessName, L"..") ||
|
||||
wcsstr(prefetchProcessName, L"\\") ||
|
||||
wcsstr(prefetchProcessName, L"*") ||
|
||||
wcsstr(prefetchProcessName, L"/") ||
|
||||
prefetchProcessNameLength < 2 ||
|
||||
prefetchProcessNameLength >= (MAX_PATH - 10)) {
|
||||
LOG(("Prefetch path to clear is not safe\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Quick shortcut to make sure we don't try to clear multiple times for
|
||||
// different FIREFOX installs.
|
||||
static WCHAR lastPrefetchProcessName[MAX_PATH - 10] = { '\0' };
|
||||
if (!wcscmp(lastPrefetchProcessName, prefetchProcessName)) {
|
||||
LOG(("Already processed process name\n"));
|
||||
return FALSE;
|
||||
}
|
||||
wcscpy(lastPrefetchProcessName, prefetchProcessName);
|
||||
|
||||
// Obtain the windows prefetch directory path.
|
||||
WCHAR prefetchPath[MAX_PATH + 1];
|
||||
if (!GetWindowsDirectoryW(prefetchPath,
|
||||
sizeof(prefetchPath) /
|
||||
sizeof(prefetchPath[0]))) {
|
||||
LOG(("Could not obtain windows directory\n"));
|
||||
return FALSE;
|
||||
}
|
||||
if (!PathAppendSafe(prefetchPath, L"prefetch")) {
|
||||
LOG(("Could not obtain prefetch directory\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t prefetchDirLen = wcslen(prefetchPath);
|
||||
WCHAR prefetchSearchFile[MAX_PATH + 1];
|
||||
// We know this is safe based on the check at the start of this function
|
||||
wsprintf(prefetchSearchFile, L"\\%s.EXE-*.pf", prefetchProcessName);
|
||||
// Append the search file to the full path
|
||||
wcscpy(prefetchPath + prefetchDirLen, prefetchSearchFile);
|
||||
|
||||
// Find the first path matching and get a find handle for future calls.
|
||||
WIN32_FIND_DATAW findFileData;
|
||||
HANDLE findHandle = FindFirstFileW(prefetchPath, &findFileData);
|
||||
if (INVALID_HANDLE_VALUE == findHandle) {
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
LOG(("No files matching firefox.exe prefetch path.\n"));
|
||||
return TRUE;
|
||||
} else {
|
||||
LOG(("Error finding firefox.exe prefetch files. (%d)\n",
|
||||
GetLastError()));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL deletedAllFFPrefetch = TRUE;
|
||||
do {
|
||||
// Reset back to the prefetch directory, we know from an above check that
|
||||
// we aren't exceeding MAX_PATH + 1 characters with prefetchDirLen + 1.
|
||||
// From above we know: prefetchPath[prefetchDirLen] == L'\\';
|
||||
prefetchPath[prefetchDirLen + 1] = L'\0';
|
||||
|
||||
// Get the new file's prefetch path
|
||||
LPWSTR filenameOffsetInBuffer = prefetchPath + prefetchDirLen + 1;
|
||||
if (wcslen(findFileData.cFileName) + prefetchDirLen + 1 > MAX_PATH) {
|
||||
LOG(("Error appending prefetch path %ls, path is too long. (%d)\n",
|
||||
findFileData.cFileName, GetLastError()));
|
||||
deletedAllFFPrefetch = FALSE;
|
||||
continue;
|
||||
}
|
||||
if (!PathAppendSafe(filenameOffsetInBuffer, findFileData.cFileName)) {
|
||||
LOG(("Error appending prefetch path %ls. (%d)\n", findFileData.cFileName,
|
||||
GetLastError()));
|
||||
deletedAllFFPrefetch = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete the prefetch file and replace it with a blank read only file
|
||||
HANDLE prefetchFile =
|
||||
CreateFile(prefetchPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (INVALID_HANDLE_VALUE == prefetchFile) {
|
||||
LOG(("Error replacing prefetch path %ls. (%d)\n", findFileData.cFileName,
|
||||
GetLastError()));
|
||||
deletedAllFFPrefetch = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
CloseHandle(prefetchFile);
|
||||
|
||||
DWORD attributes = GetFileAttributes(prefetchPath);
|
||||
if (INVALID_FILE_ATTRIBUTES == attributes) {
|
||||
LOG(("Could not get/set attributes on prefetch file: %ls. (%d)\n",
|
||||
findFileData.cFileName, GetLastError()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SetFileAttributes(prefetchPath,
|
||||
attributes | FILE_ATTRIBUTE_READONLY)) {
|
||||
LOG(("Could not set read only on prefetch file: %ls. (%d)\n",
|
||||
findFileData.cFileName, GetLastError()));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(("Prefetch file cleared and set to read-only successfully: %ls\n",
|
||||
prefetchPath));
|
||||
} while (FindNextFileW(findHandle, &findFileData));
|
||||
LOG(("Done searching prefetch paths. (%d)\n", GetLastError()));
|
||||
|
||||
// Cleanup after ourselves.
|
||||
FindClose(findHandle);
|
||||
return deletedAllFFPrefetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all prefetch files specified in the installation dirctories
|
||||
* @return FALSE if there was an error clearing the known prefetch directories
|
||||
*/
|
||||
BOOL
|
||||
ClearKnownPrefetch()
|
||||
{
|
||||
// The service always uses the 64-bit registry key
|
||||
HKEY baseKeyRaw;
|
||||
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
BASE_SERVICE_REG_KEY, 0,
|
||||
KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
LOG(("Could not open maintenance service base key. (%d)\n", retCode));
|
||||
return FALSE;
|
||||
}
|
||||
nsAutoRegKey baseKey(baseKeyRaw);
|
||||
|
||||
// Get the number of subkeys.
|
||||
DWORD subkeyCount = 0;
|
||||
retCode = RegQueryInfoKeyW(baseKey, NULL, NULL, NULL, &subkeyCount, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
LOG(("Could not query info key: %d\n", retCode));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Enumerate the subkeys, each subkey represents an install
|
||||
for (DWORD i = 0; i < subkeyCount; i++) {
|
||||
WCHAR subkeyBuffer[MAX_KEY_LENGTH];
|
||||
DWORD subkeyBufferCount = MAX_KEY_LENGTH;
|
||||
retCode = RegEnumKeyExW(baseKey, i, subkeyBuffer,
|
||||
&subkeyBufferCount, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
LOG(("Could not enum installations: %d\n", retCode));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Open the subkey
|
||||
HKEY subKeyRaw;
|
||||
retCode = RegOpenKeyExW(baseKey,
|
||||
subkeyBuffer,
|
||||
0,
|
||||
KEY_READ | KEY_WOW64_64KEY,
|
||||
&subKeyRaw);
|
||||
nsAutoRegKey subKey(subKeyRaw);
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
LOG(("Could not open subkey: %d\n", retCode));
|
||||
continue; // Try the next subkey
|
||||
}
|
||||
|
||||
const int MAX_CHAR_COUNT = 256;
|
||||
DWORD valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
|
||||
WCHAR prefetchProcessName[MAX_CHAR_COUNT] = { L'\0' };
|
||||
|
||||
// Get the prefetch process name from the registry
|
||||
retCode = RegQueryValueExW(subKey, L"prefetchProcessName", 0, NULL,
|
||||
(LPBYTE)prefetchProcessName, &valueBufSize);
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
LOG(("Could not obtain process name from registry: %d\n", retCode));
|
||||
continue; // Try the next subkey
|
||||
}
|
||||
|
||||
// The value for prefetch process name comes from HKLM so is trusted.
|
||||
// We will do some sanity checks on it though inside ClearPrefetch.
|
||||
ClearPrefetch(prefetchProcessName);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
38
toolkit/components/maintenanceservice/prefetch.h
Normal file
38
toolkit/components/maintenanceservice/prefetch.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Maintenance service prefetch cleaning.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
BOOL ClearKnownPrefetch();
|
@ -10,6 +10,7 @@
|
||||
#include "pathhash.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "servicebase.h"
|
||||
#include "updatehelper.h"
|
||||
#define MAX_KEY_LENGTH 255
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "uachelper.h"
|
||||
#include "updatehelper.h"
|
||||
#include "errors.h"
|
||||
#include "prefetch.h"
|
||||
|
||||
// Wait 15 minutes for an update operation to run at most.
|
||||
// Updates usually take less than a minute so this seems like a
|
||||
@ -482,6 +483,8 @@ ExecuteServiceCommand(int argc, LPWSTR *argv)
|
||||
// because the service self updates itself and the service
|
||||
// installer will stop the service.
|
||||
LOG(("Service command %ls complete.\n", argv[2]));
|
||||
} else if (!lstrcmpi(argv[2], L"clear-prefetch")) {
|
||||
result = ClearKnownPrefetch();
|
||||
} else {
|
||||
LOG(("Service command not recognized: %ls.\n", argv[2]));
|
||||
// result is already set to FALSE
|
||||
|
@ -34,6 +34,7 @@ CPPSRCS += updatehelper.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = updatehelper.h \
|
||||
updatehelper.cpp \
|
||||
uachelper.h \
|
||||
pathhash.h \
|
||||
$(NULL)
|
||||
|
@ -16,13 +16,4 @@
|
||||
BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath,
|
||||
LPWSTR registryPath);
|
||||
|
||||
// The test only fallback key, as its name implies, is only present on machines
|
||||
// that will use automated tests. Since automated tests always run from a
|
||||
// different directory for each test, the presence of this key bypasses the
|
||||
// "This is a valid installation directory" check. This key also stores
|
||||
// the allowed name and issuer for cert checks so that the cert check
|
||||
// code can still be run unchanged.
|
||||
#define TEST_ONLY_FALLBACK_KEY_PATH \
|
||||
L"SOFTWARE\\Mozilla\\MaintenanceService\\3932ecacee736d366d6436db0f55bce4"
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Needed for CreateToolhelp32Snapshot
|
||||
#include <tlhelp32.h>
|
||||
#ifndef ONLY_SERVICE_LAUNCHING
|
||||
|
||||
#include <stdio.h>
|
||||
#include "shlobj.h"
|
||||
#include "updatehelper.h"
|
||||
@ -10,8 +15,6 @@
|
||||
|
||||
// Needed for PathAppendW
|
||||
#include <shlwapi.h>
|
||||
// Needed for CreateToolhelp32Snapshot
|
||||
#include <tlhelp32.h>
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
WCHAR* MakeCommandLine(int argc, WCHAR **argv);
|
||||
@ -236,6 +239,8 @@ StartServiceUpdate(int argc, LPWSTR *argv)
|
||||
return svcUpdateProcessStarted;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Executes a maintenance service command
|
||||
*
|
||||
@ -294,6 +299,8 @@ StartServiceCommand(int argc, LPCWSTR* argv)
|
||||
return lastError;
|
||||
}
|
||||
|
||||
#ifndef ONLY_SERVICE_LAUNCHING
|
||||
|
||||
/**
|
||||
* Launch a service initiated action for a software update with the
|
||||
* specified arguments.
|
||||
@ -403,6 +410,8 @@ WriteStatusFailure(LPCWSTR updateDirPath, int errorCode)
|
||||
return ok && wrote == toWrite;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Waits for a service to enter a stopped state.
|
||||
* This function does not stop the service, it just blocks until the service
|
||||
@ -535,6 +544,8 @@ WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds)
|
||||
return lastServiceState;
|
||||
}
|
||||
|
||||
#ifndef ONLY_SERVICE_LAUNCHING
|
||||
|
||||
/**
|
||||
* Determines if there is at least one process running for the specified
|
||||
* application. A match will be found across any session for any user.
|
||||
@ -620,6 +631,8 @@ DoesFallbackKeyExist()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Determines if the file system for the specified file handle is local
|
||||
* @param file path to check the filesystem type for, must be at most MAX_PATH
|
||||
|
@ -15,5 +15,18 @@ DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
|
||||
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
|
||||
BOOL DoesFallbackKeyExist();
|
||||
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal);
|
||||
DWORD StartServiceCommand(int argc, LPCWSTR* argv);
|
||||
|
||||
#define SVC_NAME L"MozillaMaintenance"
|
||||
|
||||
#define BASE_SERVICE_REG_KEY \
|
||||
L"SOFTWARE\\Mozilla\\MaintenanceService"
|
||||
|
||||
// The test only fallback key, as its name implies, is only present on machines
|
||||
// that will use automated tests. Since automated tests always run from a
|
||||
// different directory for each test, the presence of this key bypasses the
|
||||
// "This is a valid installation directory" check. This key also stores
|
||||
// the allowed name and issuer for cert checks so that the cert check
|
||||
// code can still be run unchanged.
|
||||
#define TEST_ONLY_FALLBACK_KEY_PATH \
|
||||
BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4"
|
||||
|
Loading…
x
Reference in New Issue
Block a user