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
UDFDebugAcquireResourceSharedLite(IN PERESOURCE Resource,IN BOOLEAN Wait,ULONG BugCheckId,ULONG Line)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
UDFDebugAcquireSharedStarveExclusive(IN PERESOURCE Resource,IN BOOLEAN Wait,ULONG BugCheckId,ULONG Line)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
UDFDebugAcquireResourceExclusiveLite(IN PERESOURCE Resource,IN BOOLEAN Wait,ULONG BugCheckId,ULONG Line)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
UDFDebugReleaseResourceForThreadLite(IN PERESOURCE Resource,IN ERESOURCE_THREAD ResourceThreadId,ULONG BugCheckId,ULONG Line)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
UDFDebugDeleteResource(IN PERESOURCE Resource,IN ERESOURCE_THREAD ResourceThreadId,ULONG BugCheckId,ULONG Line)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
UDFDebugInitializeResourceLite(IN PERESOURCE Resource,IN ERESOURCE_THREAD ResourceThreadId,ULONG BugCheckId,ULONG Line)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
UDFDebugConvertExclusiveToSharedLite(IN PERESOURCE Resource,IN ERESOURCE_THREAD ResourceThreadId,ULONG BugCheckId,ULONG Line)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
UDFDebugAcquireSharedWaitForExclusive(IN PERESOURCE Resource,IN BOOLEAN Wait,ULONG BugCheckId,ULONG Line)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
UDFDebugInterlockedIncrement(IN PLONG addr,ULONG BugCheckId,ULONG Line)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
UDFDebugInterlockedDecrement(IN PLONG addr,ULONG BugCheckId,ULONG Line)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
UDFDebugInterlockedExchangeAdd(IN PLONG addr,IN LONG i,ULONG BugCheckId,ULONG Line)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
DebugAllocatePool(POOL_TYPE Type,ULONG size,ULONG SrcId,ULONG SrcLine)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
DebugFreePool(PVOID addr)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
UDFWaitForSingleObject(IN PLONG Object,IN PLARGE_INTEGER Timeout OPTIONAL)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
DbgWaitForSingleObject_(IN PVOID Object,IN PLARGE_INTEGER Timeout OPTIONAL)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