00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
#include "precomp.h"
00013 
#pragma hdrstop
00014 
00015 BOOL gdwPoolFlags;
00016 
00017 
#ifdef POOL_INSTR
00018 
    
00019     
00020 
00021 
00022     
00023     PVOID     gRecordedStackTrace[
RECORD_STACK_TRACE_SIZE];
00024     
PEPROCESS gpepRecorded;
00025     
PETHREAD  gpetRecorded;
00026 
00027 
00028     
DWORD gdwAllocFailIndex;        
00029                                     
00030 
00031     
DWORD gdwAllocsToFail = 1;      
00032 
00033     
DWORD gdwFreeRecords;
00034     
00035     
00036 
00037 
00038     LPDWORD gparrTagsToFail;
00039     SIZE_T  gdwTagsToFailCount;
00040 
00041     
00042 
00043 
00044     
DWORD gdwFailRecords;
00045     
DWORD gdwFailRecordCrtIndex;
00046     
DWORD gdwFailRecordTotalFailures;
00047 
00048     
PPOOLRECORD gparrFailRecord;
00049     
00050     
00051 
00052 
00053     
DWORD gdwFreeRecords;
00054     
DWORD gdwFreeRecordCrtIndex;
00055     
DWORD gdwFreeRecordTotalFrees;
00056 
00057     
PPOOLRECORD gparrFreeRecord;
00058 
00059     
FAST_MUTEX* gpAllocFastMutex;   
00060 
00061     
Win32AllocStats gAllocList;
00062 
00063     
char gszTailAlloc[] = 
"Win32kAlloc";
00064 
#endif // POOL_INSTR
00065 
00066 
00067 
00068 PVOID 
Win32AllocPoolWithTagZInit(SIZE_T uBytes, ULONG uTag)
00069 {
00070     PVOID   pv;
00071     
00072     pv = Win32AllocPool(uBytes, uTag);
00073     
if (pv) {
00074         RtlZeroMemory(pv, uBytes);
00075     }
00076 
00077     
return pv;
00078 }
00079 
00080 PVOID 
Win32AllocPoolWithQuotaTagZInit(SIZE_T uBytes, ULONG uTag)
00081 {
00082     PVOID   pv;
00083     
00084     pv = Win32AllocPoolWithQuota(uBytes, uTag);
00085     
if (pv) {
00086         RtlZeroMemory(pv, uBytes);
00087     }
00088 
00089     
return pv;
00090 }
00091 
00092 PVOID 
UserReAllocPoolWithTag(
00093     PVOID pSrc,
00094     SIZE_T uBytesSrc,
00095     SIZE_T uBytes,
00096     ULONG iTag)
00097 {
00098     PVOID pDest;
00099 
00100     pDest = UserAllocPool(uBytes, iTag);
00101     
if (pDest != 
NULL) {
00102 
00103         
00104 
00105 
00106         
if (uBytesSrc > uBytes) {
00107             uBytesSrc = uBytes;
00108         }
00109 
00110         RtlCopyMemory(pDest, pSrc, uBytesSrc);
00111 
00112         UserFreePool(pSrc);
00113     }
00114 
00115     
return pDest;
00116 }
00117 
00118 PVOID 
UserReAllocPoolWithQuotaTag(
00119     PVOID pSrc,
00120     SIZE_T uBytesSrc,
00121     SIZE_T uBytes,
00122     ULONG iTag)
00123 {
00124     PVOID pDest;
00125 
00126     pDest = UserAllocPoolWithQuota(uBytes, iTag);
00127     
if (pDest != 
NULL) {
00128 
00129         
00130 
00131 
00132         
if (uBytesSrc > uBytes)
00133             uBytesSrc = uBytes;
00134 
00135         RtlCopyMemory(pDest, pSrc, uBytesSrc);
00136 
00137         UserFreePool(pSrc);
00138     }
00139 
00140     
return pDest;
00141 }
00142 
00143 
00144 
00145 
00146 
00147 PVOID 
UserRtlAllocMem(
00148     SIZE_T uBytes)
00149 {
00150     
return UserAllocPool(uBytes, TAG_RTL);
00151 }
00152 
00153 VOID UserRtlFreeMem(
00154     PVOID pMem)
00155 {
00156     UserFreePool(pMem);
00157 }
00158 
00159 
#ifdef POOL_INSTR
00160 
00161 
void RecordStackTrace(
void)
00162 {
00163     ULONG hash;
00164 
00165     RtlZeroMemory(gRecordedStackTrace, RECORD_STACK_TRACE_SIZE * 
sizeof(PVOID));
00166 
00167     GetStackTrace(2,
00168                   RECORD_STACK_TRACE_SIZE,
00169                   gRecordedStackTrace,
00170                   &hash);
00171 
00172     gpepRecorded = 
PsGetCurrentProcess();
00173     gpetRecorded = 
PsGetCurrentThread();
00174 }
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
void RecordFailAllocation(
00184     ULONG  tag,
00185     SIZE_T size)
00186 {
00187     ULONG hash;
00188 
00189     UserAssert(gdwPoolFlags & POOL_KEEP_FAIL_RECORD);
00190     
00191     gparrFailRecord[gdwFailRecordCrtIndex].
ExtraData = LongToPtr( tag );
00192     gparrFailRecord[gdwFailRecordCrtIndex].
size = size;
00193     
00194     gdwFailRecordTotalFailures++;
00195     
00196     RtlZeroMemory(gparrFailRecord[gdwFailRecordCrtIndex].trace,
00197                   RECORD_STACK_TRACE_SIZE * 
sizeof(PVOID));
00198 
00199     GetStackTrace(2,
00200                   RECORD_STACK_TRACE_SIZE,
00201                   gparrFailRecord[gdwFailRecordCrtIndex].trace,
00202                   &hash);
00203     
00204     gdwFailRecordCrtIndex++;
00205     
00206     
if (gdwFailRecordCrtIndex >= gdwFailRecords) {
00207         gdwFailRecordCrtIndex = 0;
00208     }
00209 }
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
void RecordFreePool(
00219     PVOID  p,
00220     SIZE_T size)
00221 {
00222     ULONG hash;
00223 
00224     UserAssert(gdwPoolFlags & POOL_KEEP_FREE_RECORD);
00225     
00226     gparrFreeRecord[gdwFreeRecordCrtIndex].
ExtraData = p;
00227     gparrFreeRecord[gdwFreeRecordCrtIndex].
size = size;
00228     
00229     gdwFreeRecordTotalFrees++;
00230     
00231     RtlZeroMemory(gparrFreeRecord[gdwFreeRecordCrtIndex].trace,
00232                   RECORD_STACK_TRACE_SIZE * 
sizeof(PVOID));
00233 
00234     GetStackTrace(2,
00235                   RECORD_STACK_TRACE_SIZE,
00236                   gparrFreeRecord[gdwFreeRecordCrtIndex].trace,
00237                   &hash);
00238     
00239     gdwFreeRecordCrtIndex++;
00240     
00241     
if (gdwFreeRecordCrtIndex >= gdwFreeRecords) {
00242         gdwFreeRecordCrtIndex = 0;
00243     }
00244 }
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 PVOID HeavyAllocPool(
00255     SIZE_T uBytes,
00256     ULONG  tag,
00257     DWORD  dwFlags)
00258 {
00259     
DWORD*         p;
00260     PWin32PoolHead ph;
00261 
00262     
00263 
00264 
00265 
00266     
if (!(
gdwPoolFlags & 
POOL_HEAVY_ALLOCS)) {
00267         
if (
dwFlags & DAP_USEQUOTA) {
00268             
if (
dwFlags & DAP_NONPAGEDPOOL) {
00269                 p = 
ExAllocatePoolWithQuotaTag(SESSION_POOL_MASK | NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
00270                                                uBytes,
00271                                                tag);
00272             } 
else {
00273                 p = 
ExAllocatePoolWithQuotaTag(
00274                                        SESSION_POOL_MASK | PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
00275                                        uBytes,
00276                                        tag);
00277             }
00278         } 
else {
00279             
if (
dwFlags & DAP_NONPAGEDPOOL) {
00280                 p = 
ExAllocatePoolWithTag(SESSION_POOL_MASK | NonPagedPool, uBytes, tag);
00281             } 
else {
00282                 p = 
ExAllocatePoolWithTag(SESSION_POOL_MASK | PagedPool, uBytes, tag);
00283             }
00284         }
00285         
00286         
if (p != 
NULL && (
dwFlags & DAP_ZEROINIT)) {
00287             RtlZeroMemory(p, uBytes);
00288         }
00289         
00290         
return p; 
00291     }
00292     
00293     
00294 
00295 
00296     
if (uBytes >= MAXULONG - 
sizeof(Win32PoolHead) - 
sizeof(gszTailAlloc)) {
00297         
00298         
if (
gdwPoolFlags & 
POOL_KEEP_FAIL_RECORD) {
00299             RecordFailAllocation(tag, 0);
00300         }
00301         
return NULL;
00302     }
00303 
00304     
00305 
00306 
00307     
KeEnterCriticalRegion();
00308     
ExAcquireFastMutexUnsafe(gpAllocFastMutex);
00309     
00310 
#ifdef POOL_INSTR_API
00311 
    
00312 
00313 
00314 
00315     
if (
gdwPoolFlags & 
POOL_FAIL_ALLOCS
00316 
#if DBG
00317 
        && (tag != TAG_GLOBALTHREADLOCK)
00318 
#endif // DBG
00319 
        ) {
00320         
00321 
00322         SIZE_T dwInd;
00323 
00324         
for (dwInd = 0; dwInd < gdwTagsToFailCount; dwInd++) {
00325             
if (tag == gparrTagsToFail[dwInd]) {
00326                 
break;
00327             }
00328         }
00329         
00330         
if (dwInd < gdwTagsToFailCount) {
00331             
if (
gdwPoolFlags & 
POOL_KEEP_FAIL_RECORD) {
00332                 RecordFailAllocation(tag, uBytes);
00333             }
00334 
00335             RIPMSG0(RIP_WARNING, 
"Pool allocation failed because of global restriction");
00336             p = 
NULL;
00337             
goto exit;
00338         }
00339     }
00340 
#endif // POOL_INSTR_API
00341 
00342 
#if DBG
00343 
    if ((
gdwPoolFlags & 
POOL_FAIL_BY_INDEX) && (tag != TAG_GLOBALTHREADLOCK)) {
00344         
00345         
00346 
00347 
00348         gdwAllocCrt++;
00349 
00350         
if (gdwAllocCrt >= gdwAllocFailIndex &&
00351             gdwAllocCrt < gdwAllocFailIndex + gdwAllocsToFail) {
00352 
00353             RecordStackTrace();
00354 
00355             KdPrint((
"\n--------------------------------------------------\n"));
00356             KdPrint((
00357                     
"\nPool allocation %d failed because of registry settings",
00358                     gdwAllocCrt));
00359             KdPrint((
"\n--------------------------------------------------\n\n"));
00360 
00361             
if (
gdwPoolFlags & 
POOL_KEEP_FAIL_RECORD) {
00362                 RecordFailAllocation(tag, uBytes);
00363             }
00364             p = 
NULL;
00365             
goto exit;
00366         }
00367     }
00368 
#endif // DBG
00369 
    
00370     
00371 
00372 
00373     uBytes += 
sizeof(Win32PoolHead);
00374 
00375     
if (
gdwPoolFlags & 
POOL_TAIL_CHECK) {
00376         uBytes += 
sizeof(gszTailAlloc);
00377     }
00378     
00379     
if (
dwFlags & DAP_USEQUOTA) {
00380         
if (
dwFlags & DAP_NONPAGEDPOOL) {
00381             p = 
ExAllocatePoolWithQuotaTag(SESSION_POOL_MASK | NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
00382                                            uBytes,
00383                                            tag);
00384         } 
else {
00385             p = 
ExAllocatePoolWithQuotaTag(
00386                                    SESSION_POOL_MASK | PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
00387                                    uBytes,
00388                                    tag);
00389         }
00390     } 
else {
00391         
if (
dwFlags & DAP_NONPAGEDPOOL) {
00392             p = 
ExAllocatePoolWithTag(SESSION_POOL_MASK | NonPagedPool, uBytes, tag);
00393         } 
else {
00394             p = 
ExAllocatePoolWithTag(SESSION_POOL_MASK | PagedPool, uBytes, tag);
00395         }
00396     }
00397 
00398     
00399 
00400 
00401     
if (p == 
NULL) {
00402         
00403         
if (
gdwPoolFlags & 
POOL_KEEP_FAIL_RECORD) {
00404             
00405             uBytes -= 
sizeof(Win32PoolHead);
00406 
00407             
if (
gdwPoolFlags & 
POOL_TAIL_CHECK) {
00408                 uBytes -= 
sizeof(gszTailAlloc);
00409             }
00410             
00411             RecordFailAllocation(tag, uBytes);
00412         }
00413         
00414         
goto exit;
00415     }
00416 
00417     uBytes -= 
sizeof(Win32PoolHead);
00418 
00419     
if (
gdwPoolFlags & 
POOL_TAIL_CHECK) {
00420         uBytes -= 
sizeof(gszTailAlloc);
00421         
00422         RtlCopyMemory(((BYTE*)p) + uBytes, gszTailAlloc, 
sizeof(gszTailAlloc));
00423     }
00424 
00425     
00426 
00427 
00428     ph = (PWin32PoolHead)p;
00429 
00430     p += (
sizeof(Win32PoolHead) / 
sizeof(
DWORD));
00431 
00432     
00433 
00434 
00435     gAllocList.
dwCrtMem += uBytes;
00436 
00437     
if (gAllocList.
dwMaxMem < gAllocList.
dwCrtMem) {
00438         gAllocList.
dwMaxMem = gAllocList.
dwCrtMem;
00439     }
00440 
00441     (gAllocList.
dwCrtAlloc)++;
00442 
00443     
if (gAllocList.
dwMaxAlloc < gAllocList.
dwCrtAlloc) {
00444         gAllocList.
dwMaxAlloc = gAllocList.
dwCrtAlloc;
00445     }
00446 
00447     
00448 
00449 
00450     
if (
gdwPoolFlags & 
POOL_CAPTURE_STACK) {
00451         ph->pTrace = 
ExAllocatePoolWithTag(SESSION_POOL_MASK | PagedPool,
00452                                            POOL_ALLOC_TRACE_SIZE * 
sizeof(PVOID),
00453                                            TAG_STACK);
00454         
00455         
if (ph->pTrace != 
NULL) {
00456             
00457             ULONG hash;
00458             
00459             RtlZeroMemory(ph->pTrace, POOL_ALLOC_TRACE_SIZE * 
sizeof(PVOID));
00460 
00461             GetStackTrace(1,
00462                           POOL_ALLOC_TRACE_SIZE,
00463                           ph->pTrace,
00464                           &hash);
00465         }
00466     } 
else {
00467         ph->pTrace = 
NULL;
00468     }
00469 
00470     
00471 
00472 
00473     ph->size = uBytes;
00474 
00475     
00476 
00477 
00478     ph->pPrev = 
NULL;
00479     ph->pNext = gAllocList.
pHead;
00480 
00481     
if (gAllocList.
pHead != 
NULL)
00482         gAllocList.
pHead->pPrev = ph;
00483 
00484     gAllocList.
pHead = ph;
00485 
00486     
if (
dwFlags & DAP_ZEROINIT) {
00487         RtlZeroMemory(p, uBytes);
00488     }
00489 
00490 
exit:
00491     
00492 
00493 
00494     
ExReleaseFastMutexUnsafe(gpAllocFastMutex);
00495     
KeLeaveCriticalRegion();
00496     
00497     
return p;
00498 }
00499 
00500 
00501 
00502 
00503 
00504 
00505 
void HeavyFreePool(
00506     PVOID p)
00507 {
00508     SIZE_T         uBytes;
00509     PWin32PoolHead ph;
00510 
00511     
00512 
00513 
00514 
00515     
if (!(
gdwPoolFlags & 
POOL_HEAVY_ALLOCS)) {
00516         
ExFreePool(p);
00517         
return;
00518     }
00519     
00520     
00521 
00522 
00523     
KeEnterCriticalRegion();
00524     
ExAcquireFastMutexUnsafe(gpAllocFastMutex);
00525     
00526     ph = (PWin32PoolHead)((
DWORD*)p - (
sizeof(Win32PoolHead) / 
sizeof(
DWORD)));
00527 
00528     uBytes = ph->size;
00529 
00530     
00531 
00532 
00533     
if (
gdwPoolFlags & 
POOL_TAIL_CHECK) {
00534         
if (!RtlEqualMemory((BYTE*)p + uBytes, gszTailAlloc, 
sizeof(gszTailAlloc))) {
00535             RIPMSG1(RIP_ERROR, 
"POOL CORRUPTION for %#p", p);
00536         }
00537     }
00538 
00539     gAllocList.
dwCrtMem -= uBytes;
00540 
00541     UserAssert(gAllocList.
dwCrtAlloc > 0);
00542 
00543     (gAllocList.
dwCrtAlloc)--;
00544 
00545     
00546 
00547 
00548     
if (ph->pPrev == 
NULL) {
00549         
if (ph->pNext == 
NULL) {
00550 
00551             UserAssert(gAllocList.
dwCrtAlloc == 0);
00552 
00553             gAllocList.
pHead = 
NULL;
00554         } 
else {
00555             ph->pNext->pPrev = 
NULL;
00556             gAllocList.
pHead = ph->pNext;
00557         }
00558     } 
else {
00559         ph->pPrev->pNext = ph->pNext;
00560         
if (ph->pNext != 
NULL) {
00561             ph->pNext->pPrev = ph->pPrev;
00562         }
00563     }
00564     
00565     
00566 
00567 
00568     
if (ph->pTrace != 
NULL) {
00569         
ExFreePool(ph->pTrace);
00570     }
00571 
00572     
if (
gdwPoolFlags & 
POOL_KEEP_FREE_RECORD) {
00573         RecordFreePool(ph, ph->size);
00574     }
00575     
00576     
ExFreePool(ph);
00577     
00578     
00579 
00580 
00581     
ExReleaseFastMutexUnsafe(gpAllocFastMutex);
00582     
KeLeaveCriticalRegion();
00583 }
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
void CleanupPoolAllocations(
00592     
void)
00593 {
00594     PWin32PoolHead pHead;
00595     PWin32PoolHead pNext;
00596 
00597     
if (gAllocList.
dwCrtAlloc != 0) {
00598         
00599         
if ((
gdwPoolFlags & 
POOL_BREAK_FOR_LEAKS) &&
00600             **((PBOOLEAN*)&
KdDebuggerEnabled)) {
00601 
00602             
00603 
00604 
00605 
00606 
            #undef DbgPrint
00607 
            DbgPrint(
"\n------------------------\n"
00608                      
"There is still pool memory not freed in win32k.sys !!!\n"
00609                      
"Use !dpa -vs to dump it\n"
00610                      
"-------------------------\n");
00611             DbgBreakPoint();
00612         }
00613         
00614         pHead = gAllocList.
pHead;
00615 
00616         
while (pHead != 
NULL) {
00617 
00618             pNext = pHead->pNext;
00619 
00620             UserFreePool(pHead + 1);
00621 
00622             pHead = pNext;
00623         }
00624     }
00625 }
00626 
00627 
00628 
00629 
00630 
00631 
void CleanUpPoolLimitations(
void)
00632 {
00633     
if (gpAllocFastMutex != 
NULL) {
00634         
ExFreePool(gpAllocFastMutex);
00635         gpAllocFastMutex = 
NULL;
00636     }
00637     
00638     
if (gparrFailRecord != 
NULL) {
00639         
ExFreePool(gparrFailRecord);
00640         gparrFailRecord = 
NULL;
00641     }
00642     
00643     
if (gparrFreeRecord != 
NULL) {
00644         
ExFreePool(gparrFreeRecord);
00645         gparrFreeRecord = 
NULL;
00646     }
00647 
00648     
if (gparrTagsToFail != 
NULL) {
00649         
ExFreePool(gparrTagsToFail);
00650         gparrTagsToFail = 
NULL;
00651     }
00652     
00653 }
00654 
00655 
00656 
00657 
00658 
00659 
00660 
void InitPoolLimitations(
void)
00661 {
00662     UNICODE_STRING      UnicodeString;
00663     OBJECT_ATTRIBUTES   
ObjectAttributes;
00664     HANDLE              hkey;
00665     
NTSTATUS            Status;
00666     WCHAR               achKeyName[512];
00667     WCHAR               achKeyValue[512];
00668     
DWORD               dwData;
00669     ULONG               ucb;
00670     
00671     
00672 
00673 
00674 
00675     gpAllocFastMutex = 
ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
00676                                              
sizeof(
FAST_MUTEX),
00677                                              TAG_DEBUG);
00678 
00679     UserAssert(gpAllocFastMutex != NULL);
00680 
00681     
ExInitializeFastMutex(gpAllocFastMutex);
00682 
00683     
00684 
00685 
00686     
if (
gbRemoteSession) {
00687         
gdwPoolFlags = 
POOL_HEAVY_ALLOCS;
00688 
00689 
#if DBG
00690 
        gdwPoolFlags |= (
POOL_CAPTURE_STACK | 
POOL_BREAK_FOR_LEAKS);
00691 
#endif // DBG
00692 
    }
