mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1626887 Followup - Don't leave a task folder around when we fail to create a scheduled task. r=bytesized
This is needed to prevent a failed attempt to create the task from blocking out the ability to try again later if the two attempts are run under different user contexts, where the second is more limited than the first, because the less privileged attempt is unlikely to have permission to write to the folder created by the more privileged one. In particular the MSI installer runs into this scenario, because it makes one attempt to register the task as SYSTEM, followed by a second attempt as the unelevated interactive user. This is also nice because it keeps us from leaving an empty folder behind under any circumstances, not just this specific situation. Differential Revision: https://phabricator.services.mozilla.com/D77184
This commit is contained in:
parent
43b37c090e
commit
ff022d25ab
@ -12,6 +12,7 @@
|
||||
#include <taskschd.h>
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||
|
||||
@ -43,6 +44,12 @@ HRESULT RegisterTask(const wchar_t* uniqueToken,
|
||||
// Make sure we don't try to register a task that already exists.
|
||||
RemoveTask(uniqueToken);
|
||||
|
||||
// If we create a folder and then fail to create the task, we need to
|
||||
// remember to delete the folder so that whatever set of permissions it ends
|
||||
// up with doesn't interfere with trying to create the task again later, and
|
||||
// so that we don't just leave an empty folder behind.
|
||||
bool createdFolder = false;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
RefPtr<ITaskService> scheduler;
|
||||
ENSURE(CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER,
|
||||
@ -61,13 +68,24 @@ HRESULT RegisterTask(const wchar_t* uniqueToken,
|
||||
getter_AddRefs(taskFolder)))) {
|
||||
hr = rootFolder->CreateFolder(vendorBStr.get(), VARIANT{},
|
||||
getter_AddRefs(taskFolder));
|
||||
// The folder already existing isn't an error.
|
||||
if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) {
|
||||
if (SUCCEEDED(hr)) {
|
||||
createdFolder = true;
|
||||
} else if (hr != HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) {
|
||||
// The folder already existing isn't an error, but anything else is.
|
||||
LOG_ERROR(hr);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
auto cleanupFolder =
|
||||
mozilla::MakeScopeExit([hr, createdFolder, &rootFolder, &vendorBStr] {
|
||||
if (createdFolder && FAILED(hr)) {
|
||||
// If this fails, we can't really handle that intelligently, so
|
||||
// don't even bother to check the return code.
|
||||
rootFolder->DeleteFolder(vendorBStr.get(), 0);
|
||||
}
|
||||
});
|
||||
|
||||
RefPtr<ITaskDefinition> newTask;
|
||||
ENSURE(scheduler->NewTask(0, getter_AddRefs(newTask)));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user