You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
448 lines
9.4 KiB
448 lines
9.4 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
CorrectedEngine.cpp
|
|
|
|
Abstract:
|
|
|
|
This module encapsulates the routines that are needed only for
|
|
corrected error retrieval.
|
|
|
|
Author:
|
|
|
|
Abdullah Ustuner (AUstuner) 28-August-2002
|
|
|
|
--*/
|
|
|
|
#include "mca.h"
|
|
|
|
extern IWbemServices *gPIWbemServices;
|
|
extern IWbemLocator *gPIWbemLocator;
|
|
|
|
//
|
|
// Event which signals the corrected error retrieval.
|
|
//
|
|
HANDLE gErrorProcessedEvent;
|
|
|
|
//
|
|
// TimeOut period in minutes for corrected error retrieval.
|
|
//
|
|
INT gTimeOut;
|
|
|
|
|
|
BOOL
|
|
MCACreateProcessedEvent(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates the "processed event", which is used to keep track of
|
|
whether a corrected error record has been retrieved from WMI or not. When a
|
|
corrected error is retrieved from WMI then, this event is signaled which
|
|
causes the application to finish.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE - Successful.
|
|
FALSE - Unsuccessful.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Create the processsed event.
|
|
//
|
|
gErrorProcessedEvent = CreateEvent(NULL,
|
|
TRUE,
|
|
FALSE,
|
|
L"ErrorProcessedEvent"
|
|
);
|
|
|
|
return (gErrorProcessedEvent != NULL);
|
|
}
|
|
|
|
|
|
VOID
|
|
MCAErrorReceived(
|
|
IN IWbemClassObject *ErrorObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by an instance of the MCAObjectSink class when a corrected
|
|
error is retrieved from WMI. The error record data is extracted from the object and
|
|
the contents of this record is displayed on the screen.
|
|
|
|
Arguments:
|
|
|
|
ErrorObject - Error object retrieved from WMI.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
PUCHAR pErrorRecordBuffer = NULL;
|
|
|
|
//
|
|
// Extract the actual MCA error record from the retrieved object.
|
|
//
|
|
if (!MCAExtractErrorRecord(ErrorObject, &pErrorRecordBuffer)) {
|
|
|
|
wprintf(L"ERROR: Failed to get corrected error record data!\n");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Display the corrected error record on the screen.
|
|
//
|
|
MCAPrintErrorRecord(pErrorRecordBuffer);
|
|
|
|
CleanUp:
|
|
|
|
if (pErrorRecordBuffer) {
|
|
|
|
free(pErrorRecordBuffer);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
MCAGetCorrectedError(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function registers to WMI for corrected error notification and waits until
|
|
TimeOut limit is reached or an error is retrieved. If an error is successfully
|
|
retrieved then, the contents of the error record are displayed on the screen.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE - Successful.
|
|
FALSE - Unsuccessful.
|
|
|
|
--*/
|
|
{
|
|
BOOL isSuccess = TRUE;
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
DWORD returnValue = 0;
|
|
|
|
//
|
|
// Create the Sink instances, which will be responsible for handling
|
|
// the event callbacks from WMI.
|
|
//
|
|
MCAObjectSink *pCMCSink = new MCAObjectSink();
|
|
MCAObjectSink *pCPESink = new MCAObjectSink();
|
|
|
|
//
|
|
// Check if instance creation was successful.
|
|
//
|
|
if (pCMCSink == NULL || pCPESink == NULL) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Memory allocation failed for object sinks!");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Complete the required initialization tasks.
|
|
//
|
|
if (!MCAInitialize()) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Initialization failed!\n");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Create processed event, which will be used to signal event retrieval from WMI.
|
|
//
|
|
if(!MCACreateProcessedEvent()){
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Processed event creation failed!\n");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Register to WMI for CMC event notification.
|
|
//
|
|
if (!MCARegisterCMCConsumer(pCMCSink)) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Register to WMI for CPE event notification.
|
|
//
|
|
if (!MCARegisterCPEConsumer(pCPESink)) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
wprintf(L"INFO: Waiting for notification from WMI...\n");
|
|
|
|
//
|
|
// Wait for error retrieval until TimeOut limit is reached.
|
|
//
|
|
returnValue = WaitForSingleObjectEx(gErrorProcessedEvent,
|
|
gTimeOut*60*1000,
|
|
FALSE
|
|
);
|
|
|
|
if (returnValue == WAIT_TIMEOUT) {
|
|
|
|
wprintf(L"INFO: No error notification is received during the timeout period.\n");
|
|
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (gPIWbemServices) {
|
|
|
|
//
|
|
// Cancel any currently pending asynchronous call based on the MCAObjectSink pointers.
|
|
//
|
|
hResult = gPIWbemServices->CancelAsyncCall(pCMCSink);
|
|
|
|
if (hResult != WBEM_S_NO_ERROR){
|
|
|
|
wprintf(L"IWbemServices::CancelAsyncCall failed on CMCSink: %d\n", hResult);
|
|
|
|
}
|
|
|
|
hResult = gPIWbemServices->CancelAsyncCall(pCPESink);
|
|
|
|
if(hResult != WBEM_S_NO_ERROR){
|
|
|
|
wprintf(L"IWbemServices::CancelAsyncCall failed on CPESink: %d\n", hResult);
|
|
|
|
}
|
|
|
|
gPIWbemServices->Release();
|
|
|
|
}
|
|
|
|
//
|
|
// Release the sink object associated with CMC notification.
|
|
//
|
|
if (pCMCSink != NULL) {
|
|
|
|
pCMCSink->Release();
|
|
|
|
}
|
|
|
|
//
|
|
// Release the sink object associated with CPE notification.
|
|
//
|
|
if (pCPESink != NULL) {
|
|
|
|
pCPESink->Release();
|
|
|
|
}
|
|
|
|
if (gPIWbemLocator) {
|
|
|
|
gPIWbemLocator->Release();
|
|
}
|
|
|
|
return isSuccess;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MCARegisterCMCConsumer(
|
|
MCAObjectSink *pCMCSink
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function registers the provided object sink as a temporary consumer
|
|
to WMI for CMC event notification.
|
|
|
|
Arguments:
|
|
|
|
pCMCSink - Object sink that will be registered to WMI for CMC error notification.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Successful.
|
|
FALSE - Unsuccessful.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hResult = 0;
|
|
BOOL isSuccess = TRUE;
|
|
LPWSTR pQueryLanguage = L"WQL";
|
|
LPWSTR pQueryStatement = L"select * from MSMCAInfo_RawCMCEvent";
|
|
|
|
BSTR bQueryLanguage = SysAllocString(pQueryLanguage);
|
|
BSTR bQueryStatement = SysAllocString(pQueryStatement);
|
|
|
|
if (bQueryLanguage == NULL || bQueryStatement == NULL) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Memory allocation for string failed!\n");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Register the object sink as a temporary consumer to WMI for CMC error notification.
|
|
//
|
|
hResult = gPIWbemServices->ExecNotificationQueryAsync(bQueryLanguage,
|
|
bQueryStatement,
|
|
WBEM_FLAG_SEND_STATUS,
|
|
NULL,
|
|
pCMCSink
|
|
);
|
|
|
|
if (FAILED(hResult)) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Temporary consumer registration for CMC failed!\n");
|
|
|
|
wprintf(L"Result: 0x%x\n", hResult);
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
wprintf(L"INFO: Registered for CMC error notification successfully.\n");
|
|
|
|
CleanUp:
|
|
|
|
if (bQueryLanguage != NULL) {
|
|
|
|
SysFreeString(bQueryLanguage);
|
|
|
|
}
|
|
|
|
if (bQueryStatement != NULL) {
|
|
|
|
SysFreeString(bQueryStatement);
|
|
|
|
}
|
|
|
|
return isSuccess;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MCARegisterCPEConsumer(
|
|
MCAObjectSink *pCPESink
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function registers the provided object sink as a temporary consumer
|
|
to WMI for CPE event notification.
|
|
|
|
Arguments:
|
|
|
|
pCPESink - Object sink that will be registered to WMI for CPE error notification.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Successful.
|
|
FALSE - Unsuccessful.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hResult = 0;
|
|
BOOL isSuccess = TRUE;
|
|
LPWSTR pQueryLanguage = L"WQL";
|
|
LPWSTR pQueryStatement = L"select * from MSMCAInfo_RawCorrectedPlatformEvent";
|
|
|
|
BSTR bQueryLanguage = SysAllocString(pQueryLanguage);
|
|
BSTR bQueryStatement = SysAllocString(pQueryStatement);
|
|
|
|
if (bQueryLanguage == NULL || bQueryStatement == NULL) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Memory allocation for string failed!\n");
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
//
|
|
// Register the object sink as a temporary consumer to WMI for CPE error notification.
|
|
//
|
|
hResult = gPIWbemServices->ExecNotificationQueryAsync(bQueryLanguage,
|
|
bQueryStatement,
|
|
WBEM_FLAG_SEND_STATUS,
|
|
NULL,
|
|
pCPESink
|
|
);
|
|
if (FAILED(hResult)) {
|
|
|
|
isSuccess = FALSE;
|
|
|
|
wprintf(L"ERROR: Temporary consumer registration for CPE failed!\n");
|
|
|
|
wprintf(L"ERROR: Result: 0x%x\n", hResult);
|
|
|
|
goto CleanUp;
|
|
|
|
}
|
|
|
|
wprintf(L"INFO: Registered for CPE error notification successfully.\n");
|
|
|
|
CleanUp:
|
|
|
|
if (bQueryLanguage != NULL) {
|
|
|
|
SysFreeString(bQueryLanguage);
|
|
|
|
}
|
|
|
|
if (bQueryStatement != NULL) {
|
|
|
|
SysFreeString(bQueryStatement);
|
|
|
|
}
|
|
|
|
return isSuccess;
|
|
}
|