Leaked source code of windows server 2003
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.
 
 
 
 
 
 

651 lines
17 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
output.hxx
Abstract:
This header file declares output classes for callbacks,
control, parsing, and filtering.
Author:
JasonHa
--*/
#ifndef _OUTPUT_HXX_
#define _OUTPUT_HXX_
class OutputControl
{
public:
// IUnknown
virtual ULONG STDMETHODCALLTYPE AddRef(THIS) {
return ++RefCount;
}
virtual ULONG STDMETHODCALLTYPE Release(void) {
ULONG NewCount = RefCount-1;
if (NewCount == 0)
{
delete this;
}
else
{
RefCount = NewCount;
}
return NewCount;
}
OutputControl()
{
RefCount = 1;
OutCtl = DEBUG_OUTCTL_AMBIENT;
Control = NULL;
}
OutputControl(ULONG OutputControl,
PDEBUG_CLIENT Client = NULL)
{
RefCount = 1;
OutCtl = DEBUG_OUTCTL_AMBIENT;
Control = NULL;
SetControl(OutputControl, Client);
}
OutputControl(PDEBUG_CLIENT Client)
{
RefCount = 1;
OutCtl = DEBUG_OUTCTL_AMBIENT;
Control = NULL;
SetControl(DEBUG_OUTCTL_AMBIENT, Client);
}
~OutputControl()
{
if (RefCount != 1)
{
DbgPrint("OutputControl::RefCount != 1.\n");
DbgBreakPoint();
}
if (Control != NULL) Control->Release();
}
ULONG GetControl() { return OutCtl; }
HRESULT SetControl(ULONG OutputControl, PDEBUG_CLIENT Client = NULL);
HRESULT Output(ULONG Mask, PCSTR Format, ...);
HRESULT OutputVaList(ULONG Mask, PCSTR Format, va_list Args);
HRESULT Output(PCSTR Format, ...);
HRESULT OutErr(PCSTR Format, ...);
HRESULT OutWarn(PCSTR Format, ...);
HRESULT OutVerb(PCSTR Format, ...);
HRESULT GetInterrupt();
HRESULT SetInterrupt(ULONG Flags);
HRESULT Evaluate(IN PCSTR Expression, IN ULONG DesiredType, OUT PDEBUG_VALUE Value, OUT OPTIONAL PULONG RemainderIndex);
HRESULT CoerceValue(IN PDEBUG_VALUE In, IN ULONG OutType, OUT PDEBUG_VALUE Out);
HRESULT IsPointer64Bit();
private:
ULONG RefCount;
PDEBUG_CONTROL Control;
ULONG OutCtl;
};
class OutputState
{
public:
OutputState(PDEBUG_CLIENT OrgClient, BOOL SameClient=FALSE);
~OutputState();
HRESULT Setup(ULONG OutMask, PDEBUG_OUTPUT_CALLBACKS OutCallbacks);
HRESULT Execute(IN PCSTR pszCommand);
HRESULT OutputType(
IN BOOL Physical,
IN ULONG64 Offset,
IN ULONG64 Module,
IN ULONG TypeId,
IN ULONG Flags
);
HRESULT OutputType(
IN BOOL Physical,
IN ULONG64 Offset,
IN PCSTR Type,
IN ULONG Flags
);
HRESULT OutputTypePhysical(
IN ULONG64 Offset,
IN ULONG64 Module,
IN ULONG TypeId,
IN ULONG Flags
)
{
return OutputType(TRUE, Offset, Module, TypeId, Flags);
}
HRESULT OutputTypePhysical(
IN ULONG64 Offset,
IN PCSTR Type,
IN ULONG Flags
)
{
return OutputType(TRUE, Offset, Type, Flags);
}
HRESULT OutputTypeVirtual(
IN ULONG64 Offset,
IN ULONG64 Module,
IN ULONG TypeId,
IN ULONG Flags
)
{
return OutputType(FALSE, Offset, Module, TypeId, Flags);
}
HRESULT OutputTypeVirtual(
IN ULONG64 Offset,
IN PCSTR Type,
IN ULONG Flags
)
{
return OutputType(FALSE, Offset, Type, Flags);
}
void Restore();
public:
PDEBUG_CLIENT Client;
private:
HRESULT hrInit;
PDEBUG_CONTROL Control;
PDEBUG_SYMBOLS Symbols;
BOOL CreatedClient;
BOOL SetCallbacks;
BOOL Saved;
ULONG OrgOutMask;
PDEBUG_OUTPUT_CALLBACKS OrgOutCallbacks;
};
//----------------------------------------------------------------------------
//
// Default output callbacks implementation, provides IUnknown for
// static classes.
//
//----------------------------------------------------------------------------
class DefOutputCallbacks :
public IDebugOutputCallbacks
{
public:
DefOutputCallbacks() { RefCount = 1; }
~DefOutputCallbacks()
{
if (RefCount != 1)
{
DbgPrint("DefOutputCallbacks@0x%p::RefCount(%lu) != 1.\n", this, RefCount);
DbgBreakPoint();
}
#if DBG
RefCount--;
#endif
}
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG Mask,
IN PCSTR Text
);
protected:
ULONG RefCount;
};
//----------------------------------------------------------------------------
//
// DebugOutputCallbacks.
//
//----------------------------------------------------------------------------
class DebugOutputCallbacks : public DefOutputCallbacks
{
public:
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG Mask,
IN PCSTR Text
);
};
//----------------------------------------------------------------------------
//
// OutputReader
//
// General DebugOutputCallback class to read output.
//
//----------------------------------------------------------------------------
class OutputReader : public DefOutputCallbacks
{
public:
OutputReader()
{
hHeap = NULL;
Buffer = NULL;
BufferSize = 0;
BufferLeft = 0;
}
~OutputReader()
{
if (Buffer) HeapFree(hHeap, 0, Buffer);
}
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG Mask,
IN PCSTR Text
);
// Discard any text left unused by Parse
virtual void DiscardOutput();
// Get a copy of the output buffer
HRESULT GetOutputCopy(PSTR *Copy);
// Free the copy
void FreeOutputCopy(PSTR Copy)
{
if (hHeap != NULL) { HeapFree(hHeap, 0, Copy); }
}
protected:
HANDLE hHeap;
PSTR Buffer;
SIZE_T BufferSize;
SIZE_T BufferLeft;
};
//----------------------------------------------------------------------------
//
// OutputParser
//
// General DebugOutputCallback class to parse output.
//
//----------------------------------------------------------------------------
#define PARSE_OUTPUT_DISCARD 0x00000000
#define PARSE_OUTPUT_NO_DISCARD 0x00000001
#define PARSE_OUTPUT_UNPARSED 0x00000000
#define PARSE_OUTPUT_ALL 0x00000002
#define PARSE_OUTPUT_DEFAULT (PARSE_OUTPUT_DISCARD | PARSE_OUTPUT_UNPARSED)
class OutputParser : public OutputReader
{
public:
OutputParser() : OutputReader()
{
UnparsedIndex = 0;
}
// Send all read text through Parse method
// Flags:
// PARSE_OUTPUT_DISCARD or PARSE_OUTPUT_NO_DISCARD
// PARSE_OUTPUT_UNPARSED or PARSE_OUTPUT_ALL
// PARSE_OUTPUT_DEFAULT = PARSE_OUTPUT_DISCARD + PARSE_OUTPUT_UNPARSED
HRESULT ParseOutput(FLONG Flags = PARSE_OUTPUT_DEFAULT);
// Discard any text left unused by Parse
void DiscardOutput();
// Check if ready to look for keys/values
virtual HRESULT Ready() PURE;
// Reset progress counter so we may parse more output
virtual void Relook() PURE;
// Parse line of text and optionally return index to unused portion of text
virtual HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex) PURE;
// Check if all keys/values were found during past reads
virtual HRESULT Complete() PURE;
private:
DWORD UnparsedIndex;
};
//----------------------------------------------------------------------------
//
// BasicOutputParser
//
// Basic DebugOutputCallback class to parse output looking for
// string keys and subsequent values.
//
//----------------------------------------------------------------------------
#define PARSER_UNSPECIFIED_RADIX -1
#define PARSER_DEFAULT_RADIX 0
class BasicOutputParser : public OutputParser
{
typedef struct {
PDEBUG_VALUE Value;
ULONG Type;
ULONG Radix;
CHAR Key[80];
} LookupEntry;
public:
BasicOutputParser(PDEBUG_CLIENT OutputClient, ULONG TotalEntries = 4)
{
Client = OutputClient;
Entries = new LookupEntry[TotalEntries];
if (!Entries) TotalEntries = 0;
MaxEntries = TotalEntries;
NumEntries = 0;
CurEntry = 0;
}
~BasicOutputParser()
{
if (Entries) delete[] Entries;
}
HRESULT LookFor(OUT PDEBUG_VALUE Value,
IN PCSTR Key,
IN ULONG Type = DEBUG_VALUE_INVALID,
IN ULONG Radix = PARSER_UNSPECIFIED_RADIX);
// Check if ready to look for keys/values
HRESULT Ready() { return (CurEntry != NumEntries) ? S_OK : S_FALSE; }
// Reset progress counter so we may parse more output
void Relook() { CurEntry = 0; }
// Parse line of text and optionally return index to unused portion of text
HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
// Check if all keys/values were found during past reads
HRESULT Complete()
{
return (Client != NULL &&
CurEntry == NumEntries) ?
S_OK :
S_FALSE;
}
private:
PDEBUG_CLIENT Client;
ULONG MaxEntries;
ULONG NumEntries;
ULONG CurEntry;
LookupEntry *Entries;
};
//----------------------------------------------------------------------------
//
// BitFieldParser
//
// DebugOutputCallback class to parse bitfield type output
//
//----------------------------------------------------------------------------
class BitFieldInfo {
public:
BitFieldInfo() { Valid = FALSE; };
BitFieldInfo(ULONG InitBitPos, ULONG InitBits) {
Valid = Compose(InitBitPos, InitBits);
}
BOOL Compose(ULONG CBitPos, ULONG CBits)
{
BitPos = CBitPos;
Bits = CBits;
Mask = (((((ULONG64) 1) << Bits) - 1) << BitPos);
return TRUE;
}
BOOL Valid;
ULONG BitPos;
ULONG Bits;
ULONG64 Mask;
};
class BitFieldParser : public OutputParser
{
public:
BitFieldParser(PDEBUG_CLIENT Client, BitFieldInfo *BFI);
// Reset progress counter so we may parse more output
void Relook()
{
if (BitField != NULL)
{
BitField->Valid = FALSE;
BitField->BitPos = 0;
BitField->Bits = 0;
BitField->Mask = 0;
}
BitFieldReader.Relook();
}
// Check if ready to look for bit fields
HRESULT Ready()
{
return (BitField != NULL) ?
BitFieldReader.Ready() :
S_FALSE;
}
// Parse line of text and optionally return index to unused portion of text
HRESULT Parse(IN PCSTR Text, OUT OPTIONAL PULONG RemainderIndex);
// Check if bit fields were found during past reads
HRESULT Complete()
{
return (BitField != NULL && BitField->Valid) ?
BitFieldReader.Complete() :
S_FALSE;
}
private:
BitFieldInfo *BitField;
DEBUG_VALUE BitPos;
DEBUG_VALUE Bits;
BasicOutputParser BitFieldReader;
};
//----------------------------------------------------------------------------
//
// OutputFilter
//
// DebugOutputCallback class to filter output
// by skipping/replacing lines.
//
//----------------------------------------------------------------------------
// Query Flags
#define OUTFILTER_QUERY_EVERY_LINE 0x00000000
#define OUTFILTER_QUERY_ONE_LINE 0x00000001
#define OUTFILTER_QUERY_WHOLE_WORD 0x00000002 // Characters before and after
// query must not be C symbols
// [a-z,A-A,0-9,_]
#define OUTFILTER_QUERY_ENABLED 0x00000004
#define OUTFILTER_QUERY_HIT 0x00000008
// Replace Flags
#define OUTFILTER_REPLACE_EVERY 0x00000000
#define OUTFILTER_REPLACE_ONCE 0x00010000
#define OUTFILTER_REPLACE_ALL_INSTANCES (OUTFILTER_REPLACE_EVERY | OUTFILTER_QUERY_EVERY_LINE)
#define OUTFILTER_REPLACE_ONCE_PER_LINE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_EVERY_LINE)
#define OUTFILTER_REPLACE_EXACTLY_ONCE (OUTFILTER_REPLACE_ONCE | OUTFILTER_QUERY_ONE_LINE)
#define OUTFILTER_REPLACE_CONTINUE 0x00000000
#define OUTFILTER_REPLACE_NEXT_LINE 0x00020000 // Stop replacement checks
// for current line after
// this replacement
#define OUTFILTER_REPLACE_BEFORE 0x04000000 // Replace text in line prior to query match
#define OUTFILTER_REPLACE_THIS 0x02000000 // Replace query text
#define OUTFILTER_REPLACE_AFTER 0x01000000 // Replace text following query match
#define OUTFILTER_REPLACE_FROM_START (OUTFILTER_REPLACE_BEFORE | OUTFILTER_REPLACE_THIS)
#define OUTFILTER_REPLACE_TO_END (OUTFILTER_REPLACE_THIS | OUTFILTER_REPLACE_AFTER)
#define OUTFILTER_REPLACE_LINE (OUTFILTER_REPLACE_BEFORE | \
OUTFILTER_REPLACE_THIS | \
OUTFILTER_REPLACE_AFTER)
#define OUTFILTER_REPLACE_PRIORITY(x) (((x+8) & 0xF) << 28) // Higher priority replacement queries
// are tested before lower. Priority
// range: 7 (high) to -7 (low)
#define OUTFILTER_REPLACE_DEFAULT (OUTFILTER_REPLACE_ALL_INSTANCES | \
OUTFILTER_REPLACE_CONTINUE | \
OUTFILTER_REPLACE_THIS | \
OUTFILTER_REPLACE_PRIORITY(0))
// Skip Flags
#define OUTFILTER_SKIP_DEFAULT OUTFILTER_QUERY_EVERY_LINE
// FindMatch Flags
#define OUTFILTER_FINDMATCH_ANYWHERE 0
#define OUTFILTER_FINDMATCH_AT_START 1
#define OUTFILTER_FINDMATCH_MARK 0
#define OUTFILTER_FINDMATCH_NO_MARK 2
#define OUTFILTER_FINDMATCH_DEFAULT (OUTFILTER_FINDMATCH_ANYWHERE | OUTFILTER_FINDMATCH_MARK)
class OutputFilter : public OutputReader
{
public:
OutputFilter(PDEBUG_CLIENT DbgClient) : OutputReader()
{
Client = DbgClient;
if (Client != NULL) Client->AddRef();
SkipList = NULL;
ReplaceList = NULL;
Outputing = FALSE;
}
~OutputFilter()
{
if (Client != NULL) Client->Release();
}
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG Mask,
IN PCSTR Text
);
HRESULT Query(PCSTR Query,
PDEBUG_VALUE Value = NULL,
ULONG Type = DEBUG_VALUE_INVALID,
ULONG Radix = PARSER_UNSPECIFIED_RADIX);
HRESULT Replace(ULONG Flags, PCSTR Query, PCSTR Replacement);
HRESULT Skip(ULONG Flags, PCSTR Query);
HRESULT OutputText(OutputControl *OutCtl = NULL, ULONG Mask = DEBUG_OUTPUT_NORMAL);
protected:
class QuerySpec
{
public:
QuerySpec(ULONG Flags, PCSTR Query);
~QuerySpec()
{
if (Query != NULL)
{
delete[] Query;
}
}
QuerySpec *Next;
ULONG Flags;
ULONG QueryLen;
PSTR Query;
};
class ReplacementSpec : public QuerySpec
{
public:
ReplacementSpec(ULONG Flags, PCSTR QueryText, PCSTR ReplacementText);
~ReplacementSpec()
{
if (Replacement != NULL)
{
delete[] Replacement;
}
}
// ReplacementSpec *Next;
ULONG ReplacementLen;
PSTR Replacement;
};
QuerySpec **FindPrior(ULONG Flags, PCSTR Query, QuerySpec **List);
QuerySpec *FindMatch(PCSTR Text,
QuerySpec *List,
ULONG Start = 0,
ULONG Flags = OUTFILTER_FINDMATCH_DEFAULT,
PULONG MatchPos = NULL);
PDEBUG_CLIENT Client;
ReplacementSpec *ReplaceList;
QuerySpec *SkipList;
private:
BOOL Outputing;
};
#endif _OUTPUT_HXX_