1477 lines
32 KiB
C++
1477 lines
32 KiB
C++
/********************************************************************
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
srrpcc.cpp
|
|
|
|
Abstract:
|
|
implements functions exported in srclient.DLL
|
|
Exported API:
|
|
SRSetRestorePoint / SRRemoveRestorePoint
|
|
DisableSR / EnableSR
|
|
DisableFIFO / EnableFIFO
|
|
|
|
|
|
Revision History:
|
|
|
|
Brijesh Krishnaswami (brijeshk) - 04/10/00 - Created
|
|
|
|
********************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef THIS_FILE
|
|
#undef THIS_FILE
|
|
#endif
|
|
static char __szTraceSourceFile[] = __FILE__;
|
|
#define THIS_FILE __szTraceSourceFile
|
|
|
|
|
|
//
|
|
// function to check if SR configuration is disabled
|
|
// via group policy
|
|
//
|
|
|
|
DWORD
|
|
CheckPolicy()
|
|
{
|
|
DWORD dwPolicyEnabled = 0;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HKEY hKey = NULL;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
s_cszGroupPolicy,
|
|
0,
|
|
KEY_READ,
|
|
&hKey))
|
|
{
|
|
// if this value exists,
|
|
// then config policy is either enabled or disabled
|
|
// we need to disable access in both cases
|
|
|
|
if (ERROR_SUCCESS == RegReadDWORD(hKey, s_cszDisableConfig, &dwPolicyEnabled))
|
|
dwErr = ERROR_ACCESS_DENIED;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
// bind handle to endpoint
|
|
|
|
DWORD
|
|
SRRPCInit(
|
|
RPC_IF_HANDLE * pIfHandle,
|
|
BOOL fVerifyRights)
|
|
{
|
|
RPC_STATUS status;
|
|
LPWSTR pszStringBinding = NULL;
|
|
DWORD dwRc = ERROR_SUCCESS;
|
|
|
|
InitAsyncTrace();
|
|
|
|
TENTER("SRRPCInit");
|
|
|
|
//
|
|
// if admin rights are required
|
|
//
|
|
|
|
if (fVerifyRights && ! IsAdminOrSystem())
|
|
{
|
|
TRACE(0, "Caller does not have admin or localsystem rights");
|
|
dwRc = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// check if the service is stopping
|
|
// if it is, then we don't want to accept any more rpc calls
|
|
//
|
|
|
|
if (IsStopSignalled(NULL))
|
|
{
|
|
TRACE(0, "Service shut down - not accepting rpc call");
|
|
dwRc = ERROR_SERVICE_DISABLED;
|
|
goto exit;
|
|
}
|
|
|
|
// compose string to pass to binding api
|
|
|
|
dwRc = (DWORD) RpcStringBindingCompose(NULL,
|
|
s_cszRPCProtocol,
|
|
NULL,
|
|
s_cszRPCEndPoint,
|
|
NULL,
|
|
&pszStringBinding);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
TRACE(0, "RPCStringBindingCompose: error=%ld", dwRc);
|
|
goto exit;
|
|
}
|
|
|
|
// set the binding handle that will be used to bind to the server.
|
|
|
|
dwRc = (DWORD) RpcBindingFromStringBinding(pszStringBinding,
|
|
pIfHandle);
|
|
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
TRACE(0, "RPCBindingFromStringBinding: error=%ld", dwRc);
|
|
}
|
|
|
|
// free string
|
|
|
|
RpcStringFree(&pszStringBinding);
|
|
|
|
if (dwRc != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
RPC_SECURITY_QOS qos;
|
|
|
|
qos.Version = RPC_C_SECURITY_QOS_VERSION;
|
|
qos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; // Important!!!
|
|
qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
|
|
qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
|
|
|
|
dwRc = RpcBindingSetAuthInfoEx(*pIfHandle,
|
|
L"NT AUTHORITY\\SYSTEM",
|
|
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,
|
|
RPC_C_AUTHN_WINNT,
|
|
0,
|
|
0,
|
|
&qos);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
// free binding handle
|
|
|
|
DWORD
|
|
SRRPCTerm(
|
|
RPC_IF_HANDLE * pIfHandle)
|
|
{
|
|
RPC_STATUS status;
|
|
|
|
TENTER("SRRPCTerm");
|
|
|
|
// free binding handle
|
|
|
|
if (pIfHandle && *pIfHandle)
|
|
status = RpcBindingFree(pIfHandle);
|
|
|
|
TLEAVE();
|
|
|
|
TermAsyncTrace();
|
|
return (DWORD) status;
|
|
}
|
|
|
|
|
|
// API to disable System Restore
|
|
|
|
extern "C" DWORD WINAPI
|
|
DisableSR(LPCWSTR pszDrive)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("DisableSR");
|
|
|
|
//
|
|
// check if sr config is disabled via group policy
|
|
//
|
|
|
|
dwRc = CheckPolicy();
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = DisableSRS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "DisableSRS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// private function to start the SR service
|
|
// fWait - if TRUE : function is synchronous - waits till service is started completely
|
|
// if FALSE : function is asynchronous - does not wait for service to complete starting
|
|
|
|
DWORD
|
|
StartSRService(BOOL fWait)
|
|
{
|
|
DWORD dwRc = ERROR_SUCCESS;
|
|
SC_HANDLE hSCM = ::OpenSCManager(NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS);
|
|
SERVICE_STATUS Status;
|
|
|
|
if (hSCM)
|
|
{
|
|
SC_HANDLE hSR = OpenService(hSCM,
|
|
s_cszServiceName,
|
|
SERVICE_ALL_ACCESS);
|
|
if (hSR)
|
|
{
|
|
if (FALSE == StartService(hSR, 0, NULL))
|
|
{
|
|
dwRc = GetLastError();
|
|
if (dwRc == ERROR_SERVICE_ALREADY_RUNNING)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if (FALSE == QueryServiceStatus(hSR, &Status))
|
|
{
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
dwRc = Status.dwWin32ExitCode;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if (fWait)
|
|
{
|
|
//
|
|
// query the service until it starts or stops
|
|
// try thrice
|
|
//
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
Sleep(2000);
|
|
if (FALSE == QueryServiceStatus(hSR, &Status))
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if (Status.dwCurrentState == SERVICE_STOPPED)
|
|
{
|
|
dwRc = Status.dwWin32ExitCode;
|
|
if (dwRc == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// service masks DISABLED error code
|
|
// to avoid unnecessary event log messages
|
|
//
|
|
dwRc = ERROR_SERVICE_DISABLED;
|
|
}
|
|
goto done;
|
|
}
|
|
|
|
if (Status.dwCurrentState == SERVICE_RUNNING)
|
|
{
|
|
//
|
|
// wait on init event
|
|
//
|
|
|
|
HANDLE hInit = OpenEvent(SYNCHRONIZE, FALSE, s_cszSRInitEvent);
|
|
if (hInit)
|
|
{
|
|
dwRc = WaitForSingleObject(hInit, 120000); // wait for 2 minutes
|
|
CloseHandle(hInit);
|
|
if (dwRc == WAIT_OBJECT_0)
|
|
{
|
|
dwRc = ERROR_SUCCESS;
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
dwRc = ERROR_TIMEOUT;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CloseServiceHandle(hSR);
|
|
}
|
|
else
|
|
{
|
|
dwRc = GetLastError();
|
|
}
|
|
|
|
CloseServiceHandle(hSCM);
|
|
}
|
|
else
|
|
{
|
|
dwRc = GetLastError();
|
|
}
|
|
|
|
done:
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SetDisableFlag(DWORD dwValue)
|
|
{
|
|
HKEY hKeySR = NULL;
|
|
DWORD dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
s_cszSRRegKey,
|
|
0,
|
|
KEY_WRITE,
|
|
&hKeySR);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto done;
|
|
|
|
dwRc = RegWriteDWORD(hKeySR, s_cszDisableSR, &dwValue);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto done;
|
|
|
|
done:
|
|
if (hKeySR)
|
|
RegCloseKey(hKeySR);
|
|
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// API to enable System Restore
|
|
|
|
extern "C" DWORD WINAPI
|
|
EnableSR(LPCWSTR pszDrive)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("EnableSR");
|
|
|
|
//
|
|
// check if sr config is disabled via group policy
|
|
//
|
|
|
|
dwRc = CheckPolicy();
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// if whole of SR is enabled, then
|
|
// set the boot mode of service/filter to automatic
|
|
// and start the service
|
|
|
|
if (! pszDrive || IsSystemDrive((LPWSTR) pszDrive))
|
|
{
|
|
//
|
|
// if safe mode, then don't
|
|
//
|
|
|
|
if (0 != GetSystemMetrics(SM_CLEANBOOT))
|
|
{
|
|
TRACE(0, "This is safemode");
|
|
dwRc = ERROR_BAD_ENVIRONMENT;
|
|
goto exit;
|
|
}
|
|
|
|
dwRc = SetServiceStartup(s_cszServiceName, SERVICE_AUTO_START);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
dwRc = SetServiceStartup(s_cszFilterName, SERVICE_BOOT_START);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
// set the disable flag to false
|
|
// BUGBUG - this piece of code is duplicated in the service code as well
|
|
// reason is: we need the ability to disable/enable SR from within and outside
|
|
// the service
|
|
|
|
dwRc = SetDisableFlag(FALSE);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
dwRc = StartSRService(FALSE);
|
|
}
|
|
else
|
|
{
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = EnableSRS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "EnableSRS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
}
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
// API to enable System Restore - extended version
|
|
|
|
extern "C" DWORD WINAPI
|
|
EnableSREx(LPCWSTR pszDrive, BOOL fWait)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("EnableSREx");
|
|
|
|
//
|
|
// check if sr config is disabled via group policy
|
|
//
|
|
|
|
dwRc = CheckPolicy();
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// if whole of SR is enabled, then
|
|
// set the boot mode of service/filter to automatic
|
|
// and start the service
|
|
|
|
if (! pszDrive || IsSystemDrive((LPWSTR) pszDrive))
|
|
{
|
|
//
|
|
// if safe mode, then don't
|
|
//
|
|
|
|
if (0 != GetSystemMetrics(SM_CLEANBOOT))
|
|
{
|
|
TRACE(0, "This is safemode");
|
|
dwRc = ERROR_BAD_ENVIRONMENT;
|
|
goto exit;
|
|
}
|
|
|
|
dwRc = SetServiceStartup(s_cszServiceName, SERVICE_AUTO_START);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
dwRc = SetServiceStartup(s_cszFilterName, SERVICE_BOOT_START);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
// set the disable flag to false
|
|
// BUGBUG - this piece of code is duplicated in the service code as well
|
|
// reason is: we need the ability to disable/enable SR from within and outside
|
|
// the service
|
|
|
|
dwRc = SetDisableFlag(FALSE);
|
|
if (ERROR_SUCCESS != dwRc)
|
|
goto exit;
|
|
|
|
dwRc = StartSRService(fWait);
|
|
}
|
|
else
|
|
{
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = EnableSRS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "EnableSRS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
}
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// API to update the list of protected files - UNICODE version
|
|
// pass the fullpath name of the XML file containing the updated list of files
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRUpdateMonitoredListA(
|
|
LPCSTR pszXMLFile)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
LPWSTR pwszXMLFile = NULL;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRUpdateMonitoredListA");
|
|
|
|
pwszXMLFile = ConvertToUnicode((LPSTR) pszXMLFile);
|
|
if (! pwszXMLFile)
|
|
{
|
|
TRACE(0, "ConvertToUnicode");
|
|
goto exit;
|
|
}
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = SRUpdateMonitoredListS(srrpc_IfHandle, pwszXMLFile);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRUpdateMonitoredListS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
if (pwszXMLFile)
|
|
SRMemFree(pwszXMLFile);
|
|
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
// API to update the list of protected files - UNICODE version
|
|
// pass the fullpath name of the XML file containing the updated list of files
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRUpdateMonitoredListW(
|
|
LPCWSTR pwszXMLFile)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRUpdateMonitoredListW");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = SRUpdateMonitoredListS(srrpc_IfHandle, pwszXMLFile);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRUpdateMonitoredListS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// API to set a restore point - ANSI version
|
|
|
|
extern "C" BOOL
|
|
SRSetRestorePointA(
|
|
PRESTOREPOINTINFOA pRPInfoA,
|
|
PSTATEMGRSTATUS pSMgrStatus)
|
|
{
|
|
BOOL fRc = FALSE;
|
|
RESTOREPOINTINFOW RPInfoW;
|
|
LPWSTR pszDescW = NULL;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRSetRestorePointA");
|
|
|
|
// Initialize return values
|
|
|
|
if (! pSMgrStatus || ! pRPInfoA)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pSMgrStatus->llSequenceNumber = 0;
|
|
pSMgrStatus->nStatus = ERROR_INTERNAL_ERROR;
|
|
|
|
|
|
// convert struct to unicode
|
|
// since the string is the last member of the struct, we can memcpy
|
|
// all
|
|
memcpy(&RPInfoW, pRPInfoA, sizeof(RESTOREPOINTINFOA));
|
|
pszDescW = ConvertToUnicode(pRPInfoA->szDescription);
|
|
if (! pszDescW)
|
|
{
|
|
TRACE(0, "ConvertToUnicode");
|
|
goto exit;
|
|
}
|
|
lstrcpy(RPInfoW.szDescription, pszDescW);
|
|
|
|
|
|
// initialize
|
|
// don't need admin rights to call this api
|
|
|
|
pSMgrStatus->nStatus = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (pSMgrStatus->nStatus != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
fRc = SRSetRestorePointS(srrpc_IfHandle, &RPInfoW, pSMgrStatus);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
// set right error code if SR is disabled
|
|
|
|
DWORD dwRc = RpcExceptionCode();
|
|
if (RPC_S_SERVER_UNAVAILABLE == dwRc ||
|
|
RPC_S_UNKNOWN_IF == dwRc)
|
|
{
|
|
pSMgrStatus->nStatus = ERROR_SERVICE_DISABLED;
|
|
}
|
|
else
|
|
{
|
|
pSMgrStatus->nStatus = dwRc;
|
|
}
|
|
|
|
TRACE(0, "SRSetRestorePointS threw exception: nStatus=%ld", pSMgrStatus->nStatus);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
if (pszDescW)
|
|
SRMemFree(pszDescW);
|
|
|
|
TLEAVE();
|
|
return fRc;
|
|
}
|
|
|
|
|
|
|
|
// API to set a restore point - UNICODE version
|
|
|
|
extern "C" BOOL
|
|
SRSetRestorePointW(
|
|
PRESTOREPOINTINFOW pRPInfoW,
|
|
PSTATEMGRSTATUS pSMgrStatus)
|
|
{
|
|
BOOL fRc = FALSE;
|
|
DWORD dwRc = ERROR_SUCCESS;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRSetRestorePointW");
|
|
|
|
// Initialize return values
|
|
|
|
if (! pSMgrStatus || ! pRPInfoW)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pSMgrStatus->llSequenceNumber = 0;
|
|
pSMgrStatus->nStatus = ERROR_INTERNAL_ERROR;
|
|
|
|
// initialize
|
|
pSMgrStatus->nStatus = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (pSMgrStatus->nStatus != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
fRc = SRSetRestorePointS(srrpc_IfHandle, pRPInfoW, pSMgrStatus);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
// set right error code if SR is disabled
|
|
|
|
DWORD dwRc = RpcExceptionCode();
|
|
if (RPC_S_SERVER_UNAVAILABLE == dwRc ||
|
|
RPC_S_UNKNOWN_IF == dwRc)
|
|
{
|
|
pSMgrStatus->nStatus = ERROR_SERVICE_DISABLED;
|
|
}
|
|
else
|
|
{
|
|
pSMgrStatus->nStatus = dwRc;
|
|
}
|
|
|
|
TRACE(0, "SRSetRestorePointS threw exception: nStatus=%ld", pSMgrStatus->nStatus);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return fRc;
|
|
}
|
|
|
|
|
|
|
|
// API to remove a restore point
|
|
|
|
extern "C" DWORD
|
|
SRRemoveRestorePoint(
|
|
DWORD dwRPNum)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRRemoveRestorePoint");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = SRRemoveRestorePointS(srrpc_IfHandle, dwRPNum);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRRemoveRestorePointS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
// api to disable FIFO
|
|
|
|
extern "C" DWORD WINAPI
|
|
DisableFIFO(
|
|
DWORD dwRPNum)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("DisableFIFO");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = DisableFIFOS(srrpc_IfHandle, dwRPNum);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "DisableFIFOS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
// api to enable FIFO
|
|
|
|
extern "C" DWORD WINAPI
|
|
EnableFIFO()
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("EnableFIFO");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = EnableFIFOS(srrpc_IfHandle);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "EnableFIFOS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
|
|
// api to reset SR
|
|
|
|
extern "C" DWORD WINAPI
|
|
ResetSR(
|
|
LPCWSTR pszDrive)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("ResetSR");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = ResetSRS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "ResetSRS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// api to refresh the drive table from disk
|
|
// restore UI will call this - service will update its drivetable in memory
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRUpdateDSSize(LPCWSTR pszDrive, UINT64 ullSizeLimit)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRUpdateDSSize");
|
|
|
|
//
|
|
// check if sr config is disabled via group policy
|
|
//
|
|
dwRc = CheckPolicy();
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = SRUpdateDSSizeS(srrpc_IfHandle, pszDrive, ullSizeLimit);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRUpdateDSSizeS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRSwitchLog()
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRSwitchLog");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = SRSwitchLogS(srrpc_IfHandle);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRSwitchLogS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
extern "C" void WINAPI
|
|
SRNotify(LPCWSTR pszDrive, DWORD dwFreeSpaceInMB, BOOL fImproving)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRNotify");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
SRNotifyS(srrpc_IfHandle, pszDrive, dwFreeSpaceInMB, fImproving);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRNotifyS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return;
|
|
}
|
|
|
|
|
|
extern "C" void WINAPI
|
|
SRPrintState()
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("SRPrintState");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, FALSE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
SRPrintStateS(srrpc_IfHandle);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "SRPrintStateS threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return;
|
|
}
|
|
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRFifo(LPCWSTR pszDrive, DWORD dwTargetRp, int nPercent, BOOL fIncludeCurrentRp, BOOL fFifoAtleastOneRp)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("Fifo");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = FifoS(srrpc_IfHandle, pszDrive, dwTargetRp, nPercent, fIncludeCurrentRp, fFifoAtleastOneRp);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "Fifo threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRCompress(LPCWSTR pszDrive)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("Compress");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = CompressS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "Compress threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRFreeze(LPCWSTR pszDrive)
|
|
{
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
handle_t srrpc_IfHandle = NULL;
|
|
|
|
TENTER("Freeze");
|
|
|
|
// initialize
|
|
dwRc = SRRPCInit(&srrpc_IfHandle, TRUE);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// call remote procedure
|
|
RpcTryExcept
|
|
{
|
|
dwRc = FreezeS(srrpc_IfHandle, pszDrive);
|
|
}
|
|
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
|
|
{
|
|
dwRc = RpcExceptionCode();
|
|
TRACE(0, "Freeze threw exception: error=%ld", dwRc);
|
|
}
|
|
RpcEndExcept
|
|
|
|
// terminate
|
|
SRRPCTerm(&srrpc_IfHandle);
|
|
|
|
exit:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
// registration of callback method for third-parties to
|
|
// do their own snapshotting and restoration for their components
|
|
// clients will call this method with the full path of their dll.
|
|
// system restore will call "CreateSnapshot" and "RestoreSnapshot"
|
|
// methods in the registered dll when creating a restore point and
|
|
// when restoring respectively
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRRegisterSnapshotCallback(
|
|
LPCWSTR pszDllPath)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HKEY hKey = NULL;
|
|
LPWSTR pszDllName = NULL;
|
|
WCHAR szKey[MAX_PATH];
|
|
DWORD dwDisposition;
|
|
|
|
TENTER("RegisterSnapshotCallback");
|
|
|
|
//
|
|
// allow this only if admin or system
|
|
//
|
|
|
|
if (! IsAdminOrSystem())
|
|
{
|
|
dwErr = ERROR_ACCESS_DENIED;
|
|
trace(0, "Not admin or system");
|
|
goto Err;
|
|
}
|
|
|
|
if (pszDllPath == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
trace(0, "pszDllPath = NULL");
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// add the dll to Software\...\SystemRestore\SnapshotCallbacks
|
|
// each dll will be a value
|
|
// value name : name of dll, value: fullpath of dll
|
|
// this way, the registration is idempotent
|
|
//
|
|
|
|
//
|
|
// create/open the key
|
|
//
|
|
|
|
lstrcpy(szKey, s_cszSRRegKey);
|
|
lstrcat(szKey, L"\\");
|
|
lstrcat(szKey, s_cszCallbacksRegKey);
|
|
|
|
CHECKERR( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
szKey,
|
|
0,
|
|
NULL,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition),
|
|
L"RegCreateKeyEx" );
|
|
|
|
|
|
//
|
|
// get the dll name from the path
|
|
// if the path is not specified, this is same as input param
|
|
//
|
|
|
|
pszDllName = wcsrchr(pszDllPath, L'\\');
|
|
if (pszDllName == NULL)
|
|
{
|
|
pszDllName = (LPWSTR) pszDllPath;
|
|
}
|
|
else
|
|
{
|
|
pszDllName++; // skip the '\'
|
|
}
|
|
|
|
|
|
//
|
|
// if the value already exists
|
|
// bail
|
|
//
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hKey,
|
|
pszDllName,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
trace(0, "Dll is already registered");
|
|
dwErr = ERROR_ALREADY_EXISTS;
|
|
goto Err;
|
|
}
|
|
|
|
|
|
//
|
|
// add the value
|
|
//
|
|
|
|
CHECKERR(RegSetValueEx(hKey,
|
|
pszDllName,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *) pszDllPath,
|
|
(lstrlen(pszDllPath)+1)*sizeof(WCHAR)),
|
|
L"RegSetValueEx");
|
|
|
|
|
|
trace(0, "Added %S as snapshot callback", pszDllPath);
|
|
|
|
Err:
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
// corresponding unregistration function to above function
|
|
// clients can call this to unregister any snapshot callbacks
|
|
// they have already registered
|
|
|
|
extern "C" DWORD WINAPI
|
|
SRUnregisterSnapshotCallback(
|
|
LPCWSTR pszDllPath)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HKEY hKey = NULL;
|
|
LPWSTR pszDllName = NULL;
|
|
WCHAR szKey[MAX_PATH];
|
|
|
|
TENTER("SRUnregisterSnapshotCallback");
|
|
|
|
//
|
|
// allow this only if admin or system
|
|
//
|
|
|
|
if (! IsAdminOrSystem())
|
|
{
|
|
dwErr = ERROR_ACCESS_DENIED;
|
|
trace(0, "Not admin or system");
|
|
goto Err;
|
|
}
|
|
|
|
if (pszDllPath == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
trace(0, "pszDllPath = NULL");
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// add the dll to Software\...\SystemRestore\SnapshotCallbacks
|
|
// each dll will be a value
|
|
// value name : name of dll, value: fullpath of dll
|
|
// this way, the registration is idempotent
|
|
//
|
|
|
|
//
|
|
// open the key
|
|
//
|
|
|
|
lstrcpy(szKey, s_cszSRRegKey);
|
|
lstrcat(szKey, L"\\");
|
|
lstrcat(szKey, s_cszCallbacksRegKey);
|
|
|
|
CHECKERR( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
szKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey),
|
|
L"RegOpenKeyEx" );
|
|
|
|
|
|
//
|
|
// get the dll name from the path
|
|
// if the path is not specified, this is same as input param
|
|
//
|
|
|
|
pszDllName = wcsrchr(pszDllPath, L'\\');
|
|
if (pszDllName == NULL)
|
|
{
|
|
pszDllName = (LPWSTR) pszDllPath;
|
|
}
|
|
else
|
|
{
|
|
pszDllName++; // skip the '\'
|
|
}
|
|
|
|
//
|
|
// remove the value
|
|
//
|
|
|
|
CHECKERR(RegDeleteValue(hKey,
|
|
pszDllName),
|
|
L"RegDeleteValue");
|
|
|
|
trace(0, "Removed %S from snapshot callback", pszDllPath);
|
|
|
|
Err:
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// test functions for snapshot callbacks
|
|
//
|
|
|
|
extern "C" DWORD WINAPI
|
|
CreateSnapshot(LPCWSTR pszSnapshotDir)
|
|
{
|
|
TENTER("CreateSnapshot");
|
|
|
|
WCHAR szFile[MAX_PATH];
|
|
wsprintf(szFile, L"%s\\srclient.txt", pszSnapshotDir);
|
|
|
|
DebugTrace(0, "Callback createsnapshot");
|
|
if (FALSE == CopyFile(L"c:\\srclient.txt", szFile, FALSE))
|
|
{
|
|
trace(0, "! CopyFile");
|
|
}
|
|
|
|
TLEAVE();
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
extern "C" DWORD WINAPI
|
|
RestoreSnapshot(LPCWSTR pszSnapshotDir)
|
|
{
|
|
TENTER("RestoreSnapshot");
|
|
|
|
WCHAR szFile[MAX_PATH];
|
|
wsprintf(szFile, L"%s\\srclient.txt", pszSnapshotDir);
|
|
|
|
DebugTrace(0, "Callback restoresnapshot");
|
|
if (FALSE == CopyFile(szFile, L"c:\\restored.txt", FALSE))
|
|
{
|
|
trace(0, "! CopyFile");
|
|
}
|
|
|
|
TLEAVE();
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
// alloc/dealloc functions for midl compiler
|
|
|
|
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
|
|
{
|
|
return(SRMemAlloc((DWORD) len));
|
|
}
|
|
|
|
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
|
|
{
|
|
SRMemFree(ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|