00693     
00694     
00695 
00696 
00697     
RtlInitUnicodeString(
00698             &UnicodeString,
00699             L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\SubSystems\\Pool");
00700 
00701     InitializeObjectAttributes(
00702             &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
00703 
00704     
Status = ZwOpenKey(&hkey, KEY_READ, &ObjectAttributes);
00705     
if (!
NT_SUCCESS(Status)) {
00706         
00707 
#if DBG
00708 
        
00709 
00710 
00711         
if (
gbRemoteSession) {
00712 
00713             gparrFailRecord = 
ExAllocatePoolWithTag(PagedPool,
00714                                                     32 * 
sizeof(
POOLRECORD),
00715                                                     TAG_DEBUG);
00716 
00717             
if (gparrFailRecord != 
NULL) {
00718                 gdwFailRecords = 32;
00719                 
gdwPoolFlags |= 
POOL_KEEP_FAIL_RECORD;
00720             }
00721             
00722             gparrFreeRecord = 
ExAllocatePoolWithTag(PagedPool,
00723                                                     32 * 
sizeof(
POOLRECORD),
00724                                                     TAG_DEBUG);
00725 
00726             
if (gparrFreeRecord != 
NULL) {
00727                 gdwFreeRecords = 32;
00728                 
gdwPoolFlags |= 
POOL_KEEP_FREE_RECORD;
00729             }
00730         }
00731 
#endif // DBG
00732 
        
00733         
return;
00734     }
00735 
00736     
if (
gbRemoteSession) {
00737         
00738         
00739 
00740 
00741         
RtlInitUnicodeString(&UnicodeString, L
"BreakForPoolLeaks");
00742 
00743         
Status = ZwQueryValueKey(
00744                 hkey,
00745                 &UnicodeString,
00746                 KeyValuePartialInformation,
00747                 &achKeyValue,
00748                 
sizeof(achKeyValue),
00749                 &ucb);
00750 
00751         
if (
NT_SUCCESS(Status) &&
00752                 ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00753 
00754             dwData = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00755 
00756             
if (dwData != 0) {
00757                 
gdwPoolFlags |= 
POOL_BREAK_FOR_LEAKS;
00758             } 
else {
00759                 
gdwPoolFlags &= ~
POOL_BREAK_FOR_LEAKS;
00760             }
00761         }
00762         
00763         
00764 
00765 
00766         
RtlInitUnicodeString(&UnicodeString, L
"HeavyRemoteSession");
00767 
00768         
Status = ZwQueryValueKey(
00769                 hkey,
00770                 &UnicodeString,
00771                 KeyValuePartialInformation,
00772                 &achKeyValue,
00773                 
sizeof(achKeyValue),
00774                 &ucb);
00775 
00776         
if (
NT_SUCCESS(Status) &&
00777                 ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00778 
00779             dwData = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00780 
00781             
if (dwData == 0) {
00782                 
gdwPoolFlags &= ~
POOL_HEAVY_ALLOCS;
00783             }
00784         }
00785     } 
else {
00786         
00787         
00788 
00789 
00790         
RtlInitUnicodeString(&UnicodeString, L
"HeavyConsoleSession");
00791 
00792         
Status = ZwQueryValueKey(
00793                 hkey,
00794                 &UnicodeString,
00795                 KeyValuePartialInformation,
00796                 &achKeyValue,
00797                 
sizeof(achKeyValue),
00798                 &ucb);
00799 
00800         
if (
NT_SUCCESS(Status) &&
00801                 ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00802 
00803             dwData = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00804 
00805             
if (dwData != 0) {
00806                 
gdwPoolFlags |= 
POOL_HEAVY_ALLOCS;
00807             }
00808         }
00809     }
00810     
00811     
if (!(
gdwPoolFlags & 
POOL_HEAVY_ALLOCS)) {
00812         ZwClose(hkey);
00813         
return;
00814     }
00815     
00816     
00817 
00818 
00819     
RtlInitUnicodeString(&UnicodeString, L
"StackTraces");
00820 
00821     RtlZeroMemory(achKeyName, 
sizeof(achKeyName));
00822 
00823     
Status = ZwQueryValueKey(
00824             hkey,
00825             &UnicodeString,
00826             KeyValuePartialInformation,
00827             &achKeyValue,
00828             
sizeof(achKeyValue),
00829             &ucb);
00830 
00831     
if (
NT_SUCCESS(Status) &&
00832             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00833 
00834         dwData = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00835 
00836         
if (dwData == 0) {
00837             
gdwPoolFlags &= ~
POOL_CAPTURE_STACK;
00838         } 
else {
00839             
gdwPoolFlags |= 
POOL_CAPTURE_STACK;
00840         }
00841     }
00842 
00843     
00844 
00845 
00846     
RtlInitUnicodeString(&UnicodeString, L
"UseTailString");
00847 
00848     
Status = ZwQueryValueKey(
00849             hkey,
00850             &UnicodeString,
00851             KeyValuePartialInformation,
00852             &achKeyValue,
00853             
sizeof(achKeyValue),
00854             &ucb);
00855 
00856     
if (
NT_SUCCESS(Status) &&
00857             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00858 
00859         dwData = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00860 
00861         
if (dwData != 0) {
00862             
gdwPoolFlags |= 
POOL_TAIL_CHECK;
00863         }
00864     }
00865     
00866     
00867 
00868 
00869 
#if DBG
00870 
    gdwFreeRecords = 32;
00871 
#endif // DBG
00872 
00873     
RtlInitUnicodeString(&UnicodeString, L
"KeepFreeRecords");
00874 
00875     
Status = ZwQueryValueKey(
00876             hkey,
00877             &UnicodeString,
00878             KeyValuePartialInformation,
00879             &achKeyValue,
00880             
sizeof(achKeyValue),
00881             &ucb);
00882 
00883     
if (
NT_SUCCESS(Status) &&
00884             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00885 
00886         gdwFreeRecords = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00887     }
00888     
00889     
if (gdwFreeRecords != 0) {
00890 
00891         gparrFreeRecord = 
ExAllocatePoolWithTag(PagedPool,
00892                                                 gdwFreeRecords * 
sizeof(
POOLRECORD),
00893                                                 TAG_DEBUG);
00894 
00895         
if (gparrFreeRecord != 
NULL) {
00896             
gdwPoolFlags |= 
POOL_KEEP_FREE_RECORD;
00897         }
00898     }
00899 
00900     
00901 
00902 
00903 
#if DBG
00904 
    gdwFailRecords = 32;
00905 
#endif // DBG
00906 
00907     
RtlInitUnicodeString(&UnicodeString, L
"KeepFailRecords");
00908 
00909     
Status = ZwQueryValueKey(
00910             hkey,
00911             &UnicodeString,
00912             KeyValuePartialInformation,
00913             &achKeyValue,
00914             
sizeof(achKeyValue),
00915             &ucb);
00916 
00917     
if (
NT_SUCCESS(Status) &&
00918             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00919 
00920         gdwFailRecords = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00921     }
00922     
00923     
if (gdwFailRecords != 0) {
00924 
00925         gparrFailRecord = 
ExAllocatePoolWithTag(PagedPool,
00926                                                 gdwFailRecords * 
sizeof(
POOLRECORD),
00927                                                 TAG_DEBUG);
00928 
00929         
if (gparrFailRecord != 
NULL) {
00930             
gdwPoolFlags |= 
POOL_KEEP_FAIL_RECORD;
00931         }
00932     }
00933 
00934 
#if DBG
00935 
    
00936 
00937 
00938     
RtlInitUnicodeString(&UnicodeString, L
"AllocationIndex");
00939 
00940     
Status = ZwQueryValueKey(
00941             hkey,
00942             &UnicodeString,
00943             KeyValuePartialInformation,
00944             &achKeyValue,
00945             
sizeof(achKeyValue),
00946             &ucb);
00947 
00948     
if (
NT_SUCCESS(Status) &&
00949             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00950 
00951         gdwAllocFailIndex = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00952     }
00953 
00954 
00955     
RtlInitUnicodeString(&UnicodeString, L
"AllocationsToFail");
00956 
00957     
Status = ZwQueryValueKey(
00958             hkey,
00959             &UnicodeString,
00960             KeyValuePartialInformation,
00961             &achKeyValue,
00962             
sizeof(achKeyValue),
00963             &ucb);
00964 
00965     
if (
NT_SUCCESS(Status) &&
00966             ((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Type == REG_DWORD) {
00967 
00968         gdwAllocsToFail = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)achKeyValue)->Data);
00969     }
00970 
00971     
if (gdwAllocFailIndex != 0 && gdwAllocsToFail > 0) {
00972         
gdwPoolFlags |= 
POOL_FAIL_BY_INDEX;
00973     }
00974 
#endif // DBG
00975 
00976     ZwClose(hkey);
00977 
00978     
return;
00979 }
00980 
#endif // POOL_INSTR
00981 
00982 
#ifdef POOL_INSTR_API
00983 
00984 
BOOL _Win32PoolAllocationStats(
00985     LPDWORD  parrTags,
00986     SIZE_T   tagsCount,
00987     SIZE_T*  lpdwMaxMem,
00988     SIZE_T*  lpdwCrtMem,
00989     LPDWORD  lpdwMaxAlloc,
00990     LPDWORD  lpdwCrtAlloc)
00991 {
00992     
BOOL bRet = 
FALSE;
00993 
00994     
00995 
00996 
00997     
if (!(
gdwPoolFlags & 
POOL_HEAVY_ALLOCS)) {
00998         
return FALSE;
00999     }
01000     
01001     *lpdwMaxMem   = gAllocList.
dwMaxMem;
01002     *lpdwCrtMem   = gAllocList.
dwCrtMem;
01003     *lpdwMaxAlloc = gAllocList.
dwMaxAlloc;
01004     *lpdwCrtAlloc = gAllocList.
dwCrtAlloc;
01005     
01006     
01007 
01008 
01009     
KeEnterCriticalRegion();
01010     
ExAcquireFastMutexUnsafe(gpAllocFastMutex);
01011     
01012     
if (gparrTagsToFail != 
NULL) {
01013         
ExFreePool(gparrTagsToFail);
01014         gparrTagsToFail = 
NULL;
01015         gdwTagsToFailCount = 0;
01016     }
01017 
01018     
if (tagsCount != 0) {
01019         
gdwPoolFlags |= 
POOL_FAIL_ALLOCS;
01020 
01021         
if (tagsCount > MAX_TAGS_TO_FAIL) {
01022             gdwTagsToFailCount = 0xFFFFFFFF;
01023             RIPMSG0(RIP_WARNING, 
"All pool allocations in WIN32K.SYS will fail !!!");
01024             bRet = 
TRUE;
01025             
goto exit;
01026         }
01027 
01028     } 
else {
01029         
gdwPoolFlags &= ~
POOL_FAIL_ALLOCS;
01030         
01031         RIPMSG0(RIP_WARNING, 
"Pool allocations in WIN32K.SYS back to normal !");
01032         bRet = 
TRUE;
01033         
goto exit;
01034     }
01035     
01036     gparrTagsToFail = 
ExAllocatePoolWithTag(PagedPool,
01037                                             
sizeof(DWORD) * tagsCount,
01038                                             TAG_DEBUG);
01039     
01040     
if (gparrTagsToFail == 
NULL) {
01041         
gdwPoolFlags &= ~
POOL_FAIL_ALLOCS;
01042         RIPMSG0(RIP_WARNING, 
"Pool allocations in WIN32K.SYS back to normal !");
01043         
goto exit;
01044     }
01045 
01046     
try {
01047         
ProbeForRead(parrTags, 
sizeof(DWORD) * tagsCount, DATAALIGN);
01048 
01049         RtlCopyMemory(gparrTagsToFail, parrTags, 
sizeof(DWORD) * tagsCount);
01050 
01051     } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
01052           
01053           
if (gparrTagsToFail != 
NULL) {
01054               
ExFreePool(gparrTagsToFail);
01055               gparrTagsToFail = 
NULL;
01056               
01057               
gdwPoolFlags &= ~
POOL_FAIL_ALLOCS;
01058               RIPMSG0(RIP_WARNING, 
"Pool allocations in WIN32K.SYS back to normal !");
01059               
goto exit;
01060           }
01061     }
01062     gdwTagsToFailCount = tagsCount;
01063         
01064     RIPMSG0(RIP_WARNING, 
"Specific pool allocations in WIN32K.SYS will fail !!!");
01065 
01066 
exit:        
01067     
01068 
01069 
01070     
ExReleaseFastMutexUnsafe(gpAllocFastMutex);
01071     
KeLeaveCriticalRegion();
01072     
01073     
return TRUE;
01074 }
01075 
01076 
#endif // POOL_INSTR_API
01077 
01078 
#ifdef TRACE_MAP_VIEWS
01079 
01080 
FAST_MUTEX*   gpSectionFastMutex;
01081 PWin32Section gpSections;
01082 
01083 
#define EnterSectionCrit()                          \
01084 
    KeEnterCriticalRegion();                        \
