389 lines
8.5 KiB
C++
389 lines
8.5 KiB
C++
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
checkpoint.cxx
|
|
|
|
Abstract:
|
|
|
|
This file implements a class (or for 'C' handle based) calls to set and
|
|
restore system breakpoints.
|
|
|
|
Author:
|
|
|
|
Mark Lawrence (mlawrenc).
|
|
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "spllibp.hxx"
|
|
#include "checkpoint.hxx"
|
|
|
|
TSystemRestorePoint::
|
|
TSystemRestorePoint(
|
|
VOID
|
|
) : m_hLibrary(NULL),
|
|
m_pfnSetRestorePoint(NULL),
|
|
m_bSystemRestoreSet(FALSE),
|
|
m_hr(E_FAIL)
|
|
{
|
|
memset(&m_RestorePointInfo, 0, sizeof(m_RestorePointInfo));
|
|
|
|
m_hr = Initialize();
|
|
}
|
|
|
|
TSystemRestorePoint::
|
|
~TSystemRestorePoint(
|
|
VOID
|
|
)
|
|
{
|
|
if (m_hLibrary)
|
|
{
|
|
FreeLibrary(m_hLibrary);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
TSystemRestorePoint::
|
|
IsValid(
|
|
VOID
|
|
) const
|
|
{
|
|
return m_hr;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
StartSystemRestorePoint
|
|
|
|
Routine Description:
|
|
|
|
This routine starts a system restore point in the AddPrinterDriver code.
|
|
|
|
Arguments:
|
|
|
|
pszServer - The server name on which we are setting the restore point.
|
|
pszDriverName - The driver name of which we are trying to install.
|
|
hInst - The hInstance of the resource library.
|
|
ResId - The resource id to use for the message string.
|
|
|
|
Return Value:
|
|
|
|
An HRESULT.
|
|
|
|
--*/
|
|
HRESULT
|
|
TSystemRestorePoint::
|
|
StartSystemRestorePoint(
|
|
IN PCWSTR pszServer,
|
|
IN PCWSTR pszDriverName,
|
|
IN HINSTANCE hInst,
|
|
IN UINT ResId
|
|
)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
STATEMGRSTATUS SMgrStatus;
|
|
WCHAR szDriverName[MAX_DESC];
|
|
WCHAR szMessage[MAX_DESC];
|
|
|
|
hRetval = pszDriverName && hInst ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
|
|
//
|
|
// We only set system restore points on the local machine for now.
|
|
//
|
|
if (SUCCEEDED(hRetval) && !pszServer)
|
|
{
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
if (LoadString(hInst, ResId, szMessage, COUNTOF(szMessage)))
|
|
{
|
|
//
|
|
// We have to check here if the length of the message
|
|
// is at least two (because of the string terminator and
|
|
// at least one format specifier)
|
|
//
|
|
if (lstrlen(szMessage) > 2)
|
|
{
|
|
hRetval = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hRetval = HResultFromWin32(ERROR_RESOURCE_DATA_NOT_FOUND);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hRetval = GetLastErrorAsHResult();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
PWSTR pszArray[1];
|
|
|
|
//
|
|
// Now we calculate how much of the driver name we can fit into the
|
|
// message (which is only 64 characters). This is
|
|
// MAX_DESC - (strlen(szMessage) - 2) - 1.
|
|
//
|
|
wcsncpy(szDriverName, pszDriverName, MAX_DESC - wcslen(szMessage) + 2);
|
|
|
|
szDriverName[MAX_DESC - wcslen(szMessage) + 1] = L'\0';
|
|
|
|
pszArray[0] = szDriverName;
|
|
|
|
hRetval = FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
szMessage,
|
|
0,
|
|
0,
|
|
m_RestorePointInfo.szDescription,
|
|
COUNTOF(m_RestorePointInfo.szDescription),
|
|
(va_list *)pszArray) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
//
|
|
// Now that we have the system restore point, set it.
|
|
//
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
m_RestorePointInfo.dwEventType = BEGIN_NESTED_SYSTEM_CHANGE;
|
|
m_RestorePointInfo.dwRestorePtType = DEVICE_DRIVER_INSTALL;
|
|
m_RestorePointInfo.llSequenceNumber = 0;
|
|
|
|
hRetval = m_pfnSetRestorePoint(&m_RestorePointInfo, &SMgrStatus) ? S_OK : HRESULT_FROM_WIN32(SMgrStatus.nStatus);
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
m_bSystemRestoreSet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failing to set the system restore point should not stop us adding
|
|
// the printer driver.
|
|
//
|
|
hRetval = S_OK;
|
|
}
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
EndSystemRestorePoint
|
|
|
|
Routine Description:
|
|
|
|
This function either completes the system restore point or it cancels it if
|
|
if whoever was doing the installiong tells us to.
|
|
|
|
Arguments:
|
|
|
|
bCancel - If TRUE, the restore point should be cancelled.
|
|
|
|
Return Value:
|
|
|
|
An HRESULT.
|
|
|
|
--*/
|
|
HRESULT
|
|
TSystemRestorePoint::
|
|
EndSystemRestorePoint(
|
|
IN BOOL bCancel
|
|
)
|
|
{
|
|
HRESULT hRetval = S_OK;
|
|
STATEMGRSTATUS SMgrStatus;
|
|
|
|
if (m_bSystemRestoreSet)
|
|
{
|
|
m_RestorePointInfo.dwEventType = END_NESTED_SYSTEM_CHANGE;
|
|
m_RestorePointInfo.dwRestorePtType = bCancel ? CANCELLED_OPERATION : DEVICE_DRIVER_INSTALL;
|
|
|
|
hRetval = m_pfnSetRestorePoint(&m_RestorePointInfo, &SMgrStatus) ? S_OK : HRESULT_FROM_WIN32(SMgrStatus.nStatus);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Private Methods
|
|
|
|
******************************************************************************/
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Initialize
|
|
|
|
Routine Description:
|
|
|
|
Load the system restore library and get the address of the system restore
|
|
function.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
HRESULT
|
|
TSystemRestorePoint::
|
|
Initialize(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
|
|
m_hLibrary = LoadLibraryFromSystem32(L"srclient.dll");
|
|
|
|
hRetval = m_hLibrary ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
m_pfnSetRestorePoint = reinterpret_cast<PFnSRSetRestorePoint>(GetProcAddress(m_hLibrary, "SRSetRestorePointW"));
|
|
|
|
hRetval = m_pfnSetRestorePoint ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
StartSystemRestorePoint
|
|
|
|
Routine Description:
|
|
|
|
This form of the function is for C callers, it is handle based.
|
|
|
|
Arguments:
|
|
|
|
pszServer - The server on which we are doing the restore point.
|
|
pszDriverName - The driver name we are installing.
|
|
hInst - The instance in which the resource which we want to load is.
|
|
ResId - The Resource Id.
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
extern "C"
|
|
HANDLE
|
|
StartSystemRestorePoint(
|
|
IN PCWSTR pszServer,
|
|
IN PCWSTR pszDriverName,
|
|
IN HINSTANCE hInst,
|
|
IN UINT ResId
|
|
)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
HANDLE hRestorePoint = NULL;
|
|
|
|
#ifdef _WIN64
|
|
return NULL;
|
|
#endif
|
|
|
|
TSystemRestorePoint *pSystemRestorePoint = new TSystemRestorePoint;
|
|
|
|
hRetval = pSystemRestorePoint ? pSystemRestorePoint->IsValid() : E_OUTOFMEMORY;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval = pSystemRestorePoint->StartSystemRestorePoint(pszServer, pszDriverName, hInst, ResId);
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRestorePoint = pSystemRestorePoint;
|
|
|
|
pSystemRestorePoint = NULL;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(HRESULT_CODE(hRetval));
|
|
}
|
|
|
|
delete pSystemRestorePoint;
|
|
|
|
return hRestorePoint;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
EndSystemRestorePoint
|
|
|
|
Routine Description:
|
|
|
|
This form of the function is for C callers, it is handle based.
|
|
Note: This also closes the handle.
|
|
|
|
Arguments:
|
|
|
|
hRestorePoint - The system restore point.
|
|
bCancel - If TRUE, the system restore point should be cancelled
|
|
and not completed.
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
extern "C"
|
|
BOOL
|
|
EndSystemRestorePoint(
|
|
IN HANDLE hRestorePoint,
|
|
IN BOOL bCancel
|
|
)
|
|
{
|
|
|
|
HRESULT hRetval = E_FAIL;
|
|
TSystemRestorePoint *pRestorePoint = reinterpret_cast<TSystemRestorePoint *>(hRestorePoint);
|
|
|
|
#ifdef _WIN64
|
|
return SUCCEEDED( E_FAIL );
|
|
#endif
|
|
|
|
hRetval = pRestorePoint ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval = pRestorePoint->EndSystemRestorePoint(bCancel);
|
|
|
|
delete pRestorePoint;
|
|
}
|
|
|
|
if (FAILED(hRetval))
|
|
{
|
|
SetLastError(HRESULT_CODE(hRetval));
|
|
}
|
|
|
|
return SUCCEEDED(hRetval);
|
|
}
|
|
|