From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../taskscheduler/nsWinTaskScheduler.cpp | 334 +++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 toolkit/components/taskscheduler/nsWinTaskScheduler.cpp (limited to 'toolkit/components/taskscheduler/nsWinTaskScheduler.cpp') diff --git a/toolkit/components/taskscheduler/nsWinTaskScheduler.cpp b/toolkit/components/taskscheduler/nsWinTaskScheduler.cpp new file mode 100644 index 0000000000..1efae5c349 --- /dev/null +++ b/toolkit/components/taskscheduler/nsWinTaskScheduler.cpp @@ -0,0 +1,334 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "nsWinTaskScheduler.h" + +#include +#include +#include +#include +#include + +#include "nsString.h" + +#include "mozilla/RefPtr.h" +#include "mozilla/ResultVariant.h" + +using namespace mozilla; + +struct SysFreeStringDeleter { + void operator()(BSTR aPtr) { ::SysFreeString(aPtr); } +}; +using BStrPtr = mozilla::UniquePtr; + +static nsresult ToNotFoundOrFailure(HRESULT hr) { + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { + return NS_ERROR_FILE_NOT_FOUND; + } else { + return NS_ERROR_FAILURE; + } +} + +static nsresult ToAlreadyExistsOrFailure(HRESULT hr) { + if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) { + return NS_ERROR_FILE_ALREADY_EXISTS; + } else { + return NS_ERROR_FAILURE; + } +} + +[[nodiscard]] static Result, HRESULT> GetTaskFolder( + const char16_t* aFolderName) { + HRESULT hr; + RefPtr scheduler = nullptr; + + hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, + IID_ITaskService, getter_AddRefs(scheduler)); + if (FAILED(hr)) { + return Err(hr); + } + + // Connect to the local Task Scheduler. + hr = scheduler->Connect(VARIANT{}, VARIANT{}, VARIANT{}, VARIANT{}); + if (FAILED(hr)) { + return Err(hr); + } + + BStrPtr bstrFolderName = + BStrPtr(::SysAllocString(reinterpret_cast(aFolderName))); + + RefPtr folder = nullptr; + hr = scheduler->GetFolder(bstrFolderName.get(), getter_AddRefs(folder)); + if (FAILED(hr)) { + return Err(hr); + } + + return folder; +} + +[[nodiscard]] static Result, HRESULT> GetRegisteredTask( + const char16_t* aFolderName, const char16_t* aTaskName) { + auto folder = GetTaskFolder(aFolderName); + if (!folder.isOk()) { + return Err(folder.unwrapErr()); + } + + BStrPtr bstrTaskName = + BStrPtr(::SysAllocString(reinterpret_cast(aTaskName))); + + RefPtr task = nullptr; + HRESULT hr = + folder.unwrap()->GetTask(bstrTaskName.get(), getter_AddRefs(task)); + if (FAILED(hr)) { + return Err(hr); + } + + return task; +} + +NS_IMPL_ISUPPORTS(nsWinTaskSchedulerService, nsIWinTaskSchedulerService) + +NS_IMETHODIMP +nsWinTaskSchedulerService::GetTaskXML(const char16_t* aFolderName, + const char16_t* aTaskName, + nsAString& aResult) { + if (!aFolderName || !aTaskName) { + return NS_ERROR_NULL_POINTER; + } + + auto task = GetRegisteredTask(aFolderName, aTaskName); + if (!task.isOk()) { + return ToNotFoundOrFailure(task.unwrapErr()); + } + + { + BSTR bstrXml = nullptr; + if (FAILED(task.unwrap()->get_Xml(&bstrXml))) { + return NS_ERROR_FAILURE; + } + + aResult.Assign(bstrXml, ::SysStringLen(bstrXml)); + ::SysFreeString(bstrXml); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::GetCurrentUserSid(nsAString& aUserSid) { +#ifndef XP_WIN + return NS_ERROR_NOT_IMPLEMENTED; +#else // !XP_WIN + DWORD tokenLen; + LPWSTR stringSid; + BYTE tokenBuf[TOKEN_USER_MAX_SIZE]; + PTOKEN_USER tokenInfo = reinterpret_cast(tokenBuf); + BOOL success = GetTokenInformation(GetCurrentProcessToken(), TokenUser, + tokenInfo, sizeof(tokenBuf), &tokenLen); + if (!success) { + return NS_ERROR_FAILURE; + } + success = ConvertSidToStringSidW(tokenInfo->User.Sid, &stringSid); + if (!success) { + return NS_ERROR_ABORT; + } + aUserSid.Assign(stringSid); + LocalFree(stringSid); + return NS_OK; +#endif +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::RegisterTask(const char16_t* aFolderName, + const char16_t* aTaskName, + const char16_t* aDefinitionXML, + bool aUpdateExisting) { + if (!aFolderName || !aTaskName || !aDefinitionXML) { + return NS_ERROR_NULL_POINTER; + } + + auto folder = GetTaskFolder(aFolderName); + if (!folder.isOk()) { + return ToNotFoundOrFailure(folder.unwrapErr()); + } + + BStrPtr bstrTaskName = + BStrPtr(::SysAllocString(reinterpret_cast(aTaskName))); + BStrPtr bstrXml = BStrPtr( + ::SysAllocString(reinterpret_cast(aDefinitionXML))); + LONG flags = aUpdateExisting ? TASK_CREATE_OR_UPDATE : TASK_CREATE; + TASK_LOGON_TYPE logonType = TASK_LOGON_INTERACTIVE_TOKEN; + + // The outparam is not needed, but not documented as optional. + RefPtr unusedTaskOutput = nullptr; + HRESULT hr = folder.unwrap()->RegisterTask( + bstrTaskName.get(), bstrXml.get(), flags, VARIANT{} /* userId */, + VARIANT{} /* password */, logonType, VARIANT{} /* sddl */, + getter_AddRefs(unusedTaskOutput)); + + if (FAILED(hr)) { + return ToAlreadyExistsOrFailure(hr); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::ValidateTaskDefinition( + const char16_t* aDefinitionXML, int32_t* aResult) { + if (!aDefinitionXML) { + return NS_ERROR_NULL_POINTER; + } + + auto folder = GetTaskFolder(reinterpret_cast(L"\\")); + if (!folder.isOk()) { + return NS_ERROR_FAILURE; + } + + BStrPtr bstrXml = BStrPtr( + ::SysAllocString(reinterpret_cast(aDefinitionXML))); + LONG flags = TASK_VALIDATE_ONLY; + TASK_LOGON_TYPE logonType = TASK_LOGON_INTERACTIVE_TOKEN; + + // The outparam is not needed, but not documented as optional. + RefPtr unusedTaskOutput = nullptr; + HRESULT hr = folder.unwrap()->RegisterTask( + nullptr /* path */, bstrXml.get(), flags, VARIANT{} /* userId */, + VARIANT{} /* password */, logonType, VARIANT{} /* sddl */, + getter_AddRefs(unusedTaskOutput)); + + if (aResult) { + *aResult = hr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::DeleteTask(const char16_t* aFolderName, + const char16_t* aTaskName) { + if (!aFolderName || !aTaskName) { + return NS_ERROR_NULL_POINTER; + } + + auto folder = GetTaskFolder(aFolderName); + if (!folder.isOk()) { + return ToNotFoundOrFailure(folder.unwrapErr()); + } + + BStrPtr bstrTaskName = + BStrPtr(::SysAllocString(reinterpret_cast(aTaskName))); + + HRESULT hr = folder.unwrap()->DeleteTask(bstrTaskName.get(), 0 /* flags */); + if (FAILED(hr)) { + return ToNotFoundOrFailure(hr); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::GetFolderTasks(const char16_t* aFolderName, + nsTArray& aResult) { + if (!aFolderName) { + return NS_ERROR_NULL_POINTER; + } + + auto folder = GetTaskFolder(aFolderName); + if (!folder.isOk()) { + return ToNotFoundOrFailure(folder.unwrapErr()); + } + + RefPtr taskCollection = nullptr; + if (FAILED(folder.unwrap()->GetTasks(TASK_ENUM_HIDDEN, + getter_AddRefs(taskCollection)))) { + return NS_ERROR_FAILURE; + } + + LONG taskCount = 0; + if (FAILED(taskCollection->get_Count(&taskCount))) { + return NS_ERROR_FAILURE; + } + + aResult.Clear(); + + for (LONG i = 0; i < taskCount; ++i) { + RefPtr task = nullptr; + + // nb: Collections are indexed from 1. + if (FAILED(taskCollection->get_Item(_variant_t(i + 1), + getter_AddRefs(task)))) { + return NS_ERROR_FAILURE; + } + + BStrPtr bstrTaskName; + { + BSTR tempTaskName = nullptr; + if (FAILED(task->get_Name(&tempTaskName))) { + return NS_ERROR_FAILURE; + } + bstrTaskName = BStrPtr(tempTaskName); + } + + aResult.AppendElement(nsString(bstrTaskName.get())); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::CreateFolder(const char16_t* aParentFolderName, + const char16_t* aSubFolderName) { + if (!aParentFolderName || !aSubFolderName) { + return NS_ERROR_NULL_POINTER; + } + + auto parentFolder = GetTaskFolder(aParentFolderName); + if (!parentFolder.isOk()) { + return ToNotFoundOrFailure(parentFolder.unwrapErr()); + } + + BStrPtr bstrSubFolderName = BStrPtr( + ::SysAllocString(reinterpret_cast(aSubFolderName))); + + HRESULT hr = parentFolder.unwrap()->CreateFolder(bstrSubFolderName.get(), + VARIANT{}, // sddl + nullptr); // ppFolder + + if (FAILED(hr)) { + return ToAlreadyExistsOrFailure(hr); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWinTaskSchedulerService::DeleteFolder(const char16_t* aParentFolderName, + const char16_t* aSubFolderName) { + if (!aParentFolderName || !aSubFolderName) { + return NS_ERROR_NULL_POINTER; + } + + auto parentFolder = GetTaskFolder(aParentFolderName); + if (!parentFolder.isOk()) { + return ToNotFoundOrFailure(parentFolder.unwrapErr()); + } + + BStrPtr bstrSubFolderName = BStrPtr( + ::SysAllocString(reinterpret_cast(aSubFolderName))); + + HRESULT hr = parentFolder.unwrap()->DeleteFolder(bstrSubFolderName.get(), + 0 /* flags */); + + if (FAILED(hr)) { + if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY)) { + return NS_ERROR_FILE_DIR_NOT_EMPTY; + } else { + return ToNotFoundOrFailure(hr); + } + } + + return NS_OK; +} -- cgit v1.2.3