[IMM32] Improve ImmGetImeInfoEx (#3833)
[reactos.git] / drivers / filesystems / ffs / src / memory.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * memory.c
5 *
6 * 2004.5.6 ~
7 *
8 * Lee Jae-Hong, http://www.pyrasis.com
9 *
10 * See License.txt
11 *
12 */
13
14 #include "ntifs.h"
15 #include "ffsdrv.h"
16
17 /* Globals */
18
19 extern PFFS_GLOBAL FFSGlobal;
20
21
22 /* Definitions */
23
24 #ifdef ALLOC_PRAGMA
25 #pragma alloc_text(PAGE, FFSAllocateIrpContext)
26 #pragma alloc_text(PAGE, FFSFreeIrpContext)
27 #pragma alloc_text(PAGE, FFSv1AllocateFcb)
28 #pragma alloc_text(PAGE, FFSv2AllocateFcb)
29 #pragma alloc_text(PAGE, FFSFreeFcb)
30 #pragma alloc_text(PAGE, FFSAllocateMcb)
31 #pragma alloc_text(PAGE, FFSFreeMcb)
32 #pragma alloc_text(PAGE, FFSSearchMcbTree)
33 #pragma alloc_text(PAGE, FFSSearchMcb)
34 #pragma alloc_text(PAGE, FFSGetFullFileName)
35 #pragma alloc_text(PAGE, FFSRefreshMcb)
36 #pragma alloc_text(PAGE, FFSAddMcbNode)
37 #pragma alloc_text(PAGE, FFSDeleteMcbNode)
38 #pragma alloc_text(PAGE, FFSFreeMcbTree)
39 #pragma alloc_text(PAGE, FFSCheckBitmapConsistency)
40 #pragma alloc_text(PAGE, FFSCheckSetBlock)
41 #pragma alloc_text(PAGE, FFSInitializeVcb)
42 #pragma alloc_text(PAGE, FFSFreeCcb)
43 #pragma alloc_text(PAGE, FFSAllocateCcb)
44 #pragma alloc_text(PAGE, FFSFreeVcb)
45 #pragma alloc_text(PAGE, FFSCreateFcbFromMcb)
46 #pragma alloc_text(PAGE, FFSSyncUninitializeCacheMap)
47 #endif
48
49
50 __drv_mustHoldCriticalRegion
51 PFFS_IRP_CONTEXT
52 FFSAllocateIrpContext(
53 IN PDEVICE_OBJECT DeviceObject,
54 IN PIRP Irp)
55 {
56 PIO_STACK_LOCATION IoStackLocation;
57 PFFS_IRP_CONTEXT IrpContext;
58
59 PAGED_CODE();
60
61 ASSERT(DeviceObject != NULL);
62 ASSERT(Irp != NULL);
63
64 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
65
66 ExAcquireResourceExclusiveLite(
67 &FFSGlobal->LAResource,
68 TRUE);
69
70 IrpContext = (PFFS_IRP_CONTEXT)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList)));
71
72 ExReleaseResourceForThreadLite(
73 &FFSGlobal->LAResource,
74 ExGetCurrentResourceThread());
75
76 if (IrpContext == NULL)
77 {
78 IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_IRP_CONTEXT), FFS_POOL_TAG);
79
80 //
81 // Zero out the irp context and indicate that it is from pool and
82 // not region allocated
83 //
84
85 RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));
86
87 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
88 }
89 else
90 {
91 //
92 // Zero out the irp context and indicate that it is from zone and
93 // not pool allocated
94 //
95
96 RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));
97 }
98
99 if (!IrpContext)
100 {
101 return NULL;
102 }
103
104 IrpContext->Identifier.Type = FFSICX;
105 IrpContext->Identifier.Size = sizeof(FFS_IRP_CONTEXT);
106
107 IrpContext->Irp = Irp;
108
109 IrpContext->MajorFunction = IoStackLocation->MajorFunction;
110 IrpContext->MinorFunction = IoStackLocation->MinorFunction;
111
112 IrpContext->DeviceObject = DeviceObject;
113
114 IrpContext->FileObject = IoStackLocation->FileObject;
115
116 if (IrpContext->FileObject != NULL)
117 {
118 IrpContext->RealDevice = IrpContext->FileObject->DeviceObject;
119 }
120 else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
121 {
122 if (IoStackLocation->Parameters.MountVolume.Vpb)
123 {
124 IrpContext->RealDevice =
125 IoStackLocation->Parameters.MountVolume.Vpb->RealDevice;
126 }
127 }
128
129 if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
130 IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
131 IrpContext->MajorFunction == IRP_MJ_SHUTDOWN)
132 {
133 IrpContext->IsSynchronous = TRUE;
134 }
135 else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
136 IrpContext->MajorFunction == IRP_MJ_CLOSE)
137 {
138 IrpContext->IsSynchronous = FALSE;
139 }
140 #if (_WIN32_WINNT >= 0x0500)
141 else if (IrpContext->MajorFunction == IRP_MJ_PNP)
142 {
143 if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL)
144 {
145 IrpContext->IsSynchronous = TRUE;
146 }
147 else
148 {
149 IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
150 }
151 }
152 #endif //(_WIN32_WINNT >= 0x0500)
153 else
154 {
155 IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
156 }
157
158 #if 0
159 //
160 // Temporary workaround for a bug in close that makes it reference a
161 // fileobject when it is no longer valid.
162 //
163 if (IrpContext->MajorFunction == IRP_MJ_CLOSE)
164 {
165 IrpContext->IsSynchronous = TRUE;
166 }
167 #endif
168
169 IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
170
171 IrpContext->ExceptionInProgress = FALSE;
172
173 return IrpContext;
174 }
175
176
177 __drv_mustHoldCriticalRegion
178 VOID
179 FFSFreeIrpContext(
180 IN PFFS_IRP_CONTEXT IrpContext)
181 {
182 PAGED_CODE();
183
184 ASSERT(IrpContext != NULL);
185
186 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
187 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
188
189 FFSUnpinRepinnedBcbs(IrpContext);
190
191 // Return the Irp context record to the region or to pool depending on
192 // its flag
193
194 if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL))
195 {
196 IrpContext->Identifier.Type = 0;
197 IrpContext->Identifier.Size = 0;
198
199 ExFreePool(IrpContext);
200 }
201 else
202 {
203 IrpContext->Identifier.Type = 0;
204 IrpContext->Identifier.Size = 0;
205
206 ExAcquireResourceExclusiveLite(
207 &FFSGlobal->LAResource,
208 TRUE);
209
210 ExFreeToNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), IrpContext);
211
212 ExReleaseResourceForThreadLite(
213 &FFSGlobal->LAResource,
214 ExGetCurrentResourceThread());
215
216 }
217 }
218
219
220 VOID
221 FFSRepinBcb(
222 IN PFFS_IRP_CONTEXT IrpContext,
223 IN PBCB Bcb)
224 {
225 PFFS_REPINNED_BCBS Repinned;
226 ULONG i;
227
228 Repinned = &IrpContext->Repinned;
229
230
231 return;
232
233 while (Repinned)
234 {
235 for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
236 {
237 if (Repinned->Bcb[i] == Bcb)
238 {
239 return;
240 }
241 }
242
243 Repinned = Repinned->Next;
244 }
245
246 while (TRUE)
247 {
248 for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
249 {
250 if (Repinned->Bcb[i] == Bcb)
251 {
252 return;
253 }
254
255 if (Repinned->Bcb[i] == NULL)
256 {
257 Repinned->Bcb[i] = Bcb;
258 CcRepinBcb(Bcb);
259
260 return;
261 }
262 }
263
264 if (Repinned->Next == NULL)
265 {
266 Repinned->Next = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_REPINNED_BCBS), FFS_POOL_TAG);
267 RtlZeroMemory(Repinned->Next, sizeof(FFS_REPINNED_BCBS));
268 }
269
270 Repinned = Repinned->Next;
271 }
272 }
273
274
275 VOID
276 FFSUnpinRepinnedBcbs(
277 IN PFFS_IRP_CONTEXT IrpContext)
278 {
279 IO_STATUS_BLOCK RaiseIosb;
280 PFFS_REPINNED_BCBS Repinned;
281 BOOLEAN WriteThroughToDisk;
282 PFILE_OBJECT FileObject = NULL;
283 BOOLEAN ForceVerify = FALSE;
284 ULONG i;
285
286 Repinned = &IrpContext->Repinned;
287 RaiseIosb.Status = STATUS_SUCCESS;
288
289 WriteThroughToDisk = (BOOLEAN)(IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
290 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));
291
292 while (Repinned != NULL)
293 {
294 for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
295 {
296 if (Repinned->Bcb[i] != NULL)
297 {
298 IO_STATUS_BLOCK Iosb;
299
300 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
301
302 if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY))
303 {
304 FileObject = CcGetFileObjectFromBcb(Repinned->Bcb[i]);
305 }
306
307 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
308
309 CcUnpinRepinnedBcb(Repinned->Bcb[i],
310 WriteThroughToDisk,
311 &Iosb);
312
313 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
314
315 if (!NT_SUCCESS(Iosb.Status))
316 {
317 if (RaiseIosb.Status == STATUS_SUCCESS)
318 {
319 RaiseIosb = Iosb;
320 }
321
322 if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
323 (IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
324 (IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
325 (IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION))
326 {
327
328 CcPurgeCacheSection(FileObject->SectionObjectPointer,
329 NULL,
330 0,
331 FALSE);
332
333 ForceVerify = TRUE;
334 }
335 }
336
337 Repinned->Bcb[i] = NULL;
338
339 }
340 else
341 {
342 break;
343 }
344 }
345
346 if (Repinned != &IrpContext->Repinned)
347 {
348 PFFS_REPINNED_BCBS Saved;
349
350 Saved = Repinned->Next;
351 ExFreePool(Repinned);
352 Repinned = Saved;
353
354 }
355 else
356 {
357 Repinned = Repinned->Next;
358 IrpContext->Repinned.Next = NULL;
359 }
360 }
361
362 if (!NT_SUCCESS(RaiseIosb.Status))
363 {
364 FFSBreakPoint();
365
366 if (ForceVerify && FileObject)
367 {
368 SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
369 IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
370 FileObject->DeviceObject);
371 }
372
373 IrpContext->Irp->IoStatus = RaiseIosb;
374 FFSNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status);
375 }
376
377 return;
378 }
379
380
381 __drv_mustHoldCriticalRegion
382 PFFS_FCB
383 FFSv1AllocateFcb(
384 IN PFFS_VCB Vcb,
385 IN PFFS_MCB FFSMcb,
386 IN PFFSv1_INODE dinode1)
387 {
388 PFFS_FCB Fcb;
389
390 PAGED_CODE();
391
392 ExAcquireResourceExclusiveLite(
393 &FFSGlobal->LAResource,
394 TRUE);
395
396 Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)));
397
398 ExReleaseResourceForThreadLite(
399 &FFSGlobal->LAResource,
400 ExGetCurrentResourceThread());
401
402 if (Fcb == NULL)
403 {
404 Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG);
405
406 RtlZeroMemory(Fcb, sizeof(FFS_FCB));
407
408 SetFlag(Fcb->Flags, FCB_FROM_POOL);
409 }
410 else
411 {
412 RtlZeroMemory(Fcb, sizeof(FFS_FCB));
413 }
414
415 if (!Fcb)
416 {
417 return NULL;
418 }
419
420 Fcb->Identifier.Type = FFSFCB;
421 Fcb->Identifier.Size = sizeof(FFS_FCB);
422
423 FsRtlInitializeFileLock(
424 &Fcb->FileLockAnchor,
425 NULL,
426 NULL);
427
428 Fcb->OpenHandleCount = 0;
429 Fcb->ReferenceCount = 0;
430
431 Fcb->Vcb = Vcb;
432
433 #if DBG
434
435 Fcb->AnsiFileName.MaximumLength = (USHORT)
436 RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1;
437
438 Fcb->AnsiFileName.Buffer = (PUCHAR)
439 ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG);
440
441 if (!Fcb->AnsiFileName.Buffer)
442 {
443 goto errorout;
444 }
445
446 RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
447
448 FFSUnicodeToOEM(&(Fcb->AnsiFileName),
449 &(FFSMcb->ShortName));
450
451 #endif
452
453 FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
454
455 if ((dinode1->di_mode & IFMT) == IFDIR)
456 {
457 SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
458 }
459
460 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
461 FFSIsReadOnly(dinode1->di_mode))
462 {
463 SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
464 }
465
466 Fcb->dinode1 = dinode1;
467
468 Fcb->FFSMcb = FFSMcb;
469 FFSMcb->FFSFcb = Fcb;
470
471 RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
472
473 Fcb->Header.NodeTypeCode = (USHORT)FFSFCB;
474 Fcb->Header.NodeByteSize = sizeof(FFS_FCB);
475 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
476 Fcb->Header.Resource = &(Fcb->MainResource);
477 Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
478
479 {
480 ULONG Totalblocks = (Fcb->dinode1->di_blocks);
481 Fcb->Header.AllocationSize.QuadPart =
482 (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
483 }
484
485 Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode1->di_size);
486 Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
487
488 Fcb->SectionObject.DataSectionObject = NULL;
489 Fcb->SectionObject.SharedCacheMap = NULL;
490 Fcb->SectionObject.ImageSectionObject = NULL;
491
492 ExInitializeResourceLite(&(Fcb->MainResource));
493 ExInitializeResourceLite(&(Fcb->PagingIoResource));
494
495 InsertTailList(&Vcb->FcbList, &Fcb->Next);
496
497 #if DBG
498
499 ExAcquireResourceExclusiveLite(
500 &FFSGlobal->CountResource,
501 TRUE);
502
503 FFSGlobal->FcbAllocated++;
504
505 ExReleaseResourceForThreadLite(
506 &FFSGlobal->CountResource,
507 ExGetCurrentResourceThread());
508 #endif
509
510 return Fcb;
511
512 #if DBG
513 errorout:
514 #endif
515
516 if (Fcb)
517 {
518
519 #if DBG
520 if (Fcb->AnsiFileName.Buffer)
521 ExFreePool(Fcb->AnsiFileName.Buffer);
522 #endif
523
524 if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
525 {
526 ExFreePool(Fcb);
527 }
528 else
529 {
530 ExAcquireResourceExclusiveLite(
531 &FFSGlobal->LAResource,
532 TRUE);
533
534 ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
535
536 ExReleaseResourceForThreadLite(
537 &FFSGlobal->LAResource,
538 ExGetCurrentResourceThread());
539 }
540
541 }
542
543 return NULL;
544 }
545
546
547 __drv_mustHoldCriticalRegion
548 PFFS_FCB
549 FFSv2AllocateFcb(
550 IN PFFS_VCB Vcb,
551 IN PFFS_MCB FFSMcb,
552 IN PFFSv2_INODE dinode2)
553 {
554 PFFS_FCB Fcb;
555
556 PAGED_CODE();
557
558 ExAcquireResourceExclusiveLite(
559 &FFSGlobal->LAResource,
560 TRUE);
561
562 Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)));
563
564 ExReleaseResourceForThreadLite(
565 &FFSGlobal->LAResource,
566 ExGetCurrentResourceThread());
567
568 if (Fcb == NULL)
569 {
570 Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG);
571
572 RtlZeroMemory(Fcb, sizeof(FFS_FCB));
573
574 SetFlag(Fcb->Flags, FCB_FROM_POOL);
575 }
576 else
577 {
578 RtlZeroMemory(Fcb, sizeof(FFS_FCB));
579 }
580
581 if (!Fcb)
582 {
583 return NULL;
584 }
585
586 Fcb->Identifier.Type = FFSFCB;
587 Fcb->Identifier.Size = sizeof(FFS_FCB);
588
589 FsRtlInitializeFileLock(
590 &Fcb->FileLockAnchor,
591 NULL,
592 NULL);
593
594 Fcb->OpenHandleCount = 0;
595 Fcb->ReferenceCount = 0;
596
597 Fcb->Vcb = Vcb;
598
599 #if DBG
600
601 Fcb->AnsiFileName.MaximumLength = (USHORT)
602 RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1;
603
604 Fcb->AnsiFileName.Buffer = (PUCHAR)
605 ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG);
606
607 if (!Fcb->AnsiFileName.Buffer)
608 {
609 goto errorout;
610 }
611
612 RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
613
614 FFSUnicodeToOEM(&(Fcb->AnsiFileName),
615 &(FFSMcb->ShortName));
616
617 #endif
618
619 FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
620
621 if ((dinode2->di_mode & IFMT) == IFDIR)
622 {
623 SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
624 }
625
626 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
627 FFSIsReadOnly(dinode2->di_mode))
628 {
629 SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
630 }
631
632 Fcb->dinode2 = dinode2;
633
634 Fcb->FFSMcb = FFSMcb;
635 FFSMcb->FFSFcb = Fcb;
636
637 RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
638
639 Fcb->Header.NodeTypeCode = (USHORT)FFSFCB;
640 Fcb->Header.NodeByteSize = sizeof(FFS_FCB);
641 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
642 Fcb->Header.Resource = &(Fcb->MainResource);
643 Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
644
645 {
646 ULONG Totalblocks = (ULONG)(Fcb->dinode2->di_blocks);
647 Fcb->Header.AllocationSize.QuadPart =
648 (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
649 }
650
651 Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode2->di_size);
652 Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
653
654 Fcb->SectionObject.DataSectionObject = NULL;
655 Fcb->SectionObject.SharedCacheMap = NULL;
656 Fcb->SectionObject.ImageSectionObject = NULL;
657
658 ExInitializeResourceLite(&(Fcb->MainResource));
659 ExInitializeResourceLite(&(Fcb->PagingIoResource));
660
661 InsertTailList(&Vcb->FcbList, &Fcb->Next);
662
663 #if DBG
664
665 ExAcquireResourceExclusiveLite(
666 &FFSGlobal->CountResource,
667 TRUE);
668
669 FFSGlobal->FcbAllocated++;
670
671 ExReleaseResourceForThreadLite(
672 &FFSGlobal->CountResource,
673 ExGetCurrentResourceThread());
674 #endif
675
676 return Fcb;
677
678 #if DBG
679 errorout:
680 #endif
681
682 if (Fcb)
683 {
684
685 #if DBG
686 if (Fcb->AnsiFileName.Buffer)
687 ExFreePool(Fcb->AnsiFileName.Buffer);
688 #endif
689
690 if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
691 {
692 ExFreePool(Fcb);
693 }
694 else
695 {
696 ExAcquireResourceExclusiveLite(
697 &FFSGlobal->LAResource,
698 TRUE);
699
700 ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
701
702 ExReleaseResourceForThreadLite(
703 &FFSGlobal->LAResource,
704 ExGetCurrentResourceThread());
705 }
706
707 }
708
709 return NULL;
710 }
711
712
713 __drv_mustHoldCriticalRegion
714 VOID
715 FFSFreeFcb(
716 IN PFFS_FCB Fcb)
717 {
718 PFFS_VCB Vcb;
719
720 PAGED_CODE();
721
722 ASSERT(Fcb != NULL);
723
724 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
725 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
726
727 Vcb = Fcb->Vcb;
728
729 FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
730
731 ExDeleteResourceLite(&Fcb->MainResource);
732
733 ExDeleteResourceLite(&Fcb->PagingIoResource);
734
735 Fcb->FFSMcb->FFSFcb = NULL;
736
737 if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
738 {
739 if (Fcb->FFSMcb)
740 {
741 FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
742 FFSFreeMcb(Fcb->FFSMcb);
743 }
744 }
745
746 if (Fcb->LongName.Buffer)
747 {
748 ExFreePool(Fcb->LongName.Buffer);
749 Fcb->LongName.Buffer = NULL;
750 }
751
752 #if DBG
753 ExFreePool(Fcb->AnsiFileName.Buffer);
754 #endif
755
756 if (FS_VERSION == 1)
757 {
758 ExFreePool(Fcb->dinode1);
759 }
760 else
761 {
762 ExFreePool(Fcb->dinode2);
763 }
764
765 Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
766 Fcb->Header.NodeByteSize = (SHORT)0xC0C0;
767
768 if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
769 {
770 ExFreePool(Fcb);
771 }
772 else
773 {
774 ExAcquireResourceExclusiveLite(
775 &FFSGlobal->LAResource,
776 TRUE);
777
778 ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
779
780 ExReleaseResourceForThreadLite(
781 &FFSGlobal->LAResource,
782 ExGetCurrentResourceThread());
783 }
784
785 #if DBG
786
787 ExAcquireResourceExclusiveLite(
788 &FFSGlobal->CountResource,
789 TRUE);
790
791 FFSGlobal->FcbAllocated--;
792
793 ExReleaseResourceForThreadLite(
794 &FFSGlobal->CountResource,
795 ExGetCurrentResourceThread());
796 #endif
797
798 }
799
800
801 __drv_mustHoldCriticalRegion
802 PFFS_CCB
803 FFSAllocateCcb(
804 VOID)
805 {
806 PFFS_CCB Ccb;
807
808 PAGED_CODE();
809
810 ExAcquireResourceExclusiveLite(
811 &FFSGlobal->LAResource,
812 TRUE);
813
814 Ccb = (PFFS_CCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList)));
815
816 ExReleaseResourceForThreadLite(
817 &FFSGlobal->LAResource,
818 ExGetCurrentResourceThread());
819
820 if (Ccb == NULL)
821 {
822 Ccb = (PFFS_CCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_CCB), FFS_POOL_TAG);
823
824 RtlZeroMemory(Ccb, sizeof(FFS_CCB));
825
826 SetFlag(Ccb->Flags, CCB_FROM_POOL);
827 }
828 else
829 {
830 RtlZeroMemory(Ccb, sizeof(FFS_CCB));
831 }
832
833 if (!Ccb)
834 {
835 return NULL;
836 }
837
838 Ccb->Identifier.Type = FFSCCB;
839 Ccb->Identifier.Size = sizeof(FFS_CCB);
840
841 Ccb->CurrentByteOffset = 0;
842
843 Ccb->DirectorySearchPattern.Length = 0;
844 Ccb->DirectorySearchPattern.MaximumLength = 0;
845 Ccb->DirectorySearchPattern.Buffer = 0;
846
847 return Ccb;
848 }
849
850
851 __drv_mustHoldCriticalRegion
852 VOID
853 FFSFreeCcb(
854 IN PFFS_CCB Ccb)
855 {
856 PAGED_CODE();
857
858 ASSERT(Ccb != NULL);
859
860 ASSERT((Ccb->Identifier.Type == FFSCCB) &&
861 (Ccb->Identifier.Size == sizeof(FFS_CCB)));
862
863 if (Ccb->DirectorySearchPattern.Buffer != NULL)
864 {
865 ExFreePool(Ccb->DirectorySearchPattern.Buffer);
866 }
867
868 if (FlagOn(Ccb->Flags, CCB_FROM_POOL))
869 {
870 ExFreePool(Ccb);
871 }
872 else
873 {
874 ExAcquireResourceExclusiveLite(
875 &FFSGlobal->LAResource,
876 TRUE);
877
878 ExFreeToNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), Ccb);
879
880 ExReleaseResourceForThreadLite(
881 &FFSGlobal->LAResource,
882 ExGetCurrentResourceThread());
883 }
884 }
885
886
887 __drv_mustHoldCriticalRegion
888 PFFS_MCB
889 FFSAllocateMcb(
890 PFFS_VCB Vcb,
891 PUNICODE_STRING FileName,
892 ULONG FileAttr)
893 {
894 PFFS_MCB Mcb = NULL;
895 PLIST_ENTRY List = NULL;
896
897 ULONG Extra = 0;
898
899 PAGED_CODE();
900
901 #define MCB_NUM_SHIFT 0x04
902
903 if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT))
904 Extra = FFSGlobal->McbAllocated -
905 (FFSGlobal->MaxDepth << MCB_NUM_SHIFT) +
906 FFSGlobal->MaxDepth;
907
908 FFSPrint((DBG_INFO,
909 "FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n",
910 FFSGlobal->McbAllocated,
911 FFSGlobal->MaxDepth << MCB_NUM_SHIFT,
912 FFSGlobal->FcbAllocated,
913 FileName->Buffer));
914
915 List = Vcb->McbList.Flink;
916
917 while ((List != &(Vcb->McbList)) && (Extra > 0))
918 {
919 Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
920 List = List->Flink;
921
922 if ((Mcb->Inode != 2) && (Mcb->Child == NULL) &&
923 (Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb)))
924 {
925 FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n",
926 Mcb->ShortName.Buffer));
927
928 if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb))
929 {
930 FFSFreeMcb(Mcb);
931
932 Extra--;
933 }
934 }
935 }
936
937 ExAcquireResourceExclusiveLite(
938 &FFSGlobal->LAResource,
939 TRUE);
940
941 Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList(
942 &(FFSGlobal->FFSMcbLookasideList)));
943
944 ExReleaseResourceForThreadLite(
945 &FFSGlobal->LAResource,
946 ExGetCurrentResourceThread());
947
948 if (Mcb == NULL)
949 {
950 Mcb = (PFFS_MCB)ExAllocatePoolWithTag(PagedPool, sizeof(FFS_MCB), FFS_POOL_TAG);
951
952 RtlZeroMemory(Mcb, sizeof(FFS_MCB));
953
954 SetFlag(Mcb->Flags, MCB_FROM_POOL);
955 }
956 else
957 {
958 RtlZeroMemory(Mcb, sizeof(FFS_MCB));
959 }
960
961 if (!Mcb)
962 {
963 return NULL;
964 }
965
966 Mcb->Identifier.Type = FFSMCB;
967 Mcb->Identifier.Size = sizeof(FFS_MCB);
968
969 if (FileName && FileName->Length)
970 {
971 Mcb->ShortName.Length = FileName->Length;
972 Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;
973
974 Mcb->ShortName.Buffer = ExAllocatePoolWithTag(PagedPool, Mcb->ShortName.MaximumLength, FFS_POOL_TAG);
975
976 if (!Mcb->ShortName.Buffer)
977 goto errorout;
978
979 RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
980 RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
981 }
982
983 Mcb->FileAttr = FileAttr;
984
985 ExAcquireResourceExclusiveLite(
986 &FFSGlobal->CountResource,
987 TRUE);
988
989 FFSGlobal->McbAllocated++;
990
991 ExReleaseResourceForThreadLite(
992 &FFSGlobal->CountResource,
993 ExGetCurrentResourceThread());
994
995 return Mcb;
996
997 errorout:
998
999 if (Mcb)
1000 {
1001 if (Mcb->ShortName.Buffer)
1002 ExFreePool(Mcb->ShortName.Buffer);
1003
1004 if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
1005 {
1006 ExFreePool(Mcb);
1007 }
1008 else
1009 {
1010 ExAcquireResourceExclusiveLite(
1011 &FFSGlobal->LAResource,
1012 TRUE);
1013
1014 ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);
1015
1016 ExReleaseResourceForThreadLite(
1017 &FFSGlobal->LAResource,
1018 ExGetCurrentResourceThread());
1019 }
1020 }
1021
1022 return NULL;
1023 }
1024
1025
1026 __drv_mustHoldCriticalRegion
1027 VOID
1028 FFSFreeMcb(
1029 IN PFFS_MCB Mcb)
1030 {
1031 #ifndef __REACTOS__
1032 PFFS_MCB Parent = Mcb->Parent;
1033 #endif
1034 PAGED_CODE();
1035
1036 ASSERT(Mcb != NULL);
1037
1038 ASSERT((Mcb->Identifier.Type == FFSMCB) &&
1039 (Mcb->Identifier.Size == sizeof(FFS_MCB)));
1040
1041 FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));
1042
1043 if (Mcb->ShortName.Buffer)
1044 ExFreePool(Mcb->ShortName.Buffer);
1045
1046 if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
1047 {
1048 ExFreePool(Mcb);
1049 }
1050 else
1051 {
1052 ExAcquireResourceExclusiveLite(
1053 &FFSGlobal->LAResource,
1054 TRUE);
1055
1056 ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);
1057
1058 ExReleaseResourceForThreadLite(
1059 &FFSGlobal->LAResource,
1060 ExGetCurrentResourceThread());
1061 }
1062
1063 ExAcquireResourceExclusiveLite(
1064 &FFSGlobal->CountResource,
1065 TRUE);
1066
1067 FFSGlobal->McbAllocated--;
1068
1069 ExReleaseResourceForThreadLite(
1070 &FFSGlobal->CountResource,
1071 ExGetCurrentResourceThread());
1072 }
1073
1074
1075 __drv_mustHoldCriticalRegion
1076 PFFS_FCB
1077 FFSCreateFcbFromMcb(
1078 PFFS_VCB Vcb,
1079 PFFS_MCB Mcb)
1080 {
1081 PFFS_FCB Fcb = NULL;
1082 FFSv1_INODE dinode1;
1083 FFSv2_INODE dinode2;
1084
1085 PAGED_CODE();
1086
1087 if (Mcb->FFSFcb)
1088 return Mcb->FFSFcb;
1089
1090 if (FS_VERSION == 1)
1091 {
1092 if (FFSv1LoadInode(Vcb, Mcb->Inode, &dinode1))
1093 {
1094 PFFSv1_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE1_SIZE, FFS_POOL_TAG);
1095 if (!pTmpInode)
1096 {
1097 goto errorout;
1098 }
1099
1100 RtlCopyMemory(pTmpInode, &dinode1, DINODE1_SIZE);
1101 Fcb = FFSv1AllocateFcb(Vcb, Mcb, pTmpInode);
1102 if (!Fcb)
1103 {
1104 ExFreePool(pTmpInode);
1105 }
1106 }
1107 }
1108 else
1109 {
1110 if (FFSv2LoadInode(Vcb, Mcb->Inode, &dinode2))
1111 {
1112 PFFSv2_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE2_SIZE, FFS_POOL_TAG);
1113 if (!pTmpInode)
1114 {
1115 goto errorout;
1116 }
1117
1118 RtlCopyMemory(pTmpInode, &dinode2, DINODE2_SIZE);
1119 Fcb = FFSv2AllocateFcb(Vcb, Mcb, pTmpInode);
1120 if (!Fcb)
1121 {
1122 ExFreePool(pTmpInode);
1123 }
1124 }
1125 }
1126
1127 errorout:
1128
1129 return Fcb;
1130 }
1131
1132
1133 BOOLEAN
1134 FFSGetFullFileName(
1135 PFFS_MCB Mcb,
1136 PUNICODE_STRING FileName)
1137 {
1138 USHORT Length = 0;
1139 PFFS_MCB TmpMcb = Mcb;
1140 PUNICODE_STRING FileNames[256];
1141 SHORT Count = 0 , i = 0, j = 0;
1142
1143 PAGED_CODE();
1144
1145 while(TmpMcb && Count < 256)
1146 {
1147 if (TmpMcb->Inode == FFS_ROOT_INO)
1148 break;
1149
1150 FileNames[Count++] = &TmpMcb->ShortName;
1151 Length += (2 + TmpMcb->ShortName.Length);
1152
1153 TmpMcb = TmpMcb->Parent;
1154 }
1155
1156 if (Count >= 256)
1157 return FALSE;
1158
1159 if (Count == 0)
1160 Length = 2;
1161
1162 FileName->Length = Length;
1163 FileName->MaximumLength = Length + 2;
1164 FileName->Buffer = ExAllocatePoolWithTag(PagedPool, Length + 2, FFS_POOL_TAG);
1165
1166 if (!FileName->Buffer)
1167 {
1168 return FALSE;
1169 }
1170
1171 RtlZeroMemory(FileName->Buffer, FileName->MaximumLength);
1172
1173 if (Count == 0)
1174 {
1175 FileName->Buffer[0] = L'\\';
1176 return TRUE;
1177 }
1178
1179 for (i = Count - 1; i >= 0 && j < (SHORT)(FileName->MaximumLength); i--)
1180 {
1181 FileName->Buffer[j++] = L'\\';
1182
1183 RtlCopyMemory(&(FileName->Buffer[j]),
1184 FileNames[i]->Buffer,
1185 FileNames[i]->Length);
1186
1187 j += FileNames[i]->Length / 2;
1188 }
1189
1190 return TRUE;
1191 }
1192
1193
1194 PFFS_MCB
1195 FFSSearchMcbTree(
1196 PFFS_VCB Vcb,
1197 PFFS_MCB FFSMcb,
1198 ULONG Inode)
1199 {
1200 PFFS_MCB Mcb = NULL;
1201 PLIST_ENTRY List = NULL;
1202 BOOLEAN bFind = FALSE;
1203
1204 PAGED_CODE();
1205
1206 List = Vcb->McbList.Flink;
1207
1208 while ((!bFind) && (List != &(Vcb->McbList)))
1209 {
1210 Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
1211 List = List->Flink;
1212
1213 if (Mcb->Inode == Inode)
1214 {
1215 bFind = TRUE;
1216 break;
1217 }
1218 }
1219
1220 if (bFind)
1221 {
1222 ASSERT(Mcb != NULL);
1223 FFSRefreshMcb(Vcb, Mcb);
1224 }
1225 else
1226 {
1227 Mcb = NULL;
1228 }
1229
1230 return Mcb;
1231 }
1232
1233
1234 PFFS_MCB
1235 FFSSearchMcb(
1236 PFFS_VCB Vcb,
1237 PFFS_MCB Parent,
1238 PUNICODE_STRING FileName)
1239 {
1240 PFFS_MCB TmpMcb = Parent->Child;
1241
1242 PAGED_CODE();
1243
1244 while (TmpMcb)
1245 {
1246 if (!RtlCompareUnicodeString(
1247 &(TmpMcb->ShortName),
1248 FileName, TRUE))
1249 break;
1250
1251 TmpMcb = TmpMcb->Next;
1252 }
1253
1254 if (TmpMcb)
1255 {
1256 FFSRefreshMcb(Vcb, TmpMcb);
1257 }
1258
1259 return TmpMcb;
1260 }
1261
1262
1263 VOID
1264 FFSRefreshMcb(
1265 PFFS_VCB Vcb,
1266 PFFS_MCB Mcb)
1267 {
1268 PAGED_CODE();
1269
1270 ASSERT (IsFlagOn(Mcb->Flags, MCB_IN_TREE));
1271
1272 RemoveEntryList(&(Mcb->Link));
1273 InsertTailList(&(Vcb->McbList), &(Mcb->Link));
1274 }
1275
1276
1277 VOID
1278 FFSAddMcbNode(
1279 PFFS_VCB Vcb,
1280 PFFS_MCB Parent,
1281 PFFS_MCB Child)
1282 {
1283 PFFS_MCB TmpMcb = Parent->Child;
1284
1285 PAGED_CODE();
1286
1287 if(IsFlagOn(Child->Flags, MCB_IN_TREE))
1288 {
1289 FFSBreakPoint();
1290 FFSPrint((DBG_ERROR, "FFSAddMcbNode: Child Mcb is alreay in the tree.\n"));
1291 return;
1292 }
1293
1294 if (TmpMcb)
1295 {
1296 ASSERT(TmpMcb->Parent == Parent);
1297
1298 while (TmpMcb->Next)
1299 {
1300 TmpMcb = TmpMcb->Next;
1301 ASSERT(TmpMcb->Parent == Parent);
1302 }
1303
1304 TmpMcb->Next = Child;
1305 Child->Parent = Parent;
1306 Child->Next = NULL;
1307 }
1308 else
1309 {
1310 Parent->Child = Child;
1311 Child->Parent = Parent;
1312 Child->Next = NULL;
1313 }
1314
1315 InsertTailList(&(Vcb->McbList), &(Child->Link));
1316 SetFlag(Child->Flags, MCB_IN_TREE);
1317 }
1318
1319
1320 BOOLEAN
1321 FFSDeleteMcbNode(
1322 PFFS_VCB Vcb,
1323 PFFS_MCB McbTree,
1324 PFFS_MCB FFSMcb)
1325 {
1326 PFFS_MCB TmpMcb;
1327
1328 PAGED_CODE();
1329
1330 if(!IsFlagOn(FFSMcb->Flags, MCB_IN_TREE))
1331 {
1332 return TRUE;
1333 }
1334
1335 if (FFSMcb->Parent)
1336 {
1337 if (FFSMcb->Parent->Child == FFSMcb)
1338 {
1339 FFSMcb->Parent->Child = FFSMcb->Next;
1340 }
1341 else
1342 {
1343 TmpMcb = FFSMcb->Parent->Child;
1344
1345 while (TmpMcb && TmpMcb->Next != FFSMcb)
1346 TmpMcb = TmpMcb->Next;
1347
1348 if (TmpMcb)
1349 {
1350 TmpMcb->Next = FFSMcb->Next;
1351 }
1352 else
1353 {
1354 // error
1355 return FALSE;
1356 }
1357 }
1358 }
1359 else if (FFSMcb->Child)
1360 {
1361 return FALSE;
1362 }
1363
1364 RemoveEntryList(&(FFSMcb->Link));
1365 ClearFlag(FFSMcb->Flags, MCB_IN_TREE);
1366
1367 return TRUE;
1368 }
1369
1370
1371 __drv_mustHoldCriticalRegion
1372 VOID
1373 FFSFreeMcbTree(
1374 PFFS_MCB McbTree)
1375 {
1376 PAGED_CODE();
1377
1378 if (!McbTree)
1379 return;
1380
1381 if (McbTree->Child)
1382 {
1383 FFSFreeMcbTree(McbTree->Child);
1384 }
1385
1386 if (McbTree->Next)
1387 {
1388 PFFS_MCB Current;
1389 PFFS_MCB Next;
1390
1391 Current = McbTree->Next;
1392
1393 while (Current)
1394 {
1395 Next = Current->Next;
1396
1397 if (Current->Child)
1398 {
1399 FFSFreeMcbTree(Current->Child);
1400 }
1401
1402 FFSFreeMcb(Current);
1403 Current = Next;
1404 }
1405 }
1406
1407 FFSFreeMcb(McbTree);
1408 }
1409
1410
1411 BOOLEAN
1412 FFSCheckSetBlock(
1413 PFFS_IRP_CONTEXT IrpContext,
1414 PFFS_VCB Vcb,
1415 ULONG Block)
1416 {
1417 PAGED_CODE();
1418 #if 0
1419 ULONG Group, dwBlk, Length;
1420
1421 RTL_BITMAP BlockBitmap;
1422 PVOID BitmapCache;
1423 PBCB BitmapBcb;
1424
1425 LARGE_INTEGER Offset;
1426
1427 BOOLEAN bModified = FALSE;
1428
1429
1430 //Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
1431
1432 dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
1433
1434
1435 Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
1436 Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
1437
1438 if (Group == Vcb->ffs_groups - 1)
1439 {
1440 Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
1441
1442 /* s_blocks_count is integer multiple of s_blocks_per_group */
1443 if (Length == 0)
1444 Length = BLOCKS_PER_GROUP;
1445 }
1446 else
1447 {
1448 Length = BLOCKS_PER_GROUP;
1449 }
1450
1451 if (dwBlk >= Length)
1452 return FALSE;
1453
1454 if (!CcPinRead(Vcb->StreamObj,
1455 &Offset,
1456 Vcb->BlockSize,
1457 PIN_WAIT,
1458 &BitmapBcb,
1459 &BitmapCache))
1460 {
1461 FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n"));
1462 return FALSE;
1463 }
1464
1465 RtlInitializeBitMap(&BlockBitmap,
1466 BitmapCache,
1467 Length);
1468
1469 if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
1470 {
1471 FFSBreakPoint();
1472 RtlSetBits(&BlockBitmap, dwBlk, 1);
1473 bModified = TRUE;
1474 }
1475
1476 if (bModified)
1477 {
1478 CcSetDirtyPinnedData(BitmapBcb, NULL);
1479
1480 FFSRepinBcb(IrpContext, BitmapBcb);
1481
1482 FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
1483 }
1484
1485 {
1486 CcUnpinData(BitmapBcb);
1487 BitmapBcb = NULL;
1488 BitmapCache = NULL;
1489
1490 RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
1491 }
1492
1493 return (!bModified);
1494 #endif
1495 return FALSE;
1496 }
1497
1498
1499 BOOLEAN
1500 FFSCheckBitmapConsistency(
1501 PFFS_IRP_CONTEXT IrpContext,
1502 PFFS_VCB Vcb)
1503 {
1504 PAGED_CODE();
1505 #if 0
1506 ULONG i, j, InodeBlocks;
1507
1508 for (i = 0; i < Vcb->ffs_groups; i++)
1509 {
1510 FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_block_bitmap);
1511 FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_bitmap);
1512
1513
1514 if (i == Vcb->ffs_groups - 1)
1515 {
1516 InodeBlocks = ((INODES_COUNT % INODES_PER_GROUP) * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
1517 }
1518 else
1519 {
1520 InodeBlocks = (INODES_PER_GROUP * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
1521 }
1522
1523 for (j = 0; j < InodeBlocks; j++)
1524 FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_table + j);
1525 }
1526
1527 return TRUE;
1528 #endif
1529 return FALSE;
1530 }
1531
1532
1533 VOID
1534 FFSInsertVcb(
1535 PFFS_VCB Vcb)
1536 {
1537 InsertTailList(&(FFSGlobal->VcbList), &Vcb->Next);
1538 }
1539
1540
1541 VOID
1542 FFSRemoveVcb(
1543 PFFS_VCB Vcb)
1544 {
1545 RemoveEntryList(&Vcb->Next);
1546 }
1547
1548
1549 __drv_mustHoldCriticalRegion
1550 NTSTATUS
1551 FFSInitializeVcb(
1552 IN PFFS_IRP_CONTEXT IrpContext,
1553 IN PFFS_VCB Vcb,
1554 IN PFFS_SUPER_BLOCK FFSSb,
1555 IN PDEVICE_OBJECT TargetDevice,
1556 IN PDEVICE_OBJECT VolumeDevice,
1557 IN PVPB Vpb)
1558 {
1559 BOOLEAN VcbResourceInitialized = FALSE;
1560 USHORT VolumeLabelLength;
1561 ULONG IoctlSize;
1562 BOOLEAN NotifySyncInitialized = FALSE;
1563 LONGLONG DiskSize;
1564 LONGLONG PartSize;
1565 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1566 UNICODE_STRING RootNode;
1567 USHORT Buffer[2];
1568 ULONG ChangeCount;
1569
1570 PAGED_CODE();
1571
1572 _SEH2_TRY
1573 {
1574 if (!Vpb)
1575 {
1576 Status = STATUS_DEVICE_NOT_READY;
1577 _SEH2_LEAVE;
1578 }
1579
1580 Buffer[0] = L'\\';
1581 Buffer[1] = 0;
1582
1583 RootNode.Buffer = Buffer;
1584 RootNode.MaximumLength = RootNode.Length = 2;
1585
1586 Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode,
1587 FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);
1588
1589 if (!Vcb->McbTree)
1590 {
1591 _SEH2_LEAVE;
1592 }
1593
1594 #if FFS_READ_ONLY
1595 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1596 #endif // FFS_READ_ONLY
1597
1598 if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA))
1599 {
1600 SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
1601 }
1602
1603 if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
1604 {
1605 SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
1606 }
1607 #if 0
1608 if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
1609 {
1610 if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
1611 {
1612 ClearFlag(Vcb->Flags, VCB_READ_ONLY);
1613 }
1614 else
1615 {
1616 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1617 }
1618 }
1619 else
1620 #endif
1621 {
1622 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1623 }
1624
1625 ExInitializeResourceLite(&Vcb->MainResource);
1626 ExInitializeResourceLite(&Vcb->PagingIoResource);
1627
1628 ExInitializeResourceLite(&Vcb->McbResource);
1629
1630 VcbResourceInitialized = TRUE;
1631
1632 Vcb->McbTree->Inode = FFS_ROOT_INO;
1633
1634 Vcb->Vpb = Vpb;
1635
1636 Vcb->RealDevice = Vpb->RealDevice;
1637 Vpb->DeviceObject = VolumeDevice;
1638
1639 {
1640 UNICODE_STRING LabelName;
1641 OEM_STRING OemName;
1642
1643 LabelName.MaximumLength = 16 * 2;
1644 LabelName.Length = 0;
1645 LabelName.Buffer = Vcb->Vpb->VolumeLabel;
1646
1647 RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);
1648
1649 VolumeLabelLength = 16;
1650
1651 while((VolumeLabelLength > 0) &&
1652 ((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) ||
1653 (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20)))
1654 {
1655 VolumeLabelLength--;
1656 }
1657
1658 OemName.Buffer = FFSSb->fs_volname;
1659 OemName.MaximumLength = 16;
1660 OemName.Length = VolumeLabelLength;
1661
1662 Status = FFSOEMToUnicode(&LabelName,
1663 &OemName);
1664
1665 if (!NT_SUCCESS(Status))
1666 {
1667 _SEH2_LEAVE;
1668 }
1669
1670 Vpb->VolumeLabelLength = LabelName.Length;
1671 }
1672
1673 Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1];
1674
1675 Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice);
1676
1677 if (Vcb->StreamObj)
1678 {
1679 Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
1680 Vcb->StreamObj->Vpb = Vcb->Vpb;
1681 Vcb->StreamObj->ReadAccess = TRUE;
1682 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
1683 {
1684 Vcb->StreamObj->WriteAccess = TRUE;
1685 Vcb->StreamObj->DeleteAccess = TRUE;
1686 }
1687 else
1688 {
1689 Vcb->StreamObj->WriteAccess = TRUE;
1690 Vcb->StreamObj->DeleteAccess = TRUE;
1691 }
1692 Vcb->StreamObj->FsContext = (PVOID) Vcb;
1693 Vcb->StreamObj->FsContext2 = NULL;
1694 Vcb->StreamObj->Vpb = Vcb->Vpb;
1695
1696 SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1697 }
1698 else
1699 {
1700 _SEH2_LEAVE;
1701 }
1702
1703 InitializeListHead(&Vcb->FcbList);
1704
1705 InitializeListHead(&Vcb->NotifyList);
1706
1707 FsRtlNotifyInitializeSync(&Vcb->NotifySync);
1708
1709 NotifySyncInitialized = TRUE;
1710
1711 Vcb->DeviceObject = VolumeDevice;
1712
1713 Vcb->TargetDeviceObject = TargetDevice;
1714
1715 Vcb->OpenFileHandleCount = 0;
1716
1717 Vcb->ReferenceCount = 0;
1718
1719 Vcb->ffs_super_block = FFSSb;
1720
1721 Vcb->Header.NodeTypeCode = (USHORT) FFSVCB;
1722 Vcb->Header.NodeByteSize = sizeof(FFS_VCB);
1723 Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
1724 Vcb->Header.Resource = &(Vcb->MainResource);
1725 Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);
1726
1727 Vcb->Vpb->SerialNumber = 'PS';
1728
1729 DiskSize =
1730 Vcb->DiskGeometry.Cylinders.QuadPart *
1731 Vcb->DiskGeometry.TracksPerCylinder *
1732 Vcb->DiskGeometry.SectorsPerTrack *
1733 Vcb->DiskGeometry.BytesPerSector;
1734
1735 IoctlSize = sizeof(PARTITION_INFORMATION);
1736
1737 Status = FFSDiskIoControl(
1738 TargetDevice,
1739 IOCTL_DISK_GET_PARTITION_INFO,
1740 NULL,
1741 0,
1742 &Vcb->PartitionInformation,
1743 &IoctlSize);
1744
1745 PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;
1746
1747 if (!NT_SUCCESS(Status))
1748 {
1749 Vcb->PartitionInformation.StartingOffset.QuadPart = 0;
1750
1751 Vcb->PartitionInformation.PartitionLength.QuadPart =
1752 DiskSize;
1753
1754 PartSize = DiskSize;
1755
1756 Status = STATUS_SUCCESS;
1757 }
1758
1759 IoctlSize = sizeof(ULONG);
1760 Status = FFSDiskIoControl(
1761 TargetDevice,
1762 IOCTL_DISK_CHECK_VERIFY,
1763 NULL,
1764 0,
1765 &ChangeCount,
1766 &IoctlSize);
1767
1768 if (!NT_SUCCESS(Status))
1769 {
1770 _SEH2_LEAVE;
1771 }
1772
1773 Vcb->ChangeCount = ChangeCount;
1774
1775 Vcb->Header.AllocationSize.QuadPart =
1776 Vcb->Header.FileSize.QuadPart = PartSize;
1777
1778 Vcb->Header.ValidDataLength.QuadPart =
1779 (LONGLONG)(0x7fffffffffffffff);
1780 /*
1781 Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count)
1782 * (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size);
1783 Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
1784 Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
1785 */
1786
1787 {
1788 CC_FILE_SIZES FileSizes;
1789
1790 FileSizes.AllocationSize.QuadPart =
1791 FileSizes.FileSize.QuadPart =
1792 Vcb->Header.AllocationSize.QuadPart;
1793
1794 FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);
1795
1796 CcInitializeCacheMap(Vcb->StreamObj,
1797 &FileSizes,
1798 TRUE,
1799 &(FFSGlobal->CacheManagerNoOpCallbacks),
1800 Vcb);
1801 }
1802 #if 0 // LoadGroup XXX
1803 if (!FFSLoadGroup(Vcb))
1804 {
1805 Status = STATUS_UNSUCCESSFUL;
1806 _SEH2_LEAVE;
1807 }
1808 #endif
1809 FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
1810 InitializeListHead(&(Vcb->McbList));
1811
1812 if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP))
1813 {
1814 FFSCheckBitmapConsistency(IrpContext, Vcb);
1815 }
1816
1817 {
1818 ULONG dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1};
1819 ULONG dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0};
1820 ULONG i;
1821
1822 if (FS_VERSION == 1)
1823 {
1824 for (i = 0; i < FFS_BLOCK_TYPES; i++)
1825 {
1826 dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);
1827
1828 if (i > 0)
1829 {
1830 dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
1831 }
1832
1833 Vcb->dwData[i] = dwData[i];
1834 Vcb->dwMeta[i] = dwMeta[i];
1835 }
1836 }
1837 else
1838 {
1839 for (i = 0; i < FFS_BLOCK_TYPES; i++)
1840 {
1841 dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i);
1842
1843 if (i > 0)
1844 {
1845 dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3));
1846 }
1847
1848 Vcb->dwData[i] = dwData[i];
1849 Vcb->dwMeta[i] = dwMeta[i];
1850 }
1851 }
1852 }
1853
1854 SetFlag(Vcb->Flags, VCB_INITIALIZED);
1855 }
1856
1857 _SEH2_FINALLY
1858 {
1859 if (!NT_SUCCESS(Status))
1860 {
1861 if (NotifySyncInitialized)
1862 {
1863 FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
1864 }
1865
1866 if (Vcb->ffs_super_block)
1867 {
1868 ExFreePool(Vcb->ffs_super_block);
1869 Vcb->ffs_super_block = NULL;
1870 }
1871
1872 if (VcbResourceInitialized)
1873 {
1874 ExDeleteResourceLite(&Vcb->MainResource);
1875 ExDeleteResourceLite(&Vcb->PagingIoResource);
1876 }
1877 }
1878 } _SEH2_END;
1879
1880 return Status;
1881 }
1882
1883
1884 __drv_mustHoldCriticalRegion
1885 VOID
1886 FFSFreeVcb(
1887 IN PFFS_VCB Vcb)
1888 {
1889 PAGED_CODE();
1890
1891 ASSERT(Vcb != NULL);
1892
1893 ASSERT((Vcb->Identifier.Type == FFSVCB) &&
1894 (Vcb->Identifier.Size == sizeof(FFS_VCB)));
1895
1896 FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
1897
1898 if (Vcb->StreamObj)
1899 {
1900 if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
1901 {
1902 IO_STATUS_BLOCK IoStatus;
1903
1904 CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
1905 ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
1906 }
1907
1908 if (Vcb->StreamObj->PrivateCacheMap)
1909 FFSSyncUninitializeCacheMap(Vcb->StreamObj);
1910
1911 ObDereferenceObject(Vcb->StreamObj);
1912 Vcb->StreamObj = NULL;
1913 }
1914
1915 #if DBG
1916 if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0)
1917 {
1918 LONGLONG DirtyVba;
1919 LONGLONG DirtyLba;
1920 LONGLONG DirtyLength;
1921 int i;
1922
1923 for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++)
1924 {
1925 FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
1926 FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
1927 FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
1928 }
1929
1930 FFSBreakPoint();
1931 }
1932 #endif
1933
1934 FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs));
1935
1936 FFSFreeMcbTree(Vcb->McbTree);
1937
1938 if (Vcb->ffs_super_block)
1939 {
1940 ExFreePool(Vcb->ffs_super_block);
1941 Vcb->ffs_super_block = NULL;
1942 }
1943
1944 ExDeleteResourceLite(&Vcb->McbResource);
1945
1946 ExDeleteResourceLite(&Vcb->PagingIoResource);
1947
1948 ExDeleteResourceLite(&Vcb->MainResource);
1949
1950 IoDeleteDevice(Vcb->DeviceObject);
1951 }
1952
1953
1954 VOID
1955 FFSSyncUninitializeCacheMap(
1956 IN PFILE_OBJECT FileObject)
1957 {
1958 CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent;
1959 NTSTATUS WaitStatus;
1960 LARGE_INTEGER FFSLargeZero = {0, 0};
1961
1962 PAGED_CODE();
1963
1964 KeInitializeEvent(&UninitializeCompleteEvent.Event,
1965 SynchronizationEvent,
1966 FALSE);
1967
1968 CcUninitializeCacheMap(FileObject,
1969 &FFSLargeZero,
1970 &UninitializeCompleteEvent);
1971
1972 WaitStatus = KeWaitForSingleObject(&UninitializeCompleteEvent.Event,
1973 Executive,
1974 KernelMode,
1975 FALSE,
1976 NULL);
1977
1978 ASSERT (NT_SUCCESS(WaitStatus));
1979 }