897 lines
15 KiB
C++
897 lines
15 KiB
C++
#include <pch.cxx>
|
|
|
|
#define _ULIB_MEMBER_
|
|
#include "ulib.hxx"
|
|
#include "message.hxx"
|
|
#include "hmem.hxx"
|
|
|
|
extern "C" {
|
|
#include "stdio.h"
|
|
#if defined(_AUTOCHECK_)
|
|
#include "ntos.h"
|
|
#endif
|
|
}
|
|
|
|
DEFINE_EXPORTED_CONSTRUCTOR(MESSAGE, OBJECT, ULIB_EXPORT);
|
|
|
|
|
|
MESSAGE::~MESSAGE(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for MESSAGE.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
|
|
VOID
|
|
MESSAGE::Construct(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the object to a default initial state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
_logged_chars = 0;
|
|
_next_message_offset = 0;
|
|
_logging_enabled = FALSE;
|
|
_msgid = 0;
|
|
_inuse = 0;
|
|
_timeout.QuadPart = 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
MESSAGE::Destroy(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the object to a default initial state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
_logged_chars = 0;
|
|
_next_message_offset = 0;
|
|
_logging_enabled = FALSE;
|
|
_msgid = 0;
|
|
_inuse = 0;
|
|
_timeout.QuadPart = 0;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::Initialize(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the class to a valid initial state.
|
|
|
|
Arguments:
|
|
|
|
DotsOnly - Autochk should produce only dots instead of messages.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
Destroy();
|
|
|
|
_timeout.QuadPart = -10000;
|
|
return _log_buffer.Initialize();
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::IsSuppressedMessage(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function determines whether the specified message ID
|
|
should be suppressed, i.e. not recorded in the message log.
|
|
|
|
Arguments:
|
|
|
|
MessageId -- Supplies the Message ID in question.
|
|
|
|
Return Value:
|
|
|
|
TRUE if this message ID is in the set which is not recorded
|
|
in the message log.
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN result;
|
|
|
|
switch( _msgid ) {
|
|
|
|
case MSG_HIDDEN_STATUS:
|
|
case MSG_PERCENT_COMPLETE:
|
|
case MSG_PERCENT_COMPLETE2:
|
|
case MSG_CHK_NTFS_CHECKING_FILES:
|
|
case MSG_CHK_NTFS_CHECKING_INDICES:
|
|
case MSG_CHK_NTFS_INDEX_VERIFICATION_COMPLETED:
|
|
case MSG_CHK_NTFS_FILE_VERIFICATION_COMPLETED:
|
|
case MSG_CHK_NTFS_CHECKING_SECURITY:
|
|
case MSG_CHK_NTFS_SECURITY_VERIFICATION_COMPLETED:
|
|
case MSG_CHK_VOLUME_CLEAN:
|
|
case MSG_CHK_CHECKING_FILES:
|
|
case MSG_CHK_DONE_CHECKING:
|
|
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::Display(
|
|
IN PCSTR Format ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine displays the message with the specified parameters.
|
|
|
|
Arguments:
|
|
|
|
Format ... - Supplies a printf style list of arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
BOOLEAN r;
|
|
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
va_start(ap, Format);
|
|
r = DisplayV(Format, ap);
|
|
va_end(ap);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::DisplayMsg(
|
|
IN MSGID MsgId,
|
|
IN PCSTR Format ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine displays the message with the specified parameters.
|
|
It performs the operation atomically.
|
|
|
|
Arguments:
|
|
|
|
Format ... - Supplies a printf style list of arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
BOOLEAN r;
|
|
|
|
while (InterlockedCompareExchange(&_inuse, 1, 0)) {
|
|
NtDelayExecution(FALSE, &_timeout);
|
|
}
|
|
|
|
Set(MsgId);
|
|
|
|
va_start(ap, Format);
|
|
r = DisplayV(Format, ap);
|
|
va_end(ap);
|
|
|
|
InterlockedDecrement(&_inuse);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::DisplayMsg(
|
|
IN MSGID MsgId,
|
|
IN MESSAGE_TYPE MessageType,
|
|
IN ULONG MessageVisual,
|
|
IN PCSTR Format ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine displays the message with the specified parameters.
|
|
It performs the operation atomically.
|
|
|
|
Arguments:
|
|
|
|
Format ... - Supplies a printf style list of arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
BOOLEAN r;
|
|
|
|
while (InterlockedCompareExchange(&_inuse, 1, 0)) {
|
|
NtDelayExecution(FALSE, &_timeout);
|
|
}
|
|
|
|
Set(MsgId, MessageType, MessageVisual);
|
|
|
|
va_start(ap, Format);
|
|
r = DisplayV(Format, ap);
|
|
va_end(ap);
|
|
|
|
InterlockedDecrement(&_inuse);
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::LogMsg(
|
|
IN MSGID MsgId,
|
|
IN PCSTR Format ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine logs the message with the specified parameters.
|
|
It performs the operation atomically.
|
|
|
|
Arguments:
|
|
|
|
Format ... - Supplies a printf style list of arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
BOOLEAN r;
|
|
|
|
while (InterlockedCompareExchange(&_inuse, 1, 0)) {
|
|
NtDelayExecution(FALSE, &_timeout);
|
|
}
|
|
|
|
Set(MsgId);
|
|
|
|
va_start(ap, Format);
|
|
r = LogV(Format, ap);
|
|
va_end(ap);
|
|
|
|
InterlockedDecrement(&_inuse);
|
|
|
|
return r;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::Log(
|
|
IN PCSTR Format ...
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine logs the message with the specified parameters.
|
|
|
|
Arguments:
|
|
|
|
Format ... - Supplies a printf style list of arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
BOOLEAN r;
|
|
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
va_start(ap, Format);
|
|
r = LogV(Format, ap);
|
|
va_end(ap);
|
|
|
|
return r;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::DumpDataToLog(
|
|
IN PVOID Data,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine dumps the binary data to the log.
|
|
|
|
Arguments:
|
|
|
|
Data - Supplies a pointer to the data to be dumped
|
|
Length - Supplies the number of bytes to dump
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR pdata = (PUCHAR)Data;
|
|
ULONG block;
|
|
BOOLEAN rst = TRUE;
|
|
WCHAR buffer[50], buffer2[20];
|
|
USHORT i;
|
|
|
|
block = ((Length + 0xf) >> 4) + 1;
|
|
Set(MSG_CHKLOG_DUMP_DATA);
|
|
|
|
while (rst && block--) {
|
|
|
|
for (i=0; i<16; i++) {
|
|
__try {
|
|
swprintf(buffer+i*3, L"%02x ", pdata[i]);
|
|
if (isprint(pdata[i]))
|
|
swprintf(buffer2+i, L"%c", pdata[i]);
|
|
else
|
|
buffer2[i] = '.';
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
buffer[i*3] = '?';
|
|
buffer[i*3+1] = '?';
|
|
buffer[i*3+2] = ' ';
|
|
buffer2[i] = '.';
|
|
}
|
|
}
|
|
buffer[48] = ' ';
|
|
buffer[49] = 0;
|
|
buffer2[16] = 0;
|
|
|
|
pdata += 0x10;
|
|
rst = rst && Log("%ws%ws", buffer, buffer2);
|
|
}
|
|
|
|
return rst;
|
|
}
|
|
|
|
BOOLEAN
|
|
MESSAGE::DisplayV(
|
|
IN PCSTR Format,
|
|
IN va_list VarPointer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine displays the message with the specified parameters.
|
|
|
|
Arguments:
|
|
|
|
Format - Supplies a printf style list of arguments.
|
|
VarPointer - Supplies a varargs pointer to the arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
(void)(Format);
|
|
(void)(VarPointer);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
MESSAGE::LogV(
|
|
IN PCSTR Format,
|
|
IN va_list VarPointer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine logs the message with the specified parameters.
|
|
|
|
Arguments:
|
|
|
|
Format - Supplies a printf style list of arguments.
|
|
VarPointer - Supplies a varargs pointer to the arguments.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
DSTRING display_string;
|
|
CHAR buffer[512];
|
|
|
|
if (IsLoggingEnabled()) {
|
|
|
|
if (!BASE_SYSTEM::QueryResourceStringV(&display_string, _msgid, Format,
|
|
VarPointer)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (display_string.QuerySTR(0, TO_END, buffer, 512, TRUE)) {
|
|
DebugPrintTrace(("%s", buffer));
|
|
}
|
|
|
|
return LogMessage(&display_string);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PMESSAGE
|
|
MESSAGE::Dup(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns a new MESSAGE of the same type.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
A pointer to a new MESSAGE object.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
return NEW MESSAGE;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::IsYesResponse(
|
|
IN BOOLEAN Default
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries to see if the response to a message is either
|
|
yes or no.
|
|
|
|
Arguments:
|
|
|
|
Default - Supplies a default answer to the question.
|
|
|
|
Return Value:
|
|
|
|
FALSE - A "no" response.
|
|
TRUE - A "yes" response.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
return Default;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::QueryStringInput(
|
|
OUT PWSTRING String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries a string from the user.
|
|
|
|
Arguments:
|
|
|
|
String - Supplies a buffer to return the string into.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
return String->Initialize("");
|
|
}
|
|
|
|
|
|
|
|
ULIB_EXPORT
|
|
MSGID
|
|
MESSAGE::SelectResponse(
|
|
IN ULONG NumberOfSelections ...
|
|
)
|
|
/*++
|
|
|
|
Routine Descriptions:
|
|
|
|
This routine queries a response from the user. It returns the
|
|
message id of the response inputted.
|
|
|
|
Arguments:
|
|
|
|
NumberOfSelections - Supplies the number of possible message
|
|
responses.
|
|
|
|
... - Supplies 'NumberOfSelections' message identifiers.
|
|
|
|
Return Value:
|
|
|
|
The first message id on the list.
|
|
|
|
--*/
|
|
{
|
|
va_list ap;
|
|
MSGID msg;
|
|
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
va_start(ap, NumberOfSelections);
|
|
msg = va_arg(ap, MSGID);
|
|
va_end(ap);
|
|
return msg;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::IsInAutoChk(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine simply returns FALSE to indicate it is not
|
|
in regular autochk.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Not in autochk
|
|
|
|
--*/
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::IsInSetup(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine simply returns FALSE to indicate it is not
|
|
in setup.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Not in setup
|
|
|
|
--*/
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::IsKeyPressed(
|
|
MSGID MsgId,
|
|
ULONG TimeOutInSeconds
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine simply returns FALSE to indicate no
|
|
key has been pressed.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
FALSE - No key is pressed within the time out period.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
UNREFERENCED_PARAMETER( MsgId );
|
|
UNREFERENCED_PARAMETER( TimeOutInSeconds );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::WaitForUserSignal(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine waits for a signal from the user.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
FALSE - Failure.
|
|
TRUE - Success.
|
|
|
|
--*/
|
|
{
|
|
// unreferenced parameters
|
|
(void)(this);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::SetDotsOnly(
|
|
IN BOOLEAN DotsState
|
|
)
|
|
{
|
|
// unreferenced parameters
|
|
(void)this;
|
|
(void)DotsState;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::QueryPackedLog(
|
|
IN OUT PHMEM Mem,
|
|
OUT PULONG PackedDataLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Mem -- Supplies a container for the packed log.
|
|
PackedDataLength -- Receives the number of bytes written to Mem.
|
|
|
|
Return Value:
|
|
|
|
TRUE upon successful completion.
|
|
|
|
--*/
|
|
{
|
|
FSTRING CurrentString;
|
|
PWCHAR Buffer;
|
|
ULONG NewBufferSize, CurrentOffset;
|
|
|
|
if( !IsLoggingEnabled() ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ResetLoggingIterator();
|
|
CurrentOffset = 0;
|
|
|
|
while( QueryNextLoggedMessage( &CurrentString ) ) {
|
|
|
|
NewBufferSize = (CurrentOffset + CurrentString.QueryChCount()) * sizeof(WCHAR);
|
|
if( NewBufferSize > Mem->QuerySize() &&
|
|
!Mem->Resize( (NewBufferSize + 1023)/1024 * 1024, 0x1 ) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Buffer = (PWCHAR)Mem->GetBuf();
|
|
memcpy( Buffer + CurrentOffset,
|
|
CurrentString.GetWSTR(),
|
|
CurrentString.QueryChCount() * sizeof(WCHAR) );
|
|
|
|
CurrentOffset += CurrentString.QueryChCount();
|
|
}
|
|
|
|
*PackedDataLength = CurrentOffset * sizeof(WCHAR);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MESSAGE::QueryNextLoggedMessage(
|
|
OUT PFSTRING MessageText
|
|
)
|
|
{
|
|
PWCHAR Buffer = (PWCHAR)_log_buffer.GetBuf();
|
|
BOOLEAN Result;
|
|
|
|
if( _next_message_offset >= _logged_chars ) {
|
|
|
|
// No more logged messages.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
Result = (MessageText->Initialize( Buffer + _next_message_offset ) != NULL) ?
|
|
TRUE : FALSE;
|
|
|
|
// Push _next_message_offset to the next message. Note
|
|
// that _next_message_offset is also incremented if this
|
|
// loop terminates because a zero was found, so that it
|
|
// will be one character past the next NULL character.
|
|
//
|
|
while( _next_message_offset < _logged_chars &&
|
|
Buffer[_next_message_offset++] );
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
ULIB_EXPORT
|
|
BOOLEAN
|
|
MESSAGE::LogMessage(
|
|
PCWSTRING Message
|
|
)
|
|
{
|
|
ULONG NewBufferSize;
|
|
PWCHAR Buffer;
|
|
|
|
// The buffer must be large enough to accept this message plus
|
|
// a trailing null. To cut down the number of memory allocation
|
|
// calls, grow the buffer by 1K chunks.
|
|
//
|
|
NewBufferSize = (_logged_chars + Message->QueryChCount() + 1) * sizeof(WCHAR);
|
|
|
|
// Don't allow the buffer to grow more than 0.5MB
|
|
// otherwise we may use up all the pages.
|
|
|
|
if (NewBufferSize > 512000)
|
|
return FALSE;
|
|
|
|
if( _log_buffer.QuerySize() < NewBufferSize &&
|
|
!_log_buffer.Resize( (NewBufferSize + 1023)/1024 * 1024, 0x1 ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
Buffer = (PWCHAR)_log_buffer.GetBuf();
|
|
|
|
// QueryWSTR will append a trailing NULL.
|
|
//
|
|
Message->QueryWSTR( 0, TO_END,
|
|
Buffer + _logged_chars,
|
|
_log_buffer.QuerySize()/sizeof(WCHAR) - _logged_chars );
|
|
|
|
_logged_chars += Message->QueryChCount() + 1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
VOID
|
|
MESSAGE::Lock(
|
|
)
|
|
{
|
|
while (InterlockedCompareExchange(&_inuse, 1, 0)) {
|
|
NtDelayExecution(FALSE, &_timeout);
|
|
}
|
|
}
|
|
|
|
ULIB_EXPORT
|
|
VOID
|
|
MESSAGE::Unlock(
|
|
)
|
|
{
|
|
InterlockedDecrement(&_inuse);
|
|
}
|
|
|