ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

gdidbg.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.