//////////////////////////////////////////////////////////////////// // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine // All rights reserved // This file was released under the GPLv2 on June 2015. //////////////////////////////////////////////////////////////////// #include "udffs.h" #if defined(UDF_DBG) || defined(PRINT_ALWAYS) //#define TRACK_RESOURCES //#define TRACK_REF_COUNTERS ULONG ResCounter = 0; ULONG AcqCounter = 0; ULONG UdfTimeStamp = -1; BOOLEAN UDFDebugAcquireResourceSharedLite( IN PERESOURCE Resource, IN BOOLEAN Wait, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif BOOLEAN Success; #ifdef USE_DLD if (Wait) { DLDAcquireShared(Resource, BugCheckId, Line,FALSE); Success = TRUE; } else { Success = ExAcquireResourceSharedLite(Resource,Wait); } #else Success = ExAcquireResourceSharedLite(Resource,Wait); #endif // USE_DLD if(Success) { #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif AcqCounter++; return Success; } #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif return FALSE; } BOOLEAN UDFDebugAcquireSharedStarveExclusive( IN PERESOURCE Resource, IN BOOLEAN Wait, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif BOOLEAN Success; #ifdef USE_DLD if (Wait) { DLDAcquireShared(Resource, BugCheckId, Line,FALSE); Success = TRUE; } else { Success = ExAcquireResourceSharedLite(Resource,Wait); } #else Success = ExAcquireResourceSharedLite(Resource,Wait); #endif // USE_DLD if(Success) { #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif AcqCounter++; return Success; } #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif return FALSE; } BOOLEAN UDFDebugAcquireResourceExclusiveLite( IN PERESOURCE Resource, IN BOOLEAN Wait, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Exc:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif BOOLEAN Success; #ifdef USE_DLD if (Wait) { DLDAcquireExclusive(Resource, BugCheckId, Line); Success = TRUE; } else { Success = ExAcquireResourceExclusiveLite(Resource,Wait); } #else Success = ExAcquireResourceExclusiveLite(Resource,Wait); #endif // USE_DLD if(Success) { #ifdef TRACK_RESOURCES UDFPrint(("Res:Exc:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif AcqCounter++; return Success; } #ifdef TRACK_RESOURCES UDFPrint(("Res:Exc:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif // BrutePoint(); return FALSE; } VOID UDFDebugReleaseResourceForThreadLite( IN PERESOURCE Resource, IN ERESOURCE_THREAD ResourceThreadId, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Free:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif ExReleaseResourceForThreadLite(Resource, ResourceThreadId); #ifdef TRACK_RESOURCES UDFPrint(("Res:Free:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif AcqCounter--; } VOID UDFDebugDeleteResource( IN PERESOURCE Resource, IN ERESOURCE_THREAD ResourceThreadId, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Del:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif _SEH2_TRY { ASSERT((*((PULONG)Resource))); ASSERT((*(((PULONG)Resource)+1))); ExDeleteResourceLite(Resource); RtlZeroMemory(Resource, sizeof(ERESOURCE)); } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { BrutePoint(); } _SEH2_END; #ifdef TRACK_RESOURCES UDFPrint(("Res:Del:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif ResCounter--; } NTSTATUS UDFDebugInitializeResourceLite( IN PERESOURCE Resource, IN ERESOURCE_THREAD ResourceThreadId, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); NTSTATUS RC; #ifdef TRACK_RESOURCES UDFPrint(("Res:Ini:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif ASSERT(!(*((PULONG)Resource))); ASSERT(!(*(((PULONG)Resource)+1))); RC = ExInitializeResourceLite(Resource); #ifdef TRACK_RESOURCES UDFPrint(("Res:Ini:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif if(NT_SUCCESS(RC)) { ResCounter++; } return RC; } VOID UDFDebugConvertExclusiveToSharedLite( IN PERESOURCE Resource, IN ERESOURCE_THREAD ResourceThreadId, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:2Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif ExConvertExclusiveToSharedLite(Resource); #ifdef TRACK_RESOURCES UDFPrint(("Res:2Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,ResourceThreadId)); #endif } BOOLEAN UDFDebugAcquireSharedWaitForExclusive( IN PERESOURCE Resource, IN BOOLEAN Wait, ULONG BugCheckId, ULONG Line ) { ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif BOOLEAN Success; #ifdef USE_DLD if (Wait) { DLDAcquireShared(Resource, BugCheckId, Line,TRUE); Success = TRUE; } else { Success = ExAcquireSharedWaitForExclusive(Resource,Wait); } #else Success = ExAcquireSharedWaitForExclusive(Resource,Wait); #endif // USE_DLD if(Success) { #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif return Success; } #ifdef TRACK_RESOURCES UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, BugCheckId,Line,PsGetCurrentThread())); #endif // BrutePoint(); return FALSE; } LONG UDFDebugInterlockedIncrement( IN PLONG addr, ULONG BugCheckId, ULONG Line) { #ifdef TRACK_REF_COUNTERS LONG a; a = InterlockedIncrement(addr); UDFPrint(("ThId:%x:Ilck:Inc:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", PsGetCurrentThread(),BugCheckId,Line,addr,a-1,a)); return a; #else return InterlockedIncrement(addr); #endif } LONG UDFDebugInterlockedDecrement( IN PLONG addr, ULONG BugCheckId, ULONG Line) { #ifdef TRACK_REF_COUNTERS LONG a; a = InterlockedDecrement(addr); UDFPrint(("ThId:%x:Ilck:Dec:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", PsGetCurrentThread(),BugCheckId,Line,addr,a+1,a)); return a; #else return InterlockedDecrement(addr); #endif } LONG UDFDebugInterlockedExchangeAdd( IN PLONG addr, IN LONG i, ULONG BugCheckId, ULONG Line) { #ifdef TRACK_REF_COUNTERS LONG a; a = InterlockedExchangeAdd(addr,i); UDFPrint(("ThId:%x:Ilck:Add:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", PsGetCurrentThread(),BugCheckId,Line,addr,a,a+i)); return a; #else return InterlockedExchangeAdd(addr,i); #endif } #define MAX_MEM_DEBUG_DESCRIPTORS 8192 typedef struct _MEM_DESC { ULONG Length; PCHAR Addr; #ifdef TRACK_SYS_ALLOC_CALLERS ULONG SrcId; ULONG SrcLine; #endif //TRACK_SYS_ALLOC_CALLERS POOL_TYPE Type; } MEM_DESC, *PMEM_DESC; MEM_DESC MemDesc[MAX_MEM_DEBUG_DESCRIPTORS]; ULONG cur_max = 0; ULONG AllocCountPaged = 0; ULONG AllocCountNPaged = 0; ULONG MemDescInited = 0; PVOID DebugAllocatePool( POOL_TYPE Type, ULONG size #ifdef TRACK_SYS_ALLOC_CALLERS , ULONG SrcId, ULONG SrcLine #endif //TRACK_SYS_ALLOC_CALLERS ) { ULONG i; // UDFPrint(("SysAllocated: %x\n",AllocCount)); if(!MemDescInited) { RtlZeroMemory(&MemDesc, sizeof(MemDesc)); MemDescInited = 1; } for (i=0;iQuadPart)) LocalTimeout = *Timeout; else LocalTimeout.QuadPart = 0x7FFFFFFFFFFFFFFFLL; UDFPrint(("SignalState %x\n", *Object)); if(!Object) return STATUS_INVALID_PARAMETER; if((*Object)) return STATUS_SUCCESS; while(LocalTimeout.QuadPart>0 && !(*Object) ) { UDFPrint(("SignalState %x\n", *Object)); // Stall for a while. KeDelayExecutionThread(KernelMode, FALSE, &delay); LocalTimeout.QuadPart -= WAIT_FOR_XXX_EMU_DELAY; } return STATUS_SUCCESS; } // end UDFWaitForSingleObject() NTSTATUS DbgWaitForSingleObject_( IN PVOID Object, IN PLARGE_INTEGER Timeout OPTIONAL ) { PLARGE_INTEGER to; LARGE_INTEGER dto; // LARGE_INTEGER cto; NTSTATUS RC; ULONG c = 20; dto.QuadPart = -5LL*1000000LL*10LL; // 5 sec // cto.QuadPart = Timeout->QuadPart; if(Timeout) { if(dto.QuadPart > Timeout->QuadPart) { to = Timeout; } else { to = &dto; } } else { to = &dto; } for(; c--; c) { RC = KeWaitForSingleObject(Object, Executive, KernelMode, FALSE, to); if(RC == STATUS_SUCCESS) break; UDFPrint(("No response ?\n")); if(c<2) BrutePoint(); } return RC; } #endif // UDF_DBG