ReactOS 0.4.16-dev-401-g45b008d
btrfs.c
Go to the documentation of this file.
1/* Copyright (c) Mark Harmstone 2016-17
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18#ifdef _DEBUG
19#define DEBUG
20#endif
21
22#include "btrfs_drv.h"
23#include "xxhash.h"
24#include "crc32c.h"
25#ifndef __REACTOS__
26#ifndef _MSC_VER
27#include <cpuid.h>
28#else
29#include <intrin.h>
30#endif
31#endif // __REACTOS__
32#include <ntddscsi.h>
33#include "btrfs.h"
34#include <ata.h>
35
36#ifndef _MSC_VER
37#include <initguid.h>
38#include <ntddstor.h>
39#undef INITGUID
40#endif
41
42#include <ntdddisk.h>
43#include <ntddvol.h>
44
45#ifdef _MSC_VER
46#include <initguid.h>
47#include <ntddstor.h>
48#undef INITGUID
49#endif
50
51#include <ntstrsafe.h>
52
53#define INCOMPAT_SUPPORTED (BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL | BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS | \
54 BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO | BTRFS_INCOMPAT_FLAGS_BIG_METADATA | BTRFS_INCOMPAT_FLAGS_RAID56 | \
55 BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA | BTRFS_INCOMPAT_FLAGS_NO_HOLES | \
56 BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD | BTRFS_INCOMPAT_FLAGS_METADATA_UUID | BTRFS_INCOMPAT_FLAGS_RAID1C34)
57#define COMPAT_RO_SUPPORTED (BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE | BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID | \
58 BTRFS_COMPAT_RO_FLAGS_VERITY)
59
60static const WCHAR device_name[] = {'\\','B','t','r','f','s',0};
61static const WCHAR dosdevice_name[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','B','t','r','f','s',0};
62
63DEFINE_GUID(BtrfsBusInterface, 0x4d414874, 0x6865, 0x6761, 0x6d, 0x65, 0x83, 0x69, 0x17, 0x9a, 0x7d, 0x1d);
64
88bool log_started = false;
101bool diskacc = false;
105bool finished_probing = false;
107bool degraded_wait = true;
109bool shutting_down = false;
112extern uint64_t boot_subvol;
113
114#ifdef _DEBUG
115PFILE_OBJECT comfo = NULL;
116PDEVICE_OBJECT comdo = NULL;
117HANDLE log_handle = NULL;
118ERESOURCE log_lock;
119HANDLE serial_thread_handle = NULL;
120
121static void init_serial(bool first_time);
122#endif
123
125static void __stdcall do_xor_basic(uint8_t* buf1, uint8_t* buf2, uint32_t len);
126
128
129typedef struct {
133
134// no longer in Windows headers??
136
137#ifdef _DEBUG
138_Function_class_(IO_COMPLETION_ROUTINE)
139static NTSTATUS __stdcall dbg_completion(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID conptr) {
140 read_context* context = conptr;
141
143
144 context->iosb = Irp->IoStatus;
145 KeSetEvent(&context->Event, 0, false);
146
148}
149
150#define DEBUG_MESSAGE_LEN 1024
151
152#ifdef DEBUG_LONG_MESSAGES
153void _debug_message(_In_ const char* func, _In_ const char* file, _In_ unsigned int line, _In_ char* s, ...) {
154#else
155void _debug_message(_In_ const char* func, _In_ char* s, ...) {
156#endif
160 PIRP Irp;
161 va_list ap;
162 char *buf2, *buf;
165
166 buf2 = ExAllocatePoolWithTag(NonPagedPool, DEBUG_MESSAGE_LEN, ALLOC_TAG);
167
168 if (!buf2) {
169 DbgPrint("Couldn't allocate buffer in debug_message\n");
170 return;
171 }
172
173#ifdef DEBUG_LONG_MESSAGES
174 sprintf(buf2, "%p:%s:%s:%u:", (void*)PsGetCurrentThread(), func, file, line);
175#else
176 sprintf(buf2, "%p:%s:", (void*)PsGetCurrentThread(), func);
177#endif
178 buf = &buf2[strlen(buf2)];
179
180 va_start(ap, s);
181
182 RtlStringCbVPrintfA(buf, DEBUG_MESSAGE_LEN - strlen(buf2), s, ap);
183
184 ExAcquireResourceSharedLite(&log_lock, true);
185
186 if (!log_started || (log_device.Length == 0 && log_file.Length == 0)) {
187 DbgPrint(buf2);
188 } else if (log_device.Length > 0) {
189 if (!comdo) {
190 DbgPrint(buf2);
191 goto exit2;
192 }
193
194 length = (uint32_t)strlen(buf2);
195
196 offset.u.LowPart = 0;
197 offset.u.HighPart = 0;
198
200
202
203 Irp = IoAllocateIrp(comdo->StackSize, false);
204
205 if (!Irp) {
206 DbgPrint("IoAllocateIrp failed\n");
207 goto exit2;
208 }
209
212 IrpSp->FileObject = comfo;
213
214 if (comdo->Flags & DO_BUFFERED_IO) {
215 Irp->AssociatedIrp.SystemBuffer = buf2;
216
217 Irp->Flags = IRP_BUFFERED_IO;
218 } else if (comdo->Flags & DO_DIRECT_IO) {
219 Irp->MdlAddress = IoAllocateMdl(buf2, length, false, false, NULL);
220 if (!Irp->MdlAddress) {
221 DbgPrint("IoAllocateMdl failed\n");
222 goto exit;
223 }
224
225 MmBuildMdlForNonPagedPool(Irp->MdlAddress);
226 } else {
227 Irp->UserBuffer = buf2;
228 }
229
230 IrpSp->Parameters.Write.Length = length;
231 IrpSp->Parameters.Write.ByteOffset = offset;
232
233 Irp->UserIosb = &context.iosb;
234
235 Irp->UserEvent = &context.Event;
236
237 IoSetCompletionRoutine(Irp, dbg_completion, &context, true, true, true);
238
239 Status = IoCallDriver(comdo, Irp);
240
241 if (Status == STATUS_PENDING) {
243 Status = context.iosb.Status;
244 }
245
246 if (comdo->Flags & DO_DIRECT_IO)
247 IoFreeMdl(Irp->MdlAddress);
248
249 if (!NT_SUCCESS(Status)) {
250 DbgPrint("failed to write to COM1 - error %08lx\n", Status);
251 goto exit;
252 }
253
254exit:
255 IoFreeIrp(Irp);
256 } else if (log_handle != NULL) {
258
259 length = (uint32_t)strlen(buf2);
260
261 Status = ZwWriteFile(log_handle, NULL, NULL, NULL, &iosb, buf2, length, NULL, NULL);
262
263 if (!NT_SUCCESS(Status)) {
264 DbgPrint("failed to write to file - error %08lx\n", Status);
265 }
266 }
267
268exit2:
269 ExReleaseResourceLite(&log_lock);
270
271 va_end(ap);
272
273 if (buf2)
274 ExFreePool(buf2);
275}
276#endif
277
279 if (!IoGetTopLevelIrp()) {
281 return true;
282 }
283
284 return false;
285}
286
287static void __stdcall do_xor_basic(uint8_t* buf1, uint8_t* buf2, uint32_t len) {
288 uint32_t j;
289
290#if defined(_ARM_) || defined(_ARM64_)
291 uint64x2_t x1, x2;
292
293 if (((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
294 while (len >= 16) {
295 x1 = vld1q_u64((const uint64_t*)buf1);
296 x2 = vld1q_u64((const uint64_t*)buf2);
297 x1 = veorq_u64(x1, x2);
298 vst1q_u64((uint64_t*)buf1, x1);
299
300 buf1 += 16;
301 buf2 += 16;
302 len -= 16;
303 }
304 }
305#endif
306
307#if defined(_AMD64_) || defined(_ARM64_)
308 while (len > 8) {
309 *(uint64_t*)buf1 ^= *(uint64_t*)buf2;
310 buf1 += 8;
311 buf2 += 8;
312 len -= 8;
313 }
314#endif
315
316 while (len > 4) {
317 *(uint32_t*)buf1 ^= *(uint32_t*)buf2;
318 buf1 += 4;
319 buf2 += 4;
320 len -= 4;
321 }
322
323 for (j = 0; j < len; j++) {
324 *buf1 ^= *buf2;
325 buf1++;
326 buf2++;
327 }
328}
329
330_Function_class_(DRIVER_UNLOAD)
332 UNICODE_STRING dosdevice_nameW;
333
334 TRACE("(%p)\n", DriverObject);
335
336 dosdevice_nameW.Buffer = (WCHAR*)dosdevice_name;
337 dosdevice_nameW.Length = dosdevice_nameW.MaximumLength = sizeof(dosdevice_name) - sizeof(WCHAR);
338
339 IoDeleteSymbolicLink(&dosdevice_nameW);
340 IoDeleteDevice(DriverObject->DeviceObject);
341
342 while (!IsListEmpty(&uid_map_list)) {
344 uid_map* um = CONTAINING_RECORD(le, uid_map, listentry);
345
346 ExFreePool(um->sid);
347
348 ExFreePool(um);
349 }
350
351 while (!IsListEmpty(&gid_map_list)) {
353
354 ExFreePool(gm->sid);
355 ExFreePool(gm);
356 }
357
358 // FIXME - free volumes and their devpaths
359
360#ifdef _DEBUG
361 if (comfo)
362 ObDereferenceObject(comfo);
363
364 if (log_handle)
365 ZwClose(log_handle);
366#endif
367
370
371 if (log_device.Buffer)
373
374 if (log_file.Buffer)
376
379
380#ifdef _DEBUG
381 ExDeleteResourceLite(&log_lock);
382#endif
384}
385
387 KEY searchkey;
388 traverse_ptr tp, prev_tp;
390
391 // get last entry
392 searchkey.obj_id = 0xffffffffffffffff;
393 searchkey.obj_type = 0xff;
394 searchkey.offset = 0xffffffffffffffff;
395
396 Status = find_item(Vcb, r, &tp, &searchkey, false, Irp);
397 if (!NT_SUCCESS(Status)) {
398 ERR("error - find_item returned %08lx\n", Status);
399 return false;
400 }
401
403 r->lastinode = tp.item->key.obj_id;
404 TRACE("last inode for tree %I64x is %I64x\n", r->id, r->lastinode);
405 return true;
406 }
407
408 while (find_prev_item(Vcb, &tp, &prev_tp, Irp)) {
409 tp = prev_tp;
410
411 TRACE("moving on to %I64x,%x,%I64x\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
412
414 r->lastinode = tp.item->key.obj_id;
415 TRACE("last inode for tree %I64x is %I64x\n", r->id, r->lastinode);
416 return true;
417 }
418 }
419
420 r->lastinode = SUBVOL_ROOT_INODE;
421
422 WARN("no INODE_ITEMs in tree %I64x\n", r->id);
423
424 return true;
425}
426
428static bool extract_xattr(_In_reads_bytes_(size) void* item, _In_ USHORT size, _In_z_ char* name, _Out_ uint8_t** data, _Out_ uint16_t* datalen) {
429 DIR_ITEM* xa = (DIR_ITEM*)item;
430 USHORT xasize;
431
432 while (true) {
433 if (size < sizeof(DIR_ITEM) || size < (sizeof(DIR_ITEM) - 1 + xa->m + xa->n)) {
434 WARN("DIR_ITEM is truncated\n");
435 return false;
436 }
437
438 if (xa->n == strlen(name) && RtlCompareMemory(name, xa->name, xa->n) == xa->n) {
439 TRACE("found xattr %s\n", name);
440
441 *datalen = xa->m;
442
443 if (xa->m > 0) {
445 if (!*data) {
446 ERR("out of memory\n");
447 return false;
448 }
449
450 RtlCopyMemory(*data, &xa->name[xa->n], xa->m);
451 } else
452 *data = NULL;
453
454 return true;
455 }
456
457 xasize = sizeof(DIR_ITEM) - 1 + xa->m + xa->n;
458
459 if (size > xasize) {
460 size -= xasize;
461 xa = (DIR_ITEM*)&xa->name[xa->m + xa->n];
462 } else
463 break;
464 }
465
466 TRACE("xattr %s not found\n", name);
467
468 return false;
469}
470
471_Success_(return)
472bool get_xattr(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* subvol, _In_ uint64_t inode, _In_z_ char* name, _In_ uint32_t crc32,
474 KEY searchkey;
477
478 TRACE("(%p, %I64x, %I64x, %s, %08x, %p, %p)\n", Vcb, subvol->id, inode, name, crc32, data, datalen);
479
480 searchkey.obj_id = inode;
481 searchkey.obj_type = TYPE_XATTR_ITEM;
482 searchkey.offset = crc32;
483
484 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
485 if (!NT_SUCCESS(Status)) {
486 ERR("error - find_item returned %08lx\n", Status);
487 return false;
488 }
489
490 if (keycmp(tp.item->key, searchkey)) {
491 TRACE("could not find item (%I64x,%x,%I64x)\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
492 return false;
493 }
494
495 if (tp.item->size < sizeof(DIR_ITEM)) {
496 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
497 return false;
498 }
499
500 return extract_xattr(tp.item->data, tp.item->size, name, data, datalen);
501}
502
508 device_extension* Vcb = DeviceObject->DeviceExtension;
509 bool top_level;
510
512
513 TRACE("close\n");
514
515 top_level = is_top_level(Irp);
516
518 TRACE("Closing file system\n");
520 goto end;
521 } else if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
523 goto end;
524 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
526 goto end;
527 }
528
530
531 // FIXME - call FsRtlNotifyUninitializeSync(&Vcb->NotifySync) if unmounting
532
534
535end:
536 Irp->IoStatus.Status = Status;
537 Irp->IoStatus.Information = 0;
538
540
541 if (top_level)
543
544 TRACE("returning %08lx\n", Status);
545
547
548 return Status;
549}
550
553static NTSTATUS __stdcall drv_flush_buffers(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
557 fcb* fcb = FileObject->FsContext;
558 device_extension* Vcb = DeviceObject->DeviceExtension;
559 bool top_level;
560
562
563 TRACE("flush buffers\n");
564
565 top_level = is_top_level(Irp);
566
567 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
569 goto end;
570 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
572 goto end;
573 }
574
575 if (!fcb) {
576 ERR("fcb was NULL\n");
578 goto end;
579 }
580
581 if (fcb == Vcb->volume_fcb) {
583 goto end;
584 }
585
587
588 Irp->IoStatus.Information = 0;
589
590 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
591
593 Irp->IoStatus.Status = Status;
594
595 if (fcb->type != BTRFS_TYPE_DIRECTORY) {
596 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &Irp->IoStatus);
597
598 if (fcb->Header.PagingIoResource) {
599 ExAcquireResourceExclusiveLite(fcb->Header.PagingIoResource, true);
600 ExReleaseResourceLite(fcb->Header.PagingIoResource);
601 }
602
603 Status = Irp->IoStatus.Status;
604 }
605
606end:
608
609 TRACE("returning %08lx\n", Status);
610
611 if (top_level)
613
615
616 return Status;
617}
618
620 uint64_t nfactor, dfactor, sectors_used;
621
622 if (Vcb->data_flags & BLOCK_FLAG_DUPLICATE || Vcb->data_flags & BLOCK_FLAG_RAID1 || Vcb->data_flags & BLOCK_FLAG_RAID10) {
623 nfactor = 1;
624 dfactor = 2;
625 } else if (Vcb->data_flags & BLOCK_FLAG_RAID5) {
626 nfactor = Vcb->superblock.num_devices - 1;
627 dfactor = Vcb->superblock.num_devices;
628 } else if (Vcb->data_flags & BLOCK_FLAG_RAID6) {
629 nfactor = Vcb->superblock.num_devices - 2;
630 dfactor = Vcb->superblock.num_devices;
631 } else if (Vcb->data_flags & BLOCK_FLAG_RAID1C3) {
632 nfactor = 1;
633 dfactor = 3;
634 } else if (Vcb->data_flags & BLOCK_FLAG_RAID1C4) {
635 nfactor = 1;
636 dfactor = 4;
637 } else {
638 nfactor = 1;
639 dfactor = 1;
640 }
641
642 sectors_used = (Vcb->superblock.bytes_used >> Vcb->sector_shift) * nfactor / dfactor;
643
644 *totalsize = (Vcb->superblock.total_bytes >> Vcb->sector_shift) * nfactor / dfactor;
645 *freespace = sectors_used > *totalsize ? 0 : (*totalsize - sectors_used);
646}
647
648#ifndef __REACTOS__
649// simplified version of FsRtlAreNamesEqual, which can be a bottleneck!
650static bool compare_strings(const UNICODE_STRING* us1, const UNICODE_STRING* us2) {
651 if (us1->Length != us2->Length)
652 return false;
653
654 WCHAR* s1 = us1->Buffer;
655 WCHAR* s2 = us2->Buffer;
656
657 for (unsigned int i = 0; i < us1->Length; i++) {
658 WCHAR c1 = *s1;
659 WCHAR c2 = *s2;
660
661 if (c1 != c2) {
662 if (c1 >= 'a' && c1 <= 'z')
663 c1 = c1 - 'a' + 'A';
664
665 if (c2 >= 'a' && c2 <= 'z')
666 c2 = c2 - 'a' + 'A';
667
668 if (c1 != c2)
669 return false;
670 }
671
672 s1++;
673 s2++;
674 }
675
676 return true;
677}
678
679#define INIT_UNICODE_STRING(var, val) UNICODE_STRING us##var; us##var.Buffer = (WCHAR*)val; us##var.Length = us##var.MaximumLength = sizeof(val) - sizeof(WCHAR);
680
681// This function exists because we have to lie about our FS type in certain situations.
682// MPR!MprGetConnection queries the FS type, and compares it to a whitelist. If it doesn't match,
683// it will return ERROR_NO_NET_OR_BAD_PATH, which prevents UAC from working.
684// The command mklink refuses to create hard links on anything other than NTFS, so we have to
685// blacklist cmd.exe too.
686
687static bool lie_about_fs_type() {
690 PPEB peb;
691 LIST_ENTRY* le;
692 ULONG retlen;
693#ifdef _AMD64_
694 ULONG_PTR wow64info;
695#endif
696
697 INIT_UNICODE_STRING(mpr, L"MPR.DLL");
698 INIT_UNICODE_STRING(cmd, L"CMD.EXE");
699 INIT_UNICODE_STRING(fsutil, L"FSUTIL.EXE");
700 INIT_UNICODE_STRING(storsvc, L"STORSVC.DLL");
701
702 /* Not doing a Volkswagen, honest! Some IFS tests won't run if not recognized FS. */
703 INIT_UNICODE_STRING(ifstest, L"IFSTEST.EXE");
704
705 if (!PsGetCurrentProcess())
706 return false;
707
708#ifdef _AMD64_
710
711 if (NT_SUCCESS(Status) && wow64info != 0)
712 return true;
713#endif
714
716
717 if (!NT_SUCCESS(Status)) {
718 ERR("ZwQueryInformationProcess returned %08lx\n", Status);
719 return false;
720 }
721
722 if (!pbi.PebBaseAddress)
723 return false;
724
725 peb = pbi.PebBaseAddress;
726
727 if (!peb->Ldr)
728 return false;
729
731 while (le != &peb->Ldr->InMemoryOrderModuleList) {
733 bool blacklist = false;
734
735 if (entry->FullDllName.Length >= usmpr.Length) {
737
738 name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usmpr.Length) / sizeof(WCHAR)];
739 name.Length = name.MaximumLength = usmpr.Length;
740
741 blacklist = compare_strings(&name, &usmpr);
742 }
743
744 if (!blacklist && entry->FullDllName.Length >= uscmd.Length) {
746
747 name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - uscmd.Length) / sizeof(WCHAR)];
748 name.Length = name.MaximumLength = uscmd.Length;
749
750 blacklist = compare_strings(&name, &uscmd);
751 }
752
753 if (!blacklist && entry->FullDllName.Length >= usfsutil.Length) {
755
756 name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usfsutil.Length) / sizeof(WCHAR)];
757 name.Length = name.MaximumLength = usfsutil.Length;
758
759 blacklist = compare_strings(&name, &usfsutil);
760 }
761
762 if (!blacklist && entry->FullDllName.Length >= usstorsvc.Length) {
764
765 name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usstorsvc.Length) / sizeof(WCHAR)];
766 name.Length = name.MaximumLength = usstorsvc.Length;
767
768 blacklist = compare_strings(&name, &usstorsvc);
769 }
770
771 if (!blacklist && entry->FullDllName.Length >= usifstest.Length) {
773
774 name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usifstest.Length) / sizeof(WCHAR)];
775 name.Length = name.MaximumLength = usifstest.Length;
776
777 blacklist = compare_strings(&name, &usifstest);
778 }
779
780 if (blacklist) {
781 void** frames;
782 ULONG i, num_frames;
783
784 frames = ExAllocatePoolWithTag(PagedPool, 256 * sizeof(void*), ALLOC_TAG);
785 if (!frames) {
786 ERR("out of memory\n");
787 return false;
788 }
789
790 num_frames = RtlWalkFrameChain(frames, 256, 1);
791
792 for (i = 0; i < num_frames; i++) {
793 // entry->Reserved3[1] appears to be the image size
794 if (frames[i] >= entry->DllBase && (ULONG_PTR)frames[i] <= (ULONG_PTR)entry->DllBase + (ULONG_PTR)entry->Reserved3[1]) {
795 ExFreePool(frames);
796 return true;
797 }
798 }
799
800 ExFreePool(frames);
801 }
802
803 le = le->Flink;
804 }
805
806 return false;
807}
808#endif // __REACTOS__
809
810// version of RtlUTF8ToUnicodeN for Vista and below
811NTSTATUS utf8_to_utf16(WCHAR* dest, ULONG dest_max, ULONG* dest_len, char* src, ULONG src_len) {
813 uint8_t* in = (uint8_t*)src;
815 ULONG needed = 0, left = dest_max / sizeof(uint16_t);
816
817 for (ULONG i = 0; i < src_len; i++) {
818 uint32_t cp;
819
820 if (!(in[i] & 0x80))
821 cp = in[i];
822 else if ((in[i] & 0xe0) == 0xc0) {
823 if (i == src_len - 1 || (in[i+1] & 0xc0) != 0x80) {
824 cp = 0xfffd;
826 } else {
827 cp = ((in[i] & 0x1f) << 6) | (in[i+1] & 0x3f);
828 i++;
829 }
830 } else if ((in[i] & 0xf0) == 0xe0) {
831 if (i >= src_len - 2 || (in[i+1] & 0xc0) != 0x80 || (in[i+2] & 0xc0) != 0x80) {
832 cp = 0xfffd;
834 } else {
835 cp = ((in[i] & 0xf) << 12) | ((in[i+1] & 0x3f) << 6) | (in[i+2] & 0x3f);
836 i += 2;
837 }
838 } else if ((in[i] & 0xf8) == 0xf0) {
839 if (i >= src_len - 3 || (in[i+1] & 0xc0) != 0x80 || (in[i+2] & 0xc0) != 0x80 || (in[i+3] & 0xc0) != 0x80) {
840 cp = 0xfffd;
842 } else {
843 cp = ((in[i] & 0x7) << 18) | ((in[i+1] & 0x3f) << 12) | ((in[i+2] & 0x3f) << 6) | (in[i+3] & 0x3f);
844 i += 3;
845 }
846 } else {
847 cp = 0xfffd;
849 }
850
851 if (cp > 0x10ffff) {
852 cp = 0xfffd;
854 }
855
856 if (dest) {
857 if (cp <= 0xffff) {
858 if (left < 1)
860
861 *out = (uint16_t)cp;
862 out++;
863
864 left--;
865 } else {
866 if (left < 2)
868
869 cp -= 0x10000;
870
871 *out = 0xd800 | ((cp & 0xffc00) >> 10);
872 out++;
873
874 *out = 0xdc00 | (cp & 0x3ff);
875 out++;
876
877 left -= 2;
878 }
879 }
880
881 if (cp <= 0xffff)
882 needed += sizeof(uint16_t);
883 else
884 needed += 2 * sizeof(uint16_t);
885 }
886
887 if (dest_len)
888 *dest_len = needed;
889
890 return Status;
891}
892
893// version of RtlUnicodeToUTF8N for Vista and below
894NTSTATUS utf16_to_utf8(char* dest, ULONG dest_max, ULONG* dest_len, WCHAR* src, ULONG src_len) {
896 uint16_t* in = (uint16_t*)src;
897 uint8_t* out = (uint8_t*)dest;
898 ULONG in_len = src_len / sizeof(uint16_t);
899 ULONG needed = 0, left = dest_max;
900
901 for (ULONG i = 0; i < in_len; i++) {
902 uint32_t cp = *in;
903 in++;
904
905 if ((cp & 0xfc00) == 0xd800) {
906 if (i == in_len - 1 || (*in & 0xfc00) != 0xdc00) {
907 cp = 0xfffd;
909 } else {
910 cp = (cp & 0x3ff) << 10;
911 cp |= *in & 0x3ff;
912 cp += 0x10000;
913
914 in++;
915 i++;
916 }
917 } else if ((cp & 0xfc00) == 0xdc00) {
918 cp = 0xfffd;
920 }
921
922 if (cp > 0x10ffff) {
923 cp = 0xfffd;
925 }
926
927 if (dest) {
928 if (cp < 0x80) {
929 if (left < 1)
931
932 *out = (uint8_t)cp;
933 out++;
934
935 left--;
936 } else if (cp < 0x800) {
937 if (left < 2)
939
940 *out = 0xc0 | ((cp & 0x7c0) >> 6);
941 out++;
942
943 *out = 0x80 | (cp & 0x3f);
944 out++;
945
946 left -= 2;
947 } else if (cp < 0x10000) {
948 if (left < 3)
950
951 *out = 0xe0 | ((cp & 0xf000) >> 12);
952 out++;
953
954 *out = 0x80 | ((cp & 0xfc0) >> 6);
955 out++;
956
957 *out = 0x80 | (cp & 0x3f);
958 out++;
959
960 left -= 3;
961 } else {
962 if (left < 4)
964
965 *out = 0xf0 | ((cp & 0x1c0000) >> 18);
966 out++;
967
968 *out = 0x80 | ((cp & 0x3f000) >> 12);
969 out++;
970
971 *out = 0x80 | ((cp & 0xfc0) >> 6);
972 out++;
973
974 *out = 0x80 | (cp & 0x3f);
975 out++;
976
977 left -= 4;
978 }
979 }
980
981 if (cp < 0x80)
982 needed++;
983 else if (cp < 0x800)
984 needed += 2;
985 else if (cp < 0x10000)
986 needed += 3;
987 else
988 needed += 4;
989 }
990
991 if (dest_len)
992 *dest_len = needed;
993
994 return Status;
995}
996
999static NTSTATUS __stdcall drv_query_volume_information(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
1002 ULONG BytesCopied = 0;
1003 device_extension* Vcb = DeviceObject->DeviceExtension;
1004 bool top_level;
1005
1007
1008 TRACE("query volume information\n");
1009 top_level = is_top_level(Irp);
1010
1011 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
1013 goto end;
1014 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
1016 goto end;
1017 }
1018
1020
1022
1023 switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
1025 {
1026 FILE_FS_ATTRIBUTE_INFORMATION* data = Irp->AssociatedIrp.SystemBuffer;
1027 bool overflow = false;
1028#ifndef __REACTOS__
1029 static const WCHAR ntfs[] = L"NTFS";
1030#endif
1031 static const WCHAR btrfs[] = L"Btrfs";
1032 const WCHAR* fs_name;
1033 ULONG fs_name_len, orig_fs_name_len;
1034
1035#ifndef __REACTOS__
1036 if (Irp->RequestorMode == UserMode && lie_about_fs_type()) {
1037 fs_name = ntfs;
1038 orig_fs_name_len = fs_name_len = sizeof(ntfs) - sizeof(WCHAR);
1039 } else {
1040 fs_name = btrfs;
1041 orig_fs_name_len = fs_name_len = sizeof(btrfs) - sizeof(WCHAR);
1042 }
1043#else
1044 fs_name = btrfs;
1045 orig_fs_name_len = fs_name_len = sizeof(btrfs) - sizeof(WCHAR);
1046#endif
1047
1048 TRACE("FileFsAttributeInformation\n");
1049
1050 if (IrpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION) - sizeof(WCHAR) + fs_name_len) {
1051 if (IrpSp->Parameters.QueryVolume.Length > sizeof(FILE_FS_ATTRIBUTE_INFORMATION) - sizeof(WCHAR))
1052 fs_name_len = IrpSp->Parameters.QueryVolume.Length - sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + sizeof(WCHAR);
1053 else
1054 fs_name_len = 0;
1055
1056 overflow = true;
1057 }
1058
1064 if (Vcb->readonly)
1065 data->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
1066
1067 // should also be FILE_FILE_COMPRESSION when supported
1068 data->MaximumComponentNameLength = 255; // FIXME - check
1069 data->FileSystemNameLength = orig_fs_name_len;
1070 RtlCopyMemory(data->FileSystemName, fs_name, fs_name_len);
1071
1072 BytesCopied = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) - sizeof(WCHAR) + fs_name_len;
1074 break;
1075 }
1076
1078 {
1079 FILE_FS_DEVICE_INFORMATION* ffdi = Irp->AssociatedIrp.SystemBuffer;
1080
1081 TRACE("FileFsDeviceInformation\n");
1082
1084
1085 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1086 ffdi->Characteristics = Vcb->Vpb->RealDevice->Characteristics;
1087 ExReleaseResourceLite(&Vcb->tree_lock);
1088
1089 if (Vcb->readonly)
1091 else
1092 ffdi->Characteristics &= ~FILE_READ_ONLY_DEVICE;
1093
1096
1097 break;
1098 }
1099
1101 {
1102 FILE_FS_FULL_SIZE_INFORMATION* ffsi = Irp->AssociatedIrp.SystemBuffer;
1103
1104 TRACE("FileFsFullSizeInformation\n");
1105
1108 ffsi->SectorsPerAllocationUnit = Vcb->superblock.sector_size / 512;
1109 ffsi->BytesPerSector = 512;
1110
1113
1114 break;
1115 }
1116
1118 {
1119 FILE_FS_OBJECTID_INFORMATION* ffoi = Irp->AssociatedIrp.SystemBuffer;
1120
1121 TRACE("FileFsObjectIdInformation\n");
1122
1123 RtlCopyMemory(ffoi->ObjectId, &Vcb->superblock.uuid.uuid[0], sizeof(UCHAR) * 16);
1124 RtlZeroMemory(ffoi->ExtendedInfo, sizeof(ffoi->ExtendedInfo));
1125
1128
1129 break;
1130 }
1131
1133 {
1134 FILE_FS_SIZE_INFORMATION* ffsi = Irp->AssociatedIrp.SystemBuffer;
1135
1136 TRACE("FileFsSizeInformation\n");
1137
1139 ffsi->SectorsPerAllocationUnit = Vcb->superblock.sector_size / 512;
1140 ffsi->BytesPerSector = 512;
1141
1144
1145 break;
1146 }
1147
1149 {
1150 FILE_FS_VOLUME_INFORMATION* data = Irp->AssociatedIrp.SystemBuffer;
1152 bool overflow = false;
1153 ULONG label_len, orig_label_len;
1154
1155 TRACE("FileFsVolumeInformation\n");
1156 TRACE("max length = %lu\n", IrpSp->Parameters.QueryVolume.Length);
1157
1158 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1159
1160 Status = utf8_to_utf16(NULL, 0, &label_len, Vcb->superblock.label, (ULONG)strlen(Vcb->superblock.label));
1161 if (!NT_SUCCESS(Status)) {
1162 ERR("utf8_to_utf16 returned %08lx\n", Status);
1163 ExReleaseResourceLite(&Vcb->tree_lock);
1164 break;
1165 }
1166
1167 orig_label_len = label_len;
1168
1169 if (IrpSp->Parameters.QueryVolume.Length < offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + label_len) {
1171 label_len = IrpSp->Parameters.QueryVolume.Length - offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel);
1172 else
1173 label_len = 0;
1174
1175 overflow = true;
1176 }
1177
1178 TRACE("label_len = %lu\n", label_len);
1179
1181
1182 ffvi.VolumeSerialNumber = Vcb->superblock.uuid.uuid[12] << 24 | Vcb->superblock.uuid.uuid[13] << 16 | Vcb->superblock.uuid.uuid[14] << 8 | Vcb->superblock.uuid.uuid[15];
1183 ffvi.VolumeLabelLength = orig_label_len;
1184
1186
1187 if (label_len > 0) {
1188 ULONG bytecount;
1189
1190 Status = utf8_to_utf16(&data->VolumeLabel[0], label_len, &bytecount, Vcb->superblock.label, (ULONG)strlen(Vcb->superblock.label));
1192 ERR("utf8_to_utf16 returned %08lx\n", Status);
1193 ExReleaseResourceLite(&Vcb->tree_lock);
1194 break;
1195 }
1196
1197 TRACE("label = %.*S\n", (int)(label_len / sizeof(WCHAR)), data->VolumeLabel);
1198 }
1199
1200 ExReleaseResourceLite(&Vcb->tree_lock);
1201
1202 BytesCopied = offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + label_len;
1204 break;
1205 }
1206
1207#ifndef __REACTOS__
1208#ifdef _MSC_VER // not in mingw yet
1209 case FileFsSectorSizeInformation:
1210 {
1211 FILE_FS_SECTOR_SIZE_INFORMATION* data = Irp->AssociatedIrp.SystemBuffer;
1212
1213 data->LogicalBytesPerSector = Vcb->superblock.sector_size;
1214 data->PhysicalBytesPerSectorForAtomicity = Vcb->superblock.sector_size;
1215 data->PhysicalBytesPerSectorForPerformance = Vcb->superblock.sector_size;
1216 data->FileSystemEffectivePhysicalBytesPerSectorForAtomicity = Vcb->superblock.sector_size;
1217 data->ByteOffsetForSectorAlignment = 0;
1218 data->ByteOffsetForPartitionAlignment = 0;
1219
1220 data->Flags = SSINFO_FLAGS_ALIGNED_DEVICE | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE;
1221
1222 if (Vcb->trim && !Vcb->options.no_trim)
1223 data->Flags |= SSINFO_FLAGS_TRIM_ENABLED;
1224
1225 BytesCopied = sizeof(FILE_FS_SECTOR_SIZE_INFORMATION);
1227
1228 break;
1229 }
1230#endif
1231#endif /* __REACTOS__ */
1232
1233 default:
1235 WARN("unknown FsInformationClass %u\n", IrpSp->Parameters.QueryVolume.FsInformationClass);
1236 break;
1237 }
1238
1240 Irp->IoStatus.Information = 0;
1241 else
1242 Irp->IoStatus.Information = BytesCopied;
1243
1244end:
1245 Irp->IoStatus.Status = Status;
1246
1248
1249 if (top_level)
1251
1252 TRACE("query volume information returning %08lx\n", Status);
1253
1255
1256 return Status;
1257}
1258
1259_Function_class_(IO_COMPLETION_ROUTINE)
1260static NTSTATUS __stdcall read_completion(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID conptr) {
1261 read_context* context = conptr;
1262
1264
1265 context->iosb = Irp->IoStatus;
1266 KeSetEvent(&context->Event, 0, false);
1267
1269}
1270
1272 _Out_ root** rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp) {
1274 root* r;
1275 ROOT_ITEM* ri;
1277
1279 if (!r) {
1280 ERR("out of memory\n");
1282 }
1283
1285 if (!r->nonpaged) {
1286 ERR("out of memory\n");
1287 ExFreePool(r);
1289 }
1290
1292 if (!ri) {
1293 ERR("out of memory\n");
1294
1295 ExFreePool(r->nonpaged);
1296 ExFreePool(r);
1298 }
1299
1300 r->id = id;
1301 r->treeholder.address = 0;
1302 r->treeholder.generation = Vcb->superblock.generation;
1303 r->treeholder.tree = NULL;
1304 r->lastinode = 0;
1305 r->dirty = false;
1306 r->received = false;
1307 r->reserved = NULL;
1308 r->parent = 0;
1309 r->send_ops = 0;
1310 RtlZeroMemory(&r->root_item, sizeof(ROOT_ITEM));
1311 r->root_item.num_references = 1;
1312 r->fcbs_version = 0;
1313 r->checked_for_orphans = true;
1314 r->dropped = false;
1315 InitializeListHead(&r->fcbs);
1316 RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
1317
1318 RtlCopyMemory(ri, &r->root_item, sizeof(ROOT_ITEM));
1319
1320 // We ask here for a traverse_ptr to the item we're inserting, so we can
1321 // copy some of the tree's variables
1322
1323 Status = insert_tree_item(Vcb, Vcb->root_root, id, TYPE_ROOT_ITEM, offset, ri, sizeof(ROOT_ITEM), &tp, Irp);
1324 if (!NT_SUCCESS(Status)) {
1325 ERR("insert_tree_item returned %08lx\n", Status);
1326 ExFreePool(ri);
1327 ExFreePool(r->nonpaged);
1328 ExFreePool(r);
1329 return Status;
1330 }
1331
1332 ExInitializeResourceLite(&r->nonpaged->load_tree_lock);
1333
1334 InsertTailList(&Vcb->roots, &r->list_entry);
1335
1336 if (!no_tree) {
1338 if (!t) {
1339 ERR("out of memory\n");
1340
1342
1343 ExFreePool(r->nonpaged);
1344 ExFreePool(r);
1345 ExFreePool(ri);
1347 }
1348
1349 t->nonpaged = NULL;
1350
1351 t->is_unique = true;
1352 t->uniqueness_determined = true;
1353 t->buf = NULL;
1354
1355 r->treeholder.tree = t;
1356
1357 RtlZeroMemory(&t->header, sizeof(tree_header));
1358 t->header.fs_uuid = tp.tree->header.fs_uuid;
1359 t->header.address = 0;
1360 t->header.flags = HEADER_FLAG_MIXED_BACKREF | 1; // 1 == "written"? Why does the Linux driver record this?
1361 t->header.chunk_tree_uuid = tp.tree->header.chunk_tree_uuid;
1362 t->header.generation = Vcb->superblock.generation;
1363 t->header.tree_id = id;
1364 t->header.num_items = 0;
1365 t->header.level = 0;
1366
1367 t->has_address = false;
1368 t->size = 0;
1369 t->Vcb = Vcb;
1370 t->parent = NULL;
1371 t->paritem = NULL;
1372 t->root = r;
1373
1374 InitializeListHead(&t->itemlist);
1375
1376 t->new_address = 0;
1377 t->has_new_address = false;
1378 t->updated_extents = false;
1379
1380 InsertTailList(&Vcb->trees, &t->list_entry);
1381 t->list_entry_hash.Flink = NULL;
1382
1383 t->write = true;
1384 Vcb->need_write = true;
1385 }
1386
1387 *rootptr = r;
1388
1389 return STATUS_SUCCESS;
1390}
1391
1393 ULONG utf8len;
1395 ULONG vollen, i;
1396
1397 TRACE("label = %.*S\n", (int)(ffli->VolumeLabelLength / sizeof(WCHAR)), ffli->VolumeLabel);
1398
1399 vollen = ffli->VolumeLabelLength;
1400
1401 for (i = 0; i < ffli->VolumeLabelLength / sizeof(WCHAR); i++) {
1402 if (ffli->VolumeLabel[i] == 0) {
1403 vollen = i * sizeof(WCHAR);
1404 break;
1405 } else if (ffli->VolumeLabel[i] == '/' || ffli->VolumeLabel[i] == '\\') {
1407 goto end;
1408 }
1409 }
1410
1411 if (vollen == 0) {
1412 utf8len = 0;
1413 } else {
1414 Status = utf16_to_utf8(NULL, 0, &utf8len, ffli->VolumeLabel, vollen);
1415 if (!NT_SUCCESS(Status))
1416 goto end;
1417
1418 if (utf8len > MAX_LABEL_SIZE) {
1420 goto end;
1421 }
1422 }
1423
1424 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1425
1426 if (utf8len > 0) {
1427 Status = utf16_to_utf8((PCHAR)&Vcb->superblock.label, MAX_LABEL_SIZE, &utf8len, ffli->VolumeLabel, vollen);
1428 if (!NT_SUCCESS(Status))
1429 goto release;
1430 } else
1432
1433 if (utf8len < MAX_LABEL_SIZE)
1434 RtlZeroMemory(Vcb->superblock.label + utf8len, MAX_LABEL_SIZE - utf8len);
1435
1436 Vcb->need_write = true;
1437
1438release:
1439 ExReleaseResourceLite(&Vcb->tree_lock);
1440
1441end:
1442 TRACE("returning %08lx\n", Status);
1443
1444 return Status;
1445}
1446
1449static NTSTATUS __stdcall drv_set_volume_information(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
1451 device_extension* Vcb = DeviceObject->DeviceExtension;
1453 bool top_level;
1454
1456
1457 TRACE("set volume information\n");
1458
1459 top_level = is_top_level(Irp);
1460
1461 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
1463 goto end;
1464 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
1466 goto end;
1467 }
1468
1470
1471 if (Vcb->readonly) {
1473 goto end;
1474 }
1475
1476 if (Vcb->removing || Vcb->locked) {
1478 goto end;
1479 }
1480
1481 switch (IrpSp->Parameters.SetVolume.FsInformationClass) {
1483 FIXME("STUB: FileFsControlInformation\n");
1484 break;
1485
1487 TRACE("FileFsLabelInformation\n");
1488
1489 Status = set_label(Vcb, Irp->AssociatedIrp.SystemBuffer);
1490 break;
1491
1493 FIXME("STUB: FileFsObjectIdInformation\n");
1494 break;
1495
1496 default:
1497 WARN("Unrecognized FsInformationClass 0x%x\n", IrpSp->Parameters.SetVolume.FsInformationClass);
1498 break;
1499 }
1500
1501end:
1502 Irp->IoStatus.Status = Status;
1503 Irp->IoStatus.Information = 0;
1504
1505 TRACE("returning %08lx\n", Status);
1506
1508
1509 if (top_level)
1511
1513
1514 return Status;
1515}
1516
1520 ULONG reqlen;
1521 USHORT name_offset;
1522 fcb* fcb = fileref->fcb;
1523
1524 fn.Length = fn.MaximumLength = 0;
1525 Status = fileref_get_filename(fileref, &fn, NULL, &reqlen);
1527 ERR("fileref_get_filename returned %08lx\n", Status);
1528 return;
1529 }
1530
1531 if (reqlen > 0xffff) {
1532 WARN("reqlen was too long for FsRtlNotifyFilterReportChange\n");
1533 return;
1534 }
1535
1536 fn.Buffer = ExAllocatePoolWithTag(PagedPool, reqlen, ALLOC_TAG);
1537 if (!fn.Buffer) {
1538 ERR("out of memory\n");
1539 return;
1540 }
1541
1542 fn.MaximumLength = (USHORT)reqlen;
1543 fn.Length = 0;
1544
1545 Status = fileref_get_filename(fileref, &fn, &name_offset, &reqlen);
1546 if (!NT_SUCCESS(Status)) {
1547 ERR("fileref_get_filename returned %08lx\n", Status);
1548 ExFreePool(fn.Buffer);
1549 return;
1550 }
1551
1552 FsRtlNotifyFilterReportChange(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, (PSTRING)&fn, name_offset,
1553 (PSTRING)stream, NULL, filter_match, action, NULL, NULL);
1554 ExFreePool(fn.Buffer);
1555}
1556
1558 fcb* fcb = fileref->fcb;
1559 LIST_ENTRY* le;
1561
1562 // no point looking for hardlinks if st_nlink == 1
1563 if (fileref->fcb->inode_item.st_nlink == 1) {
1564 ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
1565 send_notification_fileref(fileref, filter_match, action, stream);
1566 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
1567 return;
1568 }
1569
1570 ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
1571
1572 le = fcb->hardlinks.Flink;
1573 while (le != &fcb->hardlinks) {
1575 file_ref* parfr;
1576
1578
1579 if (!NT_SUCCESS(Status))
1580 ERR("open_fileref_by_inode returned %08lx\n", Status);
1581 else if (!parfr->deleted) {
1583 ULONG pathlen;
1584
1585 fn.Length = fn.MaximumLength = 0;
1586 Status = fileref_get_filename(parfr, &fn, NULL, &pathlen);
1588 ERR("fileref_get_filename returned %08lx\n", Status);
1589 free_fileref(parfr);
1590 break;
1591 }
1592
1593 if (parfr != fcb->Vcb->root_fileref)
1594 pathlen += sizeof(WCHAR);
1595
1596 if (pathlen + hl->name.Length > 0xffff) {
1597 WARN("pathlen + hl->name.Length was too long for FsRtlNotifyFilterReportChange\n");
1598 free_fileref(parfr);
1599 break;
1600 }
1601
1602 fn.MaximumLength = (USHORT)(pathlen + hl->name.Length);
1603 fn.Buffer = ExAllocatePoolWithTag(PagedPool, fn.MaximumLength, ALLOC_TAG);
1604 if (!fn.Buffer) {
1605 ERR("out of memory\n");
1606 free_fileref(parfr);
1607 break;
1608 }
1609
1610 Status = fileref_get_filename(parfr, &fn, NULL, NULL);
1611 if (!NT_SUCCESS(Status)) {
1612 ERR("fileref_get_filename returned %08lx\n", Status);
1613 free_fileref(parfr);
1614 ExFreePool(fn.Buffer);
1615 break;
1616 }
1617
1618 if (parfr != fcb->Vcb->root_fileref) {
1619 fn.Buffer[(pathlen / sizeof(WCHAR)) - 1] = '\\';
1620 fn.Length += sizeof(WCHAR);
1621 }
1622
1623 RtlCopyMemory(&fn.Buffer[pathlen / sizeof(WCHAR)], hl->name.Buffer, hl->name.Length);
1624 fn.Length += hl->name.Length;
1625
1626 FsRtlNotifyFilterReportChange(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, (PSTRING)&fn, (USHORT)pathlen,
1627 (PSTRING)stream, NULL, filter_match, action, NULL, NULL);
1628
1629 ExFreePool(fn.Buffer);
1630
1631 free_fileref(parfr);
1632 }
1633
1634 le = le->Flink;
1635 }
1636
1637 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
1638}
1639
1640typedef struct {
1647
1648_Function_class_(IO_WORKITEM_ROUTINE)
1649static void __stdcall notification_work_item(PDEVICE_OBJECT DeviceObject, PVOID con) {
1650 notification_fcb* nf = con;
1651
1653
1654 ExAcquireResourceSharedLite(&nf->fileref->fcb->Vcb->tree_lock, TRUE); // protect us from fileref being reaped
1655
1657
1658 free_fileref(nf->fileref);
1659
1660 ExReleaseResourceLite(&nf->fileref->fcb->Vcb->tree_lock);
1661
1663
1664 ExFreePool(nf);
1665}
1666
1668 notification_fcb* nf;
1669 PIO_WORKITEM work_item;
1670
1672 if (!nf) {
1673 ERR("out of memory\n");
1674 return;
1675 }
1676
1677 work_item = IoAllocateWorkItem(master_devobj);
1678 if (!work_item) {
1679 ERR("out of memory\n");
1680 ExFreePool(nf);
1681 return;
1682 }
1683
1684 InterlockedIncrement(&fileref->refcount);
1685
1686 nf->fileref = fileref;
1687 nf->filter_match = filter_match;
1688 nf->action = action;
1689 nf->stream = stream;
1690 nf->work_item = work_item;
1691
1692 IoQueueWorkItem(work_item, notification_work_item, DelayedWorkQueue, nf);
1693}
1694
1696 if (!fcb->dirty) {
1697#ifdef DEBUG_FCB_REFCOUNTS
1698 LONG rc;
1699#endif
1700 fcb->dirty = true;
1701
1702#ifdef DEBUG_FCB_REFCOUNTS
1704 WARN("fcb %p: refcount now %i\n", fcb, rc);
1705#else
1707#endif
1708
1709 ExAcquireResourceExclusiveLite(&fcb->Vcb->dirty_fcbs_lock, true);
1710 InsertTailList(&fcb->Vcb->dirty_fcbs, &fcb->list_entry_dirty);
1711 ExReleaseResourceLite(&fcb->Vcb->dirty_fcbs_lock);
1712 }
1713
1714 fcb->Vcb->need_write = true;
1715}
1716
1718 if (!fileref->dirty) {
1719 fileref->dirty = true;
1721
1722 ExAcquireResourceExclusiveLite(&fileref->fcb->Vcb->dirty_filerefs_lock, true);
1723 InsertTailList(&fileref->fcb->Vcb->dirty_filerefs, &fileref->list_entry_dirty);
1724 ExReleaseResourceLite(&fileref->fcb->Vcb->dirty_filerefs_lock);
1725 }
1726
1727 fileref->fcb->Vcb->need_write = true;
1728}
1729
1730#ifdef DEBUG_FCB_REFCOUNTS
1731void _free_fcb(_Inout_ fcb* fcb, _In_ const char* func) {
1733#else
1736#endif
1737
1738#ifdef DEBUG_FCB_REFCOUNTS
1739 ERR("fcb %p (%s): refcount now %i (subvol %I64x, inode %I64x)\n", fcb, func, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
1740#endif
1741}
1742
1744 uint8_t c = fcb->hash >> 24;
1745
1746 if (fcb->subvol && fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
1747 if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
1748 fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
1749 else
1750 fcb->subvol->fcbs_ptrs[c] = NULL;
1751 }
1752
1753 if (fcb->list_entry.Flink) {
1755
1756 if (fcb->subvol && fcb->subvol->dropped && IsListEmpty(&fcb->subvol->fcbs)) {
1757 ExDeleteResourceLite(&fcb->subvol->nonpaged->load_tree_lock);
1758 ExFreePool(fcb->subvol->nonpaged);
1760 }
1761 }
1762
1765
1766 ExDeleteResourceLite(&fcb->nonpaged->resource);
1767 ExDeleteResourceLite(&fcb->nonpaged->paging_resource);
1768 ExDeleteResourceLite(&fcb->nonpaged->dir_children_lock);
1769
1770 ExFreeToNPagedLookasideList(&fcb->Vcb->fcb_np_lookaside, fcb->nonpaged);
1771
1772 if (fcb->sd)
1773 ExFreePool(fcb->sd);
1774
1775 if (fcb->adsxattr.Buffer)
1777
1780
1781 if (fcb->ea_xattr.Buffer)
1783
1784 if (fcb->adsdata.Buffer)
1786
1787 while (!IsListEmpty(&fcb->extents)) {
1790
1791 if (ext->csum)
1792 ExFreePool(ext->csum);
1793
1794 ExFreePool(ext);
1795 }
1796
1797 while (!IsListEmpty(&fcb->hardlinks)) {
1800
1801 if (hl->name.Buffer)
1802 ExFreePool(hl->name.Buffer);
1803
1804 if (hl->utf8.Buffer)
1805 ExFreePool(hl->utf8.Buffer);
1806
1807 ExFreePool(hl);
1808 }
1809
1810 while (!IsListEmpty(&fcb->xattrs)) {
1812
1813 ExFreePool(xa);
1814 }
1815
1816 while (!IsListEmpty(&fcb->dir_children_index)) {
1818 dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
1819
1820 ExFreePool(dc->utf8.Buffer);
1821 ExFreePool(dc->name.Buffer);
1822 ExFreePool(dc->name_uc.Buffer);
1823 ExFreePool(dc);
1824 }
1825
1826 if (fcb->hash_ptrs)
1828
1829 if (fcb->hash_ptrs_uc)
1831
1834
1835 if (fcb->pool_type == NonPagedPool)
1836 ExFreePool(fcb);
1837 else
1838 ExFreeToPagedLookasideList(&fcb->Vcb->fcb_lookaside, fcb);
1839}
1840
1842 LIST_ENTRY* le;
1843
1844 le = Vcb->all_fcbs.Flink;
1845 while (le != &Vcb->all_fcbs) {
1846 fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
1847 LIST_ENTRY* le2 = le->Flink;
1848
1849 if (fcb->refcount == 0)
1850 reap_fcb(fcb);
1851
1852 le = le2;
1853 }
1854}
1855
1857#if defined(_DEBUG) || defined(DEBUG_FCB_REFCOUNTS)
1858 LONG rc = InterlockedDecrement(&fr->refcount);
1859
1860#ifdef DEBUG_FCB_REFCOUNTS
1861 ERR("fileref %p: refcount now %i\n", fr, rc);
1862#endif
1863
1864#ifdef _DEBUG
1865 if (rc < 0) {
1866 ERR("fileref %p: refcount now %li\n", fr, rc);
1867 int3;
1868 }
1869#endif
1870#else
1871 InterlockedDecrement(&fr->refcount);
1872#endif
1873}
1874
1876 // FIXME - do we need a file_ref lock?
1877
1878 // FIXME - do delete if needed
1879
1880 // FIXME - throw error if children not empty
1881
1882 if (fr->fcb->fileref == fr)
1883 fr->fcb->fileref = NULL;
1884
1885 if (fr->dc) {
1886 if (fr->fcb->ads)
1887 fr->dc->size = fr->fcb->adsdata.Length;
1888
1889 fr->dc->fileref = NULL;
1890 }
1891
1892 if (fr->list_entry.Flink)
1894
1895 if (fr->parent)
1896 free_fileref(fr->parent);
1897
1898 free_fcb(fr->fcb);
1899
1900 if (fr->oldutf8.Buffer)
1902
1903 ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, fr);
1904}
1905
1907 LIST_ENTRY* le;
1908
1909 // FIXME - recursion is a bad idea in kernel mode
1910
1911 le = fr->children.Flink;
1912 while (le != &fr->children) {
1914 LIST_ENTRY* le2 = le->Flink;
1915
1917
1918 le = le2;
1919 }
1920
1921 if (fr->refcount == 0)
1922 reap_fileref(Vcb, fr);
1923}
1924
1926 fcb* fcb;
1927 ccb* ccb;
1928 file_ref* fileref = NULL;
1929 LONG open_files;
1930
1931 UNUSED(Irp);
1932
1933 TRACE("FileObject = %p\n", FileObject);
1934
1935 fcb = FileObject->FsContext;
1936 if (!fcb) {
1937 TRACE("FCB was NULL, returning success\n");
1938 return STATUS_SUCCESS;
1939 }
1940
1941 open_files = InterlockedDecrement(&fcb->Vcb->open_files);
1942
1943 ccb = FileObject->FsContext2;
1944
1945 TRACE("close called for fcb %p)\n", fcb);
1946
1947 // FIXME - make sure notification gets sent if file is being deleted
1948
1949 if (ccb) {
1950 if (ccb->query_string.Buffer)
1952
1953 if (ccb->filename.Buffer)
1955
1956 // FIXME - use refcounts for fileref
1957 fileref = ccb->fileref;
1958
1959 if (fcb->Vcb->running_sends > 0) {
1960 bool send_cancelled = false;
1961
1962 ExAcquireResourceExclusiveLite(&fcb->Vcb->send_load_lock, true);
1963
1964 if (ccb->send) {
1965 ccb->send->cancelling = true;
1966 send_cancelled = true;
1967 KeSetEvent(&ccb->send->cleared_event, 0, false);
1968 }
1969
1970 ExReleaseResourceLite(&fcb->Vcb->send_load_lock);
1971
1972 if (send_cancelled) {
1973 while (ccb->send) {
1974 ExAcquireResourceExclusiveLite(&fcb->Vcb->send_load_lock, true);
1975 ExReleaseResourceLite(&fcb->Vcb->send_load_lock);
1976 }
1977 }
1978 }
1979
1980 ExFreePool(ccb);
1981 }
1982
1984
1985 if (open_files == 0 && fcb->Vcb->removing) {
1986 uninit(fcb->Vcb);
1987 return STATUS_SUCCESS;
1988 }
1989
1990 if (!(fcb->Vcb->Vpb->Flags & VPB_MOUNTED))
1991 return STATUS_SUCCESS;
1992
1993 if (fileref)
1994 free_fileref(fileref);
1995 else
1996 free_fcb(fcb);
1997
1998 return STATUS_SUCCESS;
1999}
2000
2002 uint64_t i;
2003 KIRQL irql;
2005 LIST_ENTRY* le;
2007
2008 if (!Vcb->removing) {
2009 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2010 Vcb->removing = true;
2011 ExReleaseResourceLite(&Vcb->tree_lock);
2012 }
2013
2014 if (Vcb->vde && Vcb->vde->mounted_device == Vcb->devobj)
2015 Vcb->vde->mounted_device = NULL;
2016
2018 Vcb->Vpb->Flags &= ~VPB_MOUNTED;
2019 Vcb->Vpb->Flags |= VPB_DIRECT_WRITES_ALLOWED;
2020 Vcb->Vpb->DeviceObject = NULL;
2022
2023 // FIXME - needs global_loading_lock to be held
2024 if (Vcb->list_entry.Flink)
2025 RemoveEntryList(&Vcb->list_entry);
2026
2027 if (Vcb->balance.thread) {
2028 Vcb->balance.paused = false;
2029 Vcb->balance.stopping = true;
2030 KeSetEvent(&Vcb->balance.event, 0, false);
2031 KeWaitForSingleObject(&Vcb->balance.finished, Executive, KernelMode, false, NULL);
2032 }
2033
2034 if (Vcb->scrub.thread) {
2035 Vcb->scrub.paused = false;
2036 Vcb->scrub.stopping = true;
2037 KeSetEvent(&Vcb->scrub.event, 0, false);
2038 KeWaitForSingleObject(&Vcb->scrub.finished, Executive, KernelMode, false, NULL);
2039 }
2040
2041 if (Vcb->running_sends != 0) {
2042 bool send_cancelled = false;
2043
2044 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
2045
2046 le = Vcb->send_ops.Flink;
2047 while (le != &Vcb->send_ops) {
2049
2050 if (!send->cancelling) {
2051 send->cancelling = true;
2052 send_cancelled = true;
2053 send->ccb = NULL;
2054 KeSetEvent(&send->cleared_event, 0, false);
2055 }
2056
2057 le = le->Flink;
2058 }
2059
2060 ExReleaseResourceLite(&Vcb->send_load_lock);
2061
2062 if (send_cancelled) {
2063 while (Vcb->running_sends != 0) {
2064 ExAcquireResourceExclusiveLite(&Vcb->send_load_lock, true);
2065 ExReleaseResourceLite(&Vcb->send_load_lock);
2066 }
2067 }
2068 }
2069
2070 Status = registry_mark_volume_unmounted(&Vcb->superblock.uuid);
2072 WARN("registry_mark_volume_unmounted returned %08lx\n", Status);
2073
2074 for (i = 0; i < Vcb->calcthreads.num_threads; i++) {
2075 Vcb->calcthreads.threads[i].quit = true;
2076 }
2077
2078 KeSetEvent(&Vcb->calcthreads.event, 0, false);
2079
2080 for (i = 0; i < Vcb->calcthreads.num_threads; i++) {
2081 KeWaitForSingleObject(&Vcb->calcthreads.threads[i].finished, Executive, KernelMode, false, NULL);
2082
2083 ZwClose(Vcb->calcthreads.threads[i].handle);
2084 }
2085
2086 ExFreePool(Vcb->calcthreads.threads);
2087
2088 time.QuadPart = 0;
2089 KeSetTimer(&Vcb->flush_thread_timer, time, NULL); // trigger the timer early
2090 KeWaitForSingleObject(&Vcb->flush_thread_finished, Executive, KernelMode, false, NULL);
2091
2092 reap_fcb(Vcb->volume_fcb);
2093 reap_fcb(Vcb->dummy_fcb);
2094
2095 if (Vcb->root_file)
2096 ObDereferenceObject(Vcb->root_file);
2097
2098 le = Vcb->chunks.Flink;
2099 while (le != &Vcb->chunks) {
2101
2102 if (c->cache) {
2103 reap_fcb(c->cache);
2104 c->cache = NULL;
2105 }
2106
2107 le = le->Flink;
2108 }
2109
2110 while (!IsListEmpty(&Vcb->all_fcbs)) {
2111 fcb* fcb = CONTAINING_RECORD(Vcb->all_fcbs.Flink, struct _fcb, list_entry_all);
2112
2113 reap_fcb(fcb);
2114 }
2115
2116 while (!IsListEmpty(&Vcb->sys_chunks)) {
2118
2119 if (sc->data)
2120 ExFreePool(sc->data);
2121
2122 ExFreePool(sc);
2123 }
2124
2125 while (!IsListEmpty(&Vcb->roots)) {
2127
2128 ExDeleteResourceLite(&r->nonpaged->load_tree_lock);
2129 ExFreePool(r->nonpaged);
2130 ExFreePool(r);
2131 }
2132
2133 while (!IsListEmpty(&Vcb->chunks)) {
2135
2136 while (!IsListEmpty(&c->space)) {
2137 LIST_ENTRY* le2 = RemoveHeadList(&c->space);
2139
2140 ExFreePool(s);
2141 }
2142
2143 while (!IsListEmpty(&c->deleting)) {
2144 LIST_ENTRY* le2 = RemoveHeadList(&c->deleting);
2146
2147 ExFreePool(s);
2148 }
2149
2150 if (c->devices)
2151 ExFreePool(c->devices);
2152
2153 if (c->cache)
2154 reap_fcb(c->cache);
2155
2156 ExDeleteResourceLite(&c->range_locks_lock);
2157 ExDeleteResourceLite(&c->partial_stripes_lock);
2158 ExDeleteResourceLite(&c->lock);
2159 ExDeleteResourceLite(&c->changed_extents_lock);
2160
2161 ExFreePool(c->chunk_item);
2162 ExFreePool(c);
2163 }
2164
2165 while (!IsListEmpty(&Vcb->devices)) {
2167
2168 while (!IsListEmpty(&dev->space)) {
2169 LIST_ENTRY* le2 = RemoveHeadList(&dev->space);
2171
2172 ExFreePool(s);
2173 }
2174
2175 ExFreePool(dev);
2176 }
2177
2178 ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
2179 while (!IsListEmpty(&Vcb->scrub.errors)) {
2181
2182 ExFreePool(err);
2183 }
2184 ExReleaseResourceLite(&Vcb->scrub.stats_lock);
2185
2186 ExDeleteResourceLite(&Vcb->fcb_lock);
2187 ExDeleteResourceLite(&Vcb->fileref_lock);
2188 ExDeleteResourceLite(&Vcb->load_lock);
2189 ExDeleteResourceLite(&Vcb->tree_lock);
2190 ExDeleteResourceLite(&Vcb->chunk_lock);
2191 ExDeleteResourceLite(&Vcb->dirty_fcbs_lock);
2192 ExDeleteResourceLite(&Vcb->dirty_filerefs_lock);
2193 ExDeleteResourceLite(&Vcb->dirty_subvols_lock);
2194 ExDeleteResourceLite(&Vcb->scrub.stats_lock);
2195 ExDeleteResourceLite(&Vcb->send_load_lock);
2196
2197 ExDeletePagedLookasideList(&Vcb->tree_data_lookaside);
2198 ExDeletePagedLookasideList(&Vcb->traverse_ptr_lookaside);
2199 ExDeletePagedLookasideList(&Vcb->batch_item_lookaside);
2200 ExDeletePagedLookasideList(&Vcb->fileref_lookaside);
2201 ExDeletePagedLookasideList(&Vcb->fcb_lookaside);
2202 ExDeletePagedLookasideList(&Vcb->name_bit_lookaside);
2203 ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside);
2204 ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside);
2205
2206 ZwClose(Vcb->flush_thread_handle);
2207
2208 if (Vcb->devobj->AttachedDevice)
2209 IoDetachDevice(Vcb->devobj);
2210
2211 IoDeleteDevice(Vcb->devobj);
2212}
2213
2216 LIST_ENTRY* le;
2217
2218 // excise extents
2219
2220 if (fileref->fcb->type != BTRFS_TYPE_DIRECTORY && fileref->fcb->inode_item.st_size > 0) {
2221 Status = excise_extents(fileref->fcb->Vcb, fileref->fcb, 0, sector_align(fileref->fcb->inode_item.st_size, fileref->fcb->Vcb->superblock.sector_size), Irp, rollback);
2222 if (!NT_SUCCESS(Status)) {
2223 ERR("excise_extents returned %08lx\n", Status);
2224 return Status;
2225 }
2226 }
2227
2228 fileref->fcb->Header.AllocationSize.QuadPart = 0;
2229 fileref->fcb->Header.FileSize.QuadPart = 0;
2230 fileref->fcb->Header.ValidDataLength.QuadPart = 0;
2231
2232 if (FileObject) {
2233 CC_FILE_SIZES ccfs;
2234
2235 ccfs.AllocationSize = fileref->fcb->Header.AllocationSize;
2236 ccfs.FileSize = fileref->fcb->Header.FileSize;
2237 ccfs.ValidDataLength = fileref->fcb->Header.ValidDataLength;
2238
2240
2241 _SEH2_TRY {
2242 CcSetFileSizes(FileObject, &ccfs);
2245 } _SEH2_END;
2246
2247 if (!NT_SUCCESS(Status)) {
2248 ERR("CcSetFileSizes threw exception %08lx\n", Status);
2249 return Status;
2250 }
2251 }
2252
2253 fileref->fcb->deleted = true;
2254
2255 le = fileref->children.Flink;
2256 while (le != &fileref->children) {
2258
2259 if (fr2->fcb->ads) {
2260 fr2->fcb->deleted = true;
2261 mark_fcb_dirty(fr2->fcb);
2262 }
2263
2264 le = le->Flink;
2265 }
2266
2267 return STATUS_SUCCESS;
2268}
2269
2271 LARGE_INTEGER newlength, time;
2274 ULONG utf8len = 0;
2275
2278
2279 ExAcquireResourceExclusiveLite(fileref->fcb->Header.Resource, true);
2280
2281 if (fileref->deleted) {
2282 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2283 return STATUS_SUCCESS;
2284 }
2285
2286 if (fileref->fcb->subvol->send_ops > 0) {
2287 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2288 return STATUS_ACCESS_DENIED;
2289 }
2290
2291 fileref->deleted = true;
2292 mark_fileref_dirty(fileref);
2293
2294 // delete INODE_ITEM (0x1)
2295
2296 TRACE("nlink = %u\n", fileref->fcb->inode_item.st_nlink);
2297
2298 if (!fileref->fcb->ads) {
2299 if (fileref->parent->fcb->subvol == fileref->fcb->subvol) {
2300 LIST_ENTRY* le;
2301
2302 mark_fcb_dirty(fileref->fcb);
2303
2304 fileref->fcb->inode_item_changed = true;
2305
2306 if (fileref->fcb->inode_item.st_nlink > 1 || make_orphan) {
2307 fileref->fcb->inode_item.st_nlink--;
2308 fileref->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
2309 fileref->fcb->inode_item.sequence++;
2310 fileref->fcb->inode_item.st_ctime = now;
2311 } else {
2313 if (!NT_SUCCESS(Status)) {
2314 ERR("delete_fileref_fcb returned %08lx\n", Status);
2315 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2316 return Status;
2317 }
2318 }
2319
2320 if (fileref->dc) {
2321 le = fileref->fcb->hardlinks.Flink;
2322 while (le != &fileref->fcb->hardlinks) {
2324
2325 if (hl->parent == fileref->parent->fcb->inode && hl->index == fileref->dc->index) {
2327
2328 if (hl->name.Buffer)
2329 ExFreePool(hl->name.Buffer);
2330
2331 if (hl->utf8.Buffer)
2332 ExFreePool(hl->utf8.Buffer);
2333
2334 ExFreePool(hl);
2335 break;
2336 }
2337
2338 le = le->Flink;
2339 }
2340 }
2341 } else if (fileref->fcb->subvol->parent == fileref->parent->fcb->subvol->id) { // valid subvolume
2342 if (fileref->fcb->subvol->root_item.num_references > 1) {
2343 fileref->fcb->subvol->root_item.num_references--;
2344
2345 mark_fcb_dirty(fileref->fcb); // so ROOT_ITEM gets updated
2346 } else {
2347 LIST_ENTRY* le;
2348
2349 // FIXME - we need a lock here
2350
2351 RemoveEntryList(&fileref->fcb->subvol->list_entry);
2352
2353 InsertTailList(&fileref->fcb->Vcb->drop_roots, &fileref->fcb->subvol->list_entry);
2354
2355 le = fileref->children.Flink;
2356 while (le != &fileref->children) {
2358
2359 if (fr2->fcb->ads) {
2360 fr2->fcb->deleted = true;
2361 mark_fcb_dirty(fr2->fcb);
2362 }
2363
2364 le = le->Flink;
2365 }
2366 }
2367 }
2368 } else {
2369 fileref->fcb->deleted = true;
2370 mark_fcb_dirty(fileref->fcb);
2371 }
2372
2373 // remove dir_child from parent
2374
2375 if (fileref->dc) {
2376 TRACE("delete file %.*S\n", (int)(fileref->dc->name.Length / sizeof(WCHAR)), fileref->dc->name.Buffer);
2377
2378 ExAcquireResourceExclusiveLite(&fileref->parent->fcb->nonpaged->dir_children_lock, true);
2379 RemoveEntryList(&fileref->dc->list_entry_index);
2380
2381 if (!fileref->fcb->ads)
2382 remove_dir_child_from_hash_lists(fileref->parent->fcb, fileref->dc);
2383
2384 ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
2385
2386 if (!fileref->oldutf8.Buffer)
2387 fileref->oldutf8 = fileref->dc->utf8;
2388 else
2389 ExFreePool(fileref->dc->utf8.Buffer);
2390
2391 utf8len = fileref->dc->utf8.Length;
2392
2393 fileref->oldindex = fileref->dc->index;
2394
2395 ExFreePool(fileref->dc->name.Buffer);
2396 ExFreePool(fileref->dc->name_uc.Buffer);
2397 ExFreePool(fileref->dc);
2398
2399 fileref->dc = NULL;
2400 }
2401
2402 // update INODE_ITEM of parent
2403
2404 ExAcquireResourceExclusiveLite(fileref->parent->fcb->Header.Resource, true);
2405
2406 fileref->parent->fcb->inode_item.transid = fileref->fcb->Vcb->superblock.generation;
2407 fileref->parent->fcb->inode_item.sequence++;
2408 fileref->parent->fcb->inode_item.st_ctime = now;
2409
2410 if (!fileref->fcb->ads) {
2411 TRACE("fileref->parent->fcb->inode_item.st_size (inode %I64x) was %I64x\n", fileref->parent->fcb->inode, fileref->parent->fcb->inode_item.st_size);
2412 fileref->parent->fcb->inode_item.st_size -= utf8len * 2;
2413 TRACE("fileref->parent->fcb->inode_item.st_size (inode %I64x) now %I64x\n", fileref->parent->fcb->inode, fileref->parent->fcb->inode_item.st_size);
2414 fileref->parent->fcb->inode_item.st_mtime = now;
2415 }
2416
2417 fileref->parent->fcb->inode_item_changed = true;
2418 ExReleaseResourceLite(fileref->parent->fcb->Header.Resource);
2419
2420 if (!fileref->fcb->ads && fileref->parent->dc)
2422
2423 mark_fcb_dirty(fileref->parent->fcb);
2424
2425 fileref->fcb->subvol->root_item.ctransid = fileref->fcb->Vcb->superblock.generation;
2426 fileref->fcb->subvol->root_item.ctime = now;
2427
2428 newlength.QuadPart = 0;
2429
2430 if (FileObject && !CcUninitializeCacheMap(FileObject, &newlength, NULL))
2431 TRACE("CcUninitializeCacheMap failed\n");
2432
2433 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2434
2435 return STATUS_SUCCESS;
2436}
2437
2444 device_extension* Vcb = DeviceObject->DeviceExtension;
2445 fcb* fcb = FileObject->FsContext;
2446 bool top_level;
2447
2449
2450 TRACE("cleanup\n");
2451
2452 top_level = is_top_level(Irp);
2453
2454 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
2455 Irp->IoStatus.Information = 0;
2457 goto exit;
2458 } else if (DeviceObject == master_devobj) {
2459 TRACE("closing file system\n");
2461 goto exit;
2462 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
2464 goto exit;
2465 }
2466
2467 if (FileObject->Flags & FO_CLEANUP_COMPLETE) {
2468 TRACE("FileObject %p already cleaned up\n", FileObject);
2470 goto exit;
2471 }
2472
2473 if (!fcb) {
2474 ERR("fcb was NULL\n");
2476 goto exit;
2477 }
2478
2480
2481 // We have to use the pointer to Vcb stored in the fcb, as we can receive cleanup
2482 // messages belonging to other devices.
2483
2484 if (FileObject && FileObject->FsContext) {
2485 ccb* ccb;
2486 file_ref* fileref;
2487 bool locked = true;
2488
2489 ccb = FileObject->FsContext2;
2490 fileref = ccb ? ccb->fileref : NULL;
2491
2492 TRACE("cleanup called for FileObject %p\n", FileObject);
2493 TRACE("fileref %p, refcount = %li, open_count = %li\n", fileref, fileref ? fileref->refcount : 0, fileref ? fileref->open_count : 0);
2494
2495 ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
2496
2497 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
2498
2500
2502
2503 if (ccb)
2504 FsRtlNotifyCleanup(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, ccb);
2505
2506 if (ccb && ccb->options & FILE_DELETE_ON_CLOSE && fileref)
2507 fileref->delete_on_close = true;
2508
2509 if (fileref && fileref->delete_on_close && fcb->type == BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0 && fcb != fcb->Vcb->dummy_fcb)
2510 fileref->delete_on_close = false;
2511
2512 if (fcb->Vcb->locked && fcb->Vcb->locked_fileobj == FileObject) {
2513 TRACE("unlocking volume\n");
2516 }
2517
2518 if (ccb && ccb->reserving) {
2519 fcb->subvol->reserved = NULL;
2520 ccb->reserving = false;
2521 // FIXME - flush all of subvol's fcbs
2522 }
2523
2524 if (fileref) {
2525 LONG oc = InterlockedDecrement(&fileref->open_count);
2526#ifdef DEBUG_FCB_REFCOUNTS
2527 ERR("fileref %p: open_count now %i\n", fileref, oc);
2528#endif
2529
2530 if (oc == 0 || (fileref->delete_on_close && fileref->posix_delete)) {
2531 if (!fcb->Vcb->removing) {
2532 if (oc == 0 && fileref->fcb->inode_item.st_nlink == 0 && fileref != fcb->Vcb->root_fileref &&
2533 fcb != fcb->Vcb->volume_fcb && !fcb->ads) { // last handle closed on POSIX-deleted file
2535
2537
2539 if (!NT_SUCCESS(Status)) {
2540 ERR("delete_fileref_fcb returned %08lx\n", Status);
2542 ExReleaseResourceLite(fileref->fcb->Header.Resource);
2543 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
2544 goto exit;
2545 }
2546
2548
2549 mark_fcb_dirty(fileref->fcb);
2550 } else if (fileref->delete_on_close && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) {
2552
2554
2555 if (!fileref->fcb->ads || fileref->dc) {
2556 if (fileref->fcb->ads) {
2558 FILE_ACTION_REMOVED, &fileref->dc->name);
2559 } else
2561 }
2562
2563 ExReleaseResourceLite(fcb->Header.Resource);
2564 locked = false;
2565
2566 // fileref_lock needs to be acquired before fcb->Header.Resource
2567 ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
2568
2569 Status = delete_fileref(fileref, FileObject, oc > 0 && fileref->posix_delete, Irp, &rollback);
2570 if (!NT_SUCCESS(Status)) {
2571 ERR("delete_fileref returned %08lx\n", Status);
2573 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
2574 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
2575 goto exit;
2576 }
2577
2578 ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
2579
2581 } else if (FileObject->Flags & FO_CACHE_SUPPORTED && FileObject->SectionObjectPointer->DataSectionObject) {
2583
2584 if (locked) {
2585 ExReleaseResourceLite(fcb->Header.Resource);
2586 locked = false;
2587 }
2588
2589 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb);
2590
2591 if (!NT_SUCCESS(iosb.Status))
2592 ERR("CcFlushCache returned %08lx\n", iosb.Status);
2593
2594 if (!ExIsResourceAcquiredSharedLite(fcb->Header.PagingIoResource)) {
2595 ExAcquireResourceExclusiveLite(fcb->Header.PagingIoResource, true);
2596 ExReleaseResourceLite(fcb->Header.PagingIoResource);
2597 }
2598
2599 CcPurgeCacheSection(FileObject->SectionObjectPointer, NULL, 0, false);
2600
2601 TRACE("flushed cache on close (FileObject = %p, fcb = %p, AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x)\n",
2602 FileObject, fcb, fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
2603 }
2604 }
2605
2606 if (fcb->Vcb && fcb != fcb->Vcb->volume_fcb)
2608 }
2609 }
2610
2611 if (locked)
2612 ExReleaseResourceLite(fcb->Header.Resource);
2613
2614 ExReleaseResourceLite(&fcb->Vcb->tree_lock);
2615
2617 }
2618
2620
2621exit:
2622 TRACE("returning %08lx\n", Status);
2623
2624 Irp->IoStatus.Status = Status;
2625 Irp->IoStatus.Information = 0;
2626
2628
2629 if (top_level)
2631
2633
2634 return Status;
2635}
2636
2637_Success_(return)
2638bool get_file_attributes_from_xattr(_In_reads_bytes_(len) char* val, _In_ uint16_t len, _Out_ ULONG* atts) {
2639 if (len > 2 && val[0] == '0' && val[1] == 'x') {
2640 int i;
2641 ULONG dosnum = 0;
2642
2643 for (i = 2; i < len; i++) {
2644 dosnum *= 0x10;
2645
2646 if (val[i] >= '0' && val[i] <= '9')
2647 dosnum |= val[i] - '0';
2648 else if (val[i] >= 'a' && val[i] <= 'f')
2649 dosnum |= val[i] + 10 - 'a';
2650 else if (val[i] >= 'A' && val[i] <= 'F')
2651 dosnum |= val[i] + 10 - 'a';
2652 }
2653
2654 TRACE("DOSATTRIB: %08lx\n", dosnum);
2655
2656 *atts = dosnum;
2657
2658 return true;
2659 }
2660
2661 return false;
2662}
2663
2665 _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp) {
2666 ULONG att;
2667 char* eaval;
2668 uint16_t ealen;
2669
2670 if (!ignore_xa && get_xattr(Vcb, r, inode, EA_DOSATTRIB, EA_DOSATTRIB_HASH, (uint8_t**)&eaval, &ealen, Irp)) {
2671 ULONG dosnum = 0;
2672
2673 if (get_file_attributes_from_xattr(eaval, ealen, &dosnum)) {
2674 ExFreePool(eaval);
2675
2677 dosnum |= FILE_ATTRIBUTE_DIRECTORY;
2678 else if (type == BTRFS_TYPE_SYMLINK)
2680
2682 dosnum &= ~FILE_ATTRIBUTE_DIRECTORY;
2683
2684 if (inode == SUBVOL_ROOT_INODE) {
2685 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
2686 dosnum |= FILE_ATTRIBUTE_READONLY;
2687 else
2688 dosnum &= ~FILE_ATTRIBUTE_READONLY;
2689 }
2690
2691 return dosnum;
2692 }
2693
2694 ExFreePool(eaval);
2695 }
2696
2697 switch (type) {
2700 break;
2701
2702 case BTRFS_TYPE_SYMLINK:
2704 break;
2705
2706 default:
2707 att = 0;
2708 break;
2709 }
2710
2711 if (dotfile || (r->id == BTRFS_ROOT_FSTREE && inode == SUBVOL_ROOT_INODE))
2712 att |= FILE_ATTRIBUTE_HIDDEN;
2713
2715
2716 if (inode == SUBVOL_ROOT_INODE) {
2717 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
2719 else
2720 att &= ~FILE_ATTRIBUTE_READONLY;
2721 }
2722
2723 // FIXME - get READONLY from ii->st_mode
2724 // FIXME - return SYSTEM for block/char devices?
2725
2726 if (att == 0)
2728
2729 return att;
2730}
2731
2733 _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override) {
2736 PIRP Irp;
2740
2741 num_reads++;
2742
2745
2746 Offset.QuadPart = (LONGLONG)StartingOffset;
2747
2748 Irp = IoAllocateIrp(DeviceObject->StackSize, false);
2749
2750 if (!Irp) {
2751 ERR("IoAllocateIrp failed\n");
2753 }
2754
2755 Irp->Flags |= IRP_NOCACHE;
2759
2760 if (override)
2762
2763 if (DeviceObject->Flags & DO_BUFFERED_IO) {
2764 Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, ALLOC_TAG);
2765 if (!Irp->AssociatedIrp.SystemBuffer) {
2766 ERR("out of memory\n");
2768 goto exit;
2769 }
2770
2772
2773 Irp->UserBuffer = Buffer;
2774 } else if (DeviceObject->Flags & DO_DIRECT_IO) {
2775 Irp->MdlAddress = IoAllocateMdl(Buffer, Length, false, false, NULL);
2776 if (!Irp->MdlAddress) {
2777 ERR("IoAllocateMdl failed\n");
2779 goto exit;
2780 }
2781
2783
2784 _SEH2_TRY {
2788 } _SEH2_END;
2789
2790 if (!NT_SUCCESS(Status)) {
2791 ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2792 IoFreeMdl(Irp->MdlAddress);
2793 goto exit;
2794 }
2795 } else
2796 Irp->UserBuffer = Buffer;
2797
2798 IrpSp->Parameters.Read.Length = Length;
2799 IrpSp->Parameters.Read.ByteOffset = Offset;
2800
2801 Irp->UserIosb = &IoStatus;
2802
2803 Irp->UserEvent = &context.Event;
2804
2805 IoSetCompletionRoutine(Irp, read_completion, &context, true, true, true);
2806
2808
2809 if (Status == STATUS_PENDING) {
2811 Status = context.iosb.Status;
2812 }
2813
2814 if (DeviceObject->Flags & DO_DIRECT_IO) {
2815 MmUnlockPages(Irp->MdlAddress);
2816 IoFreeMdl(Irp->MdlAddress);
2817 }
2818
2819exit:
2820 IoFreeIrp(Irp);
2821
2822 return Status;
2823}
2824
2826 switch (sb->csum_type) {
2827 case CSUM_TYPE_CRC32C: {
2828 uint32_t crc32 = ~calc_crc32c(0xffffffff, (uint8_t*)&sb->uuid, (ULONG)sizeof(superblock) - sizeof(sb->checksum));
2829
2830 if (crc32 == *((uint32_t*)sb->checksum))
2831 return true;
2832
2833 WARN("crc32 was %08x, expected %08x\n", crc32, *((uint32_t*)sb->checksum));
2834
2835 break;
2836 }
2837
2838 case CSUM_TYPE_XXHASH: {
2839 uint64_t hash = XXH64(&sb->uuid, sizeof(superblock) - sizeof(sb->checksum), 0);
2840
2841 if (hash == *((uint64_t*)sb->checksum))
2842 return true;
2843
2844 WARN("superblock hash was %I64x, expected %I64x\n", hash, *((uint64_t*)sb->checksum));
2845
2846 break;
2847 }
2848
2849 case CSUM_TYPE_SHA256: {
2851
2852 calc_sha256(hash, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2853
2855 return true;
2856
2857 WARN("superblock hash was invalid\n");
2858
2859 break;
2860 }
2861
2862 case CSUM_TYPE_BLAKE2: {
2864
2865 blake2b(hash, sizeof(hash), &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2866
2868 return true;
2869
2870 WARN("superblock hash was invalid\n");
2871
2872 break;
2873 }
2874
2875 default:
2876 WARN("unrecognized csum type %x\n", sb->csum_type);
2877 }
2878
2879 return false;
2880}
2881
2884 superblock* sb;
2885 ULONG i, to_read;
2886 uint8_t valid_superblocks;
2887
2888 to_read = device->SectorSize == 0 ? sizeof(superblock) : (ULONG)sector_align(sizeof(superblock), device->SectorSize);
2889
2891 if (!sb) {
2892 ERR("out of memory\n");
2894 }
2895
2896 if (superblock_addrs[0] + to_read > length) {
2897 WARN("device was too short to have any superblock\n");
2898 ExFreePool(sb);
2900 }
2901
2902 i = 0;
2903 valid_superblocks = 0;
2904
2905 while (superblock_addrs[i] > 0) {
2906 if (i > 0 && superblock_addrs[i] + to_read > length)
2907 break;
2908
2910 if (!NT_SUCCESS(Status)) {
2911 ERR("Failed to read superblock %lu: %08lx\n", i, Status);
2912 ExFreePool(sb);
2913 return Status;
2914 }
2915
2916 if (sb->magic != BTRFS_MAGIC) {
2917 if (i == 0) {
2918 TRACE("not a BTRFS volume\n");
2919 ExFreePool(sb);
2921 }
2922 } else {
2923 TRACE("got superblock %lu!\n", i);
2924
2925 if (sb->sector_size == 0)
2926 WARN("superblock sector size was 0\n");
2927 else if (sb->sector_size & (sb->sector_size - 1))
2928 WARN("superblock sector size was not power of 2\n");
2929 else if (sb->node_size < sizeof(tree_header) + sizeof(internal_node) || sb->node_size > 0x10000)
2930 WARN("invalid node size %x\n", sb->node_size);
2931 else if ((sb->node_size % sb->sector_size) != 0)
2932 WARN("node size %x was not a multiple of sector_size %x\n", sb->node_size, sb->sector_size);
2933 else if (check_superblock_checksum(sb) && (valid_superblocks == 0 || sb->generation > Vcb->superblock.generation)) {
2934 RtlCopyMemory(&Vcb->superblock, sb, sizeof(superblock));
2935 valid_superblocks++;
2936 }
2937 }
2938
2939 i++;
2940 }
2941
2942 ExFreePool(sb);
2943
2944 if (valid_superblocks == 0) {
2945 ERR("could not find any valid superblocks\n");
2946 return STATUS_INTERNAL_ERROR;
2947 }
2948
2949 TRACE("label is %s\n", Vcb->superblock.label);
2950
2951 return STATUS_SUCCESS;
2952}
2953
2955 _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK* iosb) {
2956 PIRP Irp;
2957 KEVENT Event;
2961
2963
2967 InputBufferSize,
2969 OutputBufferSize,
2970 false,
2971 &Event,
2972 &IoStatus);
2973
2975
2976 if (Override) {
2979 }
2980
2982
2983 if (Status == STATUS_PENDING) {
2985 Status = IoStatus.Status;
2986 }
2987
2988 if (iosb)
2989 *iosb = IoStatus;
2990
2991 return Status;
2992}
2993
2998 if (!r) {
2999 ERR("out of memory\n");
3001 }
3002
3003 r->id = id;
3004 r->dirty = false;
3005 r->received = false;
3006 r->reserved = NULL;
3007 r->treeholder.address = addr;
3008 r->treeholder.tree = NULL;
3009 r->treeholder.generation = generation;
3010 r->parent = 0;
3011 r->send_ops = 0;
3012 r->fcbs_version = 0;
3013 r->checked_for_orphans = false;
3014 r->dropped = false;
3016 RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
3017
3019 if (!r->nonpaged) {
3020 ERR("out of memory\n");
3021 ExFreePool(r);
3023 }
3024
3025 ExInitializeResourceLite(&r->nonpaged->load_tree_lock);
3026
3027 r->lastinode = 0;
3028
3029 if (tp) {
3030 RtlCopyMemory(&r->root_item, tp->item->data, min(sizeof(ROOT_ITEM), tp->item->size));
3031 if (tp->item->size < sizeof(ROOT_ITEM))
3032 RtlZeroMemory(((uint8_t*)&r->root_item) + tp->item->size, sizeof(ROOT_ITEM) - tp->item->size);
3033 } else
3034 RtlZeroMemory(&r->root_item, sizeof(ROOT_ITEM));
3035
3036 if (!Vcb->readonly && (r->id == BTRFS_ROOT_ROOT || r->id == BTRFS_ROOT_FSTREE || (r->id >= 0x100 && !(r->id & 0xf000000000000000)))) { // FS tree root
3037 // FIXME - don't call this if subvol is readonly (though we will have to if we ever toggle this flag)
3039
3040 if (r->id == BTRFS_ROOT_ROOT && r->lastinode < 0x100)
3041 r->lastinode = 0x100;
3042 }
3043
3044 InsertTailList(&Vcb->roots, &r->list_entry);
3045
3046 switch (r->id) {
3047 case BTRFS_ROOT_ROOT:
3048 Vcb->root_root = r;
3049 break;
3050
3051 case BTRFS_ROOT_EXTENT:
3052 Vcb->extent_root = r;
3053 break;
3054
3055 case BTRFS_ROOT_CHUNK:
3056 Vcb->chunk_root = r;
3057 break;
3058
3059 case BTRFS_ROOT_DEVTREE:
3060 Vcb->dev_root = r;
3061 break;
3062
3064 Vcb->checksum_root = r;
3065 break;
3066
3067 case BTRFS_ROOT_UUID:
3068 Vcb->uuid_root = r;
3069 break;
3070
3072 Vcb->space_root = r;
3073 break;
3074
3076 Vcb->data_reloc_root = r;
3077 break;
3078 }
3079
3081}
3082
3084 traverse_ptr tp, next_tp;
3085 KEY searchkey;
3086 bool b;
3088
3089 searchkey.obj_id = 0;
3090 searchkey.obj_type = 0;
3091 searchkey.offset = 0;
3092
3093 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
3094 if (!NT_SUCCESS(Status)) {
3095 ERR("error - find_item returned %08lx\n", Status);
3096 return Status;
3097 }
3098
3099 do {
3100 TRACE("(%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
3101
3102 if (tp.item->key.obj_type == TYPE_ROOT_ITEM) {
3103 ROOT_ITEM* ri = (ROOT_ITEM*)tp.item->data;
3104
3105 if (tp.item->size < offsetof(ROOT_ITEM, byte_limit)) {
3106 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(ROOT_ITEM, byte_limit));
3107 } else {
3108 TRACE("root %I64x - address %I64x\n", tp.item->key.obj_id, ri->block_number);
3109
3111 if (!NT_SUCCESS(Status)) {
3112 ERR("add_root returned %08lx\n", Status);
3113 return Status;
3114 }
3115 }
3116 } else if (tp.item->key.obj_type == TYPE_ROOT_BACKREF && !IsListEmpty(&Vcb->roots)) {
3117 root* lastroot = CONTAINING_RECORD(Vcb->roots.Blink, root, list_entry);
3118
3119 if (lastroot->id == tp.item->key.obj_id)
3120 lastroot->parent = tp.item->key.offset;
3121 }
3122
3123 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
3124
3125 if (b)
3126 tp = next_tp;
3127 } while (b);
3128
3129 if (!Vcb->readonly && !Vcb->data_reloc_root) {
3131 INODE_ITEM* ii;
3132 uint16_t irlen;
3133 INODE_REF* ir;
3136
3137 WARN("data reloc root doesn't exist, creating it\n");
3138
3140
3141 if (!NT_SUCCESS(Status)) {
3142 ERR("create_root returned %08lx\n", Status);
3143 return Status;
3144 }
3145
3146 reloc_root->root_item.inode.generation = 1;
3147 reloc_root->root_item.inode.st_size = 3;
3148 reloc_root->root_item.inode.st_blocks = Vcb->superblock.node_size;
3149 reloc_root->root_item.inode.st_nlink = 1;
3150 reloc_root->root_item.inode.st_mode = 040755;
3151 reloc_root->root_item.inode.flags = 0x80000000;
3152 reloc_root->root_item.inode.flags_ro = 0xffffffff;
3153 reloc_root->root_item.objid = SUBVOL_ROOT_INODE;
3154 reloc_root->root_item.bytes_used = Vcb->superblock.node_size;
3155
3157 if (!ii) {
3158 ERR("out of memory\n");
3160 }
3161
3164
3165 RtlZeroMemory(ii, sizeof(INODE_ITEM));
3166 ii->generation = Vcb->superblock.generation;
3167 ii->st_blocks = Vcb->superblock.node_size;
3168 ii->st_nlink = 1;
3169 ii->st_mode = 040755;
3170 ii->st_atime = now;
3171 ii->st_ctime = now;
3172 ii->st_mtime = now;
3173
3175 if (!NT_SUCCESS(Status)) {
3176 ERR("insert_tree_item returned %08lx\n", Status);
3177 ExFreePool(ii);
3178 return Status;
3179 }
3180
3181 irlen = (uint16_t)offsetof(INODE_REF, name[0]) + 2;
3183 if (!ir) {
3184 ERR("out of memory\n");
3186 }
3187
3188 ir->index = 0;
3189 ir->n = 2;
3190 ir->name[0] = '.';
3191 ir->name[1] = '.';
3192
3194 if (!NT_SUCCESS(Status)) {
3195 ERR("insert_tree_item returned %08lx\n", Status);
3196 ExFreePool(ir);
3197 return Status;
3198 }
3199
3200 Vcb->data_reloc_root = reloc_root;
3201 Vcb->need_write = true;
3202 }
3203
3204 return STATUS_SUCCESS;
3205}
3206
3208 KEY searchkey;
3209 traverse_ptr tp, next_tp;
3210 bool b;
3211 uint64_t lastaddr;
3213
3214 InitializeListHead(&dev->space);
3215
3216 searchkey.obj_id = 0;
3217 searchkey.obj_type = TYPE_DEV_STATS;
3218 searchkey.offset = dev->devitem.dev_id;
3219
3220 Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
3221 if (NT_SUCCESS(Status) && !keycmp(tp.item->key, searchkey))
3222 RtlCopyMemory(dev->stats, tp.item->data, min(sizeof(uint64_t) * 5, tp.item->size));
3223
3224 searchkey.obj_id = dev->devitem.dev_id;
3225 searchkey.obj_type = TYPE_DEV_EXTENT;
3226 searchkey.offset = 0;
3227
3228 Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
3229 if (!NT_SUCCESS(Status)) {
3230 ERR("error - find_item returned %08lx\n", Status);
3231 return Status;
3232 }
3233
3234 lastaddr = 0;
3235
3236 do {
3237 if (tp.item->key.obj_id == dev->devitem.dev_id && tp.item->key.obj_type == TYPE_DEV_EXTENT) {
3238 if (tp.item->size >= sizeof(DEV_EXTENT)) {
3239 DEV_EXTENT* de = (DEV_EXTENT*)tp.item->data;
3240
3241 if (tp.item->key.offset > lastaddr) {
3242 Status = add_space_entry(&dev->space, NULL, lastaddr, tp.item->key.offset - lastaddr);
3243 if (!NT_SUCCESS(Status)) {
3244 ERR("add_space_entry returned %08lx\n", Status);
3245 return Status;
3246 }
3247 }
3248
3249 lastaddr = tp.item->key.offset + de->length;
3250 } else {
3251 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DEV_EXTENT));
3252 }
3253 }
3254
3255 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
3256
3257 if (b) {
3258 tp = next_tp;
3259 if (tp.item->key.obj_id > searchkey.obj_id || tp.item->key.obj_type > searchkey.obj_type)
3260 break;
3261 }
3262 } while (b);
3263
3264 if (lastaddr < dev->devitem.num_bytes) {
3265 Status = add_space_entry(&dev->space, NULL, lastaddr, dev->devitem.num_bytes - lastaddr);
3266 if (!NT_SUCCESS(Status)) {
3267 ERR("add_space_entry returned %08lx\n", Status);
3268 return Status;
3269 }
3270 }
3271
3272 // The Linux driver doesn't like to allocate chunks within the first megabyte of a device.
3273
3274 space_list_subtract2(&dev->space, NULL, 0, 0x100000, NULL, NULL);
3275
3276 return STATUS_SUCCESS;
3277}
3278
3280 LIST_ENTRY* le;
3281
3282 le = Vcb->devices.Flink;
3283
3284 while (le != &Vcb->devices) {
3286
3287 if (dev2->devitem.dev_id > dev->devitem.dev_id) {
3288 InsertHeadList(le->Blink, &dev->list_entry);
3289 return;
3290 }
3291
3292 le = le->Flink;
3293 }
3294
3295 InsertTailList(&Vcb->devices, &dev->list_entry);
3296}
3297
3301 pdo_device_extension* pdode;
3302 LIST_ENTRY* le;
3303
3304 le = Vcb->devices.Flink;
3305 while (le != &Vcb->devices) {
3307
3308 TRACE("device %I64x, uuid %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", dev->devitem.dev_id,
3309 dev->devitem.device_uuid.uuid[0], dev->devitem.device_uuid.uuid[1], dev->devitem.device_uuid.uuid[2], dev->devitem.device_uuid.uuid[3], dev->devitem.device_uuid.uuid[4], dev->devitem.device_uuid.uuid[5], dev->devitem.device_uuid.uuid[6], dev->devitem.device_uuid.uuid[7],
3310 dev->devitem.device_uuid.uuid[8], dev->devitem.device_uuid.uuid[9], dev->devitem.device_uuid.uuid[10], dev->devitem.device_uuid.uuid[11], dev->devitem.device_uuid.uuid[12], dev->devitem.device_uuid.uuid[13], dev->devitem.device_uuid.uuid[14], dev->devitem.device_uuid.uuid[15]);
3311
3312 if (RtlCompareMemory(&dev->devitem.device_uuid, uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3313 TRACE("returning device %I64x\n", dev->devitem.dev_id);
3314 return dev;
3315 }
3316
3317 le = le->Flink;
3318 }
3319
3320 vde = Vcb->vde;
3321
3322 if (!vde)
3323 goto end;
3324
3325 pdode = vde->pdode;
3326
3328
3329 if (Vcb->devices_loaded < Vcb->superblock.num_devices) {
3330 le = pdode->children.Flink;
3331
3332 while (le != &pdode->children) {
3334
3335 if (RtlCompareMemory(uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3336 device* dev;
3337
3339 if (!dev) {
3341 ERR("out of memory\n");
3342 return NULL;
3343 }
3344
3345 RtlZeroMemory(dev, sizeof(device));
3346 dev->devobj = vc->devobj;
3347 dev->fileobj = vc->fileobj;
3348 dev->devitem.device_uuid = *uuid;
3349 dev->devitem.dev_id = vc->devid;
3350 dev->devitem.num_bytes = vc->size;
3351 dev->seeding = vc->seeding;
3352 dev->readonly = dev->seeding;
3353 dev->reloc = false;
3354 dev->removable = false;
3355 dev->disk_num = vc->disk_num;
3356 dev->part_num = vc->part_num;
3357 dev->num_trim_entries = 0;
3358 InitializeListHead(&dev->trim_list);
3359
3361 Vcb->devices_loaded++;
3362
3364
3365 return dev;
3366 }
3367
3368 le = le->Flink;
3369 }
3370 }
3371
3373
3374end:
3375 WARN("could not find device with uuid %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
3376 uuid->uuid[0], uuid->uuid[1], uuid->uuid[2], uuid->uuid[3], uuid->uuid[4], uuid->uuid[5], uuid->uuid[6], uuid->uuid[7],
3377 uuid->uuid[8], uuid->uuid[9], uuid->uuid[10], uuid->uuid[11], uuid->uuid[12], uuid->uuid[13], uuid->uuid[14], uuid->uuid[15]);
3378
3379 return NULL;
3380}
3381
3385
3386 Status = dev_ioctl(devobj, IOCTL_STORAGE_GET_HOTPLUG_INFO, NULL, 0, &shi, sizeof(STORAGE_HOTPLUG_INFO), true, NULL);
3387
3388 if (!NT_SUCCESS(Status)) {
3389 ERR("dev_ioctl returned %08lx\n", Status);
3390 return false;
3391 }
3392
3393 return shi.MediaRemovable != 0 ? true : false;
3394}
3395
3398 ULONG cc;
3400
3401 Status = dev_ioctl(devobj, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), true, &iosb);
3402
3403 if (!NT_SUCCESS(Status)) {
3404 ERR("dev_ioctl returned %08lx\n", Status);
3405 return 0;
3406 }
3407
3408 if (iosb.Information < sizeof(ULONG)) {
3409 ERR("iosb.Information was too short\n");
3410 return 0;
3411 }
3412
3413 return cc;
3414}
3415
3418 ULONG aptelen;
3419 ATA_PASS_THROUGH_EX* apte;
3422
3423 dev->removable = is_device_removable(dev->devobj);
3424 dev->change_count = dev->removable ? get_device_change_count(dev->devobj) : 0;
3425
3426 if (get_nums) {
3428
3430 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
3431
3432 if (!NT_SUCCESS(Status)) {
3433 WARN("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08lx\n", Status);
3434 dev->disk_num = 0xffffffff;
3435 dev->part_num = 0xffffffff;
3436 } else {
3437 dev->disk_num = sdn.DeviceNumber;
3438 dev->part_num = sdn.PartitionNumber;
3439 }
3440 }
3441
3442 dev->trim = false;
3443 dev->readonly = dev->seeding;
3444 dev->reloc = false;
3445 dev->num_trim_entries = 0;
3446 dev->stats_changed = false;
3447 InitializeListHead(&dev->trim_list);
3448
3449 if (!dev->readonly) {
3451 NULL, 0, true, NULL);
3453 dev->readonly = true;
3454 }
3455
3456 aptelen = sizeof(ATA_PASS_THROUGH_EX) + 512;
3458 if (!apte) {
3459 ERR("out of memory\n");
3460 return;
3461 }
3462
3463 RtlZeroMemory(apte, aptelen);
3464
3465 apte->Length = sizeof(ATA_PASS_THROUGH_EX);
3467 apte->DataTransferLength = aptelen - sizeof(ATA_PASS_THROUGH_EX);
3468 apte->TimeOutValue = 3;
3469 apte->DataBufferOffset = apte->Length;
3471
3472 Status = dev_ioctl(dev->devobj, IOCTL_ATA_PASS_THROUGH, apte, aptelen,
3473 apte, aptelen, true, NULL);
3474
3475 if (!NT_SUCCESS(Status))
3476 TRACE("IOCTL_ATA_PASS_THROUGH returned %08lx for IDENTIFY DEVICE\n", Status);
3477 else {
3479
3480 if (idd->CommandSetSupport.FlushCache) {
3481 dev->can_flush = true;
3482 TRACE("FLUSH CACHE supported\n");
3483 } else
3484 TRACE("FLUSH CACHE not supported\n");
3485 }
3486
3487 ExFreePool(apte);
3488
3489#ifdef DEBUG_TRIM_EMULATION
3490 dev->trim = true;
3491 Vcb->trim = true;
3492#else
3495 spq.AdditionalParameters[0] = 0;
3496
3498 &dtd, sizeof(DEVICE_TRIM_DESCRIPTOR), true, NULL);
3499
3500 if (NT_SUCCESS(Status)) {
3501 if (dtd.TrimEnabled) {
3502 dev->trim = true;
3503 Vcb->trim = true;
3504 TRACE("TRIM supported\n");
3505 } else
3506 TRACE("TRIM not supported\n");
3507 }
3508#endif
3509
3510 RtlZeroMemory(dev->stats, sizeof(uint64_t) * 5);
3511}
3512
3514 traverse_ptr tp, next_tp;
3515 KEY searchkey;
3516 bool b;
3517 chunk* c;
3519
3520 searchkey.obj_id = 0;
3521 searchkey.obj_type = 0;
3522 searchkey.offset = 0;
3523
3524 Vcb->data_flags = 0;
3525 Vcb->metadata_flags = 0;
3526 Vcb->system_flags = 0;
3527
3528 Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, false, Irp);
3529 if (!NT_SUCCESS(Status)) {
3530 ERR("error - find_item returned %08lx\n", Status);
3531 return Status;
3532 }
3533
3534 do {
3535 TRACE("(%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
3536
3537 if (tp.item->key.obj_id == 1 && tp.item->key.obj_type == TYPE_DEV_ITEM) {
3538 if (tp.item->size < sizeof(DEV_ITEM)) {
3539 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DEV_ITEM));
3540 } else {
3541 DEV_ITEM* di = (DEV_ITEM*)tp.item->data;
3542 LIST_ENTRY* le;
3543 bool done = false;
3544
3545 le = Vcb->devices.Flink;
3546 while (le != &Vcb->devices) {
3548
3549 if (dev->devobj && RtlCompareMemory(&dev->devitem.device_uuid, &di->device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3550 RtlCopyMemory(&dev->devitem, tp.item->data, min(tp.item->size, sizeof(DEV_ITEM)));
3551
3552 if (le != Vcb->devices.Flink)
3553 init_device(Vcb, dev, true);
3554
3555 done = true;
3556 break;
3557 }
3558
3559 le = le->Flink;
3560 }
3561
3562 if (!done && Vcb->vde) {
3563 volume_device_extension* vde = Vcb->vde;
3564 pdo_device_extension* pdode = vde->pdode;
3565
3567
3568 if (Vcb->devices_loaded < Vcb->superblock.num_devices) {
3569 le = pdode->children.Flink;
3570
3571 while (le != &pdode->children) {
3573
3574 if (RtlCompareMemory(&di->device_uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
3575 device* dev;
3576
3578 if (!dev) {
3580 ERR("out of memory\n");
3582 }
3583
3584 RtlZeroMemory(dev, sizeof(device));
3585
3586 dev->devobj = vc->devobj;
3587 dev->fileobj = vc->fileobj;
3588 RtlCopyMemory(&dev->devitem, di, min(tp.item->size, sizeof(DEV_ITEM)));
3589 dev->seeding = vc->seeding;
3590 init_device(Vcb, dev, false);
3591
3592 if (dev->devitem.num_bytes > vc->size) {
3593 WARN("device %I64x: DEV_ITEM says %I64x bytes, but Windows only reports %I64x\n", tp.item->key.offset,
3594 dev->devitem.num_bytes, vc->size);
3595
3596 dev->devitem.num_bytes = vc->size;
3597 }
3598
3599 dev->disk_num = vc->disk_num;
3600 dev->part_num = vc->part_num;
3602 Vcb->devices_loaded++;
3603
3604 done = true;
3605 break;
3606 }
3607
3608 le = le->Flink;
3609 }
3610
3611 if (!done) {
3612 if (!Vcb->options.allow_degraded) {
3613 ERR("volume not found: device %I64x, uuid %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", tp.item->key.offset,
3614 di->device_uuid.uuid[0], di->device_uuid.uuid[1], di->device_uuid.uuid[2], di->device_uuid.uuid[3], di->device_uuid.uuid[4], di->device_uuid.uuid[5], di->device_uuid.uuid[6], di->device_uuid.uuid[7],
3615 di->device_uuid.uuid[8], di->device_uuid.uuid[9], di->device_uuid.uuid[10], di->device_uuid.uuid[11], di->device_uuid.uuid[12], di->device_uuid.uuid[13], di->device_uuid.uuid[14], di->device_uuid.uuid[15]);
3616 } else {
3617 device* dev;
3618
3620 if (!dev) {
3622 ERR("out of memory\n");
3624 }
3625
3626 RtlZeroMemory(dev, sizeof(device));
3627
3628 // Missing device, so we keep dev->devobj as NULL
3629 RtlCopyMemory(&dev->devitem, di, min(tp.item->size, sizeof(DEV_ITEM)));
3630 InitializeListHead(&dev->trim_list);
3631
3633 Vcb->devices_loaded++;
3634 }
3635 }
3636 } else
3637 ERR("unexpected device %I64x found\n", tp.item->key.offset);
3638
3640 }
3641 }
3642 } else if (tp.item->key.obj_type == TYPE_CHUNK_ITEM) {
3643 if (tp.item->size < sizeof(CHUNK_ITEM)) {
3644 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(CHUNK_ITEM));
3645 } else {
3647
3648 if (!c) {
3649 ERR("out of memory\n");
3651 }
3652
3653 c->size = tp.item->size;
3654 c->offset = tp.item->key.offset;
3655 c->used = c->oldused = 0;
3656 c->cache = c->old_cache = NULL;
3657 c->created = false;
3658 c->readonly = false;
3659 c->reloc = false;
3660 c->cache_loaded = false;
3661 c->changed = false;
3662 c->space_changed = false;
3663 c->balance_num = 0;
3664
3666
3667 if (!c->chunk_item) {
3668 ERR("out of memory\n");
3669 ExFreePool(c);
3671 }
3672
3673 RtlCopyMemory(c->chunk_item, tp.item->data, tp.item->size);
3674
3675 if (c->chunk_item->type & BLOCK_FLAG_DATA && c->chunk_item->type > Vcb->data_flags)
3676 Vcb->data_flags = c->chunk_item->type;
3677
3678 if (c->chunk_item->type & BLOCK_FLAG_METADATA && c->chunk_item->type > Vcb->metadata_flags)
3679 Vcb->metadata_flags = c->chunk_item->type;
3680
3681 if (c->chunk_item->type & BLOCK_FLAG_SYSTEM && c->chunk_item->type > Vcb->system_flags)
3682 Vcb->system_flags = c->chunk_item->type;
3683
3684 if (c->chunk_item->type & BLOCK_FLAG_RAID10) {
3685 if (c->chunk_item->sub_stripes == 0 || c->chunk_item->sub_stripes > c->chunk_item->num_stripes) {
3686 ERR("chunk %I64x: invalid stripes (num_stripes %u, sub_stripes %u)\n", c->offset, c->chunk_item->num_stripes, c->chunk_item->sub_stripes);
3687 ExFreePool(c->chunk_item);
3688 ExFreePool(c);
3689 return STATUS_INTERNAL_ERROR;
3690 }
3691 }
3692
3693 if (c->chunk_item->num_stripes > 0) {
3694 CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
3695 uint16_t i;
3696
3697 c->devices = ExAllocatePoolWithTag(NonPagedPool, sizeof(device*) * c->chunk_item->num_stripes, ALLOC_TAG);
3698
3699 if (!c->devices) {
3700 ERR("out of memory\n");
3701 ExFreePool(c->chunk_item);
3702 ExFreePool(c);
3704 }
3705
3706 for (i = 0; i < c->chunk_item->num_stripes; i++) {
3707 c->devices[i] = find_device_from_uuid(Vcb, &cis[i].dev_uuid);
3708 TRACE("device %u = %p\n", i, c->devices[i]);
3709
3710 if (!c->devices[i]) {
3711 ERR("missing device\n");
3712 ExFreePool(c->chunk_item);
3713 ExFreePool(c);
3714 return STATUS_INTERNAL_ERROR;
3715 }
3716
3717 if (c->devices[i]->readonly)
3718 c->readonly = true;
3719 }
3720 } else {
3721 ERR("chunk %I64x: number of stripes is 0\n", c->offset);
3722 ExFreePool(c->chunk_item);
3723 ExFreePool(c);
3724 return STATUS_INTERNAL_ERROR;
3725 }
3726
3728 ExInitializeResourceLite(&c->changed_extents_lock);
3729
3730 InitializeListHead(&c->space);
3731 InitializeListHead(&c->space_size);
3732 InitializeListHead(&c->deleting);
3733 InitializeListHead(&c->changed_extents);
3734
3735 InitializeListHead(&c->range_locks);
3736 ExInitializeResourceLite(&c->range_locks_lock);
3737 KeInitializeEvent(&c->range_locks_event, NotificationEvent, false);
3738
3739 InitializeListHead(&c->partial_stripes);
3740 ExInitializeResourceLite(&c->partial_stripes_lock);
3741
3742 c->last_alloc_set = false;
3743
3744 c->last_stripe = 0;
3745
3746 InsertTailList(&Vcb->chunks, &c->list_entry);
3747
3748 c->list_entry_balance.Flink = NULL;
3749 }
3750 }
3751
3752 b = find_next_item(Vcb, &tp, &next_tp, false, Irp);
3753
3754 if (b)
3755 tp = next_tp;
3756 } while (b);
3757
3758 Vcb->log_to_phys_loaded = true;
3759
3760 if (Vcb->data_flags == 0)
3761 Vcb->data_flags = BLOCK_FLAG_DATA | (Vcb->superblock.num_devices > 1 ? BLOCK_FLAG_RAID0 : 0);
3762
3763 if (Vcb->metadata_flags == 0)
3764 Vcb->metadata_flags = BLOCK_FLAG_METADATA | (Vcb->superblock.num_devices > 1 ? BLOCK_FLAG_RAID1 : BLOCK_FLAG_DUPLICATE);
3765
3766 if (Vcb->system_flags == 0)
3767 Vcb->system_flags = BLOCK_FLAG_SYSTEM | (Vcb->superblock.num_devices > 1 ? BLOCK_FLAG_RAID1 : BLOCK_FLAG_DUPLICATE);
3768
3769 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS) {
3770 Vcb->metadata_flags |= BLOCK_FLAG_DATA;
3771 Vcb->data_flags = Vcb->metadata_flags;
3772 }
3773
3774 return STATUS_SUCCESS;
3775}
3776
3778 uint16_t i = 0, j;
3779 uint64_t off_start, off_end;
3780
3781 // The Linux driver also protects all the space before the first superblock.
3782 // I realize this confuses physical and logical addresses, but this is what btrfs-progs does -
3783 // evidently Linux assumes the chunk at 0 is always SINGLE.
3784 if (c->offset < superblock_addrs[0])
3785 space_list_subtract(c, c->offset, superblock_addrs[0] - c->offset, NULL);
3786
3787 while (superblock_addrs[i] != 0) {
3788 CHUNK_ITEM* ci = c->chunk_item;
3789 CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
3790
3791 if (ci->type & BLOCK_FLAG_RAID0 || ci->type & BLOCK_FLAG_RAID10) {
3792 for (j = 0; j < ci->num_stripes; j++) {
3793 uint16_t sub_stripes = max(ci->sub_stripes, 1);
3794
3795 if (cis[j].offset + (ci->size * ci->num_stripes / sub_stripes) > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3796#ifdef _DEBUG
3797 uint64_t startoff;
3798 uint16_t startoffstripe;
3799#endif
3800
3801 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3802
3803 off_start = superblock_addrs[i] - cis[j].offset;
3804 off_start -= off_start % ci->stripe_length;
3805 off_start *= ci->num_stripes / sub_stripes;
3806 off_start += (j / sub_stripes) * ci->stripe_length;
3807
3808 off_end = off_start + ci->stripe_length;
3809
3810#ifdef _DEBUG
3811 get_raid0_offset(off_start, ci->stripe_length, ci->num_stripes / sub_stripes, &startoff, &startoffstripe);
3812 TRACE("j = %u, startoffstripe = %u\n", j, startoffstripe);
3813 TRACE("startoff = %I64x, superblock = %I64x\n", startoff + cis[j].offset, superblock_addrs[i]);
3814#endif
3815
3816 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3817 }
3818 }
3819 } else if (ci->type & BLOCK_FLAG_RAID5) {
3820 uint64_t stripe_size = ci->size / (ci->num_stripes - 1);
3821
3822 for (j = 0; j < ci->num_stripes; j++) {
3823 if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3824 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3825
3826 off_start = superblock_addrs[i] - cis[j].offset;
3827 off_start -= off_start % ci->stripe_length;
3828 off_start *= ci->num_stripes - 1;
3829
3830 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), ci->stripe_length);
3831 off_end *= ci->num_stripes - 1;
3832
3833 TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
3834
3835 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3836 }
3837 }
3838 } else if (ci->type & BLOCK_FLAG_RAID6) {
3839 uint64_t stripe_size = ci->size / (ci->num_stripes - 2);
3840
3841 for (j = 0; j < ci->num_stripes; j++) {
3842 if (cis[j].offset + stripe_size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3843 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3844
3845 off_start = superblock_addrs[i] - cis[j].offset;
3846 off_start -= off_start % ci->stripe_length;
3847 off_start *= ci->num_stripes - 2;
3848
3849 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), ci->stripe_length);
3850 off_end *= ci->num_stripes - 2;
3851
3852 TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
3853
3854 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3855 }
3856 }
3857 } else { // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
3858 for (j = 0; j < ci->num_stripes; j++) {
3859 if (cis[j].offset + ci->size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) {
3860 TRACE("cut out superblock in chunk %I64x\n", c->offset);
3861
3862 // The Linux driver protects the whole stripe in which the superblock lives
3863
3864 off_start = ((superblock_addrs[i] - cis[j].offset) / c->chunk_item->stripe_length) * c->chunk_item->stripe_length;
3865 off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), c->chunk_item->stripe_length);
3866
3867 space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL);
3868 }
3869 }
3870 }
3871
3872 i++;
3873 }
3874}
3875
3877 LIST_ENTRY* le = Vcb->chunks.Flink;
3878 chunk* c;
3879 KEY searchkey;
3881 BLOCK_GROUP_ITEM* bgi;
3883
3884 searchkey.obj_type = TYPE_BLOCK_GROUP_ITEM;
3885
3886 Vcb->superblock.bytes_used = 0;
3887
3888 while (le != &Vcb->chunks) {
3890
3891 searchkey.obj_id = c->offset;
3892 searchkey.offset = c->chunk_item->size;
3893
3894 Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
3895 if (!NT_SUCCESS(Status)) {
3896 ERR("error - find_item returned %08lx\n", Status);
3897 return Status;
3898 }
3899
3900 if (!keycmp(searchkey, tp.item->key)) {
3901 if (tp.item->size >= sizeof(BLOCK_GROUP_ITEM)) {
3902 bgi = (BLOCK_GROUP_ITEM*)tp.item->data;
3903
3904 c->used = c->oldused = bgi->used;
3905
3906 TRACE("chunk %I64x has %I64x bytes used\n", c->offset, c->used);
3907
3908 Vcb->superblock.bytes_used += bgi->used;
3909 } else {
3910 ERR("(%I64x;%I64x,%x,%I64x) is %u bytes, expected %Iu\n",
3911 Vcb->extent_root->id, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(BLOCK_GROUP_ITEM));
3912 }
3913 }
3914
3915 le = le->Flink;
3916 }
3917
3918 Vcb->chunk_usage_found = true;
3919
3920 return STATUS_SUCCESS;
3921}
3922
3924 KEY key;
3925 ULONG n = Vcb->superblock.n;
3926
3927 while (n > 0) {
3928 if (n > sizeof(KEY)) {
3929 RtlCopyMemory(&key, &Vcb->superblock.sys_chunk_array[Vcb->superblock.n - n], sizeof(KEY));
3930 n -= sizeof(KEY);
3931 } else
3932 return STATUS_SUCCESS;
3933
3934 TRACE("bootstrap: %I64x,%x,%I64x\n", key.obj_id, key.obj_type, key.offset);
3935
3936 if (key.obj_type == TYPE_CHUNK_ITEM) {
3937 CHUNK_ITEM* ci;
3938 USHORT cisize;
3939 sys_chunk* sc;
3940
3941 if (n < sizeof(CHUNK_ITEM))
3942 return STATUS_SUCCESS;
3943
3944 ci = (CHUNK_ITEM*)&Vcb->superblock.sys_chunk_array[Vcb->superblock.n - n];
3945 cisize = sizeof(CHUNK_ITEM) + (ci->num_stripes * sizeof(CHUNK_ITEM_STRIPE));
3946
3947 if (n < cisize)
3948 return STATUS_SUCCESS;
3949
3951
3952 if (!sc) {
3953 ERR("out of memory\n");
3955 }
3956
3957 sc->key = key;
3958 sc->size = cisize;
3960
3961 if (!sc->data) {
3962 ERR("out of memory\n");
3963 ExFreePool(sc);
3965 }
3966
3967 RtlCopyMemory(sc->data, ci, sc->size);
3968 InsertTailList(&Vcb->sys_chunks, &sc->list_entry);
3969
3970 n -= cisize;
3971 } else {
3972 ERR("unexpected item %I64x,%x,%I64x in bootstrap\n", key.obj_id, key.obj_type, key.offset);
3973 return STATUS_INTERNAL_ERROR;
3974 }
3975 }
3976
3977 return STATUS_SUCCESS;
3978}
3979
3982 LIST_ENTRY* le;
3983
3984 static const char fn[] = "default";
3985 static uint32_t crc32 = 0x8dbfc2d2;
3986
3987 if (Vcb->options.subvol_id != 0) {
3988 le = Vcb->roots.Flink;
3989 while (le != &Vcb->roots) {
3991
3992 if (r->id == Vcb->options.subvol_id)
3993 return r;
3994
3995 le = le->Flink;
3996 }
3997 }
3998
3999 if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL) {
4001 KEY searchkey;
4003 DIR_ITEM* di;
4004
4005 searchkey.obj_id = Vcb->superblock.root_dir_objectid;
4006 searchkey.obj_type = TYPE_DIR_ITEM;
4007 searchkey.offset = crc32;
4008
4009 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
4010 if (!NT_SUCCESS(Status)) {
4011 ERR("error - find_item returned %08lx\n", Status);
4012 goto end;
4013 }
4014
4015 if (keycmp(tp.item->key, searchkey)) {
4016 ERR("could not find (%I64x,%x,%I64x) in root tree\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset);
4017 goto end;
4018 }
4019
4020 if (tp.item->size < sizeof(DIR_ITEM)) {
4021 ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
4022 goto end;
4023 }
4024
4025 di = (DIR_ITEM*)tp.item->data;
4026
4027 if (tp.item->size < sizeof(DIR_ITEM) - 1 + di->n) {
4028 ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM) - 1 + di->n);
4029 goto end;
4030 }
4031
4032 if (di->n != strlen(fn) || RtlCompareMemory(di->name, fn, di->n) != di->n) {
4033 ERR("root DIR_ITEM had same CRC32, but was not \"default\"\n");
4034 goto end;
4035 }
4036
4037 if (di->key.obj_type != TYPE_ROOT_ITEM) {
4038 ERR("default root has key (%I64x,%x,%I64x), expected subvolume\n", di->key.obj_id, di->key.obj_type, di->key.offset);
4039 goto end;
4040 }
4041
4042 le = Vcb->roots.Flink;
4043 while (le != &Vcb->roots) {
4045
4046 if (r->id == di->key.obj_id)
4047 return r;
4048
4049 le = le->Flink;
4050 }
4051
4052 ERR("could not find root %I64x, using default instead\n", di->key.obj_id);
4053 }
4054
4055end:
4056 le = Vcb->roots.Flink;
4057 while (le != &Vcb->roots) {
4059
4060 if (r->id == BTRFS_ROOT_FSTREE)
4061 return r;
4062
4063 le = le->Flink;
4064 }
4065
4066 return NULL;
4067}
4068
4070 TRACE("(%p, %p)\n", FileObject, ccfs);
4071
4073
4074 if (diskacc)
4076
4078}
4079
4082 uint32_t r = 0;
4083
4084 while (p != 0) {
4085 if (p & 1)
4086 r++;
4087
4088 p >>= 1;
4089 }
4090
4091 return r;
4092}
4093
4095 device_extension* Vcb = DeviceObject->DeviceExtension;
4097 ULONG i;
4098
4099 Vcb->calcthreads.num_threads = get_num_of_processors();
4100
4101 Vcb->calcthreads.threads = ExAllocatePoolWithTag(NonPagedPool, sizeof(drv_calc_thread) * Vcb->calcthreads.num_threads, ALLOC_TAG);
4102 if (!Vcb->calcthreads.threads) {
4103 ERR("out of memory\n");
4105 }
4106
4107 InitializeListHead(&Vcb->calcthreads.job_list);
4108 KeInitializeSpinLock(&Vcb->calcthreads.spinlock);
4109 KeInitializeEvent(&Vcb->calcthreads.event, NotificationEvent, false);
4110
4111 RtlZeroMemory(Vcb->calcthreads.threads, sizeof(drv_calc_thread) * Vcb->calcthreads.num_threads);
4112
4114
4115 for (i = 0; i < Vcb->calcthreads.num_threads; i++) {
4117
4118 Vcb->calcthreads.threads[i].DeviceObject = DeviceObject;
4119 Vcb->calcthreads.threads[i].number = i;
4120 KeInitializeEvent(&Vcb->calcthreads.threads[i].finished, NotificationEvent, false);
4121
4122 Status = PsCreateSystemThread(&Vcb->calcthreads.threads[i].handle, 0, &oa, NULL, NULL, calc_thread, &Vcb->calcthreads.threads[i]);
4123 if (!NT_SUCCESS(Status)) {
4124 ULONG j;
4125
4126 ERR("PsCreateSystemThread returned %08lx\n", Status);
4127
4128 for (j = 0; j < i; j++) {
4129 Vcb->calcthreads.threads[i].quit = true;
4130 }
4131
4132 KeSetEvent(&Vcb->calcthreads.event, 0, false);
4133
4134 return Status;
4135 }
4136 }
4137
4138 return STATUS_SUCCESS;
4139}
4140
4143 MOUNTDEV_NAME mdn, *mdn2;
4144 ULONG mdnsize;
4145
4148 ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
4149 return false;
4150 }
4151
4152 mdnsize = (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
4153
4154 mdn2 = ExAllocatePoolWithTag(PagedPool, mdnsize, ALLOC_TAG);
4155 if (!mdn2) {
4156 ERR("out of memory\n");
4157 return false;
4158 }
4159
4161 if (!NT_SUCCESS(Status)) {
4162 ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
4163 ExFreePool(mdn2);
4164 return false;
4165 }
4166
4167 if (mdn2->NameLength > (sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR)) &&
4168 RtlCompareMemory(mdn2->Name, BTRFS_VOLUME_PREFIX, sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR)) == sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR)) {
4169 ExFreePool(mdn2);
4170 return true;
4171 }
4172
4173 ExFreePool(mdn2);
4174
4175 return false;
4176}
4177
4180 WCHAR *list = NULL, *s;
4181
4183 if (!NT_SUCCESS(Status)) {
4184 ERR("IoGetDeviceInterfaces returned %08lx\n", Status);
4185 return Status;
4186 }
4187
4188 s = list;
4189 while (s[0] != 0) {
4191 PDEVICE_OBJECT devobj;
4193
4194 name.Length = name.MaximumLength = (USHORT)wcslen(s) * sizeof(WCHAR);
4195 name.Buffer = s;
4196
4198 if (DeviceObject == devobj || DeviceObject == FileObject->DeviceObject) {
4200
4201 pnp_name->Buffer = ExAllocatePoolWithTag(PagedPool, name.Length, ALLOC_TAG);
4202 if (!pnp_name->Buffer) {
4203 ERR("out of memory\n");
4205 goto end;
4206 }
4207
4208 RtlCopyMemory(pnp_name->Buffer, name.Buffer, name.Length);
4209 pnp_name->Length = pnp_name->MaximumLength = name.Length;
4210
4212 goto end;
4213 }
4214
4216 }
4217
4218 s = &s[wcslen(s) + 1];
4219 }
4220
4221 pnp_name->Length = pnp_name->MaximumLength = 0;
4222 pnp_name->Buffer = 0;
4223
4225
4226end:
4227 if (list)
4229
4230 return Status;
4231}
4232
4235
4236 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_VOLUME);
4237 if (NT_SUCCESS(Status)) {
4238 *guid = &GUID_DEVINTERFACE_VOLUME;
4239 return Status;
4240 }
4241
4242 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_HIDDEN_VOLUME);
4243 if (NT_SUCCESS(Status)) {
4244 *guid = &GUID_DEVINTERFACE_HIDDEN_VOLUME;
4245 return Status;
4246 }
4247
4248 Status = get_device_pnp_name_guid(DeviceObject, pnp_name, &GUID_DEVINTERFACE_DISK);
4249 if (NT_SUCCESS(Status)) {
4250 *guid = &GUID_DEVINTERFACE_DISK;
4251 return Status;
4252 }
4253
4254 return STATUS_NOT_FOUND;
4255}
4256
4257_Success_(return>=0)
4258static NTSTATUS check_mount_device(_In_ PDEVICE_OBJECT DeviceObject, _Out_ bool* pno_pnp) {
4262 // UNICODE_STRING pnp_name;
4263 // const GUID* guid;
4264
4265 to_read = DeviceObject->SectorSize == 0 ? sizeof(superblock) : (ULONG)sector_align(sizeof(superblock), DeviceObject->SectorSize);
4266
4268 if (!sb) {
4269 ERR("out of memory\n");
4271 }
4272
4275 ERR("sync_read_phys returned %08lx\n", Status);
4276 goto end;
4277 }
4278
4281 goto end;
4282 }
4283
4286 goto end;
4287 }
4288
4289 DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
4290
4291 // pnp_name.Buffer = NULL;
4292
4293 // Status = get_device_pnp_name(DeviceObject, &pnp_name, &guid);
4294 // if (!NT_SUCCESS(Status)) {
4295 // WARN("get_device_pnp_name returned %08lx\n", Status);
4296 // pnp_name.Length = 0;
4297 // }
4298
4299 // *pno_pnp = pnp_name.Length == 0;
4300 *pno_pnp = true;
4301
4302 // if (pnp_name.Buffer)
4303 // ExFreePool(pnp_name.Buffer);
4304
4306
4308 ExFreePool(sb);
4309
4310 return Status;
4311}
4312
4315 ULONG to_read;
4316 superblock* sb;
4317
4318 if (!device)
4319 return false;
4320
4321 to_read = device->SectorSize == 0 ? sizeof(superblock) : (ULONG)sector_align(sizeof(superblock), device->SectorSize);
4322
4324 if (!sb) {
4325 ERR("out of memory\n");
4326 return false;
4327 }
4328
4329 Status = sync_read_phys(device, fileobj, superblock_addrs[0], to_read, (PUCHAR)sb, true);
4330 if (!NT_SUCCESS(Status)) {
4331 ERR("Failed to read superblock: %08lx\n", Status);
4332 ExFreePool(sb);
4333 return false;
4334 }
4335
4336 if (sb->magic != BTRFS_MAGIC) {
4337 TRACE("not a BTRFS volume\n");
4338 ExFreePool(sb);
4339 return false;
4340 } else {
4342 ExFreePool(sb);
4343 return false;
4344 }
4345 }
4346
4348
4349 while (device) {
4351
4352 device->Flags &= ~DO_VERIFY_VOLUME;
4353
4355
4356 device = device2;
4357 }
4358
4359 ExFreePool(sb);
4360
4361 return true;
4362}
4363
4365 uint32_t ss = Vcb->superblock.sector_size;
4366
4367 Vcb->sector_shift = 0;
4368
4369 while (!(ss & 1)) {
4370 Vcb->sector_shift++;
4371 ss >>= 1;
4372 }
4373}
4374
4377 PDEVICE_OBJECT NewDeviceObject = NULL;
4378 PDEVICE_OBJECT DeviceToMount, readobj;
4379 PFILE_OBJECT fileobj;
4382 LIST_ENTRY *le, batchlist;
4383 KEY searchkey;
4385 fcb* root_fcb = NULL;
4386 ccb* root_ccb = NULL;
4387 bool init_lookaside = false;
4388 device* dev;
4390 pdo_device_extension* pdode = NULL;
4391 volume_child* vc;
4392 uint64_t readobjsize;
4394 device_extension* real_devext;
4395 KIRQL irql;
4396
4397 TRACE("(%p, %p)\n", DeviceObject, Irp);
4398
4401
4403 DeviceToMount = IrpSp->Parameters.MountVolume.DeviceObject;
4404
4405 real_devext = IrpSp->Parameters.MountVolume.Vpb->RealDevice->DeviceExtension;
4406
4407 // Make sure we're not trying to mount the PDO
4408 if (IrpSp->Parameters.MountVolume.Vpb->RealDevice->DriverObject == drvobj && real_devext->type == VCB_TYPE_PDO)
4410
4411 if (!is_btrfs_volume(DeviceToMount)) {
4412 bool not_pnp = false;
4413
4414 Status = check_mount_device(DeviceToMount, &not_pnp);
4415 if (!NT_SUCCESS(Status))
4416 WARN("check_mount_device returned %08lx\n", Status);
4417
4418 if (!not_pnp) {
4420 goto exit;
4421 }
4422 } else {
4423 PDEVICE_OBJECT pdo;
4424
4425 pdo = DeviceToMount;
4426
4427 ObReferenceObject(pdo);
4428
4429 while (true) {
4431
4433
4434 if (!pdo2)
4435 break;
4436 else
4437 pdo = pdo2;
4438 }
4439
4441
4442 le = pdo_list.Flink;
4443 while (le != &pdo_list) {
4445
4446 if (pdode2->pdo == pdo) {
4447 vde = pdode2->vde;
4448 break;
4449 }
4450
4451 le = le->Flink;
4452 }
4453
4455
4456 if (!vde || vde->type != VCB_TYPE_VOLUME) {
4457 vde = NULL;
4459 goto exit;
4460 }
4461 }
4462
4463 if (vde) {
4464 pdode = vde->pdode;
4465
4467
4468 le = pdode->children.Flink;
4469 while (le != &pdode->children) {
4470 LIST_ENTRY* le2 = le->Flink;
4471
4473
4474 if (!still_has_superblock(vc->devobj, vc->fileobj)) {
4475 remove_volume_child(vde, vc, false);
4476
4477 if (pdode->num_children == 0) {
4478 ERR("error - number of devices is zero\n");
4481 goto exit;
4482 }
4483
4486 goto exit;
4487 }
4488
4489 le = le2;
4490 }
4491
4492 if (pdode->num_children == 0 || pdode->children_loaded == 0) {
4493 ERR("error - number of devices is zero\n");
4496 goto exit;
4497 }
4498
4500
4502
4503 readobj = vc->devobj;
4504 fileobj = vc->fileobj;
4505 readobjsize = vc->size;
4506
4507 vde->device->Characteristics &= ~FILE_DEVICE_SECURE_OPEN;
4508 } else {
4510
4511 vc = NULL;
4512 readobj = DeviceToMount;
4513 fileobj = NULL;
4514
4516 &gli, sizeof(gli), true, NULL);
4517
4518 if (!NT_SUCCESS(Status)) {
4519 ERR("error reading length information: %08lx\n", Status);
4520 goto exit;
4521 }
4522
4523 readobjsize = gli.Length.QuadPart;
4524 }
4525
4526 Status = IoCreateDevice(drvobj, sizeof(device_extension), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, false, &NewDeviceObject);
4527 if (!NT_SUCCESS(Status)) {
4528 ERR("IoCreateDevice returned %08lx\n", Status);
4530
4531 if (pdode)
4533
4534 goto exit;
4535 }
4536
4537 NewDeviceObject->Flags |= DO_DIRECT_IO;
4538
4539 // Some programs seem to expect that the sector size will be 512, for
4540 // FILE_NO_INTERMEDIATE_BUFFERING and the like.
4541 NewDeviceObject->SectorSize = min(DeviceToMount->SectorSize, 512);
4542
4543 Vcb = (PVOID)NewDeviceObject->DeviceExtension;
4545 Vcb->type = VCB_TYPE_FS;
4546 Vcb->vde = vde;
4547
4548 ExInitializeResourceLite(&Vcb->tree_lock);
4549 Vcb->need_write = false;
4550
4551 ExInitializeResourceLite(&Vcb->fcb_lock);
4552 ExInitializeResourceLite(&Vcb->fileref_lock);
4553 ExInitializeResourceLite(&Vcb->chunk_lock);
4554 ExInitializeResourceLite(&Vcb->dirty_fcbs_lock);
4555 ExInitializeResourceLite(&Vcb->dirty_filerefs_lock);
4556 ExInitializeResourceLite(&Vcb->dirty_subvols_lock);
4557 ExInitializeResourceLite(&Vcb->scrub.stats_lock);
4558
4559 ExInitializeResourceLite(&Vcb->load_lock);
4560 ExAcquireResourceExclusiveLite(&Vcb->load_lock, true);
4561
4562 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
4563
4564 DeviceToMount->Flags |= DO_DIRECT_IO;
4565
4566 Status = read_superblock(Vcb, readobj, fileobj, readobjsize);
4567 if (!NT_SUCCESS(Status)) {
4570 else if (Irp->Tail.Overlay.Thread)
4572
4573 if (pdode)
4575
4576 goto exit;
4577 }
4578
4579 if (!vde && Vcb->superblock.num_devices > 1) {
4580 ERR("cannot mount multi-device FS with non-PNP device\n");
4582
4583 if (pdode)
4585
4586 goto exit;
4587 }
4588
4590 if (!NT_SUCCESS(Status)) {
4591 ERR("registry_load_volume_options returned %08lx\n", Status);
4592
4593 if (pdode)
4595
4596 goto exit;
4597 }
4598
4599 if (pdode && RtlCompareMemory(&boot_uuid, &pdode->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID) && boot_subvol != 0)
4600 Vcb->options.subvol_id = boot_subvol;
4601
4602 if (pdode && pdode->children_loaded < pdode->num_children && (!Vcb->options.allow_degraded || !finished_probing || degraded_wait)) {
4603 ERR("could not mount as %I64u device(s) missing\n", pdode->num_children - pdode->children_loaded);
4606 goto exit;
4607 }
4608
4609 if (pdode) {
4610 // Windows holds DeviceObject->DeviceLock, guaranteeing that mount_vol is serialized
4612 }
4613
4614 if (Vcb->options.ignore) {
4615 TRACE("ignoring volume\n");
4617 goto exit;
4618 }
4619
4620 if (Vcb->superblock.incompat_flags & ~INCOMPAT_SUPPORTED) {
4621 WARN("cannot mount because of unsupported incompat flags (%I64x)\n", Vcb->superblock.incompat_flags & ~INCOMPAT_SUPPORTED);
4623 goto exit;
4624 }
4625
4626 if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_METADATA_UUID))
4627 Vcb->superblock.metadata_uuid = Vcb->superblock.uuid;
4628
4629 Vcb->readonly = false;
4630 if (Vcb->superblock.compat_ro_flags & ~COMPAT_RO_SUPPORTED) {
4631 WARN("mounting read-only because of unsupported flags (%I64x)\n", Vcb->superblock.compat_ro_flags & ~COMPAT_RO_SUPPORTED);
4632 Vcb->readonly = true;
4633 }
4634
4635 if (Vcb->options.readonly)
4636 Vcb->readonly = true;
4637
4639
4640 Vcb->superblock.generation++;
4641 Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF;
4642
4643 if (Vcb->superblock.log_tree_addr != 0) {
4644 FIXME("FIXME - replay transaction log (clearing for now)\n");
4645 Vcb->superblock.log_tree_addr = 0;
4646 }
4647
4648 switch (Vcb->superblock.csum_type) {
4649 case CSUM_TYPE_CRC32C:
4650 Vcb->csum_size = sizeof(uint32_t);
4651 break;
4652
4653 case CSUM_TYPE_XXHASH:
4654 Vcb->csum_size = sizeof(uint64_t);
4655 break;
4656
4657 case CSUM_TYPE_SHA256:
4658 Vcb->csum_size = SHA256_HASH_SIZE;
4659 break;
4660
4661 case CSUM_TYPE_BLAKE2:
4662 Vcb->csum_size = BLAKE2_HASH_SIZE;
4663 break;
4664
4665 default:
4666 ERR("unrecognized csum type %x\n", Vcb->superblock.csum_type);
4667 break;
4668 }
4669
4670 InitializeListHead(&Vcb->devices);
4672 if (!dev) {
4673 ERR("out of memory\n");
4675 goto exit;
4676 }
4677
4678 dev->devobj = readobj;
4679 dev->fileobj = fileobj;
4680 RtlCopyMemory(&dev->devitem, &Vcb->superblock.dev_item, sizeof(DEV_ITEM));
4681
4682 if (dev->devitem.num_bytes > readobjsize) {
4683 WARN("device %I64x: DEV_ITEM says %I64x bytes, but Windows only reports %I64x\n", dev->devitem.dev_id,
4684 dev->devitem.num_bytes, readobjsize);
4685
4686 dev->devitem.num_bytes = readobjsize;
4687 }
4688
4689 dev->seeding = Vcb->superblock.flags & BTRFS_SUPERBLOCK_FLAGS_SEEDING ? true : false;
4690
4691 init_device(Vcb, dev, true);
4692
4693 InsertTailList(&Vcb->devices, &dev->list_entry);
4694 Vcb->devices_loaded = 1;
4695
4696 if (DeviceToMount->Flags & DO_SYSTEM_BOOT_PARTITION)
4697 Vcb->disallow_dismount = true;
4698
4699 TRACE("DeviceToMount = %p\n", DeviceToMount);
4700 TRACE("IrpSp->Parameters.MountVolume.Vpb = %p\n", IrpSp->Parameters.MountVolume.Vpb);
4701
4702 NewDeviceObject->StackSize = DeviceToMount->StackSize + 1;
4703 NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4704
4705 InitializeListHead(&Vcb->roots);
4706 InitializeListHead(&Vcb->drop_roots);
4707
4708 Vcb->log_to_phys_loaded = false;
4709
4710 add_root(Vcb, BTRFS_ROOT_CHUNK, Vcb->superblock.chunk_tree_addr, Vcb->superblock.chunk_root_generation, NULL);
4711
4712 if (!Vcb->chunk_root) {
4713 ERR("Could not load chunk root.\n");
4715 goto exit;
4716 }
4717
4718 InitializeListHead(&Vcb->sys_chunks);
4720 if (!NT_SUCCESS(Status)) {
4721 ERR("load_sys_chunks returned %08lx\n", Status);
4722 goto exit;
4723 }
4724
4725 InitializeListHead(&Vcb->chunks);
4726 InitializeListHead(&Vcb->trees);
4727 InitializeListHead(&Vcb->trees_hash);
4728 InitializeListHead(&Vcb->all_fcbs);
4729 InitializeListHead(&Vcb->dirty_fcbs);
4730 InitializeListHead(&Vcb->dirty_filerefs);
4731 InitializeListHead(&Vcb->dirty_subvols);
4732 InitializeListHead(&Vcb->send_ops);
4733
4734 ExInitializeFastMutex(&Vcb->trees_list_mutex);
4735
4736 InitializeListHead(&Vcb->DirNotifyList);
4737 InitializeListHead(&Vcb->scrub.errors);
4738
4739 FsRtlNotifyInitializeSync(&Vcb->NotifySync);
4740
4741 ExInitializePagedLookasideList(&Vcb->tree_data_lookaside, NULL, NULL, 0, sizeof(tree_data), ALLOC_TAG, 0);
4742 ExInitializePagedLookasideList(&Vcb->traverse_ptr_lookaside, NULL, NULL, 0, sizeof(traverse_ptr), ALLOC_TAG, 0);
4743 ExInitializePagedLookasideList(&Vcb->batch_item_lookaside, NULL, NULL, 0, sizeof(batch_item), ALLOC_TAG, 0);
4744 ExInitializePagedLookasideList(&Vcb->fileref_lookaside, NULL, NULL, 0, sizeof(file_ref), ALLOC_TAG, 0);
4745 ExInitializePagedLookasideList(&Vcb->fcb_lookaside, NULL, NULL, 0, sizeof(fcb), ALLOC_TAG, 0);
4746 ExInitializePagedLookasideList(&Vcb->name_bit_lookaside, NULL, NULL, 0, sizeof(name_bit), ALLOC_TAG, 0);
4747 ExInitializeNPagedLookasideList(&Vcb->range_lock_lookaside, NULL, NULL, 0, sizeof(range_lock), ALLOC_TAG, 0);
4748 ExInitializeNPagedLookasideList(&Vcb->fcb_np_lookaside, NULL, NULL, 0, sizeof(fcb_nonpaged), ALLOC_TAG, 0);
4749 init_lookaside = true;
4750
4751 Vcb->Vpb = IrpSp->Parameters.MountVolume.Vpb;
4752
4754 if (!NT_SUCCESS(Status)) {
4755 ERR("load_chunk_root returned %08lx\n", Status);
4756 goto exit;
4757 }
4758
4759 if (Vcb->superblock.num_devices > 1) {
4760 if (Vcb->devices_loaded < Vcb->superblock.num_devices && (!Vcb->options.allow_degraded || !finished_probing)) {
4761 ERR("could not mount as %I64u device(s) missing\n", Vcb->superblock.num_devices - Vcb->devices_loaded);
4762
4764
4766 goto exit;
4767 }
4768
4769 if (dev->readonly && !Vcb->readonly) {
4770 Vcb->readonly = true;
4771
4772 le = Vcb->devices.Flink;
4773 while (le != &Vcb->devices) {
4775
4776 if (dev2->readonly && !dev2->seeding)
4777 break;
4778
4779 if (!dev2->readonly) {
4780 Vcb->readonly = false;
4781 break;
4782 }
4783
4784 le = le->Flink;
4785 }
4786
4787 if (Vcb->readonly)
4788 WARN("setting volume to readonly\n");
4789 }
4790 } else {
4791 if (dev->readonly) {
4792 WARN("setting volume to readonly as device is readonly\n");
4793 Vcb->readonly = true;
4794 }
4795 }
4796
4797 add_root(Vcb, BTRFS_ROOT_ROOT, Vcb->superblock.root_tree_addr, Vcb->superblock.generation - 1, NULL);
4798
4799 if (!Vcb->root_root) {
4800 ERR("Could not load root of roots.\n");
4802 goto exit;
4803 }
4804
4806 if (!NT_SUCCESS(Status)) {
4807 ERR("look_for_roots returned %08lx\n", Status);
4808 goto exit;
4809 }
4810
4811 if (!Vcb->readonly) {
4813 if (!NT_SUCCESS(Status)) {
4814 ERR("find_chunk_usage returned %08lx\n", Status);
4815 goto exit;
4816 }
4817 }
4818
4819 InitializeListHead(&batchlist);
4820
4821 // We've already increased the generation by one
4822 if (!Vcb->readonly && (
4823 Vcb->options.clear_cache ||
4824 (!(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE) && Vcb->superblock.generation - 1 != Vcb->superblock.cache_generation) ||
4825 (Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE && !(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID)))) {
4826 if (Vcb->options.clear_cache)
4827 WARN("ClearCache option was set, clearing cache...\n");
4828 else if (Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE && !(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID))
4829 WARN("clearing free-space tree created by buggy Linux driver\n");
4830 else
4831 WARN("generation was %I64x, free-space cache generation was %I64x; clearing cache...\n", Vcb->superblock.generation - 1, Vcb->superblock.cache_generation);
4832
4833 Status = clear_free_space_cache(Vcb, &batchlist, Irp);
4834 if (!NT_SUCCESS(Status)) {
4835 ERR("clear_free_space_cache returned %08lx\n", Status);
4836 clear_batch_list(Vcb, &batchlist);
4837 goto exit;
4838 }
4839 }
4840
4841 Status = commit_batch_list(Vcb, &batchlist, Irp);
4842 if (!NT_SUCCESS(Status)) {
4843 ERR("commit_batch_list returned %08lx\n", Status);
4844 goto exit;
4845 }
4846
4847 Vcb->volume_fcb = create_fcb(Vcb, NonPagedPool);
4848 if (!Vcb->volume_fcb) {
4849 ERR("out of memory\n");
4851 goto exit;
4852 }
4853
4854 Vcb->volume_fcb->Vcb = Vcb;
4855 Vcb->volume_fcb->sd = NULL;
4856
4857 Vcb->dummy_fcb = create_fcb(Vcb, NonPagedPool);
4858 if (!Vcb->dummy_fcb) {
4859 ERR("out of memory\n");
4861 goto exit;
4862 }
4863
4864 Vcb->dummy_fcb->Vcb = Vcb;
4865 Vcb->dummy_fcb->type = BTRFS_TYPE_DIRECTORY;
4866 Vcb->dummy_fcb->inode = 2;
4867 Vcb->dummy_fcb->subvol = Vcb->root_root;
4868 Vcb->dummy_fcb->atts = FILE_ATTRIBUTE_DIRECTORY;
4869 Vcb->dummy_fcb->inode_item.st_nlink = 1;
4870 Vcb->dummy_fcb->inode_item.st_mode = __S_IFDIR;
4871
4872 Vcb->dummy_fcb->hash_ptrs = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
4873 if (!Vcb->dummy_fcb->hash_ptrs) {
4874 ERR("out of memory\n");
4876 goto exit;
4877 }
4878
4879 RtlZeroMemory(Vcb->dummy_fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
4880
4881 Vcb->dummy_fcb->hash_ptrs_uc = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
4882 if (!Vcb->dummy_fcb->hash_ptrs_uc) {
4883 ERR("out of memory\n");
4885 goto exit;
4886 }
4887
4888 RtlZeroMemory(Vcb->dummy_fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
4889
4890 root_fcb = create_fcb(Vcb, NonPagedPool);
4891 if (!root_fcb) {
4892 ERR("out of memory\n");
4894 goto exit;
4895 }
4896
4897 root_fcb->Vcb = Vcb;
4898 root_fcb->inode = SUBVOL_ROOT_INODE;
4899 root_fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&root_fcb->inode, sizeof(uint64_t));
4900 root_fcb->type = BTRFS_TYPE_DIRECTORY;
4901
4902#ifdef DEBUG_FCB_REFCOUNTS
4903 WARN("volume FCB = %p\n", Vcb->volume_fcb);
4904 WARN("root FCB = %p\n", root_fcb);
4905#endif
4906
4907 root_fcb->subvol = find_default_subvol(Vcb, Irp);
4908
4909 if (!root_fcb->subvol) {
4910 ERR("could not find top subvol\n");
4912 goto exit;
4913 }
4914
4915 Status = load_dir_children(Vcb, root_fcb, true, Irp);
4916 if (!NT_SUCCESS(Status)) {
4917 ERR("load_dir_children returned %08lx\n", Status);
4918 goto exit;
4919 }
4920
4921 searchkey.obj_id = root_fcb->inode;
4922 searchkey.obj_type = TYPE_INODE_ITEM;
4923 searchkey.offset = 0xffffffffffffffff;
4924
4925 Status = find_item(Vcb, root_fcb->subvol, &tp, &searchkey, false, Irp);
4926 if (!NT_SUCCESS(Status)) {
4927 ERR("error - find_item returned %08lx\n", Status);
4928 goto exit;
4929 }
4930
4931 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
4932 ERR("couldn't find INODE_ITEM for root directory\n");
4934 goto exit;
4935 }
4936
4937 if (tp.item->size > 0)
4938 RtlCopyMemory(&root_fcb->inode_item, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size));
4939
4940 fcb_get_sd(root_fcb, NULL, true, Irp);
4941
4942 root_fcb->atts = get_file_attributes(Vcb, root_fcb->subvol, root_fcb->inode, root_fcb->type, false, false, Irp);
4943
4944 if (root_fcb->subvol->id == BTRFS_ROOT_FSTREE)
4945 root_fcb->atts &= ~FILE_ATTRIBUTE_HIDDEN;
4946
4947 Vcb->root_fileref = create_fileref(Vcb);
4948 if (!Vcb->root_fileref) {
4949 ERR("out of memory\n");
4951 goto exit;
4952 }
4953
4954 Vcb->root_fileref->fcb = root_fcb;
4955 InsertTailList(&root_fcb->subvol->fcbs, &root_fcb->list_entry);
4956 InsertTailList(&Vcb->all_fcbs, &root_fcb->list_entry_all);
4957
4958 root_fcb->subvol->fcbs_ptrs[root_fcb->hash >> 24] = &root_fcb->list_entry;
4959
4960 root_fcb->fileref = Vcb->root_fileref;
4961
4962 root_ccb = ExAllocatePoolWithTag(PagedPool, sizeof(ccb), ALLOC_TAG);
4963 if (!root_ccb) {
4964 ERR("out of memory\n");
4966 goto exit;
4967 }
4968
4969 Vcb->root_file = IoCreateStreamFileObject(NULL, DeviceToMount);
4970 Vcb->root_file->FsContext = root_fcb;
4971 Vcb->root_file->SectionObjectPointer = &root_fcb->nonpaged->segment_object;
4972 Vcb->root_file->Vpb = DeviceObject->Vpb;
4973
4974 RtlZeroMemory(root_ccb, sizeof(ccb));
4975 root_ccb->NodeType = BTRFS_NODE_TYPE_CCB;
4976 root_ccb->NodeSize = sizeof(ccb);
4977
4978 Vcb->root_file->FsContext2 = root_ccb;
4979
4980 _SEH2_TRY {
4981 CcInitializeCacheMap(Vcb->root_file, (PCC_FILE_SIZES)(&root_fcb->Header.AllocationSize), false, &cache_callbacks, Vcb->root_file);
4984 goto exit;
4985 } _SEH2_END;
4986
4987 le = Vcb->devices.Flink;
4988 while (le != &Vcb->devices) {
4990
4991 Status = find_disk_holes(Vcb, dev2, Irp);
4992 if (!NT_SUCCESS(Status)) {
4993 ERR("find_disk_holes returned %08lx\n", Status);
4994 goto exit;
4995 }
4996
4997 le = le->Flink;
4998 }
4999
5001
5002 NewDeviceObject->Vpb = IrpSp->Parameters.MountVolume.Vpb;
5003 IrpSp->Parameters.MountVolume.Vpb->DeviceObject = NewDeviceObject;
5004 IrpSp->Parameters.MountVolume.Vpb->Flags |= VPB_MOUNTED;
5005 NewDeviceObject->Vpb->VolumeLabelLength = 4; // FIXME
5006 NewDeviceObject->Vpb->VolumeLabel[0] = '?';
5007 NewDeviceObject->Vpb->VolumeLabel[1] = 0;
5008 NewDeviceObject->Vpb->ReferenceCount++;
5009
5011
5012 KeInitializeEvent(&Vcb->flush_thread_finished, NotificationEvent, false);
5013
5015
5016 Status = PsCreateSystemThread(&Vcb->flush_thread_handle, 0, &oa, NULL, NULL, flush_thread, NewDeviceObject);
5017 if (!NT_SUCCESS(Status)) {
5018 ERR("PsCreateSystemThread returned %08lx\n", Status);
5019 goto exit;
5020 }
5021
5022 Status = create_calc_threads(NewDeviceObject);
5023 if (!NT_SUCCESS(Status)) {
5024 ERR("create_calc_threads returned %08lx\n", Status);
5025 goto exit;
5026 }
5027
5028 Status = registry_mark_volume_mounted(&Vcb->superblock.uuid);
5029 if (!NT_SUCCESS(Status))
5030 WARN("registry_mark_volume_mounted returned %08lx\n", Status);
5031
5034 WARN("look_for_balance_item returned %08lx\n", Status);
5035
5037
5038 if (vde)
5039 vde->mounted_device = NewDeviceObject;
5040
5041 Vcb->devobj = NewDeviceObject;
5042
5043 ExInitializeResourceLite(&Vcb->send_load_lock);
5044
5045exit:
5046 if (Vcb) {
5047 ExReleaseResourceLite(&Vcb->tree_lock);
5048 ExReleaseResourceLite(&Vcb->load_lock);
5049 }
5050
5051 if (!NT_SUCCESS(Status)) {
5052 if (Vcb) {
5053 if (init_lookaside) {
5054 ExDeletePagedLookasideList(&Vcb->tree_data_lookaside);
5055 ExDeletePagedLookasideList(&Vcb->traverse_ptr_lookaside);
5056 ExDeletePagedLookasideList(&Vcb->batch_item_lookaside);
5057 ExDeletePagedLookasideList(&Vcb->fileref_lookaside);
5058 ExDeletePagedLookasideList(&Vcb->fcb_lookaside);
5059 ExDeletePagedLookasideList(&Vcb->name_bit_lookaside);
5060 ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside);
5061 ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside);
5062 }
5063
5064 if (Vcb->root_file)
5065 ObDereferenceObject(Vcb->root_file);
5066 else if (Vcb->root_fileref)
5067 free_fileref(Vcb->root_fileref);
5068 else if (root_fcb)
5069 free_fcb(root_fcb);
5070
5071 if (root_fcb && root_fcb->refcount == 0)
5072 reap_fcb(root_fcb);
5073
5074 if (Vcb->volume_fcb)
5075 reap_fcb(Vcb->volume_fcb);
5076
5077 ExDeleteResourceLite(&Vcb->tree_lock);
5078 ExDeleteResourceLite(&Vcb->load_lock);
5079 ExDeleteResourceLite(&Vcb->fcb_lock);
5080 ExDeleteResourceLite(&Vcb->fileref_lock);
5081 ExDeleteResourceLite(&Vcb->chunk_lock);
5082 ExDeleteResourceLite(&Vcb->dirty_fcbs_lock);
5083 ExDeleteResourceLite(&Vcb->dirty_filerefs_lock);
5084 ExDeleteResourceLite(&Vcb->dirty_subvols_lock);
5085 ExDeleteResourceLite(&Vcb->scrub.stats_lock);
5086
5087 if (Vcb->devices.Flink) {
5088 while (!IsListEmpty(&Vcb->devices)) {
5090
5091 ExFreePool(dev2);
5092 }
5093 }
5094 }
5095
5096 if (NewDeviceObject)
5097 IoDeleteDevice(NewDeviceObject);
5098 } else {
5100 InsertTailList(&VcbList, &Vcb->list_entry);
5102
5104 }
5105
5106 TRACE("mount_vol done (status: %lx)\n", Status);
5107
5108 return Status;
5109}
5110
5113 superblock* sb;
5114 ULONG to_read, cc;
5115
5116 if (!dev->devobj)
5117 return STATUS_WRONG_VOLUME;
5118
5119 if (dev->removable) {
5121
5122 Status = dev_ioctl(dev->devobj, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), true, &iosb);
5123
5125 ERR("IOCTL_STORAGE_CHECK_VERIFY returned %08lx (user-induced)\n", Status);
5126
5127 if (Vcb->vde) {
5128 pdo_device_extension* pdode = Vcb->vde->pdode;
5129 LIST_ENTRY* le2;
5130 bool changed = false;
5131
5133
5134 le2 = pdode->children.Flink;
5135 while (le2 != &pdode->children) {
5137
5138 if (vc->devobj == dev->devobj) {
5139 TRACE("removing device\n");
5140
5141 remove_volume_child(Vcb->vde, vc, true);
5142 changed = true;
5143
5144 break;
5145 }
5146
5147 le2 = le2->Flink;
5148 }
5149
5150 if (!changed)
5152 }
5153 } else if (!NT_SUCCESS(Status)) {
5154 ERR("IOCTL_STORAGE_CHECK_VERIFY returned %08lx\n", Status);
5155 return Status;
5156 } else if (iosb.Information < sizeof(ULONG)) {
5157 ERR("iosb.Information was too short\n");
5158 return STATUS_INTERNAL_ERROR;
5159 }
5160
5161 dev->change_count = cc;
5162 }
5163
5164 to_read = dev->devobj->SectorSize == 0 ? sizeof(superblock) : (ULONG)sector_align(sizeof(superblock), dev->devobj->SectorSize);
5165
5167 if (!sb) {
5168 ERR("out of memory\n");
5170 }
5171
5172 Status = sync_read_phys(dev->devobj, dev->fileobj, superblock_addrs[0], to_read, (PUCHAR)sb, true);
5173 if (!NT_SUCCESS(Status)) {
5174 ERR("Failed to read superblock: %08lx\n", Status);
5175 ExFreePool(sb);
5176 return Status;
5177 }
5178
5179 if (sb->magic != BTRFS_MAGIC) {
5180 ERR("not a BTRFS volume\n");
5181 ExFreePool(sb);
5182 return STATUS_WRONG_VOLUME;
5183 }
5184
5186 ExFreePool(sb);
5187 return STATUS_WRONG_VOLUME;
5188 }
5189
5190 if (RtlCompareMemory(&sb->uuid, &Vcb->superblock.uuid, sizeof(BTRFS_UUID)) != sizeof(BTRFS_UUID)) {
5191 ERR("different UUIDs\n");
5192 ExFreePool(sb);
5193 return STATUS_WRONG_VOLUME;
5194 }
5195
5196 ExFreePool(sb);
5197
5198 dev->devobj->Flags &= ~DO_VERIFY_VOLUME;
5199
5200 return STATUS_SUCCESS;
5201}
5202
5204 device_extension* Vcb = devobj->DeviceExtension;
5206 LIST_ENTRY* le;
5207 uint64_t failed_devices = 0;
5208 bool locked = false, remove = false;
5209
5210 if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
5211 return STATUS_WRONG_VOLUME;
5212
5213 if (!ExIsResourceAcquiredExclusive(&Vcb->tree_lock)) {
5214 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
5215 locked = true;
5216 }
5217
5218 if (Vcb->removing) {
5219 if (locked) ExReleaseResourceLite(&Vcb->tree_lock);
5220 return STATUS_WRONG_VOLUME;
5221 }
5222
5224
5225 InterlockedIncrement(&Vcb->open_files); // so pnp_surprise_removal doesn't uninit the device while we're still using it
5226
5227 le = Vcb->devices.Flink;
5228 while (le != &Vcb->devices) {
5230
5232 if (!NT_SUCCESS(Status)) {
5233 failed_devices++;
5234
5235 if (dev->devobj && Vcb->options.allow_degraded)
5236 dev->devobj = NULL;
5237 }
5238
5239 le = le->Flink;
5240 }
5241
5242 InterlockedDecrement(&Vcb->open_files);
5243
5244 if (Vcb->removing && Vcb->open_files == 0)
5245 remove = true;
5246
5247 if (locked)
5248 ExReleaseResourceLite(&Vcb->tree_lock);
5249
5250 if (remove) {
5251 uninit(Vcb);
5252 return Status;
5253 }
5254
5255 if (failed_devices == 0 || (Vcb->options.allow_degraded && failed_devices < Vcb->superblock.num_devices)) {
5256 Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
5257
5258 return STATUS_SUCCESS;
5259 }
5260
5261 return Status;
5262}
5263
5266static NTSTATUS __stdcall drv_file_system_control(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
5269 device_extension* Vcb = DeviceObject->DeviceExtension;
5270 bool top_level;
5271
5273
5274 TRACE("file system control\n");
5275
5276 top_level = is_top_level(Irp);
5277
5278 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5280 goto end;
5281 } else if (!Vcb || (Vcb->type != VCB_TYPE_FS && Vcb->type != VCB_TYPE_CONTROL)) {
5283 goto end;
5284 }
5285
5287
5289
5290 Irp->IoStatus.Information = 0;
5291
5292 switch (IrpSp->MinorFunction) {
5294 TRACE("IRP_MN_MOUNT_VOLUME\n");
5295
5297 break;
5298
5299 case IRP_MN_KERNEL_CALL:
5300 TRACE("IRP_MN_KERNEL_CALL\n");
5301
5303 break;
5304
5306 TRACE("IRP_MN_USER_FS_REQUEST\n");
5307
5309 break;
5310
5312 TRACE("IRP_MN_VERIFY_VOLUME\n");
5313
5315
5316 if (!NT_SUCCESS(Status) && Vcb->Vpb->Flags & VPB_MOUNTED) {
5317 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
5318 Vcb->removing = true;
5319 ExReleaseResourceLite(&Vcb->tree_lock);
5320 }
5321
5322 break;
5323
5324 default:
5325 break;
5326 }
5327
5328end:
5329 TRACE("returning %08lx\n", Status);
5330
5331 if (Irp) {
5332 Irp->IoStatus.Status = Status;
5333
5335 }
5336
5337 if (top_level)
5339
5341
5342 return Status;
5343}
5344
5347static NTSTATUS __stdcall drv_lock_control(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
5350 fcb* fcb = IrpSp->FileObject ? IrpSp->FileObject->FsContext : NULL;
5351 device_extension* Vcb = DeviceObject->DeviceExtension;
5352 bool top_level;
5353
5355
5356 top_level = is_top_level(Irp);
5357
5358 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5360
5361 Irp->IoStatus.Status = Status;
5363
5364 goto exit;
5365 }
5366
5367 TRACE("lock control\n");
5368
5369 if (!fcb) {
5370 ERR("fcb was NULL\n");
5372 goto exit;
5373 }
5374
5376
5378
5379 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
5380
5381exit:
5382 TRACE("returning %08lx\n", Status);
5383
5384 if (top_level)
5386
5388
5389 return Status;
5390}
5391
5393 LIST_ENTRY* le;
5395
5396 shutting_down = true;
5398
5399 le = VcbList.Flink;
5400 while (le != &VcbList) {
5401 LIST_ENTRY* le2 = le->Flink;
5402
5404 volume_device_extension* vde = Vcb->vde;
5405 PDEVICE_OBJECT devobj = vde ? vde->device : NULL;
5406
5407 TRACE("shutting down Vcb %p\n", Vcb);
5408
5409 if (vde)
5411
5412 if (devobj)
5413 ObReferenceObject(devobj);
5414
5415 dismount_volume(Vcb, true, Irp);
5416
5417 if (vde) {
5419 UNICODE_STRING mmdevpath;
5421 PFILE_OBJECT mountmgrfo;
5422 KIRQL irql;
5423 PVPB newvpb;
5424
5426 Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
5427 if (!NT_SUCCESS(Status))
5428 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
5429 else {
5431
5432 ObDereferenceObject(mountmgrfo);
5433 }
5434
5435 vde->removing = true;
5436
5437 newvpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), ALLOC_TAG);
5438 if (!newvpb) {
5439 ERR("out of memory\n");
5440 return;
5441 }
5442
5443 RtlZeroMemory(newvpb, sizeof(VPB));
5444
5445 newvpb->Type = IO_TYPE_VPB;
5446 newvpb->Size = sizeof(VPB);
5447 newvpb->RealDevice = newvpb->DeviceObject = vde->device;
5449
5451 vde->device->Vpb = newvpb;
5453
5454 if (InterlockedDecrement(&vde->open_count) == 0)
5455 free_vol(vde);
5456 }
5457
5458 if (devobj)
5459 ObDereferenceObject(devobj);
5460
5461 le = le2;
5462 }
5463
5464#ifdef _DEBUG
5465 if (comfo) {
5466 ObDereferenceObject(comfo);
5467 comdo = NULL;
5468 comfo = NULL;
5469 }
5470#endif
5471
5473
5474 if (notification_entry2) {
5477 else
5479
5481 }
5482
5483 if (notification_entry3) {
5486 else
5488
5490 }
5491
5492 if (notification_entry) {
5495 else
5497
5499 }
5500
5501 bde = busobj->DeviceExtension;
5502
5503 if (bde->attached_device)
5505
5508}
5509
5514 bool top_level;
5515 device_extension* Vcb = DeviceObject->DeviceExtension;
5516
5518
5519 TRACE("shutdown\n");
5520
5521 top_level = is_top_level(Irp);
5522
5523 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5525 goto end;
5526 }
5527
5529
5531
5532end:
5533 Irp->IoStatus.Status = Status;
5534 Irp->IoStatus.Information = 0;
5535
5537
5538 if (top_level)
5540
5542
5543 return Status;
5544}
5545
5546static bool device_still_valid(device* dev, uint64_t expected_generation) {
5548 unsigned int to_read;
5549 superblock* sb;
5550
5551 to_read = (unsigned int)(dev->devobj->SectorSize == 0 ? sizeof(superblock) : sector_align(sizeof(superblock), dev->devobj->SectorSize));
5552
5554 if (!sb) {
5555 ERR("out of memory\n");
5556 return false;
5557 }
5558
5559 Status = sync_read_phys(dev->devobj, dev->fileobj, superblock_addrs[0], to_read, (PUCHAR)sb, false);
5560 if (!NT_SUCCESS(Status)) {
5561 ERR("sync_read_phys returned %08lx\n", Status);
5562 ExFreePool(sb);
5563 return false;
5564 }
5565
5566 if (sb->magic != BTRFS_MAGIC) {
5567 ERR("magic not found\n");
5568 ExFreePool(sb);
5569 return false;
5570 }
5571
5573 ExFreePool(sb);
5574 return false;
5575 }
5576
5577 if (sb->generation > expected_generation) {
5578 ERR("generation was %I64x, expected %I64x\n", sb->generation, expected_generation);
5579 ExFreePool(sb);
5580 return false;
5581 }
5582
5583 ExFreePool(sb);
5584
5585 return true;
5586}
5587
5588_Function_class_(IO_WORKITEM_ROUTINE)
5589static void __stdcall check_after_wakeup(PDEVICE_OBJECT DeviceObject, PVOID con) {
5591 LIST_ENTRY* le;
5592
5594
5595 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
5596
5597 le = Vcb->devices.Flink;
5598
5599 // FIXME - do reads in parallel?
5600
5601 while (le != &Vcb->devices) {
5603
5604 if (dev->devobj) {
5605 if (!device_still_valid(dev, Vcb->superblock.generation - 1)) {
5606 PDEVICE_OBJECT voldev = Vcb->Vpb->RealDevice;
5607 KIRQL irql;
5608 PVPB newvpb;
5609
5610 WARN("forcing remount\n");
5611
5612 newvpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), ALLOC_TAG);
5613 if (!newvpb) {
5614 ERR("out of memory\n");
5615 return;
5616 }
5617
5618 RtlZeroMemory(newvpb, sizeof(VPB));
5619
5620 newvpb->Type = IO_TYPE_VPB;
5621 newvpb->Size = sizeof(VPB);
5622 newvpb->RealDevice = voldev;
5624
5625 Vcb->removing = true;
5626
5628 voldev->Vpb = newvpb;
5630
5631 Vcb->vde = NULL;
5632
5633 ExReleaseResourceLite(&Vcb->tree_lock);
5634
5635 if (Vcb->open_files == 0)
5636 uninit(Vcb);
5637 else { // remove from VcbList
5639 RemoveEntryList(&Vcb->list_entry);
5640 Vcb->list_entry.Flink = NULL;
5642 }
5643
5644 return;
5645 }
5646 }
5647
5648 le = le->Flink;
5649 }
5650
5651 ExReleaseResourceLite(&Vcb->tree_lock);
5652}
5653
5659 device_extension* Vcb = DeviceObject->DeviceExtension;
5660 bool top_level;
5661
5662 // no need for FsRtlEnterFileSystem, as this only ever gets called in a system thread
5663
5664 top_level = is_top_level(Irp);
5665
5666 Irp->IoStatus.Information = 0;
5667
5668 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5669 volume_device_extension* vde = DeviceObject->DeviceExtension;
5670
5672 IrpSp->Parameters.Power.State.SystemState != PowerSystemWorking && vde->mounted_device) {
5674
5675 /* If power state is about to go to sleep or hibernate, do a flush. We do this on IRP_MJ_QUERY_POWER
5676 * rather than IRP_MJ_SET_POWER because we know that the hard disks are still awake. */
5677
5678 if (Vcb2) {
5679 ExAcquireResourceExclusiveLite(&Vcb2->tree_lock, true);
5680
5681 if (Vcb2->need_write && !Vcb2->readonly) {
5682 TRACE("doing protective flush on power state change\n");
5683 Status = do_write(Vcb2, NULL);
5684 } else
5686
5687 free_trees(Vcb2);
5688
5689 if (!NT_SUCCESS(Status))
5690 ERR("do_write returned %08lx\n", Status);
5691
5692 ExReleaseResourceLite(&Vcb2->tree_lock);
5693 }
5695 IrpSp->Parameters.Power.State.SystemState == PowerSystemWorking && vde->mounted_device) {
5697
5698 /* If waking up, make sure that the FS hasn't been changed while we've been out (e.g., by dual-boot Linux) */
5699
5700 if (Vcb2) {
5701 PIO_WORKITEM work_item;
5702
5703 work_item = IoAllocateWorkItem(DeviceObject);
5704 if (!work_item) {
5705 ERR("out of memory\n");
5706 } else
5707 IoQueueWorkItem(work_item, check_after_wakeup, DelayedWorkQueue, Vcb2);
5708 }
5709 }
5710
5713 Status = PoCallDriver(vde->attached_device, Irp);
5714
5715 goto exit;
5716 } else if (Vcb && Vcb->type == VCB_TYPE_FS) {
5718
5719 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
5720
5721 goto exit;
5722 } else if (Vcb && Vcb->type == VCB_TYPE_BUS) {
5723 bus_device_extension* bde = DeviceObject->DeviceExtension;
5724
5727 Status = PoCallDriver(bde->attached_device, Irp);
5728
5729 goto exit;
5730 }
5731
5733 Irp->IoStatus.Status = STATUS_SUCCESS;
5734
5735 Status = Irp->IoStatus.Status;
5736
5738
5740
5741exit:
5742 if (top_level)
5744
5745 return Status;
5746}
5747
5750static NTSTATUS __stdcall drv_system_control(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
5752 device_extension* Vcb = DeviceObject->DeviceExtension;
5753 bool top_level;
5754
5756
5757 top_level = is_top_level(Irp);
5758
5759 Irp->IoStatus.Information = 0;
5760
5761 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
5762 volume_device_extension* vde = DeviceObject->DeviceExtension;
5763
5765
5767
5768 goto exit;
5769 } else if (Vcb && Vcb->type == VCB_TYPE_FS) {
5771
5772 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
5773
5774 goto exit;
5775 } else if (Vcb && Vcb->type == VCB_TYPE_BUS) {
5776 bus_device_extension* bde = DeviceObject->DeviceExtension;
5777
5779
5781
5782 goto exit;
5783 }
5784
5785 Status = Irp->IoStatus.Status;
5787
5788exit:
5789 if (top_level)
5791
5793
5794 return Status;
5795}
5796
5798 ULONG i;
5799
5800 if (us->Length < sizeof(WCHAR))
5802
5803 if (us->Length > 255 * sizeof(WCHAR))
5805
5806 for (i = 0; i < us->Length / sizeof(WCHAR); i++) {
5807 if (us->Buffer[i] == '/' || us->Buffer[i] == 0 ||
5808 (!posix && (us->Buffer[i] == '/' || us->Buffer[i] == ':')) ||
5809 (!posix && !stream && (us->Buffer[i] == '<' || us->Buffer[i] == '>' || us->Buffer[i] == '"' ||
5810 us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31))))
5812
5813 /* Don't allow unpaired surrogates ("WTF-16") */
5814
5815 if ((us->Buffer[i] & 0xfc00) == 0xdc00 && (i == 0 || ((us->Buffer[i-1] & 0xfc00) != 0xd800)))
5817
5818 if ((us->Buffer[i] & 0xfc00) == 0xd800 && (i == (us->Length / sizeof(WCHAR)) - 1 || ((us->Buffer[i+1] & 0xfc00) != 0xdc00)))
5820 }
5821
5822 if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.')))
5824
5825 /* The Linux driver expects filenames with a maximum length of 255 bytes - make sure
5826 * that our UTF-8 length won't be longer than that. */
5827 if (us->Length >= 85 * sizeof(WCHAR)) {
5829 ULONG utf8len;
5830
5831 Status = utf16_to_utf8(NULL, 0, &utf8len, us->Buffer, us->Length);
5832 if (!NT_SUCCESS(Status))
5833 return Status;
5834
5835 if (utf8len > 255)
5837 else if (stream && utf8len > 250) // minus five bytes for "user."
5839 }
5840
5841 return STATUS_SUCCESS;
5842}
5843
5845 LIST_ENTRY* le;
5846 bool locked;
5847 range_lock* rl;
5848
5849 rl = ExAllocateFromNPagedLookasideList(&Vcb->range_lock_lookaside);
5850 if (!rl) {
5851 ERR("out of memory\n");
5852 return;
5853 }
5854
5855 rl->start = start;
5856 rl->length = length;
5857 rl->thread = PsGetCurrentThread();
5858
5859 while (true) {
5860 locked = false;
5861
5862 ExAcquireResourceExclusiveLite(&c->range_locks_lock, true);
5863
5864 le = c->range_locks.Flink;
5865 while (le != &c->range_locks) {
5867
5868 if (rl2->start < start + length && rl2->start + rl2->length > start && rl2->thread != PsGetCurrentThread()) {
5869 locked = true;
5870 break;
5871 }
5872
5873 le = le->Flink;
5874 }
5875
5876 if (!locked) {
5877 InsertTailList(&c->range_locks, &rl->list_entry);
5878
5879 ExReleaseResourceLite(&c->range_locks_lock);
5880 return;
5881 }
5882
5883 KeClearEvent(&c->range_locks_event);
5884
5885 ExReleaseResourceLite(&c->range_locks_lock);
5886
5887 KeWaitForSingleObject(&c->range_locks_event, UserRequest, KernelMode, false, NULL);
5888 }
5889}
5890
5892 LIST_ENTRY* le;
5893
5894 ExAcquireResourceExclusiveLite(&c->range_locks_lock, true);
5895
5896 le = c->range_locks.Flink;
5897 while (le != &c->range_locks) {
5899
5900 if (rl->start == start && rl->length == length) {
5902 ExFreeToNPagedLookasideList(&Vcb->range_lock_lookaside, rl);
5903 break;
5904 }
5905
5906 le = le->Flink;
5907 }
5908
5909 KeSetEvent(&c->range_locks_event, 0, false);
5910
5911 ExReleaseResourceLite(&c->range_locks_lock);
5912}
5913
5915 dev->stats[error]++;
5916 dev->stats_changed = true;
5917 Vcb->stats_changed = true;
5918}
5919
5920#ifdef _DEBUG
5921_Function_class_(KSTART_ROUTINE)
5922static void __stdcall serial_thread(void* context) {
5923 LARGE_INTEGER due_time;
5924 KTIMER timer;
5925
5926 UNUSED(context);
5927
5928 KeInitializeTimer(&timer);
5929
5930 due_time.QuadPart = (uint64_t)-10000000;
5931
5932 KeSetTimer(&timer, due_time, NULL);
5933
5934 while (true) {
5936
5937 init_serial(false);
5938
5939 if (comdo)
5940 break;
5941
5942 KeSetTimer(&timer, due_time, NULL);
5943 }
5944
5945 KeCancelTimer(&timer);
5946
5948
5949 serial_thread_handle = NULL;
5950}
5951
5952static void init_serial(bool first_time) {
5954
5956 if (!NT_SUCCESS(Status)) {
5957 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
5958
5959 if (first_time) {
5961
5963
5964 Status = PsCreateSystemThread(&serial_thread_handle, 0, &oa, NULL, NULL, serial_thread, NULL);
5965 if (!NT_SUCCESS(Status)) {
5966 ERR("PsCreateSystemThread returned %08lx\n", Status);
5967 return;
5968 }
5969 }
5970 }
5971}
5972#endif
5973
5974#if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_))
5975static void check_cpu() {
5976 bool have_sse2 = false, have_sse42 = false, have_avx2 = false;
5977 int cpu_info[4];
5978
5979 __cpuid(cpu_info, 1);
5980 have_sse42 = cpu_info[2] & (1 << 20);
5981 have_sse2 = cpu_info[3] & (1 << 26);
5982
5983 __cpuidex(cpu_info, 7, 0);
5984 have_avx2 = cpu_info[1] & (1 << 5);
5985
5986 if (have_avx2) {
5987 // check Windows has enabled AVX2 - Windows 10 doesn't immediately
5988
5989 if (__readcr4() & (1 << 18)) {
5990 uint32_t xcr0;
5991
5992#ifdef _MSC_VER
5993 xcr0 = (uint32_t)_xgetbv(0);
5994#else
5995 __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "edx");
5996#endif
5997
5998 if ((xcr0 & 6) != 6)
5999 have_avx2 = false;
6000 } else
6001 have_avx2 = false;
6002 }
6003
6004 if (have_sse42) {
6005 TRACE("SSE4.2 is supported\n");
6006 calc_crc32c = calc_crc32c_hw;
6007 } else
6008 TRACE("SSE4.2 not supported\n");
6009
6010 if (have_sse2) {
6011 TRACE("SSE2 is supported\n");
6012
6013 if (!have_avx2)
6014 do_xor = do_xor_sse2;
6015 } else
6016 TRACE("SSE2 is not supported\n");
6017
6018 if (have_avx2) {
6019 TRACE("AVX2 is supported\n");
6020 do_xor = do_xor_avx2;
6021 } else
6022 TRACE("AVX2 is not supported\n");
6023}
6024#endif
6025
6026#ifdef _DEBUG
6027static void init_logging() {
6028 ExAcquireResourceExclusiveLite(&log_lock, true);
6029
6030 if (log_device.Length > 0)
6031 init_serial(true);
6032 else if (log_file.Length > 0) {
6036 char* dateline;
6039
6041
6042 Status = ZwCreateFile(&log_handle, FILE_WRITE_DATA, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6044
6045 if (!NT_SUCCESS(Status)) {
6046 ERR("ZwCreateFile returned %08lx\n", Status);
6047 goto end;
6048 }
6049
6050 if (iosb.Information == FILE_OPENED) { // already exists
6053
6054 static const char delim[] = "\n---\n";
6055
6056 // move to end of file
6057
6058 Status = ZwQueryInformationFile(log_handle, &iosb, &fsi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
6059
6060 if (!NT_SUCCESS(Status)) {
6061 ERR("ZwQueryInformationFile returned %08lx\n", Status);
6062 goto end;
6063 }
6064
6065 fpi.CurrentByteOffset = fsi.EndOfFile;
6066
6067 Status = ZwSetInformationFile(log_handle, &iosb, &fpi, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
6068
6069 if (!NT_SUCCESS(Status)) {
6070 ERR("ZwSetInformationFile returned %08lx\n", Status);
6071 goto end;
6072 }
6073
6074 Status = ZwWriteFile(log_handle, NULL, NULL, NULL, &iosb, (void*)delim, sizeof(delim) - 1, NULL, NULL);
6075
6076 if (!NT_SUCCESS(Status)) {
6077 ERR("ZwWriteFile returned %08lx\n", Status);
6078 goto end;
6079 }
6080 }
6081
6082 dateline = ExAllocatePoolWithTag(PagedPool, 256, ALLOC_TAG);
6083
6084 if (!dateline) {
6085 ERR("out of memory\n");
6086 goto end;
6087 }
6088
6090
6092
6093 sprintf(dateline, "Starting logging at %04i-%02i-%02i %02i:%02i:%02i\n", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second);
6094
6095 Status = ZwWriteFile(log_handle, NULL, NULL, NULL, &iosb, dateline, (ULONG)strlen(dateline), NULL, NULL);
6096
6097 ExFreePool(dateline);
6098
6099 if (!NT_SUCCESS(Status)) {
6100 ERR("ZwWriteFile returned %08lx\n", Status);
6101 goto end;
6102 }
6103 }
6104
6105end:
6106 ExReleaseResourceLite(&log_lock);
6107}
6108#endif
6109
6110_Function_class_(KSTART_ROUTINE)
6111static void __stdcall degraded_wait_thread(_In_ void* context) {
6112 KTIMER timer;
6113 LARGE_INTEGER delay;
6114
6115 UNUSED(context);
6116
6117 KeInitializeTimer(&timer);
6118
6119 delay.QuadPart = -30000000; // wait three seconds
6120 KeSetTimer(&timer, delay, NULL);
6122
6123 TRACE("timer expired\n");
6124
6125 degraded_wait = false;
6126
6129
6131}
6132
6133_Function_class_(DRIVER_ADD_DEVICE)
6135 LIST_ENTRY* le;
6137 UNICODE_STRING volname;
6138 ULONG i;
6139 WCHAR* s;
6140 pdo_device_extension* pdode = NULL;
6141 PDEVICE_OBJECT voldev;
6143 UNICODE_STRING arc_name_us;
6144 WCHAR* anp;
6145
6146 static const WCHAR arc_name_prefix[] = L"\\ArcName\\btrfs(";
6147
6148 WCHAR arc_name[(sizeof(arc_name_prefix) / sizeof(WCHAR)) - 1 + 37];
6149
6150 TRACE("(%p, %p)\n", DriverObject, PhysicalDeviceObject);
6151
6153
6155
6156 le = pdo_list.Flink;
6157 while (le != &pdo_list) {
6159
6160 if (pdode2->pdo == PhysicalDeviceObject) {
6161 pdode = pdode2;
6162 break;
6163 }
6164
6165 le = le->Flink;
6166 }
6167
6168 if (!pdode) {
6169 WARN("unrecognized PDO %p\n", PhysicalDeviceObject);
6171 goto end;
6172 }
6173
6175
6176 if (pdode->vde) { // if already done, return success
6178 goto end2;
6179 }
6180
6181 volname.Length = volname.MaximumLength = (sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR)) + ((36 + 1) * sizeof(WCHAR));
6182 volname.Buffer = ExAllocatePoolWithTag(PagedPool, volname.MaximumLength, ALLOC_TAG); // FIXME - when do we free this?
6183
6184 if (!volname.Buffer) {
6185 ERR("out of memory\n");
6187 goto end2;
6188 }
6189
6191 RtlCopyMemory(arc_name, arc_name_prefix, sizeof(arc_name_prefix) - sizeof(WCHAR));
6192
6193 anp = &arc_name[(sizeof(arc_name_prefix) / sizeof(WCHAR)) - 1];
6194 s = &volname.Buffer[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1];
6195
6196 for (i = 0; i < 16; i++) {
6197 *s = *anp = hex_digit(pdode->uuid.uuid[i] >> 4);
6198 s++;
6199 anp++;
6200
6201 *s = *anp = hex_digit(pdode->uuid.uuid[i] & 0xf);
6202 s++;
6203 anp++;
6204
6205 if (i == 3 || i == 5 || i == 7 || i == 9) {
6206 *s = *anp = '-';
6207 s++;
6208 anp++;
6209 }
6210 }
6211
6212 *s = '}';
6213 *anp = ')';
6214
6217 if (!NT_SUCCESS(Status)) {
6218 ERR("IoCreateDevice returned %08lx\n", Status);
6219 goto end2;
6220 }
6221
6222 arc_name_us.Buffer = arc_name;
6223 arc_name_us.Length = arc_name_us.MaximumLength = sizeof(arc_name);
6224
6225 Status = IoCreateSymbolicLink(&arc_name_us, &volname);
6226 if (!NT_SUCCESS(Status))
6227 WARN("IoCreateSymbolicLink returned %08lx\n", Status);
6228
6229 voldev->SectorSize = PhysicalDeviceObject->SectorSize;
6230 voldev->Flags |= DO_DIRECT_IO;
6231
6232 vde = voldev->DeviceExtension;
6233 vde->type = VCB_TYPE_VOLUME;
6234 vde->name = volname;
6235 vde->device = voldev;
6236 vde->mounted_device = NULL;
6238 vde->pdode = pdode;
6239 vde->removing = false;
6240 vde->dead = false;
6241 vde->open_count = 0;
6242
6243 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_DEVINTERFACE_VOLUME, NULL, &vde->bus_name);
6244 if (!NT_SUCCESS(Status))
6245 WARN("IoRegisterDeviceInterface returned %08lx\n", Status);
6246
6248
6249 pdode->vde = vde;
6250
6251 if (pdode->removable)
6252 voldev->Characteristics |= FILE_REMOVABLE_MEDIA;
6253
6254 if (RtlCompareMemory(&boot_uuid, &pdode->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
6257 }
6258
6259 voldev->Flags &= ~DO_DEVICE_INITIALIZING;
6260
6262 if (!NT_SUCCESS(Status))
6263 WARN("IoSetDeviceInterfaceState returned %08lx\n", Status);
6264
6266
6267end2:
6269
6270end:
6272
6273 return Status;
6274}
6275
6276_Function_class_(DRIVER_INITIALIZE)
6280 UNICODE_STRING device_nameW;
6281 UNICODE_STRING dosdevice_nameW;
6284 HANDLE regh;
6285 OBJECT_ATTRIBUTES oa, system_thread_attributes;
6286 ULONG dispos;
6288
6290
6291 Status = RtlGetVersion(&ver);
6292 if (!NT_SUCCESS(Status)) {
6293 ERR("RtlGetVersion returned %08lx\n", Status);
6294 return Status;
6295 }
6296
6297 is_windows_8 = ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2);
6298
6300
6303
6304#ifdef _DEBUG
6305 ExInitializeResourceLite(&log_lock);
6306#endif
6308
6313
6316
6317 if (!registry_path.Buffer) {
6318 ERR("out of memory\n");
6320 }
6321
6323
6325
6326#ifdef _DEBUG
6327 if (debug_log_level > 0)
6328 init_logging();
6329
6330 log_started = true;
6331#endif
6332
6333 TRACE("DriverEntry\n");
6334
6335#if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_))
6336 check_cpu();
6337#endif
6338
6339 if (ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2)) { // Windows 8 or above
6341 tPsIsDiskCountersEnabled fPsIsDiskCountersEnabled;
6342
6343 RtlInitUnicodeString(&name, L"PsIsDiskCountersEnabled");
6344 fPsIsDiskCountersEnabled = (tPsIsDiskCountersEnabled)MmGetSystemRoutineAddress(&name);
6345
6346 if (fPsIsDiskCountersEnabled) {
6347 diskacc = fPsIsDiskCountersEnabled();
6348
6349 RtlInitUnicodeString(&name, L"PsUpdateDiskCounters");
6351
6353 diskacc = false;
6354
6355 RtlInitUnicodeString(&name, L"FsRtlUpdateDiskCounters");
6357 }
6358
6359 RtlInitUnicodeString(&name, L"CcCopyReadEx");
6361
6362 RtlInitUnicodeString(&name, L"CcCopyWriteEx");
6364
6365 RtlInitUnicodeString(&name, L"CcSetAdditionalCacheAttributesEx");
6367
6368 RtlInitUnicodeString(&name, L"FsRtlCheckLockForOplockRequest");
6370 } else {
6377 }
6378
6379 if (ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 1)) { // Windows 7 or above
6381
6382 RtlInitUnicodeString(&name, L"IoUnregisterPlugPlayNotificationEx");
6384
6385 RtlInitUnicodeString(&name, L"FsRtlAreThereCurrentOrInProgressFileLocks");
6387 } else {
6390 }
6391
6392 if (ver.dwMajorVersion >= 6) { // Windows Vista or above
6394
6395 RtlInitUnicodeString(&name, L"FsRtlGetEcpListFromIrp");
6397
6398 RtlInitUnicodeString(&name, L"FsRtlGetNextExtraCreateParameter");
6400
6401 RtlInitUnicodeString(&name, L"FsRtlValidateReparsePointBuffer");
6403 } else {
6407 }
6408
6410
6412
6413 DriverObject->DriverExtension->AddDevice = AddDevice;
6414
6415 DriverObject->MajorFunction[IRP_MJ_CREATE] = drv_create;
6416 DriverObject->MajorFunction[IRP_MJ_CLOSE] = drv_close;
6417 DriverObject->MajorFunction[IRP_MJ_READ] = drv_read;
6418 DriverObject->MajorFunction[IRP_MJ_WRITE] = drv_write;
6419 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = drv_query_information;
6420 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = drv_set_information;
6421 DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = drv_query_ea;
6422 DriverObject->MajorFunction[IRP_MJ_SET_EA] = drv_set_ea;
6423 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = drv_flush_buffers;
6424 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = drv_query_volume_information;
6425 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = drv_set_volume_information;
6426 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = drv_directory_control;
6427 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = drv_file_system_control;
6428 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = drv_device_control;
6429 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = drv_shutdown;
6430 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = drv_lock_control;
6431 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = drv_cleanup;
6432 DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = drv_query_security;
6433 DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = drv_set_security;
6434 DriverObject->MajorFunction[IRP_MJ_POWER] = drv_power;
6435 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = drv_system_control;
6436 DriverObject->MajorFunction[IRP_MJ_PNP] = drv_pnp;
6437
6438 init_fast_io_dispatch(&DriverObject->FastIoDispatch);
6439
6440 device_nameW.Buffer = (WCHAR*)device_name;
6441 device_nameW.Length = device_nameW.MaximumLength = sizeof(device_name) - sizeof(WCHAR);
6442 dosdevice_nameW.Buffer = (WCHAR*)dosdevice_name;
6443 dosdevice_nameW.Length = dosdevice_nameW.MaximumLength = sizeof(dosdevice_name) - sizeof(WCHAR);
6444
6447 if (!NT_SUCCESS(Status)) {
6448 ERR("IoCreateDevice returned %08lx\n", Status);
6449 return Status;
6450 }
6451
6454
6456
6457 cde->type = VCB_TYPE_CONTROL;
6458
6459 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
6460
6461 Status = IoCreateSymbolicLink(&dosdevice_nameW, &device_nameW);
6462 if (!NT_SUCCESS(Status)) {
6463 ERR("IoCreateSymbolicLink returned %08lx\n", Status);
6464 return Status;
6465 }
6466
6467 init_cache();
6468
6472
6474
6477 if (!NT_SUCCESS(Status)) {
6478 ERR("ZwCreateKey returned %08lx\n", Status);
6479 return Status;
6480 }
6481
6482 watch_registry(regh);
6483
6486 if (!NT_SUCCESS(Status)) {
6487 ERR("IoCreateDevice returned %08lx\n", Status);
6488 return Status;
6489 }
6490
6492
6493 RtlZeroMemory(bde, sizeof(bus_device_extension));
6494
6495 bde->type = VCB_TYPE_BUS;
6496
6498 NULL, NULL, 0, &bde->buspdo);
6499 if (!NT_SUCCESS(Status)) {
6500 ERR("IoReportDetectedDevice returned %08lx\n", Status);
6501 return Status;
6502 }
6503
6504 Status = IoRegisterDeviceInterface(bde->buspdo, &BtrfsBusInterface, NULL, &bde->bus_name);
6505 if (!NT_SUCCESS(Status))
6506 WARN("IoRegisterDeviceInterface returned %08lx\n", Status);
6507
6509
6510 busobj->Flags &= ~DO_DEVICE_INITIALIZING;
6511
6513 if (!NT_SUCCESS(Status))
6514 WARN("IoSetDeviceInterfaceState returned %08lx\n", Status);
6515
6517
6518 InitializeObjectAttributes(&system_thread_attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
6519
6520 Status = PsCreateSystemThread(&degraded_wait_handle, 0, &system_thread_attributes, NULL, NULL, degraded_wait_thread, NULL);
6521 if (!NT_SUCCESS(Status))
6522 WARN("PsCreateSystemThread returned %08lx\n", Status);
6523
6525
6527 (PVOID)&GUID_DEVINTERFACE_VOLUME, DriverObject, volume_notification, NULL, &notification_entry2);
6528 if (!NT_SUCCESS(Status))
6529 ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
6530
6532 (PVOID)&GUID_DEVINTERFACE_HIDDEN_VOLUME, DriverObject, volume_notification, NULL, &notification_entry3);
6533 if (!NT_SUCCESS(Status))
6534 ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
6535
6537 (PVOID)&GUID_DEVINTERFACE_DISK, DriverObject, pnp_notification, DriverObject, &notification_entry);
6538 if (!NT_SUCCESS(Status))
6539 ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
6540
6541 finished_probing = true;
6542
6544
6545 // Status = PsCreateSystemThread(&mountmgr_thread_handle, 0, &system_thread_attributes, NULL, NULL, mountmgr_thread, NULL);
6546 // if (!NT_SUCCESS(Status))
6547 // WARN("PsCreateSystemThread returned %08lx\n", Status);
6548
6550
6552
6553 return STATUS_SUCCESS;
6554}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned short int uint16_t
Definition: acefiex.h:54
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
#define BTRFS_LAST_FREE_OBJECTID
Definition: btrfs.h:62
#define BTRFS_MAGIC
Definition: btrfs.h:42
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer)
Definition: fsrtl.c:32
NTSTATUS(__stdcall * tFsRtlValidateReparsePointBuffer)(ULONG BufferLength, PREPARSE_DATA_BUFFER ReparseBuffer)
Definition: btrfs_drv.h:1864
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739
NTSTATUS registry_load_volume_options(device_extension *Vcb)
Definition: registry.c:36
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:997
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
CACHE_MANAGER_CALLBACKS cache_callbacks
Definition: cache.c:20
#define BTRFS_VOLUME_PREFIX
Definition: btrfs_drv.h:127
#define READ_AHEAD_GRANULARITY
Definition: btrfs_drv.h:114
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
NTSTATUS(__stdcall * tIoUnregisterPlugPlayNotificationEx)(PVOID NotificationEntry)
Definition: btrfs_drv.h:1857
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define _Dispatch_type_(a)
Definition: btrfs_drv.h:204
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
BOOLEAN(__stdcall * tPsIsDiskCountersEnabled)()
Definition: btrfs_drv.h:1833
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:407
void void void NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp) __attribute__((nonnull(1
#define __S_IFDIR
Definition: btrfs_drv.h:1754
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
void(__stdcall * xor_func)(uint8_t *buf1, uint8_t *buf2, uint32_t len)
Definition: btrfs_drv.h:1131
NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID *uuid)
Definition: registry.c:385
#define VCB_TYPE_CONTROL
Definition: btrfs_drv.h:688
struct _fcb fcb
Definition: btrfs_drv.h:1364
#define FILE_SUPPORTS_POSIX_UNLINK_RENAME
Definition: btrfs_drv.h:152
KSPIN_LOCK fve_data_lock
Definition: search.c:63
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
void fcb_get_sd(fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
Definition: security.c:511
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:2155
#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
Definition: btrfs_drv.h:156
VOID(__stdcall * tCcSetAdditionalCacheAttributesEx)(PFILE_OBJECT FileObject, ULONG Flags)
Definition: btrfs_drv.h:1853
BOOLEAN(__stdcall * tFsRtlCheckLockForOplockRequest)(PFILE_LOCK FileLock, PLARGE_INTEGER AllocationSize)
Definition: btrfs_drv.h:1866
#define EA_DOSATTRIB_HASH
Definition: btrfs_drv.h:97
void init_cache()
Definition: cache.c:85
#define ALLOC_TAG
Definition: btrfs_drv.h:87
VOID(__stdcall * tFsRtlUpdateDiskCounters)(ULONG64 BytesRead, ULONG64 BytesWritten)
Definition: btrfs_drv.h:1855
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252
#define hex_digit(c)
Definition: btrfs_drv.h:1748
NTSTATUS vol_close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:95
#define UNUSED(x)
Definition: btrfs_drv.h:82
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
void init_fast_io_dispatch(FAST_IO_DISPATCH **fiod)
Definition: fastio.c:535
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
void free_vol(volume_device_extension *vde)
Definition: volume.c:50
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
VOID(__stdcall * tPsUpdateDiskCounters)(PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten, ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount)
Definition: btrfs_drv.h:1835
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
NTSTATUS(__stdcall * tFsRtlGetEcpListFromIrp)(PIRP Irp, PECP_LIST *EcpList)
Definition: btrfs_drv.h:1859
void watch_registry(HANDLE regh)
Definition: registry.c:1036
void void void NTSTATUS void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist) __attribute__((nonnull(1
#define FILE_SUPPORTS_BLOCK_REFCOUNTING
Definition: btrfs_drv.h:148
NTSTATUS dismount_volume(device_extension *Vcb, bool shutdown, PIRP Irp)
Definition: fsctl.c:2584
#define EA_DOSATTRIB
Definition: btrfs_drv.h:96
#define VCB_TYPE_PDO
Definition: btrfs_drv.h:690
NTSTATUS clear_free_space_cache(device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
Definition: free-space.c:59
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, file_ref **pfr, PIRP Irp)
Definition: create.c:4136
NTSTATUS NTSTATUS bool bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *prev_tp, PIRP Irp) __attribute__((nonnull(1
BOOLEAN(__stdcall * tFsRtlAreThereCurrentOrInProgressFileLocks)(PFILE_LOCK FileLock)
Definition: btrfs_drv.h:1868
#define VCB_TYPE_BUS
Definition: btrfs_drv.h:691
NTSTATUS(__stdcall * tFsRtlGetNextExtraCreateParameter)(PECP_LIST EcpList, PVOID CurrentEcpContext, LPGUID NextEcpType, PVOID *NextEcpContext, ULONG *NextEcpContextSize)
Definition: btrfs_drv.h:1861
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define CC_ENABLE_DISK_IO_ACCOUNTING
Definition: btrfs_drv.h:1845
struct _ccb ccb
BOOLEAN(__stdcall * tCcCopyWriteEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer, PETHREAD IoIssuerThread)
Definition: btrfs_drv.h:1838
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension *vde, _In_ volume_child *vc, _In_ bool skip_dev)
Definition: search.c:531
void read_registry(PUNICODE_STRING regpath, bool refresh)
Definition: registry.c:777
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
NTSTATUS registry_mark_volume_mounted(BTRFS_UUID *uuid)
Definition: registry.c:242
NTSTATUS fileref_get_filename(file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
Definition: fileinfo.c:4245
void do_unlock_volume(device_extension *Vcb)
Definition: fsctl.c:2326
NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP *Pirp, uint32_t type)
Definition: fsctl.c:5345
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
BOOLEAN(__stdcall * tCcCopyReadEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PETHREAD IoIssuerThread)
Definition: btrfs_drv.h:1841
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
file_ref * create_fileref(device_extension *Vcb)
Definition: create.c:160
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2234
void remove_dir_child_from_hash_lists(fcb *fcb, dir_child *dc)
Definition: fileinfo.c:744
#define BTRFS_NODE_TYPE_CCB
Definition: btrfs_drv.h:84
#define int3
Definition: btrfs_drv.h:1745
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1248
NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, bool ignore_size, PIRP Irp)
Definition: create.c:510
static btrfs_root * add_root(LIST_ENTRY *roots, uint64_t id)
Definition: btrfslib.c:284
VOID NTAPI CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, IN ULONG Granularity)
Definition: cachesub.c:36
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
Definition: bufpool.h:45
Definition: list.h:37
#define _Requires_lock_held_(lock)
#define _Requires_exclusive_lock_held_(lock)
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
crc_func calc_crc32c
Definition: crc32c.c:23
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags)
Definition: libsupp.c:229
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define crc32(crc, buf, len)
Definition: inflate.c:1081
static const WCHAR *const ext[]
Definition: module.c:53
const WCHAR * action
Definition: action.c:7509
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
NTSTATUS look_for_balance_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb)
Definition: balance.c:3628
BTRFS_UUID boot_uuid
Definition: boot.c:33
void check_system_root()
Definition: boot.c:336
xor_func do_xor
Definition: btrfs.c:127
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
UNICODE_STRING log_file
Definition: btrfs.c:89
static ULONG get_device_change_count(_In_ PDEVICE_OBJECT devobj)
Definition: btrfs.c:3396
void do_shutdown(PIRP Irp)
Definition: btrfs.c:5392
bool shutting_down
Definition: btrfs.c:109
static bool is_device_removable(_In_ PDEVICE_OBJECT devobj)
Definition: btrfs.c:3382
#define INIT_UNICODE_STRING(var, val)
Definition: btrfs.c:679
void reap_filerefs(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1906
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5914
static bool lie_about_fs_type()
Definition: btrfs.c:687
uint32_t mount_readonly
Definition: btrfs.c:84
NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID **guid)
Definition: btrfs.c:4233
superblock * sb
Definition: btrfs.c:4261
NTSTATUS delete_fileref(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
Definition: btrfs.c:2270
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
tCcCopyReadEx fCcCopyReadEx
Definition: btrfs.c:91
static bool device_still_valid(device *dev, uint64_t expected_generation)
Definition: btrfs.c:5546
void chunk_lock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5844
HANDLE mountmgr_thread_handle
Definition: btrfs.c:106
uint32_t mount_max_inline
Definition: btrfs.c:78
tCcCopyWriteEx fCcCopyWriteEx
Definition: btrfs.c:92
void reap_fileref(device_extension *Vcb, file_ref *fr)
Definition: btrfs.c:1875
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ uint64_t id, _Out_ root **rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp)
Definition: btrfs.c:1271
NTSTATUS utf16_to_utf8(char *dest, ULONG dest_max, ULONG *dest_len, WCHAR *src, ULONG src_len)
Definition: btrfs.c:894
static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: btrfs.c:4375
bool diskacc
Definition: btrfs.c:101
static bool is_btrfs_volume(_In_ PDEVICE_OBJECT DeviceObject)
Definition: btrfs.c:4141
static void calculate_total_space(_In_ device_extension *Vcb, _Out_ uint64_t *totalsize, _Out_ uint64_t *freespace)
Definition: btrfs.c:619
UNICODE_STRING log_device
Definition: btrfs.c:89
void chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5891
LIST_ENTRY VcbList
Definition: btrfs.c:69
uint32_t mount_no_trim
Definition: btrfs.c:81
uint32_t mount_compress
Definition: btrfs.c:72
UNICODE_STRING registry_path
Definition: btrfs.c:89
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
Definition: btrfs.c:100
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1734
static void add_device_to_list(_In_ device_extension *Vcb, _In_ device *dev)
Definition: btrfs.c:3279
static bool compare_strings(const UNICODE_STRING *us1, const UNICODE_STRING *us2)
Definition: btrfs.c:650
uint32_t mount_allow_degraded
Definition: btrfs.c:83
uint32_t mount_skip_balance
Definition: btrfs.c:79
NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3876
static const WCHAR device_name[]
Definition: btrfs.c:60
static NTSTATUS look_for_roots(_Requires_exclusive_lock_held_(_Curr_->tree_lock) _In_ device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3083
InitializeListHead & r
Definition: btrfs.c:3015
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
uint32_t mount_zlib_level
Definition: btrfs.c:75
static NTSTATUS verify_device(_In_ device_extension *Vcb, _Inout_ device *dev)
Definition: btrfs.c:5111
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2664
uint64_t boot_subvol
Definition: boot.c:34
KEVENT mountmgr_thread_event
Definition: btrfs.c:108
_In_ uint64_t id
Definition: btrfs.c:2995
return STATUS_SUCCESS
Definition: btrfs.c:3080
InsertTailList & Vcb
Definition: btrfs.c:3044
uint32_t mount_zstd_level
Definition: btrfs.c:76
static NTSTATUS get_device_pnp_name_guid(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _In_ const GUID *guid)
Definition: btrfs.c:4178
static const WCHAR dosdevice_name[]
Definition: btrfs.c:61
LIST_ENTRY pdo_list
Definition: btrfs.c:104
tCcSetAdditionalCacheAttributesEx fCcSetAdditionalCacheAttributesEx
Definition: btrfs.c:93
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
uint32_t mount_nodatacow
Definition: btrfs.c:86
uint32_t mount_compress_type
Definition: btrfs.c:74
tPsUpdateDiskCounters fPsUpdateDiskCounters
Definition: btrfs.c:90
static NTSTATUS find_disk_holes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ device *dev, _In_opt_ PIRP Irp)
Definition: btrfs.c:3207
uint64_t num_reads
Definition: btrfs.c:67
bool check_superblock_checksum(superblock *sb)
Definition: btrfs.c:2825
_Out_ bool * pno_pnp
Definition: btrfs.c:4258
static NTSTATUS create_calc_threads(_In_ PDEVICE_OBJECT DeviceObject)
Definition: btrfs.c:4094
ERESOURCE mapping_lock
Definition: btrfs.c:103
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
static NTSTATUS delete_fileref_fcb(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
Definition: btrfs.c:2214
ERESOURCE pdo_list_lock
Definition: btrfs.c:103
tFsRtlGetEcpListFromIrp fFsRtlGetEcpListFromIrp
Definition: btrfs.c:96
uint32_t mount_no_root_dir
Definition: btrfs.c:85
uint32_t mount_flush_interval
Definition: btrfs.c:77
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
Definition: btrfs.c:99
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
Definition: btrfs.c:94
_Ret_maybenull_ root * find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3981
PDEVICE_OBJECT master_devobj
Definition: btrfs.c:66
tFsRtlGetNextExtraCreateParameter fFsRtlGetNextExtraCreateParameter
Definition: btrfs.c:97
bool log_started
Definition: btrfs.c:88
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3416
bool degraded_wait
Definition: btrfs.c:107
_In_ uint64_t _In_ uint64_t addr
Definition: btrfs.c:2995
static NTSTATUS set_label(_In_ device_extension *Vcb, _In_ FILE_FS_LABEL_INFORMATION *ffli)
Definition: btrfs.c:1392
#define INCOMPAT_SUPPORTED
Definition: btrfs.c:53
ERESOURCE global_loading_lock
Definition: btrfs.c:70
LIST_ENTRY uid_map_list
Definition: btrfs.c:68
void * notification_entry3
Definition: btrfs.c:102
NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
Definition: btrfs.c:2732
HANDLE degraded_wait_handle
Definition: btrfs.c:106
static bool still_has_superblock(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj)
Definition: btrfs.c:4313
static NTSTATUS verify_volume(_In_ PDEVICE_OBJECT devobj)
Definition: btrfs.c:5203
tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx
Definition: btrfs.c:95
uint32_t no_pnp
Definition: btrfs.c:87
bool finished_probing
Definition: btrfs.c:105
void protect_superblocks(_Inout_ chunk *c)
Definition: btrfs.c:3777
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
Definition: btrfs.c:4069
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2996
uint32_t mount_no_barrier
Definition: btrfs.c:80
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
static NTSTATUS load_chunk_root(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3513
LIST_ENTRY gid_map_list
Definition: btrfs.c:68
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
Definition: btrfs.c:98
static void __stdcall do_xor_basic(uint8_t *buf1, uint8_t *buf2, uint32_t len)
Definition: btrfs.c:287
static NTSTATUS read_superblock(_In_ device_extension *Vcb, _In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t length)
Definition: btrfs.c:2882
static void send_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1557
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1517
#define COMPAT_RO_SUPPORTED
Definition: btrfs.c:57
uint32_t mount_compress_force
Definition: btrfs.c:73
void reap_fcbs(device_extension *Vcb)
Definition: btrfs.c:1841
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2954
PDEVICE_OBJECT busobj
Definition: btrfs.c:66
void * notification_entry2
Definition: btrfs.c:102
NTSTATUS utf8_to_utf16(WCHAR *dest, ULONG dest_max, ULONG *dest_len, char *src, ULONG src_len)
Definition: btrfs.c:811
BOOLEAN WdmlibRtlIsNtDdiVersionAvailable(ULONG Version)
uint32_t mount_clear_cache
Definition: btrfs.c:82
uint32_t debug_log_level
Definition: btrfs.c:71
ULONG to_read
Definition: btrfs.c:4260
uint32_t get_num_of_processors()
Definition: btrfs.c:4080
static void calculate_sector_shift(device_extension *Vcb)
Definition: btrfs.c:4364
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
ERESOURCE boot_lock
Definition: btrfs.c:110
static NTSTATUS load_sys_chunks(_In_ device_extension *Vcb)
Definition: btrfs.c:3923
static bool get_last_inode(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_opt_ PIRP Irp)
Definition: btrfs.c:386
bool is_windows_8
Definition: btrfs.c:111
_Ret_maybenull_ device * find_device_from_uuid(_In_ device_extension *Vcb, _In_ BTRFS_UUID *uuid)
Definition: btrfs.c:3299
void * notification_entry
Definition: btrfs.c:102
#define BTRFS_ROOT_DATA_RELOC
Definition: btrfs.h:63
#define CSUM_TYPE_SHA256
Definition: btrfs.h:134
#define BTRFS_ROOT_UUID
Definition: btrfs.h:61
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
Definition: btrfs.h:111
static const uint64_t superblock_addrs[]
Definition: btrfs.h:16
#define BTRFS_ROOT_FREE_SPACE
Definition: btrfs.h:62
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define TYPE_DEV_ITEM
Definition: btrfs.h:47
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID
Definition: btrfs.h:112
#define TYPE_DEV_EXTENT
Definition: btrfs.h:46
#define BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL
Definition: btrfs.h:116
#define BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS
Definition: btrfs.h:117
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:88
#define BTRFS_INCOMPAT_FLAGS_METADATA_UUID
Definition: btrfs.h:125
#define MAX_LABEL_SIZE
Definition: btrfs.h:19
#define TYPE_XATTR_ITEM
Definition: btrfs.h:26
#define TYPE_DEV_STATS
Definition: btrfs.h:50
#define HEADER_FLAG_MIXED_BACKREF
Definition: btrfs.h:151
#define TYPE_BLOCK_GROUP_ITEM
Definition: btrfs.h:42
#define BTRFS_SUPERBLOCK_FLAGS_SEEDING
Definition: btrfs.h:128
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:48
#define BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF
Definition: btrfs.h:115
#define TYPE_ROOT_BACKREF
Definition: btrfs.h:33
#define BTRFS_ROOT_CHUNK
Definition: btrfs.h:56
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
#define BTRFS_ROOT_ROOT
Definition: btrfs.h:54
#define TYPE_INODE_REF
Definition: btrfs.h:24
#define BTRFS_ROOT_DEVTREE
Definition: btrfs.h:57
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
#define BTRFS_ROOT_FSTREE
Definition: btrfs.h:58
#define BTRFS_ROOT_EXTENT
Definition: btrfs.h:55
#define BTRFS_ROOT_CHECKSUM
Definition: btrfs.h:60
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
#define TYPE_DIR_ITEM
Definition: btrfs.h:28
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
KIRQL irql
Definition: wave.h:1
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExConvertExclusiveToSharedLite(res)
Definition: env_spec_w32.h:652
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1279
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1152
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1025
time_t now
Definition: finger.c:65
@ FilePositionInformation
Definition: from_kernel.h:75
#define FILE_NAMED_STREAMS
Definition: from_kernel.h:245
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES
Definition: from_kernel.h:250
#define FILE_SUPPORTS_SPARSE_FILES
Definition: from_kernel.h:239
#define FILE_SUPPORTS_REPARSE_POINTS
Definition: from_kernel.h:240
#define FILE_READ_ONLY_VOLUME
Definition: from_kernel.h:246
struct _FILE_FS_ATTRIBUTE_INFORMATION FILE_FS_ATTRIBUTE_INFORMATION
#define FILE_SUPPORTS_HARD_LINKS
Definition: from_kernel.h:249
@ FileFsControlInformation
Definition: from_kernel.h:224
@ FileFsDeviceInformation
Definition: from_kernel.h:222
@ FileFsLabelInformation
Definition: from_kernel.h:220
@ FileFsAttributeInformation
Definition: from_kernel.h:223
@ FileFsVolumeInformation
Definition: from_kernel.h:219
@ FileFsSizeInformation
Definition: from_kernel.h:221
#define FILE_SUPPORTS_OBJECT_IDS
Definition: from_kernel.h:243
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
struct _FILE_FS_SIZE_INFORMATION FILE_FS_SIZE_INFORMATION
#define FILE_PERSISTENT_ACLS
Definition: from_kernel.h:236
#define FILE_CASE_SENSITIVE_SEARCH
Definition: from_kernel.h:233
struct _FILE_FS_FULL_SIZE_INFORMATION FILE_FS_FULL_SIZE_INFORMATION
#define FILE_CASE_PRESERVED_NAMES
Definition: from_kernel.h:234
#define FILE_SUPPORTS_OPEN_BY_FILE_ID
Definition: from_kernel.h:251
#define FILE_UNICODE_ON_DISK
Definition: from_kernel.h:235
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLsizeiptr size
Definition: glext.h:5919
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLint left
Definition: glext.h:7726
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint GLenum GLenum dfactor
Definition: glfuncs.h:252
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define DbgPrint
Definition: hal.h:12
@ InterfaceTypeUndefined
Definition: hwresource.cpp:136
#define ss
Definition: i386-dis.c:441
HFONT tf
Definition: icontest.c:17
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
@ ProcessBasicInformation
Definition: winternl.h:394
@ ProcessWow64Information
Definition: winternl.h:396
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
Definition: msctf.idl:550
PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
Definition: intrin_ppc.h:682
__INTRIN_INLINE void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
Definition: intrin_x86.h:1649
__INTRIN_INLINE unsigned long __readcr4(void)
Definition: intrin_x86.h:1825
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
uint32_t cc
Definition: isohybrid.c:75
uint32_t entry
Definition: isohybrid.c:63
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
static DRIVER_UNLOAD DriverUnload
Definition: kbdclass.c:17
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
VOID NTAPI ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:270
VOID NTAPI ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside)
Definition: lookas.c:194
VOID NTAPI ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)
Definition: lookas.c:170
VOID NTAPI ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:218
POINT cp
Definition: magnifier.c:59
static const WCHAR dc[]
const GUID * guid
struct S1 s1
struct S2 s2
unsigned int uintptr_t
Definition: intrin.h:47
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
char * reloc_root
Definition: mkisofs.c:177
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:91
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:74
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const BYTE us[]
Definition: encode.c:689
#define KEY
Definition: profile.c:30
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
static char * dest
Definition: rtl.c:135
static ATOM item
Definition: dde.c:856
#define min(a, b)
Definition: monoChain.cc:55
int remove
Definition: msacm.c:1366
BYTE uint8_t
Definition: msvideo1.c:66
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3171
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Ret_maybenull_
Definition: no_sal2.h:328
#define _Success_(c)
Definition: no_sal2.h:84
#define _In_z_
Definition: no_sal2.h:164
#define _Out_writes_bytes_opt_(s)
Definition: no_sal2.h:228
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Function_class_(n)
Definition: no_sal2.h:398
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define _In_reads_bytes_opt_(s)
Definition: no_sal2.h:224
#define uint32_t
Definition: nsiface.idl:61
#define uint64_t
Definition: nsiface.idl:62
#define uint16_t
Definition: nsiface.idl:60
#define uint8_t
Definition: nsiface.idl:59
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
struct _FILE_FS_DEVICE_INFORMATION FILE_FS_DEVICE_INFORMATION
#define FILE_READ_ONLY_DEVICE
Definition: nt_native.h:808
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define FILE_OPENED
Definition: nt_native.h:769
#define KEY_NOTIFY
Definition: nt_native.h:1020
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
@ StorageDeviceTrimProperty
Definition: ntddstor.h:520
@ PropertyStandardQuery
Definition: ntddstor.h:505
@ NotificationEvent
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define FileFsFullSizeInformation
Definition: ntifs_ex.h:389
#define FileFsObjectIdInformation
Definition: ntifs_ex.h:390
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IO_ERR_INTERNAL_ERROR
Definition: ntiologc.h:39
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
VOID NTAPI FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:659
VOID NTAPI FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
Definition: notify.c:1590
VOID NTAPI FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
Definition: notify.c:997
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
PDEVICE_OBJECT NTAPI IoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:966
PDEVICE_OBJECT NTAPI IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1507
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:454
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
BOOLEAN NTAPI IoRaiseInformationalHardError(IN NTSTATUS ErrorStatus, IN PUNICODE_STRING String, IN PKTHREAD Thread)
Definition: error.c:710
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3187
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
VOID NTAPI IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
Definition: volume.c:1056
VOID NTAPI IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
Definition: volume.c:987
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
KAFFINITY NTAPI KeQueryActiveProcessors(VOID)
Definition: cpu.c:672
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:758
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1145
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
@ PowerSystemWorking
Definition: ntpoapi.h:36
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_TOO_LATE
Definition: ntstatus.h:626
#define STATUS_SOME_NOT_MAPPED
Definition: ntstatus.h:86
NTSTRSAFEAPI RtlStringCbVPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat, _In_ va_list argList)
Definition: ntstrsafe.h:1034
#define L(x)
Definition: ntvdm.h:50
VOID NTAPI FsRtlUninitializeOplock(IN POPLOCK Oplock)
Definition: oplock.c:1600
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
DRIVER_ADD_DEVICE AddDevice
Definition: parport.h:72
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:346
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:480
NTSTATUS NTAPI IoReportDetectedDevice(_In_ PDRIVER_OBJECT DriverObject, _In_ INTERFACE_TYPE LegacyBusType, _In_ ULONG BusNumber, _In_ ULONG SlotNumber, _In_opt_ PCM_RESOURCE_LIST ResourceList, _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements, _In_ BOOLEAN ResourceAssigned, _Inout_ PDEVICE_OBJECT *DeviceObject)
Definition: pnpreport.c:148
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:53
#define FILE_DEVICE_UNKNOWN
Definition: winioctl.h:79
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define err(...)
static FILE * out
Definition: regtests2xml.c:44
static void close_file()
Definition: regtests2xml.c:133
#define list
Definition: rosglue.h:35
#define offsetof(TYPE, MEMBER)
#define IOCTL_ATA_PASS_THROUGH
Definition: ntddscsi.h:40
struct _ATA_PASS_THROUGH_EX ATA_PASS_THROUGH_EX
#define exit(n)
Definition: config.h:202
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define FileStandardInformation
Definition: propsheet.cpp:61
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
#define TRACE(s)
Definition: solgame.cpp:4
#define true
Definition: stdbool.h:36
uint64_t used
Definition: btrfs.h:424
uint8_t uuid[16]
Definition: btrfs.h:140
uint64_t offset
Definition: btrfs.h:353
uint16_t num_stripes
Definition: btrfs.h:347
uint64_t stripe_length
Definition: btrfs.h:342
uint16_t sub_stripes
Definition: btrfs.h:348
uint64_t size
Definition: btrfs.h:340
uint64_t type
Definition: btrfs.h:343
uint64_t length
Definition: btrfs.h:472
BTRFS_UUID device_uuid
Definition: btrfs.h:190
uint64_t dev_id
Definition: btrfs.h:178
uint16_t m
Definition: btrfs.h:275
char name[1]
Definition: btrfs.h:278
uint16_t n
Definition: btrfs.h:276
KEY key
Definition: btrfs.h:273
uint32_t st_mode
Definition: btrfs.h:295
uint32_t st_nlink
Definition: btrfs.h:292
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t st_size
Definition: btrfs.h:289
BTRFS_TIME st_atime
Definition: btrfs.h:301
uint64_t st_blocks
Definition: btrfs.h:290
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t generation
Definition: btrfs.h:287
uint64_t index
Definition: btrfs.h:375
char name[1]
Definition: btrfs.h:377
uint16_t n
Definition: btrfs.h:376
Definition: btrfs.h:143
uint8_t obj_type
Definition: btrfs.h:145
uint64_t obj_id
Definition: btrfs.h:144
uint64_t offset
Definition: btrfs.h:146
uint64_t block_number
Definition: btrfs.h:315
uint64_t generation
Definition: btrfs.h:313
ULONG DataTransferLength
Definition: ntddscsi.h:198
UCHAR CurrentTaskFile[8]
Definition: ntddscsi.h:203
ULONG_PTR DataBufferOffset
Definition: ntddscsi.h:201
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2288
LARGE_INTEGER ActualAvailableAllocationUnits
Definition: from_kernel.h:272
LARGE_INTEGER CallerAvailableAllocationUnits
Definition: from_kernel.h:271
LARGE_INTEGER TotalAllocationUnits
Definition: from_kernel.h:270
LARGE_INTEGER TotalAllocationUnits
Definition: from_kernel.h:263
LARGE_INTEGER AvailableAllocationUnits
Definition: from_kernel.h:264
LARGE_INTEGER CurrentByteOffset
Definition: nt_native.h:955
LARGE_INTEGER Length
Definition: imports.h:232
struct _IDENTIFY_DEVICE_DATA::@1905 CommandSetSupport
struct _IO_STACK_LOCATION::@3983::@3987 Read
struct _IO_STACK_LOCATION::@3983::@3998 FileSystemControl
struct _IO_STACK_LOCATION::@3983::@3996 QueryVolume
struct _IO_STACK_LOCATION::@3983::@4003 MountVolume
struct _IO_STACK_LOCATION::@3983::@3997 SetVolume
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _IO_STACK_LOCATION::@3983::@4019 Power
struct _IO_STACK_LOCATION::@3983::@3988 Write
union _IO_STACK_LOCATION::@1584 Parameters
Definition: btrfs_drv.h:1876
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT NameLength
Definition: imports.h:141
WCHAR Name[1]
Definition: imports.h:142
ULONG dwMinorVersion
Definition: rtltypes.h:248
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:246
ULONG dwMajorVersion
Definition: rtltypes.h:247
LIST_ENTRY InMemoryOrderModuleList
Definition: btrfs_drv.h:1895
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1912
BOOLEAN MediaRemovable
Definition: imports.h:246
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
UCHAR AdditionalParameters[1]
Definition: ntddstor.h:554
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: iotypes.h:189
CSHORT Type
Definition: iotypes.h:190
CSHORT Size
Definition: iotypes.h:191
struct _DEVICE_OBJECT * DeviceObject
Definition: iotypes.h:194
USHORT Flags
Definition: iotypes.h:192
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
CSHORT NodeSize
Definition: btrfs_drv.h:372
bool reserving
Definition: btrfs_drv.h:381
send_info * send
Definition: btrfs_drv.h:392
UNICODE_STRING query_string
Definition: btrfs_drv.h:376
USHORT NodeType
Definition: btrfs_drv.h:371
UNICODE_STRING filename
Definition: btrfs_drv.h:384
file_ref * fileref
Definition: btrfs_drv.h:383
ULONG options
Definition: btrfs_drv.h:374
bool ads
Definition: btrfs_drv.h:330
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
LIST_ENTRY hardlinks
Definition: btrfs_drv.h:304
FILE_LOCK lock
Definition: btrfs_drv.h:294
LIST_ENTRY dir_children_index
Definition: btrfs_drv.h:314
ULONG atts
Definition: btrfs_drv.h:297
bool deleted
Definition: btrfs_drv.h:295
POOL_TYPE pool_type
Definition: btrfs_drv.h:286
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY extents
Definition: btrfs_drv.h:300
uint64_t inode
Definition: btrfs_drv.h:289
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
ANSI_STRING adsxattr
Definition: btrfs_drv.h:333
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
uint8_t type
Definition: btrfs_drv.h:291
bool dirty
Definition: btrfs_drv.h:320
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
struct _root * subvol
Definition: btrfs_drv.h:288
LIST_ENTRY list_entry
Definition: btrfs_drv.h:336
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
uint32_t hash
Definition: btrfs_drv.h:290
LONG refcount
Definition: btrfs_drv.h:285
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:338
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
SHARE_ACCESS share_access
Definition: btrfs_drv.h:298
ANSI_STRING ea_xattr
Definition: btrfs_drv.h:302
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
bool deleted
Definition: btrfs_drv.h:347
LONG refcount
Definition: btrfs_drv.h:350
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
bool posix_delete
Definition: btrfs_drv.h:346
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
LIST_ENTRY children
Definition: btrfs_drv.h:349
LONG open_count
Definition: btrfs_drv.h:351
bool delete_on_close
Definition: btrfs_drv.h:345
ANSI_STRING oldutf8
Definition: btrfs_drv.h:343
uint64_t id
Definition: btrfs_drv.h:451
uint64_t parent
Definition: btrfs_drv.h:459
uint8_t * data
Definition: btrfs_drv.h:415
uint16_t size
Definition: btrfs_drv.h:414
tree_header header
Definition: btrfs_drv.h:426
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:878
PDEVICE_OBJECT device
Definition: btrfs_drv.h:875
UNICODE_STRING name
Definition: btrfs_drv.h:874
UNICODE_STRING bus_name
Definition: btrfs_drv.h:879
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:880
PDEVICE_OBJECT mounted_device
Definition: btrfs_drv.h:876
PDEVICE_OBJECT pdo
Definition: btrfs_drv.h:877
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:849
UNICODE_STRING bus_name
Definition: btrfs_drv.h:850
PDEVICE_OBJECT buspdo
Definition: btrfs_drv.h:848
Definition: ftp_var.h:139
Definition: http.c:7252
uint64_t dev_id
Definition: devices.h:37
DEV_ITEM devitem
Definition: btrfs_drv.h:527
bool readonly
Definition: btrfs_drv.h:530
bool seeding
Definition: btrfs_drv.h:529
UNICODE_STRING name
Definition: btrfs_drv.h:256
ULONG size
Definition: btrfs_drv.h:259
struct _file_ref * fileref
Definition: btrfs_drv.h:260
Definition: fci.c:127
PSID sid
Definition: btrfs_drv.h:910
Definition: _hash_fun.h:40
Definition: fs.h:78
Definition: copy.c:22
Definition: parser.c:49
Definition: list.h:27
Definition: name.c:39
ULONG filter_match
Definition: btrfs.c:1642
ULONG action
Definition: btrfs.c:1643
PUNICODE_STRING stream
Definition: btrfs.c:1644
file_ref * fileref
Definition: btrfs.c:1641
PIO_WORKITEM work_item
Definition: btrfs.c:1645
ERESOURCE child_lock
Definition: btrfs_drv.h:896
PDEVICE_OBJECT pdo
Definition: btrfs_drv.h:890
uint64_t children_loaded
Definition: btrfs_drv.h:895
LIST_ENTRY children
Definition: btrfs_drv.h:897
volume_device_extension * vde
Definition: btrfs_drv.h:889
uint64_t num_children
Definition: btrfs_drv.h:894
uint64_t start
Definition: btrfs_drv.h:546
uint64_t length
Definition: btrfs_drv.h:547
PETHREAD thread
Definition: btrfs_drv.h:548
LIST_ENTRY list_entry
Definition: btrfs_drv.h:549
IO_STATUS_BLOCK iosb
Definition: btrfs.c:131
KEVENT Event
Definition: btrfs.c:130
KEVENT cleared_event
Definition: btrfs_drv.h:365
bool cancelling
Definition: btrfs_drv.h:366
Definition: parse.h:23
uint16_t csum_type
Definition: btrfs.h:247
uint32_t sector_size
Definition: btrfs.h:238
BTRFS_UUID uuid
Definition: btrfs.h:225
uint32_t node_size
Definition: btrfs.h:239
uint8_t checksum[32]
Definition: btrfs.h:224
uint64_t magic
Definition: btrfs.h:228
uint64_t generation
Definition: btrfs.h:229
uint64_t num_devices
Definition: btrfs.h:237
LIST_ENTRY list_entry
Definition: btrfs_drv.h:624
USHORT size
Definition: btrfs_drv.h:623
void * data
Definition: btrfs_drv.h:622
tree_data * item
Definition: btrfs_drv.h:509
tree * tree
Definition: btrfs_drv.h:508
BTRFS_UUID chunk_tree_uuid
Definition: btrfs.h:158
BTRFS_UUID fs_uuid
Definition: btrfs.h:155
PSID sid
Definition: btrfs_drv.h:904
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:858
uint64_t size
Definition: btrfs_drv.h:860
uint64_t devid
Definition: btrfs_drv.h:855
ULONG part_num
Definition: btrfs_drv.h:865
ULONG disk_num
Definition: btrfs_drv.h:864
bool seeding
Definition: btrfs_drv.h:861
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:857
BTRFS_UUID uuid
Definition: btrfs_drv.h:854
#define max(a, b)
Definition: svc.c:63
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3604
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
int64_t LONGLONG
Definition: typedefs.h:68
void * PVOID
Definition: typedefs.h:50
#define __stdcall
Definition: typedefs.h:25
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define ATA_FLAGS_DATA_IN
Definition: uata_ctl.h:222
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_INVALID_VOLUME_LABEL
Definition: udferr_usr.h:156
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_Inout_ PERBANDINFO * pbi
Definition: winddi.h:3917
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
@ DelayedWorkQueue
Definition: extypes.h:190
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
@ BusRelations
Definition: iotypes.h:2152
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IRP_DEALLOCATE_BUFFER
#define IRP_MJ_QUERY_EA
#define IRP_INPUT_OPERATION
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define FILE_ACTION_MODIFIED
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IO_TYPE_VPB
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_MJ_SET_VOLUME_INFORMATION
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define FILE_ACTION_REMOVED
struct _FILE_FS_OBJECTID_INFORMATION FILE_FS_OBJECTID_INFORMATION
#define IRP_MJ_QUERY_SECURITY
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define IRP_MJ_SET_EA
#define IRP_MJ_SYSTEM_CONTROL
struct _VPB VPB
@ EventCategoryDeviceInterfaceChange
Definition: iotypes.h:1226
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MN_SET_POWER
#define IRP_MJ_FLUSH_BUFFERS
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4408
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define IRP_MJ_SHUTDOWN
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define IRP_MJ_POWER
#define IRP_BUFFERED_IO
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
#define IRP_MJ_SET_SECURITY
_In_ SYSTEM_POWER_STATE SystemPowerState
Definition: iotypes.h:7519
#define IRP_NOCACHE
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define IRP_MN_QUERY_POWER
#define IRP_MJ_CLEANUP
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1239
@ UserRequest
Definition: ketypes.h:421
@ Executive
Definition: ketypes.h:415
@ IoWriteAccess
Definition: ketypes.h:864
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
struct _OSVERSIONINFOW RTL_OSVERSIONINFOW
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555