NDF 帮助程序类扩展
此示例演示如何实现 NDF 诊断和修复函数。 在此示例中,必须存在关键配置文件才能使系统保持正常运行。 因此,问题在于确定文件是否存在。 否则,表示系统运行不正常,由 NDF 诊断问题。 修复是重新创建缺少的文件。
若要诊断和修复此问题,需要使用四种 INetDiagHelper 方法: Initialize、 LowHealth、 GetRepairInfo 和 Repair。
初始化帮助程序类
初始化并检索要查找的文件的名称。 此文件名在诊断期间作为名为“filename”的帮助程序属性传递。
#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;
}
}
}
检查文件是否存在
LowHealth 方法用于检查文件是否存在。 如果文件存在,诊断状态将设置为 DS_REJECTED,表示没有任何错误。 如果找不到该文件,诊断状态将设置为 DS_CONFIRMED。
#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;
}
确定修复操作
如果 LowHealth 返回 DS_CONFIRMED,则实现 GetRepairInfo 以确定适当的修复操作。 在此示例中,这意味着重新创建文件。
#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;
}
修复问题
用户会看到 GetRepairInfo 返回的修复选项,除非只有一个修复选项,在这种情况下会自动执行该修复选项。 使用适用的 RepairInfo 结构调用 Repair 方法,以便可以还原配置文件。
#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;
}