1 /* Copyright (c) Mark Harmstone 2016-17
3 * This file is part of WinBtrfs.
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.
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.
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/>. */
24 #define _WIN32_WINNT 0x0601
25 #define NTDDI_VERSION 0x06020000 // Win 8
26 #define _CRT_SECURE_NO_WARNINGS
27 #define _NO_CRT_STDIO_INLINE
28 #endif /* __REACTOS__ */
32 #pragma warning(disable:4163)
33 #pragma warning(disable:4311)
34 #pragma warning(disable:4312)
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wsign-compare"
38 #pragma GCC diagnostic ignored "-Wsign-conversion"
45 #endif /* __REACTOS__ */
50 #include <pseh/pseh2.h>
51 #endif /* __REACTOS__ */
58 #pragma GCC diagnostic pop
68 #include <emmintrin.h>
69 #endif /* __REACTOS__ */
71 #include "btrfsioctl.h"
74 C_ASSERT(sizeof(bool) == 1);
78 // #define DEBUG_FCB_REFCOUNTS
79 // #define DEBUG_LONG_MESSAGES
80 // #define DEBUG_FLUSH_TIMES
81 // #define DEBUG_CHUNK_LOCKS
82 // #define DEBUG_TRIM_EMULATION
83 #define DEBUG_PARANOID
86 #define UNUSED(x) (void)(x)
88 #define BTRFS_NODE_TYPE_CCB 0x2295
89 #define BTRFS_NODE_TYPE_FCB 0x2296
91 #define ALLOC_TAG 0x7442484D //'MHBt'
92 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
94 #define UID_NOBODY 65534
95 #define GID_NOBODY 65534
97 #define EA_NTACL "security.NTACL"
98 #define EA_NTACL_HASH 0x45922146
100 #define EA_DOSATTRIB "user.DOSATTRIB"
101 #define EA_DOSATTRIB_HASH 0x914f9939
103 #define EA_REPARSE "user.reparse"
104 #define EA_REPARSE_HASH 0xfabad1fe
106 #define EA_EA "user.EA"
107 #define EA_EA_HASH 0x8270dd43
109 #define EA_CASE_SENSITIVE "user.casesensitive"
110 #define EA_CASE_SENSITIVE_HASH 0x1a9d97d4
112 #define EA_PROP_COMPRESSION "btrfs.compression"
113 #define EA_PROP_COMPRESSION_HASH 0x20ccdf69
115 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
116 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
118 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
120 #define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
122 #define IO_REPARSE_TAG_LXSS_SOCKET 0x80000023
123 #define IO_REPARSE_TAG_LXSS_FIFO 0x80000024
124 #define IO_REPARSE_TAG_LXSS_CHARDEV 0x80000025
125 #define IO_REPARSE_TAG_LXSS_BLOCKDEV 0x80000026
127 #define BTRFS_VOLUME_PREFIX L"\\Device\\Btrfs{"
131 #define except __except
132 #define finally __finally
135 #define except(x) if (0 && (x))
136 #define finally if (1)
141 #define InterlockedIncrement64(a) __sync_add_and_fetch(a, 1)
145 #ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING
146 #define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000
149 #ifndef FILE_SUPPORTS_POSIX_UNLINK_RENAME
150 #define FILE_SUPPORTS_POSIX_UNLINK_RENAME 0x00000400
153 #ifndef FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
154 #define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
157 typedef struct _FILE_ID_128
{
158 UCHAR Identifier
[16];
159 } FILE_ID_128
, *PFILE_ID_128
;
161 typedef struct _DUPLICATE_EXTENTS_DATA
{
163 LARGE_INTEGER SourceFileOffset
;
164 LARGE_INTEGER TargetFileOffset
;
165 LARGE_INTEGER ByteCount
;
166 } DUPLICATE_EXTENTS_DATA
, *PDUPLICATE_EXTENTS_DATA
;
168 #define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
170 typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
{
171 WORD ChecksumAlgorithm
;
174 DWORD ChecksumChunkSizeInBytes
;
175 DWORD ClusterSizeInBytes
;
176 } FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER
;
178 typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
{
179 WORD ChecksumAlgorithm
;
182 } FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER
;
184 #define FSCTL_GET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)
185 #define FSCTL_SET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
189 #define __drv_aliasesMem
190 #define _Requires_lock_held_(a)
191 #define _Requires_exclusive_lock_held_(a)
192 #define _Releases_lock_(a)
193 #define _Out_writes_bytes_opt_(a)
194 #define _Pre_satisfies_(a)
195 #define _Post_satisfies_(a)
196 #define _Releases_exclusive_lock_(a)
197 #define _Dispatch_type_(a)
198 #define _Create_lock_level_(a)
199 #define _Lock_level_order_(a,b)
200 #define _Has_lock_level_(a)
201 #define _Requires_lock_not_held_(a)
202 #define _Acquires_exclusive_lock_(a)
203 #define _Acquires_shared_lock_(a)
207 _Create_lock_level_(tree_lock
)
208 _Create_lock_level_(fcb_lock
)
209 _Lock_level_order_(tree_lock
, fcb_lock
)
211 struct _device_extension
;
213 typedef struct _fcb_nonpaged
{
214 FAST_MUTEX HeaderMutex
;
215 SECTION_OBJECT_POINTERS segment_object
;
217 ERESOURCE paging_resource
;
218 ERESOURCE dir_children_lock
;
231 LIST_ENTRY list_entry
;
233 EXTENT_DATA extent_data
;
241 LIST_ENTRY list_entry
;
254 UNICODE_STRING name_uc
;
256 struct _file_ref
* fileref
;
258 LIST_ENTRY list_entry_index
;
259 LIST_ENTRY list_entry_hash
;
260 LIST_ENTRY list_entry_hash_uc
;
263 enum prop_compression_type
{
264 PropCompression_None
,
265 PropCompression_Zlib
,
271 LIST_ENTRY list_entry
;
278 typedef struct _fcb
{
279 FSRTL_ADVANCED_FCB_HEADER Header
;
280 struct _fcb_nonpaged
* nonpaged
;
283 struct _device_extension
* Vcb
;
284 struct _root
* subvol
;
288 INODE_ITEM inode_item
;
289 SECURITY_DESCRIPTOR
* sd
;
292 PKTHREAD lazy_writer_thread
;
294 SHARE_ACCESS share_access
;
297 ANSI_STRING reparse_xattr
;
298 ANSI_STRING ea_xattr
;
300 LIST_ENTRY hardlinks
;
301 struct _file_ref
* fileref
;
302 bool inode_item_changed
;
303 enum prop_compression_type prop_compression
;
305 bool marked_as_orphan
;
307 bool case_sensitive_set
;
310 LIST_ENTRY dir_children_index
;
311 LIST_ENTRY dir_children_hash
;
312 LIST_ENTRY dir_children_hash_uc
;
313 LIST_ENTRY
** hash_ptrs
;
314 LIST_ENTRY
** hash_ptrs_uc
;
317 bool sd_dirty
, sd_deleted
;
318 bool atts_changed
, atts_deleted
;
319 bool extents_changed
;
320 bool reparse_xattr_changed
;
322 bool prop_compression_changed
;
329 ANSI_STRING adsxattr
;
332 LIST_ENTRY list_entry
;
333 LIST_ENTRY list_entry_all
;
334 LIST_ENTRY list_entry_dirty
;
338 ERESOURCE fileref_lock
;
341 typedef struct _file_ref
{
345 bool delete_on_close
;
349 file_ref_nonpaged
* nonpaged
;
353 struct _file_ref
* parent
;
358 LIST_ENTRY list_entry
;
359 LIST_ENTRY list_entry_dirty
;
366 KEVENT cleared_event
;
368 LIST_ENTRY list_entry
;
371 typedef struct _ccb
{
376 uint64_t query_dir_offset
;
377 UNICODE_STRING query_string
;
380 bool manage_volume_privilege
;
381 bool allow_extended_dasd_io
;
385 UNICODE_STRING filename
;
388 bool user_set_creation_time
;
389 bool user_set_access_time
;
390 bool user_set_write_time
;
391 bool user_set_change_time
;
394 NTSTATUS send_status
;
397 struct _device_extension
;
405 typedef struct _tree_data
{
407 LIST_ENTRY list_entry
;
412 tree_holder treeholder
;
425 typedef struct _tree
{
426 tree_nonpaged
* nonpaged
;
431 struct _device_extension
* Vcb
;
432 struct _tree
* parent
;
436 LIST_ENTRY list_entry
;
437 LIST_ENTRY list_entry_hash
;
438 uint64_t new_address
;
439 bool has_new_address
;
440 bool updated_extents
;
443 bool uniqueness_determined
;
448 ERESOURCE load_tree_lock
;
451 typedef struct _root
{
453 LONGLONG lastinode
; // signed so we can use InterlockedIncrement64
454 tree_holder treeholder
;
455 root_nonpaged
* nonpaged
;
462 uint64_t fcbs_version
;
463 bool checked_for_orphans
;
465 LIST_ENTRY
* fcbs_ptrs
[256];
466 LIST_ENTRY list_entry
;
467 LIST_ENTRY list_entry_dirty
;
470 enum batch_operation
{
474 Batch_DeleteInodeRef
,
475 Batch_DeleteInodeExtRef
,
477 Batch_DeleteExtentData
,
478 Batch_DeleteFreeSpace
,
490 enum batch_operation operation
;
491 LIST_ENTRY list_entry
;
497 LIST_ENTRY list_entry
;
505 typedef struct _root_cache
{
507 struct _root_cache
* next
;
513 LIST_ENTRY list_entry
;
514 LIST_ENTRY list_entry_size
;
518 PDEVICE_OBJECT devobj
;
519 PFILE_OBJECT fileobj
;
533 LIST_ENTRY list_entry
;
534 ULONG num_trim_entries
;
535 LIST_ENTRY trim_list
;
542 LIST_ENTRY list_entry
;
550 LIST_ENTRY list_entry
;
555 CHUNK_ITEM
* chunk_item
;
564 LIST_ENTRY space_size
;
566 LIST_ENTRY changed_extents
;
567 LIST_ENTRY range_locks
;
568 ERESOURCE range_locks_lock
;
569 KEVENT range_locks_event
;
571 ERESOURCE changed_extents_lock
;
580 uint16_t last_stripe
;
581 LIST_ENTRY partial_stripes
;
582 ERESOURCE partial_stripes_lock
;
585 LIST_ENTRY list_entry
;
586 LIST_ENTRY list_entry_balance
;
599 LIST_ENTRY list_entry
;
610 LIST_ENTRY list_entry
;
611 } changed_extent_ref
;
617 LIST_ENTRY list_entry
;
627 LIST_ENTRY list_entry
;
631 PDEVICE_OBJECT DeviceObject
;
641 drv_calc_thread
* threads
;
649 uint8_t compress_type
;
653 uint32_t flush_interval
;
664 #define VCB_TYPE_FS 1
665 #define VCB_TYPE_CONTROL 2
666 #define VCB_TYPE_VOLUME 3
667 #define VCB_TYPE_PDO 4
668 #define VCB_TYPE_BUS 5
670 #define BALANCE_OPTS_DATA 0
671 #define BALANCE_OPTS_METADATA 1
672 #define BALANCE_OPTS_SYSTEM 2
676 uint64_t total_chunks
;
677 uint64_t chunks_left
;
678 btrfs_balance_opts opts
[3];
696 LIST_ENTRY list_entry
;
702 uint16_t filename_length
;
716 ERESOURCE stats_lock
;
721 LARGE_INTEGER start_time
;
722 LARGE_INTEGER finish_time
;
723 LARGE_INTEGER resume_time
;
724 LARGE_INTEGER duration
;
725 uint64_t total_chunks
;
726 uint64_t chunks_left
;
727 uint64_t data_scrubbed
;
733 struct _volume_device_extension
;
735 typedef struct _device_extension
{
737 mount_options options
;
739 PDEVICE_OBJECT devobj
;
740 struct _volume_device_extension
* vde
;
742 #ifdef DEBUG_CHUNK_LOCKS
743 LONG chunk_locks_held
;
745 uint64_t devices_loaded
;
746 superblock superblock
;
750 bool lock_paused_balance
;
751 bool disallow_dismount
;
752 LONG page_file_count
;
754 PFILE_OBJECT locked_fileobj
;
757 file_ref
* root_fileref
;
759 _Has_lock_level_(fcb_lock
) ERESOURCE fcb_lock
;
760 ERESOURCE fileref_lock
;
762 _Has_lock_level_(tree_lock
) ERESOURCE tree_lock
;
763 PNOTIFY_SYNC NotifySync
;
764 LIST_ENTRY DirNotifyList
;
768 uint64_t metadata_flags
;
769 uint64_t system_flags
;
771 LIST_ENTRY drop_roots
;
778 root
* data_reloc_root
;
780 bool log_to_phys_loaded
;
781 bool chunk_usage_found
;
782 LIST_ENTRY sys_chunks
;
785 LIST_ENTRY trees_hash
;
786 LIST_ENTRY
* trees_ptrs
[256];
787 FAST_MUTEX trees_list_mutex
;
789 LIST_ENTRY dirty_fcbs
;
790 ERESOURCE dirty_fcbs_lock
;
791 LIST_ENTRY dirty_filerefs
;
792 ERESOURCE dirty_filerefs_lock
;
793 LIST_ENTRY dirty_subvols
;
794 ERESOURCE dirty_subvols_lock
;
795 ERESOURCE chunk_lock
;
796 HANDLE flush_thread_handle
;
797 KTIMER flush_thread_timer
;
798 KEVENT flush_thread_finished
;
799 drv_calc_threads calcthreads
;
800 balance_info balance
;
802 ERESOURCE send_load_lock
;
805 PFILE_OBJECT root_file
;
806 PAGED_LOOKASIDE_LIST tree_data_lookaside
;
807 PAGED_LOOKASIDE_LIST traverse_ptr_lookaside
;
808 PAGED_LOOKASIDE_LIST batch_item_lookaside
;
809 PAGED_LOOKASIDE_LIST fileref_lookaside
;
810 PAGED_LOOKASIDE_LIST fcb_lookaside
;
811 PAGED_LOOKASIDE_LIST name_bit_lookaside
;
812 NPAGED_LOOKASIDE_LIST range_lock_lookaside
;
813 NPAGED_LOOKASIDE_LIST fileref_np_lookaside
;
814 NPAGED_LOOKASIDE_LIST fcb_np_lookaside
;
815 LIST_ENTRY list_entry
;
820 } control_device_extension
;
824 PDEVICE_OBJECT buspdo
;
825 PDEVICE_OBJECT attached_device
;
826 UNICODE_STRING bus_name
;
827 } bus_device_extension
;
833 PDEVICE_OBJECT devobj
;
834 PFILE_OBJECT fileobj
;
835 UNICODE_STRING pnp_name
;
838 bool had_drive_letter
;
839 void* notification_entry
;
842 LIST_ENTRY list_entry
;
845 struct pdo_device_extension
;
847 typedef struct _volume_device_extension
{
850 PDEVICE_OBJECT device
;
851 PDEVICE_OBJECT mounted_device
;
853 struct pdo_device_extension
* pdode
;
854 UNICODE_STRING bus_name
;
855 PDEVICE_OBJECT attached_device
;
859 } volume_device_extension
;
861 typedef struct pdo_device_extension
{
864 volume_device_extension
* vde
;
869 uint64_t num_children
;
870 uint64_t children_loaded
;
871 ERESOURCE child_lock
;
874 LIST_ENTRY list_entry
;
875 } pdo_device_extension
;
878 LIST_ENTRY listentry
;
884 LIST_ENTRY listentry
;
889 enum write_data_status
{
890 WriteDataStatus_Pending
,
891 WriteDataStatus_Success
,
892 WriteDataStatus_Error
,
893 WriteDataStatus_Cancelling
,
894 WriteDataStatus_Cancelled
,
895 WriteDataStatus_Ignore
898 struct _write_data_context
;
901 struct _write_data_context
* context
;
906 IO_STATUS_BLOCK iosb
;
907 enum write_data_status status
;
908 LIST_ENTRY list_entry
;
911 typedef struct _write_data_context
{
916 uint8_t *parity1
, *parity2
, *scratch
;
917 PMDL mdl
, parity1_mdl
, parity2_mdl
;
918 } write_data_context
;
926 LIST_ENTRY list_entry
;
931 LIST_ENTRY list_entry
;
934 _Requires_lock_not_held_(Vcb
->fcb_lock
)
935 _Acquires_shared_lock_(Vcb
->fcb_lock
)
936 static __inline
void acquire_fcb_lock_shared(device_extension
* Vcb
) {
937 ExAcquireResourceSharedLite(&Vcb
->fcb_lock
, true);
940 _Requires_lock_not_held_(Vcb
->fcb_lock
)
941 _Acquires_exclusive_lock_(Vcb
->fcb_lock
)
942 static __inline
void acquire_fcb_lock_exclusive(device_extension
* Vcb
) {
943 ExAcquireResourceExclusiveLite(&Vcb
->fcb_lock
, true);
946 _Requires_lock_held_(Vcb
->fcb_lock
)
947 _Releases_lock_(Vcb
->fcb_lock
)
948 static __inline
void release_fcb_lock(device_extension
* Vcb
) {
949 ExReleaseResourceLite(&Vcb
->fcb_lock
);
952 static __inline
void* map_user_buffer(PIRP Irp
, ULONG priority
) {
953 if (!Irp
->MdlAddress
) {
954 return Irp
->UserBuffer
;
956 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, priority
);
960 static __inline
uint64_t unix_time_to_win(BTRFS_TIME
* t
) {
961 return (t
->seconds
* 10000000) + (t
->nanoseconds
/ 100) + 116444736000000000;
964 static __inline
void win_time_to_unix(LARGE_INTEGER t
, BTRFS_TIME
* out
) {
965 ULONGLONG l
= (ULONGLONG
)t
.QuadPart
- 116444736000000000;
967 out
->seconds
= l
/ 10000000;
968 out
->nanoseconds
= (uint32_t)((l
% 10000000) * 100);
971 _Post_satisfies_(*stripe
>=0&&*stripe
<num_stripes
)
972 static __inline
void get_raid0_offset(_In_
uint64_t off
, _In_
uint64_t stripe_length
, _In_
uint16_t num_stripes
, _Out_
uint64_t* stripeoff
, _Out_
uint16_t* stripe
) {
973 uint64_t initoff
, startoff
;
975 startoff
= off
% (num_stripes
* stripe_length
);
976 initoff
= (off
/ (num_stripes
* stripe_length
)) * stripe_length
;
978 *stripe
= (uint16_t)(startoff
/ stripe_length
);
979 *stripeoff
= initoff
+ startoff
- (*stripe
* stripe_length
);
982 /* We only have 64 bits for a file ID, which isn't technically enough to be
983 * unique on Btrfs. We fudge it by having three bytes for the subvol and
984 * five for the inode, which should be good enough.
985 * Inodes are also 64 bits on Linux, but the Linux driver seems to get round
986 * this by tricking it into thinking subvols are separate volumes. */
987 static __inline
uint64_t make_file_id(root
* r
, uint64_t inode
) {
988 return (r
->id
<< 40) | (inode
& 0xffffffffff);
991 #define keycmp(key1, key2)\
992 ((key1.obj_id < key2.obj_id) ? -1 :\
993 ((key1.obj_id > key2.obj_id) ? 1 :\
994 ((key1.obj_type < key2.obj_type) ? -1 :\
995 ((key1.obj_type > key2.obj_type) ? 1 :\
996 ((key1.offset < key2.offset) ? -1 :\
997 ((key1.offset > key2.offset) ? 1 :\
1000 _Post_satisfies_(return>=n
)
1001 __inline
static uint64_t sector_align(_In_
uint64_t n
, _In_
uint64_t a
) {
1003 n
= (n
+ a
) & ~(a
- 1);
1008 __inline
static bool is_subvol_readonly(root
* r
, PIRP Irp
) {
1009 if (!(r
->root_item
.flags
& BTRFS_SUBVOL_READONLY
))
1015 return (!Irp
|| Irp
->RequestorMode
== UserMode
) && PsGetCurrentProcess() != r
->reserved
? true : false;
1018 __inline
static uint16_t get_extent_data_len(uint8_t type
) {
1020 case TYPE_TREE_BLOCK_REF
:
1021 return sizeof(TREE_BLOCK_REF
);
1023 case TYPE_EXTENT_DATA_REF
:
1024 return sizeof(EXTENT_DATA_REF
);
1026 case TYPE_EXTENT_REF_V0
:
1027 return sizeof(EXTENT_REF_V0
);
1029 case TYPE_SHARED_BLOCK_REF
:
1030 return sizeof(SHARED_BLOCK_REF
);
1032 case TYPE_SHARED_DATA_REF
:
1033 return sizeof(SHARED_DATA_REF
);
1040 __inline
static uint32_t get_extent_data_refcount(uint8_t type
, void* data
) {
1042 case TYPE_TREE_BLOCK_REF
:
1045 case TYPE_EXTENT_DATA_REF
:
1047 EXTENT_DATA_REF
* edr
= (EXTENT_DATA_REF
*)data
;
1051 case TYPE_EXTENT_REF_V0
:
1053 EXTENT_REF_V0
* erv0
= (EXTENT_REF_V0
*)data
;
1057 case TYPE_SHARED_BLOCK_REF
:
1060 case TYPE_SHARED_DATA_REF
:
1062 SHARED_DATA_REF
* sdr
= (SHARED_DATA_REF
*)data
;
1073 device
* find_device_from_uuid(_In_ device_extension
* Vcb
, _In_ BTRFS_UUID
* uuid
);
1076 bool get_file_attributes_from_xattr(_In_reads_bytes_(len
) char* val
, _In_
uint16_t len
, _Out_ ULONG
* atts
);
1078 ULONG
get_file_attributes(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _In_
uint64_t inode
,
1079 _In_
uint8_t type
, _In_
bool dotfile
, _In_
bool ignore_xa
, _In_opt_ PIRP Irp
);
1082 bool get_xattr(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* subvol
, _In_
uint64_t inode
, _In_z_
char* name
, _In_
uint32_t crc32
,
1083 _Out_
uint8_t** data
, _Out_
uint16_t* datalen
, _In_opt_ PIRP Irp
);
1085 #ifndef DEBUG_FCB_REFCOUNTS
1086 void free_fcb(_Inout_ fcb
* fcb
);
1088 void free_fileref(_Inout_ file_ref
* fr
);
1089 void protect_superblocks(_Inout_ chunk
* c
);
1090 bool is_top_level(_In_ PIRP Irp
);
1091 NTSTATUS
create_root(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_
uint64_t id
,
1092 _Out_ root
** rootptr
, _In_
bool no_tree
, _In_
uint64_t offset
, _In_opt_ PIRP Irp
);
1093 void uninit(_In_ device_extension
* Vcb
);
1094 NTSTATUS
dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject
, _In_ ULONG ControlCode
, _In_reads_bytes_opt_(InputBufferSize
) PVOID InputBuffer
, _In_ ULONG InputBufferSize
,
1095 _Out_writes_bytes_opt_(OutputBufferSize
) PVOID OutputBuffer
, _In_ ULONG OutputBufferSize
, _In_
bool Override
, _Out_opt_ IO_STATUS_BLOCK
* iosb
);
1096 bool is_file_name_valid(_In_ PUNICODE_STRING us
, _In_
bool posix
, _In_
bool stream
);
1097 void send_notification_fileref(_In_ file_ref
* fileref
, _In_ ULONG filter_match
, _In_ ULONG action
, _In_opt_ PUNICODE_STRING stream
);
1098 void queue_notification_fcb(_In_ file_ref
* fileref
, _In_ ULONG filter_match
, _In_ ULONG action
, _In_opt_ PUNICODE_STRING stream
);
1100 #ifdef DEBUG_CHUNK_LOCKS
1101 #define acquire_chunk_lock(c, Vcb) { ExAcquireResourceExclusiveLite(&c->lock, true); InterlockedIncrement(&Vcb->chunk_locks_held); }
1102 #define release_chunk_lock(c, Vcb) { InterlockedDecrement(&Vcb->chunk_locks_held); ExReleaseResourceLite(&c->lock); }
1104 #define acquire_chunk_lock(c, Vcb) ExAcquireResourceExclusiveLite(&(c)->lock, true)
1105 #define release_chunk_lock(c, Vcb) ExReleaseResourceLite(&(c)->lock)
1108 void mark_fcb_dirty(_In_ fcb
* fcb
);
1109 void mark_fileref_dirty(_In_ file_ref
* fileref
);
1110 NTSTATUS
delete_fileref(_In_ file_ref
* fileref
, _In_opt_ PFILE_OBJECT FileObject
, _In_
bool make_orphan
, _In_opt_ PIRP Irp
, _In_ LIST_ENTRY
* rollback
);
1111 void chunk_lock_range(_In_ device_extension
* Vcb
, _In_ chunk
* c
, _In_
uint64_t start
, _In_
uint64_t length
);
1112 void chunk_unlock_range(_In_ device_extension
* Vcb
, _In_ chunk
* c
, _In_
uint64_t start
, _In_
uint64_t length
);
1113 void init_device(_In_ device_extension
* Vcb
, _Inout_ device
* dev
, _In_
bool get_nums
);
1114 void init_file_cache(_In_ PFILE_OBJECT FileObject
, _In_ CC_FILE_SIZES
* ccfs
);
1115 NTSTATUS
sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject
, _In_ PFILE_OBJECT FileObject
, _In_
uint64_t StartingOffset
, _In_ ULONG Length
,
1116 _Out_writes_bytes_(Length
) PUCHAR Buffer
, _In_
bool override
);
1117 NTSTATUS
get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject
, _Out_ PUNICODE_STRING pnp_name
, _Out_
const GUID
** guid
);
1118 void log_device_error(_In_ device_extension
* Vcb
, _Inout_ device
* dev
, _In_
int error
);
1119 NTSTATUS
find_chunk_usage(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_opt_ PIRP Irp
);
1121 _Function_class_(DRIVER_ADD_DEVICE
)
1122 NTSTATUS __stdcall
AddDevice(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT PhysicalDeviceObject
);
1124 void reap_fcb(fcb
* fcb
);
1125 void reap_fcbs(device_extension
* Vcb
);
1126 void reap_fileref(device_extension
* Vcb
, file_ref
* fr
);
1127 void reap_filerefs(device_extension
* Vcb
, file_ref
* fr
);
1128 uint64_t chunk_estimate_phys_size(device_extension
* Vcb
, chunk
* c
, uint64_t u
);
1129 NTSTATUS
utf8_to_utf16(WCHAR
* dest
, ULONG dest_max
, ULONG
* dest_len
, char* src
, ULONG src_len
);
1130 NTSTATUS
utf16_to_utf8(char* dest
, ULONG dest_max
, ULONG
* dest_len
, WCHAR
* src
, ULONG src_len
);
1131 uint32_t get_num_of_processors();
1134 root
* find_default_subvol(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_opt_ PIRP Irp
);
1136 void do_shutdown(PIRP Irp
);
1139 #define funcname __FUNCTION__
1141 #define funcname __func__
1144 extern bool have_sse2
;
1146 extern uint32_t mount_compress
;
1147 extern uint32_t mount_compress_force
;
1148 extern uint32_t mount_compress_type
;
1149 extern uint32_t mount_zlib_level
;
1150 extern uint32_t mount_zstd_level
;
1151 extern uint32_t mount_flush_interval
;
1152 extern uint32_t mount_max_inline
;
1153 extern uint32_t mount_skip_balance
;
1154 extern uint32_t mount_no_barrier
;
1155 extern uint32_t mount_no_trim
;
1156 extern uint32_t mount_clear_cache
;
1157 extern uint32_t mount_allow_degraded
;
1158 extern uint32_t mount_readonly
;
1159 extern uint32_t mount_no_root_dir
;
1160 extern uint32_t no_pnp
;
1164 extern bool log_started
;
1165 extern uint32_t debug_log_level
;
1167 #ifdef DEBUG_LONG_MESSAGES
1169 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
1171 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
1172 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
1173 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
1174 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
1176 void _debug_message(_In_
const char* func
, _In_
const char* file
, _In_
unsigned int line
, _In_
char* s
, ...);
1180 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
1182 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
1183 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
1184 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
1185 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
1187 void _debug_message(_In_
const char* func
, _In_
char* s
, ...);
1193 #define TRACE(s, ...)
1194 #define WARN(s, ...)
1195 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
1196 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
1200 #ifdef DEBUG_FCB_REFCOUNTS
1201 void _free_fcb(_Inout_ fcb
* fcb
, _In_
const char* func
);
1202 #define free_fcb(fcb) _free_fcb(fcb, funcname)
1206 void init_fast_io_dispatch(FAST_IO_DISPATCH
** fiod
);
1209 uint32_t calc_crc32c(_In_
uint32_t seed
, _In_reads_bytes_(msglen
) uint8_t* msg
, _In_ ULONG msglen
);
1213 LIST_ENTRY
* list_size
;
1224 enum rollback_type
{
1225 ROLLBACK_INSERT_EXTENT
,
1226 ROLLBACK_DELETE_EXTENT
,
1228 ROLLBACK_SUBTRACT_SPACE
1232 enum rollback_type type
;
1234 LIST_ENTRY list_entry
;
1241 LIST_ENTRY list_entry
;
1244 static const char lxuid
[] = "$LXUID";
1245 static const char lxgid
[] = "$LXGID";
1246 static const char lxmod
[] = "$LXMOD";
1247 static const char lxdev
[] = "$LXDEV";
1250 NTSTATUS
find_item(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _Out_ traverse_ptr
* tp
,
1251 _In_
const KEY
* searchkey
, _In_
bool ignore
, _In_opt_ PIRP Irp
);
1252 NTSTATUS
find_item_to_level(device_extension
* Vcb
, root
* r
, traverse_ptr
* tp
, const KEY
* searchkey
, bool ignore
, uint8_t level
, PIRP Irp
);
1253 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
);
1254 bool find_prev_item(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, const traverse_ptr
* tp
, traverse_ptr
* prev_tp
, PIRP Irp
);
1255 void free_trees(device_extension
* Vcb
);
1256 NTSTATUS
insert_tree_item(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _In_
uint64_t obj_id
,
1257 _In_
uint8_t obj_type
, _In_
uint64_t offset
, _In_reads_bytes_opt_(size
) _When_(return >= 0, __drv_aliasesMem
) void* data
,
1258 _In_
uint16_t size
, _Out_opt_ traverse_ptr
* ptp
, _In_opt_ PIRP Irp
);
1259 NTSTATUS
delete_tree_item(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _Inout_ traverse_ptr
* tp
);
1260 void free_tree(tree
* t
);
1261 NTSTATUS
load_tree(device_extension
* Vcb
, uint64_t addr
, uint8_t* buf
, root
* r
, tree
** pt
);
1262 NTSTATUS
do_load_tree(device_extension
* Vcb
, tree_holder
* th
, root
* r
, tree
* t
, tree_data
* td
, PIRP Irp
);
1263 void clear_rollback(LIST_ENTRY
* rollback
);
1264 void do_rollback(device_extension
* Vcb
, LIST_ENTRY
* rollback
);
1265 void free_trees_root(device_extension
* Vcb
, root
* r
);
1266 void add_rollback(_In_ LIST_ENTRY
* rollback
, _In_
enum rollback_type type
, _In_ __drv_aliasesMem
void* ptr
);
1267 NTSTATUS
commit_batch_list(_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1268 void clear_batch_list(device_extension
* Vcb
, LIST_ENTRY
* batchlist
);
1269 NTSTATUS
skip_to_difference(device_extension
* Vcb
, traverse_ptr
* tp
, traverse_ptr
* tp2
, bool* ended1
, bool* ended2
);
1272 NTSTATUS
remove_drive_letter(PDEVICE_OBJECT mountmgr
, PUNICODE_STRING devpath
);
1274 _Function_class_(KSTART_ROUTINE
)
1275 void __stdcall
mountmgr_thread(_In_
void* context
);
1277 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1278 NTSTATUS __stdcall
pnp_notification(PVOID NotificationStructure
, PVOID Context
);
1280 void disk_arrival(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1281 void volume_arrival(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1282 void volume_removal(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1284 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1285 NTSTATUS __stdcall
volume_notification(PVOID NotificationStructure
, PVOID Context
);
1287 void remove_volume_child(_Inout_
_Requires_exclusive_lock_held_(_Curr_
->child_lock
) _Releases_exclusive_lock_(_Curr_
->child_lock
) _In_ volume_device_extension
* vde
,
1288 _In_ volume_child
* vc
, _In_
bool skip_dev
);
1292 extern CACHE_MANAGER_CALLBACKS cache_callbacks
;
1295 NTSTATUS
write_file(device_extension
* Vcb
, PIRP Irp
, bool wait
, bool deferred_write
);
1296 NTSTATUS
write_file2(device_extension
* Vcb
, PIRP Irp
, LARGE_INTEGER offset
, void* buf
, ULONG
* length
, bool paging_io
, bool no_cache
,
1297 bool wait
, bool deferred_write
, bool write_irp
, LIST_ENTRY
* rollback
);
1298 NTSTATUS
truncate_file(fcb
* fcb
, uint64_t end
, PIRP Irp
, LIST_ENTRY
* rollback
);
1299 NTSTATUS
extend_file(fcb
* fcb
, file_ref
* fileref
, uint64_t end
, bool prealloc
, PIRP Irp
, LIST_ENTRY
* rollback
);
1300 NTSTATUS
excise_extents(device_extension
* Vcb
, fcb
* fcb
, uint64_t start_data
, uint64_t end_data
, PIRP Irp
, LIST_ENTRY
* rollback
);
1301 chunk
* get_chunk_from_address(device_extension
* Vcb
, uint64_t address
);
1302 NTSTATUS
alloc_chunk(device_extension
* Vcb
, uint64_t flags
, chunk
** pc
, bool full_size
);
1303 NTSTATUS
write_data(_In_ device_extension
* Vcb
, _In_
uint64_t address
, _In_reads_bytes_(length
) void* data
, _In_
uint32_t length
, _In_ write_data_context
* wtc
,
1304 _In_opt_ PIRP Irp
, _In_opt_ chunk
* c
, _In_
bool file_write
, _In_
uint64_t irp_offset
, _In_ ULONG priority
);
1305 NTSTATUS
write_data_complete(device_extension
* Vcb
, uint64_t address
, void* data
, uint32_t length
, PIRP Irp
, chunk
* c
, bool file_write
, uint64_t irp_offset
, ULONG priority
);
1306 void free_write_data_stripes(write_data_context
* wtc
);
1308 _Dispatch_type_(IRP_MJ_WRITE
)
1309 _Function_class_(DRIVER_DISPATCH
)
1310 NTSTATUS __stdcall
drv_write(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1312 _Requires_lock_held_(c
->lock
)
1313 _When_(return != 0, _Releases_lock_(c
->lock
))
1314 bool insert_extent_chunk(_In_ device_extension
* Vcb
, _In_ fcb
* fcb
, _In_ chunk
* c
, _In_
uint64_t start_data
, _In_
uint64_t length
, _In_
bool prealloc
, _In_opt_
void* data
,
1315 _In_opt_ PIRP Irp
, _In_ LIST_ENTRY
* rollback
, _In_
uint8_t compression
, _In_
uint64_t decoded_size
, _In_
bool file_write
, _In_
uint64_t irp_offset
);
1317 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
);
1318 NTSTATUS
write_compressed(fcb
* fcb
, uint64_t start_data
, uint64_t end_data
, void* data
, PIRP Irp
, LIST_ENTRY
* rollback
);
1319 bool find_data_address_in_chunk(device_extension
* Vcb
, chunk
* c
, uint64_t length
, uint64_t* address
);
1320 void get_raid56_lock_range(chunk
* c
, uint64_t address
, uint64_t length
, uint64_t* lockaddr
, uint64_t* locklen
);
1321 NTSTATUS
calc_csum(_In_ device_extension
* Vcb
, _In_reads_bytes_(sectors
*Vcb
->superblock
.sector_size
) uint8_t* data
,
1322 _In_
uint32_t sectors
, _Out_writes_bytes_(sectors
*sizeof(uint32_t)) uint32_t* csum
);
1323 void add_insert_extent_rollback(LIST_ENTRY
* rollback
, fcb
* fcb
, extent
* ext
);
1324 NTSTATUS
add_extent_to_fcb(_In_ fcb
* fcb
, _In_
uint64_t offset
, _In_reads_bytes_(edsize
) EXTENT_DATA
* ed
, _In_
uint16_t edsize
,
1325 _In_
bool unique
, _In_opt_
_When_(return >= 0, __drv_aliasesMem
) uint32_t* csum
, _In_ LIST_ENTRY
* rollback
);
1326 void add_extent(_In_ fcb
* fcb
, _In_ LIST_ENTRY
* prevextle
, _In_ __drv_aliasesMem extent
* newext
);
1330 _Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL
)
1331 _Function_class_(DRIVER_DISPATCH
)
1332 NTSTATUS __stdcall
drv_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1334 ULONG
get_reparse_tag(device_extension
* Vcb
, root
* subvol
, uint64_t inode
, uint8_t type
, ULONG atts
, bool lxss
, PIRP Irp
);
1335 ULONG
get_reparse_tag_fcb(fcb
* fcb
);
1339 _Dispatch_type_(IRP_MJ_QUERY_SECURITY
)
1340 _Function_class_(DRIVER_DISPATCH
)
1341 NTSTATUS __stdcall
drv_query_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1343 _Dispatch_type_(IRP_MJ_SET_SECURITY
)
1344 _Function_class_(DRIVER_DISPATCH
)
1345 NTSTATUS __stdcall
drv_set_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1347 void fcb_get_sd(fcb
* fcb
, struct _fcb
* parent
, bool look_for_xattr
, PIRP Irp
);
1348 void add_user_mapping(WCHAR
* sidstring
, ULONG sidstringlength
, uint32_t uid
);
1349 void add_group_mapping(WCHAR
* sidstring
, ULONG sidstringlength
, uint32_t gid
);
1350 uint32_t sid_to_uid(PSID sid
);
1351 NTSTATUS
uid_to_sid(uint32_t uid
, PSID
* sid
);
1352 NTSTATUS
fcb_get_new_sd(fcb
* fcb
, file_ref
* parfileref
, ACCESS_STATE
* as
);
1353 void find_gid(struct _fcb
* fcb
, struct _fcb
* parfcb
, PSECURITY_SUBJECT_CONTEXT subjcont
);
1357 _Dispatch_type_(IRP_MJ_SET_INFORMATION
)
1358 _Function_class_(DRIVER_DISPATCH
)
1359 NTSTATUS __stdcall
drv_set_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1361 _Dispatch_type_(IRP_MJ_QUERY_INFORMATION
)
1362 _Function_class_(DRIVER_DISPATCH
)
1363 NTSTATUS __stdcall
drv_query_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1365 _Dispatch_type_(IRP_MJ_QUERY_EA
)
1366 _Function_class_(DRIVER_DISPATCH
)
1367 NTSTATUS __stdcall
drv_query_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1369 _Dispatch_type_(IRP_MJ_SET_EA
)
1370 _Function_class_(DRIVER_DISPATCH
)
1371 NTSTATUS __stdcall
drv_set_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1373 bool has_open_children(file_ref
* fileref
);
1374 NTSTATUS
stream_set_end_of_file_information(device_extension
* Vcb
, uint16_t end
, fcb
* fcb
, file_ref
* fileref
, bool advance_only
);
1375 NTSTATUS
fileref_get_filename(file_ref
* fileref
, PUNICODE_STRING fn
, USHORT
* name_offset
, ULONG
* preqlen
);
1376 void insert_dir_child_into_hash_lists(fcb
* fcb
, dir_child
* dc
);
1377 void remove_dir_child_from_hash_lists(fcb
* fcb
, dir_child
* dc
);
1380 NTSTATUS
get_reparse_point(PDEVICE_OBJECT DeviceObject
, PFILE_OBJECT FileObject
, void* buffer
, DWORD buflen
, ULONG_PTR
* retlen
);
1381 NTSTATUS
set_reparse_point2(fcb
* fcb
, REPARSE_DATA_BUFFER
* rdb
, ULONG buflen
, ccb
* ccb
, file_ref
* fileref
, PIRP Irp
, LIST_ENTRY
* rollback
);
1382 NTSTATUS
set_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1383 NTSTATUS
delete_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1387 _Dispatch_type_(IRP_MJ_CREATE
)
1388 _Function_class_(DRIVER_DISPATCH
)
1389 NTSTATUS __stdcall
drv_create(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1391 NTSTATUS
open_fileref(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
, _Out_ file_ref
** pfr
,
1392 _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
,
1393 _In_
bool case_sensitive
, _In_opt_ PIRP Irp
);
1394 NTSTATUS
open_fcb(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) device_extension
* Vcb
,
1395 root
* subvol
, uint64_t inode
, uint8_t type
, PANSI_STRING utf8
, bool always_add_hl
, fcb
* parent
, fcb
** pfcb
, POOL_TYPE pooltype
, PIRP Irp
);
1396 NTSTATUS
load_csum(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, uint32_t* csum
, uint64_t start
, uint64_t length
, PIRP Irp
);
1397 NTSTATUS
load_dir_children(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, fcb
* fcb
, bool ignore_size
, PIRP Irp
);
1398 NTSTATUS
add_dir_child(fcb
* fcb
, uint64_t inode
, bool subvol
, PANSI_STRING utf8
, PUNICODE_STRING name
, uint8_t type
, dir_child
** pdc
);
1399 NTSTATUS
open_fileref_child(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
,
1400 _In_ file_ref
* sf
, _In_ PUNICODE_STRING name
, _In_
bool case_sensitive
, _In_
bool lastpart
, _In_
bool streampart
,
1401 _In_ POOL_TYPE pooltype
, _Out_ file_ref
** psf2
, _In_opt_ PIRP Irp
);
1402 fcb
* create_fcb(device_extension
* Vcb
, POOL_TYPE pool_type
);
1403 NTSTATUS
find_file_in_dir(PUNICODE_STRING filename
, fcb
* fcb
, root
** subvol
, uint64_t* inode
, dir_child
** pdc
, bool case_sensitive
);
1404 uint32_t inherit_mode(fcb
* parfcb
, bool is_dir
);
1405 file_ref
* create_fileref(device_extension
* Vcb
);
1406 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
);
1409 NTSTATUS
fsctl_request(PDEVICE_OBJECT DeviceObject
, PIRP
* Pirp
, uint32_t type
);
1410 void do_unlock_volume(device_extension
* Vcb
);
1411 void trim_whole_device(device
* dev
);
1412 void flush_subvol_fcbs(root
* subvol
);
1413 bool fcb_is_inline(fcb
* fcb
);
1414 NTSTATUS
dismount_volume(device_extension
* Vcb
, bool shutdown
, PIRP Irp
);
1418 _Function_class_(KSTART_ROUTINE
)
1419 void __stdcall
flush_thread(void* context
);
1421 NTSTATUS
do_write(device_extension
* Vcb
, PIRP Irp
);
1422 NTSTATUS
get_tree_new_address(device_extension
* Vcb
, tree
* t
, PIRP Irp
, LIST_ENTRY
* rollback
);
1423 NTSTATUS
flush_fcb(fcb
* fcb
, bool cache
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1424 NTSTATUS
write_data_phys(_In_ PDEVICE_OBJECT device
, _In_ PFILE_OBJECT fileobj
, _In_
uint64_t address
,
1425 _In_reads_bytes_(length
) void* data
, _In_
uint32_t length
);
1426 bool is_tree_unique(device_extension
* Vcb
, tree
* t
, PIRP Irp
);
1427 NTSTATUS
do_tree_writes(device_extension
* Vcb
, LIST_ENTRY
* tree_writes
, bool no_free
);
1428 void add_checksum_entry(device_extension
* Vcb
, uint64_t address
, ULONG length
, uint32_t* csum
, PIRP Irp
);
1429 bool find_metadata_address_in_chunk(device_extension
* Vcb
, chunk
* c
, uint64_t* address
);
1430 void add_trim_entry_avoid_sb(device_extension
* Vcb
, device
* dev
, uint64_t address
, uint64_t size
);
1431 NTSTATUS
insert_tree_item_batch(LIST_ENTRY
* batchlist
, device_extension
* Vcb
, root
* r
, uint64_t objid
, uint8_t objtype
, uint64_t offset
,
1432 _In_opt_
_When_(return >= 0, __drv_aliasesMem
) void* data
, uint16_t datalen
, enum batch_operation operation
);
1433 NTSTATUS
flush_partial_stripe(device_extension
* Vcb
, chunk
* c
, partial_stripe
* ps
);
1434 NTSTATUS
update_dev_item(device_extension
* Vcb
, device
* device
, PIRP Irp
);
1438 _Dispatch_type_(IRP_MJ_READ
)
1439 _Function_class_(DRIVER_DISPATCH
)
1440 NTSTATUS __stdcall
drv_read(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1442 NTSTATUS
read_data(_In_ device_extension
* Vcb
, _In_
uint64_t addr
, _In_
uint32_t length
, _In_reads_bytes_opt_(length
*sizeof(uint32_t)/Vcb
->superblock
.sector_size
) uint32_t* csum
,
1443 _In_
bool is_tree
, _Out_writes_bytes_(length
) uint8_t* buf
, _In_opt_ chunk
* c
, _Out_opt_ chunk
** pc
, _In_opt_ PIRP Irp
, _In_
uint64_t generation
, _In_
bool file_read
,
1444 _In_ ULONG priority
);
1445 NTSTATUS
read_file(fcb
* fcb
, uint8_t* data
, uint64_t start
, uint64_t length
, ULONG
* pbr
, PIRP Irp
);
1446 NTSTATUS
read_stream(fcb
* fcb
, uint8_t* data
, uint64_t start
, ULONG length
, ULONG
* pbr
);
1447 NTSTATUS
do_read(PIRP Irp
, bool wait
, ULONG
* bytes_read
);
1448 NTSTATUS
check_csum(device_extension
* Vcb
, uint8_t* data
, uint32_t sectors
, uint32_t* csum
);
1449 void raid6_recover2(uint8_t* sectors
, uint16_t num_stripes
, ULONG sector_size
, uint16_t missing1
, uint16_t missing2
, uint8_t* out
);
1453 _Dispatch_type_(IRP_MJ_PNP
)
1454 _Function_class_(DRIVER_DISPATCH
)
1455 NTSTATUS __stdcall
drv_pnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1457 NTSTATUS
pnp_surprise_removal(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1458 NTSTATUS
pnp_query_remove_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1461 NTSTATUS
load_cache_chunk(device_extension
* Vcb
, chunk
* c
, PIRP Irp
);
1462 NTSTATUS
clear_free_space_cache(device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1463 NTSTATUS
allocate_cache(device_extension
* Vcb
, bool* changed
, PIRP Irp
, LIST_ENTRY
* rollback
);
1464 NTSTATUS
update_chunk_caches(device_extension
* Vcb
, PIRP Irp
, LIST_ENTRY
* rollback
);
1465 NTSTATUS
update_chunk_caches_tree(device_extension
* Vcb
, PIRP Irp
);
1466 NTSTATUS
add_space_entry(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, uint64_t offset
, uint64_t size
);
1467 void space_list_add(chunk
* c
, uint64_t address
, uint64_t length
, LIST_ENTRY
* rollback
);
1468 void space_list_add2(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, uint64_t address
, uint64_t length
, chunk
* c
, LIST_ENTRY
* rollback
);
1469 void space_list_subtract(chunk
* c
, bool deleting
, uint64_t address
, uint64_t length
, LIST_ENTRY
* rollback
);
1470 void space_list_subtract2(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, uint64_t address
, uint64_t length
, chunk
* c
, LIST_ENTRY
* rollback
);
1471 NTSTATUS
load_stored_free_space_cache(device_extension
* Vcb
, chunk
* c
, bool load_only
, PIRP Irp
);
1474 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
);
1475 NTSTATUS
decrease_extent_refcount_data(device_extension
* Vcb
, uint64_t address
, uint64_t size
, uint64_t root
, uint64_t inode
, uint64_t offset
,
1476 uint32_t refcount
, bool superseded
, PIRP Irp
);
1477 NTSTATUS
decrease_extent_refcount_tree(device_extension
* Vcb
, uint64_t address
, uint64_t size
, uint64_t root
, uint8_t level
, PIRP Irp
);
1478 uint64_t get_extent_refcount(device_extension
* Vcb
, uint64_t address
, uint64_t size
, PIRP Irp
);
1479 bool is_extent_unique(device_extension
* Vcb
, uint64_t address
, uint64_t size
, PIRP Irp
);
1480 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
);
1481 uint64_t get_extent_flags(device_extension
* Vcb
, uint64_t address
, PIRP Irp
);
1482 void update_extent_flags(device_extension
* Vcb
, uint64_t address
, uint64_t flags
, PIRP Irp
);
1483 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
,
1484 int32_t count
, bool no_csum
, bool superseded
, PIRP Irp
);
1485 void add_changed_extent_ref(chunk
* c
, uint64_t address
, uint64_t size
, uint64_t root
, uint64_t objid
, uint64_t offset
, uint32_t count
, bool no_csum
);
1486 uint64_t find_extent_shared_tree_refcount(device_extension
* Vcb
, uint64_t address
, uint64_t parent
, PIRP Irp
);
1487 uint32_t find_extent_shared_data_refcount(device_extension
* Vcb
, uint64_t address
, uint64_t parent
, PIRP Irp
);
1488 NTSTATUS
decrease_extent_refcount(device_extension
* Vcb
, uint64_t address
, uint64_t size
, uint8_t type
, void* data
, KEY
* firstitem
,
1489 uint8_t level
, uint64_t parent
, bool superseded
, PIRP Irp
);
1490 uint64_t get_extent_data_ref_hash2(uint64_t root
, uint64_t objid
, uint64_t offset
);
1492 // in worker-thread.c
1493 NTSTATUS
do_read_job(PIRP Irp
);
1494 NTSTATUS
do_write_job(device_extension
* Vcb
, PIRP Irp
);
1495 bool add_thread_job(device_extension
* Vcb
, PIRP Irp
);
1498 void read_registry(PUNICODE_STRING regpath
, bool refresh
);
1499 NTSTATUS
registry_mark_volume_mounted(BTRFS_UUID
* uuid
);
1500 NTSTATUS
registry_mark_volume_unmounted(BTRFS_UUID
* uuid
);
1501 NTSTATUS
registry_load_volume_options(device_extension
* Vcb
);
1502 void watch_registry(HANDLE regh
);
1505 NTSTATUS
zlib_decompress(uint8_t* inbuf
, uint32_t inlen
, uint8_t* outbuf
, uint32_t outlen
);
1506 NTSTATUS
lzo_decompress(uint8_t* inbuf
, uint32_t inlen
, uint8_t* outbuf
, uint32_t outlen
, uint32_t inpageoff
);
1507 NTSTATUS
zstd_decompress(uint8_t* inbuf
, uint32_t inlen
, uint8_t* outbuf
, uint32_t outlen
);
1508 NTSTATUS
write_compressed_bit(fcb
* fcb
, uint64_t start_data
, uint64_t end_data
, void* data
, bool* compressed
, PIRP Irp
, LIST_ENTRY
* rollback
);
1511 void galois_double(uint8_t* data
, uint32_t len
);
1512 void galois_divpower(uint8_t* data
, uint8_t div
, uint32_t readlen
);
1513 uint8_t gpow2(uint8_t e
);
1514 uint8_t gmul(uint8_t a
, uint8_t b
);
1515 uint8_t gdiv(uint8_t a
, uint8_t b
);
1519 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL
)
1520 _Function_class_(DRIVER_DISPATCH
)
1521 NTSTATUS __stdcall
drv_device_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1525 _Function_class_(KSTART_ROUTINE
)
1526 void __stdcall
calc_thread(void* context
);
1528 NTSTATUS
add_calc_job(device_extension
* Vcb
, uint8_t* data
, uint32_t sectors
, uint32_t* csum
, calc_job
** pcj
);
1529 void free_calc_job(calc_job
* cj
);
1532 NTSTATUS
start_balance(device_extension
* Vcb
, void* data
, ULONG length
, KPROCESSOR_MODE processor_mode
);
1533 NTSTATUS
query_balance(device_extension
* Vcb
, void* data
, ULONG length
);
1534 NTSTATUS
pause_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1535 NTSTATUS
resume_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1536 NTSTATUS
stop_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1537 NTSTATUS
look_for_balance_item(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
);
1538 NTSTATUS
remove_device(device_extension
* Vcb
, void* data
, ULONG length
, KPROCESSOR_MODE processor_mode
);
1540 _Function_class_(KSTART_ROUTINE
)
1541 void __stdcall
balance_thread(void* context
);
1544 NTSTATUS
vol_create(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1545 NTSTATUS
vol_close(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1546 NTSTATUS
vol_read(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1547 NTSTATUS
vol_write(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1548 NTSTATUS
vol_query_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1549 NTSTATUS
vol_set_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1550 NTSTATUS
vol_query_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1551 NTSTATUS
vol_set_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1552 NTSTATUS
vol_flush_buffers(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1553 NTSTATUS
vol_query_volume_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1554 NTSTATUS
vol_set_volume_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1555 NTSTATUS
vol_cleanup(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1556 NTSTATUS
vol_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1557 NTSTATUS
vol_file_system_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1558 NTSTATUS
vol_lock_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1559 NTSTATUS
vol_device_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1560 NTSTATUS
vol_shutdown(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1561 NTSTATUS
vol_query_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1562 NTSTATUS
vol_set_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1563 void add_volume_device(superblock
* sb
, PUNICODE_STRING devpath
, uint64_t length
, ULONG disk_num
, ULONG part_num
);
1564 NTSTATUS
mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr
, PUNICODE_STRING devpath
);
1566 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1567 NTSTATUS __stdcall
pnp_removal(PVOID NotificationStructure
, PVOID Context
);
1569 void free_vol(volume_device_extension
* vde
);
1572 NTSTATUS
start_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1573 NTSTATUS
query_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
, void* data
, ULONG length
);
1574 NTSTATUS
pause_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1575 NTSTATUS
resume_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1576 NTSTATUS
stop_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1579 NTSTATUS
send_subvol(device_extension
* Vcb
, void* data
, ULONG datalen
, PFILE_OBJECT FileObject
, PIRP Irp
);
1580 NTSTATUS
read_send_buffer(device_extension
* Vcb
, PFILE_OBJECT FileObject
, void* data
, ULONG datalen
, ULONG_PTR
* retlen
, KPROCESSOR_MODE processor_mode
);
1583 NTSTATUS __stdcall
compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength
, IN PREPARSE_DATA_BUFFER ReparseBuffer
);
1586 void __stdcall
check_system_root(PDRIVER_OBJECT DriverObject
, PVOID Context
, ULONG Count
);
1588 // based on function in sys/sysmacros.h
1589 #define makedev(major, minor) (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((uint64_t)((minor) & ~0xFF)) << 12) | (((uint64_t)((major) & ~0xFFF)) << 32))
1595 FSRTL_COMMON_FCB_HEADER DUMMYSTRUCTNAME
;
1596 PFAST_MUTEX FastMutex
;
1597 LIST_ENTRY FilterContexts
;
1598 EX_PUSH_LOCK PushLock
;
1599 PVOID
* FileContextSupportPointer
;
1602 PVOID ReservedForRemote
;
1604 PVOID ReservedContext
;
1605 } FSRTL_ADVANCED_FCB_HEADER_NEW
;
1607 #define FSRTL_FCB_HEADER_V2 2
1610 #define FSRTL_ADVANCED_FCB_HEADER_NEW FSRTL_ADVANCED_FCB_HEADER
1614 FSRTL_COMMON_FCB_HEADER DUMMYSTRUCTNAME
;
1615 PFAST_MUTEX FastMutex
;
1616 LIST_ENTRY FilterContexts
;
1617 EX_PUSH_LOCK PushLock
;
1618 PVOID
* FileContextSupportPointer
;
1621 PVOID ReservedForRemote
;
1623 PVOID ReservedContext
;
1624 } FSRTL_ADVANCED_FCB_HEADER_NEW
;
1626 #define FSRTL_FCB_HEADER_V2 2
1629 static __inline POPLOCK
fcb_oplock(fcb
* fcb
) {
1630 if (fcb
->Header
.Version
>= FSRTL_FCB_HEADER_V2
)
1631 return &((FSRTL_ADVANCED_FCB_HEADER_NEW
*)&fcb
->Header
)->Oplock
;
1633 return &fcb
->oplock
;
1636 static __inline FAST_IO_POSSIBLE
fast_io_possible(fcb
* fcb
) {
1637 if (!FsRtlOplockIsFastIoPossible(fcb_oplock(fcb
)))
1638 return FastIoIsNotPossible
;
1640 if (!FsRtlAreThereCurrentFileLocks(&fcb
->lock
) && !fcb
->Vcb
->readonly
)
1641 return FastIoIsPossible
;
1643 return FastIoIsQuestionable
;
1646 static __inline
void print_open_trees(device_extension
* Vcb
) {
1647 LIST_ENTRY
* le
= Vcb
->trees
.Flink
;
1648 while (le
!= &Vcb
->trees
) {
1649 tree
* t
= CONTAINING_RECORD(le
, tree
, list_entry
);
1650 tree_data
* td
= CONTAINING_RECORD(t
->itemlist
.Flink
, tree_data
, list_entry
);
1651 ERR("tree %p: root %I64x, level %u, first key (%I64x,%x,%I64x)\n",
1652 t
, t
->root
->id
, t
->header
.level
, td
->key
.obj_id
, td
->key
.obj_type
, td
->key
.offset
);
1658 static __inline
bool write_fcb_compressed(fcb
* fcb
) {
1659 // make sure we don't accidentally write the cache inodes or pagefile compressed
1660 if (fcb
->subvol
->id
== BTRFS_ROOT_ROOT
|| fcb
->Header
.Flags2
& FSRTL_FLAG2_IS_PAGING_FILE
)
1663 if (fcb
->Vcb
->options
.compress_force
)
1666 if (fcb
->inode_item
.flags
& BTRFS_INODE_NOCOMPRESS
)
1669 if (fcb
->inode_item
.flags
& BTRFS_INODE_COMPRESS
|| fcb
->Vcb
->options
.compress
)
1675 static __inline
void do_xor(uint8_t* buf1
, uint8_t* buf2
, uint32_t len
) {
1682 if (have_sse2
&& ((uintptr_t)buf1
& 0xf) == 0 && ((uintptr_t)buf2
& 0xf) == 0) {
1684 x1
= _mm_load_si128((__m128i
*)buf1
);
1685 x2
= _mm_load_si128((__m128i
*)buf2
);
1686 x1
= _mm_xor_si128(x1
, x2
);
1687 _mm_store_si128((__m128i
*)buf1
, x1
);
1696 for (j
= 0; j
< len
; j
++) {
1703 #ifdef DEBUG_FCB_REFCOUNTS
1704 #ifdef DEBUG_LONG_MESSAGES
1705 #define increase_fileref_refcount(fileref) {\
1706 LONG rc = InterlockedIncrement(&fileref->refcount);\
1707 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1710 #define increase_fileref_refcount(fileref) {\
1711 LONG rc = InterlockedIncrement(&fileref->refcount);\
1712 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1716 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount)
1720 #define int3 __debugbreak()
1722 #define int3 asm("int3;")
1725 #define hex_digit(c) ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')
1727 // FIXME - find a way to catch unfreed trees again
1730 #define __S_IFMT 0170000 /* These bits determine file type. */
1731 #define __S_IFDIR 0040000 /* Directory. */
1732 #define __S_IFCHR 0020000 /* Character device. */
1733 #define __S_IFBLK 0060000 /* Block device. */
1734 #define __S_IFREG 0100000 /* Regular file. */
1735 #define __S_IFIFO 0010000 /* FIFO. */
1736 #define __S_IFLNK 0120000 /* Symbolic link. */
1737 #define __S_IFSOCK 0140000 /* Socket. */
1738 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
1741 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
1745 #define S_IRUSR 0000400
1749 #define S_IWUSR 0000200
1753 #define S_IXUSR 0000100
1757 #define S_IFDIR __S_IFDIR
1758 #define S_IFREG __S_IFREG
1759 #endif /* __REACTOS__ */
1762 #define S_IRGRP (S_IRUSR >> 3)
1766 #define S_IWGRP (S_IWUSR >> 3)
1770 #define S_IXGRP (S_IXUSR >> 3)
1774 #define S_IROTH (S_IRGRP >> 3)
1778 #define S_IWOTH (S_IWGRP >> 3)
1782 #define S_IXOTH (S_IXGRP >> 3)
1786 #define S_ISUID 0004000
1790 #define S_ISGID 0002000
1794 #define S_ISVTX 0001000
1797 // based on functions in sys/sysmacros.h
1798 #define major(rdev) ((((rdev) >> 8) & 0xFFF) | ((uint32_t)((rdev) >> 32) & ~0xFFF))
1799 #define minor(rdev) (((rdev) & 0xFF) | ((uint32_t)((rdev) >> 12) & ~0xFF))
1801 static __inline
uint64_t fcb_alloc_size(fcb
* fcb
) {
1802 if (S_ISDIR(fcb
->inode_item
.st_mode
))
1804 else if (fcb
->atts
& FILE_ATTRIBUTE_SPARSE_FILE
)
1805 return fcb
->inode_item
.st_blocks
;
1807 return sector_align(fcb
->inode_item
.st_size
, fcb
->Vcb
->superblock
.sector_size
);
1810 typedef BOOLEAN (__stdcall
*tPsIsDiskCountersEnabled
)();
1812 typedef VOID (__stdcall
*tPsUpdateDiskCounters
)(PEPROCESS Process
, ULONG64 BytesRead
, ULONG64 BytesWritten
,
1813 ULONG ReadOperationCount
, ULONG WriteOperationCount
, ULONG FlushOperationCount
);
1815 typedef BOOLEAN (__stdcall
*tCcCopyWriteEx
)(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
,
1816 PVOID Buffer
, PETHREAD IoIssuerThread
);
1818 typedef BOOLEAN (__stdcall
*tCcCopyReadEx
)(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
,
1819 PVOID Buffer
, PIO_STATUS_BLOCK IoStatus
, PETHREAD IoIssuerThread
);
1821 #ifndef CC_ENABLE_DISK_IO_ACCOUNTING
1822 #define CC_ENABLE_DISK_IO_ACCOUNTING 0x00000010
1825 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
1826 typedef struct _ECP_LIST ECP_LIST
;
1827 typedef struct _ECP_LIST
*PECP_LIST
;
1830 typedef VOID (__stdcall
*tCcSetAdditionalCacheAttributesEx
)(PFILE_OBJECT FileObject
, ULONG Flags
);
1832 typedef VOID (__stdcall
*tFsRtlUpdateDiskCounters
)(ULONG64 BytesRead
, ULONG64 BytesWritten
);
1834 typedef NTSTATUS (__stdcall
*tIoUnregisterPlugPlayNotificationEx
)(PVOID NotificationEntry
);
1836 typedef NTSTATUS (__stdcall
*tFsRtlGetEcpListFromIrp
)(PIRP Irp
, PECP_LIST
* EcpList
);
1838 typedef NTSTATUS (__stdcall
*tFsRtlGetNextExtraCreateParameter
)(PECP_LIST EcpList
, PVOID CurrentEcpContext
, LPGUID NextEcpType
,
1839 PVOID
* NextEcpContext
, ULONG
* NextEcpContextSize
);
1841 typedef NTSTATUS (__stdcall
*tFsRtlValidateReparsePointBuffer
)(ULONG BufferLength
, PREPARSE_DATA_BUFFER ReparseBuffer
);
1843 typedef BOOLEAN (__stdcall
*tFsRtlCheckLockForOplockRequest
)(PFILE_LOCK FileLock
, PLARGE_INTEGER AllocationSize
);
1845 typedef BOOLEAN (__stdcall
*tFsRtlAreThereCurrentOrInProgressFileLocks
)(PFILE_LOCK FileLock
);
1849 PEPROCESS __stdcall
PsGetThreadProcess(_In_ PETHREAD Thread
); // not in mingw
1852 // not in DDK headers - taken from winternl.h
1853 typedef struct _LDR_DATA_TABLE_ENTRY
{
1855 LIST_ENTRY InMemoryOrderLinks
;
1859 UNICODE_STRING FullDllName
;
1866 ULONG TimeDateStamp
;
1867 } LDR_DATA_TABLE_ENTRY
,*PLDR_DATA_TABLE_ENTRY
;
1869 typedef struct _PEB_LDR_DATA
{
1872 LIST_ENTRY InMemoryOrderModuleList
;
1873 } PEB_LDR_DATA
,*PPEB_LDR_DATA
;
1875 typedef struct _RTL_USER_PROCESS_PARAMETERS
{
1877 PVOID Reserved2
[10];
1878 UNICODE_STRING ImagePathName
;
1879 UNICODE_STRING CommandLine
;
1880 } RTL_USER_PROCESS_PARAMETERS
,*PRTL_USER_PROCESS_PARAMETERS
;
1882 typedef VOID (NTAPI
*PPS_POST_PROCESS_INIT_ROUTINE
)(VOID
);
1884 typedef struct _PEB
{
1890 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1891 BYTE Reserved4
[104];
1892 PVOID Reserved5
[52];
1893 PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine
;
1894 BYTE Reserved6
[128];
1902 NTSTATUS NTAPI
ZwQueryInformationProcess(
1903 IN HANDLE ProcessHandle
,
1904 IN PROCESSINFOCLASS ProcessInformationClass
,
1905 OUT PVOID ProcessInformation
,
1906 IN ULONG ProcessInformationLength
,
1907 OUT PULONG ReturnLength OPTIONAL