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.
500 lines
12 KiB
500 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
powermsg.c
|
|
|
|
Abstract:
|
|
|
|
Classes for manipulating power logging error messages.
|
|
|
|
Author:
|
|
|
|
Andrew Ritz (andrewr) 1-May-2002
|
|
|
|
Revision History:
|
|
|
|
|
|
Andrew Ritz (andrewr) 1-May-2002 - created it.
|
|
|
|
--*/
|
|
|
|
|
|
#include "powercfg.h"
|
|
#include "resource.h"
|
|
|
|
|
|
PowerLoggingMessage::PowerLoggingMessage(
|
|
IN PSYSTEM_POWER_STATE_DISABLE_REASON LoggingReason,
|
|
IN DWORD SStateBaseMessageIndex,
|
|
IN HINSTANCE hInstance
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Base PowerLoggingMessage class constructor.
|
|
|
|
Arguments:
|
|
|
|
LoggingReason - structure containing the reason data we're wrapping.
|
|
SStateBaseMessageIndex - base message id we use for looking up a resource
|
|
string associated with this problem.
|
|
hInstance - module handle for looking up resource associated with this
|
|
problem.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// save off the logging reason data.
|
|
//
|
|
_LoggingReason = (PSYSTEM_POWER_STATE_DISABLE_REASON) LocalAlloc(LPTR, sizeof(SYSTEM_POWER_STATE_DISABLE_REASON)+LoggingReason->PowerReasonLength);
|
|
|
|
if (!_LoggingReason) {
|
|
throw(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
|
|
}
|
|
|
|
CopyMemory(_LoggingReason,LoggingReason, sizeof(SYSTEM_POWER_STATE_DISABLE_REASON)+LoggingReason->PowerReasonLength);
|
|
|
|
//
|
|
// the message resource is offset from the supplied base index.
|
|
//
|
|
if (_LoggingReason->PowerReasonCode == SPSD_REASON_UNKNOWN) {
|
|
_MessageResourceId = SStateBaseMessageIndex + MAX_REASON_OFFSET;
|
|
} else {
|
|
_MessageResourceId = SStateBaseMessageIndex + _LoggingReason->PowerReasonCode;
|
|
}
|
|
|
|
ASSERT(_MessageResourceId <= SStateBaseMessageIndex + MAX_REASON_OFFSET);
|
|
|
|
_hInst = hInstance;
|
|
//
|
|
// this is a cache of the reason, initialized to NULL, filled in when we
|
|
// call GetString
|
|
//
|
|
_MessageResourceString = NULL;
|
|
|
|
}
|
|
|
|
PowerLoggingMessage::~PowerLoggingMessage(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Base PowerLoggingMessage class destructor. deletes some member data.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// delete member data.
|
|
//
|
|
if (_LoggingReason) {
|
|
LocalFree(_LoggingReason);
|
|
}
|
|
|
|
if (_MessageResourceString) {
|
|
LocalFree(_MessageResourceString);
|
|
}
|
|
}
|
|
|
|
PWSTR
|
|
PowerLoggingMessage::DuplicateString(
|
|
IN PWSTR String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
PowerLoggingMessage helper for copying a string to a newly allocated
|
|
heap buffer.
|
|
|
|
Arguments:
|
|
|
|
String - null terminated unicode string to duplicate.
|
|
|
|
Return Value:
|
|
|
|
pointer to new heap buffer with copy of string if successful, else NULL.
|
|
|
|
--*/
|
|
{
|
|
PWSTR MyString;
|
|
DWORD StringLength;
|
|
|
|
StringLength = (wcslen(String)+1);
|
|
MyString = (PWSTR)LocalAlloc(LPTR, StringLength*sizeof(WCHAR));
|
|
if (MyString) {
|
|
CopyMemory(MyString,String,StringLength*sizeof(WCHAR));
|
|
}
|
|
|
|
return(MyString);
|
|
}
|
|
|
|
|
|
BOOL
|
|
PowerLoggingMessage::GetResourceString(
|
|
OUT PWSTR *pString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
PowerLoggingMessage wrapper for LoadString.
|
|
|
|
Arguments:
|
|
|
|
pString - receives a pointer to a string with the resource.
|
|
|
|
Return Value:
|
|
|
|
TRUE inidicates success.
|
|
|
|
--*/
|
|
{
|
|
PWSTR MyString;
|
|
DWORD StringLength,RetVal;
|
|
|
|
ASSERT(pString != NULL);
|
|
|
|
//
|
|
// arbitrary string length of 200 should hopefully be enough for any
|
|
// resource string.
|
|
//
|
|
StringLength = 200;
|
|
RetVal = 0;
|
|
MyString = (PWSTR)LocalAlloc(LPTR, StringLength*sizeof(WCHAR));
|
|
if (MyString) {
|
|
RetVal = ::LoadString(
|
|
_hInst,
|
|
_MessageResourceId,
|
|
MyString,
|
|
StringLength);
|
|
}
|
|
|
|
if (RetVal != 0) {
|
|
*pString = MyString;
|
|
}
|
|
|
|
return(*pString != NULL);
|
|
}
|
|
|
|
SubstituteNtStatusPowerLoggingMessage::SubstituteNtStatusPowerLoggingMessage(
|
|
IN PSYSTEM_POWER_STATE_DISABLE_REASON LoggingReason,
|
|
IN DWORD SStateBaseMessageIndex,
|
|
IN HINSTANCE hInstance
|
|
) : PowerLoggingMessage(LoggingReason,SStateBaseMessageIndex,hInstance)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized class constructor.
|
|
|
|
Arguments:
|
|
|
|
LoggingReason - structure containing the reason data we're wrapping.
|
|
SStateBaseMessageIndex - base message id we use for looking up a resource
|
|
string associated with this problem.
|
|
hInstance - module handle for looking up resource associated with this
|
|
problem.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
//We just inherit the base case behavior.
|
|
//
|
|
}
|
|
|
|
NoSubstitutionPowerLoggingMessage::NoSubstitutionPowerLoggingMessage(
|
|
IN PSYSTEM_POWER_STATE_DISABLE_REASON LoggingReason,
|
|
IN DWORD SStateBaseMessageIndex,
|
|
IN HINSTANCE hInstance
|
|
) : PowerLoggingMessage(LoggingReason,SStateBaseMessageIndex,hInstance)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized class constructor.
|
|
|
|
Arguments:
|
|
|
|
LoggingReason - structure containing the reason data we're wrapping.
|
|
SStateBaseMessageIndex - base message id we use for looking up a resource
|
|
string associated with this problem.
|
|
hInstance - module handle for looking up resource associated with this
|
|
problem.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
//We just inherit the base case behavior.
|
|
//
|
|
}
|
|
|
|
SubstituteMultiSzPowerLoggingMessage::SubstituteMultiSzPowerLoggingMessage(
|
|
IN PSYSTEM_POWER_STATE_DISABLE_REASON LoggingReason,
|
|
IN DWORD SStateBaseMessageIndex,
|
|
IN HINSTANCE hInstance
|
|
) : PowerLoggingMessage(LoggingReason,SStateBaseMessageIndex,hInstance)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized class constructor.
|
|
|
|
Arguments:
|
|
|
|
LoggingReason - structure containing the reason data we're wrapping.
|
|
SStateBaseMessageIndex - base message id we use for looking up a resource
|
|
string associated with this problem.
|
|
hInstance - module handle for looking up resource associated with this
|
|
problem.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
//We just inherit the base case behavior.
|
|
//
|
|
}
|
|
|
|
BOOL
|
|
NoSubstitutionPowerLoggingMessage::GetString(
|
|
PWSTR *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized GetString method, gets a string appropriate for display to
|
|
the end user. This one is just looking up a resource string.
|
|
|
|
Arguments:
|
|
|
|
String - receives a pointer to a heap allocated string. must be freed
|
|
with LocalFree() when complete.
|
|
Return Value:
|
|
|
|
BOOL indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
|
|
ASSERT(String != NULL);
|
|
|
|
//
|
|
// lookup and cache the message.
|
|
//
|
|
if (!_MessageResourceString) {
|
|
if (!GetResourceString(&_MessageResourceString)) {
|
|
_MessageResourceString = NULL;
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
ASSERT(_MessageResourceString != NULL);
|
|
|
|
//
|
|
// dup the cached string and return to caller.
|
|
//
|
|
*String = DuplicateString(_MessageResourceString);
|
|
return(*String != NULL);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SubstituteNtStatusPowerLoggingMessage::GetString(
|
|
PWSTR *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized GetString method, gets a string appropriate for display to
|
|
the end user. this one takes a string with a %d in it and returns a
|
|
formatted string.
|
|
|
|
Arguments:
|
|
|
|
String - receives a pointer to a heap allocated string. must be freed
|
|
with LocalFree() when complete.
|
|
Return Value:
|
|
|
|
BOOL indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
PWSTR MyString;
|
|
PDWORD NtStatusCode = (PDWORD)(PCHAR)((PCHAR)_LoggingReason + sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
|
|
|
|
if (!_MessageResourceString) {
|
|
if (!GetResourceString(&MyString)) {
|
|
_MessageResourceString = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// 10 is the maximum # of digits for the substituted NTSTATUS code.
|
|
// 1 for the NULL.
|
|
//
|
|
_MessageResourceString = (PWSTR)LocalAlloc(LPTR,(wcslen(MyString)+10+1)*sizeof(WCHAR));
|
|
if (!_MessageResourceString) {
|
|
LocalFree(MyString);
|
|
return(FALSE);
|
|
}
|
|
|
|
wsprintf(_MessageResourceString,MyString,*NtStatusCode);
|
|
|
|
LocalFree(MyString);
|
|
|
|
}
|
|
|
|
ASSERT(_MessageResourceString != NULL);
|
|
|
|
//
|
|
// dup the cached string and return to caller.
|
|
//
|
|
*String = DuplicateString(_MessageResourceString);
|
|
return(*String != NULL);
|
|
|
|
}
|
|
|
|
BOOL
|
|
SubstituteMultiSzPowerLoggingMessage::GetString(
|
|
PWSTR *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
specialized GetString method, gets a string appropriate for display to
|
|
the end user. this one massages a multi-sz string and substitutes that
|
|
into the resource.
|
|
|
|
Arguments:
|
|
|
|
String - receives a pointer to a heap allocated string. must be freed
|
|
with LocalFree() when complete.
|
|
Return Value:
|
|
|
|
BOOL indicating outcome.
|
|
|
|
--*/
|
|
{
|
|
PWSTR MyString;
|
|
PWSTR SubstitutionString;
|
|
DWORD NumberOfStrings;
|
|
DWORD StringSize;
|
|
PWSTR CurrentString;
|
|
DWORD CurrentStringLength;
|
|
PWSTR BaseOfString = (PWSTR)(PCHAR)((PCHAR)_LoggingReason + sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
|
|
|
|
PWSTR SeparatorString = L"\n\t\t";
|
|
DWORD SeparatorLength = wcslen(SeparatorString);
|
|
|
|
if (!_MessageResourceString) {
|
|
//
|
|
// get the resource
|
|
//
|
|
if (!GetResourceString(&MyString)) {
|
|
_MessageResourceString = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// get the multi-sz into a prettier format
|
|
// first figure out the size, then alloc space and print it out into
|
|
// a buffer.
|
|
//
|
|
NumberOfStrings = 0;
|
|
StringSize = 0;
|
|
CurrentString = BaseOfString;
|
|
CurrentStringLength = 0;
|
|
while (*CurrentString) {
|
|
CurrentStringLength = wcslen(CurrentString)+1;
|
|
StringSize +=CurrentStringLength;
|
|
CurrentString += CurrentStringLength;
|
|
NumberOfStrings += 1;
|
|
}
|
|
|
|
SubstitutionString = (PWSTR)LocalAlloc(LPTR,(StringSize+1+(NumberOfStrings*SeparatorLength))*sizeof(WCHAR));
|
|
if (!SubstitutionString) {
|
|
LocalFree(MyString);
|
|
return(FALSE);
|
|
}
|
|
|
|
CurrentString = BaseOfString;
|
|
do {
|
|
CurrentStringLength = wcslen(CurrentString)+1;
|
|
|
|
wcscat(SubstitutionString,SeparatorString);
|
|
wcscat(SubstitutionString,CurrentString);
|
|
|
|
CurrentString += CurrentStringLength;
|
|
NumberOfStrings -= 1;
|
|
|
|
} while (NumberOfStrings != 0);
|
|
|
|
//
|
|
// alloc space for the substitution string PLUS the base message.
|
|
//
|
|
_MessageResourceString = (PWSTR)LocalAlloc(
|
|
LPTR,
|
|
(wcslen(SubstitutionString) +
|
|
wcslen(MyString) + 1)
|
|
*sizeof(WCHAR));
|
|
if (!_MessageResourceString) {
|
|
LocalFree(SubstitutionString);
|
|
LocalFree(MyString);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// finally "sprintf" them together to get the final string.
|
|
// free the strings we allocated along the way.
|
|
//
|
|
wsprintf(_MessageResourceString,MyString,SubstitutionString);
|
|
|
|
LocalFree(SubstitutionString);
|
|
LocalFree(MyString);
|
|
|
|
}
|
|
|
|
ASSERT(_MessageResourceString != NULL);
|
|
|
|
//
|
|
// dup the cached string and return to caller.
|
|
//
|
|
*String = DuplicateString(_MessageResourceString);
|
|
return(*String != NULL);
|
|
|
|
}
|