windows-nt/Source/XPSP1/NT/admin/pchealth/sr/srrpc/client/srrpcc.cpp
2020-09-26 16:20:57 +08:00

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);
}