252 lines
6.7 KiB
C
252 lines
6.7 KiB
C
/*
|
|
* Process Hacker Extra Plugins -
|
|
* Service Backup and Restore Plugin
|
|
*
|
|
* Copyright (C) 2015 dmex
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "main.h"
|
|
|
|
static PH_STRINGREF servicesKeyName = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Services\\");
|
|
static PH_STRINGREF fileExtName = PH_STRINGREF_INIT(L".phservicebackup");
|
|
|
|
static PH_FILETYPE_FILTER filters[] =
|
|
{
|
|
{ L"Service Backup File (*.phservicebackup)", L"*.phservicebackup" },
|
|
};
|
|
|
|
VOID PhBackupService(
|
|
_In_ HWND OwnerWindow,
|
|
_In_ PPH_SERVICE_ITEM ServiceItem
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
HANDLE keyHandle = NULL;
|
|
HANDLE fileHandle = NULL;
|
|
PVOID fileDialog = NULL;
|
|
PPH_STRING ofdFileName = NULL;
|
|
PPH_STRING backupFileName = NULL;
|
|
PPH_STRING serviceKeyName = NULL;
|
|
|
|
backupFileName = PhConcatStringRef2(&ServiceItem->Name->sr, &fileExtName);
|
|
serviceKeyName = PhConcatStringRef2(&servicesKeyName, &ServiceItem->Name->sr);
|
|
|
|
__try
|
|
{
|
|
if (!NT_SUCCESS(status = PhOpenKey(
|
|
&keyHandle,
|
|
KEY_ALL_ACCESS, // KEY_READ,
|
|
PH_KEY_LOCAL_MACHINE,
|
|
&serviceKeyName->sr,
|
|
0
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
fileDialog = PhCreateSaveFileDialog();
|
|
PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
|
|
PhSetFileDialogFileName(fileDialog, backupFileName->Buffer);
|
|
|
|
if (!PhShowFileDialog(OwnerWindow, fileDialog))
|
|
__leave;
|
|
|
|
ofdFileName = PhGetFileDialogFileName(fileDialog);
|
|
|
|
if (!NT_SUCCESS(status = PhCreateFileWin32(
|
|
&fileHandle,
|
|
ofdFileName->Buffer,
|
|
FILE_GENERIC_WRITE | DELETE,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status = NtSaveKeyEx(
|
|
keyHandle,
|
|
fileHandle,
|
|
PhGetIntegerSetting(SETTING_NAME_REG_FORMAT)
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
if (fileHandle)
|
|
{
|
|
NtClose(fileHandle);
|
|
}
|
|
|
|
if (keyHandle)
|
|
{
|
|
NtClose(keyHandle);
|
|
}
|
|
|
|
if (ofdFileName)
|
|
{
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
PhDeleteFileWin32(ofdFileName->Buffer);
|
|
}
|
|
|
|
PhDereferenceObject(ofdFileName);
|
|
}
|
|
|
|
if (fileDialog)
|
|
{
|
|
PhFreeFileDialog(fileDialog);
|
|
}
|
|
|
|
PhDereferenceObject(backupFileName);
|
|
PhDereferenceObject(serviceKeyName);
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
PhShowStatus(OwnerWindow, L"Unable to backup the service", status, 0);
|
|
}
|
|
}
|
|
|
|
VOID PhRestoreService(
|
|
_In_ HWND OwnerWindow,
|
|
_In_ PPH_SERVICE_ITEM ServiceItem
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
HANDLE keyHandle = NULL;
|
|
HANDLE fileHandle = NULL;
|
|
PVOID fileDialog = NULL;
|
|
PPH_STRING ofdFileName = NULL;
|
|
PPH_STRING backupFileName = NULL;
|
|
PPH_STRING serviceKeyName = NULL;
|
|
|
|
backupFileName = PhConcatStringRef2(&ServiceItem->Name->sr, &fileExtName);
|
|
serviceKeyName = PhConcatStringRef2(&servicesKeyName, &ServiceItem->Name->sr);
|
|
|
|
__try
|
|
{
|
|
if (!NT_SUCCESS(status = PhOpenKey(
|
|
&keyHandle,
|
|
KEY_ALL_ACCESS,// KEY_WRITE
|
|
PH_KEY_LOCAL_MACHINE,
|
|
&serviceKeyName->sr,
|
|
0
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
fileDialog = PhCreateOpenFileDialog();
|
|
PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
|
|
|
|
if (!PhShowFileDialog(OwnerWindow, fileDialog))
|
|
__leave;
|
|
|
|
ofdFileName = PhGetFileDialogFileName(fileDialog);
|
|
|
|
HKEY appKeyHandle;
|
|
|
|
if (RegLoadAppKey(
|
|
ofdFileName->Buffer,
|
|
&appKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
REG_PROCESS_APPKEY, // REG_APP_HIVE
|
|
0
|
|
) == ERROR_SUCCESS)
|
|
{
|
|
PPH_STRING displayName = PhQueryRegistryString(appKeyHandle, L"DisplayName");
|
|
PPH_STRING currentDisplayName = PhQueryRegistryString(keyHandle, L"DisplayName");
|
|
|
|
if (!PhEqualString(displayName, currentDisplayName, TRUE))
|
|
{
|
|
PhDereferenceObject(currentDisplayName);
|
|
PhDereferenceObject(displayName);
|
|
NtClose(appKeyHandle);
|
|
PhShowError(OwnerWindow, L"The display name does not match the backup of this service.");
|
|
__leave;
|
|
}
|
|
|
|
PhDereferenceObject(currentDisplayName);
|
|
PhDereferenceObject(displayName);
|
|
NtClose(appKeyHandle);
|
|
}
|
|
|
|
if (PhFindStringInString(ofdFileName, 0, ServiceItem->Name->Buffer) == -1)
|
|
{
|
|
PhShowError(OwnerWindow, L"The file name does not match the name of this service.");
|
|
__leave;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status = PhCreateFileWin32(
|
|
&fileHandle,
|
|
ofdFileName->Buffer,
|
|
FILE_GENERIC_READ,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status = NtRestoreKey(
|
|
keyHandle,
|
|
fileHandle,
|
|
0 // REG_FORCE_RESTORE
|
|
)))
|
|
{
|
|
__leave;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
if (fileHandle)
|
|
{
|
|
NtClose(fileHandle);
|
|
}
|
|
|
|
if (keyHandle)
|
|
{
|
|
NtClose(keyHandle);
|
|
}
|
|
|
|
if (ofdFileName)
|
|
{
|
|
PhDereferenceObject(ofdFileName);
|
|
}
|
|
|
|
if (fileDialog)
|
|
{
|
|
PhFreeFileDialog(fileDialog);
|
|
}
|
|
|
|
PhDereferenceObject(backupFileName);
|
|
PhDereferenceObject(serviceKeyName);
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
PhShowStatus(OwnerWindow, L"Unable to restore the service", status, 0);
|
|
}
|
|
} |