diff --git a/reactos/subsystems/win32/win32k/include/gdidebug.h b/reactos/subsystems/win32/win32k/include/gdidebug.h index be2a0237d80..5b53ec44218 100644 --- a/reactos/subsystems/win32/win32k/include/gdidebug.h +++ b/reactos/subsystems/win32/win32k/include/gdidebug.h @@ -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); diff --git a/reactos/subsystems/win32/win32k/include/win32.h b/reactos/subsystems/win32/win32k/include/win32.h index 0204ff96bf1..51c0a094c2f 100644 --- a/reactos/subsystems/win32/win32k/include/win32.h +++ b/reactos/subsystems/win32/win32k/include/win32.h @@ -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; diff --git a/reactos/subsystems/win32/win32k/include/win32kdebug.h b/reactos/subsystems/win32/win32k/include/win32kdebug.h new file mode 100644 index 00000000000..2bd70465a38 --- /dev/null +++ b/reactos/subsystems/win32/win32k/include/win32kdebug.h @@ -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(); diff --git a/reactos/subsystems/win32/win32k/include/win32kp.h b/reactos/subsystems/win32/win32k/include/win32kp.h index 7c79d893c7b..f2843b1cf55 100644 --- a/reactos/subsystems/win32/win32k/include/win32kp.h +++ b/reactos/subsystems/win32/win32k/include/win32kp.h @@ -24,6 +24,7 @@ #define DBG_ENABLE_SERVICE_HOOKS 0 /* Internal Win32k Headers */ +#include #include #include #include diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index d6d2147934d..f1e16891900 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -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 */ diff --git a/reactos/subsystems/win32/win32k/ntuser/class.c b/reactos/subsystems/win32/win32k/ntuser/class.c index 74595eccaa3..4f298de6229 100644 --- a/reactos/subsystems/win32/win32k/ntuser/class.c +++ b/reactos/subsystems/win32/win32k/ntuser/class.c @@ -13,9 +13,6 @@ #define NDEBUG #include -#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 diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index b10e238fcf4..6d3c93947ce 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -14,9 +14,6 @@ #define NDEBUG #include -#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; diff --git a/reactos/subsystems/win32/win32k/objects/gdidbg.c b/reactos/subsystems/win32/win32k/objects/gdidbg.c index 3d2fa58f266..4d556614b56 100644 --- a/reactos/subsystems/win32/win32k/objects/gdidbg.c +++ b/reactos/subsystems/win32/win32k/objects/gdidbg.c @@ -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; +} +