windows-nt/Source/XPSP1/NT/printscan/print/spooler/spllib/checkpoint.cxx
2020-09-26 16:20:57 +08:00

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