36#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED 0x0002
37#define ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED 0x0080
38#define ATOMIC_CREATE_ECP_IN_FLAG_BEST_EFFORT 0x0100
40#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET 0x0002
41#define ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED 0x0080
43#define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED 1
44#define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET 1
46#ifndef SL_IGNORE_READONLY_ATTRIBUTE
47#define SL_IGNORE_READONLY_ATTRIBUTE 0x40
79static const GUID GUID_ECP_ATOMIC_CREATE = { 0x4720bd83, 0x52ac, 0x4104, { 0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5 } };
80static const GUID GUID_ECP_QUERY_ON_CREATE = { 0x1aca62e9, 0xabb4, 0x4ff2, { 0xbb, 0x5c, 0x1c, 0x79, 0x02, 0x5e, 0x41, 0x7f } };
81static const GUID GUID_ECP_CREATE_REDIRECTION = { 0x188d6bd6, 0xa126, 0x4fa8, { 0xbd, 0xf2, 0x1c, 0xcd, 0xf8, 0x96, 0xf3, 0xe0 } };
97 ERR(
"out of memory\n");
101 fcb = ExAllocateFromPagedLookasideList(&
Vcb->fcb_lookaside);
103 ERR(
"out of memory\n");
108#ifdef DEBUG_FCB_REFCOUNTS
109 WARN(
"allocating fcb %p\n",
fcb);
117 fcb->
nonpaged = ExAllocateFromNPagedLookasideList(&
Vcb->fcb_np_lookaside);
119 ERR(
"out of memory\n");
124 ExFreeToPagedLookasideList(&
Vcb->fcb_lookaside,
fcb);
137#ifdef DEBUG_FCB_REFCOUNTS
163 fr = ExAllocateFromPagedLookasideList(&
Vcb->fileref_lookaside);
165 ERR(
"out of memory\n");
173#ifdef DEBUG_FCB_REFCOUNTS
174 WARN(
"fileref %p: refcount now 1\n", fr);
194 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
230 le2 =
fcb->
Vcb->roots.Flink;
231 while (le2 != &
fcb->
Vcb->roots) {
234 if (
r2->id ==
dc->key.obj_id) {
253 }
else if (
dc->hash >
hash) {
270 if (
dc->hash_uc ==
hash) {
277 le2 =
fcb->
Vcb->roots.Flink;
278 while (le2 != &
fcb->
Vcb->roots) {
281 if (
r2->id ==
dc->key.obj_id) {
300 }
else if (
dc->hash_uc >
hash) {
332 if (
len == 0 || (
path->Buffer[
len - 1] ==
'/' ||
path->Buffer[
len - 1] ==
'\\')) {
333 WARN(
"zero-length filename part\n");
338 for (
i = 0;
i <
len;
i++) {
339 if (
path->Buffer[
i] ==
'/' ||
path->Buffer[
i] ==
'\\') {
341 }
else if (
path->Buffer[
i] ==
':') {
348 for (
i = 0;
i <
len;
i++) {
349 if (
path->Buffer[
i] ==
'/' ||
path->Buffer[
i] ==
'\\') {
350 if (
buf[0] ==
'/' ||
buf[0] ==
'\\') {
351 WARN(
"zero-length filename part\n");
356 nb = ExAllocateFromPagedLookasideList(&
Vcb->name_bit_lookaside);
358 ERR(
"out of memory\n");
371 nb = ExAllocateFromPagedLookasideList(&
Vcb->name_bit_lookaside);
373 ERR(
"out of memory\n");
383 static const WCHAR datasuf[] = {
':',
'$',
'D',
'A',
'T',
'A',0};
394 WARN(
"zero-length stream name\n");
399 nb2 = ExAllocateFromPagedLookasideList(&
Vcb->name_bit_lookaside);
401 ERR(
"out of memory\n");
426 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb);
433 if (has_stream &&
path->Length >=
sizeof(
WCHAR) &&
path->Buffer[0] ==
':') {
436 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb1);
447 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb);
467 ERR(
"error - find_item returned %08lx\n",
Status);
476 if (start < tp.item->
key.offset)
482 ERR(
"checksum not found for %I64x\n",
start + (
i <<
Vcb->sector_shift));
503 ERR(
"could not read checksums: offset %I64x, length %I64x sectors\n",
start,
length);
514 ULONG num_children = 0;
519 ERR(
"out of memory\n");
527 ERR(
"out of memory\n");
542 ERR(
"find_item returned %08lx\n",
Status);
570 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
576 ERR(
"out of memory\n");
584 dc->root_dir =
false;
586 max_index =
dc->index;
588 dc->utf8.MaximumLength =
dc->utf8.Length = di->
n;
590 if (!
dc->utf8.Buffer) {
591 ERR(
"out of memory\n");
598 dc->name.MaximumLength =
dc->name.Length = (
uint16_t)utf16len;
600 if (!
dc->name.Buffer) {
601 ERR(
"out of memory\n");
609 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
618 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
644 if (
Vcb->root_fileref &&
Vcb->root_fileref->fcb)
645 top_subvol =
Vcb->root_fileref->fcb->subvol;
652 ERR(
"out of memory\n");
659 dc->index = max_index + 1;
664 dc->utf8.MaximumLength =
dc->utf8.Length =
sizeof(
root_dir) -
sizeof(
char);
666 if (!
dc->utf8.Buffer) {
667 ERR(
"out of memory\n");
676 if (!
dc->name.Buffer) {
677 ERR(
"out of memory\n");
687 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
712 bool atts_set =
false, sd_set =
false, no_data;
720 acquire_fcb_lock_shared(
Vcb);
725 while (le != &
subvol->fcbs) {
733#ifdef DEBUG_FCB_REFCOUNTS
742 release_fcb_lock(
Vcb);
750 release_fcb_lock(
Vcb);
764 release_fcb_lock(
Vcb);
774 ERR(
"out of memory\n");
787 searchkey.
offset = 0xffffffffffffffff;
791 ERR(
"error - find_item returned %08lx\n",
Status);
797 WARN(
"couldn't find INODE_ITEM for inode %I64x in subvol %I64x\n",
inode,
subvol->id);
846 ERR(
"out of memory\n");
863 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
877 ERR(
"out of memory\n");
885 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
911 ERR(
"out of memory\n");
928 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
942 ERR(
"out of memory\n");
950 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
967 static const char xapref[] =
"user.";
985 ERR(
"out of memory\n");
1002 WARN(
"IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n",
Status,
offset);
1008 ERR(
"out of memory\n");
1033 if (get_file_attributes_from_xattr(&di->name[di->n], di->m, &
fcb->
atts)) {
1042 fcb->
atts &= ~FILE_ATTRIBUTE_DIRECTORY;
1048 fcb->
atts &= ~FILE_ATTRIBUTE_READONLY;
1056 ERR(
"out of memory\n");
1072 static const char lzo[] =
"lzo";
1073 static const char zlib[] =
"zlib";
1074 static const char zstd[] =
"zstd";
1076 if (di->m ==
sizeof(lzo) - 1 &&
RtlCompareMemory(&di->name[di->n], lzo, di->m) == di->m)
1078 else if (di->m ==
sizeof(zlib) - 1 &&
RtlCompareMemory(&di->name[di->n], zlib, di->m) == di->m)
1080 else if (di->m ==
sizeof(zstd) - 1 &&
RtlCompareMemory(&di->name[di->n], zstd, di->m) == di->m)
1090 }
else if (di->n >
sizeof(xapref) - 1 &&
RtlCompareMemory(xapref, di->name,
sizeof(xapref) - 1) ==
sizeof(xapref) - 1) {
1096 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
1103 ERR(
"out of memory\n");
1110 dc->utf8.MaximumLength =
dc->utf8.Length = di->n + 1 -
sizeof(xapref);
1112 if (!
dc->utf8.Buffer) {
1113 ERR(
"out of memory\n");
1121 dc->name.MaximumLength =
dc->name.Length = (
uint16_t)utf16len;
1123 if (!
dc->name.Buffer) {
1124 ERR(
"out of memory\n");
1133 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
1143 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
1159 ERR(
"out of memory\n");
1213 ERR(
"out of memory\n");
1222 ext->ignore =
false;
1223 ext->inserted =
false;
1233 ERR(
"load_dir_children returned %08lx\n",
Status);
1240 fcb->
Header.AllocationSize.QuadPart = 0;
1242 fcb->
Header.ValidDataLength.QuadPart = 0;
1259 acquire_fcb_lock_exclusive(
Vcb);
1272 while (le != &
subvol->fcbs) {
1280#ifdef DEBUG_FCB_REFCOUNTS
1283 WARN(
"fcb %p: refcount now %i (subvol %I64x, inode %I64x)\n", fcb2, rc, fcb2->
subvol->id, fcb2->
inode);
1290 release_fcb_lock(
Vcb);
1297 *pfcb = deleted_fcb;
1299 release_fcb_lock(
Vcb);
1312 fcb->
atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
1328 lastle =
subvol->fcbs_ptrs[
d]->Blink;
1357 release_fcb_lock(
Vcb);
1374 static const char xapref[] =
"user.";
1378 xattr.Length =
sizeof(xapref) - 1 +
dc->utf8.Length;
1381 if (!
xattr.Buffer) {
1382 ERR(
"out of memory\n");
1392 ERR(
"out of memory\n");
1402 ERR(
"get_xattr failed\n");
1423 ERR(
"find_item returned %08lx\n",
Status);
1429 ERR(
"error - could not find key for xattr\n");
1448 fcb->
Header.AllocationSize.QuadPart = xattrlen;
1449 fcb->
Header.FileSize.QuadPart = xattrlen;
1450 fcb->
Header.ValidDataLength.QuadPart = xattrlen;
1452 TRACE(
"stream found: size = %x, hash = %08x\n", xattrlen,
fcb->
adshash);
1465 if (sf->fcb ==
Vcb->dummy_fcb)
1469 bool locked =
false;
1480 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
1490 le = sf->fcb->dir_children_index.
Flink;
1491 while (le != &sf->fcb->dir_children_index) {
1494 if (dc2->
index == 0) {
1525 *psf2 =
dc->fileref;
1537 ERR(
"open_fcb_stream returned %08lx\n",
Status);
1543 acquire_fcb_lock_exclusive(
Vcb);
1545 if (sf->fcb->subvol->fcbs_ptrs[
fcb->
hash >> 24]) {
1546 le = sf->fcb->subvol->fcbs_ptrs[
fcb->
hash >> 24];
1548 while (le != &sf->fcb->subvol->fcbs) {
1570 release_fcb_lock(
Vcb);
1579 ERR(
"out of memory\n");
1602 ExFreeToPagedLookasideList(&
Vcb->fileref_lookaside, duff_fr);
1614 TRACE(
"invalid filename: %.*S\n", (
int)(
name->Length /
sizeof(
WCHAR)),
name->Buffer);
1617 ERR(
"find_file_in_dir returned %08lx\n",
Status);
1625 TRACE(
"passed path including file as subdirectory\n");
1630 *psf2 =
dc->fileref;
1641 ERR(
"open_fcb returned %08lx\n",
Status);
1647 TRACE(
"passed path including file as subdirectory\n");
1654 ERR(
"out of memory\n");
1696 bool has_stream =
false;
1700 TRACE(
"(%p, %p, %p, %u, %p)\n",
Vcb, pfr, related,
parent, parsed);
1702 if (
Vcb->removing ||
Vcb->locked)
1708 ERR(
"error - fnus was too short\n");
1712 if (related && fnus->Length == 0) {
1722 if (fnus2.
Buffer[0] !=
'\\') {
1723 ERR(
"error - filename %.*S did not begin with \\\n", (
int)(fnus2.
Length /
sizeof(
WCHAR)), fnus2.
Buffer);
1739 *pfr =
Vcb->root_fileref;
1756 WARN(
"passed related fileref which isn't a directory (fnus = %.*S)\n",
1757 (
int)(fnus->Length /
sizeof(
WCHAR)), fnus->Buffer);
1763 if (fnus->Length != 0 &&
1767 ERR(
"split_path returned %08lx\n",
Status);
1779 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb);
1783 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb);
1803 bool streampart = has_stream && le->
Flink == &
parts;
1804 bool cs = case_sensitive;
1807 if (streampart && sf->
parent)
1808 cs = sf->
parent->fcb->case_sensitive;
1817 TRACE(
"open_fileref_child returned %08lx\n",
Status);
1819 ERR(
"open_fileref_child returned %08lx\n",
Status);
1851 }
while (le != &
parts);
1862 ExFreeToPagedLookasideList(&
Vcb->name_bit_lookaside, nb);
1878 ERR(
"out of memory\n");
1885 if (!
dc->utf8.Buffer) {
1886 ERR(
"out of memory\n");
1892 if (!
dc->name.Buffer) {
1893 ERR(
"out of memory\n");
1901 dc->key.offset = subvol ? 0xffffffffffffffff : 0;
1905 dc->utf8.Length =
dc->utf8.MaximumLength =
utf8->Length;
1908 dc->name.Length =
dc->name.MaximumLength =
name->Length;
1913 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
1982 while (le != &ealist) {
1999 ERR(
"out of memory\n");
2023 while (le != &ealist) {
2029 ERR(
"uid value was shorter than expected\n");
2042 ERR(
"gid value was shorter than expected\n");
2056 ERR(
"mode value was shorter than expected\n");
2092 ERR(
"dev value was shorter than expected\n");
2116 while (le != &ealist) {
2129 ERR(
"out of memory\n");
2141 while (le != &ealist) {
2201#ifdef DEBUG_FCB_REFCOUNTS
2205 if (parfileref->fcb ==
Vcb->dummy_fcb)
2213 ERR(
"utf16_to_utf8 returned %08lx\n",
Status);
2219 ERR(
"out of memory\n");
2225 ERR(
"utf16_to_utf8 returned %08lx\n",
Status);
2235 TRACE(
"create file %.*S\n", (
int)(fpus->Length /
sizeof(
WCHAR)), fpus->Buffer);
2237 TRACE(
"parfileref->fcb->inode_item.st_size (inode %I64x) was %I64x\n", parfileref->fcb->inode, parfileref->fcb->inode_item.st_size);
2238 parfileref->fcb->inode_item.st_size += utf8len * 2;
2239 TRACE(
"parfileref->fcb->inode_item.st_size (inode %I64x) now %I64x\n", parfileref->fcb->inode, parfileref->fcb->inode_item.st_size);
2240 parfileref->fcb->inode_item.transid =
Vcb->superblock.generation;
2241 parfileref->fcb->inode_item.sequence++;
2242 parfileref->fcb->inode_item.st_ctime =
now;
2243 parfileref->fcb->inode_item.st_mtime =
now;
2246 parfileref->fcb->inode_item_changed =
true;
2273 TRACE(
"defda = %x\n", defda);
2280 ERR(
"out of memory\n");
2284 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2344 fcb->
Header.AllocationSize.QuadPart = 0;
2346 fcb->
Header.ValidDataLength.QuadPart = 0;
2351#ifdef DEBUG_FCB_REFCOUNTS
2353 WARN(
"fcb %p: refcount now %i\n", parfileref->fcb, rc);
2365 acquire_fcb_lock_exclusive(
Vcb);
2415 release_fcb_lock(
Vcb);
2422 ERR(
"fcb_get_new_sd returned %08lx\n",
Status);
2426 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2436 if (ea &&
ealen > 0) {
2439 ERR(
"file_create_parse_ea returned %08lx\n",
Status);
2443 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2454 ERR(
"out of memory\n");
2458 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2472 ERR(
"extend_file returned %08lx\n",
Status);
2476 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2488 ERR(
"out of memory\n");
2492 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2504 ERR(
"out of memory\n");
2508 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2523 fcb->
subvol->root_item.ctransid =
Vcb->superblock.generation;
2535 if (parfileref->fcb->hash_ptrs[dc_hash >> 24]) {
2536 LIST_ENTRY* le = parfileref->fcb->hash_ptrs[dc_hash >> 24];
2537 while (le != &parfileref->fcb->dir_children_hash) {
2540 if (
dc->hash == dc_hash &&
dc->name.Length == fpus->Length &&
RtlCompareMemory(
dc->name.Buffer, fpus->Buffer, fpus->Length) == fpus->Length) {
2541 existing_fileref =
dc->fileref;
2543 }
else if (
dc->hash > dc_hash)
2555 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
2559 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2569 if (parfileref->fcb->hash_ptrs_uc[dc_hash >> 24]) {
2570 LIST_ENTRY* le = parfileref->fcb->hash_ptrs_uc[dc_hash >> 24];
2571 while (le != &parfileref->fcb->dir_children_hash_uc) {
2575 existing_fileref =
dc->fileref;
2577 }
else if (
dc->hash_uc > dc_hash)
2587 if (existing_fileref) {
2592 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2598 *pfr = existing_fileref;
2606 ERR(
"add_dir_child returned %08lx\n",
Status);
2610 parfileref->fcb->inode_item.st_size -= utf8len * 2;
2646 static const char xapref[] =
"user.";
2647 static const WCHAR DOSATTRIB[] =
L"DOSATTRIB";
2648 static const WCHAR EA[] =
L"EA";
2649 static const WCHAR reparse[] =
L"reparse";
2650 static const WCHAR casesensitive_str[] =
L"casesensitive";
2653 ULONG utf8len, overhead;
2660#ifdef DEBUG_FCB_REFCOUNTS
2667 parfileref = *pparfileref;
2669 if (parfileref->
fcb ==
Vcb->dummy_fcb)
2689 ERR(
"out of memory\n");
2700 &granted_access, &
Status)) {
2710 ERR(
"file_create2 returned %08lx\n",
Status);
2720 ERR(
"open_fileref returned %08lx\n",
Status);
2724 parfileref = newpar;
2725 *pparfileref = parfileref;
2728 WARN(
"parent not file, directory, or symlink\n");
2734 WARN(
"tried to create directory as stream\n");
2748 &granted_access, &
Status)) {
2766 ERR(
"out of memory\n");
2774 fcb->
Header.AllocationSize.QuadPart = 0;
2776 fcb->
Header.ValidDataLength.QuadPart = 0;
2778#ifdef DEBUG_FCB_REFCOUNTS
2780 WARN(
"fcb %p: refcount now %i\n", parfileref->
fcb, rc);
2793 ERR(
"utf16_to_utf8 1 returned %08lx\n",
Status);
2803 ERR(
"out of memory\n");
2813 ERR(
"utf16_to_utf8 2 returned %08lx\n",
Status);
2832 ERR(
"find_item returned %08lx\n",
Status);
2845 if (utf8len +
sizeof(xapref) - 1 + overhead >
fcb->
adsmaxlen) {
2846 WARN(
"not enough room for new DIR_ITEM (%Iu + %lu > %lu)\n", utf8len +
sizeof(xapref) - 1, overhead,
fcb->
adsmaxlen);
2851 fcb->
adsmaxlen -= overhead + utf8len +
sizeof(xapref) - 1;
2856 acquire_fcb_lock_exclusive(
Vcb);
2859 parfileref->
fcb->
subvol->fcbs_version++;
2860 release_fcb_lock(
Vcb);
2866 ERR(
"out of memory\n");
2876 ERR(
"out of memory\n");
2886 if (!
dc->utf8.Buffer) {
2887 ERR(
"out of memory\n");
2896 dc->name.MaximumLength =
dc->name.Length =
stream->Length;
2898 if (!
dc->name.Buffer) {
2899 ERR(
"out of memory\n");
2911 ERR(
"RtlUpcaseUnicodeString returned %08lx\n",
Status);
2929 if (dc2->
index == 0) {
2950 *pfileref = existing_dc->
fileref;
2975 parfileref->
fcb->
subvol->root_item.ctransid =
Vcb->superblock.generation;
2980 *pfileref = fileref;
2997 ERR(
"ZwQueryInformationProcess returned %08lx\n",
Status);
3001 return !
pbi.PebBaseAddress;
3004#define called_from_lxss() false
3014 static const WCHAR datasuf[] = {
':',
'$',
'D',
'A',
'T',
'A',0};
3020#ifdef DEBUG_FCB_REFCOUNTS
3024 TRACE(
"(%p, %p, %p, %.*S, %lx, %lx)\n",
Irp,
Vcb,
FileObject, (
int)(fnus->
Length /
sizeof(
WCHAR)), fnus->
Buffer, disposition,
options);
3048 ERR(
"GUID_ECP_ATOMIC_CREATE context was too short: %lu bytes, expected %Iu\n", ctxsize,
3052 WARN(
"unhandled ECP GUID_ECP_QUERY_ON_CREATE\n");
3054 WARN(
"unhandled ECP GUID_ECP_CREATE_REDIRECTION\n");
3056 WARN(
"unhandled ECP {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
type.Data1,
type.Data2,
3069 if (!loaded_related) {
3075 parfileref = related;
3088 while ((fnus->
Buffer[
i] ==
'\\' || fnus->
Buffer[
i] ==
'/') &&
i > 0) {
i--; }
3092 while (
i > 0 && fnus->
Buffer[
i-1] !=
'\\' && fnus->
Buffer[
i-1] !=
'/') {
i--; }
3097 ERR(
"out of memory\n");
3116 TRACE(
"ignoring :$DATA suffix\n");
3142 ERR(
"create_stream returned %08lx\n",
Status);
3160 &granted_access, &
Status)) {
3172 ERR(
"IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n",
Status,
offset);
3181 *existing_fileref = fileref;
3184 ERR(
"file_create2 returned %08lx\n",
Status);
3198 ERR(
"out of memory\n");
3203 if (
stream.Length == 0) {
3230#ifdef DEBUG_FCB_REFCOUNTS
3232 ERR(
"fileref %p: open_count now %i\n", fileref, oc);
3247 fileref->
fcb->
atts &= ~FILE_ATTRIBUTE_DIRECTORY;
3256 ERR(
"set_reparse_point2 returned %08lx\n",
Status);
3260 if (
stream.Length == 0) {
3294 if (parfileref && !loaded_related)
3301 if (RequestedOptions != 0) {
3304 TRACE(
"requested options:\n");
3307 TRACE(
" FILE_DIRECTORY_FILE\n");
3308 options &= ~FILE_DIRECTORY_FILE;
3312 TRACE(
" FILE_WRITE_THROUGH\n");
3313 options &= ~FILE_WRITE_THROUGH;
3317 TRACE(
" FILE_SEQUENTIAL_ONLY\n");
3318 options &= ~FILE_SEQUENTIAL_ONLY;
3322 TRACE(
" FILE_NO_INTERMEDIATE_BUFFERING\n");
3323 options &= ~FILE_NO_INTERMEDIATE_BUFFERING;
3327 TRACE(
" FILE_SYNCHRONOUS_IO_ALERT\n");
3328 options &= ~FILE_SYNCHRONOUS_IO_ALERT;
3332 TRACE(
" FILE_SYNCHRONOUS_IO_NONALERT\n");
3333 options &= ~FILE_SYNCHRONOUS_IO_NONALERT;
3337 TRACE(
" FILE_NON_DIRECTORY_FILE\n");
3338 options &= ~FILE_NON_DIRECTORY_FILE;
3342 TRACE(
" FILE_CREATE_TREE_CONNECTION\n");
3343 options &= ~FILE_CREATE_TREE_CONNECTION;
3347 TRACE(
" FILE_COMPLETE_IF_OPLOCKED\n");
3348 options &= ~FILE_COMPLETE_IF_OPLOCKED;
3352 TRACE(
" FILE_NO_EA_KNOWLEDGE\n");
3353 options &= ~FILE_NO_EA_KNOWLEDGE;
3357 TRACE(
" FILE_OPEN_REMOTE_INSTANCE\n");
3358 options &= ~FILE_OPEN_REMOTE_INSTANCE;
3362 TRACE(
" FILE_RANDOM_ACCESS\n");
3363 options &= ~FILE_RANDOM_ACCESS;
3367 TRACE(
" FILE_DELETE_ON_CLOSE\n");
3368 options &= ~FILE_DELETE_ON_CLOSE;
3372 TRACE(
" FILE_OPEN_BY_FILE_ID\n");
3373 options &= ~FILE_OPEN_BY_FILE_ID;
3377 TRACE(
" FILE_OPEN_FOR_BACKUP_INTENT\n");
3378 options &= ~FILE_OPEN_FOR_BACKUP_INTENT;
3382 TRACE(
" FILE_NO_COMPRESSION\n");
3383 options &= ~FILE_NO_COMPRESSION;
3386#if NTDDI_VERSION >= NTDDI_WIN7
3388 TRACE(
" FILE_OPEN_REQUIRING_OPLOCK\n");
3389 options &= ~FILE_OPEN_REQUIRING_OPLOCK;
3393 TRACE(
" FILE_DISALLOW_EXCLUSIVE\n");
3394 options &= ~FILE_DISALLOW_EXCLUSIVE;
3399 TRACE(
" FILE_RESERVE_OPFILTER\n");
3400 options &= ~FILE_RESERVE_OPFILTER;
3404 TRACE(
" FILE_OPEN_REPARSE_POINT\n");
3405 options &= ~FILE_OPEN_REPARSE_POINT;
3409 TRACE(
" FILE_OPEN_NO_RECALL\n");
3410 options &= ~FILE_OPEN_NO_RECALL;
3414 TRACE(
" FILE_OPEN_FOR_FREE_SPACE_QUERY\n");
3415 options &= ~FILE_OPEN_FOR_FREE_SPACE_QUERY;
3421 TRACE(
"requested options: (none)\n");
3432 WARN(
"file was too short to be a reparse point\n");
3444 ERR(
"out of memory\n");
3450 ERR(
"read_file_fcb returned %08lx\n",
Status);
3462 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
3474 ERR(
"out of memory\n");
3493 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
3514 ERR(
"FsRtlValidateReparsePointBuffer returned %08lx\n",
Status);
3524 WARN(
"xattr was too short to be a reparse point\n");
3530 ERR(
"FsRtlValidateReparsePointBuffer returned %08lx\n",
Status);
3536 ERR(
"out of memory\n");
3569 ERR(
"out of memory\n");
3576 ERR(
"load_csum returned %08lx\n",
Status);
3613 ERR(
"stream_set_end_of_file_information returned %08lx\n",
Status);
3619 ERR(
"truncate_file returned %08lx\n",
Status);
3624 if (
Irp->Overlay.AllocationSize.QuadPart > 0) {
3628 ERR(
"extend_file returned %08lx\n",
Status);
3633 if (!fileref->
fcb->
ads) {
3642 ERR(
"IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n",
Status,
offset);
3649 eainfo =
Irp->AssociatedIrp.SystemBuffer;
3671 ERR(
"out of memory\n");
3694 if (
dc->index == 0) {
3700 WARN(
"open_fileref_child returned %08lx\n",
Status);
3708 ERR(
"delete_fileref returned %08lx\n",
Status);
3725 fileref->
parent->fcb->inode_item.st_mtime =
now;
3726 fileref->
parent->fcb->inode_item_changed =
true;
3743 if (fileref->
fcb->
atts != oldatts) {
3763 WARN(
"returning STATUS_ACCESS_DENIED as no EA knowledge\n");
3780 ERR(
"out of memory\n");
3803 FileObject->SectionObjectPointer = &fileref->fcb->nonpaged->segment_object;
3805 switch (RequestedDisposition) {
3825 bool changed =
false;
3829 le = fileref->fcb->extents.
Flink;
3831 while (le != &fileref->fcb->extents) {
3845 fileref->fcb->extents_changed =
true;
3852#ifdef DEBUG_FCB_REFCOUNTS
3854 ERR(
"fileref %p: open_count now %i\n", fileref, oc);
3952 if (
Vcb->readonly) {
3971 granted_access, &
Status)) {
3973 TRACE(
"SeAccessCheck failed, returning %08lx\n",
Status);
3979 *granted_access = 0;
3986 TRACE(
"could not open as deletion pending\n");
4026 *granted_access &= allowed;
4028 }
else if (*granted_access & ~allowed) {
4034 WARN(
"cannot overwrite readonly file\n");
4052 ERR(
"get_reparse_block returned %08lx\n",
Status);
4055 Irp->IoStatus.Information =
data->ReparseTag;
4057 if (
fn->Buffer[(
fn->Length /
sizeof(
WCHAR)) - 1] ==
'\\')
4060 Irp->Tail.Overlay.AuxiliaryBuffer = (
void*)
data;
4085 TRACE(
"IoCheckShareAccess failed, returning %08lx\n",
Status);
4087 WARN(
"IoCheckShareAccess failed, returning %08lx\n",
Status);
4094 ERR(
"out of memory\n");
4100 ctx->granted_access = *granted_access;
4116 WARN(
"FsRtlCheckOplock returned %08lx\n",
Status);
4142 bool hl_alloc =
false;
4147 ERR(
"open_fcb returned %08lx\n",
Status);
4174 while (le != &
Vcb->dirty_filerefs) {
4201 ERR(
"find_item returned %08lx\n",
Status);
4217 ERR(
"INODE_REF was too short\n");
4226 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
4239 ERR(
"out of memory\n");
4246 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
4262 ERR(
"INODE_EXTREF was too short\n");
4271 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
4284 ERR(
"out of memory\n");
4291 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
4314 WARN(
"trying to open inode with no references\n");
4333 searchkey.
offset = 0xffffffffffffffff;
4337 ERR(
"find_item returned %08lx\n",
Status);
4360 le =
Vcb->roots.Flink;
4361 while (le != &
Vcb->roots) {
4380 ERR(
"open_fileref_by_inode returned %08lx\n",
Status);
4387 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
4403 ERR(
"out of memory\n");
4410 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
4422 ERR(
"open_fileref_by_inode returned %08lx\n",
Status);
4430 ERR(
"couldn't find parent for subvol %I64x\n", subvol->
id);
4438 ERR(
"open_fileref_by_inode returned %08lx\n",
Status);
4450 ERR(
"open_fileref_child returned %08lx\n",
Status);
4469 ULONG RequestedDisposition;
4474 ULONG fn_offset = 0;
4478 bool loaded_related =
false;
4481 Irp->IoStatus.Information = 0;
4487 WARN(
"error - supersede requested with FILE_DIRECTORY_FILE\n");
4494 ERR(
"FileObject was NULL\n");
4499 struct _ccb* relatedccb =
FileObject->RelatedFileObject->FsContext2;
4501 related = relatedccb->
fileref;
4507 switch (RequestedDisposition) {
4509 TRACE(
"requested disposition: FILE_SUPERSEDE\n");
4513 TRACE(
"requested disposition: FILE_CREATE\n");
4517 TRACE(
"requested disposition: FILE_OPEN\n");
4521 TRACE(
"requested disposition: FILE_OPEN_IF\n");
4525 TRACE(
"requested disposition: FILE_OVERWRITE\n");
4529 TRACE(
"requested disposition: FILE_OVERWRITE_IF\n");
4533 ERR(
"unknown disposition: %lx\n", RequestedDisposition);
4549 if (RequestedDisposition !=
FILE_OPEN) {
4550 WARN(
"FILE_OPEN_BY_FILE_ID not supported for anything other than FILE_OPEN\n");
4559 WARN(
"cannot open by short file ID unless related fileref also provided"\
n);
4566 if (related->
fcb ==
Vcb->root_fileref->fcb &&
inode == 0)
4567 inode =
Vcb->root_fileref->fcb->inode;
4584 if (subvol_id ==
BTRFS_ROOT_FSTREE || (subvol_id >= 0x100 && subvol_id < 0x8000000000000000)) {
4586 while (le != &
Vcb->roots) {
4589 if (
r->id == subvol_id) {
4599 WARN(
"subvol %I64x not found\n", subvol_id);
4606 WARN(
"invalid ID size for FILE_OPEN_BY_FILE_ID\n");
4612 if (related &&
fn.Length != 0 &&
fn.Buffer[0] ==
'\\') {
4628 fnoff *=
sizeof(
WCHAR);
4636 fn.Buffer = &
fn.Buffer[fnoff /
sizeof(
WCHAR)];
4642 loaded_related =
true;
4659 ERR(
"get_reparse_block returned %08lx\n",
Status);
4668 Irp->Tail.Overlay.AuxiliaryBuffer = (
void*)
data;
4681 TRACE(
"file already exists, returning STATUS_OBJECT_NAME_COLLISION\n");
4690 TRACE(
"file doesn't exist, returning STATUS_OBJECT_NAME_NOT_FOUND\n");
4697 ERR(
"open_fileref returned %08lx\n",
Status);
4756 bool need_verify =
false;
4760 le =
Vcb->devices.Flink;
4761 while (le != &
Vcb->devices) {
4764 if (
dev->devobj &&
dev->removable) {
4771 ERR(
"IOCTL_STORAGE_CHECK_VERIFY returned %08lx (user-induced)\n",
Status);
4774 ERR(
"IOCTL_STORAGE_CHECK_VERIFY returned %08lx\n",
Status);
4777 ERR(
"iosb.Information was too short\n");
4779 }
else if (
cc !=
dev->change_count) {
4804 devobj =
Vcb->Vpb ?
Vcb->Vpb->RealDevice :
NULL;
4832 bool top_level, locked =
false;
4837 TRACE(
"create (flags = %lx)\n",
Irp->Flags);
4843 TRACE(
"create called for FS device object\n");
4862 if (
Vcb->removing) {
4869 ERR(
"verify_vcb returned %08lx\n",
Status);
4884 TRACE(
"SL_CASE_SENSITIVE\n");
4885 flags &= ~SL_CASE_SENSITIVE;
4889 TRACE(
"SL_FORCE_ACCESS_CHECK\n");
4890 flags &= ~SL_FORCE_ACCESS_CHECK;
4894 TRACE(
"SL_OPEN_PAGING_FILE\n");
4895 flags &= ~SL_OPEN_PAGING_FILE;
4899 TRACE(
"SL_OPEN_TARGET_DIRECTORY\n");
4900 flags &= ~SL_OPEN_TARGET_DIRECTORY;
4904 TRACE(
"SL_STOP_ON_SYMLINK\n");
4905 flags &= ~SL_STOP_ON_SYMLINK;
4909 TRACE(
"SL_IGNORE_READONLY_ATTRIBUTE\n");
4910 flags &= ~SL_IGNORE_READONLY_ATTRIBUTE;
4916 TRACE(
"flags: (none)\n");
4920 ERR(
"FileObject was NULL\n");
4928 if (relatedfcb && relatedfcb->
Vcb !=
Vcb) {
4929 WARN(
"RelatedFileObject was for different device\n");
4939#ifdef DEBUG_FCB_REFCOUNTS
4944 TRACE(
"open operation for volume\n");
4958 ERR(
"out of memory\n");
4975#ifdef DEBUG_FCB_REFCOUNTS
4977 WARN(
"fcb %p: refcount now %i (volume)\n",
Vcb->volume_fcb, rc);
4984 IrpSp->
FileObject->SectionObjectPointer = &
Vcb->volume_fcb->nonpaged->segment_object;
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
std::map< E_STRING, PART_TEST > parts
BOOLEAN NTAPI SeAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access rights can be given to an object depending on the security descrip...
unsigned short int uint16_t
#define InterlockedIncrement
#define FILE_DIRECTORY_FILE
#define FILE_NON_DIRECTORY_FILE
#define FILE_OPEN_FOR_FREE_SPACE_QUERY
#define FILE_COMPLETE_IF_OPLOCKED
#define FILE_DELETE_ON_CLOSE
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
NTSTATUS(__stdcall * tFsRtlValidateReparsePointBuffer)(ULONG BufferLength, PREPARSE_DATA_BUFFER ReparseBuffer)
#define increase_fileref_refcount(fileref)
#define InterlockedIncrement64(a)
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
#define EA_CASE_SENSITIVE
static __inline FAST_IO_POSSIBLE fast_io_possible(fcb *fcb)
#define keycmp(key1, key2)
#define _Dispatch_type_(a)
static const char lxgid[]
#define EA_PROP_COMPRESSION_HASH
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
#define BTRFS_NODE_TYPE_FCB
void fcb_get_sd(fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
#define EA_DOSATTRIB_HASH
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
static const char lxdev[]
static __inline POPLOCK fcb_oplock(fcb *fcb)
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file(fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS(__stdcall * tFsRtlGetEcpListFromIrp)(PIRP Irp, PECP_LIST *EcpList)
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define EA_PROP_COMPRESSION
NTSTATUS set_reparse_point2(fcb *fcb, REPARSE_DATA_BUFFER *rdb, ULONG buflen, ccb *ccb, file_ref *fileref, PIRP Irp, LIST_ENTRY *rollback)
NTSTATUS(__stdcall * tFsRtlGetNextExtraCreateParameter)(PECP_LIST EcpList, PVOID CurrentEcpContext, LPGUID NextEcpType, PVOID *NextEcpContext, ULONG *NextEcpContextSize)
static const char lxmod[]
static const char lxuid[]
#define EA_CASE_SENSITIVE_HASH
bool is_extent_unique(device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
#define __S_ISTYPE(mode, mask)
void insert_dir_child_into_hash_lists(fcb *fcb, dir_child *dc)
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
NTSTATUS fcb_get_new_sd(fcb *fcb, file_ref *parfileref, ACCESS_STATE *as)
NTSTATUS vol_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
#define BTRFS_NODE_TYPE_CCB
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
static __inline bool write_fcb_compressed(fcb *fcb)
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define _Requires_lock_held_(lock)
#define _Requires_exclusive_lock_held_(lock)
#define STATUS_NOT_IMPLEMENTED
#define NT_SUCCESS(StatCode)
static string utf16_to_utf8(const wstring_view &utf16)
wstring utf8_to_utf16(const string_view &utf8)
#define FILE_ATTRIBUTE_NORMAL
#define crc32(crc, buf, len)
static const WCHAR *const ext[]
static void cleanup(void)
static LONG find_item(PropertyBag *This, LPCOLESTR name)
void mark_fcb_dirty(_In_ fcb *fcb)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
NTSTATUS delete_fileref(_In_ file_ref *fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback)
void free_fileref(_Inout_ file_ref *fr)
void reap_fileref(device_extension *Vcb, file_ref *fr)
void free_fcb(_Inout_ fcb *fcb)
void mark_fileref_dirty(_In_ file_ref *fileref)
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)
bool is_top_level(_In_ PIRP Irp)
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
_Ret_maybenull_ root * find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_opt_ PIRP Irp)
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream)
void send_notification_fileref(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
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)
#define TYPE_INODE_EXTREF
#define EXTENT_TYPE_PREALLOC
#define BTRFS_SUBVOL_READONLY
#define BTRFS_INODE_RO_VERITY
#define EXTENT_TYPE_INLINE
#define TYPE_ROOT_BACKREF
#define EXTENT_TYPE_REGULAR
#define BTRFS_COMPRESSION_NONE
#define BTRFS_ROOT_FSTREE
#define SL_IGNORE_READONLY_ATTRIBUTE
static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
static NTSTATUS open_file2(device_extension *Vcb, ULONG RequestedDisposition, file_ref *fileref, ACCESS_MASK *granted_access, PFILE_OBJECT FileObject, UNICODE_STRING *fn, ULONG options, PIRP Irp, LIST_ENTRY *rollback, oplock_context **opctx)
static const WCHAR datastring[]
static void __stdcall oplock_complete(PVOID Context, PIRP Irp)
#define ATOMIC_CREATE_ECP_OUT_FLAG_OP_FLAGS_HONORED
static const GUID GUID_ECP_ATOMIC_CREATE
struct _FILE_TIMESTAMPS * PFILE_TIMESTAMPS
#define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED
static NTSTATUS file_create2(_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ PUNICODE_STRING fpus, _In_ file_ref *parfileref, _In_ ULONG options, _In_reads_bytes_opt_(ealen) FILE_FULL_EA_INFORMATION *ea, _In_ ULONG ealen, _Out_ file_ref **pfr, bool case_sensitive, _In_ LIST_ENTRY *rollback)
static const char root_dir[]
static NTSTATUS get_reparse_block(fcb *fcb, uint8_t **data)
uint32_t inherit_mode(fcb *parfcb, bool is_dir)
static const WCHAR root_dir_utf16[]
#define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET
static __inline void debug_create_options(ULONG RequestedOptions)
struct _ATOMIC_CREATE_ECP_CONTEXT ATOMIC_CREATE_ECP_CONTEXT
#define ATOMIC_CREATE_ECP_IN_FLAG_REPARSE_POINT_SPECIFIED
NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension *Vcb, _In_ file_ref *sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, _In_ POOL_TYPE pooltype, _Out_ file_ref **psf2, _In_opt_ PIRP Irp)
static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, file_ref **pfileref, file_ref **pparfileref, PUNICODE_STRING fpus, PUNICODE_STRING stream, PIRP Irp, ULONG options, POOL_TYPE pool_type, bool case_sensitive, LIST_ENTRY *rollback)
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)
struct _ATOMIC_CREATE_ECP_CONTEXT * PATOMIC_CREATE_ECP_CONTEXT
static const GUID GUID_ECP_QUERY_ON_CREATE
#define called_from_lxss()
static NTSTATUS file_create_parse_ea(fcb *fcb, FILE_FULL_EA_INFORMATION *ea)
static void fcb_load_csums(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, PIRP Irp)
NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, void *csum, uint64_t start, uint64_t length, PIRP Irp)
static NTSTATUS verify_vcb(device_extension *Vcb, PIRP Irp)
tFsRtlGetEcpListFromIrp fFsRtlGetEcpListFromIrp
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)
#define ATOMIC_CREATE_ECP_IN_FLAG_OP_FLAGS_SPECIFIED
PDEVICE_OBJECT master_devobj
tFsRtlGetNextExtraCreateParameter fFsRtlGetNextExtraCreateParameter
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)
struct _FILE_TIMESTAMPS FILE_TIMESTAMPS
static NTSTATUS open_file3(device_extension *Vcb, PIRP Irp, ACCESS_MASK granted_access, file_ref *fileref, LIST_ENTRY *rollback)
static NTSTATUS split_path(device_extension *Vcb, PUNICODE_STRING path, LIST_ENTRY *parts, bool *stream)
static NTSTATUS open_fcb_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, dir_child *dc, fcb *parent, fcb **pfcb, PIRP Irp)
tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer
static bool has_manage_volume_privilege(ACCESS_STATE *access_state, KPROCESSOR_MODE processor_mode)
#define ATOMIC_CREATE_ECP_OUT_FLAG_REPARSE_POINT_SET
fcb * create_fcb(device_extension *Vcb, POOL_TYPE pool_type)
NTSTATUS add_dir_child(fcb *fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child **pdc)
file_ref * create_fileref(device_extension *Vcb)
static const GUID GUID_ECP_CREATE_REDIRECTION
NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb *fcb, root **subvol, uint64_t *inode, dir_child **pdc, bool case_sensitive)
static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, PFILE_OBJECT FileObject, file_ref *related, bool loaded_related, PUNICODE_STRING fnus, ULONG disposition, ULONG options, file_ref **existing_fileref, LIST_ENTRY *rollback)
NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, fcb *fcb, bool ignore_size, PIRP Irp)
_In_ PIO_STACK_LOCATION IrpSp
#define RemoveEntryList(Entry)
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
#define IsListEmpty(ListHead)
#define PsGetCurrentThread()
NTSTATUS ExInitializeResourceLite(PULONG res)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define RtlCompareMemory(s1, s2, l)
#define KeInitializeEvent(pEvt, foo, foo2)
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
#define KeSetEvent(pEvt, foo, foo2)
#define KeQuerySystemTime(t)
#define RemoveTailList(ListHead)
#define ExAcquireResourceExclusiveLite(res, wait)
#define RemoveHeadList(ListHead)
#define InitializeListHead(ListHead)
#define ExAcquireResourceSharedLite(res, wait)
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
#define FILE_OPEN_BY_FILE_ID
#define FILE_NO_COMPRESSION
#define FILE_OVERWRITE_IF
#define FILE_OPEN_REPARSE_POINT
#define FILE_NO_EA_KNOWLEDGE
#define FILE_RESERVE_OPFILTER
#define FILE_SYNCHRONOUS_IO_NONALERT
#define FILE_NO_INTERMEDIATE_BUFFERING
#define FILE_RANDOM_ACCESS
#define FILE_WRITE_THROUGH
#define FILE_OPEN_NO_RECALL
#define FILE_SEQUENTIAL_ONLY
#define FILE_SYNCHRONOUS_IO_ALERT
#define FILE_OPEN_REMOTE_INSTANCE
#define FILE_CREATE_TREE_CONNECTION
#define FILE_OPEN_FOR_BACKUP_INTENT
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define FSRTL_FLAG2_IS_PAGING_FILE
VOID(NTAPI * POPLOCK_WAIT_COMPLETE_ROUTINE)(_In_ PVOID Context, _In_ PIRP Irp)
GLuint GLuint GLsizei GLenum type
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble r
GLint const GLchar GLint stringlen
GLboolean GLboolean GLboolean b
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint GLsizei GLsizei * length
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
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
#define FILE_OPEN_REQUIRING_OPLOCK
@ ProcessBasicInformation
NTSYSAPI BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR, ULONG, SECURITY_INFORMATION)
#define SE_MANAGE_VOLUME_PRIVILEGE
static PIO_STATUS_BLOCK iosb
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define _Function_class_(n)
#define _In_reads_bytes_opt_(s)
#define FILE_ATTRIBUTE_READONLY
#define ACCESS_SYSTEM_SECURITY
#define FILE_READ_ATTRIBUTES
#define FILE_LIST_DIRECTORY
#define FILE_ATTRIBUTE_HIDDEN
#define FILE_ATTRIBUTE_SYSTEM
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FILE_DELETE_CHILD
#define NtCurrentProcess()
#define FILE_WRITE_ATTRIBUTES
#define FILE_VALID_OPTION_FLAGS
#define FILE_ATTRIBUTE_ARCHIVE
#define FILE_ATTRIBUTE_DIRECTORY
#define FILE_ADD_SUBDIRECTORY
NTSYSAPI VOID NTAPI RtlUpperString(PSTRING DestinationString, PSTRING SourceString)
#define FILE_ATTRIBUTE_TEMPORARY
#define IOCTL_STORAGE_CHECK_VERIFY
#define FILE_ATTRIBUTE_REPARSE_POINT
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
VOID NTAPI IoSetShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
VOID NTAPI IoUpdateShareAccess(IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
#define IoCompleteRequest
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
VOID NTAPI IoSetDeviceToVerify(IN PETHREAD Thread, IN PDEVICE_OBJECT DeviceObject)
PDEVICE_OBJECT NTAPI IoGetDeviceToVerify(IN PETHREAD Thread)
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
NTSTATUS NTAPI IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount)
BOOLEAN NTAPI SePrivilegeCheck(_In_ PPRIVILEGE_SET Privileges, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a set of privileges exist and match within a security subject context.
#define STATUS_INTERNAL_ERROR
#define STATUS_DELETE_PENDING
#define STATUS_USER_MAPPED_FILE
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)
VOID NTAPI FsRtlInitializeOplock(IN OUT POPLOCK Oplock)
#define BTRFS_INODE_NOCOMPRESS
#define BTRFS_INODE_COMPRESS
#define BTRFS_INODE_NODATASUM
#define BTRFS_INODE_NODATACOW
#define offsetof(TYPE, MEMBER)
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
#define SUBVOL_ROOT_INODE
#define STATUS_CANNOT_DELETE
#define STATUS_DEVICE_NOT_READY
#define SYMLINK_FLAG_RELATIVE
#define BTRFS_TYPE_DIRECTORY
#define BTRFS_TYPE_SOCKET
#define BTRFS_TYPE_SYMLINK
#define BTRFS_TYPE_CHARDEV
#define BTRFS_TYPE_BLOCKDEV
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
PREPARSE_DATA_BUFFER ReparseBuffer
ULONG CaseSensitiveFlagsMask
ULONG InCaseSensitiveFlags
ULONG OutCaseSensitiveFlags
ULONG SuppressFileAttributeInheritanceMask
USHORT ReparseBufferLength
PFILE_TIMESTAMPS FileTimestamps
LARGE_INTEGER LastAccessTime
LARGE_INTEGER LastWriteTime
LARGE_INTEGER CreationTime
struct _IO_STACK_LOCATION::@4104::@4105 Create
union _IO_STACK_LOCATION::@1611 Parameters
struct _LIST_ENTRY * Blink
struct _LIST_ENTRY * Flink
LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY]
struct _REPARSE_DATA_BUFFER::@334::@336 SymbolicLinkReparseBuffer
bool manage_volume_privilege
uint64_t query_dir_offset
UNICODE_STRING query_string
LIST_ENTRY list_entry_all
LIST_ENTRY dir_children_index
struct _file_ref * fileref
LIST_ENTRY dir_children_hash
LIST_ENTRY ** hash_ptrs_uc
struct _device_extension * Vcb
LIST_ENTRY dir_children_hash_uc
ANSI_STRING reparse_xattr
enum prop_compression_type prop_compression
struct _fcb_nonpaged * nonpaged
SHARE_ACCESS share_access
bool prop_compression_changed
FSRTL_ADVANCED_FCB_HEADER Header
struct _file_ref * parent
struct _file_ref * fileref
ACCESS_MASK granted_access
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
#define STATUS_FILE_IS_A_DIRECTORY
#define STATUS_NOT_A_DIRECTORY
#define STATUS_MEDIA_WRITE_PROTECTED
#define STATUS_ACCESS_DENIED
#define STATUS_OBJECT_PATH_NOT_FOUND
#define STATUS_INVALID_PARAMETER
#define STATUS_OBJECT_NAME_COLLISION
#define STATUS_VERIFY_REQUIRED
#define STATUS_SHARING_VIOLATION
#define STATUS_OBJECT_NAME_INVALID
#define STATUS_INSUFFICIENT_RESOURCES
#define STATUS_OBJECT_NAME_NOT_FOUND
_In_ PDEVICE_OBJECT DeviceObject
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
static GLenum _GLUfuncptr fn
_Inout_ PERBANDINFO * pbi
#define ExIsResourceAcquiredExclusive
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
#define IoIsErrorUserInduced(Status)
#define SL_OPEN_PAGING_FILE
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define FILE_DISALLOW_EXCLUSIVE
#define SL_FORCE_ACCESS_CHECK
#define FILE_NOTIFY_CHANGE_STREAM_NAME
#define FILE_ACTION_REMOVED_STREAM
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define SL_STOP_ON_SYMLINK
#define IO_DISK_INCREMENT
#define IO_REPARSE_TAG_SYMLINK
#define FO_CACHE_SUPPORTED
#define FILE_ACTION_ADDED_STREAM
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define SL_OPEN_TARGET_DIRECTORY
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define SL_CASE_SENSITIVE
#define PRIVILEGE_SET_ALL_NECESSARY