註冊 PSHED Plug-In
PSHED 外掛程式會藉由呼叫 PshedRegisterPlugin 函式,將指標傳遞至初始化 的 WHEA_PSHED_PLUGIN_REGISTRATION_PACKET 結構,向 PSHED 註冊本身。 PSHED 外掛程式通常會從其 DriverEntry函式或其AddDevice函式內呼叫PshedRegisterPlugin函式。
PSHED 外掛程式可以呼叫 PshedIsSystemWheaEnabled ,以在呼叫 PshedRegisterPlugin之前檢查系統是否已啟用 WHEA。
PSHED 外掛程式有兩個版本。 兩者之間的主要差異在於 V2 外掛程式可以取消註冊。 在 V1 PSHED 外掛程式成功向 PSHED 註冊本身之後,就無法在作業系統會話期間取消註冊。 因此,註冊的 PSHED 外掛程式不得從系統卸載,或可能發生錯誤檢查。 V2 外掛程式確實允許取消註冊。
下列程式碼範例示範註冊參與錯誤資訊擷取和錯誤記錄持續性的 PSHED 外掛程式。 請注意 V1 和 V2 的差異。
// Prototypes for the callback functions for
// participating in error information retrieval
NTSTATUS
RetrieveErrorInfo(
IN OUT PVOID PluginContext,
IN PWHEA_ERROR_SOURCE_DESCRIPTOR ErrorSource,
IN ULONG64 BufferLength,
IN OUT PWHEA_ERROR_PACKET Packet
);
NTSTATUS
FinalizeErrorRecord(
IN OUT PVOID PluginContext,
IN PWHEA_ERROR_SOURCE_DESCRIPTOR ErrorSource,
IN ULONG BufferLength,
IN OUT PWHEA_ERROR_RECORD ErrorRecord
);
NTSTATUS
ClearErrorStatus(
IN OUT PVOID PluginContext,
IN PWHEA_ERROR_SOURCE_DESCRIPTOR ErrorSource,
IN ULONG BufferLength,
IN PWHEA_ERROR_RECORD ErrorRecord
);
// Prototypes for the callback functions for
// participating in error record persistence.
NTSTATUS
WriteErrorRecord(
IN OUT PVOID PluginContext,
IN ULONG Flags,
IN ULONG RecordLength,
IN PWHEA_ERROR_RECORD ErrorRecord
);
NTSTATUS
ReadErrorRecord(
IN OUT PVOID PluginContext,
IN ULONG Flags,
IN ULONGLONG ErrorRecordId
IN PULONGLONG NextErrorRecordId
IN OUT PULONG RecordLength,
OUT PWHEA_ERROR_RECORD *ErrorRecord
);
NTSTATUS
ClearErrorRecord(
IN OUT PVOID PluginContext,
IN ULONG Flags,
IN ULONGLONG ErrorRecordId
);
// The PSHED plug-in registration packet for a V1 PSHED plugin
WHEA_PSHED_PLUGIN_REGISTRATION_PACKET_V1 RegPacket =
{
sizeof(WHEA_PSHED_PLUGIN_REGISTRATION_PACKET_V1),
WHEA_PSHED_PLUGIN_REGISTRATION_PACKET_V1,
NULL,
PshedFAErrorInfoRetrieval | PshedFAErrorRecordPersistence,
0,
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
WriteErrorRecord,
ReadErrorRecord,
ClearErrorRecord,
RetrieveErrorInfo,
FinalizeErrorRecord,
ClearErrorStatus,
NULL,
NULL,
NULL
}
}
// The PSHED plug-in registration packet for a V2 PSHED plugin
WHEA_PSHED_PLUGIN_REGISTRATION_PACKET RegPacket =
{
sizeof(WHEA_PSHED_PLUGIN_REGISTRATION_PACKET),
WHEA_PLUGIN_REGISTRATION_PACKET_VERSION,
NULL,
PshedFAErrorInfoRetrieval | PshedFAErrorRecordPersistence,
0,
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
WriteErrorRecord,
ReadErrorRecord,
ClearErrorRecord,
RetrieveErrorInfo,
FinalizeErrorRecord,
ClearErrorStatus,
NULL,
NULL,
NULL
},
PluginHandle
}
//
// The PSHED plug-in's DriverEntry function for a V1 PSHED Plugin
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
BOOLEAN IsWheaEnabled;
NTSTATUS Status;
...
// No unload function for V1 PSHED plugins
DriverObject->DriverUnload = NULL;
// Query if the system is WHEA-enabled
IsWheaEnabled =
PshedIsSystemWheaEnabled(
);
// Check result
if (IsWheaEnabled == FALSE)
{
// Return "not supported" status
return STATUS_NOT_SUPPORTED;
}
// Register the PSHED plug-in
Status =
PshedRegisterPlugin(
&RegPacket
);
// Check status
if (Status != STATUS_SUCCESS)
{
// Handle error
...
}
...
// Return success
return STATUS_SUCCESS;
}
//
// The PSHED plug-in's DriverEntry function for a V2 PSHED Plugin
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
BOOLEAN IsWheaEnabled;
NTSTATUS Status;
...
// There is an unload function for V2 PSHED plugin
DriverObject->DriverUnload = PluginUnload;
// Query if the system is WHEA-enabled
IsWheaEnabled =
PshedIsSystemWheaEnabled(
);
// Check result
if (IsWheaEnabled == FALSE)
{
// Return "not supported" status
return STATUS_NOT_SUPPORTED;
}
// Register the PSHED plug-in
Status =
PshedRegisterPlugin(
&RegPacket
);
// Check status
if (Status != STATUS_SUCCESS)
{
// Handle error
...
}
...
// Return success
return STATUS_SUCCESS;
}