註冊 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;
}