Windows2003-3790/admin/pchealth/sr/srrpc/client/systemrestore.cpp
2020-09-30 16:53:55 +02:00

597 lines
21 KiB
C++

/******************************************************************
Copyright (c) 1999 Microsoft Corporation
SystemRestore.CPP -- WMI provider class implementation
Generated by Microsoft WMI Code Generation Engine
TO DO: - See individual function headers
- When linking, make sure you link to framedyd.lib &
msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).
Description:
******************************************************************/
#include <fwcommon.h> // This must be the first include.
#include "SystemRestore.h"
#include "srdefs.h"
#include "srrestoreptapi.h"
#include "srrpcapi.h"
#include "enumlogs.h"
#include "utils.h"
#include "srshell.h"
// TO DO: Replace "NameSpace" with the appropriate namespace for your
// provider instance. For instance: "root\\default or "root\\cimv2".
//===================================================================
CSystemRestore MySystemRestoreSet (PROVIDER_NAME_SYSTEMRESTORE, L"root\\default") ;
// Property names
//===============
const static WCHAR* pName = L"Description" ;
const static WCHAR* pNumber = L"SequenceNumber" ;
const static WCHAR* pType = L"RestorePointType" ;
const static WCHAR* pEventType = L"EventType" ;
const static WCHAR* pTime = L"CreationTime" ;
/*****************************************************************************
*
* FUNCTION : CSystemRestore::CSystemRestore
*
* DESCRIPTION : Constructor
*
* INPUTS : none
*
* RETURNS : nothing
*
* COMMENTS : Calls the Provider constructor.
*
*****************************************************************************/
CSystemRestore::CSystemRestore (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) :
Provider(lpwszName, lpwszNameSpace)
{
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::~CSystemRestore
*
* DESCRIPTION : Destructor
*
* INPUTS : none
*
* RETURNS : nothing
*
* COMMENTS :
*
*****************************************************************************/
CSystemRestore::~CSystemRestore ()
{
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::EnumerateInstances
*
* DESCRIPTION : Returns all the instances of this class.
*
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
* A long that contains the flags described in
* IWbemServices::CreateInstanceEnumAsync. Note that the following
* flags are handled by (and filtered out by) WinMgmt:
* WBEM_FLAG_DEEP
* WBEM_FLAG_SHALLOW
* WBEM_FLAG_RETURN_IMMEDIATELY
* WBEM_FLAG_FORWARD_ONLY
* WBEM_FLAG_BIDIRECTIONAL
*
* RETURNS : WBEM_S_NO_ERROR if successful
*
* COMMENTS : TO DO: All instances on the machine should be returned here and
* all properties that this class knows how to populate must
* be filled in. If there are no instances, return
* WBEM_S_NO_ERROR. It is not an error to have no instances.
* If you are implementing a 'method only' provider, you
* should remove this method.
*
*****************************************************************************/
HRESULT CSystemRestore::EnumerateInstances ( MethodContext* pMethodContext, long lFlags )
{
HRESULT hRes = WBEM_S_NO_ERROR;
// TO DO: The following commented lines contain the 'set' methods for the
// properties entered for this class. They are commented because they
// will NOT compile in their current form. Each <Property Value> should be
// replaced with the appropriate value. Also, consider creating a new
// method and moving these set statements and the ones from GetObject
// into that routine. See the framework sample (ReindeerProv.cpp) for
// an example of how this might be done.
//
// If the expectation is that there is more than one instance on the machine
// EnumerateInstances should loop through the instances and fill them accordingly.
//
// Note that you must ALWAYS set ALL the key properties. See the docs for
// further details.
///////////////////////////////////////////////////////////////////////////////
WCHAR szDrive[MAX_PATH]=L"";
GetSystemDrive(szDrive);
CRestorePointEnum RPEnum(szDrive, TRUE, FALSE);
CRestorePoint RP;
DWORD dwRc;
FILETIME *pft = NULL;
if (!IsAdminOrSystem())
{
return (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED));
}
dwRc = RPEnum.FindFirstRestorePoint(RP);
while (dwRc == ERROR_SUCCESS)
{
CInstance* pInstance = CreateNewInstance(pMethodContext);
if (! pInstance)
{
hRes = WBEM_E_OUT_OF_MEMORY;
break;
}
pInstance->SetCHString(pName, RP.GetName());
pInstance->SetDWORD(pNumber, RP.GetNum());
pInstance->SetDWORD(pType, RP.GetType());
pInstance->SetDWORD(pEventType, RP.GetEventType());
if (pft = RP.GetTime())
{
WBEMTime wbt(*pft);
BSTR bstrTime;
if (bstrTime = wbt.GetBSTR())
{
pInstance->SetCHString(pTime, bstrTime);
SysFreeString(bstrTime);
}
}
hRes = pInstance->Commit();
pInstance->Release();
dwRc = RPEnum.FindNextRestorePoint(RP);
}
RPEnum.FindClose();
return hRes ;
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::GetObject
*
* DESCRIPTION : Find a single instance based on the key properties for the
* class.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::GetObjectAsync.
*
* RETURNS : WBEM_S_NO_ERROR if the instance can be found
* WBEM_E_NOT_FOUND if the instance described by the key properties
* could not be found
* WBEM_E_FAILED if the instance could be found but another error
* occurred.
*
* COMMENTS : If you are implementing a 'method only' provider, you should
* remove this method.
*
*****************************************************************************/
HRESULT CSystemRestore::GetObject ( CInstance* pInstance, long lFlags )
{
// TO DO: The GetObject function is used to search for an instance of this
// class on the machine based on the key properties. Unlike
// EnumerateInstances which finds all instances on the machine, GetObject
// uses the key properties to find the matching single instance and
// returns that instance.
//
// Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against pInstance to see the key values
// the client requested.
HRESULT hr = WBEM_E_NOT_FOUND;
// if (<InstanceExists>)
// {
// TO DO: The following commented lines contain the 'set' methods for the
// properties entered for this class. They are commented because they
// will NOT compile in their current form. Each <Property Value> should be
// replaced with the appropriate value.
//
// pInstance->SetCHString(pName, <Property Value>);
// pInstance->SetVariant(pNumber, <Property Value>);
// pInstance->SetVariant(pType, <Property Value>);
//
// hr = WBEM_S_NO_ERROR;
// }
return hr ;
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::ExecQuery
*
* DESCRIPTION : You are passed a method context to use in the creation of
* instances that satisfy the query, and a CFrameworkQuery
* which describes the query. Create and populate all
* instances which satisfy the query. You may return more
* instances or more properties than are requested and WinMgmt
* will post filter out any that do not apply.
*
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
* A query object describing the query to satisfy.
* A long that contains the flags described in
* IWbemServices::CreateInstanceEnumAsync. Note that the following
* flags are handled by (and filtered out by) WinMgmt:
* WBEM_FLAG_FORWARD_ONLY
* WBEM_FLAG_BIDIRECTIONAL
* WBEM_FLAG_ENSURE_LOCATABLE
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for
* this class or if the query is too complex for this class
* to interpret. The framework will call the EnumerateInstances
* function instead and let Winmgmt post filter.
* WBEM_E_FAILED if the query failed
* WBEM_S_NO_ERROR if query was successful
*
* COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt
* will call your enumerate function to get all the instances and perform the
* filtering for you. Unless you expect SIGNIFICANT savings from implementing
* queries, you should remove this method. You should also remove this method
* if you are implementing a 'method only' provider.
*
*****************************************************************************/
HRESULT CSystemRestore::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
{
return (WBEM_E_PROVIDER_NOT_CAPABLE);
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::PutInstance
*
* DESCRIPTION : PutInstance should be used in provider classes that can
* write instance information back to the hardware or
* software. For example: Win32_Environment will allow a
* PutInstance to create or update an environment variable.
* However, a class like MotherboardDevice will not allow
* editing of the number of slots, since it is difficult for
* a provider to affect that number.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::PutInstanceAsync.
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
* WBEM_E_FAILED if there is an error delivering the instance
* WBEM_E_INVALID_PARAMETER if any of the instance properties
* are incorrect.
* WBEM_S_NO_ERROR if instance is properly delivered
*
* COMMENTS : TO DO: If you don't intend to support writing to your provider,
* or are creating a 'method only' provider, remove this
* method.
*
*****************************************************************************/
HRESULT CSystemRestore::PutInstance ( const CInstance &Instance, long lFlags)
{
// Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE);
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::DeleteInstance
*
* DESCRIPTION : DeleteInstance, like PutInstance, actually writes information
* to the software or hardware. For most hardware devices,
* DeleteInstance should not be implemented, but for software
* configuration, DeleteInstance implementation is plausible.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::DeleteInstanceAsync.
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
* WBEM_E_FAILED if there is an error deleting the instance.
* WBEM_E_INVALID_PARAMETER if any of the instance properties
* are incorrect.
* WBEM_S_NO_ERROR if instance is properly deleted.
*
* COMMENTS : TO DO: If you don't intend to support deleting instances or are
* creating a 'method only' provider, remove this method.
*
*****************************************************************************/
HRESULT CSystemRestore::DeleteInstance ( const CInstance &Instance, long lFlags )
{
// Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE);
}
/*****************************************************************************
*
* FUNCTION : CSystemRestore::ExecMethod
*
* DESCRIPTION : Override this function to provide support for methods.
* A method is an entry point for the user of your provider
* to request your class perform some function above and
* beyond a change of state. (A change of state should be
* handled by PutInstance() )
*
* INPUTS : A pointer to a CInstance containing the instance the method was executed against.
* A string containing the method name
* A pointer to the CInstance which contains the IN parameters.
* A pointer to the CInstance to contain the OUT parameters.
* A set of specialized method flags
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
* WBEM_S_NO_ERROR if method executes successfully
* WBEM_E_FAILED if error occurs executing method
*
* COMMENTS : TO DO: If you don't intend to support Methods, remove this method.
*
*****************************************************************************/
HRESULT CSystemRestore::ExecMethod ( const CInstance& Instance,
const BSTR bstrMethodName,
CInstance *pInParams,
CInstance *pOutParams,
long lFlags)
{
// For non-static methods, use the CInstance Get functions (for example,
// call GetCHString(L"Name", sTemp)) against Instance to see the key
// values the client requested.
HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
if (lstrcmpi(bstrMethodName, L"CreateRestorePoint") == 0)
{
hresult = CreateRestorePoint(pInParams, pOutParams);
}
else if (lstrcmpi(bstrMethodName, L"Enable") == 0)
{
hresult = Enable(pInParams, pOutParams);
}
else if (lstrcmpi(bstrMethodName, L"Disable") == 0)
{
hresult = Disable(pInParams, pOutParams);
}
else if (lstrcmpi(bstrMethodName, L"Restore") == 0)
{
hresult = Restore(pInParams, pOutParams);
}
else if (lstrcmpi(bstrMethodName, L"GetLastRestoreStatus") == 0)
{
hresult = GetLastRestoreStatus(pInParams, pOutParams);
}
return hresult;
}
HRESULT CSystemRestore::CreateRestorePoint(
CInstance *pInParams,
CInstance *pOutParams)
{
LPWSTR pwszName = NULL;
HRESULT hr = WBEM_S_NO_ERROR;
RESTOREPOINTINFOW rpi;
STATEMGRSTATUS ss;
ss.nStatus = ERROR_INVALID_PARAMETER;
pInParams->GetWCHAR(L"Description", &pwszName);
if (pwszName)
{
pInParams->GetDWORD(L"RestorePointType", rpi.dwRestorePtType);
pInParams->GetDWORD(L"EventType", rpi.dwEventType);
lstrcpy(rpi.szDescription, pwszName);
// cannot create a RESTORE type restore point from WMI
if (rpi.dwRestorePtType == RESTORE)
{
goto done;
}
::SRSetRestorePoint(&rpi, &ss);
free(pwszName);
}
done:
pOutParams->SetDWORD(L"ReturnValue", ss.nStatus);
return hr;
}
HRESULT CSystemRestore::Enable(
CInstance *pInParams,
CInstance *pOutParams)
{
LPWSTR pwszDrive = NULL;
HRESULT hr = WBEM_E_INVALID_PARAMETER;
bool fWait = 0;
DWORD dwRc;
pInParams->GetWCHAR(L"Drive", &pwszDrive);
pInParams->Getbool(L"WaitTillEnabled", fWait);
if (pwszDrive)
{
if (0 == lstrcmpi(pwszDrive, L""))
dwRc = ::EnableSREx(NULL, (BOOL) fWait);
else
dwRc = ::EnableSREx(pwszDrive, (BOOL) fWait);
pOutParams->SetDWORD(L"ReturnValue", dwRc);
if (pwszDrive) free(pwszDrive);
hr = WBEM_S_NO_ERROR;
}
return hr;
}
HRESULT CSystemRestore::Disable(
CInstance *pInParams,
CInstance *pOutParams)
{
LPWSTR pwszDrive = NULL;
HRESULT hr = WBEM_E_INVALID_PARAMETER;
DWORD dwRc;
pInParams->GetWCHAR(L"Drive", &pwszDrive);
if (pwszDrive)
{
if (0 == lstrcmpi(pwszDrive, L""))
dwRc = ::DisableSR(NULL);
else
dwRc = ::DisableSR(pwszDrive);
pOutParams->SetDWORD(L"ReturnValue", dwRc);
if (pwszDrive) free(pwszDrive);
hr = WBEM_S_NO_ERROR;
}
return hr;
}
HRESULT CSystemRestore::Restore(
CInstance *pInParams,
CInstance *pOutParams)
{
HRESULT hr = WBEM_E_INVALID_PARAMETER;
DWORD dwRp = 0, dwRpNew;
IRestoreContext *pCtx = NULL;
DWORD dwErr = ERROR_INTERNAL_ERROR;
HMODULE hModule = NULL;
CRestorePoint rp;
WCHAR szRp[MAX_RP_PATH];
pInParams->GetDWORD(L"SequenceNumber", dwRp);
if (dwRp == 0)
goto Err;
hr = WBEM_S_NO_ERROR;
// validate the restore point first
wsprintf( szRp, L"%s%ld", s_cszRPDir, dwRp );
rp.SetDir(szRp);
dwErr = rp.ReadLog();
if (dwErr != ERROR_SUCCESS) // it doesn't exist
{
goto Err;
}
if (rp.GetType() == CANCELLED_OPERATION) // cannot restore to it
{
dwErr = ERROR_INVALID_PARAMETER;
goto Err;
}
hModule = ::LoadLibraryW (L"srrstr.dll");
if (hModule != NULL)
{
INITFUNC pInit = NULL;
PREPFUNC pPrep = (PREPFUNC) GetProcAddress (hModule, "PrepareRestore");
if (pPrep != NULL)
{
if (FALSE == (*pPrep) ((int) dwRp, &pCtx))
{
goto Err;
}
}
else
{
dwErr = GetLastError();
goto Err;
}
//
// make this a silent restore - no result page
//
pCtx->SetSilent();
pInit = (INITFUNC) GetProcAddress (hModule, "InitiateRestore");
if (pInit != NULL)
{
if (FALSE == (*pInit) (pCtx, &dwRpNew))
{
goto Err;
}
else
{
dwErr = ERROR_SUCCESS;
}
}
else
{
dwErr = GetLastError();
goto Err;
}
}
else dwErr = GetLastError();
Err:
pOutParams->SetDWORD(L"ReturnValue", dwErr);
if (hModule != NULL)
::FreeLibrary (hModule);
return hr;
}
HRESULT
CSystemRestore::GetLastRestoreStatus(
CInstance *pInParams,
CInstance *pOutParams)
{
HRESULT hr = WBEM_S_NO_ERROR;
DWORD dwStatus = 0;
HKEY hkey = NULL;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, s_cszSRRegKey, &hkey))
{
RegReadDWORD(hkey, s_cszRestoreStatus, &dwStatus);
RegCloseKey(hkey);
}
else
{
dwStatus = 0xFFFFFFFF;
}
pOutParams->SetDWORD(L"ReturnValue", dwStatus);
return hr;
}