NDF-Hilfsklassenerweiterung
In diesem Beispiel wird veranschaulicht, wie NDF-Diagnose- und Reparaturfunktionen implementiert werden. In diesem Beispiel muss eine kritische Konfigurationsdatei vorhanden sein, damit das System fehlerfrei bleibt. Dementsprechend besteht das Problem darin, zu bestimmen, ob die Datei vorhanden ist. Wenn dies nicht der Fall ist, ist das System fehlerhaft, und das Problem wird von NDF diagnostiziert. Bei der Reparatur wird die fehlende Datei neu erstellt.
Um das Problem zu diagnostizieren und zu beheben, müssen vier INetDiagHelper-Methoden verwendet werden: Initialize, LowHealth, GetRepairInfo und Repair.
Initialisieren der Hilfsklasse
Initialisieren Sie den Namen der zu suchenden Datei, und rufen Sie ihn ab. Dieser Dateiname wird während der Diagnose als Hilfsattribute mit dem Namen "filename" übergeben.
#include <windows.h>
//utility function to simplify string allocation and copies, user throughout example
HRESULT
StringCchCopyWithAlloc (
PWSTR* Dest,
size_t cchMaxLen,
in PCWSTR Src)
{
if (NULL == Dest || NULL == Src || cchMaxLen > USHRT_MAX)
{
return E_INVALIDARG;
}
size_t cchSize = 0;
HRESULT hr = StringCchLength(Src, cchMaxLen - 1, &cchSize);
if (FAILED(hr))
{
return hr;
}
size_t cbSize = (cchSize + 1)*sizeof(WCHAR);
*Dest = (PWSTR) CoTaskMemAlloc(cbSize);
if (NULL == *Dest)
{
return E_OUTOFMEMORY;
}
SecureZeroMemory(*Dest, cbSize);
return StringCchCopy((STRSAFE_LPWSTR)*Dest, cchSize + 1, Src);
}
HRESULT SimpleFileHelperClass::Initialize(
/* [in] */ ULONG celt,
/* [size_is][in] */ HELPER_ATTRIBUTE rgAttributes[ ])
{
if(celt < 1)
{
return E_INVALIDARG;
}
if(rgAttributes == NULL)
{
return E_INVALIDARG;
}
else
{
//verify the attribute is named as expected
if (wcscmp(rgAttributes[0].pwszName, L"filename")==0)
{
//copy the attribute to member variable
return StringCchCopyWithAlloc(&m_pwszTestFile, MAX_PATH,
rgAttributes[0].PWStr);
} else {
//the attribute isn't named as expected
return E_INVALIDARG;
}
}
}
Überprüfen des Vorhandenseins der Datei
Die LowHealth-Methode wird verwendet, um das Vorhandensein der Datei zu überprüfen. Wenn die Datei vorhanden ist, wird status diagnose auf DS_REJECTED festgelegt, was darauf hinweist, dass nichts falsch ist. Wenn die Datei nicht gefunden werden kann, wird die status diagnose auf DS_CONFIRMED festgelegt.
#include <windows.h>
HRESULT SimpleFileHelperClass::LowHealth(
/* [unique][string][in] */ LPCWSTR pwszInstanceDescription,
/* [string][out] */ LPWSTR *ppwszDescription,
/* [out] */ long *pDeferredTime,
/* [out] */ DIAGNOSIS_STATUS *pStatus)
{
HANDLE hFile = NULL;
LPWSTR pwszDiagString=NULL;
// does the file already exist?
hFile = CreateFile(
m_pwszTestFile,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
// alloc and set the diagnosis description and status
HRESULT hr = StringCchCopyWithAlloc(&pwszDiagString, MAX_PATH,
L"The file was deleted.");
if (FAILED(hr))
{
return hr;
}
*ppwszDescription = pwszDiagString;
*pStatus = DS_CONFIRMED;
return S_OK;
}
CloseHandle(hFile);
//the file exists
*pStatus = DS_REJECTED;
return S_OK;
}
Bestimmen der Reparaturaktion
Wenn LowHealthDS_CONFIRMED zurückgibt, wird GetRepairInfo implementiert, um die entsprechende Reparaturaktion zu bestimmen. In diesem Beispiel bedeutet dies, dass die Datei neu erstellt wird.
#include <windows.h>
HRESULT
SimpleFileHelperClass::GetRepairInfo(
/* [in] */ PROBLEM_TYPE problem,
/* [out] */ ULONG *pcelt,
/* [size_is][size_is][out] */ RepairInfo **ppInfo)
{
HRESULT hr=S_OK;
RepairInfo* pRepair = (RepairInfo *)CoTaskMemAlloc(sizeof(RepairInfo));
if (pRepair == NULL) {
return E_OUTOFMEMORY;
}
SecureZeroMemory(pRepair,sizeof(RepairInfo));
// set the repair description and class name
hr = StringCchCopyWithAlloc(&pRepair->pwszClassName, MAX_PATH,
L"SimpleFileHelperClass");
if (FAILED(hr))
{
goto Error;
}
hr = StringCchCopyWithAlloc(&pRepair->pwszDescription, MAX_PATH,
L"Low Health Repair");
if (FAILED(hr))
{
goto Error;
}
// set the resolution GUID and cost
pRepair->guid = ID_LowHealthRepair;
pRepair->cost = 0;
// set repair status flags
pRepair->sidType = WinWorldSid;
pRepair->scope = RS_SYSTEM;
pRepair->risk = RR_NORISK;
pRepair->flags |= DF_IMPERSONATION; //impersonate the user when repairing
pRepair->UiInfo.type = UIT_NONE;
//pass back the repair
*ppInfo = pRepair;
*pcelt = 1; //number of repairs
return S_OK;
Error:
if(pRepair){
if(pRepair->pwszClassName){
CoTaskMemFree(pRepair->pwszClassName);
}
if(pRepair->pwszDescription){
CoTaskMemFree(pRepair->pwszDescription);
}
}
return hr;
}
Beheben des Problems
Dem Benutzer werden die von GetRepairInfo zurückgegebenen Korrekturoptionen angezeigt, es sei denn, es gibt nur eine Reparaturoption, in diesem Fall wird sie automatisch ausgeführt. Die Repair-Methode wird mit der entsprechenden RepairInfo-Struktur aufgerufen, damit die Konfigurationsdatei wiederhergestellt werden kann.
#include <windows.h>
HRESULT
SimpleFileHelperClass::Repair(
/* [in] */ RepairInfo *pInfo,
/* [out] */ long *pDeferredTime,
/* [out] */ REPAIR_STATUS *pStatus)
{
//verify expected repair was requested
if(IsEqualGUID(ID_LowHealthRepair, pInfo->guid)){
HANDLE hFile = NULL;
hFile = CreateFile(m_pwszTestFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
// repair failed
*pStatus = RS_UNREPAIRED;
return HRESULT_FROM_WIN32(GetLastError());
}
CloseHandle(hFile);
// repair succeeded
*pStatus = RS_REPAIRED;
} else {
return E_INVALIDARG; //unkown repair passed in
}
return S_OK;
}