1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 #include "udffs.h" 7 #if defined(UDF_DBG) || defined(PRINT_ALWAYS) 8 9 //#define TRACK_RESOURCES 10 //#define TRACK_REF_COUNTERS 11 12 ULONG ResCounter = 0; 13 ULONG AcqCounter = 0; 14 ULONG UdfTimeStamp = -1; 15 16 BOOLEAN 17 UDFDebugAcquireResourceSharedLite( 18 IN PERESOURCE Resource, 19 IN BOOLEAN Wait, 20 ULONG BugCheckId, 21 ULONG Line 22 ) { 23 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 24 #ifdef TRACK_RESOURCES 25 UDFPrint(("Res:Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 26 BugCheckId,Line,PsGetCurrentThread())); 27 #endif 28 29 BOOLEAN Success; 30 31 #ifdef USE_DLD 32 33 if (Wait) { 34 DLDAcquireShared(Resource, BugCheckId, Line,FALSE); 35 Success = TRUE; 36 } else { 37 Success = ExAcquireResourceSharedLite(Resource,Wait); 38 } 39 40 #else 41 42 Success = ExAcquireResourceSharedLite(Resource,Wait); 43 44 #endif // USE_DLD 45 46 if(Success) { 47 #ifdef TRACK_RESOURCES 48 UDFPrint(("Res:Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 49 BugCheckId,Line,PsGetCurrentThread())); 50 #endif 51 AcqCounter++; 52 return Success; 53 } 54 #ifdef TRACK_RESOURCES 55 UDFPrint(("Res:Sha:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 56 BugCheckId,Line,PsGetCurrentThread())); 57 #endif 58 return FALSE; 59 } 60 61 BOOLEAN 62 UDFDebugAcquireSharedStarveExclusive( 63 IN PERESOURCE Resource, 64 IN BOOLEAN Wait, 65 ULONG BugCheckId, 66 ULONG Line 67 ) { 68 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 69 #ifdef TRACK_RESOURCES 70 UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 71 BugCheckId,Line,PsGetCurrentThread())); 72 #endif 73 74 BOOLEAN Success; 75 76 #ifdef USE_DLD 77 78 if (Wait) { 79 DLDAcquireShared(Resource, BugCheckId, Line,FALSE); 80 Success = TRUE; 81 } else { 82 Success = ExAcquireResourceSharedLite(Resource,Wait); 83 } 84 85 #else 86 87 Success = ExAcquireResourceSharedLite(Resource,Wait); 88 89 #endif // USE_DLD 90 91 if(Success) { 92 #ifdef TRACK_RESOURCES 93 UDFPrint(("Res:Sha*:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 94 BugCheckId,Line,PsGetCurrentThread())); 95 #endif 96 AcqCounter++; 97 return Success; 98 } 99 #ifdef TRACK_RESOURCES 100 UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 101 BugCheckId,Line,PsGetCurrentThread())); 102 #endif 103 return FALSE; 104 } 105 106 BOOLEAN 107 UDFDebugAcquireResourceExclusiveLite( 108 IN PERESOURCE Resource, 109 IN BOOLEAN Wait, 110 ULONG BugCheckId, 111 ULONG Line 112 ) { 113 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 114 #ifdef TRACK_RESOURCES 115 UDFPrint(("Res:Exc:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 116 BugCheckId,Line,PsGetCurrentThread())); 117 #endif 118 119 120 BOOLEAN Success; 121 122 #ifdef USE_DLD 123 124 if (Wait) { 125 DLDAcquireExclusive(Resource, BugCheckId, Line); 126 Success = TRUE; 127 } else { 128 Success = ExAcquireResourceExclusiveLite(Resource,Wait); 129 } 130 131 #else 132 133 Success = ExAcquireResourceExclusiveLite(Resource,Wait); 134 135 #endif // USE_DLD 136 137 138 139 if(Success) { 140 #ifdef TRACK_RESOURCES 141 UDFPrint(("Res:Exc:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 142 BugCheckId,Line,PsGetCurrentThread())); 143 #endif 144 AcqCounter++; 145 return Success; 146 } 147 #ifdef TRACK_RESOURCES 148 UDFPrint(("Res:Exc:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 149 BugCheckId,Line,PsGetCurrentThread())); 150 #endif 151 // BrutePoint(); 152 return FALSE; 153 154 } 155 156 VOID 157 UDFDebugReleaseResourceForThreadLite( 158 IN PERESOURCE Resource, 159 IN ERESOURCE_THREAD ResourceThreadId, 160 ULONG BugCheckId, 161 ULONG Line 162 ) 163 { 164 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 165 #ifdef TRACK_RESOURCES 166 UDFPrint(("Res:Free:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 167 BugCheckId,Line,PsGetCurrentThread())); 168 #endif 169 ExReleaseResourceForThreadLite(Resource, ResourceThreadId); 170 #ifdef TRACK_RESOURCES 171 UDFPrint(("Res:Free:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 172 BugCheckId,Line,ResourceThreadId)); 173 #endif 174 AcqCounter--; 175 } 176 177 VOID 178 UDFDebugDeleteResource( 179 IN PERESOURCE Resource, 180 IN ERESOURCE_THREAD ResourceThreadId, 181 ULONG BugCheckId, 182 ULONG Line 183 ) 184 { 185 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 186 #ifdef TRACK_RESOURCES 187 UDFPrint(("Res:Del:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 188 BugCheckId,Line,ResourceThreadId)); 189 #endif 190 _SEH2_TRY { 191 ASSERT((*((PULONG)Resource))); 192 ASSERT((*(((PULONG)Resource)+1))); 193 ExDeleteResourceLite(Resource); 194 RtlZeroMemory(Resource, sizeof(ERESOURCE)); 195 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { 196 BrutePoint(); 197 } _SEH2_END; 198 #ifdef TRACK_RESOURCES 199 UDFPrint(("Res:Del:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 200 BugCheckId,Line,ResourceThreadId)); 201 #endif 202 ResCounter--; 203 } 204 205 NTSTATUS 206 UDFDebugInitializeResourceLite( 207 IN PERESOURCE Resource, 208 IN ERESOURCE_THREAD ResourceThreadId, 209 ULONG BugCheckId, 210 ULONG Line 211 ) 212 { 213 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 214 NTSTATUS RC; 215 #ifdef TRACK_RESOURCES 216 UDFPrint(("Res:Ini:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 217 BugCheckId,Line,ResourceThreadId)); 218 #endif 219 ASSERT(!(*((PULONG)Resource))); 220 ASSERT(!(*(((PULONG)Resource)+1))); 221 RC = ExInitializeResourceLite(Resource); 222 #ifdef TRACK_RESOURCES 223 UDFPrint(("Res:Ini:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 224 BugCheckId,Line,ResourceThreadId)); 225 #endif 226 if(NT_SUCCESS(RC)) { 227 ResCounter++; 228 } 229 return RC; 230 } 231 232 VOID 233 UDFDebugConvertExclusiveToSharedLite( 234 IN PERESOURCE Resource, 235 IN ERESOURCE_THREAD ResourceThreadId, 236 ULONG BugCheckId, 237 ULONG Line 238 ) 239 { 240 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 241 #ifdef TRACK_RESOURCES 242 UDFPrint(("Res:2Sha:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 243 BugCheckId,Line,ResourceThreadId)); 244 #endif 245 ExConvertExclusiveToSharedLite(Resource); 246 #ifdef TRACK_RESOURCES 247 UDFPrint(("Res:2Sha:Ok:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 248 BugCheckId,Line,ResourceThreadId)); 249 #endif 250 } 251 252 BOOLEAN 253 UDFDebugAcquireSharedWaitForExclusive( 254 IN PERESOURCE Resource, 255 IN BOOLEAN Wait, 256 ULONG BugCheckId, 257 ULONG Line 258 ) { 259 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 260 #ifdef TRACK_RESOURCES 261 UDFPrint(("Res:Sha*:Try:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 262 BugCheckId,Line,PsGetCurrentThread())); 263 #endif 264 265 BOOLEAN Success; 266 267 #ifdef USE_DLD 268 269 if (Wait) { 270 DLDAcquireShared(Resource, BugCheckId, Line,TRUE); 271 Success = TRUE; 272 } else { 273 Success = ExAcquireSharedWaitForExclusive(Resource,Wait); 274 } 275 276 #else 277 278 Success = ExAcquireSharedWaitForExclusive(Resource,Wait); 279 280 #endif // USE_DLD 281 282 283 if(Success) { 284 #ifdef TRACK_RESOURCES 285 UDFPrint(("Res:Sha*:OK:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 286 BugCheckId,Line,PsGetCurrentThread())); 287 #endif 288 return Success; 289 } 290 #ifdef TRACK_RESOURCES 291 UDFPrint(("Res:Sha*:Fail:Resource:%x:BugCheckId:%x:Line:%d:ThId:%x\n",Resource, 292 BugCheckId,Line,PsGetCurrentThread())); 293 #endif 294 // BrutePoint(); 295 return FALSE; 296 297 } 298 299 300 LONG 301 UDFDebugInterlockedIncrement( 302 IN PLONG addr, 303 ULONG BugCheckId, 304 ULONG Line) 305 { 306 #ifdef TRACK_REF_COUNTERS 307 LONG a; 308 a = InterlockedIncrement(addr); 309 UDFPrint(("ThId:%x:Ilck:Inc:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", 310 PsGetCurrentThread(),BugCheckId,Line,addr,a-1,a)); 311 return a; 312 #else 313 return InterlockedIncrement(addr); 314 #endif 315 } 316 317 LONG 318 UDFDebugInterlockedDecrement( 319 IN PLONG addr, 320 ULONG BugCheckId, 321 ULONG Line) 322 { 323 #ifdef TRACK_REF_COUNTERS 324 LONG a; 325 a = InterlockedDecrement(addr); 326 UDFPrint(("ThId:%x:Ilck:Dec:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", 327 PsGetCurrentThread(),BugCheckId,Line,addr,a+1,a)); 328 return a; 329 #else 330 return InterlockedDecrement(addr); 331 #endif 332 } 333 334 LONG 335 UDFDebugInterlockedExchangeAdd( 336 IN PLONG addr, 337 IN LONG i, 338 ULONG BugCheckId, 339 ULONG Line) 340 { 341 #ifdef TRACK_REF_COUNTERS 342 LONG a; 343 a = InterlockedExchangeAdd(addr,i); 344 UDFPrint(("ThId:%x:Ilck:Add:FileId:%x:Line:%d:Ref:%x:Val:%x:%x\n", 345 PsGetCurrentThread(),BugCheckId,Line,addr,a,a+i)); 346 return a; 347 #else 348 return InterlockedExchangeAdd(addr,i); 349 #endif 350 } 351 352 #define MAX_MEM_DEBUG_DESCRIPTORS 8192 353 354 typedef struct _MEM_DESC { 355 ULONG Length; 356 PCHAR Addr; 357 #ifdef TRACK_SYS_ALLOC_CALLERS 358 ULONG SrcId; 359 ULONG SrcLine; 360 #endif //TRACK_SYS_ALLOC_CALLERS 361 POOL_TYPE Type; 362 } MEM_DESC, *PMEM_DESC; 363 364 365 MEM_DESC MemDesc[MAX_MEM_DEBUG_DESCRIPTORS]; 366 ULONG cur_max = 0; 367 ULONG AllocCountPaged = 0; 368 ULONG AllocCountNPaged = 0; 369 ULONG MemDescInited = 0; 370 371 PVOID 372 DebugAllocatePool( 373 POOL_TYPE Type, 374 ULONG size 375 #ifdef TRACK_SYS_ALLOC_CALLERS 376 , ULONG SrcId, 377 ULONG SrcLine 378 #endif //TRACK_SYS_ALLOC_CALLERS 379 ) { 380 ULONG i; 381 // UDFPrint(("SysAllocated: %x\n",AllocCount)); 382 if(!MemDescInited) { 383 RtlZeroMemory(&MemDesc, sizeof(MemDesc)); 384 MemDescInited = 1; 385 } 386 for (i=0;i<cur_max;i++) { 387 if (MemDesc[i].Addr==NULL) { 388 MemDesc[i].Addr = (PCHAR)ExAllocatePoolWithTag(Type, (size), 'Fnwd'); // dwnF 389 390 ASSERT(MemDesc[i].Addr); 391 392 if(MemDesc[i].Addr) { 393 if(Type == PagedPool) { 394 AllocCountPaged += (size+7) & ~7; 395 } else { 396 AllocCountNPaged += (size+7) & ~7; 397 } 398 } 399 400 MemDesc[i].Length = size; 401 MemDesc[i].Type = Type; 402 #ifdef TRACK_SYS_ALLOC_CALLERS 403 MemDesc[i].SrcId = SrcId; 404 MemDesc[i].SrcLine = SrcLine; 405 #endif //TRACK_SYS_ALLOC_CALLERS 406 return MemDesc[i].Addr; 407 } 408 } 409 if(cur_max == MAX_MEM_DEBUG_DESCRIPTORS) { 410 UDFPrint(("Debug memory descriptor list full\n")); 411 return ExAllocatePoolWithTag(Type, (size) , 'Fnwd'); 412 } 413 414 MemDesc[i].Addr = (PCHAR)ExAllocatePoolWithTag(Type, (size) , 'Fnwd'); 415 416 if(MemDesc[i].Addr) { 417 if(Type == PagedPool) { 418 AllocCountPaged += (size+7) & ~7; 419 } else { 420 AllocCountNPaged += (size+7) & ~7; 421 } 422 } 423 424 MemDesc[i].Length = (size); 425 #ifdef TRACK_SYS_ALLOC_CALLERS 426 MemDesc[i].SrcId = SrcId; 427 MemDesc[i].SrcLine = SrcLine; 428 #endif //TRACK_SYS_ALLOC_CALLERS 429 MemDesc[i].Type = Type; 430 cur_max++; 431 return MemDesc[cur_max-1].Addr; 432 433 } 434 435 VOID DebugFreePool(PVOID addr) { 436 ULONG i; 437 438 ASSERT(addr); 439 440 for (i=0;i<cur_max;i++) { 441 if (MemDesc[i].Addr == addr) { 442 443 if(MemDesc[i].Type == PagedPool) { 444 AllocCountPaged -= (MemDesc[i].Length+7) & ~7; 445 } else { 446 AllocCountNPaged -= (MemDesc[i].Length+7) & ~7; 447 } 448 449 MemDesc[i].Addr = NULL; 450 MemDesc[i].Length = 0; 451 #ifdef TRACK_SYS_ALLOC_CALLERS 452 MemDesc[i].SrcId = 0; 453 MemDesc[i].SrcLine = 0; 454 #endif //TRACK_SYS_ALLOC_CALLERS 455 goto not_bug; 456 } 457 } 458 if (i==cur_max && cur_max != MAX_MEM_DEBUG_DESCRIPTORS) { 459 UDFPrint(("Buug! - Deallocating nonallocated block\n")); 460 return; 461 } 462 not_bug: 463 // UDFPrint(("SysAllocated: %x\n",AllocCount)); 464 ExFreePool(addr); 465 } 466 467 NTSTATUS 468 UDFWaitForSingleObject( 469 IN PLONG Object, 470 IN PLARGE_INTEGER Timeout OPTIONAL 471 ) 472 { 473 UDFPrint(("UDFWaitForSingleObject\n")); 474 LARGE_INTEGER LocalTimeout; 475 LARGE_INTEGER delay; 476 delay.QuadPart = -(WAIT_FOR_XXX_EMU_DELAY); 477 478 if(Timeout && (Timeout->QuadPart)) LocalTimeout = *Timeout; 479 else LocalTimeout.QuadPart = 0x7FFFFFFFFFFFFFFFLL; 480 481 UDFPrint(("SignalState %x\n", *Object)); 482 if(!Object) return STATUS_INVALID_PARAMETER; 483 if((*Object)) return STATUS_SUCCESS; 484 while(LocalTimeout.QuadPart>0 && !(*Object) ) { 485 UDFPrint(("SignalState %x\n", *Object)); 486 // Stall for a while. 487 KeDelayExecutionThread(KernelMode, FALSE, &delay); 488 LocalTimeout.QuadPart -= WAIT_FOR_XXX_EMU_DELAY; 489 } 490 return STATUS_SUCCESS; 491 } // end UDFWaitForSingleObject() 492 493 NTSTATUS 494 DbgWaitForSingleObject_( 495 IN PVOID Object, 496 IN PLARGE_INTEGER Timeout OPTIONAL 497 ) 498 { 499 PLARGE_INTEGER to; 500 LARGE_INTEGER dto; 501 // LARGE_INTEGER cto; 502 NTSTATUS RC; 503 ULONG c = 20; 504 505 dto.QuadPart = -5LL*1000000LL*10LL; // 5 sec 506 // cto.QuadPart = Timeout->QuadPart; 507 if(Timeout) { 508 if(dto.QuadPart > Timeout->QuadPart) { 509 to = Timeout; 510 } else { 511 to = &dto; 512 } 513 } else { 514 to = &dto; 515 } 516 517 for(; c--; c) { 518 RC = KeWaitForSingleObject(Object, Executive, KernelMode, FALSE, to); 519 if(RC == STATUS_SUCCESS) 520 break; 521 UDFPrint(("No response ?\n")); 522 if(c<2) 523 BrutePoint(); 524 } 525 return RC; 526 } 527 #endif // UDF_DBG 528