ReactOS 0.4.15-dev-7788-g1ad9096
fsctl.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#include "btrfs_drv.h"
19#include "btrfsioctl.h"
20#include "crc32c.h"
21#include <ntddstor.h>
22#include <ntdddisk.h>
23#ifndef __REACTOS__
24#include <sys/stat.h>
25#endif
26
27#ifndef FSCTL_CSV_CONTROL
28#define FSCTL_CSV_CONTROL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 181, METHOD_BUFFERED, FILE_ANY_ACCESS)
29#endif
30
31#ifndef FSCTL_QUERY_VOLUME_CONTAINER_STATE
32#define FSCTL_QUERY_VOLUME_CONTAINER_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 228, METHOD_BUFFERED, FILE_ANY_ACCESS)
33#endif
34
35#define DOTDOT ".."
36
37#define SEF_AVOID_PRIVILEGE_CHECK 0x08 // on MSDN but not in any header files(?)
38
39#define SEF_SACL_AUTO_INHERIT 0x02
40
41extern LIST_ENTRY VcbList;
46
48
51 fcb* fcb;
52
53 if (length < sizeof(btrfs_get_file_ids))
55
56 if (!FileObject)
58
59 fcb = FileObject->FsContext;
60
61 if (!fcb)
63
64 bgfi = data;
65
66 bgfi->subvol = fcb->subvol->id;
67 bgfi->inode = fcb->inode;
68 bgfi->top = fcb->Vcb->root_fileref->fcb == fcb ? true : false;
69
70 return STATUS_SUCCESS;
71}
72
73static void get_uuid(BTRFS_UUID* uuid) {
74 LARGE_INTEGER seed;
75 uint8_t i;
76
78
79 for (i = 0; i < 16; i+=2) {
81
82 uuid->uuid[i] = (rand & 0xff00) >> 8;
83 uuid->uuid[i+1] = rand & 0xff;
84 }
85}
86
88 uint8_t* buf;
91 LIST_ENTRY* le;
92 tree t;
93 tree_header* th;
94 chunk* c;
95
96 buf = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG);
97 if (!buf) {
98 ERR("out of memory\n");
100 }
101
102 wtc.parity1 = wtc.parity2 = wtc.scratch = NULL;
103 wtc.mdl = wtc.parity1_mdl = wtc.parity2_mdl = NULL;
104
105 Status = read_data(Vcb, addr, Vcb->superblock.node_size, NULL, true, buf, NULL, NULL, Irp, 0, false, NormalPagePriority);
106 if (!NT_SUCCESS(Status)) {
107 ERR("read_data returned %08lx\n", Status);
108 goto end;
109 }
110
111 th = (tree_header*)buf;
112
113 RtlZeroMemory(&t, sizeof(tree));
114 t.root = subvol;
115 t.header.level = th->level;
116 t.header.tree_id = t.root->id;
117
119 if (!NT_SUCCESS(Status)) {
120 ERR("get_tree_new_address returned %08lx\n", Status);
121 goto end;
122 }
123
124 if (!t.has_new_address) {
125 ERR("tree new address not set\n");
127 goto end;
128 }
129
130 c = get_chunk_from_address(Vcb, t.new_address);
131
132 if (c)
133 c->used += Vcb->superblock.node_size;
134 else {
135 ERR("could not find chunk for address %I64x\n", t.new_address);
137 goto end;
138 }
139
140 th->address = t.new_address;
141 th->tree_id = subvol->id;
142 th->generation = Vcb->superblock.generation;
143 th->fs_uuid = Vcb->superblock.metadata_uuid;
144
145 if (th->level == 0) {
146 uint32_t i;
147 leaf_node* ln = (leaf_node*)&th[1];
148
149 for (i = 0; i < th->num_items; i++) {
150 if (ln[i].key.obj_type == TYPE_EXTENT_DATA && ln[i].size >= sizeof(EXTENT_DATA) && ln[i].offset + ln[i].size <= Vcb->superblock.node_size - sizeof(tree_header)) {
151 EXTENT_DATA* ed = (EXTENT_DATA*)(((uint8_t*)&th[1]) + ln[i].offset);
152
153 if ((ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) && ln[i].size >= sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
154 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ed->data[0];
155
156 if (ed2->size != 0) { // not sparse
157 Status = increase_extent_refcount_data(Vcb, ed2->address, ed2->size, subvol->id, ln[i].key.obj_id, ln[i].key.offset - ed2->offset, 1, Irp);
158
159 if (!NT_SUCCESS(Status)) {
160 ERR("increase_extent_refcount_data returned %08lx\n", Status);
161 goto end;
162 }
163 }
164 }
165 }
166 }
167 } else {
168 uint32_t i;
169 internal_node* in = (internal_node*)&th[1];
170
171 for (i = 0; i < th->num_items; i++) {
172 TREE_BLOCK_REF tbr;
173
174 tbr.offset = subvol->id;
175
176 Status = increase_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_TREE_BLOCK_REF, &tbr, NULL, th->level - 1, Irp);
177 if (!NT_SUCCESS(Status)) {
178 ERR("increase_extent_refcount returned %08lx\n", Status);
179 goto end;
180 }
181 }
182 }
183
185
188 wtc.stripes_left = 0;
189
190 Status = write_data(Vcb, t.new_address, buf, Vcb->superblock.node_size, &wtc, NULL, NULL, false, 0, NormalPagePriority);
191 if (!NT_SUCCESS(Status)) {
192 ERR("write_data returned %08lx\n", Status);
193 goto end;
194 }
195
196 if (wtc.stripes.Flink != &wtc.stripes) {
197 bool need_wait = false;
198
199 // launch writes and wait
200 le = wtc.stripes.Flink;
201 while (le != &wtc.stripes) {
203
204 if (stripe->status != WriteDataStatus_Ignore) {
205 need_wait = true;
207 }
208
209 le = le->Flink;
210 }
211
212 if (need_wait)
214
215 le = wtc.stripes.Flink;
216 while (le != &wtc.stripes) {
218
219 if (stripe->status != WriteDataStatus_Ignore && !NT_SUCCESS(stripe->iosb.Status)) {
220 Status = stripe->iosb.Status;
222 break;
223 }
224
225 le = le->Flink;
226 }
227
229 buf = NULL;
230 }
231
232 if (NT_SUCCESS(Status))
233 *newaddr = t.new_address;
234
235end:
236
237 if (buf)
239
240 return Status;
241}
242
243void flush_subvol_fcbs(root* subvol) {
244 LIST_ENTRY* le = subvol->fcbs.Flink;
245
246 if (IsListEmpty(&subvol->fcbs))
247 return;
248
249 while (le != &subvol->fcbs) {
250 struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
252
254 CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
255
256 le = le->Flink;
257 }
258}
259
262 uint64_t id;
264 root *r, *subvol = subvol_fcb->subvol;
265 KEY searchkey;
267 uint64_t address, *root_num;
270 fcb* fcb = parent->FsContext;
271 ccb* ccb = parent->FsContext2;
272 LIST_ENTRY* le;
273 file_ref *fileref, *fr;
274 dir_child* dc = NULL;
275
276 if (!ccb) {
277 ERR("error - ccb was NULL\n");
279 }
280
281 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
282 WARN("insufficient privileges\n");
284 }
285
287
288 if (fileref->fcb == Vcb->dummy_fcb)
290
291 // flush open files on this subvol
292
294
295 // flush metadata
296
297 if (Vcb->need_write)
299 else
301
303
304 if (!NT_SUCCESS(Status)) {
305 ERR("do_write returned %08lx\n", Status);
306 return Status;
307 }
308
310
311 // create new root
312
313 id = InterlockedIncrement64(&Vcb->root_root->lastinode);
314 Status = create_root(Vcb, id, &r, true, Vcb->superblock.generation, Irp);
315
316 if (!NT_SUCCESS(Status)) {
317 ERR("create_root returned %08lx\n", Status);
318 goto end;
319 }
320
321 r->lastinode = subvol->lastinode;
322
323 if (!Vcb->uuid_root) {
324 root* uuid_root;
325
326 TRACE("uuid root doesn't exist, creating it\n");
327
328 Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
329
330 if (!NT_SUCCESS(Status)) {
331 ERR("create_root returned %08lx\n", Status);
332 goto end;
333 }
334
335 Vcb->uuid_root = uuid_root;
336 }
337
339 if (!root_num) {
340 ERR("out of memory\n");
342 goto end;
343 }
344
345 tp.tree = NULL;
346
347 do {
348 get_uuid(&r->root_item.uuid);
349
350 RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
351 searchkey.obj_type = TYPE_SUBVOL_UUID;
352 RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
353
354 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
355 } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
356
357 *root_num = r->id;
358
359 Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
360 if (!NT_SUCCESS(Status)) {
361 ERR("insert_tree_item returned %08lx\n", Status);
362 ExFreePool(root_num);
363 goto end;
364 }
365
366 searchkey.obj_id = r->id;
367 searchkey.obj_type = TYPE_ROOT_ITEM;
368 searchkey.offset = 0xffffffffffffffff;
369
370 Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
371 if (!NT_SUCCESS(Status)) {
372 ERR("error - find_item returned %08lx\n", Status);
373 goto end;
374 }
375
376 Status = snapshot_tree_copy(Vcb, subvol->root_item.block_number, r, &address, Irp, &rollback);
377 if (!NT_SUCCESS(Status)) {
378 ERR("snapshot_tree_copy returned %08lx\n", Status);
379 goto end;
380 }
381
384
385 r->root_item.inode.generation = 1;
386 r->root_item.inode.st_size = 3;
387 r->root_item.inode.st_blocks = subvol->root_item.inode.st_blocks;
388 r->root_item.inode.st_nlink = 1;
389 r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
390 r->root_item.inode.flags = 0x80000000; // FIXME - find out what these mean
391 r->root_item.inode.flags_ro = 0xffffffff; // FIXME - find out what these mean
392 r->root_item.generation = Vcb->superblock.generation;
393 r->root_item.objid = subvol->root_item.objid;
394 r->root_item.block_number = address;
395 r->root_item.bytes_used = subvol->root_item.bytes_used;
396 r->root_item.last_snapshot_generation = Vcb->superblock.generation;
397 r->root_item.root_level = subvol->root_item.root_level;
398 r->root_item.generation2 = Vcb->superblock.generation;
399 r->root_item.parent_uuid = subvol->root_item.uuid;
400 r->root_item.ctransid = subvol->root_item.ctransid;
401 r->root_item.otransid = Vcb->superblock.generation;
402 r->root_item.ctime = subvol->root_item.ctime;
403 r->root_item.otime = now;
404
405 if (readonly)
406 r->root_item.flags |= BTRFS_SUBVOL_READONLY;
407
408 r->treeholder.address = address;
409
410 // FIXME - do we need to copy over the send and receive fields too?
411
412 if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
413 ERR("error - could not find ROOT_ITEM for subvol %I64x\n", r->id);
415 goto end;
416 }
417
418 RtlCopyMemory(tp.item->data, &r->root_item, sizeof(ROOT_ITEM));
419
420 // update ROOT_ITEM of original subvol
421
422 subvol->root_item.last_snapshot_generation = Vcb->superblock.generation;
423
425
426 // create fileref for entry in other subvolume
427
428 fr = create_fileref(Vcb);
429 if (!fr) {
430 ERR("out of memory\n");
432 goto end;
433 }
434
435 Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, false, fcb, &fr->fcb, PagedPool, Irp);
436 if (!NT_SUCCESS(Status)) {
437 ERR("open_fcb returned %08lx\n", Status);
438 free_fileref(fr);
439 goto end;
440 }
441
442 fr->parent = fileref;
443
444 Status = add_dir_child(fileref->fcb, r->id, true, utf8, name, BTRFS_TYPE_DIRECTORY, &dc);
445 if (!NT_SUCCESS(Status))
446 WARN("add_dir_child returned %08lx\n", Status);
447
448 fr->dc = dc;
449 dc->fileref = fr;
450
451 ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
452 InsertTailList(&fileref->children, &fr->list_entry);
453 ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
454
456
457 fr->created = true;
459
460 if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
461 fr->fcb->fileref = fr;
462
463 fr->fcb->subvol->parent = fileref->fcb->subvol->id;
464
465 free_fileref(fr);
466
467 // change fcb's INODE_ITEM
468
469 fcb->inode_item.transid = Vcb->superblock.generation;
471 fcb->inode_item.st_size += utf8->Length * 2;
472
475
478
479 fcb->inode_item_changed = true;
481
482 fcb->subvol->root_item.ctime = now;
483 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
484
487
488 le = subvol->fcbs.Flink;
489 while (le != &subvol->fcbs) {
490 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
491 LIST_ENTRY* le2 = fcb2->extents.Flink;
492
493 while (le2 != &fcb2->extents) {
495
496 if (!ext->ignore)
497 ext->unique = false;
498
499 le2 = le2->Flink;
500 }
501
502 le = le->Flink;
503 }
504
506
508
509 if (!NT_SUCCESS(Status))
510 ERR("do_write returned %08lx\n", Status);
511
512end:
513 if (NT_SUCCESS(Status))
515 else
517
518 return Status;
519}
520
522 PFILE_OBJECT subvol_obj;
525 fcb* subvol_fcb;
526 HANDLE subvolh;
527 bool readonly, posix;
528 ANSI_STRING utf8;
529 UNICODE_STRING nameus;
530 ULONG len;
531 fcb* fcb;
532 ccb* ccb;
533 file_ref *fileref, *fr2;
534
535#if defined(_WIN64)
536 if (IoIs32bitProcess(Irp)) {
538
541
544
545 subvolh = Handle32ToHandle(bcs32->subvol);
546
547 nameus.Buffer = bcs32->name;
548 nameus.Length = nameus.MaximumLength = bcs32->namelen;
549
550 readonly = bcs32->readonly;
551 posix = bcs32->posix;
552 } else {
553#endif
556
559
560 subvolh = bcs->subvol;
561
562 nameus.Buffer = bcs->name;
563 nameus.Length = nameus.MaximumLength = bcs->namelen;
564
565 readonly = bcs->readonly;
566 posix = bcs->posix;
567#if defined(_WIN64)
568 }
569#endif
570
571 if (!subvolh)
573
574 if (!FileObject || !FileObject->FsContext)
576
577 fcb = FileObject->FsContext;
578 ccb = FileObject->FsContext2;
579
580 if (!fcb || !ccb || fcb->type != BTRFS_TYPE_DIRECTORY)
582
584
585 if (!fileref) {
586 ERR("fileref was NULL\n");
588 }
589
590 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
591 WARN("insufficient privileges\n");
593 }
594
595 if (Vcb->readonly)
597
600
601 Status = check_file_name_valid(&nameus, posix, false);
602 if (!NT_SUCCESS(Status))
603 return Status;
604
605 utf8.Buffer = NULL;
606
607 Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
608 if (!NT_SUCCESS(Status)) {
609 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
610 return Status;
611 }
612
613 if (len == 0) {
614 ERR("utf16_to_utf8 returned a length of 0\n");
616 }
617
618 if (len > 0xffff) {
619 ERR("len was too long\n");
621 }
622
623 utf8.MaximumLength = utf8.Length = (USHORT)len;
625
626 if (!utf8.Buffer) {
627 ERR("out of memory\n");
629 }
630
631 Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
632 if (!NT_SUCCESS(Status)) {
633 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
634 goto end2;
635 }
636
637 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
638
639 // no need for fcb_lock as we have tree_lock exclusively
640 Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || posix, Irp);
641
642 if (NT_SUCCESS(Status)) {
643 if (!fr2->deleted) {
644 WARN("file already exists\n");
645 free_fileref(fr2);
647 goto end3;
648 } else
649 free_fileref(fr2);
651 ERR("open_fileref returned %08lx\n", Status);
652 goto end3;
653 }
654
655 Status = ObReferenceObjectByHandle(subvolh, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&subvol_obj, NULL);
656 if (!NT_SUCCESS(Status)) {
657 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
658 goto end3;
659 }
660
661 if (subvol_obj->DeviceObject != FileObject->DeviceObject) {
663 goto end;
664 }
665
666 subvol_fcb = subvol_obj->FsContext;
667 if (!subvol_fcb) {
669 goto end;
670 }
671
672 if (subvol_fcb->inode != subvol_fcb->subvol->root_item.objid) {
673 WARN("handle inode was %I64x, expected %I64x\n", subvol_fcb->inode, subvol_fcb->subvol->root_item.objid);
675 goto end;
676 }
677
678 ccb = subvol_obj->FsContext2;
679
680 if (!ccb) {
682 goto end;
683 }
684
685 if (!(ccb->access & FILE_TRAVERSE)) {
686 WARN("insufficient privileges\n");
688 goto end;
689 }
690
691 if (fcb == Vcb->dummy_fcb) {
693 goto end;
694 }
695
696 // clear unique flag on extents of open files in subvol
697 if (!IsListEmpty(&subvol_fcb->subvol->fcbs)) {
698 LIST_ENTRY* le = subvol_fcb->subvol->fcbs.Flink;
699
700 while (le != &subvol_fcb->subvol->fcbs) {
701 struct _fcb* openfcb = CONTAINING_RECORD(le, struct _fcb, list_entry);
702 LIST_ENTRY* le2;
703
704 le2 = openfcb->extents.Flink;
705
706 while (le2 != &openfcb->extents) {
708
709 ext->unique = false;
710
711 le2 = le2->Flink;
712 }
713
714 le = le->Flink;
715 }
716 }
717
718 Status = do_create_snapshot(Vcb, FileObject, subvol_fcb, &utf8, &nameus, readonly, Irp);
719
720 if (NT_SUCCESS(Status)) {
721 file_ref* fr;
722
723 Status = open_fileref(Vcb, &fr, &nameus, fileref, false, NULL, NULL, PagedPool, false, Irp);
724
725 if (!NT_SUCCESS(Status)) {
726 ERR("open_fileref returned %08lx\n", Status);
728 } else {
730 free_fileref(fr);
731 }
732 }
733
734end:
735 ObDereferenceObject(subvol_obj);
736
737end3:
738 ExReleaseResourceLite(&Vcb->tree_lock);
739
740end2:
741 ExFreePool(utf8.Buffer);
742
743 return Status;
744}
745
748 fcb *fcb, *rootfcb = NULL;
749 ccb* ccb;
752 uint64_t id;
753 root* r = NULL;
756 ULONG len;
757 uint16_t irsize;
758 UNICODE_STRING nameus;
759 ANSI_STRING utf8;
760 INODE_REF* ir;
761 KEY searchkey;
764 PSID owner;
765 BOOLEAN defaulted;
766 uint64_t* root_num;
767 file_ref *fr = NULL, *fr2;
768 dir_child* dc = NULL;
769
770 fcb = FileObject->FsContext;
771 if (!fcb) {
772 ERR("error - fcb was NULL\n");
774 }
775
776 ccb = FileObject->FsContext2;
777 if (!ccb) {
778 ERR("error - ccb was NULL\n");
780 }
781
783
784 if (fcb->type != BTRFS_TYPE_DIRECTORY) {
785 ERR("parent FCB was not a directory\n");
787 }
788
789 if (!fileref) {
790 ERR("fileref was NULL\n");
792 }
793
794 if (fileref->deleted || fcb->deleted) {
795 ERR("parent has been deleted\n");
796 return STATUS_FILE_DELETED;
797 }
798
799 if (!(ccb->access & FILE_ADD_SUBDIRECTORY)) {
800 WARN("insufficient privileges\n");
802 }
803
804 if (Vcb->readonly)
806
809
810 if (fcb == Vcb->dummy_fcb)
812
813 if (!data || datalen < sizeof(btrfs_create_subvol))
815
817
820
821 nameus.Length = nameus.MaximumLength = bcs->namelen;
822 nameus.Buffer = bcs->name;
823
824 Status = check_file_name_valid(&nameus, bcs->posix, false);
825 if (!NT_SUCCESS(Status))
826 return Status;
827
828 utf8.Buffer = NULL;
829
830 Status = utf16_to_utf8(NULL, 0, &len, nameus.Buffer, nameus.Length);
831 if (!NT_SUCCESS(Status)) {
832 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
833 return Status;
834 }
835
836 if (len == 0) {
837 ERR("utf16_to_utf8 returned a length of 0\n");
839 }
840
841 if (len > 0xffff) {
842 ERR("len was too long\n");
844 }
845
846 utf8.MaximumLength = utf8.Length = (USHORT)len;
848
849 if (!utf8.Buffer) {
850 ERR("out of memory\n");
852 }
853
854 Status = utf16_to_utf8(utf8.Buffer, len, &len, nameus.Buffer, nameus.Length);
855 if (!NT_SUCCESS(Status)) {
856 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
857 goto end2;
858 }
859
860 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
861
864
865 // no need for fcb_lock as we have tree_lock exclusively
866 Status = open_fileref(fcb->Vcb, &fr2, &nameus, fileref, false, NULL, NULL, PagedPool, ccb->case_sensitive || bcs->posix, Irp);
867
868 if (NT_SUCCESS(Status)) {
869 if (!fr2->deleted) {
870 WARN("file already exists\n");
871 free_fileref(fr2);
873 goto end;
874 } else
875 free_fileref(fr2);
877 ERR("open_fileref returned %08lx\n", Status);
878 goto end;
879 }
880
881 id = InterlockedIncrement64(&Vcb->root_root->lastinode);
882 Status = create_root(Vcb, id, &r, false, 0, Irp);
883
884 if (!NT_SUCCESS(Status)) {
885 ERR("create_root returned %08lx\n", Status);
886 goto end;
887 }
888
889 TRACE("created root %I64x\n", id);
890
891 if (!Vcb->uuid_root) {
892 root* uuid_root;
893
894 TRACE("uuid root doesn't exist, creating it\n");
895
896 Status = create_root(Vcb, BTRFS_ROOT_UUID, &uuid_root, false, 0, Irp);
897
898 if (!NT_SUCCESS(Status)) {
899 ERR("create_root returned %08lx\n", Status);
900 goto end;
901 }
902
903 Vcb->uuid_root = uuid_root;
904 }
905
907 if (!root_num) {
908 ERR("out of memory\n");
910 goto end;
911 }
912
913 tp.tree = NULL;
914
915 do {
916 get_uuid(&r->root_item.uuid);
917
918 RtlCopyMemory(&searchkey.obj_id, &r->root_item.uuid, sizeof(uint64_t));
919 searchkey.obj_type = TYPE_SUBVOL_UUID;
920 RtlCopyMemory(&searchkey.offset, &r->root_item.uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
921
922 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
923 } while (NT_SUCCESS(Status) && !keycmp(searchkey, tp.item->key));
924
925 *root_num = r->id;
926
927 Status = insert_tree_item(Vcb, Vcb->uuid_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, root_num, sizeof(uint64_t), NULL, Irp);
928 if (!NT_SUCCESS(Status)) {
929 ERR("insert_tree_item returned %08lx\n", Status);
930 ExFreePool(root_num);
931 goto end;
932 }
933
934 r->root_item.inode.generation = 1;
935 r->root_item.inode.st_size = 3;
936 r->root_item.inode.st_blocks = Vcb->superblock.node_size;
937 r->root_item.inode.st_nlink = 1;
938 r->root_item.inode.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 40755
939 r->root_item.inode.flags = 0x80000000; // FIXME - find out what these mean
940 r->root_item.inode.flags_ro = 0xffffffff; // FIXME - find out what these mean
941
942 if (bcs->readonly)
943 r->root_item.flags |= BTRFS_SUBVOL_READONLY;
944
945 r->root_item.objid = SUBVOL_ROOT_INODE;
946 r->root_item.bytes_used = Vcb->superblock.node_size;
947 r->root_item.ctransid = Vcb->superblock.generation;
948 r->root_item.otransid = Vcb->superblock.generation;
949 r->root_item.ctime = now;
950 r->root_item.otime = now;
951
952 // add .. inode to new subvol
953
954 rootfcb = create_fcb(Vcb, PagedPool);
955 if (!rootfcb) {
956 ERR("out of memory\n");
958 goto end;
959 }
960
961 rootfcb->Vcb = Vcb;
962
963 rootfcb->subvol = r;
964 rootfcb->type = BTRFS_TYPE_DIRECTORY;
965 rootfcb->inode = SUBVOL_ROOT_INODE;
966 rootfcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&rootfcb->inode, sizeof(uint64_t)); // FIXME - we can hardcode this
967
968 rootfcb->inode_item.generation = Vcb->superblock.generation;
969 rootfcb->inode_item.transid = Vcb->superblock.generation;
970 rootfcb->inode_item.st_nlink = 1;
971 rootfcb->inode_item.st_mode = __S_IFDIR | inherit_mode(fileref->fcb, true);
972 rootfcb->inode_item.st_atime = rootfcb->inode_item.st_ctime = rootfcb->inode_item.st_mtime = rootfcb->inode_item.otime = now;
973 rootfcb->inode_item.st_gid = GID_NOBODY;
974
975 rootfcb->atts = get_file_attributes(Vcb, rootfcb->subvol, rootfcb->inode, rootfcb->type, false, true, Irp);
976
977 if (r->root_item.flags & BTRFS_SUBVOL_READONLY)
978 rootfcb->atts |= FILE_ATTRIBUTE_READONLY;
979
980 SeCaptureSubjectContext(&subjcont);
981
982 Status = SeAssignSecurity(fcb->sd, NULL, (void**)&rootfcb->sd, true, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
983
984 if (!NT_SUCCESS(Status)) {
985 ERR("SeAssignSecurity returned %08lx\n", Status);
986 goto end;
987 }
988
989 if (!rootfcb->sd) {
990 ERR("SeAssignSecurity returned NULL security descriptor\n");
992 goto end;
993 }
994
995 Status = RtlGetOwnerSecurityDescriptor(rootfcb->sd, &owner, &defaulted);
996 if (!NT_SUCCESS(Status)) {
997 ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
998 rootfcb->inode_item.st_uid = UID_NOBODY;
999 rootfcb->sd_dirty = true;
1000 } else {
1001 rootfcb->inode_item.st_uid = sid_to_uid(owner);
1002 rootfcb->sd_dirty = rootfcb->inode_item.st_uid == UID_NOBODY;
1003 }
1004
1005 find_gid(rootfcb, fileref->fcb, &subjcont);
1006
1007 rootfcb->inode_item_changed = true;
1008
1009 acquire_fcb_lock_exclusive(Vcb);
1010 add_fcb_to_subvol(rootfcb);
1011 InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
1012 r->fcbs_version++;
1013 release_fcb_lock(Vcb);
1014
1015 rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
1016 rootfcb->Header.AllocationSize.QuadPart = 0;
1017 rootfcb->Header.FileSize.QuadPart = 0;
1018 rootfcb->Header.ValidDataLength.QuadPart = 0;
1019
1020 rootfcb->created = true;
1021
1022 if (fileref->fcb->inode_item.flags & BTRFS_INODE_COMPRESS)
1024
1025 rootfcb->prop_compression = fileref->fcb->prop_compression;
1027
1028 r->lastinode = rootfcb->inode;
1029
1030 // add INODE_REF
1031
1032 irsize = (uint16_t)(offsetof(INODE_REF, name[0]) + sizeof(DOTDOT) - 1);
1034 if (!ir) {
1035 ERR("out of memory\n");
1037 goto end;
1038 }
1039
1040 ir->index = 0;
1041 ir->n = sizeof(DOTDOT) - 1;
1042 RtlCopyMemory(ir->name, DOTDOT, ir->n);
1043
1044 Status = insert_tree_item(Vcb, r, r->root_item.objid, TYPE_INODE_REF, r->root_item.objid, ir, irsize, NULL, Irp);
1045 if (!NT_SUCCESS(Status)) {
1046 ERR("insert_tree_item returned %08lx\n", Status);
1047 ExFreePool(ir);
1048 goto end;
1049 }
1050
1051 // create fileref for entry in other subvolume
1052
1053 fr = create_fileref(Vcb);
1054 if (!fr) {
1055 ERR("out of memory\n");
1056
1057 reap_fcb(rootfcb);
1058
1060 goto end;
1061 }
1062
1063 fr->fcb = rootfcb;
1064
1065 mark_fcb_dirty(rootfcb);
1066
1067 fr->parent = fileref;
1068
1069 Status = add_dir_child(fileref->fcb, r->id, true, &utf8, &nameus, BTRFS_TYPE_DIRECTORY, &dc);
1070 if (!NT_SUCCESS(Status))
1071 WARN("add_dir_child returned %08lx\n", Status);
1072
1073 fr->dc = dc;
1074 dc->fileref = fr;
1075
1077 if (!fr->fcb->hash_ptrs) {
1078 ERR("out of memory\n");
1079 free_fileref(fr);
1081 goto end;
1082 }
1083
1084 RtlZeroMemory(fr->fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
1085
1087 if (!fr->fcb->hash_ptrs_uc) {
1088 ERR("out of memory\n");
1089 free_fileref(fr);
1091 goto end;
1092 }
1093
1094 RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
1095
1096 ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, true);
1097 InsertTailList(&fileref->children, &fr->list_entry);
1098 ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1099
1101
1102 if (fr->fcb->type == BTRFS_TYPE_DIRECTORY)
1103 fr->fcb->fileref = fr;
1104
1105 fr->created = true;
1107
1108 // change fcb->subvol's ROOT_ITEM
1109
1110 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
1111 fcb->subvol->root_item.ctime = now;
1112
1113 // change fcb's INODE_ITEM
1114
1115 fcb->inode_item.transid = Vcb->superblock.generation;
1116 fcb->inode_item.st_size += utf8.Length * 2;
1118
1121
1124
1125 fcb->inode_item_changed = true;
1127
1128 fr->fcb->subvol->parent = fcb->subvol->id;
1129
1131
1132end:
1133 if (!NT_SUCCESS(Status)) {
1134 if (fr) {
1135 fr->deleted = true;
1137 } else if (rootfcb) {
1138 rootfcb->deleted = true;
1139 mark_fcb_dirty(rootfcb);
1140 }
1141
1142 if (r) {
1143 RemoveEntryList(&r->list_entry);
1144 InsertTailList(&Vcb->drop_roots, &r->list_entry);
1145 }
1146 }
1147
1148 ExReleaseResourceLite(&Vcb->tree_lock);
1149
1150 if (NT_SUCCESS(Status)) {
1153 }
1154
1155end2:
1156 if (fr)
1157 free_fileref(fr);
1158
1159 return Status;
1160}
1161
1163 btrfs_inode_info* bii = data;
1164 fcb* fcb;
1165 ccb* ccb;
1166 bool old_style;
1167
1168 if (length < offsetof(btrfs_inode_info, disk_size_zstd))
1170
1171 if (!FileObject)
1173
1174 fcb = FileObject->FsContext;
1175
1176 if (!fcb)
1178
1179 ccb = FileObject->FsContext2;
1180
1181 if (!ccb)
1183
1184 if (!(ccb->access & FILE_READ_ATTRIBUTES)) {
1185 WARN("insufficient privileges\n");
1186 return STATUS_ACCESS_DENIED;
1187 }
1188
1189 if (fcb->ads)
1190 fcb = ccb->fileref->parent->fcb;
1191
1192 old_style = length < offsetof(btrfs_inode_info, sparse_size) + sizeof(((btrfs_inode_info*)NULL)->sparse_size);
1193
1194 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
1195
1196 bii->subvol = fcb->subvol->id;
1197 bii->inode = fcb->inode;
1198 bii->top = fcb->Vcb->root_fileref->fcb == fcb ? true : false;
1199 bii->type = fcb->type;
1200 bii->st_uid = fcb->inode_item.st_uid;
1201 bii->st_gid = fcb->inode_item.st_gid;
1202 bii->st_mode = fcb->inode_item.st_mode;
1203
1204 if (fcb->inode_item.st_rdev == 0)
1205 bii->st_rdev = 0;
1206 else
1207 bii->st_rdev = makedev((fcb->inode_item.st_rdev & 0xFFFFFFFFFFF) >> 20, fcb->inode_item.st_rdev & 0xFFFFF);
1208
1209 bii->flags = fcb->inode_item.flags;
1210
1211 bii->inline_length = 0;
1212 bii->disk_size_uncompressed = 0;
1213 bii->disk_size_zlib = 0;
1214 bii->disk_size_lzo = 0;
1215
1216 if (!old_style) {
1217 bii->disk_size_zstd = 0;
1218 bii->sparse_size = 0;
1219 }
1220
1221 if (fcb->type != BTRFS_TYPE_DIRECTORY) {
1222 uint64_t last_end = 0;
1223 LIST_ENTRY* le;
1224 bool extents_inline = false;
1225
1226 le = fcb->extents.Flink;
1227 while (le != &fcb->extents) {
1229
1230 if (!ext->ignore) {
1231 if (!old_style && ext->offset > last_end)
1232 bii->sparse_size += ext->offset - last_end;
1233
1234 if (ext->extent_data.type == EXTENT_TYPE_INLINE) {
1235 bii->inline_length += ext->datalen - (uint16_t)offsetof(EXTENT_DATA, data[0]);
1236 last_end = ext->offset + ext->extent_data.decoded_size;
1237 extents_inline = true;
1238 } else {
1239 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
1240
1241 // FIXME - compressed extents with a hole in them are counted more than once
1242 if (ed2->size != 0) {
1243 switch (ext->extent_data.compression) {
1245 bii->disk_size_uncompressed += ed2->num_bytes;
1246 break;
1247
1249 bii->disk_size_zlib += ed2->size;
1250 break;
1251
1253 bii->disk_size_lzo += ed2->size;
1254 break;
1255
1257 if (!old_style)
1258 bii->disk_size_zstd += ed2->size;
1259 break;
1260 }
1261 }
1262
1263 last_end = ext->offset + ed2->num_bytes;
1264 }
1265 }
1266
1267 le = le->Flink;
1268 }
1269
1270 if (!extents_inline && !old_style && sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size) > last_end)
1271 bii->sparse_size += sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size) - last_end;
1272
1273 if (length >= offsetof(btrfs_inode_info, num_extents) + sizeof(((btrfs_inode_info*)NULL)->num_extents)) {
1274 EXTENT_DATA2* last_ed2 = NULL;
1275
1276 le = fcb->extents.Flink;
1277
1278 bii->num_extents = 0;
1279
1280 while (le != &fcb->extents) {
1282
1283 if (!ext->ignore && ext->extent_data.type != EXTENT_TYPE_INLINE) {
1284 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
1285
1286 if (ed2->size != 0) {
1287 if (!last_ed2 || ed2->offset != last_ed2->offset + last_ed2->num_bytes)
1288 bii->num_extents++;
1289
1290 last_ed2 = ed2;
1291 } else
1292 last_ed2 = NULL;
1293 }
1294
1295 le = le->Flink;
1296 }
1297 }
1298 }
1299
1300 switch (fcb->prop_compression) {
1303 break;
1304
1307 break;
1308
1311 break;
1312
1313 default:
1315 break;
1316 }
1317
1318 ExReleaseResourceLite(fcb->Header.Resource);
1319
1320 return STATUS_SUCCESS;
1321}
1322
1324 btrfs_set_inode_info* bsii = data;
1326 fcb* fcb;
1327 ccb* ccb;
1328
1329 if (length < sizeof(btrfs_set_inode_info))
1331
1332 if (!FileObject)
1334
1335 fcb = FileObject->FsContext;
1336
1337 if (!fcb)
1339
1340 ccb = FileObject->FsContext2;
1341
1342 if (!ccb)
1344
1345 if (bsii->flags_changed && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
1346 WARN("insufficient privileges\n");
1347 return STATUS_ACCESS_DENIED;
1348 }
1349
1350 if ((bsii->mode_changed || bsii->uid_changed || bsii->gid_changed) && !(ccb->access & WRITE_DAC)) {
1351 WARN("insufficient privileges\n");
1352 return STATUS_ACCESS_DENIED;
1353 }
1354
1357
1358 if (fcb->ads)
1359 fcb = ccb->fileref->parent->fcb;
1360
1362 WARN("trying to change inode on readonly subvolume\n");
1363 return STATUS_ACCESS_DENIED;
1364 }
1365
1366 // nocow and compression are mutually exclusive
1367 if (bsii->flags_changed && bsii->flags & BTRFS_INODE_NODATACOW && bsii->flags & BTRFS_INODE_COMPRESS)
1369
1370 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
1371
1372 if (bsii->flags_changed) {
1375 WARN("trying to change nocow flag on non-empty file\n");
1377 goto end;
1378 }
1379
1380 fcb->inode_item.flags = bsii->flags;
1381
1384 else
1386 }
1387
1388 if (bsii->mode_changed) {
1390 S_ISGID | S_ISVTX;
1391
1392 if (ccb->access & WRITE_OWNER)
1393 allowed |= S_ISUID;
1394
1395 fcb->inode_item.st_mode &= ~allowed;
1396 fcb->inode_item.st_mode |= bsii->st_mode & allowed;
1397 }
1398
1399 if (bsii->uid_changed && fcb->inode_item.st_uid != bsii->st_uid) {
1400 fcb->inode_item.st_uid = bsii->st_uid;
1401
1402 fcb->sd_dirty = true;
1403 fcb->sd_deleted = false;
1404 }
1405
1406 if (bsii->gid_changed)
1407 fcb->inode_item.st_gid = bsii->st_gid;
1408
1409 if (bsii->compression_type_changed) {
1410 switch (bsii->compression_type) {
1413 break;
1414
1417 break;
1418
1421 break;
1422
1425 break;
1426 }
1427
1429 }
1430
1431 if (bsii->flags_changed || bsii->mode_changed || bsii->uid_changed || bsii->gid_changed || bsii->compression_type_changed) {
1432 fcb->inode_item_changed = true;
1434 }
1435
1437
1438end:
1439 ExReleaseResourceLite(fcb->Header.Resource);
1440
1441 return Status;
1442}
1443
1447 LIST_ENTRY* le;
1448
1449 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1450
1451 le = Vcb->devices.Flink;
1452 while (le != &Vcb->devices) {
1454 ULONG structlen;
1455
1456 if (length < sizeof(btrfs_device) - sizeof(WCHAR)) {
1458 goto end;
1459 }
1460
1461 if (!dev)
1462 dev = data;
1463 else {
1464 dev->next_entry = sizeof(btrfs_device) - sizeof(WCHAR) + dev->namelen;
1465 dev = (btrfs_device*)((uint8_t*)dev + dev->next_entry);
1466 }
1467
1468 structlen = length - offsetof(btrfs_device, namelen);
1469
1470 if (dev2->devobj) {
1471 Status = dev_ioctl(dev2->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &dev->namelen, structlen, true, NULL);
1472 if (!NT_SUCCESS(Status))
1473 goto end;
1474
1475 dev->missing = false;
1476 } else {
1477 dev->namelen = 0;
1478 dev->missing = true;
1479 }
1480
1481 dev->next_entry = 0;
1482 dev->dev_id = dev2->devitem.dev_id;
1483 dev->readonly = (Vcb->readonly || dev2->readonly) ? true : false;
1484 dev->device_number = dev2->disk_num;
1485 dev->partition_number = dev2->part_num;
1486 dev->size = dev2->devitem.num_bytes;
1487
1488 if (dev2->devobj) {
1490
1491 Status = dev_ioctl(dev2->devobj, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), true, NULL);
1492 if (!NT_SUCCESS(Status))
1493 goto end;
1494
1495 dev->max_size = gli.Length.QuadPart;
1496 } else
1497 dev->max_size = dev->size;
1498
1499 RtlCopyMemory(dev->stats, dev2->stats, sizeof(uint64_t) * 5);
1500
1501 length -= sizeof(btrfs_device) - sizeof(WCHAR) + dev->namelen;
1502
1503 le = le->Flink;
1504 }
1505
1506end:
1507 ExReleaseResourceLite(&Vcb->tree_lock);
1508
1509 return Status;
1510}
1511
1514 btrfs_usage* lastbue = NULL;
1516 LIST_ENTRY* le;
1517
1518 if (length < sizeof(btrfs_usage))
1520
1521 if (!Vcb->chunk_usage_found) {
1522 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1523
1524 if (!Vcb->chunk_usage_found)
1526 else
1528
1529 ExReleaseResourceLite(&Vcb->tree_lock);
1530
1531 if (!NT_SUCCESS(Status)) {
1532 ERR("find_chunk_usage returned %08lx\n", Status);
1533 return Status;
1534 }
1535 }
1536
1538
1539 ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
1540
1541 le = Vcb->chunks.Flink;
1542 while (le != &Vcb->chunks) {
1543 bool addnew = false;
1544
1546
1547 if (!lastbue) // first entry
1548 addnew = true;
1549 else {
1550 btrfs_usage* bue = usage;
1551
1552 addnew = true;
1553
1554 while (true) {
1555 if (bue->type == c->chunk_item->type) {
1556 addnew = false;
1557 break;
1558 }
1559
1560 if (bue->next_entry == 0)
1561 break;
1562 else
1563 bue = (btrfs_usage*)((uint8_t*)bue + bue->next_entry);
1564 }
1565 }
1566
1567 if (addnew) {
1568 btrfs_usage* bue;
1569 LIST_ENTRY* le2;
1571
1572 if (!lastbue) {
1573 bue = usage;
1574 } else {
1577 goto end;
1578 }
1579
1581
1582 lastbue->next_entry = offsetof(btrfs_usage, devices) + (ULONG)(lastbue->num_devices * sizeof(btrfs_usage_device));
1583
1584 bue = (btrfs_usage*)((uint8_t*)lastbue + lastbue->next_entry);
1585 }
1586
1587 bue->next_entry = 0;
1588 bue->type = c->chunk_item->type;
1589 bue->size = 0;
1590 bue->used = 0;
1591 bue->num_devices = 0;
1592
1593 if (c->chunk_item->type & BLOCK_FLAG_RAID0)
1594 factor = c->chunk_item->num_stripes;
1595 else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
1596 factor = c->chunk_item->num_stripes / c->chunk_item->sub_stripes;
1597 else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
1598 factor = c->chunk_item->num_stripes - 1;
1599 else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
1600 factor = c->chunk_item->num_stripes - 2;
1601 else
1602 factor = 1;
1603
1604 le2 = le;
1605 while (le2 != &Vcb->chunks) {
1607
1608 if (c2->chunk_item->type == c->chunk_item->type) {
1609 uint16_t i;
1611 uint64_t stripesize;
1612
1613 bue->size += c2->chunk_item->size;
1614 bue->used += c2->used;
1615
1616 stripesize = c2->chunk_item->size / factor;
1617
1618 for (i = 0; i < c2->chunk_item->num_stripes; i++) {
1619 uint64_t j;
1620 bool found = false;
1621
1622 for (j = 0; j < bue->num_devices; j++) {
1623 if (bue->devices[j].dev_id == cis[i].dev_id) {
1624 bue->devices[j].alloc += stripesize;
1625 found = true;
1626 break;
1627 }
1628 }
1629
1630 if (!found) {
1631 if (length < sizeof(btrfs_usage_device)) {
1633 goto end;
1634 }
1635
1636 length -= sizeof(btrfs_usage_device);
1637
1638 bue->devices[bue->num_devices].dev_id = cis[i].dev_id;
1639 bue->devices[bue->num_devices].alloc = stripesize;
1640 bue->num_devices++;
1641 }
1642 }
1643 }
1644
1645 le2 = le2->Flink;
1646 }
1647
1648 lastbue = bue;
1649 }
1650
1651 le = le->Flink;
1652 }
1653
1655
1656end:
1657 ExReleaseResourceLite(&Vcb->chunk_lock);
1658
1659 return Status;
1660}
1661
1664 ULONG cc;
1666 bool verify = false;
1667 LIST_ENTRY* le;
1668
1669 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1670
1671 le = Vcb->devices.Flink;
1672 while (le != &Vcb->devices) {
1674
1675 if (dev->devobj && dev->removable) {
1676 Status = dev_ioctl(dev->devobj, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), false, &iosb);
1677
1678 if (iosb.Information != sizeof(ULONG))
1679 cc = 0;
1680
1681 if (Status == STATUS_VERIFY_REQUIRED || (NT_SUCCESS(Status) && cc != dev->change_count)) {
1682 dev->devobj->Flags |= DO_VERIFY_VOLUME;
1683 verify = true;
1684 }
1685
1686 if (NT_SUCCESS(Status) && iosb.Information == sizeof(ULONG))
1687 dev->change_count = cc;
1688
1689 if (!NT_SUCCESS(Status) || verify) {
1691 ExReleaseResourceLite(&Vcb->tree_lock);
1692
1693 return verify ? STATUS_VERIFY_REQUIRED : Status;
1694 }
1695 }
1696
1697 le = le->Flink;
1698 }
1699
1700 ExReleaseResourceLite(&Vcb->tree_lock);
1701
1702 return STATUS_SUCCESS;
1703}
1704
1705static NTSTATUS fs_get_statistics(void* buffer, DWORD buflen, ULONG_PTR* retlen) {
1707
1708 WARN("STUB: FSCTL_FILESYSTEM_GET_STATISTICS\n");
1709
1710 // This is hideously wrong, but at least it stops SMB from breaking
1711
1712 if (buflen < sizeof(FILESYSTEM_STATISTICS))
1714
1715 fss = buffer;
1717
1718 fss->Version = 1;
1721
1722 *retlen = sizeof(FILESYSTEM_STATISTICS);
1723
1724 return STATUS_SUCCESS;
1725}
1726
1728 FILE_SET_SPARSE_BUFFER* fssb = data;
1730 bool set;
1731 fcb* fcb;
1732 ccb* ccb = FileObject->FsContext2;
1734
1735 if (data && length < sizeof(FILE_SET_SPARSE_BUFFER))
1737
1738 if (!FileObject) {
1739 ERR("FileObject was NULL\n");
1741 }
1742
1743 fcb = FileObject->FsContext;
1744
1745 if (!fcb) {
1746 ERR("FCB was NULL\n");
1748 }
1749
1750 if (!ccb) {
1751 ERR("CCB was NULL\n");
1753 }
1754
1755 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) {
1756 WARN("insufficient privileges\n");
1757 return STATUS_ACCESS_DENIED;
1758 }
1759
1760 if (!fileref) {
1761 ERR("no fileref\n");
1763 }
1764
1765 if (fcb->ads) {
1766 fileref = fileref->parent;
1767 fcb = fileref->fcb;
1768 }
1769
1770 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1771 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
1772
1773 if (fcb->type != BTRFS_TYPE_FILE) {
1774 WARN("FileObject did not point to a file\n");
1776 goto end;
1777 }
1778
1779 if (fssb)
1780 set = fssb->SetSparse;
1781 else
1782 set = true;
1783
1784 if (set) {
1786 fcb->atts_changed = true;
1787 } else {
1788 ULONG defda;
1789
1790 fcb->atts &= ~FILE_ATTRIBUTE_SPARSE_FILE;
1791 fcb->atts_changed = true;
1792
1794 fileref && fileref->dc && fileref->dc->name.Length >= sizeof(WCHAR) && fileref->dc->name.Buffer[0] == '.', true, Irp);
1795
1796 fcb->atts_deleted = defda == fcb->atts;
1797 }
1798
1801
1803
1804end:
1805 ExReleaseResourceLite(fcb->Header.Resource);
1806 ExReleaseResourceLite(&Vcb->tree_lock);
1807
1808 return Status;
1809}
1810
1813 bool make_inline, compress;
1814 uint64_t start_data, end_data;
1815 ULONG buf_head;
1816 uint8_t* data;
1817
1818 make_inline = fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb);
1819
1820 if (!make_inline)
1822
1823 if (make_inline) {
1824 start_data = 0;
1825 end_data = fcb->inode_item.st_size;
1826 buf_head = (ULONG)offsetof(EXTENT_DATA, data[0]);
1827 } else if (compress) {
1830 sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size));
1831 buf_head = 0;
1832 } else {
1833 start_data = start & ~(uint64_t)(Vcb->superblock.sector_size - 1);
1834 end_data = sector_align(start + length, Vcb->superblock.sector_size);
1835 buf_head = 0;
1836 }
1837
1838 data = ExAllocatePoolWithTag(PagedPool, (ULONG)(buf_head + end_data - start_data), ALLOC_TAG);
1839 if (!data) {
1840 ERR("out of memory\n");
1842 }
1843
1844 RtlZeroMemory(data + buf_head, (ULONG)(end_data - start_data));
1845
1846 if (start > start_data || start + length < end_data) {
1847 Status = read_file(fcb, data + buf_head, start_data, end_data - start_data, NULL, Irp);
1848
1849 if (!NT_SUCCESS(Status)) {
1850 ERR("read_file returned %08lx\n", Status);
1852 return Status;
1853 }
1854 }
1855
1856 RtlZeroMemory(data + buf_head + start - start_data, (ULONG)length);
1857
1858 if (make_inline) {
1859 uint16_t edsize;
1861
1862 Status = excise_extents(Vcb, fcb, 0, sector_align(end_data, Vcb->superblock.sector_size), Irp, rollback);
1863 if (!NT_SUCCESS(Status)) {
1864 ERR("excise_extents returned %08lx\n", Status);
1866 return Status;
1867 }
1868
1869 edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + end_data);
1870
1871 ed->generation = Vcb->superblock.generation;
1872 ed->decoded_size = end_data;
1877
1878 Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, rollback);
1879 if (!NT_SUCCESS(Status)) {
1880 ERR("add_extent_to_fcb returned %08lx\n", Status);
1882 return Status;
1883 }
1884
1886
1887 fcb->inode_item.st_blocks += end_data;
1888 } else if (compress) {
1890
1892
1893 if (!NT_SUCCESS(Status)) {
1894 ERR("write_compressed returned %08lx\n", Status);
1895 return Status;
1896 }
1897 } else {
1898 Status = do_write_file(fcb, start_data, end_data, data, Irp, false, 0, rollback);
1899
1901
1902 if (!NT_SUCCESS(Status)) {
1903 ERR("do_write_file returned %08lx\n", Status);
1904 return Status;
1905 }
1906 }
1907
1908 return STATUS_SUCCESS;
1909}
1910
1912 FILE_ZERO_DATA_INFORMATION* fzdi = data;
1914 fcb* fcb;
1915 ccb* ccb;
1917 LIST_ENTRY rollback, *le;
1921 extent* ext;
1923
1924 if (!data || length < sizeof(FILE_ZERO_DATA_INFORMATION))
1926
1927 if (!FileObject) {
1928 ERR("FileObject was NULL\n");
1930 }
1931
1932 if (fzdi->BeyondFinalZero.QuadPart <= fzdi->FileOffset.QuadPart) {
1933 WARN("BeyondFinalZero was less than or equal to FileOffset (%I64x <= %I64x)\n", fzdi->BeyondFinalZero.QuadPart, fzdi->FileOffset.QuadPart);
1935 }
1936
1937 fcb = FileObject->FsContext;
1938
1939 if (!fcb) {
1940 ERR("FCB was NULL\n");
1942 }
1943
1944 ccb = FileObject->FsContext2;
1945
1946 if (!ccb) {
1947 ERR("ccb was NULL\n");
1949 }
1950
1951 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
1952 WARN("insufficient privileges\n");
1953 return STATUS_ACCESS_DENIED;
1954 }
1955
1956 fileref = ccb->fileref;
1957
1958 if (!fileref) {
1959 ERR("fileref was NULL\n");
1961 }
1962
1964
1965 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
1966 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
1967
1968 CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb);
1969
1970 if (fcb->type != BTRFS_TYPE_FILE) {
1971 WARN("FileObject did not point to a file\n");
1973 goto end;
1974 }
1975
1976 if (fcb->ads) {
1977 ERR("FileObject is stream\n");
1979 goto end;
1980 }
1981
1982 if ((uint64_t)fzdi->FileOffset.QuadPart >= fcb->inode_item.st_size) {
1984 goto end;
1985 }
1986
1987 ext = NULL;
1988 le = fcb->extents.Flink;
1989 while (le != &fcb->extents) {
1991
1992 if (!ext2->ignore) {
1993 ext = ext2;
1994 break;
1995 }
1996
1997 le = le->Flink;
1998 }
1999
2000 if (!ext) {
2002 goto end;
2003 }
2004
2005 if (ext->extent_data.type == EXTENT_TYPE_INLINE) {
2006 Status = zero_data(Vcb, fcb, fzdi->FileOffset.QuadPart, fzdi->BeyondFinalZero.QuadPart - fzdi->FileOffset.QuadPart, Irp, &rollback);
2007 if (!NT_SUCCESS(Status)) {
2008 ERR("zero_data returned %08lx\n", Status);
2009 goto end;
2010 }
2011 } else {
2012 start = sector_align(fzdi->FileOffset.QuadPart, Vcb->superblock.sector_size);
2013
2014 if ((uint64_t)fzdi->BeyondFinalZero.QuadPart > fcb->inode_item.st_size)
2015 end = sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size);
2016 else
2017 end = (fzdi->BeyondFinalZero.QuadPart >> Vcb->sector_shift) << Vcb->sector_shift;
2018
2019 if (end <= start) {
2020 Status = zero_data(Vcb, fcb, fzdi->FileOffset.QuadPart, fzdi->BeyondFinalZero.QuadPart - fzdi->FileOffset.QuadPart, Irp, &rollback);
2021 if (!NT_SUCCESS(Status)) {
2022 ERR("zero_data returned %08lx\n", Status);
2023 goto end;
2024 }
2025 } else {
2026 if (start > (uint64_t)fzdi->FileOffset.QuadPart) {
2027 Status = zero_data(Vcb, fcb, fzdi->FileOffset.QuadPart, start - fzdi->FileOffset.QuadPart, Irp, &rollback);
2028 if (!NT_SUCCESS(Status)) {
2029 ERR("zero_data returned %08lx\n", Status);
2030 goto end;
2031 }
2032 }
2033
2034 if (end < (uint64_t)fzdi->BeyondFinalZero.QuadPart) {
2035 Status = zero_data(Vcb, fcb, end, fzdi->BeyondFinalZero.QuadPart - end, Irp, &rollback);
2036 if (!NT_SUCCESS(Status)) {
2037 ERR("zero_data returned %08lx\n", Status);
2038 goto end;
2039 }
2040 }
2041
2042 if (end > start) {
2044 if (!NT_SUCCESS(Status)) {
2045 ERR("excise_extents returned %08lx\n", Status);
2046 goto end;
2047 }
2048 }
2049 }
2050 }
2051
2052 CcPurgeCacheSection(FileObject->SectionObjectPointer, &fzdi->FileOffset, (ULONG)(fzdi->BeyondFinalZero.QuadPart - fzdi->FileOffset.QuadPart), false);
2053
2056
2057 fcb->inode_item.transid = Vcb->superblock.generation;
2059
2062
2065
2066 fcb->extents_changed = true;
2067 fcb->inode_item_changed = true;
2069
2071
2072 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
2073 fcb->subvol->root_item.ctime = now;
2074
2076
2077end:
2078 if (!NT_SUCCESS(Status))
2080 else
2082
2083 ExReleaseResourceLite(fcb->Header.Resource);
2084 ExReleaseResourceLite(&Vcb->tree_lock);
2085
2086 return Status;
2087}
2088
2089static NTSTATUS query_ranges(PFILE_OBJECT FileObject, FILE_ALLOCATED_RANGE_BUFFER* inbuf, ULONG inbuflen, void* outbuf, ULONG outbuflen, ULONG_PTR* retlen) {
2091 fcb* fcb;
2092 LIST_ENTRY* le;
2093 FILE_ALLOCATED_RANGE_BUFFER* ranges = outbuf;
2094 ULONG i = 0;
2095 uint64_t last_start, last_end;
2096
2097 TRACE("FSCTL_QUERY_ALLOCATED_RANGES\n");
2098
2099 if (!FileObject) {
2100 ERR("FileObject was NULL\n");
2102 }
2103
2104 if (!inbuf || inbuflen < sizeof(FILE_ALLOCATED_RANGE_BUFFER) || !outbuf)
2106
2107 fcb = FileObject->FsContext;
2108
2109 if (!fcb) {
2110 ERR("FCB was NULL\n");
2112 }
2113
2114 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
2115
2116 // If file is not marked as sparse, claim the whole thing as an allocated range
2117
2119 if (fcb->inode_item.st_size == 0)
2121 else if (outbuflen < sizeof(FILE_ALLOCATED_RANGE_BUFFER))
2123 else {
2124 ranges[i].FileOffset.QuadPart = 0;
2125 ranges[i].Length.QuadPart = fcb->inode_item.st_size;
2126 i++;
2128 }
2129
2130 goto end;
2131
2132 }
2133
2134 le = fcb->extents.Flink;
2135
2136 last_start = 0;
2137 last_end = 0;
2138
2139 while (le != &fcb->extents) {
2141
2142 if (!ext->ignore) {
2143 EXTENT_DATA2* ed2 = (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) ? (EXTENT_DATA2*)ext->extent_data.data : NULL;
2144 uint64_t len = ed2 ? ed2->num_bytes : ext->extent_data.decoded_size;
2145
2146 if (ext->offset > last_end) { // first extent after a hole
2147 if (last_end > last_start) {
2148 if ((i + 1) * sizeof(FILE_ALLOCATED_RANGE_BUFFER) <= outbuflen) {
2149 ranges[i].FileOffset.QuadPart = last_start;
2150 ranges[i].Length.QuadPart = min(fcb->inode_item.st_size, last_end) - last_start;
2151 i++;
2152 } else {
2154 goto end;
2155 }
2156 }
2157
2158 last_start = ext->offset;
2159 }
2160
2161 last_end = ext->offset + len;
2162 }
2163
2164 le = le->Flink;
2165 }
2166
2167 if (last_end > last_start) {
2168 if ((i + 1) * sizeof(FILE_ALLOCATED_RANGE_BUFFER) <= outbuflen) {
2169 ranges[i].FileOffset.QuadPart = last_start;
2170 ranges[i].Length.QuadPart = min(fcb->inode_item.st_size, last_end) - last_start;
2171 i++;
2172 } else {
2174 goto end;
2175 }
2176 }
2177
2179
2180end:
2181 *retlen = i * sizeof(FILE_ALLOCATED_RANGE_BUFFER);
2182
2183 ExReleaseResourceLite(fcb->Header.Resource);
2184
2185 return Status;
2186}
2187
2188static NTSTATUS get_object_id(PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER* buf, ULONG buflen, ULONG_PTR* retlen) {
2189 fcb* fcb;
2190
2191 TRACE("(%p, %p, %lx, %p)\n", FileObject, buf, buflen, retlen);
2192
2193 if (!FileObject) {
2194 ERR("FileObject was NULL\n");
2196 }
2197
2198 if (!buf || buflen < sizeof(FILE_OBJECTID_BUFFER))
2200
2201 fcb = FileObject->FsContext;
2202
2203 if (!fcb) {
2204 ERR("FCB was NULL\n");
2206 }
2207
2208 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
2209
2210 RtlCopyMemory(&buf->ObjectId[0], &fcb->inode, sizeof(uint64_t));
2211 RtlCopyMemory(&buf->ObjectId[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
2212
2213 ExReleaseResourceLite(fcb->Header.Resource);
2214
2215 RtlZeroMemory(&buf->ExtendedInfo, sizeof(buf->ExtendedInfo));
2216
2217 *retlen = sizeof(FILE_OBJECTID_BUFFER);
2218
2219 return STATUS_SUCCESS;
2220}
2221
2223 LIST_ENTRY* le;
2224
2225 le = Vcb->all_fcbs.Flink;
2226 while (le != &Vcb->all_fcbs) {
2227 struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2229
2231 CcFlushCache(&fcb->nonpaged->segment_object, NULL, 0, &iosb);
2232
2233 le = le->Flink;
2234 }
2235}
2236
2240 KIRQL irql;
2241 bool lock_paused_balance = false;
2242
2243 TRACE("FSCTL_LOCK_VOLUME\n");
2244
2245 if (Vcb->scrub.thread) {
2246 WARN("cannot lock while scrub running\n");
2248 }
2249
2250 if (Vcb->balance.thread) {
2251 WARN("cannot lock while balance running\n");
2253 }
2254
2255 TRACE("locking volume\n");
2256
2258
2259 if (Vcb->locked)
2260 return STATUS_SUCCESS;
2261
2262 ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
2263
2264 if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
2266 ExReleaseResourceLite(&Vcb->fileref_lock);
2267 goto end;
2268 }
2269
2270 ExReleaseResourceLite(&Vcb->fileref_lock);
2271
2272 if (Vcb->balance.thread && KeReadStateEvent(&Vcb->balance.event)) {
2273 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2274 KeClearEvent(&Vcb->balance.event);
2275 ExReleaseResourceLite(&Vcb->tree_lock);
2276
2277 lock_paused_balance = true;
2278 }
2279
2280 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2281
2283
2284 if (Vcb->need_write && !Vcb->readonly)
2285 Status = do_write(Vcb, Irp);
2286 else
2288
2289 free_trees(Vcb);
2290
2291 ExReleaseResourceLite(&Vcb->tree_lock);
2292
2293 if (!NT_SUCCESS(Status)) {
2294 ERR("do_write returned %08lx\n", Status);
2295 goto end;
2296 }
2297
2299
2300 if (!(Vcb->Vpb->Flags & VPB_LOCKED)) {
2301 Vcb->Vpb->Flags |= VPB_LOCKED;
2302 Vcb->locked = true;
2303 Vcb->locked_fileobj = IrpSp->FileObject;
2304 Vcb->lock_paused_balance = lock_paused_balance;
2305 } else {
2308
2309 if (lock_paused_balance)
2310 KeSetEvent(&Vcb->balance.event, 0, false);
2311
2312 goto end;
2313 }
2314
2316
2318
2319end:
2320 if (!NT_SUCCESS(Status))
2322
2323 return Status;
2324}
2325
2327 KIRQL irql;
2328
2330
2331 Vcb->locked = false;
2332 Vcb->Vpb->Flags &= ~VPB_LOCKED;
2333 Vcb->locked_fileobj = NULL;
2334
2336
2337 if (Vcb->lock_paused_balance)
2338 KeSetEvent(&Vcb->balance.event, 0, false);
2339}
2340
2343
2344 TRACE("FSCTL_UNLOCK_VOLUME\n");
2345
2346 if (!Vcb->locked || IrpSp->FileObject != Vcb->locked_fileobj)
2347 return STATUS_NOT_LOCKED;
2348
2349 TRACE("unlocking volume\n");
2350
2352
2354
2355 return STATUS_SUCCESS;
2356}
2357
2360 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
2362 HANDLE h;
2363 PFILE_OBJECT fileobj;
2364 PDEVICE_OBJECT devobj;
2365 LIST_ENTRY* le;
2366
2367 TRACE("FSCTL_INVALIDATE_VOLUMES\n");
2368
2369 if (!SeSinglePrivilegeCheck(TcbPrivilege, Irp->RequestorMode))
2371
2372#if defined(_WIN64)
2373 if (IoIs32bitProcess(Irp)) {
2374 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2376
2377 h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2378 } else {
2379#endif
2380 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2382
2383 h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2384#if defined(_WIN64)
2385 }
2386#endif
2387
2388 Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2389
2390 if (!NT_SUCCESS(Status)) {
2391 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2392 return Status;
2393 }
2394
2395 devobj = fileobj->DeviceObject;
2396
2398
2399 le = VcbList.Flink;
2400
2401 while (le != &VcbList) {
2403
2404 if (Vcb->Vpb && Vcb->Vpb->RealDevice == devobj) {
2405 if (Vcb->Vpb == devobj->Vpb) {
2406 KIRQL irql;
2407 PVPB newvpb;
2408 bool free_newvpb = false;
2409
2410 newvpb = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), ALLOC_TAG);
2411 if (!newvpb) {
2412 ERR("out of memory\n");
2414 goto end;
2415 }
2416
2417 RtlZeroMemory(newvpb, sizeof(VPB));
2418
2419 ObReferenceObject(devobj);
2420
2421 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2422
2423 Vcb->removing = true;
2424
2425 ExReleaseResourceLite(&Vcb->tree_lock);
2426
2428
2429 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2430
2432
2433 if (Vcb->need_write && !Vcb->readonly)
2434 Status = do_write(Vcb, Irp);
2435 else
2437
2438 free_trees(Vcb);
2439
2440 if (!NT_SUCCESS(Status)) {
2441 ERR("do_write returned %08lx\n", Status);
2442 ExReleaseResourceLite(&Vcb->tree_lock);
2443 ExFreePool(newvpb);
2444 ObDereferenceObject(devobj);
2445 goto end;
2446 }
2447
2449
2450 ExReleaseResourceLite(&Vcb->tree_lock);
2451
2453
2454 if (devobj->Vpb->Flags & VPB_MOUNTED) {
2455 newvpb->Type = IO_TYPE_VPB;
2456 newvpb->Size = sizeof(VPB);
2457 newvpb->RealDevice = devobj;
2458 newvpb->Flags = devobj->Vpb->Flags & VPB_REMOVE_PENDING;
2459
2460 devobj->Vpb = newvpb;
2461 } else
2462 free_newvpb = true;
2463
2465
2466 if (free_newvpb)
2467 ExFreePool(newvpb);
2468
2469 if (Vcb->open_files == 0)
2470 uninit(Vcb);
2471
2472 ObDereferenceObject(devobj);
2473 }
2474
2475 break;
2476 }
2477
2478 le = le->Flink;
2479 }
2480
2482
2483end:
2485
2486 ObDereferenceObject(fileobj);
2487
2488 return Status;
2489}
2490
2493 ULONG* volstate;
2494
2495 if (Irp->AssociatedIrp.SystemBuffer) {
2496 volstate = Irp->AssociatedIrp.SystemBuffer;
2497 } else if (Irp->MdlAddress != NULL) {
2498 volstate = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, LowPagePriority);
2499
2500 if (!volstate)
2502 } else
2504
2505 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG))
2507
2508 *volstate = 0;
2509
2510 if (IrpSp->FileObject->FsContext != Vcb->volume_fcb)
2512
2513 Irp->IoStatus.Information = sizeof(ULONG);
2514
2515 return STATUS_SUCCESS;
2516}
2517
2521
2522 TRACE("FSCTL_GET_COMPRESSION\n");
2523
2524 if (Irp->AssociatedIrp.SystemBuffer) {
2525 compression = Irp->AssociatedIrp.SystemBuffer;
2526 } else if (Irp->MdlAddress != NULL) {
2528
2529 if (!compression)
2531 } else
2533
2534 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(USHORT))
2536
2538
2539 Irp->IoStatus.Information = sizeof(USHORT);
2540
2541 return STATUS_SUCCESS;
2542}
2543
2547
2548 TRACE("FSCTL_SET_COMPRESSION\n");
2549
2550 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(USHORT))
2552
2553 compression = Irp->AssociatedIrp.SystemBuffer;
2554
2557
2558 return STATUS_SUCCESS;
2559}
2560
2562 LIST_ENTRY* le;
2563 volume_device_extension* vde = Vcb->vde;
2564 pdo_device_extension* pdode = vde->pdode;
2565
2566 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
2567
2569
2570 le = pdode->children.Flink;
2571 while (le != &pdode->children) {
2573
2574 vc->generation = Vcb->superblock.generation - 1;
2575
2576 le = le->Flink;
2577 }
2578
2580
2581 ExReleaseResourceLite(&Vcb->tree_lock);
2582}
2583
2586 bool open_files;
2587
2588 TRACE("FSCTL_DISMOUNT_VOLUME\n");
2589
2590 if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
2591 return STATUS_SUCCESS;
2592
2593 if (!shutdown) {
2594 if (Vcb->disallow_dismount || Vcb->page_file_count != 0) {
2595 WARN("attempting to dismount boot volume or one containing a pagefile\n");
2596 return STATUS_ACCESS_DENIED;
2597 }
2598
2600 if (!NT_SUCCESS(Status)) {
2601 WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
2602 }
2603 }
2604
2605 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2606
2607 if (!Vcb->locked) {
2609
2610 if (Vcb->need_write && !Vcb->readonly) {
2611 Status = do_write(Vcb, Irp);
2612
2613 if (!NT_SUCCESS(Status))
2614 ERR("do_write returned %08lx\n", Status);
2615 }
2616 }
2617
2618 free_trees(Vcb);
2619
2620 Vcb->removing = true;
2621
2622 open_files = Vcb->open_files > 0;
2623
2624 if (Vcb->vde) {
2626 Vcb->vde->mounted_device = NULL;
2627 }
2628
2629 ExReleaseResourceLite(&Vcb->tree_lock);
2630
2631 if (!open_files)
2632 uninit(Vcb);
2633
2634 return STATUS_SUCCESS;
2635}
2636
2639 ULONG to_read;
2640 superblock* sb;
2641 BTRFS_UUID fsuuid, devuuid;
2642 LIST_ENTRY* le;
2643
2644 to_read = devobj->SectorSize == 0 ? sizeof(superblock) : (ULONG)sector_align(sizeof(superblock), devobj->SectorSize);
2645
2647 if (!sb) {
2648 ERR("out of memory\n");
2650 }
2651
2652 Status = sync_read_phys(devobj, fileobj, superblock_addrs[0], to_read, (uint8_t*)sb, true);
2653 if (!NT_SUCCESS(Status)) {
2654 ERR("sync_read_phys returned %08lx\n", Status);
2655 ExFreePool(sb);
2656 return Status;
2657 }
2658
2659 if (sb->magic != BTRFS_MAGIC) {
2660 TRACE("device is not Btrfs\n");
2661 ExFreePool(sb);
2662 return STATUS_SUCCESS;
2663 }
2664
2666 TRACE("device has Btrfs magic, but invalid superblock checksum\n");
2667 ExFreePool(sb);
2668 return STATUS_SUCCESS;
2669 }
2670
2671 fsuuid = sb->uuid;
2672 devuuid = sb->dev_item.device_uuid;
2673
2674 ExFreePool(sb);
2675
2677
2678 le = VcbList.Flink;
2679
2680 while (le != &VcbList) {
2682
2683 if (RtlCompareMemory(&Vcb->superblock.uuid, &fsuuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
2684 LIST_ENTRY* le2;
2685
2686 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
2687
2688 if (Vcb->superblock.num_devices > 1) {
2689 le2 = Vcb->devices.Flink;
2690 while (le2 != &Vcb->devices) {
2692
2693 if (RtlCompareMemory(&dev->devitem.device_uuid, &devuuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
2694 ExReleaseResourceLite(&Vcb->tree_lock);
2697 }
2698
2699 le2 = le2->Flink;
2700 }
2701 }
2702
2703 ExReleaseResourceLite(&Vcb->tree_lock);
2705 return STATUS_SUCCESS;
2706 }
2707
2708 le = le->Flink;
2709 }
2710
2712
2713 return STATUS_SUCCESS;
2714}
2715
2719
2720 // FIXME - avoid "bootloader area"??
2721
2725 dmdsa.ParameterBlockOffset = 0;
2726 dmdsa.ParameterBlockLength = 0;
2727 dmdsa.DataSetRangesOffset = 0;
2728 dmdsa.DataSetRangesLength = 0;
2729
2731 if (!NT_SUCCESS(Status))
2732 WARN("IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES returned %08lx\n", Status);
2733}
2734
2738 PFILE_OBJECT fileobj, mountmgrfo;
2740 HANDLE h;
2741 LIST_ENTRY* le;
2742 device* dev;
2743 DEV_ITEM* di;
2744 uint64_t dev_id, size;
2745 uint8_t* mb;
2746 uint64_t* stats;
2747 UNICODE_STRING mmdevpath, pnp_name, pnp_name2;
2748 volume_child* vc;
2750 KEY searchkey;
2754 pdo_device_extension* pdode;
2755 const GUID* pnp_guid;
2757
2758 pnp_name.Buffer = NULL;
2759
2760 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
2762
2763 if (!Vcb->vde) {
2764 WARN("not allowing second device to be added to non-PNP device\n");
2765 return STATUS_NOT_SUPPORTED;
2766 }
2767
2768 if (Vcb->readonly) // FIXME - handle adding R/W device to seeding device
2770
2771#if defined(_WIN64)
2772 if (IoIs32bitProcess(Irp)) {
2773 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(uint32_t))
2775
2776 h = (HANDLE)LongToHandle((*(uint32_t*)Irp->AssociatedIrp.SystemBuffer));
2777 } else {
2778#endif
2779 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE))
2781
2782 h = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
2783#if defined(_WIN64)
2784 }
2785#endif
2786
2787 Status = ObReferenceObjectByHandle(h, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&fileobj, NULL);
2788
2789 if (!NT_SUCCESS(Status)) {
2790 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
2791 return Status;
2792 }
2793
2794 DeviceObject = fileobj->DeviceObject;
2795
2796 Status = get_device_pnp_name(DeviceObject, &pnp_name, &pnp_guid);
2797 if (!NT_SUCCESS(Status)) {
2798 ERR("get_device_pnp_name returned %08lx\n", Status);
2799 ObDereferenceObject(fileobj);
2800 return Status;
2801 }
2802
2803 // If this is a disk, we have been handed the PDO, so need to go up to find something we can use
2804 if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID) && DeviceObject->AttachedDevice)
2805 DeviceObject = DeviceObject->AttachedDevice;
2806
2808 if (!NT_SUCCESS(Status)) {
2809 ERR("IOCTL_DISK_IS_WRITABLE returned %08lx\n", Status);
2810 ObDereferenceObject(fileobj);
2811 return Status;
2812 }
2813
2815 if (!NT_SUCCESS(Status)) {
2816 ERR("is_device_part_of_mounted_btrfs_raid returned %08lx\n", Status);
2817 ObDereferenceObject(fileobj);
2818 return Status;
2819 }
2820
2821 // if disk, check it has no partitions
2822 if (RtlCompareMemory(pnp_guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
2823 ULONG dlisize;
2824 DRIVE_LAYOUT_INFORMATION_EX* dli = NULL;
2825
2826 dlisize = 0;
2827
2828 do {
2829 dlisize += 1024;
2830
2831 if (dli)
2832 ExFreePool(dli);
2833
2834 dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
2835 if (!dli) {
2836 ERR("out of memory\n");
2838 goto end2;
2839 }
2840
2842 } while (Status == STATUS_BUFFER_TOO_SMALL);
2843
2844 if (NT_SUCCESS(Status) && dli->PartitionCount > 0) {
2845 ExFreePool(dli);
2846 ERR("not adding disk which has partitions\n");
2848 goto end2;
2849 }
2850
2851 ExFreePool(dli);
2852 }
2853
2855 &sdn, sizeof(STORAGE_DEVICE_NUMBER), true, NULL);
2856 if (NT_SUCCESS(Status)) {
2857 if (sdn.DeviceType != FILE_DEVICE_DISK) { // FIXME - accept floppies and CDs?
2858 WARN("device was not disk\n");
2859 ObDereferenceObject(fileobj);
2861 }
2862 } else {
2863 sdn.DeviceNumber = 0xffffffff;
2864 sdn.PartitionNumber = 0xffffffff;
2865 }
2866
2868 &gli, sizeof(gli), true, NULL);
2869 if (!NT_SUCCESS(Status)) {
2870 ERR("error reading length information: %08lx\n", Status);
2871 ObDereferenceObject(fileobj);
2872 return Status;
2873 }
2874
2875 size = gli.Length.QuadPart;
2876
2877 if (size < 0x100000) {
2878 ERR("device was not large enough to hold FS (%I64x bytes, need at least 1 MB)\n", size);
2879 ObDereferenceObject(fileobj);
2880 return STATUS_INTERNAL_ERROR;
2881 }
2882
2883 volume_removal(&pnp_name);
2884
2885 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2886
2887 if (Vcb->need_write)
2888 Status = do_write(Vcb, Irp);
2889 else
2891
2892 free_trees(Vcb);
2893
2894 if (!NT_SUCCESS(Status)) {
2895 ERR("do_write returned %08lx\n", Status);
2896 goto end;
2897 }
2898
2900 if (!dev) {
2901 ERR("out of memory\n");
2903 goto end;
2904 }
2905
2906 RtlZeroMemory(dev, sizeof(device));
2907
2908 dev->devobj = DeviceObject;
2909 dev->fileobj = fileobj;
2910 dev->seeding = false;
2911 init_device(Vcb, dev, true);
2912
2913 InitializeListHead(&dev->space);
2914
2915 if (size > 0x100000) { // add disk hole - the first MB is marked as used
2916 Status = add_space_entry(&dev->space, NULL, 0x100000, size - 0x100000);
2917 if (!NT_SUCCESS(Status)) {
2918 ERR("add_space_entry returned %08lx\n", Status);
2919 goto end;
2920 }
2921 }
2922
2923 dev_id = 0;
2924
2925 le = Vcb->devices.Flink;
2926 while (le != &Vcb->devices) {
2928
2929 if (dev2->devitem.dev_id > dev_id)
2930 dev_id = dev2->devitem.dev_id;
2931
2932 le = le->Flink;
2933 }
2934
2935 dev_id++;
2936
2937 dev->devitem.dev_id = dev_id;
2938 dev->devitem.num_bytes = size;
2939 dev->devitem.bytes_used = 0;
2940 dev->devitem.optimal_io_align = Vcb->superblock.sector_size;
2941 dev->devitem.optimal_io_width = Vcb->superblock.sector_size;
2942 dev->devitem.minimal_io_size = Vcb->superblock.sector_size;
2943 dev->devitem.type = 0;
2944 dev->devitem.generation = 0;
2945 dev->devitem.start_offset = 0;
2946 dev->devitem.dev_group = 0;
2947 dev->devitem.seek_speed = 0;
2948 dev->devitem.bandwidth = 0;
2949 get_uuid(&dev->devitem.device_uuid);
2950 dev->devitem.fs_uuid = Vcb->superblock.uuid;
2951
2953 if (!di) {
2954 ERR("out of memory\n");
2955 goto end;
2956 }
2957
2958 RtlCopyMemory(di, &dev->devitem, sizeof(DEV_ITEM));
2959
2960 Status = insert_tree_item(Vcb, Vcb->chunk_root, 1, TYPE_DEV_ITEM, di->dev_id, di, sizeof(DEV_ITEM), NULL, Irp);
2961 if (!NT_SUCCESS(Status)) {
2962 ERR("insert_tree_item returned %08lx\n", Status);
2963 ExFreePool(di);
2964 goto end;
2965 }
2966
2967 // add stats entry to dev tree
2968 stats = ExAllocatePoolWithTag(PagedPool, sizeof(uint64_t) * 5, ALLOC_TAG);
2969 if (!stats) {
2970 ERR("out of memory\n");
2972 goto end;
2973 }
2974
2975 RtlZeroMemory(stats, sizeof(uint64_t) * 5);
2976
2977 searchkey.obj_id = 0;
2978 searchkey.obj_type = TYPE_DEV_STATS;
2979 searchkey.offset = di->dev_id;
2980
2981 Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, Irp);
2982 if (!NT_SUCCESS(Status)) {
2983 ERR("error - find_item returned %08lx\n", Status);
2984 ExFreePool(stats);
2985 goto end;
2986 }
2987
2988 if (!keycmp(tp.item->key, searchkey)) {
2990 if (!NT_SUCCESS(Status)) {
2991 ERR("delete_tree_item returned %08lx\n", Status);
2992 ExFreePool(stats);
2993 goto end;
2994 }
2995 }
2996
2997 Status = insert_tree_item(Vcb, Vcb->dev_root, 0, TYPE_DEV_STATS, di->dev_id, stats, sizeof(uint64_t) * 5, NULL, Irp);
2998 if (!NT_SUCCESS(Status)) {
2999 ERR("insert_tree_item returned %08lx\n", Status);
3000 ExFreePool(stats);
3001 goto end;
3002 }
3003
3004 if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
3006
3007 // We clear the first megabyte of the device, so Windows doesn't identify it as another FS
3008 mb = ExAllocatePoolWithTag(PagedPool, 0x100000, ALLOC_TAG);
3009 if (!mb) {
3010 ERR("out of memory\n");
3012 goto end;
3013 }
3014
3015 RtlZeroMemory(mb, 0x100000);
3016
3017 Status = write_data_phys(DeviceObject, fileobj, 0, mb, 0x100000);
3018 if (!NT_SUCCESS(Status)) {
3019 ERR("write_data_phys returned %08lx\n", Status);
3020 ExFreePool(mb);
3021 goto end;
3022 }
3023
3024 ExFreePool(mb);
3025
3026 vde = Vcb->vde;
3027 pdode = vde->pdode;
3028
3030 if (!vc) {
3031 ERR("out of memory\n");
3033 goto end;
3034 }
3035
3036 vc->uuid = dev->devitem.device_uuid;
3037 vc->devid = dev_id;
3038 vc->generation = Vcb->superblock.generation;
3039 vc->devobj = DeviceObject;
3040 vc->fileobj = fileobj;
3042 vc->boot_volume = false;
3043
3045 drvobj, pnp_removal, vde->pdode, &vc->notification_entry);
3046 if (!NT_SUCCESS(Status))
3047 WARN("IoRegisterPlugPlayNotification returned %08lx\n", Status);
3048
3049 pnp_name2 = pnp_name;
3050
3051 if (pnp_name.Length > 4 * sizeof(WCHAR) && pnp_name.Buffer[0] == '\\' && (pnp_name.Buffer[1] == '\\' || pnp_name.Buffer[1] == '?') &&
3052 pnp_name.Buffer[2] == '?' && pnp_name.Buffer[3] == '\\') {
3053 pnp_name2.Buffer = &pnp_name2.Buffer[3];
3054 pnp_name2.Length -= 3 * sizeof(WCHAR);
3055 pnp_name2.MaximumLength -= 3 * sizeof(WCHAR);
3056 }
3057
3058 vc->pnp_name.Length = vc->pnp_name.MaximumLength = pnp_name2.Length;
3059
3060 if (pnp_name2.Length == 0)
3061 vc->pnp_name.Buffer = NULL;
3062 else {
3064 if (!vc->pnp_name.Buffer) {
3065 ERR("out of memory\n");
3067 goto end;
3068 }
3069
3070 RtlCopyMemory(vc->pnp_name.Buffer, pnp_name2.Buffer, pnp_name2.Length);
3071 }
3072
3073 vc->size = size;
3074 vc->seeding = false;
3075 vc->disk_num = sdn.DeviceNumber;
3076 vc->part_num = sdn.PartitionNumber;
3077 vc->had_drive_letter = false;
3078
3080 InsertTailList(&pdode->children, &vc->list_entry);
3081 pdode->num_children++;
3082 pdode->children_loaded++;
3084
3086 Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &mountmgrfo, &mountmgr);
3087 if (!NT_SUCCESS(Status))
3088 ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
3089 else {
3090 Status = remove_drive_letter(mountmgr, &pnp_name);
3092 WARN("remove_drive_letter returned %08lx\n", Status);
3093
3095
3096 ObDereferenceObject(mountmgrfo);
3097 }
3098
3099 Vcb->superblock.num_devices++;
3100 Vcb->superblock.total_bytes += size;
3101 Vcb->devices_loaded++;
3102 InsertTailList(&Vcb->devices, &dev->list_entry);
3103
3104 // FIXME - send notification that volume size has increased
3105
3106 ObReferenceObject(DeviceObject); // for Vcb
3107
3108 Status = do_write(Vcb, Irp);
3109 if (!NT_SUCCESS(Status))
3110 ERR("do_write returned %08lx\n", Status);
3111
3112 ObReferenceObject(fileobj);
3113
3114end:
3115 free_trees(Vcb);
3116
3117 ExReleaseResourceLite(&Vcb->tree_lock);
3118
3119end2:
3120 ObDereferenceObject(fileobj);
3121
3122 if (pnp_name.Buffer)
3123 ExFreePool(pnp_name.Buffer);
3124
3125 if (NT_SUCCESS(Status))
3127
3128 return Status;
3129}
3130
3132 fcb* fcb;
3133 ccb* ccb;
3134
3135 TRACE("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
3136
3137 if (!FileObject)
3139
3140 fcb = FileObject->FsContext;
3141 ccb = FileObject->FsContext2;
3142
3143 if (!fcb)
3145
3146 if (fcb != Vcb->volume_fcb)
3148
3149 if (!ccb)
3151
3153
3154 return STATUS_SUCCESS;
3155}
3156
3158 if (length < sizeof(BTRFS_UUID))
3160
3161 RtlCopyMemory(data, &Vcb->superblock.uuid, sizeof(BTRFS_UUID));
3162
3163 return STATUS_SUCCESS;
3164}
3165
3167 uint64_t devid;
3169 LIST_ENTRY* le;
3170
3171 if (length < sizeof(uint64_t))
3173
3174 if (Vcb->readonly)
3176
3177 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3179
3180 devid = *((uint64_t*)data);
3181
3182 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3183
3184 le = Vcb->devices.Flink;
3185
3186 while (le != &Vcb->devices) {
3188
3189 if (dev->devitem.dev_id == devid) {
3190 RtlZeroMemory(dev->stats, sizeof(uint64_t) * 5);
3191 dev->stats_changed = true;
3192 Vcb->stats_changed = true;
3193 Vcb->need_write = true;
3195 goto end;
3196 }
3197
3198 le = le->Flink;
3199 }
3200
3201 WARN("device %I64x not found\n", devid);
3203
3204end:
3205 ExReleaseResourceLite(&Vcb->tree_lock);
3206
3207 return Status;
3208}
3209
3212
3213 TRACE("FSCTL_GET_INTEGRITY_INFORMATION\n");
3214
3215 // STUB
3216
3217 if (!FileObject)
3219
3222
3223 fgiib->ChecksumAlgorithm = 0;
3224 fgiib->Reserved = 0;
3225 fgiib->Flags = 0;
3226 fgiib->ChecksumChunkSizeInBytes = Vcb->superblock.sector_size;
3227 fgiib->ClusterSizeInBytes = Vcb->superblock.sector_size;
3228
3229 return STATUS_SUCCESS;
3230}
3231
3233 TRACE("FSCTL_SET_INTEGRITY_INFORMATION\n");
3234
3235 // STUB
3236
3237 if (!FileObject)
3239
3242
3243 return STATUS_SUCCESS;
3244}
3245
3247 LIST_ENTRY* le;
3248
3249 le = fcb->extents.Flink;
3250 while (le != &fcb->extents) {
3252
3253 if (!ext->ignore)
3254 return ext->extent_data.type == EXTENT_TYPE_INLINE;
3255
3256 le = le->Flink;
3257 }
3258
3259 return false;
3260}
3261
3264 fcb *fcb = FileObject ? FileObject->FsContext : NULL, *sourcefcb;
3265 ccb *ccb = FileObject ? FileObject->FsContext2 : NULL, *sourceccb;
3267 PFILE_OBJECT sourcefo;
3268 uint64_t sourcelen, nbytes = 0;
3269 LIST_ENTRY rollback, *le, newexts;
3272 bool make_inline;
3273
3274 if (!ded || datalen < sizeof(DUPLICATE_EXTENTS_DATA))
3276
3277 if (Vcb->readonly)
3279
3280 if (ded->ByteCount.QuadPart == 0)
3281 return STATUS_SUCCESS;
3282
3283 if (!fcb || !ccb || fcb == Vcb->volume_fcb)
3285
3287 return STATUS_ACCESS_DENIED;
3288
3289 if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_DATA)) {
3290 WARN("insufficient privileges\n");
3291 return STATUS_ACCESS_DENIED;
3292 }
3293
3296
3297 Status = ObReferenceObjectByHandle(ded->FileHandle, 0, *IoFileObjectType, Irp->RequestorMode, (void**)&sourcefo, NULL);
3298 if (!NT_SUCCESS(Status)) {
3299 ERR("ObReferenceObjectByHandle returned %08lx\n", Status);
3300 return Status;
3301 }
3302
3303 if (sourcefo->DeviceObject != FileObject->DeviceObject) {
3304 WARN("source and destination are on different volumes\n");
3305 ObDereferenceObject(sourcefo);
3307 }
3308
3309 sourcefcb = sourcefo->FsContext;
3310 sourceccb = sourcefo->FsContext2;
3311
3312 if (!sourcefcb || !sourceccb || sourcefcb == Vcb->volume_fcb) {
3313 ObDereferenceObject(sourcefo);
3315 }
3316
3317 if (!sourcefcb->ads && !fcb->ads) {
3318 if ((ded->SourceFileOffset.QuadPart & (Vcb->superblock.sector_size - 1)) || (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1))) {
3319 ObDereferenceObject(sourcefo);
3321 }
3322
3323 if (ded->ByteCount.QuadPart & (Vcb->superblock.sector_size - 1)) {
3324 ObDereferenceObject(sourcefo);
3326 }
3327 }
3328
3329 if (Irp->RequestorMode == UserMode && (!(sourceccb->access & FILE_READ_DATA) || !(sourceccb->access & FILE_READ_ATTRIBUTES))) {
3330 WARN("insufficient privileges\n");
3331 ObDereferenceObject(sourcefo);
3332 return STATUS_ACCESS_DENIED;
3333 }
3334
3335 if (!sourcefcb->ads && sourcefcb->type != BTRFS_TYPE_FILE && sourcefcb->type != BTRFS_TYPE_SYMLINK) {
3336 ObDereferenceObject(sourcefo);
3338 }
3339
3340 sourcelen = sourcefcb->ads ? sourcefcb->adsdata.Length : sourcefcb->inode_item.st_size;
3341
3342 if (sector_align(sourcelen, Vcb->superblock.sector_size) < (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart) {
3343 ObDereferenceObject(sourcefo);
3344 return STATUS_NOT_SUPPORTED;
3345 }
3346
3347 if (fcb == sourcefcb &&
3350 WARN("source and destination are the same, and the ranges overlap\n");
3351 ObDereferenceObject(sourcefo);
3353 }
3354
3355 // fail if nocsum flag set on one file but not the other
3356 if (!fcb->ads && !sourcefcb->ads && (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) != (sourcefcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
3357 ObDereferenceObject(sourcefo);
3359 }
3360
3362 InitializeListHead(&newexts);
3363
3364 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
3365
3366 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
3367
3368 if (fcb != sourcefcb)
3369 ExAcquireResourceSharedLite(sourcefcb->Header.Resource, true);
3370
3373 goto end;
3374 }
3375
3376 if (!FsRtlFastCheckLockForRead(&sourcefcb->lock, &ded->SourceFileOffset, &ded->ByteCount, 0, FileObject, PsGetCurrentProcess())) {
3378 goto end;
3379 }
3380
3381 make_inline = fcb->ads ? false : (fcb->inode_item.st_size <= Vcb->options.max_inline || fcb_is_inline(fcb));
3382
3383 if (fcb->ads || sourcefcb->ads || make_inline || fcb_is_inline(sourcefcb)) {
3384 uint8_t* data2;
3385 ULONG bytes_read, dataoff, datalen2;
3386
3387 if (make_inline) {
3388 dataoff = (ULONG)ded->TargetFileOffset.QuadPart;
3389 datalen2 = (ULONG)fcb->inode_item.st_size;
3390 } else if (fcb->ads) {
3391 dataoff = 0;
3392 datalen2 = (ULONG)ded->ByteCount.QuadPart;
3393 } else {
3394 dataoff = ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1);
3395 datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size);
3396 }
3397
3399 if (!data2) {
3400 ERR("out of memory\n");
3402 goto end;
3403 }
3404
3405 if (dataoff > 0) {
3406 if (make_inline)
3407 Status = read_file(fcb, data2, 0, datalen2, NULL, Irp);
3408 else
3409 Status = read_file(fcb, data2, ded->TargetFileOffset.QuadPart - dataoff, dataoff, NULL, Irp);
3410
3411 if (!NT_SUCCESS(Status)) {
3412 ERR("read_file returned %08lx\n", Status);
3414 goto end;
3415 }
3416 }
3417
3418 if (sourcefcb->ads) {
3419 Status = read_stream(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, (ULONG)ded->ByteCount.QuadPart, &bytes_read);
3420 if (!NT_SUCCESS(Status)) {
3421 ERR("read_stream returned %08lx\n", Status);
3423 goto end;
3424 }
3425 } else {
3426 Status = read_file(sourcefcb, data2 + dataoff, ded->SourceFileOffset.QuadPart, ded->ByteCount.QuadPart, &bytes_read, Irp);
3427 if (!NT_SUCCESS(Status)) {
3428 ERR("read_file returned %08lx\n", Status);
3430 goto end;
3431 }
3432 }
3433
3434 if (dataoff + bytes_read < datalen2)
3435 RtlZeroMemory(data2 + dataoff + bytes_read, datalen2 - bytes_read);
3436
3437 if (fcb->ads)
3439 else if (make_inline) {
3440 uint16_t edsize;
3441 EXTENT_DATA* ed;
3442
3443 Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
3444 if (!NT_SUCCESS(Status)) {
3445 ERR("excise_extents returned %08lx\n", Status);
3447 goto end;
3448 }
3449
3450 edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + datalen2);
3451
3453 if (!ed) {
3454 ERR("out of memory\n");
3457 goto end;
3458 }
3459
3460 ed->generation = Vcb->superblock.generation;
3466
3467 RtlCopyMemory(ed->data, data2, datalen2);
3468
3469 Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, &rollback);
3470 if (!NT_SUCCESS(Status)) {
3471 ERR("add_extent_to_fcb returned %08lx\n", Status);
3473 goto end;
3474 }
3475
3476 fcb->inode_item.st_blocks += datalen2;
3477 } else {
3478 uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1));
3479
3480 Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback);
3481 if (!NT_SUCCESS(Status)) {
3482 ERR("do_write_file returned %08lx\n", Status);
3484 goto end;
3485 }
3486 }
3487
3489 } else {
3490 LIST_ENTRY* lastextle;
3491
3492 le = sourcefcb->extents.Flink;
3493 while (le != &sourcefcb->extents) {
3495
3496 if (!ext->ignore) {
3497 if (ext->offset >= (uint64_t)ded->SourceFileOffset.QuadPart + (uint64_t)ded->ByteCount.QuadPart)
3498 break;
3499
3500 if (ext->extent_data.type != EXTENT_TYPE_INLINE) {
3501 ULONG extlen = offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3502 extent* ext2;
3503 EXTENT_DATA2 *ed2s, *ed2d;
3504 chunk* c;
3505
3506 ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3507
3508 if (ext->offset + ed2s->num_bytes <= (uint64_t)ded->SourceFileOffset.QuadPart) {
3509 le = le->Flink;
3510 continue;
3511 }
3512
3514 if (!ext2) {
3515 ERR("out of memory\n");
3517 goto end;
3518 }
3519
3520 if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart)
3521 ext2->offset = ded->TargetFileOffset.QuadPart;
3522 else
3523 ext2->offset = ext->offset - ded->SourceFileOffset.QuadPart + ded->TargetFileOffset.QuadPart;
3524
3525 ext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
3526 ext2->unique = false;
3527 ext2->ignore = false;
3528 ext2->inserted = true;
3529
3530 ext2->extent_data.generation = Vcb->superblock.generation;
3531 ext2->extent_data.decoded_size = ext->extent_data.decoded_size;
3532 ext2->extent_data.compression = ext->extent_data.compression;
3533 ext2->extent_data.encryption = ext->extent_data.encryption;
3534 ext2->extent_data.encoding = ext->extent_data.encoding;
3535 ext2->extent_data.type = ext->extent_data.type;
3536
3537 ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3538
3539 ed2d->address = ed2s->address;
3540 ed2d->size = ed2s->size;
3541
3542 if (ext->offset < (uint64_t)ded->SourceFileOffset.QuadPart) {
3543 ed2d->offset = ed2s->offset + ded->SourceFileOffset.QuadPart - ext->offset;
3544 ed2d->num_bytes = min((uint64_t)ded->ByteCount.QuadPart, ed2s->num_bytes + ext->offset - ded->SourceFileOffset.QuadPart);
3545 } else {
3546 ed2d->offset = ed2s->offset;
3547 ed2d->num_bytes = min(ded->SourceFileOffset.QuadPart + ded->ByteCount.QuadPart - ext->offset, ed2s->num_bytes);
3548 }
3549
3550 if (ext->csum) {
3551 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
3552 ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3553 if (!ext2->csum) {
3554 ERR("out of memory\n");
3557 goto end;
3558 }
3559
3560 RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + (((ed2d->offset - ed2s->offset) * Vcb->csum_size) >> Vcb->sector_shift),
3561 (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift));
3562 } else {
3563 ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
3564 if (!ext2->csum) {
3565 ERR("out of memory\n");
3568 goto end;
3569 }
3570
3571 RtlCopyMemory(ext2->csum, ext->csum, (ULONG)((ed2s->size * Vcb->csum_size) >> Vcb->sector_shift));
3572 }
3573 } else
3574 ext2->csum = NULL;
3575
3576 InsertTailList(&newexts, &ext2->list_entry);
3577
3579 if (!c) {
3580 ERR("get_chunk_from_address(%I64x) failed\n", ed2s->address);
3582 goto end;
3583 }
3584
3585 Status = update_changed_extent_ref(Vcb, c, ed2s->address, ed2s->size, fcb->subvol->id, fcb->inode, ext2->offset - ed2d->offset,
3587 if (!NT_SUCCESS(Status)) {
3588 ERR("update_changed_extent_ref returned %08lx\n", Status);
3589 goto end;
3590 }
3591
3592 nbytes += ed2d->num_bytes;
3593 }
3594 }
3595
3596 le = le->Flink;
3597 }
3598
3600 if (!NT_SUCCESS(Status)) {
3601 ERR("excise_extents returned %08lx\n", Status);
3602
3603 while (!IsListEmpty(&newexts)) {
3605 ExFreePool(ext);
3606 }
3607
3608 goto end;
3609 }
3610
3611 // clear unique flags in source fcb
3612 le = sourcefcb->extents.Flink;
3613 while (le != &sourcefcb->extents) {
3615
3616 if (!ext->ignore && ext->unique && (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC)) {
3617 EXTENT_DATA2* ed2s = (EXTENT_DATA2*)ext->extent_data.data;
3618 LIST_ENTRY* le2;
3619
3620 le2 = newexts.Flink;
3621 while (le2 != &newexts) {
3623
3624 if (ext2->extent_data.type == EXTENT_TYPE_REGULAR || ext2->extent_data.type == EXTENT_TYPE_PREALLOC) {
3625 EXTENT_DATA2* ed2d = (EXTENT_DATA2*)ext2->extent_data.data;
3626
3627 if (ed2d->address == ed2s->address && ed2d->size == ed2s->size) {
3628 ext->unique = false;
3629 break;
3630 }
3631 }
3632
3633 le2 = le2->Flink;
3634 }
3635 }
3636
3637 le = le->Flink;
3638 }
3639
3640 lastextle = &fcb->extents;
3641 while (!IsListEmpty(&newexts)) {
3643
3644 add_extent(fcb, lastextle, ext);
3645 lastextle = &ext->list_entry;
3646 }
3647 }
3648
3651
3652 if (fcb->ads) {
3653 ccb->fileref->parent->fcb->inode_item.sequence++;
3654
3656 ccb->fileref->parent->fcb->inode_item.st_ctime = now;
3657
3658 ccb->fileref->parent->fcb->inode_item_changed = true;
3660 } else {
3661 fcb->inode_item.st_blocks += nbytes;
3663
3666
3667 if (!ccb->user_set_write_time) {
3670 }
3671
3672 fcb->inode_item_changed = true;
3673 fcb->extents_changed = true;
3674 }
3675
3677
3678 if (FileObject->SectionObjectPointer->DataSectionObject)
3679 CcPurgeCacheSection(FileObject->SectionObjectPointer, &ded->TargetFileOffset, (ULONG)ded->ByteCount.QuadPart, false);
3680
3682
3683end:
3684 ObDereferenceObject(sourcefo);
3685
3686 if (NT_SUCCESS(Status))
3688 else
3690
3691 if (fcb != sourcefcb)
3692 ExReleaseResourceLite(sourcefcb->Header.Resource);
3693
3694 ExReleaseResourceLite(fcb->Header.Resource);
3695
3696 ExReleaseResourceLite(&Vcb->tree_lock);
3697
3698 return Status;
3699}
3700
3703 KEY searchkey;
3706 uint8_t c = hash >> 24;
3707
3708 if (subvol->fcbs_ptrs[c]) {
3709 LIST_ENTRY* le = subvol->fcbs_ptrs[c];
3710
3711 while (le != &subvol->fcbs) {
3712 struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
3713
3714 if (fcb2->inode == inode)
3715 return STATUS_SUCCESS;
3716 else if (fcb2->hash > hash)
3717 break;
3718
3719 le = le->Flink;
3720 }
3721 }
3722
3723 searchkey.obj_id = inode;
3724 searchkey.obj_type = TYPE_INODE_ITEM;
3725 searchkey.offset = 0xffffffffffffffff;
3726
3727 Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
3728 if (!NT_SUCCESS(Status)) {
3729 ERR("find_item returned %08lx\n", Status);
3730 return Status;
3731 }
3732
3733 if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
3734 return STATUS_SUCCESS;
3735
3736 return STATUS_NOT_FOUND;
3737}
3738
3741 btrfs_mknod* bmn;
3742 fcb *parfcb, *fcb;
3743 ccb* parccb;
3744 file_ref *parfileref, *fileref;
3746 root* subvol;
3748 dir_child* dc;
3751 ANSI_STRING utf8;
3752 ULONG len, i;
3753 SECURITY_SUBJECT_CONTEXT subjcont;
3754 PSID owner;
3755 BOOLEAN defaulted;
3756
3757 TRACE("(%p, %p, %p, %lu)\n", Vcb, FileObject, data, datalen);
3758
3759 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
3761
3762 if (Vcb->readonly)
3764
3765 parfcb = FileObject->FsContext;
3766
3767 if (parfcb->type != BTRFS_TYPE_DIRECTORY) {
3768 WARN("trying to create file in something other than a directory\n");
3770 }
3771
3772 if (is_subvol_readonly(parfcb->subvol, Irp))
3773 return STATUS_ACCESS_DENIED;
3774
3775 parccb = FileObject->FsContext2;
3776 parfileref = parccb->fileref;
3777
3778 if (!parfileref)
3780
3781 if (datalen < sizeof(btrfs_mknod))
3783
3784 bmn = (btrfs_mknod*)data;
3785
3786 if (datalen < offsetof(btrfs_mknod, name[0]) + bmn->namelen || bmn->namelen < sizeof(WCHAR))
3788
3789 if (bmn->type == BTRFS_TYPE_UNKNOWN || bmn->type > BTRFS_TYPE_SYMLINK)
3791
3792 if ((bmn->type == BTRFS_TYPE_DIRECTORY && !(parccb->access & FILE_ADD_SUBDIRECTORY)) ||
3793 (bmn->type != BTRFS_TYPE_DIRECTORY && !(parccb->access & FILE_ADD_FILE))) {
3794 WARN("insufficient privileges\n");
3795 return STATUS_ACCESS_DENIED;
3796 }
3797
3798 if (bmn->inode != 0) {
3799 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
3801 }
3802
3803 for (i = 0; i < bmn->namelen / sizeof(WCHAR); i++) {
3804 if (bmn->name[i] == 0 || bmn->name[i] == '/')
3806 }
3807
3808 // don't allow files called . or ..
3809 if (bmn->name[0] == '.' && (bmn->namelen == sizeof(WCHAR) || (bmn->namelen == 2 * sizeof(WCHAR) && bmn->name[1] == '.')))
3811
3812 Status = utf16_to_utf8(NULL, 0, &len, bmn->name, bmn->namelen);
3813 if (!NT_SUCCESS(Status)) {
3814 ERR("utf16_to_utf8 returned %08lx\n", Status);
3815 return Status;
3816 }
3817
3818 if (len == 0) {
3819 ERR("utf16_to_utf8 returned a length of 0\n");
3820 return STATUS_INTERNAL_ERROR;
3821 }
3822
3823 if (len > 0xffff) {
3824 ERR("len was too long (%lx)\n", len);
3826 }
3827
3828 utf8.MaximumLength = utf8.Length = (USHORT)len;
3830
3831 if (!utf8.Buffer) {
3832 ERR("out of memory\n");
3834 }
3835
3836 Status = utf16_to_utf8(utf8.Buffer, len, &len, bmn->name, bmn->namelen);
3837 if (!NT_SUCCESS(Status)) {
3838 ERR("utf16_to_utf8 failed with error %08lx\n", Status);
3839 ExFreePool(utf8.Buffer);
3840 return Status;
3841 }
3842
3843 name.Length = name.MaximumLength = bmn->namelen;
3844 name.Buffer = bmn->name;
3845
3846 Status = find_file_in_dir(&name, parfcb, &subvol, &inode, &dc, true);
3848 ERR("find_file_in_dir returned %08lx\n", Status);
3849 goto end;
3850 }
3851
3852 if (NT_SUCCESS(Status)) {
3853 WARN("filename already exists\n");
3855 goto end;
3856 }
3857
3860
3862 if (!fcb) {
3863 ERR("out of memory\n");
3865 goto end;
3866 }
3867
3868 fcb->Vcb = Vcb;
3869
3870 fcb->inode_item.generation = Vcb->superblock.generation;
3871 fcb->inode_item.transid = Vcb->superblock.generation;
3872 fcb->inode_item.st_size = 0;
3875 fcb->inode_item.st_nlink = 1;
3879
3880 if (bmn->type == BTRFS_TYPE_BLOCKDEV || bmn->type == BTRFS_TYPE_CHARDEV)
3881 fcb->inode_item.st_rdev = (minor(bmn->st_rdev) & 0xFFFFF) | ((major(bmn->st_rdev) & 0xFFFFFFFFFFF) << 20);
3882 else
3883 fcb->inode_item.st_rdev = 0;
3884
3885 fcb->inode_item.flags = 0;
3886 fcb->inode_item.sequence = 1;
3891
3892 if (bmn->type == BTRFS_TYPE_DIRECTORY)
3894 else if (bmn->type == BTRFS_TYPE_CHARDEV)
3896 else if (bmn->type == BTRFS_TYPE_BLOCKDEV)
3898 else if (bmn->type == BTRFS_TYPE_FIFO)
3900 else if (bmn->type == BTRFS_TYPE_SOCKET)
3902 else if (bmn->type == BTRFS_TYPE_SYMLINK)
3904 else
3906
3907 if (bmn->type != BTRFS_TYPE_DIRECTORY)
3908 fcb->inode_item.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); // remove executable bit if not directory
3909
3910 // inherit nodatacow flag from parent directory
3911 if (parfcb->inode_item.flags & BTRFS_INODE_NODATACOW) {
3913
3914 if (bmn->type != BTRFS_TYPE_DIRECTORY)
3916 }
3917
3920
3923
3924 fcb->inode_item_changed = true;
3925
3926 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
3927 fcb->Header.AllocationSize.QuadPart = 0;
3928 fcb->Header.FileSize.QuadPart = 0;
3929 fcb->Header.ValidDataLength.QuadPart = 0;
3930
3931 fcb->atts = 0;
3932
3933 if (bmn->name[0] == '.')
3935
3936 if (bmn->type == BTRFS_TYPE_DIRECTORY)
3938
3939 fcb->atts_changed = false;
3940
3942 fcb->subvol = parfcb->subvol;
3943
3944 SeCaptureSubjectContext(&subjcont);
3945
3946 Status = SeAssignSecurityEx(parfileref ? parfileref->fcb->sd : NULL, NULL, (void**)&fcb->sd, NULL, fcb->type == BTRFS_TYPE_DIRECTORY,
3948
3949 if (!NT_SUCCESS(Status)) {
3950 ERR("SeAssignSecurityEx returned %08lx\n", Status);
3951 reap_fcb(fcb);
3952 goto end;
3953 }
3954
3955 Status = RtlGetOwnerSecurityDescriptor(fcb->sd, &owner, &defaulted);
3956 if (!NT_SUCCESS(Status)) {
3957 WARN("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
3958 fcb->sd_dirty = true;
3959 } else {
3960 fcb->inode_item.st_uid = sid_to_uid(owner);
3962 }
3963
3964 find_gid(fcb, parfcb, &subjcont);
3965
3966 ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
3967 acquire_fcb_lock_exclusive(Vcb);
3968
3969 if (bmn->inode == 0) {
3970 fcb->inode = InterlockedIncrement64(&parfcb->subvol->lastinode);
3971 fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
3972 } else {
3973 if (bmn->inode > (uint64_t)parfcb->subvol->lastinode) {
3974 fcb->inode = parfcb->subvol->lastinode = bmn->inode;
3975 fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
3976 } else {
3977 uint32_t hash = calc_crc32c(0xffffffff, (uint8_t*)&bmn->inode, sizeof(uint64_t));
3978
3980 if (NT_SUCCESS(Status)) { // STATUS_SUCCESS means inode found
3981 release_fcb_lock(Vcb);
3982 ExReleaseResourceLite(&Vcb->fileref_lock);
3983
3984 WARN("inode collision\n");
3986 goto end;
3987 } else if (Status != STATUS_NOT_FOUND) {
3988 ERR("check_inode_used returned %08lx\n", Status);
3989
3990 release_fcb_lock(Vcb);
3991 ExReleaseResourceLite(&Vcb->fileref_lock);
3992 goto end;
3993 }
3994
3995 fcb->inode = bmn->inode;
3996 fcb->hash = hash;
3997 }
3998 }
3999
4000 fcb->inode = inode;
4001 fcb->type = bmn->type;
4002
4004 if (!fileref) {
4005 release_fcb_lock(Vcb);
4006 ExReleaseResourceLite(&Vcb->fileref_lock);
4007
4008 ERR("out of memory\n");
4009 reap_fcb(fcb);
4011 goto end;
4012 }
4013
4014 fileref->fcb = fcb;
4015
4016 fcb->created = true;
4017 fileref->created = true;
4018
4019 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
4020 fcb->subvol->root_item.ctime = now;
4021
4022 fileref->parent = parfileref;
4023
4026
4027 Status = add_dir_child(fileref->parent->fcb, fcb->inode, false, &utf8, &name, fcb->type, &dc);
4028 if (!NT_SUCCESS(Status))
4029 WARN("add_dir_child returned %08lx\n", Status);
4030
4031 fileref->dc = dc;
4032 dc->fileref = fileref;
4033
4034 ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, true);
4035 InsertTailList(&parfileref->children, &fileref->list_entry);
4036 ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
4037
4038 increase_fileref_refcount(parfileref);
4039
4040 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
4042 if (!fcb->hash_ptrs) {
4043 release_fcb_lock(Vcb);
4044 ExReleaseResourceLite(&Vcb->fileref_lock);
4045
4046 ERR("out of memory\n");
4049 goto end;
4050 }
4051
4052 RtlZeroMemory(fcb->hash_ptrs, sizeof(LIST_ENTRY*) * 256);
4053
4055 if (!fcb->hash_ptrs_uc) {
4056 release_fcb_lock(Vcb);
4057 ExReleaseResourceLite(&Vcb->fileref_lock);
4058
4059 ERR("out of memory\n");
4062 goto end;
4063 }
4064
4065 RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
4066 }
4067
4069 InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
4070
4071 if (bmn->type == BTRFS_TYPE_DIRECTORY)
4072 fileref->fcb->fileref = fileref;
4073
4074 ExAcquireResourceExclusiveLite(parfcb->Header.Resource, true);
4075 parfcb->inode_item.st_size += utf8.Length * 2;
4076 parfcb->inode_item.transid = Vcb->superblock.generation;
4077 parfcb->inode_item.sequence++;
4078
4079 if (!parccb->user_set_change_time)
4080 parfcb->inode_item.st_ctime = now;
4081
4082 if (!parccb->user_set_write_time)
4083 parfcb->inode_item.st_mtime = now;
4084
4085 parfcb->subvol->fcbs_version++;
4086
4087 ExReleaseResourceLite(parfcb->Header.Resource);
4088 release_fcb_lock(Vcb);
4089 ExReleaseResourceLite(&Vcb->fileref_lock);
4090
4091 parfcb->inode_item_changed = true;
4092 mark_fcb_dirty(parfcb);
4093
4095
4096 if (!parccb->user_set_write_time)
4098
4100
4101end:
4102
4103 ExFreePool(utf8.Buffer);
4104
4105 return Status;
4106}
4107
4109 if (!r->dirty) {
4110 r->dirty = true;
4111
4112 ExAcquireResourceExclusiveLite(&Vcb->dirty_subvols_lock, true);
4113 InsertTailList(&Vcb->dirty_subvols, &r->list_entry_dirty);
4114 ExReleaseResourceLite(&Vcb->dirty_subvols_lock);
4115 }
4116
4117 Vcb->need_write = true;
4118}
4119
4122 fcb* fcb;
4126
4127 TRACE("(%p, %p, %p, %lu)\n", Vcb, FileObject, data, datalen);
4128
4129 if (!data || datalen < sizeof(btrfs_received_subvol))
4131
4132 if (!FileObject || !FileObject->FsContext || FileObject->FsContext == Vcb->volume_fcb)
4134
4135 fcb = FileObject->FsContext;
4136
4137 if (!fcb->subvol)
4139
4140 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
4142
4143 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4144
4145 if (fcb->subvol->root_item.rtransid != 0) {
4146 WARN("subvol already has received information set\n");
4148 goto end;
4149 }
4150
4153
4154 RtlCopyMemory(&fcb->subvol->root_item.received_uuid, &brs->uuid, sizeof(BTRFS_UUID));
4155 fcb->subvol->root_item.stransid = brs->generation;
4156 fcb->subvol->root_item.rtransid = Vcb->superblock.generation;
4157 fcb->subvol->root_item.rtime = now;
4158
4159 fcb->subvol->received = true;
4161
4163
4164end:
4165 ExReleaseResourceLite(&Vcb->tree_lock);
4166
4167 return Status;
4168}
4169
4171 LIST_ENTRY* le;
4172 btrfs_set_xattr* bsxa;
4173 ULONG reqlen = (ULONG)offsetof(btrfs_set_xattr, data[0]);
4174 fcb* fcb;
4175 ccb* ccb;
4176
4177 if (!data || datalen < reqlen)
4179
4180 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4182
4183 fcb = FileObject->FsContext;
4184 ccb = FileObject->FsContext2;
4185
4186 if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) && processor_mode == UserMode) {
4187 WARN("insufficient privileges\n");
4188 return STATUS_ACCESS_DENIED;
4189 }
4190
4191 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
4192
4193 le = fcb->xattrs.Flink;
4194 while (le != &fcb->xattrs) {
4196
4197 if (xa->valuelen > 0)
4198 reqlen += (ULONG)offsetof(btrfs_set_xattr, data[0]) + xa->namelen + xa->valuelen;
4199
4200 le = le->Flink;
4201 }
4202
4203 if (datalen < reqlen) {
4204 ExReleaseResourceLite(fcb->Header.Resource);
4206 }
4207
4208 bsxa = (btrfs_set_xattr*)data;
4209
4210 if (reqlen > 0) {
4211 le = fcb->xattrs.Flink;
4212 while (le != &fcb->xattrs) {
4214
4215 if (xa->valuelen > 0) {
4216 bsxa->namelen = xa->namelen;
4217 bsxa->valuelen = xa->valuelen;
4218 memcpy(bsxa->data, xa->data, xa->namelen + xa->valuelen);
4219
4220 bsxa = (btrfs_set_xattr*)&bsxa->data[xa->namelen + xa->valuelen];
4221 }
4222
4223 le = le->Flink;
4224 }
4225 }
4226
4227 bsxa->namelen = 0;
4228 bsxa->valuelen = 0;
4229
4230 ExReleaseResourceLite(fcb->Header.Resource);
4231
4232 return STATUS_SUCCESS;
4233}
4234
4237 btrfs_set_xattr* bsxa;
4238 xattr* xa;
4239 fcb* fcb;
4240 ccb* ccb;
4241 LIST_ENTRY* le;
4242
4243 static const char stream_pref[] = "user.";
4244
4245 TRACE("(%p, %p, %p, %lu)\n", Vcb, FileObject, data, datalen);
4246
4247 if (!data || datalen < sizeof(btrfs_set_xattr))
4249
4250 bsxa = (btrfs_set_xattr*)data;
4251
4252 if (datalen < offsetof(btrfs_set_xattr, data[0]) + bsxa->namelen + bsxa->valuelen)
4254
4255 if (bsxa->namelen + bsxa->valuelen + sizeof(tree_header) + sizeof(leaf_node) + offsetof(DIR_ITEM, name[0]) > Vcb->superblock.node_size)
4257
4258 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4260
4261 if (Vcb->readonly)
4263
4264 fcb = FileObject->FsContext;
4265 ccb = FileObject->FsContext2;
4266
4268 return STATUS_ACCESS_DENIED;
4269
4270 if (!(ccb->access & FILE_WRITE_ATTRIBUTES) && Irp->RequestorMode == UserMode) {
4271 WARN("insufficient privileges\n");
4272 return STATUS_ACCESS_DENIED;
4273 }
4274
4275 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4276
4277 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
4278
4279 if (bsxa->namelen == sizeof(EA_NTACL) - 1 && RtlCompareMemory(bsxa->data, EA_NTACL, sizeof(EA_NTACL) - 1) == sizeof(EA_NTACL) - 1) {
4280 if ((!(ccb->access & WRITE_DAC) || !(ccb->access & WRITE_OWNER)) && Irp->RequestorMode == UserMode) {
4281 WARN("insufficient privileges\n");
4283 goto end;
4284 }
4285
4286 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode)) {
4288 goto end;
4289 }
4290
4291 if (fcb->sd)
4292 ExFreePool(fcb->sd);
4293
4294 if (bsxa->valuelen > 0 && RtlValidRelativeSecurityDescriptor(bsxa->data + bsxa->namelen, bsxa->valuelen, 0)) {
4296 if (!fcb->sd) {
4297 ERR("out of memory\n");
4299 goto end;
4300 }
4301
4302 RtlCopyMemory(fcb->sd, bsxa->data + bsxa->namelen, bsxa->valuelen);
4303 } else if (fcb->sd)
4304 fcb->sd = NULL;
4305
4306 fcb->sd_dirty = true;
4307
4308 if (!fcb->sd) {
4309 fcb_get_sd(fcb, ccb->fileref->parent->fcb, false, Irp);
4310 fcb->sd_deleted = true;
4311 }
4312
4314
4316 goto end;
4317 } else if (bsxa->namelen == sizeof(EA_DOSATTRIB) - 1 && RtlCompareMemory(bsxa->data, EA_DOSATTRIB, sizeof(EA_DOSATTRIB) - 1) == sizeof(EA_DOSATTRIB) - 1) {
4318 ULONG atts;
4319
4320 if (bsxa->valuelen > 0 && get_file_attributes_from_xattr(bsxa->data + bsxa->namelen, bsxa->valuelen, &atts)) {
4321 fcb->atts = atts;
4322
4325 else if (fcb->type == BTRFS_TYPE_SYMLINK)
4327
4328 if (fcb->inode == SUBVOL_ROOT_INODE) {
4329 if (fcb->subvol->root_item.flags & BTRFS_SUBVOL_READONLY)
4331 else
4332 fcb->atts &= ~FILE_ATTRIBUTE_READONLY;
4333 }
4334
4335 fcb->atts_deleted = false;
4336 } else {
4337 bool hidden = ccb->fileref && ccb->fileref->dc && ccb->fileref->dc->utf8.Buffer && ccb->fileref->dc->utf8.Buffer[0] == '.';
4338
4340 fcb->atts_deleted = true;
4341 }
4342
4343 fcb->atts_changed = true;
4345
4347 goto end;
4348 } else if (bsxa->namelen == sizeof(EA_REPARSE) - 1 && RtlCompareMemory(bsxa->data, EA_REPARSE, sizeof(EA_REPARSE) - 1) == sizeof(EA_REPARSE) - 1) {
4349 if (fcb->reparse_xattr.Buffer) {
4353 }
4354
4355 if (bsxa->valuelen > 0) {
4357 if (!fcb->reparse_xattr.Buffer) {
4358 ERR("out of memory\n");
4360 goto end;
4361 }
4362
4363 RtlCopyMemory(fcb->reparse_xattr.Buffer, bsxa->data + bsxa->namelen, bsxa->valuelen);
4365 }
4366
4367 fcb->reparse_xattr_changed = true;
4369
4371 goto end;
4372 } else if (bsxa->namelen == sizeof(EA_EA) - 1 && RtlCompareMemory(bsxa->data, EA_EA, sizeof(EA_EA) - 1) == sizeof(EA_EA) - 1) {
4373 if (!(ccb->access & FILE_WRITE_EA) && Irp->RequestorMode == UserMode) {
4374 WARN("insufficient privileges\n");
4376 goto end;
4377 }
4378
4379 if (fcb->ea_xattr.Buffer) {
4383 }
4384
4385 fcb->ealen = 0;
4386
4387 if (bsxa->valuelen > 0) {
4388 ULONG offset;
4389
4391
4392 if (!NT_SUCCESS(Status))
4393 WARN("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
4394 else {
4396
4398 if (!fcb->ea_xattr.Buffer) {
4399 ERR("out of memory\n");
4401 goto end;
4402 }
4403
4404 RtlCopyMemory(fcb->ea_xattr.Buffer, bsxa->data + bsxa->namelen, bsxa->valuelen);
4405
4407
4408 fcb->ealen = 4;
4409
4410 // calculate ealen
4411 eainfo = (FILE_FULL_EA_INFORMATION*)(bsxa->data + bsxa->namelen);
4412 do {
4413 fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
4414
4415 if (eainfo->NextEntryOffset == 0)
4416 break;
4417
4418 eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
4419 } while (true);
4420 }
4421 }
4422
4423 fcb->ea_changed = true;
4425
4427 goto end;
4428 } else if (bsxa->namelen == sizeof(EA_CASE_SENSITIVE) - 1 && RtlCompareMemory(bsxa->data, EA_CASE_SENSITIVE, sizeof(EA_CASE_SENSITIVE) - 1) == sizeof(EA_CASE_SENSITIVE) - 1) {
4429 if (bsxa->valuelen > 0 && bsxa->data[bsxa->namelen] == '1') {
4430 fcb->case_sensitive = true;
4432 }
4433
4435 goto end;
4436 } else if (bsxa->namelen == sizeof(EA_PROP_COMPRESSION) - 1 && RtlCompareMemory(bsxa->data, EA_PROP_COMPRESSION, sizeof(EA_PROP_COMPRESSION) - 1) == sizeof(EA_PROP_COMPRESSION) - 1) {
4437 static const char lzo[] = "lzo";
4438 static const char zlib[] = "zlib";
4439 static const char zstd[] = "zstd";
4440
4441 if (bsxa->valuelen == sizeof(zstd) - 1 && RtlCompareMemory(bsxa->data + bsxa->namelen, zstd, bsxa->valuelen) == bsxa->valuelen)
4443 else if (bsxa->valuelen == sizeof(lzo) - 1 && RtlCompareMemory(bsxa->data + bsxa->namelen, lzo, bsxa->valuelen) == bsxa->valuelen)
4445 else if (bsxa->valuelen == sizeof(zlib) - 1 && RtlCompareMemory(bsxa->data + bsxa->namelen, zlib, bsxa->valuelen) == bsxa->valuelen)
4447 else
4449
4452 fcb->inode_item_changed = true;
4453 }
4454
4457
4459 goto end;
4460 } else if (bsxa->namelen >= (sizeof(stream_pref) - 1) && RtlCompareMemory(bsxa->data, stream_pref, sizeof(stream_pref) - 1) == sizeof(stream_pref) - 1) {
4461 // don't allow xattrs beginning with user., as these appear as streams instead
4463 goto end;
4464 }
4465
4467 if (!xa) {
4468 ERR("out of memory\n");
4470 goto end;
4471 }
4472
4473 le = fcb->xattrs.Flink;
4474 while (le != &fcb->xattrs) {
4476
4477 if (xa2->namelen == bsxa->namelen && RtlCompareMemory(xa2->data, bsxa->data, xa2->namelen) == xa2->namelen) {
4479 ExFreePool(xa2);
4480 break;
4481 }
4482
4483 le = le->Flink;
4484 }
4485
4486 xa->namelen = bsxa->namelen;
4487 xa->valuelen = bsxa->valuelen;
4488 xa->dirty = true;
4489 RtlCopyMemory(xa->data, bsxa->data, bsxa->namelen + bsxa->valuelen);
4490
4492
4493 fcb->xattrs_changed = true;
4495
4497
4498end:
4499 ExReleaseResourceLite(fcb->Header.Resource);
4500
4501 ExReleaseResourceLite(&Vcb->tree_lock);
4502
4503 return Status;
4504}
4505
4507 fcb* fcb;
4508 ccb* ccb;
4509
4510 TRACE("(%p, %p)\n", Vcb, FileObject);
4511
4512 // "Reserving" a readonly subvol allows the calling process to write into it until the handle is closed.
4513
4514 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4516
4517 if (!FileObject || !FileObject->FsContext || !FileObject->FsContext2 || FileObject->FsContext == Vcb->volume_fcb)
4519
4520 fcb = FileObject->FsContext;
4521 ccb = FileObject->FsContext2;
4522
4523 if (!(fcb->subvol->root_item.flags & BTRFS_SUBVOL_READONLY))
4525
4526 if (fcb->subvol->reserved)
4528
4529 fcb->subvol->reserved = PsGetCurrentProcess();
4530 ccb->reserving = true;
4531
4532 return STATUS_SUCCESS;
4533}
4534
4536 LIST_ENTRY* le;
4537 root* r = NULL;
4539 file_ref* fr;
4541
4542 le = Vcb->roots.Flink;
4543 while (le != &Vcb->roots) {
4545
4546 if (r2->id == id) {
4547 r = r2;
4548 break;
4549 }
4550
4551 le = le->Flink;
4552 }
4553
4554 if (!r) {
4555 ERR("couldn't find subvol %I64x\n", id);
4556 return STATUS_INTERNAL_ERROR;
4557 }
4558
4559 ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
4560
4561 Status = open_fileref_by_inode(Vcb, r, r->root_item.objid, &fr, Irp);
4562 if (!NT_SUCCESS(Status)) {
4563 ExReleaseResourceLite(&Vcb->fileref_lock);
4564 ERR("open_fileref_by_inode returned %08lx\n", Status);
4565 return Status;
4566 }
4567
4568 us.Buffer = out;
4569 us.Length = 0;
4570 us.MaximumLength = (USHORT)min(0xffff, outlen) - sizeof(WCHAR);
4571
4573
4575 out[us.Length / sizeof(WCHAR)] = 0;
4576 else
4577 ERR("fileref_get_filename returned %08lx\n", Status);
4578
4579 free_fileref(fr);
4580
4581 ExReleaseResourceLite(&Vcb->fileref_lock);
4582
4583 return Status;
4584}
4585
4586static NTSTATUS find_subvol(device_extension* Vcb, void* in, ULONG inlen, void* out, ULONG outlen, PIRP Irp) {
4587 btrfs_find_subvol* bfs;
4590 KEY searchkey;
4591
4592 if (!in || inlen < sizeof(btrfs_find_subvol))
4594
4595 if (!out || outlen < sizeof(WCHAR))
4597
4598 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4600
4601 bfs = (btrfs_find_subvol*)in;
4602
4603 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4604
4605 if (!Vcb->uuid_root) {
4606 ERR("couldn't find uuid root\n");
4608 goto end;
4609 }
4610
4611 RtlCopyMemory(&searchkey.obj_id, &bfs->uuid, sizeof(uint64_t));
4612 searchkey.obj_type = TYPE_SUBVOL_UUID;
4613 RtlCopyMemory(&searchkey.offset, &bfs->uuid.uuid[sizeof(uint64_t)], sizeof(uint64_t));
4614
4615 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4616
4617 if (!NT_SUCCESS(Status)) {
4618 ERR("find_item returned %08lx\n", Status);
4619 goto end;
4620 }
4621
4622 if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4623 uint64_t* id = (uint64_t*)tp.item->data;
4624
4625 if (bfs->ctransid != 0) {
4626 KEY searchkey2;
4627 traverse_ptr tp2;
4628
4629 searchkey2.obj_id = *id;
4630 searchkey2.obj_type = TYPE_ROOT_ITEM;
4631 searchkey2.offset = 0xffffffffffffffff;
4632
4633 Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4634 if (!NT_SUCCESS(Status)) {
4635 ERR("find_item returned %08lx\n", Status);
4636 goto end;
4637 }
4638
4639 if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4640 tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4641 ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4642
4643 if (ri->ctransid == bfs->ctransid) {
4644 TRACE("found subvol %I64x\n", *id);
4645 Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4646 goto end;
4647 }
4648 }
4649 } else {
4650 TRACE("found subvol %I64x\n", *id);
4651 Status = get_subvol_path(Vcb, *id, out, outlen, Irp);
4652 goto end;
4653 }
4654 }
4655
4656 searchkey.obj_type = TYPE_SUBVOL_REC_UUID;
4657
4658 Status = find_item(Vcb, Vcb->uuid_root, &tp, &searchkey, false, Irp);
4659
4660 if (!NT_SUCCESS(Status)) {
4661 ERR("find_item returned %08lx\n", Status);
4662 goto end;
4663 }
4664
4665 if (!keycmp(searchkey, tp.item->key) && tp.item->size >= sizeof(uint64_t)) {
4667 ULONG i;
4668
4669 for (i = 0; i < tp.item->size / sizeof(uint64_t); i++) {
4670 if (bfs->ctransid != 0) {
4671 KEY searchkey2;
4672 traverse_ptr tp2;
4673
4674 searchkey2.obj_id = ids[i];
4675 searchkey2.obj_type = TYPE_ROOT_ITEM;
4676 searchkey2.offset = 0xffffffffffffffff;
4677
4678 Status = find_item(Vcb, Vcb->root_root, &tp2, &searchkey2, false, Irp);
4679 if (!NT_SUCCESS(Status)) {
4680 ERR("find_item returned %08lx\n", Status);
4681 goto end;
4682 }
4683
4684 if (tp2.item->key.obj_id == searchkey2.obj_id && tp2.item->key.obj_type == searchkey2.obj_type &&
4685 tp2.item->size >= offsetof(ROOT_ITEM, otransid)) {
4686 ROOT_ITEM* ri = (ROOT_ITEM*)tp2.item->data;
4687
4688 if (ri->ctransid == bfs->ctransid) {
4689 TRACE("found subvol %I64x\n", ids[i]);
4690 Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4691 goto end;
4692 }
4693 }
4694 } else {
4695 TRACE("found subvol %I64x\n", ids[i]);
4696 Status = get_subvol_path(Vcb, ids[i], out, outlen, Irp);
4697 goto end;
4698 }
4699 }
4700 }
4701
4703
4704end:
4705 ExReleaseResourceLite(&Vcb->tree_lock);
4706
4707 return Status;
4708}
4709
4713 LIST_ENTRY* le;
4714 device* dev = NULL;
4715
4716 TRACE("(%p, %p, %lu)\n", Vcb, data, len);
4717
4718 if (!data || len < sizeof(btrfs_resize) || (br->size & (Vcb->superblock.sector_size - 1)) != 0)
4720
4721 if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode))
4723
4724 if (Vcb->readonly)
4726
4727 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
4728
4729 le = Vcb->devices.Flink;
4730 while (le != &Vcb->devices) {
4732
4733 if (dev2->devitem.dev_id == br->device) {
4734 dev = dev2;
4735 break;
4736 }
4737
4738 le = le->Flink;
4739 }
4740
4741 if (!dev) {
4742 ERR("could not find device %I64x\n", br->device);
4744 goto end;
4745 }
4746
4747 if (!dev->devobj) {
4748 ERR("trying to resize missing device\n");
4750 goto end;
4751 }
4752
4753 if (dev->readonly) {
4754 ERR("trying to resize readonly device\n");
4756 goto end;
4757 }
4758
4759 if (br->size > 0 && dev->devitem.num_bytes == br->size) {
4760 TRACE("size unchanged, returning STATUS_SUCCESS\n");
4762 goto end;
4763 }
4764
4765 if (br->size > 0 && dev->devitem.num_bytes > br->size) { // shrink device
4766 bool need_balance = true;
4767 uint64_t old_size, delta;
4768
4769 le = dev->space.Flink;
4770 while (le != &dev->space) {
4772
4773 if (s->address <= br->size && s->address + s->size >= dev->devitem.num_bytes) {
4774 need_balance = false;
4775 break;
4776 }
4777
4778 le = le->Flink;
4779 }
4780
4781 delta = dev->devitem.num_bytes - br->size;
4782
4783 if (need_balance) {
4785 int i;
4786
4787 if (Vcb->balance.thread) {
4788 WARN("balance already running\n");
4790 goto end;
4791 }
4792
4793 RtlZeroMemory(Vcb->balance.opts, sizeof(btrfs_balance_opts) * 3);
4794
4795 for (i = 0; i < 3; i++) {
4797 Vcb->balance.opts[i].devid = dev->devitem.dev_id;
4798 Vcb->balance.opts[i].drange_start = br->size;
4799 Vcb->balance.opts[i].drange_end = dev->devitem.num_bytes;
4800 }
4801
4802 Vcb->balance.paused = false;
4803 Vcb->balance.shrinking = true;
4804 Vcb->balance.status = STATUS_SUCCESS;
4805 KeInitializeEvent(&Vcb->balance.event, NotificationEvent, !Vcb->balance.paused);
4806
4807 space_list_subtract2(&dev->space, NULL, br->size, delta, NULL, NULL);
4808
4810
4811 Status = PsCreateSystemThread(&Vcb->balance.thread, 0, &oa, NULL, NULL, balance_thread, Vcb);
4812 if (!NT_SUCCESS(Status)) {
4813 ERR("PsCreateSystemThread returned %08lx\n", Status);
4814 goto end;
4815 }
4816
4818
4819 goto end;
4820 }
4821
4822 old_size = dev->devitem.num_bytes;
4823 dev->devitem.num_bytes = br->size;
4824
4826 if (!NT_SUCCESS(Status)) {
4827 ERR("update_dev_item returned %08lx\n", Status);
4828 dev->devitem.num_bytes = old_size;
4829 goto end;
4830 }
4831
4832 space_list_subtract2(&dev->space, NULL, br->size, delta, NULL, NULL);
4833
4834 Vcb->superblock.total_bytes -= delta;
4835 } else { // extend device
4837 uint64_t old_size, delta;
4838
4840 &gli, sizeof(gli), true, NULL);
4841 if (!NT_SUCCESS(Status)) {
4842 ERR("IOCTL_DISK_GET_LENGTH_INFO returned %08lx\n", Status);
4843 goto end;
4844 }
4845
4846 if (br->size == 0) {
4847 br->size = gli.Length.QuadPart;
4848
4849 if (dev->devitem.num_bytes == br->size) {
4850 TRACE("size unchanged, returning STATUS_SUCCESS\n");
4852 goto end;
4853 }
4854
4855 if (br->size == 0) {
4856 ERR("IOCTL_DISK_GET_LENGTH_INFO returned 0 length\n");
4858 goto end;
4859 }
4860 } else if ((uint64_t)gli.Length.QuadPart < br->size) {
4861 ERR("device was %I64x bytes, trying to extend to %I64x\n", gli.Length.QuadPart, br->size);
4863 goto end;
4864 }
4865
4866 delta = br->size - dev->devitem.num_bytes;
4867
4868 old_size = dev->devitem.num_bytes;
4869 dev->devitem.num_bytes = br->size;
4870
4872 if (!NT_SUCCESS(Status)) {
4873 ERR("update_dev_item returned %08lx\n", Status);
4874 dev->devitem.num_bytes = old_size;
4875 goto end;
4876 }
4877
4878 space_list_add2(&dev->space, NULL, dev->devitem.num_bytes, delta, NULL, NULL);
4879
4880 Vcb->superblock.total_bytes += delta;
4881 }
4882
4884 Vcb->need_write = true;
4885
4886end:
4887 ExReleaseResourceLite(&Vcb->tree_lock);
4888
4889 if (NT_SUCCESS(Status))
4891
4892 return Status;
4893}
4894
4897 PIRP Irp = *Pirp;
4899 uint32_t fsctl = IrpSp->Parameters.FileSystemControl.FsControlCode;
4901 fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4902 ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4904#if (NTDDI_VERSION >= NTDDI_WIN7)
4905 PREQUEST_OPLOCK_INPUT_BUFFER buf = NULL;
4906 bool oplock_request = false, oplock_ack = false;
4907#else
4908 bool oplock_request = false;
4909#endif
4910 ULONG oplock_count = 0;
4911#ifdef __REACTOS__
4912 bool shared_request;
4913#endif
4914
4915 if (!fcb) {
4916 ERR("fcb was NULL\n");
4918 }
4919
4920 if (!fileref) {
4921 ERR("fileref was NULL\n");
4923 }
4924
4927
4928#if (NTDDI_VERSION >= NTDDI_WIN7)
4929 if (fsctl == FSCTL_REQUEST_OPLOCK) {
4930 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER))
4932
4933 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))
4935
4936 buf = Irp->AssociatedIrp.SystemBuffer;
4937
4938 // flags are mutually exclusive
4939 if (buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST && buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK)
4941
4942 oplock_request = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
4943 oplock_ack = buf->Flags & REQUEST_OPLOCK_INPUT_FLAG_ACK;
4944
4945 if (!oplock_request && !oplock_ack)
4947 }
4948#endif
4949
4950#if (NTDDI_VERSION >= NTDDI_WIN7)
4951 bool shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2) || (fsctl == FSCTL_REQUEST_OPLOCK && !(buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_WRITE));
4952#else
4953 shared_request = (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2);
4954#endif
4955
4956#if (NTDDI_VERSION >= NTDDI_WIN7)
4957 if (fcb->type == BTRFS_TYPE_DIRECTORY && (fsctl != FSCTL_REQUEST_OPLOCK || !shared_request)) {
4958#else
4959 if (fcb->type == BTRFS_TYPE_DIRECTORY && !shared_request) {
4960#endif
4961 WARN("oplock requests on directories can only be for read or read-handle oplocks\n");
4963 }
4964
4965 ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
4966
4967 ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
4968
4970 fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2 || oplock_request) {
4971 if (shared_request) {
4972 if (fcb->type == BTRFS_TYPE_FILE) {
4974 oplock_count = !fFsRtlCheckLockForOplockRequest(&fcb->lock, &fcb->Header.AllocationSize);
4977 else
4978 oplock_count = FsRtlAreThereCurrentFileLocks(&fcb->lock);
4979 }
4980 } else
4981 oplock_count = fileref->open_count;
4982 }
4983
4984#if (NTDDI_VERSION >= NTDDI_WIN7)
4985 if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK ||
4986 (fsctl == FSCTL_REQUEST_OPLOCK && buf->RequestedOplockLevel & OPLOCK_LEVEL_CACHE_HANDLE)) &&
4987#else
4989#endif
4990 fileref->delete_on_close) {
4991 ExReleaseResourceLite(fcb->Header.Resource);
4992 ExReleaseResourceLite(&Vcb->tree_lock);
4993 return STATUS_DELETE_PENDING;
4994 }
4995
4996 Status = FsRtlOplockFsctrl(fcb_oplock(fcb), Irp, oplock_count);
4997
4998 *Pirp = NULL;
4999
5000 fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
5001
5002 ExReleaseResourceLite(fcb->Header.Resource);
5003 ExReleaseResourceLite(&Vcb->tree_lock);
5004
5005 return Status;
5006}
5007
5009 ULONG inlen, RETRIEVAL_POINTERS_BUFFER* out, ULONG outlen, ULONG_PTR* retlen) {
5011 fcb* fcb;
5012
5013 TRACE("get_retrieval_pointers(%p, %p, %p, %lx, %p, %lx, %p)\n", Vcb, FileObject, in, inlen,
5014 out, outlen, retlen);
5015
5016 if (!FileObject)
5018
5019 fcb = FileObject->FsContext;
5020
5021 if (!fcb)
5023
5024 if (inlen < sizeof(STARTING_VCN_INPUT_BUFFER) || in->StartingVcn.QuadPart < 0)
5026
5027 if (!out)
5029
5030 if (outlen < offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0]))
5032
5033 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
5034
5035 _SEH2_TRY {
5036 LIST_ENTRY* le = fcb->extents.Flink;
5037 extent* first_ext = NULL;
5038 unsigned int num_extents = 0, first_extent_num = 0, i;
5039 uint64_t num_sectors, last_off = 0;
5040
5041 num_sectors = (fcb->inode_item.st_size + Vcb->superblock.sector_size - 1) >> Vcb->sector_shift;
5042
5043 while (le != &fcb->extents) {
5045
5046 if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) {
5047 le = le->Flink;
5048 continue;
5049 }
5050
5051 if (ext->offset > last_off)
5052 num_extents++;
5053
5054 if ((ext->offset >> Vcb->sector_shift) <= (uint64_t)in->StartingVcn.QuadPart &&
5055 (ext->offset + ext->extent_data.decoded_size) >> Vcb->sector_shift > (uint64_t)in->StartingVcn.QuadPart) {
5056 first_ext = ext;
5057 first_extent_num = num_extents;
5058 }
5059
5060 num_extents++;
5061
5062 last_off = ext->offset + ext->extent_data.decoded_size;
5063
5064 le = le->Flink;
5065 }
5066
5067 if (num_sectors > last_off >> Vcb->sector_shift)
5068 num_extents++;
5069
5070 if (!first_ext) {
5073 }
5074
5075 out->ExtentCount = num_extents - first_extent_num;
5076 out->StartingVcn.QuadPart = first_ext->offset >> Vcb->sector_shift;
5077 outlen -= offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0]);
5078 *retlen = offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0]);
5079
5080 le = &first_ext->list_entry;
5081 i = 0;
5082 last_off = 0;
5083
5084 while (le != &fcb->extents) {
5086
5087 if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) {
5088 le = le->Flink;
5089 continue;
5090 }
5091
5092 if (ext->offset > last_off) {
5093 if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) {
5096 }
5097
5098 out->Extents[i].NextVcn.QuadPart = ext->offset >> Vcb->sector_shift;
5099 out->Extents[i].Lcn.QuadPart = -1;
5100
5101 outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5102 *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5103 i++;
5104 }
5105
5106 if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) {
5109 }
5110
5111 out->Extents[i].NextVcn.QuadPart = (ext->offset + ext->extent_data.decoded_size) >> Vcb->sector_shift;
5112
5113 if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) {
5114 EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
5115
5116 out->Extents[i].Lcn.QuadPart = (ed2->address + ed2->offset) >> Vcb->sector_shift;
5117 } else
5118 out->Extents[i].Lcn.QuadPart = -1;
5119
5120 outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5121 *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5122 i++;
5123
5124 le = le->Flink;
5125 }
5126
5127 if (num_sectors << Vcb->sector_shift > last_off) {
5128 if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) {
5131 }
5132
5133 out->Extents[i].NextVcn.QuadPart = num_sectors;
5134 out->Extents[i].Lcn.QuadPart = -1;
5135
5136 outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5137 *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER);
5138 }
5139
5141 } _SEH2_FINALLY {
5142 ExReleaseResourceLite(fcb->Header.Resource);
5143 } _SEH2_END;
5144
5145 return Status;
5146}
5147
5148static NTSTATUS add_csum_sparse_extents(device_extension* Vcb, uint64_t sparse_extents, uint8_t** ptr, bool found, void* hash_ptr) {
5149 if (!found) {
5150 uint8_t* sector = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
5151
5152 if (!sector) {
5153 ERR("out of memory\n");
5155 }
5156
5157 memset(sector, 0, Vcb->superblock.sector_size);
5158
5159 get_sector_csum(Vcb, sector, hash_ptr);
5160
5162 }
5163
5164 switch (Vcb->superblock.csum_type) {
5165 case CSUM_TYPE_CRC32C: {
5166 uint32_t* csum = (uint32_t*)*ptr;
5167 uint32_t sparse_hash = *(uint32_t*)hash_ptr;
5168
5169 for (uint64_t i = 0; i < sparse_extents; i++) {
5170 csum[i] = sparse_hash;
5171 }
5172
5173 break;
5174 }
5175
5176 case CSUM_TYPE_XXHASH: {
5177 uint64_t* csum = (uint64_t*)*ptr;
5178 uint64_t sparse_hash = *(uint64_t*)hash_ptr;
5179
5180 for (uint64_t i = 0; i < sparse_extents; i++) {
5181 csum[i] = sparse_hash;
5182 }
5183
5184 break;
5185 }
5186
5187 case CSUM_TYPE_SHA256:
5188 case CSUM_TYPE_BLAKE2: {
5189 uint8_t* csum = (uint8_t*)*ptr;
5190
5191 for (uint64_t i = 0; i < sparse_extents; i++) {
5192 memcpy(csum, hash_ptr, 32);
5193 csum += 32;
5194 }
5195
5196 break;
5197 }
5198
5199 default:
5200 ERR("unrecognized hash type %x\n", Vcb->superblock.csum_type);
5201 return STATUS_INTERNAL_ERROR;
5202 }
5203
5204 *ptr += sparse_extents * Vcb->csum_size;
5205
5206 return STATUS_SUCCESS;
5207}
5208
5210 ULONG_PTR* retlen, KPROCESSOR_MODE processor_mode) {
5212 fcb* fcb;
5213 ccb* ccb;
5214
5215 TRACE("get_csum_info(%p, %p, %p, %lx, %p, %x)\n", Vcb, FileObject, buf, buflen, retlen, processor_mode);
5216
5217 if (!FileObject)
5219
5220 fcb = FileObject->FsContext;
5221 ccb = FileObject->FsContext2;
5222
5223 if (!fcb || !ccb)
5225
5226 if (!buf)
5228
5229 if (buflen < offsetof(btrfs_csum_info, data[0]))
5231
5232
5233 if (processor_mode == UserMode && !(ccb->access & (FILE_READ_DATA | FILE_WRITE_DATA))) {
5234 WARN("insufficient privileges\n");
5235 return STATUS_ACCESS_DENIED;
5236 }
5237
5238 ExAcquireResourceSharedLite(fcb->Header.Resource, true);
5239
5240 _SEH2_TRY {
5241 LIST_ENTRY* le;
5242 uint8_t* ptr;
5243 uint64_t last_off;
5244 uint8_t sparse_hash[MAX_HASH_SIZE];
5245 bool sparse_hash_found = false;
5246
5247 if (fcb->ads) {
5250 }
5251
5252 if (fcb->type == BTRFS_TYPE_DIRECTORY) {
5255 }
5256
5260 }
5261
5262 buf->csum_type = Vcb->superblock.csum_type;
5263 buf->csum_length = Vcb->csum_size;
5264
5265 le = fcb->extents.Flink;
5266 while (le != &fcb->extents) {
5268
5269 if (ext->ignore) {
5270 le = le->Flink;
5271 continue;
5272 }
5273
5274 if (ext->extent_data.type == EXTENT_TYPE_INLINE) {
5275 buf->num_sectors = 0;
5276 *retlen = offsetof(btrfs_csum_info, data[0]);
5279 }
5280
5281 le = le->Flink;
5282 }
5283
5284 buf->num_sectors = (fcb->inode_item.st_size + Vcb->superblock.sector_size - 1) >> Vcb->sector_shift;
5285
5286 if (buflen < offsetof(btrfs_csum_info, data[0]) + (buf->csum_length * buf->num_sectors)) {
5288 *retlen = offsetof(btrfs_csum_info, data[0]);
5290 }
5291
5292 ptr = buf->data;
5293 last_off = 0;
5294
5295 le = fcb->extents.Flink;
5296 while (le != &fcb->extents) {
5298 EXTENT_DATA2* ed2;
5299
5300 if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) {
5301 le = le->Flink;
5302 continue;
5303 }
5304
5305 if (ext->offset > last_off) {
5306 uint64_t sparse_extents = (ext->offset - last_off) >> Vcb->sector_shift;
5307
5308 add_csum_sparse_extents(Vcb, sparse_extents, &ptr, sparse_hash_found, sparse_hash);
5309 sparse_hash_found = true;
5310 }
5311
5312 ed2 = (EXTENT_DATA2*)ext->extent_data.data;
5313
5314 if (ext->extent_data.compression != BTRFS_COMPRESSION_NONE)
5315 memset(ptr, 0, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size); // dummy value for compressed extents
5316 else {
5317 if (ext->csum)
5318 memcpy(ptr, ext->csum, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size);
5319 else
5320 memset(ptr, 0, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size);
5321
5322 ptr += (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size;
5323 }
5324
5325 last_off = ext->offset + ed2->num_bytes;
5326
5327 le = le->Flink;
5328 }
5329
5330 if (buf->num_sectors > last_off >> Vcb->sector_shift) {
5331 uint64_t sparse_extents = buf->num_sectors - (last_off >> Vcb->sector_shift);
5332
5333 add_csum_sparse_extents(Vcb, sparse_extents, &ptr, sparse_hash_found, sparse_hash);
5334 }
5335
5336 *retlen = offsetof(btrfs_csum_info, data[0]) + (buf->csum_length * buf->num_sectors);
5338 } _SEH2_FINALLY {
5339 ExReleaseResourceLite(fcb->Header.Resource);
5340 } _SEH2_END;
5341
5342 return Status;
5343}
5344
5346 PIRP Irp = *Pirp;
5349
5350 if (IrpSp->FileObject && IrpSp->FileObject->FsContext) {
5351 device_extension* Vcb = DeviceObject->DeviceExtension;
5352
5353 if (Vcb->type == VCB_TYPE_FS)
5355 }
5356
5357 switch (type) {
5366#if (NTDDI_VERSION >= NTDDI_WIN7)
5367 case FSCTL_REQUEST_OPLOCK:
5368#endif
5369 Status = fsctl_oplock(DeviceObject->DeviceExtension, Pirp);
5370 break;
5371
5372 case FSCTL_LOCK_VOLUME:
5373 Status = lock_volume(DeviceObject->DeviceExtension, Irp);
5374 break;
5375
5377 Status = unlock_volume(DeviceObject->DeviceExtension, Irp);
5378 break;
5379
5381 Status = dismount_volume(DeviceObject->DeviceExtension, false, Irp);
5382 break;
5383
5385 Status = is_volume_mounted(DeviceObject->DeviceExtension, Irp);
5386 break;
5387
5389 WARN("STUB: FSCTL_IS_PATHNAME_VALID\n");
5391 break;
5392
5394 WARN("STUB: FSCTL_MARK_VOLUME_DIRTY\n");
5396 break;
5397
5399 WARN("STUB: FSCTL_QUERY_RETRIEVAL_POINTERS\n");
5401 break;
5402
5405 break;
5406
5409 break;
5410
5412 WARN("STUB: FSCTL_SET_BOOTLOADER_ACCESSED\n");
5414 break;
5415
5418 break;
5419
5421 WARN("STUB: FSCTL_QUERY_FAT_BPB\n");
5423 break;
5424
5426 Status = fs_get_statistics(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5427 break;
5428
5430 WARN("STUB: FSCTL_GET_NTFS_VOLUME_DATA\n");
5432 break;
5433
5435 WARN("STUB: FSCTL_GET_NTFS_FILE_RECORD\n");
5437 break;
5438
5440 WARN("STUB: FSCTL_GET_VOLUME_BITMAP\n");
5442 break;
5443
5446 IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5447 IrpSp->Parameters.FileSystemControl.InputBufferLength,
5448 Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5449 &Irp->IoStatus.Information);
5450 break;
5451
5452 case FSCTL_MOVE_FILE:
5453 WARN("STUB: FSCTL_MOVE_FILE\n");
5455 break;
5456
5458 Status = is_volume_dirty(DeviceObject->DeviceExtension, Irp);
5459 break;
5460
5463 break;
5464
5466 WARN("STUB: FSCTL_FIND_FILES_BY_SID\n");
5468 break;
5469
5471 WARN("STUB: FSCTL_SET_OBJECT_ID\n");
5473 break;
5474
5476 Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5477 &Irp->IoStatus.Information);
5478 break;
5479
5481 WARN("STUB: FSCTL_DELETE_OBJECT_ID\n");
5483 break;
5484
5487 break;
5488
5490 Status = get_reparse_point(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5491 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5492 break;
5493
5496 break;
5497
5499 WARN("STUB: FSCTL_ENUM_USN_DATA\n");
5501 break;
5502
5504 WARN("STUB: FSCTL_SECURITY_ID_CHECK\n");
5506 break;
5507
5509 WARN("STUB: FSCTL_READ_USN_JOURNAL\n");
5511 break;
5512
5514 WARN("STUB: FSCTL_SET_OBJECT_ID_EXTENDED\n");
5516 break;
5517
5519 Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5520 &Irp->IoStatus.Information);
5521 break;
5522
5523 case FSCTL_SET_SPARSE:
5524 Status = set_sparse(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5525 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5526 break;
5527
5529 Status = set_zero_data(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5530 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5531 break;
5532
5534 Status = query_ranges(IrpSp->FileObject, IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5535 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->UserBuffer,
5536 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information);
5537 break;
5538
5540 WARN("STUB: FSCTL_ENABLE_UPGRADE\n");
5542 break;
5543
5545 WARN("STUB: FSCTL_SET_ENCRYPTION\n");
5547 break;
5548
5550 WARN("STUB: FSCTL_ENCRYPTION_FSCTL_IO\n");
5552 break;
5553
5555 WARN("STUB: FSCTL_WRITE_RAW_ENCRYPTED\n");
5557 break;
5558
5560 WARN("STUB: FSCTL_READ_RAW_ENCRYPTED\n");
5562 break;
5563
5565 WARN("STUB: FSCTL_CREATE_USN_JOURNAL\n");
5567 break;
5568
5570 WARN("STUB: FSCTL_READ_FILE_USN_DATA\n");
5572 break;
5573
5575 WARN("STUB: FSCTL_WRITE_USN_CLOSE_RECORD\n");
5577 break;
5578
5580 WARN("STUB: FSCTL_EXTEND_VOLUME\n");
5582 break;
5583
5585 WARN("STUB: FSCTL_QUERY_USN_JOURNAL\n");
5587 break;
5588
5590 WARN("STUB: FSCTL_DELETE_USN_JOURNAL\n");
5592 break;
5593
5594 case FSCTL_MARK_HANDLE:
5595 WARN("STUB: FSCTL_MARK_HANDLE\n");
5597 break;
5598
5599 case FSCTL_SIS_COPYFILE:
5600 WARN("STUB: FSCTL_SIS_COPYFILE\n");
5602 break;
5603
5605 WARN("STUB: FSCTL_SIS_LINK_FILES\n");
5607 break;
5608
5609 case FSCTL_RECALL_FILE:
5610 WARN("STUB: FSCTL_RECALL_FILE\n");
5612 break;
5613
5615 WARN("STUB: FSCTL_READ_FROM_PLEX\n");
5617 break;
5618
5620 WARN("STUB: FSCTL_FILE_PREFETCH\n");
5622 break;
5623
5624#if _WIN32_WINNT >= 0x0600
5626 WARN("STUB: FSCTL_MAKE_MEDIA_COMPATIBLE\n");
5628 break;
5629
5631 WARN("STUB: FSCTL_SET_DEFECT_MANAGEMENT\n");
5633 break;
5634
5636 WARN("STUB: FSCTL_QUERY_SPARING_INFO\n");
5638 break;
5639
5641 WARN("STUB: FSCTL_QUERY_ON_DISK_VOLUME_INFO\n");
5643 break;
5644
5646 WARN("STUB: FSCTL_SET_VOLUME_COMPRESSION_STATE\n");
5648 break;
5649
5651 WARN("STUB: FSCTL_TXFS_MODIFY_RM\n");
5653 break;
5654
5656 WARN("STUB: FSCTL_TXFS_QUERY_RM_INFORMATION\n");
5658 break;
5659
5661 WARN("STUB: FSCTL_TXFS_ROLLFORWARD_REDO\n");
5663 break;
5664
5666 WARN("STUB: FSCTL_TXFS_ROLLFORWARD_UNDO\n");
5668 break;
5669
5671 WARN("STUB: FSCTL_TXFS_START_RM\n");
5673 break;
5674
5676 WARN("STUB: FSCTL_TXFS_SHUTDOWN_RM\n");
5678 break;
5679
5681 WARN("STUB: FSCTL_TXFS_READ_BACKUP_INFORMATION\n");
5683 break;
5684
5686 WARN("STUB: FSCTL_TXFS_WRITE_BACKUP_INFORMATION\n");
5688 break;
5689
5691 WARN("STUB: FSCTL_TXFS_CREATE_SECONDARY_RM\n");
5693 break;
5694
5696 WARN("STUB: FSCTL_TXFS_GET_METADATA_INFO\n");
5698 break;
5699
5701 WARN("STUB: FSCTL_TXFS_GET_TRANSACTED_VERSION\n");
5703 break;
5704
5705 case FSCTL_TXFS_SAVEPOINT_INFORMATION:
5706 WARN("STUB: FSCTL_TXFS_SAVEPOINT_INFORMATION\n");
5708 break;
5709
5711 WARN("STUB: FSCTL_TXFS_CREATE_MINIVERSION\n");
5713 break;
5714
5716 WARN("STUB: FSCTL_TXFS_TRANSACTION_ACTIVE\n");
5718 break;
5719
5721 WARN("STUB: FSCTL_SET_ZERO_ON_DEALLOCATION\n");
5723 break;
5724
5725 case FSCTL_SET_REPAIR:
5726 WARN("STUB: FSCTL_SET_REPAIR\n");
5728 break;
5729
5730 case FSCTL_GET_REPAIR:
5731 WARN("STUB: FSCTL_GET_REPAIR\n");
5733 break;
5734
5736 WARN("STUB: FSCTL_WAIT_FOR_REPAIR\n");
5738 break;
5739
5741 WARN("STUB: FSCTL_INITIATE_REPAIR\n");
5743 break;
5744
5745 case FSCTL_CSC_INTERNAL:
5746 WARN("STUB: FSCTL_CSC_INTERNAL\n");
5748 break;
5749
5751 WARN("STUB: FSCTL_SHRINK_VOLUME\n");
5753 break;
5754
5756 WARN("STUB: FSCTL_SET_SHORT_NAME_BEHAVIOR\n");
5758 break;
5759
5761 WARN("STUB: FSCTL_DFSR_SET_GHOST_HANDLE_STATE\n");
5763 break;
5764
5766 WARN("STUB: FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES\n");
5768 break;
5769
5771 WARN("STUB: FSCTL_TXFS_LIST_TRANSACTIONS\n");
5773 break;
5774
5776 WARN("STUB: FSCTL_QUERY_PAGEFILE_ENCRYPTION\n");
5778 break;
5779
5780 case FSCTL_RESET_VOLUME_ALLOCATION_HINTS:
5781 WARN("STUB: FSCTL_RESET_VOLUME_ALLOCATION_HINTS\n");
5783 break;
5784
5785 case FSCTL_TXFS_READ_BACKUP_INFORMATION2:
5786 WARN("STUB: FSCTL_TXFS_READ_BACKUP_INFORMATION2\n");
5788 break;
5789
5790 case FSCTL_CSV_CONTROL:
5791 WARN("STUB: FSCTL_CSV_CONTROL\n");
5793 break;
5794#endif
5795 // TRACE rather than WARN because Windows 10 spams this undocumented fsctl
5797 TRACE("STUB: FSCTL_QUERY_VOLUME_CONTAINER_STATE\n");
5799 break;
5800
5803 IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5804 break;
5805
5807 Status = set_integrity_information(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength);
5808 break;
5809
5811 Status = duplicate_extents(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5812 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5813 break;
5814
5816 Status = get_file_ids(IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5817 break;
5818
5820 Status = create_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5821 break;
5822
5824 Status = create_snapshot(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5825 break;
5826
5828 Status = get_inode_info(IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5829 break;
5830
5832 Status = set_inode_info(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5833 break;
5834
5836 Status = get_devices(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5837 break;
5838
5840 Status = get_usage(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp);
5841 break;
5842
5844 Status = start_balance(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5845 break;
5846
5848 Status = query_balance(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5849 break;
5850
5852 Status = pause_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5853 break;
5854
5856 Status = resume_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5857 break;
5858
5860 Status = stop_balance(DeviceObject->DeviceExtension, Irp->RequestorMode);
5861 break;
5862
5864 Status = add_device(DeviceObject->DeviceExtension, Irp, Irp->RequestorMode);
5865 break;
5866
5868 Status = remove_device(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5869 break;
5870
5872 Status = query_uuid(DeviceObject->DeviceExtension, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5873 break;
5874
5876 Status = start_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5877 break;
5878
5880 Status = query_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
5881 break;
5882
5884 Status = pause_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5885 break;
5886
5888 Status = resume_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5889 break;
5890
5892 Status = stop_scrub(DeviceObject->DeviceExtension, Irp->RequestorMode);
5893 break;
5894
5896 Status = reset_stats(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5897 break;
5898
5899 case FSCTL_BTRFS_MKNOD:
5900 Status = mknod(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5901 break;
5902
5904 Status = recvd_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5905 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
5906 break;
5907
5909 Status = fsctl_get_xattrs(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp->RequestorMode);
5910 break;
5911
5913 Status = fsctl_set_xattr(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5914 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5915 break;
5916
5918 Status = reserve_subvol(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp);
5919 break;
5920
5922 Status = find_subvol(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength,
5923 Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, Irp);
5924 break;
5925
5927 Status = send_subvol(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength,
5928 IrpSp->FileObject, Irp);
5929 break;
5930
5932 Status = read_send_buffer(DeviceObject->DeviceExtension, IrpSp->FileObject, map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength,
5933 &Irp->IoStatus.Information, Irp->RequestorMode);
5934 break;
5935
5936 case FSCTL_BTRFS_RESIZE:
5937 Status = resize_device(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer,
5938 IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp);
5939 break;
5940
5942 Status = get_csum_info(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer,
5943 IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information,
5944 Irp->RequestorMode);
5945 break;
5946
5947 default:
5948 WARN("unknown control code %lx (DeviceType = %lx, Access = %lx, Function = %lx, Method = %lx)\n",
5949 IrpSp->Parameters.FileSystemControl.FsControlCode, (IrpSp->Parameters.FileSystemControl.FsControlCode & 0xff0000) >> 16,
5950 (IrpSp->Parameters.FileSystemControl.FsControlCode & 0xc000) >> 14, (IrpSp->Parameters.FileSystemControl.FsControlCode & 0x3ffc) >> 2,
5951 IrpSp->Parameters.FileSystemControl.FsControlCode & 0x3);
5953 break;
5954 }
5955
5956 return Status;
5957}
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
unsigned char BOOLEAN
unsigned short int uint16_t
Definition: acefiex.h:54
static int inbuf
Definition: adnsresfilter.c:73
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI ULONG NTAPI RtlRandomEx(PULONG Seed)
#define LongToHandle(h)
Definition: basetsd.h:82
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define BTRFS_MAGIC
Definition: btrfs.h:42
static NTSTATUS lock_volume(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2237
static NTSTATUS get_compression(PIRP Irp)
Definition: fsctl.c:2518
static NTSTATUS get_csum_info(device_extension *Vcb, PFILE_OBJECT FileObject, btrfs_csum_info *buf, ULONG buflen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:5209
static NTSTATUS mknod(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:3739
static NTSTATUS set_sparse(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1727
static void flush_fcb_caches(device_extension *Vcb)
Definition: fsctl.c:2222
static NTSTATUS unlock_volume(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2341
static NTSTATUS fs_get_statistics(void *buffer, DWORD buflen, ULONG_PTR *retlen)
Definition: fsctl.c:1705
static NTSTATUS set_zero_data(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1911
void flush_subvol_fcbs(root *subvol)
Definition: fsctl.c:243
static NTSTATUS get_file_ids(PFILE_OBJECT FileObject, void *data, ULONG length)
Definition: fsctl.c:49
static NTSTATUS create_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:746
LIST_ENTRY VcbList
Definition: btrfs.c:69
static NTSTATUS find_subvol(device_extension *Vcb, void *in, ULONG inlen, void *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4586
tFsRtlAreThereCurrentOrInProgressFileLocks fFsRtlAreThereCurrentOrInProgressFileLocks
Definition: btrfs.c:100
PDRIVER_OBJECT drvobj
Definition: btrfs.c:65
static NTSTATUS add_csum_sparse_extents(device_extension *Vcb, uint64_t sparse_extents, uint8_t **ptr, bool found, void *hash_ptr)
Definition: fsctl.c:5148
static NTSTATUS recvd_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:4120
static void get_uuid(BTRFS_UUID *uuid)
Definition: fsctl.c:73
static void mark_subvol_dirty(device_extension *Vcb, root *r)
Definition: fsctl.c:4108
static NTSTATUS get_retrieval_pointers(device_extension *Vcb, PFILE_OBJECT FileObject, STARTING_VCN_INPUT_BUFFER *in, ULONG inlen, RETRIEVAL_POINTERS_BUFFER *out, ULONG outlen, ULONG_PTR *retlen)
Definition: fsctl.c:5008
static NTSTATUS is_device_part_of_mounted_btrfs_raid(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj)
Definition: fsctl.c:2637
static NTSTATUS reserve_subvol(device_extension *Vcb, PFILE_OBJECT FileObject, PIRP Irp)
Definition: fsctl.c:4506
static NTSTATUS get_subvol_path(device_extension *Vcb, uint64_t id, WCHAR *out, ULONG outlen, PIRP Irp)
Definition: fsctl.c:4535
static NTSTATUS get_integrity_information(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen)
Definition: fsctl.c:3210
#define DOTDOT
Definition: fsctl.c:35
static NTSTATUS query_uuid(device_extension *Vcb, void *data, ULONG length)
Definition: fsctl.c:3157
static NTSTATUS get_inode_info(PFILE_OBJECT FileObject, void *data, ULONG length)
Definition: fsctl.c:1162
static NTSTATUS invalidate_volumes(PIRP Irp)
Definition: fsctl.c:2358
static NTSTATUS get_object_id(PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER *buf, ULONG buflen, ULONG_PTR *retlen)
Definition: fsctl.c:2188
NTSTATUS dismount_volume(device_extension *Vcb, bool shutdown, PIRP Irp)
Definition: fsctl.c:2584
static NTSTATUS fsctl_get_xattrs(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:4170
static void update_volumes(device_extension *Vcb)
Definition: fsctl.c:2561
tFsRtlCheckLockForOplockRequest fFsRtlCheckLockForOplockRequest
Definition: btrfs.c:99
static NTSTATUS get_usage(device_extension *Vcb, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1512
static NTSTATUS duplicate_extents(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:3262
static NTSTATUS snapshot_tree_copy(device_extension *Vcb, uint64_t addr, root *subvol, uint64_t *newaddr, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:87
static NTSTATUS resize_device(device_extension *Vcb, void *data, ULONG len, PIRP Irp)
Definition: fsctl.c:4710
ERESOURCE global_loading_lock
Definition: btrfs.c:70
#define SEF_SACL_AUTO_INHERIT
Definition: fsctl.c:39
static NTSTATUS add_device(device_extension *Vcb, PIRP Irp, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:2735
void trim_whole_device(device *dev)
Definition: fsctl.c:2716
#define FSCTL_QUERY_VOLUME_CONTAINER_STATE
Definition: fsctl.c:32
static NTSTATUS is_volume_dirty(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:2491
static NTSTATUS do_create_snapshot(device_extension *Vcb, PFILE_OBJECT parent, fcb *subvol_fcb, PANSI_STRING utf8, PUNICODE_STRING name, bool readonly, PIRP Irp)
Definition: fsctl.c:260
static NTSTATUS allow_extended_dasd_io(device_extension *Vcb, PFILE_OBJECT FileObject)
Definition: fsctl.c:3131
bool fcb_is_inline(fcb *fcb)
Definition: fsctl.c:3246
static NTSTATUS fsctl_oplock(device_extension *Vcb, PIRP *Pirp)
Definition: fsctl.c:4895
static NTSTATUS check_inode_used(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *subvol, _In_ uint64_t inode, _In_ uint32_t hash, _In_opt_ PIRP Irp)
Definition: fsctl.c:3701
void do_unlock_volume(device_extension *Vcb)
Definition: fsctl.c:2326
static NTSTATUS create_snapshot(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:521
NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP *Pirp, uint32_t type)
Definition: fsctl.c:5345
static NTSTATUS get_devices(device_extension *Vcb, void *data, ULONG length)
Definition: fsctl.c:1444
static NTSTATUS set_inode_info(PFILE_OBJECT FileObject, void *data, ULONG length, PIRP Irp)
Definition: fsctl.c:1323
static NTSTATUS set_integrity_information(PFILE_OBJECT FileObject, void *data, ULONG datalen)
Definition: fsctl.c:3232
static NTSTATUS is_volume_mounted(device_extension *Vcb, PIRP Irp)
Definition: fsctl.c:1662
static NTSTATUS zero_data(device_extension *Vcb, fcb *fcb, uint64_t start, uint64_t length, PIRP Irp, LIST_ENTRY *rollback)
Definition: fsctl.c:1811
static NTSTATUS query_ranges(PFILE_OBJECT FileObject, FILE_ALLOCATED_RANGE_BUFFER *inbuf, ULONG inbuflen, void *outbuf, ULONG outbuflen, ULONG_PTR *retlen)
Definition: fsctl.c:2089
static NTSTATUS set_compression(PIRP Irp)
Definition: fsctl.c:2544
#define FSCTL_CSV_CONTROL
Definition: fsctl.c:28
static NTSTATUS reset_stats(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: fsctl.c:3166
static NTSTATUS fsctl_set_xattr(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, PIRP Irp)
Definition: fsctl.c:4235
#define GID_NOBODY
Definition: btrfs_drv.h:91
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#define increase_fileref_refcount(fileref)
Definition: btrfs_drv.h:1739
#define InterlockedIncrement64(a)
Definition: btrfs_drv.h:143
_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
#define EA_CASE_SENSITIVE
Definition: btrfs_drv.h:105
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
Definition: btrfs_drv.h:1684
#define EA_EA
Definition: btrfs_drv.h:102
NTSTATUS stop_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3440
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1016
#define __S_IFREG
Definition: btrfs_drv.h:1757
NTSTATUS pause_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3401
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
void space_list_add2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1446
#define UID_NOBODY
Definition: btrfs_drv.h:90
NTSTATUS add_space_entry(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t offset, uint64_t size)
Definition: free-space.c:190
void void void NTSTATUS void NTSTATUS NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: search.c:407
#define __S_IFDIR
Definition: btrfs_drv.h:1754
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
#define EA_NTACL
Definition: btrfs_drv.h:93
NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void *buffer, DWORD buflen, ULONG_PTR *retlen)
Definition: reparse.c:27
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
Definition: create.c:1948
struct _fcb fcb
Definition: btrfs_drv.h:1364
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4093
#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
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define __S_IFSOCK
Definition: btrfs_drv.h:1760
NTSTATUS increase_extent_refcount_data(device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, PIRP Irp)
Definition: extent-tree.c:892
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
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
BOOLEAN(__stdcall * tFsRtlCheckLockForOplockRequest)(PFILE_LOCK FileLock, PLARGE_INTEGER AllocationSize)
Definition: btrfs_drv.h:1866
#define ALLOC_TAG
Definition: btrfs_drv.h:87
@ WriteDataStatus_Ignore
Definition: btrfs_drv.h:920
NTSTATUS query_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode, void *data, ULONG length)
Definition: scrub.c:3301
NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _Out_ file_ref **pfr, _In_ PUNICODE_STRING fnus, _In_opt_ file_ref *related, _In_ bool parent, _Out_opt_ USHORT *parsed, _Out_opt_ ULONG *fn_offset, _In_ POOL_TYPE pooltype, _In_ bool case_sensitive, _In_opt_ PIRP Irp)
Definition: create.c:1690
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1365
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: btrfs_drv.h:1364
NTSTATUS set_reparse_point(PIRP Irp)
Definition: reparse.c:409
#define COMPRESSED_EXTENT_SIZE
Definition: btrfs_drv.h:112
bool has_open_children(file_ref *fileref)
Definition: fileinfo.c:442
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1677
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
#define __S_IFLNK
Definition: btrfs_drv.h:1759
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
NTSTATUS increase_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
Definition: extent-tree.c:454
#define EA_REPARSE
Definition: btrfs_drv.h:99
#define EA_PROP_COMPRESSION
Definition: btrfs_drv.h:108
#define EA_DOSATTRIB
Definition: btrfs_drv.h:96
NTSTATUS write_compressed(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
Definition: compress.c:875
#define makedev(major, minor)
Definition: btrfs_drv.h:1637
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:70
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
BOOLEAN(__stdcall * tFsRtlAreThereCurrentOrInProgressFileLocks)(PFILE_LOCK FileLock)
Definition: btrfs_drv.h:1868
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
#define __S_IFIFO
Definition: btrfs_drv.h:1758
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:706
NTSTATUS read_send_buffer(device_extension *Vcb, PFILE_OBJECT FileObject, void *data, ULONG datalen, ULONG_PTR *retlen, KPROCESSOR_MODE processor_mode)
Definition: send.c:3839
void volume_removal(PUNICODE_STRING devpath)
Definition: search.c:795
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
struct _ccb ccb
void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb *fcb)
Definition: fileinfo.c:888
NTSTATUS delete_reparse_point(PIRP Irp)
Definition: reparse.c:482
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
NTSTATUS bool void NTSTATUS void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext) __attribute__((nonnull(1
void get_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:182
void calc_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: flushthread.c:1806
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
NTSTATUS fileref_get_filename(file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
Definition: fileinfo.c:4245
NTSTATUS start_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3260
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
NTSTATUS get_tree_new_address(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:878
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
Definition: create.c:91
#define MAX_HASH_SIZE
Definition: btrfs_drv.h:213
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
Definition: create.c:1871
@ PropCompression_None
Definition: btrfs_drv.h:268
@ PropCompression_LZO
Definition: btrfs_drv.h:270
@ PropCompression_Zlib
Definition: btrfs_drv.h:269
@ PropCompression_ZSTD
Definition: btrfs_drv.h:271
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
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:977
#define __S_IFBLK
Definition: btrfs_drv.h:1756
NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
Definition: create.c:182
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
NTSTATUS resume_scrub(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: scrub.c:3422
#define __S_IFCHR
Definition: btrfs_drv.h:1755
static __inline bool write_fcb_compressed(fcb *fcb)
Definition: btrfs_drv.h:1706
#define FSCTL_BTRFS_QUERY_SCRUB
Definition: btrfsioctl.h:24
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:133
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:9
#define FSCTL_BTRFS_SET_INODE_INFO
Definition: btrfsioctl.h:11
#define FSCTL_BTRFS_STOP_SCRUB
Definition: btrfsioctl.h:27
#define FSCTL_BTRFS_ADD_DEVICE
Definition: btrfsioctl.h:19
#define BTRFS_COMPRESSION_ANY
Definition: btrfsioctl.h:64
#define FSCTL_BTRFS_PAUSE_SCRUB
Definition: btrfsioctl.h:25
#define FSCTL_BTRFS_PAUSE_BALANCE
Definition: btrfsioctl.h:16
#define FSCTL_BTRFS_SEND_SUBVOL
Definition: btrfsioctl.h:36
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:130
#define FSCTL_BTRFS_SET_XATTR
Definition: btrfsioctl.h:33
#define FSCTL_BTRFS_RESERVE_SUBVOL
Definition: btrfsioctl.h:34
#define FSCTL_BTRFS_QUERY_BALANCE
Definition: btrfsioctl.h:15
#define FSCTL_BTRFS_GET_UUID
Definition: btrfsioctl.h:22
#define FSCTL_BTRFS_GET_XATTRS
Definition: btrfsioctl.h:32
#define FSCTL_BTRFS_RESUME_SCRUB
Definition: btrfsioctl.h:26
#define FSCTL_BTRFS_START_SCRUB
Definition: btrfsioctl.h:23
#define FSCTL_BTRFS_START_BALANCE
Definition: btrfsioctl.h:14
#define FSCTL_BTRFS_MKNOD
Definition: btrfsioctl.h:30
#define FSCTL_BTRFS_FIND_SUBVOL
Definition: btrfsioctl.h:35
#define FSCTL_BTRFS_RESIZE
Definition: btrfsioctl.h:38
#define FSCTL_BTRFS_RECEIVED_SUBVOL
Definition: btrfsioctl.h:31
#define FSCTL_BTRFS_RESUME_BALANCE
Definition: btrfsioctl.h:17
#define FSCTL_BTRFS_GET_INODE_INFO
Definition: btrfsioctl.h:10
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:132
#define FSCTL_BTRFS_REMOVE_DEVICE
Definition: btrfsioctl.h:20
#define FSCTL_BTRFS_GET_CSUM_INFO
Definition: btrfsioctl.h:40
#define FSCTL_BTRFS_GET_USAGE
Definition: btrfsioctl.h:13
#define FSCTL_BTRFS_STOP_BALANCE
Definition: btrfsioctl.h:18
#define FSCTL_BTRFS_GET_DEVICES
Definition: btrfsioctl.h:12
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:8
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:7
#define FSCTL_BTRFS_RESET_STATS
Definition: btrfsioctl.h:29
#define FSCTL_BTRFS_READ_SEND_BUFFER
Definition: btrfsioctl.h:37
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))
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
Definition: _set.h:50
#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 NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static string utf16_to_utf8(const wstring_view &utf16)
Definition: main.cpp:670
static const WCHAR *const ext[]
Definition: module.c:53
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
NTSTATUS query_balance(device_extension *Vcb, void *data, ULONG length)
Definition: balance.c:3711
NTSTATUS resume_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3765
NTSTATUS pause_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3749
NTSTATUS remove_device(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3799
NTSTATUS stop_balance(device_extension *Vcb, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3784
NTSTATUS start_balance(device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
Definition: balance.c:3511
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
_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
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
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1856
r parent
Definition: btrfs.c:3010
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 find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
Definition: btrfs.c:3876
void mark_fileref_dirty(_In_ file_ref *fileref)
Definition: btrfs.c:1717
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
bool check_superblock_checksum(superblock *sb)
Definition: btrfs.c:2825
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
void init_device(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ bool get_nums)
Definition: btrfs.c:3416
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
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
Definition: btrfs.c:5797
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1517
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
ULONG to_read
Definition: btrfs.c:4260
void reap_fcb(fcb *fcb)
Definition: btrfs.c:1743
#define BTRFS_COMPRESSION_LZO
Definition: btrfs.h:67
#define TYPE_EXTENT_DATA
Definition: btrfs.h:30
#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_COMPRESSION_ZLIB
Definition: btrfs.h:66
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:68
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
static const uint64_t superblock_addrs[]
Definition: btrfs.h:16
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
#define BTRFS_SUBVOL_READONLY
Definition: btrfs.h:109
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:72
#define TYPE_DEV_ITEM
Definition: btrfs.h:47
#define TYPE_SUBVOL_REC_UUID
Definition: btrfs.h:52
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:74
#define BTRFS_TYPE_UNKNOWN
Definition: btrfs.h:262
#define TYPE_DEV_STATS
Definition: btrfs.h:50
#define TYPE_SUBVOL_UUID
Definition: btrfs.h:51
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:539
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:37
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:65
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
#define TYPE_INODE_REF
Definition: btrfs.h:24
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:70
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
KIRQL irql
Definition: wave.h:1
static struct all_devices * devices
Definition: dsm_ctrl.c:48
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(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 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 DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#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 PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
BOOLEAN NTAPI FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:782
BOOLEAN NTAPI FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:748
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
time_t now
Definition: finger.c:65
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
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
GLuint address
Definition: glext.h:9393
GLuint * ids
Definition: glext.h:5907
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLint namelen
Definition: glext.h:7232
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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 factor
Definition: glfuncs.h:178
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 j
Definition: glfuncs.h:250
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
_Check_return_ int __cdecl rand(void)
Definition: rand.c:10
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
NTSYSAPI BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR, ULONG, SECURITY_INFORMATION)
Definition: msctf.idl:550
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
uint32_t sector
Definition: isohybrid.c:61
uint32_t cc
Definition: isohybrid.c:75
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
#define c
Definition: ke_i.h:80
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity(VOID)
Definition: lazyrite.c:30
if(dx< 0)
Definition: linetemp.h:194
static const WCHAR dc[]
__u32 hidden
Definition: mkdosfs.c:13
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define for
Definition: utility.h:88
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
@ NormalPagePriority
Definition: imports.h:56
@ LowPagePriority
Definition: imports.h:55
static PVOID ptr
Definition: dispmode.c:27
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
#define SE_TCB_PRIVILEGE
Definition: security.c:661
static const BYTE ext2[]
Definition: encode.c:2699
static const BYTE us[]
Definition: encode.c:689
static DNS_RECORDW r2
Definition: record.c:38
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
BYTE uint8_t
Definition: msvideo1.c:66
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define uint64_t
Definition: nsiface.idl:62
#define uint16_t
Definition: nsiface.idl:60
#define FSCTL_QUERY_RETRIEVAL_POINTERS
Definition: nt_native.h:840
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define WRITE_DAC
Definition: nt_native.h:59
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
#define FSCTL_IS_PATHNAME_VALID
Definition: nt_native.h:837
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define FSCTL_QUERY_FAT_BPB
Definition: nt_native.h:848
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define WRITE_OWNER
Definition: nt_native.h:60
#define FSCTL_IS_VOLUME_MOUNTED
Definition: nt_native.h:836
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define FSCTL_GET_COMPRESSION
Definition: nt_native.h:841
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define FSCTL_SET_COMPRESSION
Definition: nt_native.h:842
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES DEVICE_MANAGE_DATA_SET_ATTRIBUTES
#define DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE
Definition: ntddstor.h:306
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
Definition: ntddstor.h:764
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
#define DeviceDsmAction_Trim
Definition: ntddstor.h:276
@ NotificationEvent
#define COMPRESSION_FORMAT_NONE
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define FSCTL_GET_NTFS_VOLUME_DATA
Definition: ntifs_ex.h:261
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
Definition: sd.c:257
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
#define FSCTL_GET_NTFS_FILE_RECORD
Definition: ntifs_ex.h:262
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
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
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_NOT_LOCKED
Definition: ntstatus.h:279
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1430
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
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
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:345
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
#define S_IXGRP
Definition: propsheet.h:49
#define S_IROTH
Definition: propsheet.h:53
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define S_ISUID
Definition: propsheet.h:65
#define S_IXOTH
Definition: propsheet.h:61
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define S_IRGRP
Definition: propsheet.h:41
#define S_IWOTH
Definition: propsheet.h:57
#define S_IRUSR
Definition: propsheet.h:29
#define S_ISVTX
Definition: propsheet.h:73
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define S_ISGID
Definition: propsheet.h:69
#define S_IWUSR
Definition: propsheet.h:33
#define S_IWGRP
Definition: propsheet.h:45
#define S_IXUSR
Definition: propsheet.h:37
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:98
#define FSCTL_SET_SPARSE
Definition: winioctl.h:100
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:714
#define FILESYSTEM_STATISTICS_TYPE_NTFS
Definition: winioctl.h:750
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
struct _FILESYSTEM_STATISTICS FILESYSTEM_STATISTICS
#define FSCTL_DELETE_REPARSE_POINT
Definition: winioctl.h:99
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define FSCTL_MOVE_FILE
Definition: winioctl.h:96
#define FSCTL_CSC_INTERNAL
Definition: winioctl.h:185
#define FSCTL_READ_RAW_ENCRYPTED
Definition: winioctl.h:147
#define FSCTL_TXFS_SHUTDOWN_RM
Definition: winioctl.h:172
#define FSCTL_SET_VOLUME_COMPRESSION_STATE
Definition: winioctl.h:166
#define FSCTL_QUERY_ALLOCATED_RANGES
Definition: winioctl.h:142
#define FSCTL_GET_REPAIR
Definition: winioctl.h:182
#define FSCTL_SET_OBJECT_ID
Definition: winioctl.h:129
#define FSCTL_SET_DEFECT_MANAGEMENT
Definition: winioctl.h:163
#define FSCTL_SET_REPAIR
Definition: winioctl.h:181
#define FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES
Definition: winioctl.h:189
#define FSCTL_TXFS_ROLLFORWARD_REDO
Definition: winioctl.h:169
#define FSCTL_WRITE_USN_CLOSE_RECORD
Definition: winioctl.h:150
#define FSCTL_QUERY_SPARING_INFO
Definition: winioctl.h:164
#define FSCTL_SHRINK_VOLUME
Definition: winioctl.h:186
#define FSCTL_READ_USN_JOURNAL
Definition: winioctl.h:137
#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION
Definition: winioctl.h:174
#define FSCTL_WRITE_RAW_ENCRYPTED
Definition: winioctl.h:146
#define FSCTL_FIND_FILES_BY_SID
Definition: winioctl.h:127
#define FSCTL_DELETE_USN_JOURNAL
Definition: winioctl.h:153
#define FSCTL_SET_ZERO_DATA
Definition: winioctl.h:141
#define FSCTL_ENCRYPTION_FSCTL_IO
Definition: winioctl.h:145
#define FSCTL_TXFS_QUERY_RM_INFORMATION
Definition: winioctl.h:168
#define FSCTL_TXFS_READ_BACKUP_INFORMATION
Definition: winioctl.h:173
#define FSCTL_QUERY_ON_DISK_VOLUME_INFO
Definition: winioctl.h:165
#define FSCTL_SIS_LINK_FILES
Definition: winioctl.h:156
#define FSCTL_RECALL_FILE
Definition: winioctl.h:159
#define FSCTL_SIS_COPYFILE
Definition: winioctl.h:155
#define FSCTL_TXFS_MODIFY_RM
Definition: winioctl.h:167
#define FSCTL_SET_ENCRYPTION
Definition: winioctl.h:144
#define FSCTL_MARK_HANDLE
Definition: winioctl.h:154
#define FSCTL_QUERY_USN_JOURNAL
Definition: winioctl.h:152
#define FSCTL_FILE_PREFETCH
Definition: winioctl.h:161
#define FSCTL_CREATE_OR_GET_OBJECT_ID
Definition: winioctl.h:139
#define FSCTL_CREATE_USN_JOURNAL
Definition: winioctl.h:148
#define FSCTL_SET_OBJECT_ID_EXTENDED
Definition: winioctl.h:138
#define FSCTL_SET_ZERO_ON_DEALLOCATION
Definition: winioctl.h:180
#define FSCTL_ALLOW_EXTENDED_DASD_IO
Definition: winioctl.h:124
#define FSCTL_ENUM_USN_DATA
Definition: winioctl.h:135
#define FSCTL_MAKE_MEDIA_COMPATIBLE
Definition: winioctl.h:162
#define FSCTL_INITIATE_REPAIR
Definition: winioctl.h:184
#define FSCTL_TXFS_START_RM
Definition: winioctl.h:171
#define FSCTL_TXFS_ROLLFORWARD_UNDO
Definition: winioctl.h:170
#define FSCTL_TXFS_LIST_TRANSACTIONS
Definition: winioctl.h:190
#define FSCTL_TXFS_GET_METADATA_INFO
Definition: winioctl.h:176
#define FSCTL_GET_OBJECT_ID
Definition: winioctl.h:130
#define FSCTL_SECURITY_ID_CHECK
Definition: winioctl.h:136
#define FSCTL_TXFS_CREATE_SECONDARY_RM
Definition: winioctl.h:175
#define FSCTL_WAIT_FOR_REPAIR
Definition: winioctl.h:183
#define FSCTL_TXFS_CREATE_MINIVERSION
Definition: winioctl.h:178
#define FSCTL_EXTEND_VOLUME
Definition: winioctl.h:151
#define FSCTL_QUERY_PAGEFILE_ENCRYPTION
Definition: winioctl.h:191
#define FSCTL_TXFS_GET_TRANSACTED_VERSION
Definition: winioctl.h:177
#define FSCTL_ENABLE_UPGRADE
Definition: winioctl.h:143
#define FSCTL_READ_FILE_USN_DATA
Definition: winioctl.h:149
#define FSCTL_SET_SHORT_NAME_BEHAVIOR
Definition: winioctl.h:187
#define FSCTL_DELETE_OBJECT_ID
Definition: winioctl.h:131
#define FSCTL_DFSR_SET_GHOST_HANDLE_STATE
Definition: winioctl.h:188
#define FSCTL_TXFS_TRANSACTION_ACTIVE
Definition: winioctl.h:179
#define FSCTL_READ_FROM_PLEX
Definition: winioctl.h:160
static FILE * out
Definition: regtests2xml.c:44
#define offsetof(TYPE, MEMBER)
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: compress.c:68
#define memset(x, y, z)
Definition: compat.h:39
static void send_subvol(const wstring &subvol, const wstring &file, const wstring &parent, const vector< wstring > &clones)
Definition: send.cpp:564
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define FSCTL_SET_INTEGRITY_INFORMATION
Definition: shellext.h:222
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define FSCTL_GET_INTEGRITY_INFORMATION
Definition: shellext.h:221
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE
Definition: shellext.h:205
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#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 BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define TRACE(s)
Definition: solgame.cpp:4
#define true
Definition: stdbool.h:36
#define false
Definition: stdbool.h:37
uint8_t uuid[16]
Definition: btrfs.h:140
uint64_t dev_id
Definition: btrfs.h:352
uint16_t num_stripes
Definition: btrfs.h:347
uint64_t size
Definition: btrfs.h:340
uint64_t type
Definition: btrfs.h:343
uint64_t num_bytes
Definition: btrfs.h:179
BTRFS_UUID device_uuid
Definition: btrfs.h:190
uint64_t dev_id
Definition: btrfs.h:178
uint64_t num_bytes
Definition: btrfs.h:371
uint64_t address
Definition: btrfs.h:368
uint64_t size
Definition: btrfs.h:369
uint64_t offset
Definition: btrfs.h:370
uint8_t data[1]
Definition: btrfs.h:364
uint64_t generation
Definition: btrfs.h:358
uint8_t type
Definition: btrfs.h:363
uint16_t encoding
Definition: btrfs.h:362
uint8_t encryption
Definition: btrfs.h:361
uint8_t compression
Definition: btrfs.h:360
uint64_t decoded_size
Definition: btrfs.h:359
LARGE_INTEGER Length
Definition: winioctl.h:560
uint64_t st_rdev
Definition: btrfs.h:296
uint32_t st_mode
Definition: btrfs.h:295
uint32_t st_nlink
Definition: btrfs.h:292
uint64_t block_group
Definition: btrfs.h:291
uint32_t flags
Definition: btrfs.h:297
BTRFS_TIME otime
Definition: btrfs.h:304
BTRFS_TIME st_mtime
Definition: btrfs.h:303
uint64_t st_size
Definition: btrfs.h:289
uint32_t st_uid
Definition: btrfs.h:293
BTRFS_TIME st_atime
Definition: btrfs.h:301
uint64_t sequence
Definition: btrfs.h:299
uint64_t st_blocks
Definition: btrfs.h:290
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint32_t st_gid
Definition: btrfs.h:294
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 ctransid
Definition: btrfs.h:328
uint64_t offset
Definition: btrfs.h:413
USHORT MaximumLength
Definition: env_spec_w32.h:377
DEVICE_DATA_MANAGEMENT_SET_ACTION Action
Definition: ntddstor.h:773
LARGE_INTEGER ByteCount
Definition: shellext.h:202
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
ULONG SizeOfCompleteStructure
Definition: winioctl.h:735
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: iotypes.h:189
CSHORT Type
Definition: iotypes.h:190
CSHORT Size
Definition: iotypes.h:191
USHORT Flags
Definition: iotypes.h:192
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
bool reserving
Definition: btrfs_drv.h:381
bool user_set_change_time
Definition: btrfs_drv.h:390
bool allow_extended_dasd_io
Definition: btrfs_drv.h:380
ACCESS_MASK access
Definition: btrfs_drv.h:382
bool user_set_write_time
Definition: btrfs_drv.h:389
file_ref * fileref
Definition: btrfs_drv.h:383
bool case_sensitive
Definition: btrfs_drv.h:386
bool ads
Definition: btrfs_drv.h:330
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
ULONG ealen
Definition: btrfs_drv.h:303
LIST_ENTRY xattrs
Definition: btrfs_drv.h:308
FILE_LOCK lock
Definition: btrfs_drv.h:294
ULONG atts
Definition: btrfs_drv.h:297
bool atts_deleted
Definition: btrfs_drv.h:322
bool sd_dirty
Definition: btrfs_drv.h:321
bool deleted
Definition: btrfs_drv.h:295
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
bool case_sensitive
Definition: btrfs_drv.h:310
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
bool created
Definition: btrfs_drv.h:328
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:318
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
struct _root * subvol
Definition: btrfs_drv.h:288
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:317
bool xattrs_changed
Definition: btrfs_drv.h:327
uint32_t hash
Definition: btrfs_drv.h:290
bool sd_deleted
Definition: btrfs_drv.h:321
bool reparse_xattr_changed
Definition: btrfs_drv.h:324
LONG refcount
Definition: btrfs_drv.h:285
bool extents_changed
Definition: btrfs_drv.h:323
bool atts_changed
Definition: btrfs_drv.h:322
enum prop_compression_type prop_compression
Definition: btrfs_drv.h:307
bool ea_changed
Definition: btrfs_drv.h:325
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:284
ANSI_STRING ea_xattr
Definition: btrfs_drv.h:302
bool prop_compression_changed
Definition: btrfs_drv.h:326
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
bool deleted
Definition: btrfs_drv.h:347
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
dir_child * dc
Definition: btrfs_drv.h:353
LIST_ENTRY list_entry
Definition: btrfs_drv.h:357
LIST_ENTRY children
Definition: btrfs_drv.h:349
bool created
Definition: btrfs_drv.h:348
uint64_t id
Definition: btrfs_drv.h:451
LIST_ENTRY fcbs
Definition: btrfs_drv.h:464
uint8_t * data
Definition: btrfs_drv.h:415
uint16_t size
Definition: btrfs_drv.h:414
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:878
LIST_ENTRY stripes
Definition: btrfs_drv.h:938
uint8_t * parity1
Definition: btrfs_drv.h:941
uint8_t * parity2
Definition: btrfs_drv.h:941
uint8_t * scratch
Definition: btrfs_drv.h:941
void *POINTER_32 subvol
Definition: btrfsioctl.h:57
BTRFS_UUID uuid
Definition: btrfsioctl.h:263
uint64_t ctransid
Definition: btrfsioctl.h:264
uint32_t st_mode
Definition: btrfsioctl.h:76
uint64_t disk_size_zlib
Definition: btrfsioctl.h:81
uint32_t inline_length
Definition: btrfsioctl.h:79
uint64_t st_rdev
Definition: btrfsioctl.h:77
uint64_t sparse_size
Definition: btrfsioctl.h:85
uint32_t num_extents
Definition: btrfsioctl.h:86
uint64_t disk_size_lzo
Definition: btrfsioctl.h:82
uint64_t disk_size_zstd
Definition: btrfsioctl.h:84
uint32_t st_gid
Definition: btrfsioctl.h:75
uint64_t flags
Definition: btrfsioctl.h:78
uint32_t st_uid
Definition: btrfsioctl.h:74
uint64_t inode
Definition: btrfsioctl.h:71
uint64_t disk_size_uncompressed
Definition: btrfsioctl.h:80
uint8_t compression_type
Definition: btrfsioctl.h:83
uint64_t subvol
Definition: btrfsioctl.h:70
uint64_t inode
Definition: btrfsioctl.h:237
WCHAR name[1]
Definition: btrfsioctl.h:241
uint16_t namelen
Definition: btrfsioctl.h:240
uint64_t st_rdev
Definition: btrfsioctl.h:239
uint8_t type
Definition: btrfsioctl.h:238
uint64_t size
Definition: btrfsioctl.h:281
uint64_t device
Definition: btrfsioctl.h:280
uint8_t compression_type
Definition: btrfsioctl.h:98
BOOL compression_type_changed
Definition: btrfsioctl.h:99
uint32_t next_entry
Definition: btrfsioctl.h:122
uint64_t size
Definition: btrfsioctl.h:124
btrfs_usage_device devices[1]
Definition: btrfsioctl.h:127
uint64_t type
Definition: btrfsioctl.h:123
uint64_t num_devices
Definition: btrfsioctl.h:126
uint64_t used
Definition: btrfsioctl.h:125
uint64_t used
Definition: btrfs_drv.h:565
CHUNK_ITEM * chunk_item
Definition: btrfs_drv.h:562
Definition: ffs.h:52
Definition: tftpd.h:138
uint64_t dev_id
uint64_t size
Definition: devices.h:37
ULONG disk_num
Definition: devices.h:42
DEV_ITEM devitem
Definition: btrfs_drv.h:527
ULONG part_num
Definition: devices.h:43
bool readonly
Definition: btrfs_drv.h:530
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:525
uint64_t stats[5]
Definition: btrfs_drv.h:537
ANSI_STRING utf8
Definition: btrfs_drv.h:254
LIST_ENTRY list_entry
Definition: btrfs_drv.h:235
uint64_t offset
Definition: btrfs_drv.h:228
Definition: _hash_fun.h:40
Definition: fs.h:78
Definition: copy.c:22
uint32_t offset
Definition: btrfs.h:167
KEY key
Definition: btrfs.h:166
uint32_t size
Definition: btrfs.h:168
Definition: list.h:27
Definition: name.c:39
ERESOURCE child_lock
Definition: btrfs_drv.h:896
uint64_t children_loaded
Definition: btrfs_drv.h:895
LIST_ENTRY children
Definition: btrfs_drv.h:897
uint64_t num_children
Definition: btrfs_drv.h:894
Definition: write.c:113
device * device
Definition: write.c:115
BTRFS_UUID uuid
Definition: btrfs.h:225
uint64_t magic
Definition: btrfs.h:228
DEV_ITEM dev_item
Definition: btrfs.h:251
tree_data * item
Definition: btrfs_drv.h:509
tree * tree
Definition: btrfs_drv.h:508
uint32_t num_items
Definition: btrfs.h:161
uint64_t tree_id
Definition: btrfs.h:160
BTRFS_UUID fs_uuid
Definition: btrfs.h:155
uint64_t generation
Definition: btrfs.h:159
uint8_t level
Definition: btrfs.h:162
uint64_t address
Definition: btrfs.h:156
LIST_ENTRY list_entry
Definition: btrfs_drv.h:867
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
void * notification_entry
Definition: btrfs_drv.h:863
bool seeding
Definition: btrfs_drv.h:861
bool boot_volume
Definition: btrfs_drv.h:866
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:859
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:857
bool had_drive_letter
Definition: btrfs_drv.h:862
uint64_t generation
Definition: btrfs_drv.h:856
BTRFS_UUID uuid
Definition: btrfs_drv.h:854
bool dirty
Definition: btrfs_drv.h:278
USHORT namelen
Definition: btrfs_drv.h:276
char data[1]
Definition: btrfs_drv.h:279
USHORT valuelen
Definition: btrfs_drv.h:277
LIST_ENTRY list_entry
Definition: btrfs_drv.h:275
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
union _LARGE_INTEGER LARGE_INTEGER
PVOID HANDLE
Definition: typedefs.h:73
#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
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#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_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_FILE_DELETED
Definition: udferr_usr.h:172
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define FILE_ACTION_MODIFIED
#define IO_TYPE_VPB
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_NOTIFY_CHANGE_FILE_NAME
struct _VPB VPB
@ EventCategoryTargetDeviceChange
Definition: iotypes.h:1227
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_LOCKED
Definition: iotypes.h:1808
#define FSCTL_SET_BOOTLOADER_ACCESSED
Definition: iotypes.h:6061
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
@ Executive
Definition: ketypes.h:415
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
NTKERNELAPI NTSTATUS NTAPI SeAssignSecurityEx(_In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor, _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, _In_opt_ GUID *ObjectType, _In_ BOOLEAN IsDirectoryObject, _In_ ULONG AutoInheritFlags, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ PGENERIC_MAPPING GenericMapping, _In_ POOL_TYPE PoolType)
__wchar_t WCHAR
Definition: xmlstorage.h:180