mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
[win32k]
- Implement support for debug channels. When a process starts, win32k will parse DEBUGCHANNEL environment variable in order to enable or disable specific debug channels or levels for this application. This gives us the ability to activate from user mode extended debug output for one application, for one component, for one level. In order to use the new debugging system we have to use the macros ERR, FIXME, WARN and TRACE. These are not used yet but shortly every DPRINT/DPRINT1 call will be converted to use the new macros - Define several win32k channels that will be used in the future - Remove some hacky definitions of the new macros svn path=/trunk/; revision=52876
This commit is contained in:
parent
f1011b2525
commit
86d2150cff
8 changed files with 484 additions and 30 deletions
|
@ -43,28 +43,12 @@ VOID NTAPI DbgCleanupEventList(PSLIST_HEADER pslh);
|
|||
#define DBG_CLEANUP_EVENT_LIST(pslh)
|
||||
#endif
|
||||
|
||||
extern ULONG gulLogUnique;
|
||||
|
||||
extern ULONG gulDebugChannels;
|
||||
|
||||
enum _DEBUGCHANNELS
|
||||
{
|
||||
DbgCustom = 1,
|
||||
DbgObjects = 2,
|
||||
DbgBitBlt = 4,
|
||||
DbgXlate = 8,
|
||||
DbgModeSwitch = 16,
|
||||
};
|
||||
|
||||
VOID NTAPI DbgDumpGdiHandleTable(VOID);
|
||||
ULONG NTAPI DbgCaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture);
|
||||
BOOL NTAPI DbgGdiHTIntegrityCheck(VOID);
|
||||
VOID NTAPI DbgDumpLockedGdiHandles(VOID);
|
||||
|
||||
#define DBGENABLE(ch) gulDebugChannels |= (ch);
|
||||
#define DBGDISABLE(ch) gulDebugChannels &= ~(ch);
|
||||
#define DPRINTCH(ch) if (gulDebugChannels & (ch)) DbgPrint
|
||||
|
||||
#define KeRosDumpStackFrames(Frames, Count) KdSystemDebugControl('DsoR', (PVOID)Frames, Count, NULL, 0, NULL, KernelMode)
|
||||
NTSYSAPI ULONG APIENTRY RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
|
||||
|
||||
|
|
|
@ -192,4 +192,8 @@ typedef struct _PROCESSINFO
|
|||
struct _GDI_POOL *pPoolDcAttr;
|
||||
struct _GDI_POOL *pPoolBrushAttr;
|
||||
struct _GDI_POOL *pPoolRgnAttr;
|
||||
|
||||
#ifdef DBG
|
||||
BYTE DbgChannelLevel[DbgChCount];
|
||||
#endif
|
||||
} PROCESSINFO;
|
||||
|
|
174
reactos/subsystems/win32/win32k/include/win32kdebug.h
Normal file
174
reactos/subsystems/win32/win32k/include/win32kdebug.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
When a process is created, DbgInitDebugChannels will locate DEBUGCHANNEL
|
||||
environment variable and extract information about debug channels.
|
||||
This information includes which of the win32k debug channels will be
|
||||
enabled for the current process and which level of a channel will be active.
|
||||
This information will be stored in ppi->DbgChannelLevel.
|
||||
In this way user mode can control how win32k debugging will work when
|
||||
the following macros are used: ERR, FIXME, WARN, TRACE
|
||||
|
||||
By default only the ERR channel will be active. Remember that other
|
||||
debug channels can be activated for applications that are executed with a DEBUGCHANNEL
|
||||
|
||||
Valid syntax for DEBUGCHANNEL is the following:
|
||||
+UserProcess,info+UserWnd,err+UserWndpos,-listview
|
||||
warn+UserMsgQ,-UserMsgGet,+shell
|
||||
|
||||
Note the following:
|
||||
The debug level is not required
|
||||
The operation to enable/disable (+/-) and the name of the channel is required
|
||||
Channels are devided by commas
|
||||
No spaces are allowed
|
||||
The syntax is case sensitive. Levels must be lowercase and
|
||||
the names of the channels must be exactly like they are defined in DBG_DEFAULT_CHANNEL
|
||||
This syntax can be mixed with wine debug channels without problems
|
||||
|
||||
*/
|
||||
|
||||
#ifdef DBG
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PWCHAR Name;
|
||||
ULONG Id;
|
||||
} DBG_CHANNEL;
|
||||
|
||||
/* note: the following values don't need to be sorted */
|
||||
enum _DEBUGCHANNELS
|
||||
{
|
||||
DbgChEngBlt,
|
||||
DbgChEngBrush,
|
||||
DbgChEngClip,
|
||||
DbgChEngCursor,
|
||||
DbgChEngDev,
|
||||
DbgChEngErr,
|
||||
DbgChEngEvent,
|
||||
DbgChEngGrad,
|
||||
DbgChEngLDev,
|
||||
DbgChEngLine,
|
||||
DbgChEngMapping,
|
||||
DbgChEngPDev,
|
||||
DbgChEngSurface,
|
||||
DbgChEngWnd,
|
||||
DbgChEngXlate,
|
||||
DbgChGdiBitmap,
|
||||
DbgChGdiBlt,
|
||||
DbgChGdiBrush,
|
||||
DbgChGdiClipRgn,
|
||||
DbgChGdiCoord,
|
||||
DbgChGdiDC,
|
||||
DbgChGdiDCAttr,
|
||||
DbgChGdiDCState,
|
||||
DbgChGdiDev,
|
||||
DbgChGdiDib,
|
||||
DbgChGdiFont,
|
||||
DbgChGdiLine,
|
||||
DbgChGdiObj,
|
||||
DbgChGdiPalette,
|
||||
DbgChGdiPath,
|
||||
DbgChGdiPen,
|
||||
DbgChGdiPool,
|
||||
DbgChGdiRgn,
|
||||
DbgChGdiText,
|
||||
DbgChGdiXFormObj,
|
||||
DbgChUserAccel,
|
||||
DbgChUserCalproc,
|
||||
DbgChUserCaret,
|
||||
DbgChUserClass,
|
||||
DbgChUserClipbrd,
|
||||
DbgChUserCsr,
|
||||
DbgChUserDce,
|
||||
DbgChUserDesktop,
|
||||
DbgChUserEvent,
|
||||
DbgChUserFocus,
|
||||
DbgChUserHook,
|
||||
DbgChUserHotkey,
|
||||
DbgChUserIcon,
|
||||
DbgChUserInput,
|
||||
DbgChUserKbd,
|
||||
DbgChUserKbdLayout,
|
||||
DbgChUserMenu,
|
||||
DbgChUserMetric,
|
||||
DbgChUserMonitor,
|
||||
DbgChUserMsgGet,
|
||||
DbgChUserMsgQ,
|
||||
DbgChUserMsgSend,
|
||||
DbgChUserObj,
|
||||
DbgChUserProcess,
|
||||
DbgChUserProp,
|
||||
DbgChUserScrollbar,
|
||||
DbgChUserSysparam,
|
||||
DbgChUserThread,
|
||||
DbgChUserTimer,
|
||||
DbgChUserWinsta,
|
||||
DbgChUserWnd,
|
||||
DbgChUserWndpos,
|
||||
DbgChCount
|
||||
};
|
||||
|
||||
#define DISABLED_LEVEL 0x0
|
||||
#define ERR_LEVEL 0x1
|
||||
#define FIXME_LEVEL 0x2
|
||||
#define WARN_LEVEL 0x4
|
||||
#define TRACE_LEVEL 0x8
|
||||
|
||||
#define MAX_LEVEL ERR_LEVEL | FIXME_LEVEL | WARN_LEVEL | TRACE_LEVEL
|
||||
|
||||
/* the following assert is needed to make sure that the
|
||||
debugging routines are not used before we get a ppi*/
|
||||
#define DBG_GET_PPI (ASSERT(PsGetCurrentProcessWin32Process()), (PPROCESSINFO)PsGetCurrentProcessWin32Process())
|
||||
#define DBG_DEFAULT_CHANNEL(x) static int DbgDefaultChannel = DbgCh##x;
|
||||
|
||||
#define DBG_ENABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] |= level)
|
||||
#define DBG_DISABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] &= ~level)
|
||||
#define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] & level)
|
||||
|
||||
#define DBG_PRINT(ppi,ch,level,fmt, ...) do { \
|
||||
if(DBG_IS_CHANNEL_ENABLED(ppi,ch,level)) \
|
||||
DbgPrint("(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
}while(0);
|
||||
|
||||
#define ERR(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, ERR_LEVEL,"err: " fmt, __VA_ARGS__)
|
||||
#define FIXME(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, FIXME_LEVEL,"fixme: " fmt, __VA_ARGS__)
|
||||
#define WARN(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, WARN_LEVEL,"warn: " fmt, __VA_ARGS__)
|
||||
#define TRACE(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, TRACE_LEVEL,"trace: " fmt, __VA_ARGS__)
|
||||
|
||||
#define ERR_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, ERR_LEVEL, "err: " fmt, __VA_ARGS__)
|
||||
#define FIXME_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, FIXME_LEVEL, "fixme: " fmt, __VA_ARGS__)
|
||||
#define WARN_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, WARN_LEVEL, "warn: " fmt, __VA_ARGS__)
|
||||
#define TRACE_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, TRACE_LEVEL, "trace: " fmt, __VA_ARGS__)
|
||||
|
||||
#define ERR_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, ERR_LEVEL,"err: " fmt, __VA_ARGS__)
|
||||
#define FIXME_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, FIXME_LEVEL,"fixme: " fmt, __VA_ARGS__)
|
||||
#define WARN_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, WARN_LEVEL,"warn: " fmt, __VA_ARGS__)
|
||||
#define TRACE_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, TRACE_LEVEL,"trace: " fmt, __VA_ARGS__)
|
||||
|
||||
#else
|
||||
#define DBG_GET_PPI
|
||||
#define DBG_DEFAULT_CHANNEL(x) ()
|
||||
|
||||
#define DBG_ENABLE_CHANNEL(ppi,ch,level) ()
|
||||
#define DBG_DISABLE_CHANNEL(ppi,ch,level) ()
|
||||
#define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) ()
|
||||
|
||||
#define DBG_PRINT(ppi,ch,level)
|
||||
|
||||
#define ERR(fmt, ...)
|
||||
#define FIXME(fmt, ...)
|
||||
#define WARN(fmt, ...)
|
||||
#define TRACE(fmt, ...)
|
||||
|
||||
#define ERR_CH(ch,fmt, ...)
|
||||
#define FIXME_CH(ch,fmt, ...)
|
||||
#define WARN_CH(ch,fmt, ...)
|
||||
#define TRACE_CH(ch,fmt, ...)
|
||||
|
||||
#define ERR_PPI(ppi,ch,fmt, ...)
|
||||
#define FIXME_PPI(ppi,ch,fmt, ...)
|
||||
#define WARN_PPI(ppi,ch,fmt, ...)
|
||||
#define TRACE_PPI(ppi,ch,fmt, ...)
|
||||
#endif
|
||||
|
||||
BOOL DbgInitDebugChannels();
|
|
@ -24,6 +24,7 @@
|
|||
#define DBG_ENABLE_SERVICE_HOOKS 0
|
||||
|
||||
/* Internal Win32k Headers */
|
||||
#include <include/win32kdebug.h>
|
||||
#include <include/accelerator.h>
|
||||
#include <include/clipboard.h>
|
||||
#include <include/cliprgn.h>
|
||||
|
|
|
@ -67,6 +67,13 @@ Win32kProcessCallback(struct _EPROCESS *Process,
|
|||
PRTL_USER_PROCESS_PARAMETERS pParams = NULL;
|
||||
NTSTATUS Status;
|
||||
extern PSECTION_OBJECT GlobalUserHeapSection;
|
||||
|
||||
#ifdef DBG
|
||||
DbgInitDebugChannels();
|
||||
#endif
|
||||
|
||||
TRACE_PPI(Win32Process, UserProcess,"Allocated ppi for PID:%d\n", Process->UniqueProcessId);
|
||||
|
||||
DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
|
||||
|
||||
/* map the global heap into the process */
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#define TRACE DPRINT
|
||||
#define WARN DPRINT1
|
||||
#define ERR DPRINT1
|
||||
|
||||
REGISTER_SYSCLASS DefaultServerClasses[] =
|
||||
{
|
||||
|
@ -1636,7 +1633,7 @@ UserSetClassLongPtr(IN PCLS Class,
|
|||
{
|
||||
PULONG_PTR Data;
|
||||
|
||||
TRACE("SetClassLong(%d, %x)\n", Index, NewLong);
|
||||
DPRINT("SetClassLong(%d, %x)\n", Index, NewLong);
|
||||
|
||||
if (Index + sizeof(ULONG_PTR) < Index ||
|
||||
Index + sizeof(ULONG_PTR) > Class->cbclsExtra)
|
||||
|
@ -1944,7 +1941,7 @@ UserRegisterSystemClasses(VOID)
|
|||
}
|
||||
else
|
||||
{
|
||||
WARN("!!! Registering system class failed!\n");
|
||||
DPRINT1("!!! Registering system class failed!\n");
|
||||
Ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -2269,9 +2266,9 @@ NtUserGetClassInfo(
|
|||
CapturedClassName = ProbeForReadUnicodeString(ClassName);
|
||||
|
||||
if (CapturedClassName.Length == 0)
|
||||
TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi);
|
||||
DPRINT("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi);
|
||||
else
|
||||
TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi);
|
||||
DPRINT("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi);
|
||||
|
||||
if (CapturedClassName.Length & 1)
|
||||
{
|
||||
|
@ -2299,7 +2296,7 @@ NtUserGetClassInfo(
|
|||
{
|
||||
if (!IS_ATOM(CapturedClassName.Buffer))
|
||||
{
|
||||
ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n");
|
||||
DPRINT1("NtUserGetClassInfo() got ClassName instead of Atom!\n");
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
Ret = FALSE;
|
||||
_SEH2_LEAVE;
|
||||
|
@ -2463,7 +2460,7 @@ NtUserGetWOWClass(HINSTANCE hInstance,
|
|||
{
|
||||
if (!IS_ATOM(ClassName->Buffer))
|
||||
{
|
||||
ERR("NtUserGetWOWClass() got ClassName instead of Atom!\n");
|
||||
DPRINT1("NtUserGetWOWClass() got ClassName instead of Atom!\n");
|
||||
Hit = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#define TRACE DPRINT
|
||||
#define WARN DPRINT1
|
||||
#define ERR DPRINT1
|
||||
|
||||
static
|
||||
VOID
|
||||
|
@ -1732,7 +1729,7 @@ IntUnmapDesktopView(IN PDESKTOP DesktopObject)
|
|||
PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
TRACE("DO %p\n");
|
||||
DPRINT("DO %p\n");
|
||||
|
||||
CurrentWin32Process = PsGetCurrentProcessWin32Process();
|
||||
PrevLink = &CurrentWin32Process->HeapMappings.Next;
|
||||
|
|
|
@ -15,9 +15,79 @@
|
|||
extern ULONG gulFirstFree;
|
||||
extern ULONG gulFirstUnused;
|
||||
|
||||
ULONG gulDebugChannels = 0;
|
||||
ULONG gulLogUnique = 0;
|
||||
|
||||
/* note the following values need to be sorted */
|
||||
DBG_CHANNEL DbgChannels[DbgChCount]={
|
||||
{L"EngBlt", DbgChEngBlt},
|
||||
{L"EngBrush", DbgChEngBrush},
|
||||
{L"EngClip", DbgChEngClip},
|
||||
{L"EngCursor", DbgChEngCursor},
|
||||
{L"EngDev", DbgChEngDev},
|
||||
{L"EngErr", DbgChEngErr},
|
||||
{L"EngEvent", DbgChEngEvent},
|
||||
{L"EngGrad", DbgChEngGrad},
|
||||
{L"EngLDev", DbgChEngLDev},
|
||||
{L"EngLine", DbgChEngLine},
|
||||
{L"EngMapping", DbgChEngMapping},
|
||||
{L"EngPDev", DbgChEngPDev},
|
||||
{L"EngSurface", DbgChEngSurface},
|
||||
{L"EngWnd", DbgChEngWnd},
|
||||
{L"EngXlate", DbgChEngXlate},
|
||||
{L"GdiBitmap", DbgChGdiBitmap},
|
||||
{L"GdiBlt", DbgChGdiBlt},
|
||||
{L"GdiBrush", DbgChGdiBrush},
|
||||
{L"GdiClipRgn", DbgChGdiClipRgn},
|
||||
{L"GdiCoord", DbgChGdiCoord},
|
||||
{L"GdiDC", DbgChGdiDC},
|
||||
{L"GdiDCAttr", DbgChGdiDCAttr},
|
||||
{L"GdiDCState", DbgChGdiDCState},
|
||||
{L"GdiDev", DbgChGdiDev},
|
||||
{L"GdiDib", DbgChGdiDib},
|
||||
{L"GdiFont", DbgChGdiFont},
|
||||
{L"GdiLine", DbgChGdiLine},
|
||||
{L"GdiObj", DbgChGdiObj},
|
||||
{L"GdiPalette", DbgChGdiPalette},
|
||||
{L"GdiPath", DbgChGdiPath},
|
||||
{L"GdiPen", DbgChGdiPen},
|
||||
{L"GdiPool", DbgChGdiPool},
|
||||
{L"GdiRgn", DbgChGdiRgn},
|
||||
{L"GdiText", DbgChGdiText},
|
||||
{L"GdiXFormObj", DbgChGdiXFormObj},
|
||||
{L"UserAccel", DbgChUserAccel},
|
||||
{L"UserCalproc", DbgChUserCalproc},
|
||||
{L"UserCaret", DbgChUserCaret},
|
||||
{L"UserClass", DbgChUserClass},
|
||||
{L"UserClipbrd", DbgChUserClipbrd},
|
||||
{L"UserCsr", DbgChUserCsr},
|
||||
{L"UserDce", DbgChUserDce},
|
||||
{L"UserDesktop", DbgChUserDesktop},
|
||||
{L"UserEvent", DbgChUserEvent},
|
||||
{L"UserFocus", DbgChUserFocus},
|
||||
{L"UserHook", DbgChUserHook},
|
||||
{L"UserHotkey", DbgChUserHotkey},
|
||||
{L"UserIcon", DbgChUserIcon},
|
||||
{L"UserInput", DbgChUserInput},
|
||||
{L"UserKbd", DbgChUserKbd},
|
||||
{L"UserKbdLayout", DbgChUserKbdLayout},
|
||||
{L"UserMenu", DbgChUserMenu},
|
||||
{L"UserMetric", DbgChUserMetric},
|
||||
{L"UserMonitor", DbgChUserMonitor},
|
||||
{L"UserMsgGet", DbgChUserMsgGet},
|
||||
{L"UserMsgQ", DbgChUserMsgQ},
|
||||
{L"UserMsgSend", DbgChUserMsgSend},
|
||||
{L"UserObj", DbgChUserObj},
|
||||
{L"UserProcess", DbgChUserProcess},
|
||||
{L"UserProp", DbgChUserProp},
|
||||
{L"UserScrollbar", DbgChUserScrollbar},
|
||||
{L"UserSysparam", DbgChUserSysparam},
|
||||
{L"UserTimer", DbgChUserTimer},
|
||||
{L"UserThread", DbgChUserThread},
|
||||
{L"UserWinsta", DbgChUserWinsta},
|
||||
{L"UserWnd", DbgChUserWnd},
|
||||
{L"UserWndpos", DbgChUserWndpos}
|
||||
};
|
||||
|
||||
#ifdef GDI_DEBUG
|
||||
#if 0
|
||||
static
|
||||
|
@ -437,3 +507,223 @@ DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
|
|||
return ulResult;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
QueryEnvironmentVariable(PUNICODE_STRING Name,
|
||||
PUNICODE_STRING Value)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PWSTR wcs;
|
||||
UNICODE_STRING var;
|
||||
PWSTR val;
|
||||
PPEB Peb;
|
||||
PWSTR Environment;
|
||||
|
||||
/* Ugly hack for reactos system threads */
|
||||
if(!NtCurrentTeb())
|
||||
{
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
Peb = NtCurrentPeb();
|
||||
|
||||
if (Peb == NULL)
|
||||
{
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
Environment = Peb->ProcessParameters->Environment;
|
||||
|
||||
if (Environment == NULL)
|
||||
{
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
Value->Length = 0;
|
||||
|
||||
wcs = Environment;
|
||||
while (*wcs)
|
||||
{
|
||||
var.Buffer = wcs++;
|
||||
wcs = wcschr(wcs, L'=');
|
||||
if (wcs == NULL)
|
||||
{
|
||||
wcs = var.Buffer + wcslen(var.Buffer);
|
||||
}
|
||||
if (*wcs)
|
||||
{
|
||||
var.Length = var.MaximumLength = (wcs - var.Buffer) * sizeof(WCHAR);
|
||||
val = ++wcs;
|
||||
wcs += wcslen(wcs);
|
||||
|
||||
if (RtlEqualUnicodeString(&var, Name, TRUE))
|
||||
{
|
||||
Value->Length = (wcs - val) * sizeof(WCHAR);
|
||||
if (Value->Length <= Value->MaximumLength)
|
||||
{
|
||||
memcpy(Value->Buffer, val,
|
||||
min(Value->Length + sizeof(WCHAR), Value->MaximumLength));
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
wcs++;
|
||||
}
|
||||
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
static int
|
||||
DbgCompareChannels(const void * a, const void * b)
|
||||
{
|
||||
return wcscmp((WCHAR*)a, ((DBG_CHANNEL*)b)->Name);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DbgAddDebugChannel(PPROCESSINFO ppi, WCHAR* channel, WCHAR* level, WCHAR op)
|
||||
{
|
||||
DBG_CHANNEL *ChannelEntry;
|
||||
UINT iLevel, iChannel;
|
||||
|
||||
DbgPrint("Found channel %S,level %S, operation %C\n", channel, level, op);
|
||||
|
||||
ChannelEntry = (DBG_CHANNEL*)bsearch(channel,
|
||||
DbgChannels,
|
||||
DbgChCount,
|
||||
sizeof(DBG_CHANNEL),
|
||||
DbgCompareChannels);
|
||||
if(ChannelEntry == NULL)
|
||||
{
|
||||
DbgPrint("Failed to find channel %S\n", channel);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
iChannel = ChannelEntry->Id;
|
||||
ASSERT(iChannel >= 0 && iChannel < DbgChCount);
|
||||
|
||||
if(level == NULL || *level == L'\0' ||wcslen(level) == 0 )
|
||||
iLevel = MAX_LEVEL;
|
||||
else if(wcsncmp(level, L"err", 3) == 0)
|
||||
iLevel = ERR_LEVEL;
|
||||
else if(wcsncmp(level, L"fixme", 5) == 0)
|
||||
iLevel = FIXME_LEVEL;
|
||||
else if(wcsncmp(level, L"warn", 4) == 0)
|
||||
iLevel = WARN_LEVEL;
|
||||
else if (wcsncmp(level, L"trace", 4) == 0)
|
||||
iLevel = TRACE_LEVEL;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if(op==L'+')
|
||||
{
|
||||
DBG_ENABLE_CHANNEL(ppi, iChannel, iLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_DISABLE_CHANNEL(ppi, iChannel, iLevel);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DbgParseDebugChannels(PPROCESSINFO ppi, PUNICODE_STRING Value)
|
||||
{
|
||||
WCHAR *str, *separator, *c, op;
|
||||
|
||||
str = Value->Buffer;
|
||||
|
||||
do
|
||||
{
|
||||
separator = wcschr(str, L',');
|
||||
if(separator != NULL)
|
||||
*separator = L'\0';
|
||||
|
||||
c = wcschr(str, L'+');
|
||||
if(c == NULL)
|
||||
c = wcschr(str, L'-');
|
||||
|
||||
if(c != NULL)
|
||||
{
|
||||
op = *c;
|
||||
*c = L'\0';
|
||||
c++;
|
||||
|
||||
DbgAddDebugChannel(ppi, c, str, op);
|
||||
}
|
||||
|
||||
str = separator + 1;
|
||||
}while(separator != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DbgInitDebugChannels()
|
||||
{
|
||||
WCHAR valBuffer[100];
|
||||
UNICODE_STRING Value;
|
||||
UNICODE_STRING Name = RTL_CONSTANT_STRING(L"DEBUGCHANNEL");
|
||||
NTSTATUS Status;
|
||||
PPROCESSINFO ppi;
|
||||
BOOL ret;
|
||||
|
||||
/* Initialize all channels to ERROR */
|
||||
ppi = PsGetCurrentProcessWin32Process();
|
||||
RtlFillMemory( ppi->DbgChannelLevel,
|
||||
sizeof(ppi->DbgChannelLevel),
|
||||
ERR_LEVEL);
|
||||
|
||||
/* Find DEBUGCHANNEL env var */
|
||||
Value.Buffer = valBuffer;
|
||||
Value.Length = 0;
|
||||
Value.MaximumLength = sizeof(valBuffer);
|
||||
Status = QueryEnvironmentVariable(&Name, &Value);
|
||||
|
||||
/* It does not exist */
|
||||
if(Status == STATUS_VARIABLE_NOT_FOUND)
|
||||
{
|
||||
/* There is nothing more to do */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If the buffer in the stack is not enough allocate it */
|
||||
if(Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
Value.Buffer = ExAllocatePool(PagedPool, Value.MaximumLength);
|
||||
if(Value.Buffer == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get the env var again */
|
||||
Status = QueryEnvironmentVariable(&Name, &Value);
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
if(Value.Buffer != valBuffer)
|
||||
{
|
||||
ExFreePool(Value.Buffer);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse the variable */
|
||||
ret = DbgParseDebugChannels(ppi, &Value);
|
||||
|
||||
/* Clean up*/
|
||||
if(Value.Buffer != valBuffer)
|
||||
{
|
||||
ExFreePool(Value.Buffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue