373 lines
9.3 KiB
C
373 lines
9.3 KiB
C
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
/*++
|
|
|
|
Module Name:
|
|
|
|
whearec.c
|
|
|
|
Abstract:
|
|
|
|
This module provides the top level implementation of the functions provided
|
|
by the WHEA record interpretation library.
|
|
|
|
--*/
|
|
|
|
#include "cperhlpp.h"
|
|
|
|
BOOL
|
|
CperIsValidErrorRecordSignature (
|
|
__in PWHEA_ERROR_RECORD Record
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will compare the error record signature with the proper values
|
|
and return whether it is correct or not.
|
|
|
|
Arguments:
|
|
|
|
Record - Supplies a pointer to the error record.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the error record signature is correct.
|
|
|
|
FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
if ((Record->Header.Signature != WHEA_ERROR_RECORD_SIGNATURE) ||
|
|
(Record->Header.Revision.AsUSHORT > WHEA_ERROR_RECORD_REVISION) ||
|
|
(Record->Header.SignatureEnd != WHEA_ERROR_RECORD_SIGNATURE_END)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CperGetFirstSection (
|
|
__in PWHEA_ERROR_RECORD Record,
|
|
__out ULONG *Context,
|
|
__out PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR *SectionDescriptor,
|
|
__out_opt PVOID *SectionData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine may be used to enumerate the sections in a common platform
|
|
error record.
|
|
|
|
Arguments:
|
|
|
|
Record - Supplies a pointer to the error record.
|
|
|
|
Context - Supplies a pointer to a variable that maintains the current state
|
|
of the search. The same variable should be used in subsequent calls to
|
|
enumerate subsequent sections in the record.
|
|
|
|
Descriptor - Supplies a location in which a pointer to the descriptor for
|
|
the found section is returned.
|
|
|
|
Section - Supplies an optional location in which a pointer to the found
|
|
section is returned.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is nonzero (TRUE). If the
|
|
function fails the return value is zero (FALSE). To get extended error
|
|
information, call the GetLastError function.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Next;
|
|
BOOL Result;
|
|
|
|
Next = 0;
|
|
Result = CperGetNextSection(Record, &Next, SectionDescriptor, SectionData);
|
|
if (Result != FALSE) {
|
|
*Context = Next;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
CperGetNextSection (
|
|
__in PWHEA_ERROR_RECORD Record,
|
|
__inout ULONG *Context,
|
|
__out PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR *SectionDescriptor,
|
|
__out_opt PVOID *SectionData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine may be used to enumerate the sections in a common platform
|
|
error record.
|
|
|
|
Arguments:
|
|
|
|
Record - Supplies a pointer to the error record.
|
|
|
|
Context - Supplies a pointer to a variable that maintains the current state
|
|
of the search. The same variable should be used in subsequent calls to
|
|
enumerate subsequent sections in the record.
|
|
|
|
Descriptor - Supplies a location in which a pointer to the descriptor for
|
|
the found section is returned.
|
|
|
|
Section - Supplies an optional location in which a pointer to the found
|
|
section is returned.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is nonzero (TRUE). If the
|
|
function fails the return value is zero (FALSE). To get extended error
|
|
information, call the GetLastError function.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR Descriptor;
|
|
ULONG Error;
|
|
ULONG Index;
|
|
ULONG MinimumLength;
|
|
BOOL Result;
|
|
|
|
Result = TRUE;
|
|
Error = NO_ERROR;
|
|
if ((Record == NULL) ||
|
|
(Context == NULL) ||
|
|
(SectionDescriptor == NULL) ||
|
|
(CperIsValidErrorRecordSignature(Record) == FALSE) ||
|
|
(Record->Header.SectionCount == 0)) {
|
|
|
|
Result = FALSE;
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto GetNextSectionEnd;
|
|
}
|
|
|
|
//
|
|
// Ensure that the supplied record is at least as long as required to store
|
|
// the descriptors for the sections supposedly in the record.
|
|
//
|
|
|
|
MinimumLength = sizeof(WHEA_ERROR_RECORD_HEADER) +
|
|
(Record->Header.SectionCount *
|
|
sizeof(WHEA_ERROR_RECORD_SECTION_DESCRIPTOR));
|
|
|
|
if (Record->Header.Length < MinimumLength) {
|
|
Result = FALSE;
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto GetNextSectionEnd;
|
|
}
|
|
|
|
//
|
|
// If the index is greater than the number of sections, then it has been
|
|
// incorrectly fabricated by the caller or the record had section removed
|
|
// during the enumeration. Either way, this is different to the case where
|
|
// there are no sections left.
|
|
//
|
|
|
|
Index = *Context;
|
|
if (Index > Record->Header.SectionCount) {
|
|
Result = FALSE;
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto GetNextSectionEnd;
|
|
}
|
|
|
|
if (Index == Record->Header.SectionCount) {
|
|
Result = FALSE;
|
|
Error = ERROR_NOT_FOUND;
|
|
goto GetNextSectionEnd;
|
|
}
|
|
|
|
Descriptor = &Record->SectionDescriptor[Index];
|
|
|
|
//
|
|
// If the descriptor describes a section that is not completely contained
|
|
// within the record then the record is invalid.
|
|
//
|
|
|
|
if ((Descriptor->SectionOffset + Descriptor->SectionLength) >
|
|
Record->Header.Length) {
|
|
|
|
Result = FALSE;
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
goto GetNextSectionEnd;
|
|
}
|
|
|
|
*Context = Index + 1;
|
|
*SectionDescriptor = Descriptor;
|
|
if (SectionData != NULL) {
|
|
*SectionData = (PVOID)(((PUCHAR)Record) + Descriptor->SectionOffset);
|
|
}
|
|
|
|
GetNextSectionEnd:
|
|
if (Result == FALSE) {
|
|
SetLastError(Error);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
CperFindPrimarySection (
|
|
__in PWHEA_ERROR_RECORD Record,
|
|
__out PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR *SectionDescriptor,
|
|
__out PVOID *SectionData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will find the primary section and return a reference to its
|
|
descriptor and data. If no section is marked as primary, then by convention
|
|
the first section (section 0) is returned as the primary section.
|
|
|
|
Arguments:
|
|
|
|
Record - Supplies a pointer to the error record.
|
|
|
|
SectionDescriptor - Supplies a buffer in which a pointer to the descriptor
|
|
of the primary section will be returned.
|
|
|
|
SectionData - Supplies a buffer in which a pointer to the body of the
|
|
primary section will be returned.
|
|
|
|
Return Value:
|
|
|
|
TRUE upon success, FALSE otherwise. In the case of failure, the error code
|
|
can be obtained by calling GetLastError(). If there are no error records
|
|
remaining, the function will fail with the error code ERROR_NO_MORE_ITEMS.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Context;
|
|
PVOID Data;
|
|
PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR Descriptor;
|
|
BOOL Result;
|
|
|
|
Result = CperGetFirstSection(Record,
|
|
&Context,
|
|
&Descriptor,
|
|
&Data);
|
|
|
|
while (Result != FALSE) {
|
|
if (Descriptor->Flags.Primary == 1) {
|
|
*SectionDescriptor = Descriptor;
|
|
*SectionData = Data;
|
|
break;
|
|
}
|
|
|
|
Result = CperGetNextSection(Record,
|
|
&Context,
|
|
&Descriptor,
|
|
&Data);
|
|
}
|
|
|
|
//
|
|
// If no primary section was found, then get the first section and return
|
|
// that.
|
|
//
|
|
|
|
if ((Result == FALSE) && (GetLastError() == ERROR_NOT_FOUND)) {
|
|
Result = CperGetFirstSection(Record,
|
|
&Context,
|
|
SectionDescriptor,
|
|
SectionData);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
CperFindSection (
|
|
__in PWHEA_ERROR_RECORD Record,
|
|
__in const GUID *SectionType,
|
|
__out PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR *SectionDescriptor,
|
|
__out PVOID *SectionData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine provides a means to search an error record for a specific
|
|
section.
|
|
|
|
Arguments:
|
|
|
|
Record - Supplies a pointer to the error record.
|
|
|
|
SectionType - Supplies a GUID specifying the section being sought. This may
|
|
be any standard common platform error record or implementation specific
|
|
section type.
|
|
|
|
Descriptor - Supplies a location in which a pointer to the descriptor for
|
|
the found section is returned.
|
|
|
|
Section - Supplies an optional location in which a pointer to the found
|
|
section is returned.
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is nonzero (TRUE). If the
|
|
function fails the return value is zero (FALSE). To get extended error
|
|
information, call the GetLastError function.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Context;
|
|
PVOID Data;
|
|
PWHEA_ERROR_RECORD_SECTION_DESCRIPTOR Descriptor;
|
|
BOOL Result;
|
|
|
|
Result = CperGetFirstSection(Record,
|
|
&Context,
|
|
&Descriptor,
|
|
&Data);
|
|
|
|
while (Result != FALSE) {
|
|
if (IsEqualGUID(&Descriptor->SectionType, SectionType)) {
|
|
break;
|
|
}
|
|
|
|
Result = CperGetNextSection(Record,
|
|
&Context,
|
|
&Descriptor,
|
|
&Data);
|
|
}
|
|
|
|
if (Result != FALSE) {
|
|
*SectionDescriptor = Descriptor;
|
|
*SectionData = Data;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|