Usando a restauração do sistema
Os exemplos a seguir demonstram como criar e cancelar pontos de restauração usando a função SRSetRestorePoint.
A primeira etapa para usar a Restauração do Sistema é configurar as chamadas COM para CoInitializeEx e CoInitializeSecurity. Isso é necessário para qualquer processo que use a função SRSetRestorePoint. NetworkService, LocalService e System devem ter permissão para fazer chamadas ao processo. A função InitializeCOMSecurity a seguir é um exemplo de como inicializar a segurança COM. Talvez seja necessário modificar os parâmetros da função CoInitializeSecurity para seu aplicativo.
Observe que há uma frequência máxima de criação do ponto de restauração do sistema. 24 horas é a frequência padrão para 1 ponto de restauração.
#include <stdio.h>
#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <objbase.h>
#include <strsafe.h>
#include <srrestoreptapi.h>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "advapi32.lib")
typedef BOOL (WINAPI *PFN_SETRESTOREPTW) (PRESTOREPOINTINFOW, PSTATEMGRSTATUS);
BOOL InitializeCOMSecurity()
{
// Create the security descriptor explicitly as follows because
// CoInitializeSecurity() will not accept the relative security descriptors
// returned by ConvertStringSecurityDescriptorToSecurityDescriptor().
SECURITY_DESCRIPTOR securityDesc = {0};
EXPLICIT_ACCESS ea[5] = {0};
ACL *pAcl = NULL;
ULONGLONG rgSidBA[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
ULONGLONG rgSidLS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
ULONGLONG rgSidNS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
ULONGLONG rgSidPS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
ULONGLONG rgSidSY[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
DWORD cbSid = 0;
BOOL fRet = FALSE;
DWORD dwRet = ERROR_SUCCESS;
HRESULT hrRet = S_OK;
//
// This creates a security descriptor that is equivalent to the following
// security descriptor definition language (SDDL) string:
//
// O:BAG:BAD:(A;;0x1;;;LS)(A;;0x1;;;NS)(A;;0x1;;;PS)(A;;0x1;;;SY)(A;;0x1;;;BA)
//
// Initialize the security descriptor.
fRet = ::InitializeSecurityDescriptor( &securityDesc, SECURITY_DESCRIPTOR_REVISION );
if( !fRet )
{
goto exit;
}
// Create an administrator group security identifier (SID).
cbSid = sizeof( rgSidBA );
fRet = ::CreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, rgSidBA, &cbSid );
if( !fRet )
{
goto exit;
}
// Create a local service security identifier (SID).
cbSid = sizeof( rgSidLS );
fRet = ::CreateWellKnownSid( WinLocalServiceSid, NULL, rgSidLS, &cbSid );
if( !fRet )
{
goto exit;
}
// Create a network service security identifier (SID).
cbSid = sizeof( rgSidNS );
fRet = ::CreateWellKnownSid( WinNetworkServiceSid, NULL, rgSidNS, &cbSid );
if( !fRet )
{
goto exit;
}
// Create a personal account security identifier (SID).
cbSid = sizeof( rgSidPS );
fRet = ::CreateWellKnownSid( WinSelfSid, NULL, rgSidPS, &cbSid );
if( !fRet )
{
goto exit;
}
// Create a local service security identifier (SID).
cbSid = sizeof( rgSidSY );
fRet = ::CreateWellKnownSid( WinLocalSystemSid, NULL, rgSidSY, &cbSid );
if( !fRet )
{
goto exit;
}
// Setup the access control entries (ACE) for COM. You may need to modify
// the access permissions for your application. COM_RIGHTS_EXECUTE and
// COM_RIGHTS_EXECUTE_LOCAL are the minimum access rights required.
ea[0].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.pMultipleTrustee = NULL;
ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)rgSidBA;
ea[1].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.pMultipleTrustee = NULL;
ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR)rgSidLS;
ea[2].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
ea[2].grfAccessMode = SET_ACCESS;
ea[2].grfInheritance = NO_INHERITANCE;
ea[2].Trustee.pMultipleTrustee = NULL;
ea[2].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[2].Trustee.ptstrName = (LPTSTR)rgSidNS;
ea[3].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
ea[3].grfAccessMode = SET_ACCESS;
ea[3].grfInheritance = NO_INHERITANCE;
ea[3].Trustee.pMultipleTrustee = NULL;
ea[3].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[3].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[3].Trustee.ptstrName = (LPTSTR)rgSidPS;
ea[4].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
ea[4].grfAccessMode = SET_ACCESS;
ea[4].grfInheritance = NO_INHERITANCE;
ea[4].Trustee.pMultipleTrustee = NULL;
ea[4].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ea[4].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[4].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[4].Trustee.ptstrName = (LPTSTR)rgSidSY;
// Create an access control list (ACL) using this ACE list.
dwRet = ::SetEntriesInAcl( ARRAYSIZE( ea ), ea, NULL, &pAcl );
if( dwRet != ERROR_SUCCESS || pAcl == NULL )
{
fRet = FALSE;
goto exit;
}
// Set the security descriptor owner to Administrators.
fRet = ::SetSecurityDescriptorOwner( &securityDesc, rgSidBA, FALSE );
if( !fRet )
{
goto exit;
}
// Set the security descriptor group to Administrators.
fRet = ::SetSecurityDescriptorGroup( &securityDesc, rgSidBA, FALSE );
if( !fRet )
{
goto exit;
}
// Set the discretionary access control list (DACL) to the ACL.
fRet = ::SetSecurityDescriptorDacl( &securityDesc, TRUE, pAcl, FALSE );
if( !fRet )
{
goto exit;
}
// Initialize COM. You may need to modify the parameters of
// CoInitializeSecurity() for your application. Note that an
// explicit security descriptor is being passed down.
hrRet = ::CoInitializeSecurity( &securityDesc,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IDENTIFY,
NULL,
EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL,
NULL );
if( FAILED( hrRet ) )
{
fRet = FALSE;
goto exit;
}
fRet = TRUE;
exit:
::LocalFree( pAcl );
return fRet;
}
Exemplo 1: Criar um ponto de restauração
#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <objbase.h>
#include <strsafe.h>
#include <srrestoreptapi.h>
typedef BOOL (WINAPI *PFN_SETRESTOREPTW) (PRESTOREPOINTINFOW, PSTATEMGRSTATUS);
extern "C" int __cdecl wmain(int argc, WCHAR **argv)
{
RESTOREPOINTINFOW RestorePtInfo;
STATEMGRSTATUS SMgrStatus;
PFN_SETRESTOREPTW fnSRSetRestorePointW=NULL;
DWORD dwErr = ERROR_SUCCESS;
HMODULE hSrClient = NULL;
BOOL fRet = FALSE;
HRESULT hr = S_OK;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if( FAILED( hr ) )
{
wprintf( L"Unexpected error: CoInitializeEx() failed with 0x%08x\n", hr );
goto exit;
}
// Initialize COM security to enable NetworkService,
// LocalService and System to make callbacks to the process
// calling System Restore. This is required for any process
// that calls SRSetRestorePoint.
fRet = InitializeCOMSecurity();
if( !fRet )
{
wprintf( L"Unexpected error: failed to initialize COM security\n" );
goto exit;
}
// Initialize the RESTOREPOINTINFO structure
RestorePtInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
// Notify the system that changes are about to be made.
// An application is to be installed.
RestorePtInfo.dwRestorePtType = APPLICATION_INSTALL;
// RestPtInfo.llSequenceNumber must be 0 when creating a restore point.
RestorePtInfo.llSequenceNumber = 0;
// String to be displayed by System Restore for this restore point.
StringCbCopyW(RestorePtInfo.szDescription,
sizeof(RestorePtInfo.szDescription),
L"First Restore Point");
// Load the DLL, which may not exist on Windows server
hSrClient = LoadLibraryW(L"srclient.dll");
if(NULL == hSrClient)
{
wprintf(L"System Restore is not present.\n");
goto exit;
}
// If the library is loaded, find the entry point
fnSRSetRestorePointW = (PFN_SETRESTOREPTW) GetProcAddress(
hSrClient, "SRSetRestorePointW");
if (NULL == fnSRSetRestorePointW)
{
wprintf(L"Failed to find SRSetRestorePointW.\n");
goto exit;
}
fRet = fnSRSetRestorePointW(&RestorePtInfo, &SMgrStatus);
if(!fRet)
{
dwErr = SMgrStatus.nStatus;
if(dwErr == ERROR_SERVICE_DISABLED)
{
wprintf(L"System Restore is turned off.\n");
goto exit;
}
wprintf(L"Failure to create the restore point; error=%u.\n", dwErr);
goto exit;
}
wprintf(L"Restore point created; number=%I64d.\n", SMgrStatus.llSequenceNumber);
// The application performs some installation operations here.
// It is not necessary to call SrSetRestorePoint to indicate that the
// installation is complete except in the case of ending a nested
// restore point. Every BEGIN_NESTED_SYSTEM_CHANGE must have a
// corresponding END_NESTED_SYSTEM_CHANGE or the application cannot
// create new restore points.
// Update the RESTOREPOINTINFO structure to notify the
// system that the operation is finished.
RestorePtInfo.dwEventType = END_SYSTEM_CHANGE;
// End the system change by using the sequence number
// received from the first call to SRSetRestorePoint.
RestorePtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber;
// Notify the system that the operation is done and that this
// is the end of the restore point.
fRet = fnSRSetRestorePointW(&RestorePtInfo, &SMgrStatus);
if(!fRet)
{
dwErr = SMgrStatus.nStatus;
wprintf(L"Failure to end the restore point; error=%u.\n", dwErr);
goto exit;
}
exit:
if(hSrClient != NULL)
{
FreeLibrary(hSrClient);
hSrClient = NULL;
}
return 0;
}
Exemplo 2: Criar e cancelar um ponto de restauração
#include <stdio.h>
#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <objbase.h>
#include <strsafe.h>
#include <srrestoreptapi.h>
typedef BOOL (WINAPI *PFN_SETRESTOREPTW) (PRESTOREPOINTINFOW, PSTATEMGRSTATUS);
extern "C" int __cdecl wmain(int argc, WCHAR** argv)
{
RESTOREPOINTINFOW RestorePtInfo;
STATEMGRSTATUS SMgrStatus;
PFN_SETRESTOREPTW fnSRSetRestorePointW = NULL;
DWORD dwErr = ERROR_SUCCESS;
HMODULE hSrClient = NULL;
BOOL fRet = FALSE;
HRESULT hr = S_OK;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if( FAILED( hr ) )
{
wprintf( L"Unexpected error: CoInitializeEx() failed with 0x%08x\n", hr );
goto exit;
}
// Initialize COM security to enable NetworkService,
// LocalService and System to make callbacks to the process
// calling System Restore. This is required for any process
// that calls SRSetRestorePoint.
fRet = InitializeCOMSecurity();
if( !fRet )
{
wprintf( L"Unexpected error: failed to initialize COM security\n" );
goto exit;
}
// Initialize the RESTOREPOINTINFO structure.
RestorePtInfo.dwEventType=BEGIN_SYSTEM_CHANGE;
RestorePtInfo.dwRestorePtType=APPLICATION_INSTALL;
RestorePtInfo.llSequenceNumber=0;
StringCbCopyW(RestorePtInfo.szDescription,
sizeof(RestorePtInfo.szDescription),
L"Sample Restore Point");
// Load the DLL, which may not exist on Windows server
hSrClient = LoadLibraryW(L"srclient.dll");
if(NULL == hSrClient)
{
wprintf(L"System Restore is not present.\n");
goto exit;
}
// If the library is loaded, find the entry point
fnSRSetRestorePointW = (PFN_SETRESTOREPTW) GetProcAddress(
hSrClient, "SRSetRestorePointW");
if (NULL == fnSRSetRestorePointW)
{
wprintf(L"Failed to find SRSetRestorePointW.\n");
goto exit;
}
fRet = fnSRSetRestorePointW(&RestorePtInfo, &SMgrStatus);
if(!fRet)
{
dwErr = SMgrStatus.nStatus;
if(dwErr == ERROR_SERVICE_DISABLED)
{
wprintf(L"System Restore is turned off.\n");
goto exit;
}
wprintf(L"Failure to create the restore point; error=%u.\n", dwErr);
goto exit;
}
wprintf(L"Restore point set. Restore point data:\n");
wprintf(L"\tSequence Number=%I64d\n",SMgrStatus.llSequenceNumber);
wprintf(L"\tStatus=%u\n",SMgrStatus.nStatus);
// Update the structure to cancel the previous restore point.
RestorePtInfo.dwEventType=END_SYSTEM_CHANGE;
RestorePtInfo.dwRestorePtType=CANCELLED_OPERATION;
// This is the sequence number returned by the previous call.
RestorePtInfo.llSequenceNumber=SMgrStatus.llSequenceNumber;
// Cancel the previous restore point
fRet = fnSRSetRestorePointW(&RestorePtInfo, &SMgrStatus);
if(!fRet)
{
dwErr = SMgrStatus.nStatus;
wprintf(L"Failure to cancel the restore point; error=%u.\n", dwErr);
goto exit;
}
wprintf(L"Restore point canceled. Restore point data:\n");
wprintf(L"\tSequence Number=%I64d\n",SMgrStatus.llSequenceNumber);
wprintf(L"\tStatus=%u\n",SMgrStatus.nStatus);
exit:
if(hSrClient != NULL)
{
FreeLibrary(hSrClient);
hSrClient = NULL;
}
return 0;
}