01085 
    ExAcquireFastMutexUnsafe(gpSectionFastMutex);
01086 
01087 
#define LeaveSectionCrit()                          \
01088 
    ExReleaseFastMutexUnsafe(gpSectionFastMutex);   \
01089 
    KeLeaveCriticalRegion();
01090 
01091 
01092 
01093 
01094 
01095 
01096 
void CleanUpSections(
void)
01097 {
01098     
if (gpSectionFastMutex) {
01099         
ExFreePool(gpSectionFastMutex);
01100         gpSectionFastMutex = 
NULL;
01101     }
01102 }
01103 
01104 
VOID InitSectionTrace(VOID)
01105 {
01106     gpSectionFastMutex = 
ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
01107                                                
sizeof(
FAST_MUTEX),
01108                                                TAG_DEBUG);
01109 
01110     UserAssert(gpSectionFastMutex != NULL);
01111 
01112     
ExInitializeFastMutex(gpSectionFastMutex);
01113 }
01114 
01115 
NTSTATUS _Win32CreateSection(
01116     PVOID*              pSectionObject,
01117     ACCESS_MASK         DesiredAccess,
01118     POBJECT_ATTRIBUTES  ObjectAttributes,
01119     PLARGE_INTEGER      pInputMaximumSize,
01120     ULONG               SectionPageProtection,
01121     ULONG               AllocationAttributes,
01122     HANDLE              FileHandle,
01123     
PFILE_OBJECT        FileObject,
01124     DWORD               SectionTag)
01125 {
01126     PWin32Section pSection;
01127     
NTSTATUS      Status;
01128 
01129 
#ifdef MAP_VIEW_STACK_TRACE
01130 
    ULONG         hash;
01131 
#endif
01132 
01133     
Status = 
MmCreateSection(
01134                     pSectionObject,
01135                     DesiredAccess,
01136                     ObjectAttributes,
01137                     pInputMaximumSize,
01138                     SectionPageProtection,
01139                     AllocationAttributes,
01140                     FileHandle,
01141                     FileObject);
01142 
01143     
if (!
NT_SUCCESS(Status)) {
01144         RIPMSG1(RIP_WARNING, 
"MmCreateSection failed with Statu %x", Status);
01145         *pSectionObject = 
NULL;
01146         
return Status;
01147     }
01148 
01149     pSection = UserAllocPoolZInit(
sizeof(Win32Section), TAG_SECTION);
01150 
01151     
if (pSection == 
NULL) {
01152         
ObDereferenceObject(*pSectionObject);
01153         RIPMSG0(RIP_WARNING, 
"Failed to allocate memory for section");
01154         *pSectionObject = 
NULL;
01155         
return STATUS_UNSUCCESSFUL;
01156     }
01157 
01158     EnterSectionCrit();
01159 
01160     pSection->pNext = gpSections;
01161     
if (gpSections != 
NULL) {
01162         UserAssert(gpSections->pPrev == NULL);
01163         gpSections->pPrev = pSection;
01164     }
01165 
01166     pSection->SectionObject = *pSectionObject;
01167     pSection->SectionSize   = *pInputMaximumSize;
01168     pSection->SectionTag    = SectionTag;
01169 
01170     gpSections = pSection;
01171 
01172 
#ifdef MAP_VIEW_STACK_TRACE
01173 
    RtlZeroMemory(pSection->trace, MAP_VIEW_STACK_TRACE_SIZE * 
sizeof(PVOID));
01174 
01175     GetStackTrace(1,
01176                   MAP_VIEW_STACK_TRACE_SIZE,
01177                   pSection->trace,
01178                   &hash);
01179 
01180 
#endif // MAP_VIEW_STACK_TRACE
01181 
01182     LeaveSectionCrit();
01183 
01184     
return STATUS_SUCCESS;
01185 
01186 }
01187 
01188 
VOID _Win32DestroySection(
01189     PVOID Section)
01190 {
01191     PWin32Section ps;
01192 
01193     EnterSectionCrit();
01194 
01195     ps = gpSections;
01196 
01197     
while (ps != 
NULL) {
01198         
if (ps->SectionObject == Section) {
01199 
01200             
01201 
01202 
01203             
if (ps->pFirstView != 
NULL) {
01204                 RIPMSG1(RIP_ERROR, 
"Section %#p still has views", ps);
01205             }
01206 
01207             
01208 
01209 
01210             
if (ps->pPrev == 
NULL) {
01211 
01212                 UserAssert(ps == gpSections);
01213 
01214                 gpSections = ps->pNext;
01215 
01216                 
if (ps->pNext != 
NULL) {
01217                     ps->pNext->pPrev = 
NULL;
01218                 }
01219             } 
else {
01220                 ps->pPrev->pNext = ps->pNext;
01221                 
if (ps->pNext != 
NULL) {
01222                     ps->pNext->pPrev = ps->pPrev;
01223                 }
01224             }
01225             
ObDereferenceObject(Section);
01226             UserFreePool(ps);
01227             LeaveSectionCrit();
01228             
return;
01229         }
01230         ps = ps->pNext;
01231     }
01232 
01233     RIPMSG1(RIP_ERROR, 
"Cannot find Section %#p", Section);
01234     LeaveSectionCrit();
01235 }
01236 
01237 
NTSTATUS _Win32MapViewInSessionSpace(
01238     PVOID   Section,
01239     PVOID*  pMappedBase,
01240     PSIZE_T pViewSize)
01241 {
01242     
NTSTATUS      Status;
01243     PWin32Section ps;
01244     PWin32MapView pMapView;
01245 
01246 
#ifdef MAP_VIEW_STACK_TRACE
01247 
    ULONG         hash;
01248 
#endif
01249 
01250     
01251 
01252 
01253     
Status = 
MmMapViewInSessionSpace(Section, pMappedBase, pViewSize);
01254 
01255     
if (!
NT_SUCCESS(Status)) {
01256         RIPMSG1(RIP_WARNING, 
"MmMapViewInSessionSpace failed with Status %x",
01257                 Status);
01258         *pMappedBase = 
NULL;
01259         
return Status;
01260     }
01261 
01262     
01263 
01264 
01265     pMapView = UserAllocPoolZInit(
sizeof(Win32MapView), TAG_SECTION);
01266 
01267     
if (pMapView == 
NULL) {
01268         RIPMSG0(RIP_WARNING, 
"_Win32MapViewInSessionSpace: Memory failure");
01269 
01270         
MmUnmapViewInSessionSpace(*pMappedBase);
01271         *pMappedBase = 
NULL;
01272         
return STATUS_NO_MEMORY;
01273     }
01274 
01275     pMapView->pViewBase = *pMappedBase;
01276     pMapView->ViewSize  = *pViewSize;
01277 
01278     EnterSectionCrit();
01279 
01280     ps = gpSections;
01281 
01282     
while (ps != 
NULL) {
01283         
if (ps->SectionObject == Section) {
01284 
01285             pMapView->pSection = ps;
01286 
01287             pMapView->pNext = ps->pFirstView;
01288 
01289             
if (ps->pFirstView != 
NULL) {
01290                 ps->pFirstView->pPrev = pMapView;
01291             }
01292             ps->pFirstView = pMapView;
01293 
01294 
#ifdef MAP_VIEW_STACK_TRACE
01295 
            RtlZeroMemory(pMapView->trace, MAP_VIEW_STACK_TRACE_SIZE * 
sizeof(PVOID));
01296 
01297             GetStackTrace(1,
01298                           MAP_VIEW_STACK_TRACE_SIZE,
01299                           pMapView->trace,
01300                           &hash);
01301 
01302 
#endif // MAP_VIEW_STACK_TRACE
01303 
01304             LeaveSectionCrit();
01305             
return STATUS_SUCCESS;
01306         }
01307         ps = ps->pNext;
01308     }
01309 
01310     RIPMSG1(RIP_ERROR, 
"_Win32MapViewInSessionSpace: Could not find section for %#p",
01311             Section);
01312 
01313     LeaveSectionCrit();
01314 
01315     
return STATUS_UNSUCCESSFUL;
01316 }
01317 
01318 
NTSTATUS _Win32UnmapViewInSessionSpace(
01319     PVOID MappedBase)
01320 {
01321     PWin32Section ps;
01322     PWin32MapView pv;
01323     
NTSTATUS      Status;
01324 
01325     EnterSectionCrit();
01326 
01327     ps = gpSections;
01328 
01329     
while (ps != 
NULL) {
01330 
01331         pv = ps->pFirstView;
01332 
01333         
while (pv != 
NULL) {
01334 
01335             UserAssert(pv->pSection == ps);
01336 
01337             
if (pv->pViewBase == MappedBase) {
01338                 
01339 
01340 
01341                 
if (pv->pPrev == 
NULL) {
01342 
01343                     UserAssert(pv == ps->pFirstView);
01344 
01345                     ps->pFirstView = pv->pNext;
01346 
01347                     
if (pv->pNext != 
NULL) {
01348                         pv->pNext->pPrev = 
NULL;
01349                     }
01350                 } 
else {
01351                     pv->pPrev->pNext = pv->pNext;
01352                     
if (pv->pNext != 
NULL) {
01353                         pv->pNext->pPrev = pv->pPrev;
01354                     }
01355                 }
01356 
01357                 UserFreePool(pv);
01358 
01359                 
Status = 
MmUnmapViewInSessionSpace(MappedBase);
01360 
01361                 LeaveSectionCrit();
01362 
01363                 
return Status;
01364             }
01365             pv = pv->pNext;
01366         }
01367         ps = ps->pNext;
01368     }
01369 
01370     RIPMSG1(RIP_ERROR, 
"_Win32UnmapViewInSessionSpace: Could not find view for %#p",
01371             MappedBase);
01372 
01373     LeaveSectionCrit();
01374 
01375     
return STATUS_UNSUCCESSFUL;
01376 }
01377 
01378 
#endif // TRACE_MAP_VIEWS