Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengdidbg.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS win32 kernel mode subsystem 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: subsystems/win32/win32k/objects/gdidbg.c 00005 * PURPOSE: Special debugging functions for GDI 00006 * PROGRAMMERS: Timo Kreuzer 00007 */ 00008 00011 #if DBG 00012 #include <win32k.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 extern ULONG gulFirstFree; 00017 extern ULONG gulFirstUnused; 00018 00019 ULONG gulLogUnique = 0; 00020 00021 /* Note: the following values need to be sorted */ 00022 DBG_CHANNEL DbgChannels[DbgChCount]={ 00023 {L"EngBlt", DbgChEngBlt}, 00024 {L"EngBrush", DbgChEngBrush}, 00025 {L"EngClip", DbgChEngClip}, 00026 {L"EngCursor", DbgChEngCursor}, 00027 {L"EngDev", DbgChEngDev}, 00028 {L"EngErr", DbgChEngErr}, 00029 {L"EngEvent", DbgChEngEvent}, 00030 {L"EngGrad", DbgChEngGrad}, 00031 {L"EngLDev", DbgChEngLDev}, 00032 {L"EngLine", DbgChEngLine}, 00033 {L"EngMapping", DbgChEngMapping}, 00034 {L"EngPDev", DbgChEngPDev}, 00035 {L"EngSurface", DbgChEngSurface}, 00036 {L"EngWnd", DbgChEngWnd}, 00037 {L"EngXlate", DbgChEngXlate}, 00038 {L"GdiBitmap", DbgChGdiBitmap}, 00039 {L"GdiBlt", DbgChGdiBlt}, 00040 {L"GdiBrush", DbgChGdiBrush}, 00041 {L"GdiClipRgn", DbgChGdiClipRgn}, 00042 {L"GdiCoord", DbgChGdiCoord}, 00043 {L"GdiDC", DbgChGdiDC}, 00044 {L"GdiDCAttr", DbgChGdiDCAttr}, 00045 {L"GdiDCState", DbgChGdiDCState}, 00046 {L"GdiDev", DbgChGdiDev}, 00047 {L"GdiDib", DbgChGdiDib}, 00048 {L"GdiFont", DbgChGdiFont}, 00049 {L"GdiLine", DbgChGdiLine}, 00050 {L"GdiObj", DbgChGdiObj}, 00051 {L"GdiPalette", DbgChGdiPalette}, 00052 {L"GdiPath", DbgChGdiPath}, 00053 {L"GdiPen", DbgChGdiPen}, 00054 {L"GdiPool", DbgChGdiPool}, 00055 {L"GdiRgn", DbgChGdiRgn}, 00056 {L"GdiText", DbgChGdiText}, 00057 {L"GdiXFormObj", DbgChGdiXFormObj}, 00058 {L"UserAccel", DbgChUserAccel}, 00059 {L"UserCallback", DbgChUserCallback}, 00060 {L"UserCallProc", DbgChUserCallProc}, 00061 {L"UserCaret", DbgChUserCaret}, 00062 {L"UserClass", DbgChUserClass}, 00063 {L"UserClipbrd", DbgChUserClipbrd}, 00064 {L"UserCsr", DbgChUserCsr}, 00065 {L"UserDce", DbgChUserDce}, 00066 {L"UserDefwnd", DbgChUserDefwnd}, 00067 {L"UserDesktop", DbgChUserDesktop}, 00068 {L"UserDisplay",DbgChUserDisplay}, 00069 {L"UserEvent", DbgChUserEvent}, 00070 {L"UserFocus", DbgChUserFocus}, 00071 {L"UserHook", DbgChUserHook}, 00072 {L"UserHotkey", DbgChUserHotkey}, 00073 {L"UserIcon", DbgChUserIcon}, 00074 {L"UserInput", DbgChUserInput}, 00075 {L"UserKbd", DbgChUserKbd}, 00076 {L"UserKbdLayout", DbgChUserKbdLayout}, 00077 {L"UserMenu", DbgChUserMenu}, 00078 {L"UserMetric", DbgChUserMetric}, 00079 {L"UserMisc", DbgChUserMisc}, 00080 {L"UserMonitor", DbgChUserMonitor}, 00081 {L"UserMsg", DbgChUserMsg}, 00082 {L"UserMsgQ", DbgChUserMsgQ}, 00083 {L"UserObj", DbgChUserObj}, 00084 {L"UserPainting", DbgChUserPainting}, 00085 {L"UserProcess", DbgChUserProcess}, 00086 {L"UserProp", DbgChUserProp}, 00087 {L"UserScrollbar", DbgChUserScrollbar}, 00088 {L"UserSysparams", DbgChUserSysparams}, 00089 {L"UserTimer", DbgChUserTimer}, 00090 {L"UserThread", DbgChUserThread}, 00091 {L"UserWinpos", DbgChUserWinpos}, 00092 {L"UserWinsta", DbgChUserWinsta}, 00093 {L"UserWnd", DbgChUserWnd} 00094 }; 00095 00096 #ifdef GDI_DEBUG 00097 #if 0 00098 static 00099 BOOL 00100 CompareBacktraces(ULONG idx1, ULONG idx2) 00101 { 00102 ULONG iLevel; 00103 00104 /* Loop all stack levels */ 00105 for (iLevel = 0; iLevel < GDI_STACK_LEVELS; iLevel++) 00106 { 00107 if (GDIHandleAllocator[idx1][iLevel] 00108 != GDIHandleAllocator[idx2][iLevel]) 00109 // if (GDIHandleShareLocker[idx1][iLevel] 00110 // != GDIHandleShareLocker[idx2][iLevel]) 00111 { 00112 return FALSE; 00113 } 00114 } 00115 00116 return TRUE; 00117 } 00118 00119 VOID 00120 NTAPI 00121 DbgDumpGdiHandleTable(void) 00122 { 00123 static int leak_reported = 0; 00124 int i, j, idx, nTraces = 0; 00125 KIRQL OldIrql; 00126 00127 if (leak_reported) 00128 { 00129 DPRINT1("GDI handle abusers already reported!\n"); 00130 return; 00131 } 00132 00133 leak_reported = 1; 00134 DPRINT1("Reporting GDI handle abusers:\n"); 00135 00136 /* We've got serious business to do */ 00137 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00138 00139 /* Step through GDI handle table and find out who our culprit is... */ 00140 for (idx = RESERVE_ENTRIES_COUNT; idx < GDI_HANDLE_COUNT; idx++) 00141 { 00142 /* If the handle is free, continue */ 00143 if (!IS_HANDLE_VALID(idx)) continue; 00144 00145 /* Step through all previous backtraces */ 00146 for (j = 0; j < nTraces; j++) 00147 { 00148 /* Check if the backtrace matches */ 00149 if (CompareBacktraces(idx, AllocatorTable[j].idx)) 00150 { 00151 /* It matches, increment count and break out */ 00152 AllocatorTable[j].count++; 00153 break; 00154 } 00155 } 00156 00157 /* Did we find a new backtrace? */ 00158 if (j == nTraces) 00159 { 00160 /* Break out, if we reached the maximum */ 00161 if (nTraces == MAX_BACKTRACES) break; 00162 00163 /* Initialize this entry */ 00164 AllocatorTable[j].idx = idx; 00165 AllocatorTable[j].count = 1; 00166 nTraces++; 00167 } 00168 } 00169 00170 /* bubble sort time! weeeeee!! */ 00171 for (i = 0; i < nTraces-1; i++) 00172 { 00173 if (AllocatorTable[i].count < AllocatorTable[i+1].count) 00174 { 00175 struct DbgOpenGDIHandle temp; 00176 00177 temp = AllocatorTable[i+1]; 00178 AllocatorTable[i+1] = AllocatorTable[i]; 00179 j = i; 00180 while (j > 0 && AllocatorTable[j-1].count < temp.count) 00181 j--; 00182 AllocatorTable[j] = temp; 00183 } 00184 } 00185 00186 /* Print the worst offenders... */ 00187 DbgPrint("Worst GDI Handle leak offenders (out of %i unique locations):\n", nTraces); 00188 for (i = 0; i < nTraces && AllocatorTable[i].count > 1; i++) 00189 { 00190 /* Print out the allocation count */ 00191 DbgPrint(" %i allocs, type = 0x%lx:\n", 00192 AllocatorTable[i].count, 00193 GdiHandleTable->Entries[AllocatorTable[i].idx].Type); 00194 00195 /* Dump the frames */ 00196 KeRosDumpStackFrames(GDIHandleAllocator[AllocatorTable[i].idx], GDI_STACK_LEVELS); 00197 //KeRosDumpStackFrames(GDIHandleShareLocker[AllocatorTable[i].idx], GDI_STACK_LEVELS); 00198 00199 /* Print new line for better readability */ 00200 DbgPrint("\n"); 00201 } 00202 00203 if (i < nTraces) 00204 DbgPrint("(List terminated - the remaining entries have 1 allocation only)\n"); 00205 00206 KeLowerIrql(OldIrql); 00207 00208 ASSERT(FALSE); 00209 } 00210 #endif 00211 00212 ULONG 00213 NTAPI 00214 DbgCaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture) 00215 { 00216 ULONG nFrameCount; 00217 00218 memset(pFrames, 0x00, (nFramesToCapture + 1) * sizeof(PVOID)); 00219 00220 nFrameCount = RtlWalkFrameChain(pFrames, nFramesToCapture, 0); 00221 00222 if (nFrameCount < nFramesToCapture) 00223 { 00224 nFrameCount += RtlWalkFrameChain(pFrames + nFrameCount, 00225 nFramesToCapture - nFrameCount, 00226 1); 00227 } 00228 00229 return nFrameCount; 00230 } 00231 00232 BOOL 00233 NTAPI 00234 DbgGdiHTIntegrityCheck() 00235 { 00236 ULONG i, nDeleted = 0, nFree = 0, nUsed = 0; 00237 PGDI_TABLE_ENTRY pEntry; 00238 BOOL r = 1; 00239 00240 KeEnterCriticalRegion(); 00241 00242 /* FIXME: Check reserved entries */ 00243 00244 /* Now go through the deleted objects */ 00245 i = gulFirstFree & 0xffff; 00246 while (i) 00247 { 00248 pEntry = &GdiHandleTable->Entries[i]; 00249 if (i > GDI_HANDLE_COUNT) 00250 { 00251 DPRINT1("nDeleted=%ld\n", nDeleted); 00252 ASSERT(FALSE); 00253 } 00254 00255 nDeleted++; 00256 00257 /* Check the entry */ 00258 if ((pEntry->Type & GDI_ENTRY_BASETYPE_MASK) != 0) 00259 { 00260 r = 0; 00261 DPRINT1("Deleted Entry has a type != 0\n"); 00262 } 00263 if ((ULONG_PTR)pEntry->KernelData >= GDI_HANDLE_COUNT) 00264 { 00265 r = 0; 00266 DPRINT1("Deleted entries KernelPointer too big\n"); 00267 } 00268 if (pEntry->UserData != NULL) 00269 { 00270 r = 0; 00271 DPRINT1("Deleted entry has UserData != 0\n"); 00272 } 00273 if (pEntry->ProcessId != 0) 00274 { 00275 r = 0; 00276 DPRINT1("Deleted entry has ProcessId != 0\n"); 00277 } 00278 00279 i = (ULONG_PTR)pEntry->KernelData & 0xffff; 00280 }; 00281 00282 for (i = gulFirstUnused; 00283 i < GDI_HANDLE_COUNT; 00284 i++) 00285 { 00286 pEntry = &GdiHandleTable->Entries[i]; 00287 00288 if ((pEntry->Type) != 0) 00289 { 00290 r = 0; 00291 DPRINT1("Free Entry has a type != 0\n"); 00292 } 00293 if ((ULONG_PTR)pEntry->KernelData != 0) 00294 { 00295 r = 0; 00296 DPRINT1("Free entries KernelPointer != 0\n"); 00297 } 00298 if (pEntry->UserData != NULL) 00299 { 00300 r = 0; 00301 DPRINT1("Free entry has UserData != 0\n"); 00302 } 00303 if (pEntry->ProcessId != 0) 00304 { 00305 r = 0; 00306 DPRINT1("Free entry has ProcessId != 0\n"); 00307 } 00308 nFree++; 00309 } 00310 00311 for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++) 00312 { 00313 HGDIOBJ Handle; 00314 ULONG Type; 00315 00316 pEntry = &GdiHandleTable->Entries[i]; 00317 Type = pEntry->Type; 00318 Handle = (HGDIOBJ)((Type << GDI_ENTRY_UPPER_SHIFT) + i); 00319 00320 if (Type & GDI_ENTRY_BASETYPE_MASK) 00321 { 00322 if (pEntry->KernelData == NULL) 00323 { 00324 r = 0; 00325 DPRINT1("Used entry has KernelData == 0\n"); 00326 } 00327 if (pEntry->KernelData <= MmHighestUserAddress) 00328 { 00329 r = 0; 00330 DPRINT1("Used entry invalid KernelData\n"); 00331 } 00332 if (((POBJ)(pEntry->KernelData))->hHmgr != Handle) 00333 { 00334 r = 0; 00335 DPRINT1("Used entry %ld, has invalid hHmg %p (expected: %p)\n", 00336 i, ((POBJ)(pEntry->KernelData))->hHmgr, Handle); 00337 } 00338 nUsed++; 00339 } 00340 } 00341 00342 if (RESERVE_ENTRIES_COUNT + nDeleted + nFree + nUsed != GDI_HANDLE_COUNT) 00343 { 00344 r = 0; 00345 DPRINT1("Number of all entries incorrect: RESERVE_ENTRIES_COUNT = %ld, nDeleted = %ld, nFree = %ld, nUsed = %ld\n", 00346 RESERVE_ENTRIES_COUNT, nDeleted, nFree, nUsed); 00347 } 00348 00349 KeLeaveCriticalRegion(); 00350 00351 return r; 00352 } 00353 00354 #endif /* GDI_DEBUG */ 00355 00356 VOID 00357 NTAPI 00358 DbgDumpLockedGdiHandles() 00359 { 00360 #if 0 00361 ULONG i; 00362 00363 for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++) 00364 { 00365 PENTRY pentry = &gpentHmgr[i]; 00366 00367 if (pentry->Objt) 00368 { 00369 POBJ pobj = pentry->einfo.pobj; 00370 if (pobj->cExclusiveLock > 0) 00371 { 00372 DPRINT1("Locked object: %lx, type = %lx. allocated from:\n", 00373 i, pentry->Objt); 00374 DBG_DUMP_EVENT_LIST(&pobj->slhLog); 00375 } 00376 } 00377 } 00378 #endif 00379 } 00380 00381 VOID 00382 NTAPI 00383 DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam) 00384 { 00385 PLOGENTRY pLogEntry; 00386 00387 /* Log a maximum of 100 events */ 00388 if (QueryDepthSList(pslh) >= 1000) return; 00389 00390 /* Allocate a logentry */ 00391 pLogEntry = EngAllocMem(0, sizeof(LOGENTRY), 'golG'); 00392 if (!pLogEntry) return; 00393 00394 /* Set type */ 00395 pLogEntry->nEventType = nEventType; 00396 pLogEntry->ulUnique = InterlockedIncrement((LONG*)&gulLogUnique); 00397 pLogEntry->dwProcessId = HandleToUlong(PsGetCurrentProcessId()); 00398 pLogEntry->dwThreadId = HandleToUlong(PsGetCurrentThreadId()); 00399 pLogEntry->lParam = lParam; 00400 00401 /* Capture a backtrace */ 00402 DbgCaptureStackBackTace(pLogEntry->apvBackTrace, 20); 00403 00404 switch (nEventType) 00405 { 00406 case EVENT_ALLOCATE: 00407 case EVENT_CREATE_HANDLE: 00408 case EVENT_REFERENCE: 00409 case EVENT_DEREFERENCE: 00410 case EVENT_LOCK: 00411 case EVENT_UNLOCK: 00412 case EVENT_DELETE: 00413 case EVENT_FREE: 00414 case EVENT_SET_OWNER: 00415 default: 00416 break; 00417 } 00418 00419 /* Push it on the list */ 00420 InterlockedPushEntrySList(pslh, &pLogEntry->sleLink); 00421 } 00422 00423 #define REL_ADDR(va) ((ULONG_PTR)va - (ULONG_PTR)&__ImageBase) 00424 00425 VOID 00426 DbgPrintEvent(PLOGENTRY pLogEntry) 00427 { 00428 PSTR pstr; 00429 00430 switch (pLogEntry->nEventType) 00431 { 00432 case EVENT_ALLOCATE: pstr = "Allocate"; break; 00433 case EVENT_CREATE_HANDLE: pstr = "CreatHdl"; break; 00434 case EVENT_REFERENCE: pstr = "Ref"; break; 00435 case EVENT_DEREFERENCE: pstr = "Deref"; break; 00436 case EVENT_LOCK: pstr = "Lock"; break; 00437 case EVENT_UNLOCK: pstr = "Unlock"; break; 00438 case EVENT_DELETE: pstr = "Delete"; break; 00439 case EVENT_FREE: pstr = "Free"; break; 00440 case EVENT_SET_OWNER: pstr = "SetOwner"; break; 00441 default: pstr = "Unknown"; break; 00442 } 00443 00444 DbgPrint("[%ld] %03x:%03x %.8s val=%p <%lx,%lx,%lx,%lx>\n", 00445 pLogEntry->ulUnique, 00446 pLogEntry->dwProcessId, 00447 pLogEntry->dwThreadId, 00448 pstr, 00449 pLogEntry->lParam, 00450 REL_ADDR(pLogEntry->apvBackTrace[2]), 00451 REL_ADDR(pLogEntry->apvBackTrace[3]), 00452 REL_ADDR(pLogEntry->apvBackTrace[4]), 00453 REL_ADDR(pLogEntry->apvBackTrace[5])); 00454 } 00455 00456 VOID 00457 NTAPI 00458 DbgDumpEventList(PSLIST_HEADER pslh) 00459 { 00460 PSLIST_ENTRY psle; 00461 PLOGENTRY pLogEntry; 00462 00463 while ((psle = InterlockedPopEntrySList(pslh))) 00464 { 00465 pLogEntry = CONTAINING_RECORD(psle, LOGENTRY, sleLink); 00466 DbgPrintEvent(pLogEntry); 00467 } 00468 00469 } 00470 00471 VOID 00472 NTAPI 00473 DbgCleanupEventList(PSLIST_HEADER pslh) 00474 { 00475 PSLIST_ENTRY psle; 00476 PLOGENTRY pLogEntry; 00477 00478 while ((psle = InterlockedPopEntrySList(pslh))) 00479 { 00480 pLogEntry = CONTAINING_RECORD(psle, LOGENTRY, sleLink); 00481 EngFreeMem(pLogEntry); 00482 } 00483 } 00484 00485 void 00486 NTAPI 00487 GdiDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments) 00488 { 00489 PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread(); 00490 if (pti && pti->cExclusiveLocks != 0) 00491 { 00492 DbgPrint("FATAL: Win32DbgPreServiceHook(0x%lx): There are %ld exclusive locks!\n", 00493 ulSyscallId, pti->cExclusiveLocks); 00494 DbgDumpLockedGdiHandles(); 00495 ASSERT(FALSE); 00496 } 00497 00498 } 00499 00500 ULONG_PTR 00501 NTAPI 00502 GdiDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) 00503 { 00504 PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread(); 00505 if (pti && pti->cExclusiveLocks != 0) 00506 { 00507 DbgPrint("FATAL: Win32DbgPostServiceHook(0x%lx): There are %ld exclusive locks!\n", 00508 ulSyscallId, pti->cExclusiveLocks); 00509 DbgDumpLockedGdiHandles(); 00510 ASSERT(FALSE); 00511 } 00512 return ulResult; 00513 } 00514 00515 NTSTATUS NTAPI 00516 QueryEnvironmentVariable(PUNICODE_STRING Name, 00517 PUNICODE_STRING Value) 00518 { 00519 NTSTATUS Status; 00520 PWSTR wcs; 00521 UNICODE_STRING var; 00522 PWSTR val; 00523 PPEB Peb; 00524 PWSTR Environment; 00525 00526 /* Ugly HACK for ReactOS system threads */ 00527 if(!NtCurrentTeb()) 00528 { 00529 return(STATUS_VARIABLE_NOT_FOUND); 00530 } 00531 00532 Peb = NtCurrentPeb(); 00533 00534 if (Peb == NULL) 00535 { 00536 return(STATUS_VARIABLE_NOT_FOUND); 00537 } 00538 00539 Environment = Peb->ProcessParameters->Environment; 00540 00541 if (Environment == NULL) 00542 { 00543 return(STATUS_VARIABLE_NOT_FOUND); 00544 } 00545 00546 Value->Length = 0; 00547 00548 wcs = Environment; 00549 while (*wcs) 00550 { 00551 var.Buffer = wcs++; 00552 wcs = wcschr(wcs, L'='); 00553 if (wcs == NULL) 00554 { 00555 wcs = var.Buffer + wcslen(var.Buffer); 00556 } 00557 if (*wcs) 00558 { 00559 var.Length = var.MaximumLength = (wcs - var.Buffer) * sizeof(WCHAR); 00560 val = ++wcs; 00561 wcs += wcslen(wcs); 00562 00563 if (RtlEqualUnicodeString(&var, Name, TRUE)) 00564 { 00565 Value->Length = (wcs - val) * sizeof(WCHAR); 00566 if (Value->Length <= Value->MaximumLength) 00567 { 00568 memcpy(Value->Buffer, val, 00569 min(Value->Length + sizeof(WCHAR), Value->MaximumLength)); 00570 Status = STATUS_SUCCESS; 00571 } 00572 else 00573 { 00574 Status = STATUS_BUFFER_TOO_SMALL; 00575 } 00576 00577 return(Status); 00578 } 00579 } 00580 wcs++; 00581 } 00582 00583 return(STATUS_VARIABLE_NOT_FOUND); 00584 } 00585 00586 static int 00587 DbgCompareChannels(const void * a, const void * b) 00588 { 00589 return wcscmp((WCHAR*)a, ((DBG_CHANNEL*)b)->Name); 00590 } 00591 00592 static BOOL 00593 DbgAddDebugChannel(PPROCESSINFO ppi, WCHAR* channel, WCHAR* level, WCHAR op) 00594 { 00595 DBG_CHANNEL *ChannelEntry; 00596 UINT iLevel, iChannel; 00597 00598 ChannelEntry = (DBG_CHANNEL*)bsearch(channel, 00599 DbgChannels, 00600 DbgChCount, 00601 sizeof(DBG_CHANNEL), 00602 DbgCompareChannels); 00603 if(ChannelEntry == NULL) 00604 { 00605 return FALSE; 00606 } 00607 00608 iChannel = ChannelEntry->Id; 00609 ASSERT(iChannel >= 0 && iChannel < DbgChCount); 00610 00611 if(level == NULL || *level == L'\0' ||wcslen(level) == 0 ) 00612 iLevel = MAX_LEVEL; 00613 else if(wcsncmp(level, L"err", 3) == 0) 00614 iLevel = ERR_LEVEL; 00615 else if(wcsncmp(level, L"fixme", 5) == 0) 00616 iLevel = FIXME_LEVEL; 00617 else if(wcsncmp(level, L"warn", 4) == 0) 00618 iLevel = WARN_LEVEL; 00619 else if (wcsncmp(level, L"trace", 4) == 0) 00620 iLevel = TRACE_LEVEL; 00621 else 00622 return FALSE; 00623 00624 if(op==L'+') 00625 { 00626 DBG_ENABLE_CHANNEL(ppi, iChannel, iLevel); 00627 } 00628 else 00629 { 00630 DBG_DISABLE_CHANNEL(ppi, iChannel, iLevel); 00631 } 00632 00633 return TRUE; 00634 } 00635 00636 static BOOL 00637 DbgParseDebugChannels(PPROCESSINFO ppi, PUNICODE_STRING Value) 00638 { 00639 WCHAR *str, *separator, *c, op; 00640 00641 str = Value->Buffer; 00642 00643 do 00644 { 00645 separator = wcschr(str, L','); 00646 if(separator != NULL) 00647 *separator = L'\0'; 00648 00649 c = wcschr(str, L'+'); 00650 if(c == NULL) 00651 c = wcschr(str, L'-'); 00652 00653 if(c != NULL) 00654 { 00655 op = *c; 00656 *c = L'\0'; 00657 c++; 00658 00659 DbgAddDebugChannel(ppi, c, str, op); 00660 } 00661 00662 str = separator + 1; 00663 }while(separator != NULL); 00664 00665 return TRUE; 00666 } 00667 00668 BOOL DbgInitDebugChannels() 00669 { 00670 WCHAR valBuffer[100]; 00671 UNICODE_STRING Value; 00672 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"DEBUGCHANNEL"); 00673 NTSTATUS Status; 00674 PPROCESSINFO ppi; 00675 BOOL ret; 00676 00677 /* Initialize all channels to ERROR */ 00678 ppi = PsGetCurrentProcessWin32Process(); 00679 RtlFillMemory( ppi->DbgChannelLevel, 00680 sizeof(ppi->DbgChannelLevel), 00681 ERR_LEVEL); 00682 00683 /* Find DEBUGCHANNEL env var */ 00684 Value.Buffer = valBuffer; 00685 Value.Length = 0; 00686 Value.MaximumLength = sizeof(valBuffer); 00687 Status = QueryEnvironmentVariable(&Name, &Value); 00688 00689 /* It does not exist */ 00690 if(Status == STATUS_VARIABLE_NOT_FOUND) 00691 { 00692 /* There is nothing more to do */ 00693 return TRUE; 00694 } 00695 00696 /* If the buffer in the stack is not enough allocate it */ 00697 if(Status == STATUS_BUFFER_TOO_SMALL) 00698 { 00699 Value.Buffer = ExAllocatePool(PagedPool, Value.MaximumLength); 00700 if(Value.Buffer == NULL) 00701 { 00702 return FALSE; 00703 } 00704 00705 /* Get the env var again */ 00706 Status = QueryEnvironmentVariable(&Name, &Value); 00707 } 00708 00709 /* Check for error */ 00710 if(!NT_SUCCESS(Status)) 00711 { 00712 if(Value.Buffer != valBuffer) 00713 { 00714 ExFreePool(Value.Buffer); 00715 } 00716 00717 return FALSE; 00718 } 00719 00720 /* Parse the variable */ 00721 ret = DbgParseDebugChannels(ppi, &Value); 00722 00723 /* Clean up */ 00724 if(Value.Buffer != valBuffer) 00725 { 00726 ExFreePool(Value.Buffer); 00727 } 00728 00729 return ret; 00730 } 00731 00732 #endif 00733 00734 /* EOF */ Generated on Sun May 27 2012 04:38:26 for ReactOS by
1.7.6.1
|