22ae32e6a897eda44f04005fbc018a95a429e0a8
[reactos.git] / reactos / drivers / filesystems / btrfs / btrfs_drv.h
1 /* Copyright (c) Mark Harmstone 2016
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifndef BTRFS_DRV_H_DEFINED
19 #define BTRFS_DRV_H_DEFINED
20
21 #ifndef __REACTOS__
22 #undef _WIN32_WINNT
23 #undef NTDDI_VERSION
24
25 #define _WIN32_WINNT 0x0600
26 #define NTDDI_VERSION 0x06010000 // Win 7
27 #define _CRT_SECURE_NO_WARNINGS
28 #endif /* __REACTOS__ */
29
30 #include <ntifs.h>
31 #include <ntddk.h>
32 #ifdef __REACTOS__
33 #include <ntdddisk.h>
34 #endif /* __REACTOS__ */
35 #include <mountmgr.h>
36 #ifdef __REACTOS__
37 #include <rtlfuncs.h>
38 #include <iotypes.h>
39 #include <pseh/pseh2.h>
40 #endif /* __REACTOS__ */
41 //#include <windows.h>
42 #include <windef.h>
43 #include <wdm.h>
44 #include <stdio.h>
45 #include <stdarg.h>
46 #include <stddef.h>
47 #include <emmintrin.h>
48 #include "btrfs.h"
49
50 #ifdef _DEBUG
51 // #define DEBUG_FCB_REFCOUNTS
52 // #define DEBUG_LONG_MESSAGES
53 // #define DEBUG_FLUSH_TIMES
54 // #define DEBUG_STATS
55 #define DEBUG_PARANOID
56 #endif
57
58 #define BTRFS_NODE_TYPE_CCB 0x2295
59 #define BTRFS_NODE_TYPE_FCB 0x2296
60
61 #define ALLOC_TAG 0x7442484D //'MHBt'
62 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
63
64 #define STDCALL __stdcall
65
66 #define UID_NOBODY 65534
67 #define GID_NOBODY 65534
68
69 #define EA_NTACL "security.NTACL"
70 #define EA_NTACL_HASH 0x45922146
71
72 #define EA_DOSATTRIB "user.DOSATTRIB"
73 #define EA_DOSATTRIB_HASH 0x914f9939
74
75 #define EA_REPARSE "system.reparse"
76 #define EA_REPARSE_HASH 0x786f6167
77
78 #define EA_EA "user.EA"
79 #define EA_EA_HASH 0x8270dd43
80
81 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
82 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
83
84 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
85
86 #define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
87
88 #ifdef _MSC_VER
89 #define try __try
90 #define except __except
91 #define finally __finally
92 #else
93 #define try if (1)
94 #define except(x) if (0 && (x))
95 #define finally if (1)
96 #endif
97
98 // #pragma pack(push, 1)
99
100 struct _device_extension;
101
102 typedef struct {
103 BTRFS_UUID fsuuid;
104 BTRFS_UUID devuuid;
105 UINT64 devnum;
106 UNICODE_STRING devpath;
107 UINT64 length;
108 UINT64 gen1, gen2;
109 BOOL seeding;
110 BOOL processed;
111 LIST_ENTRY list_entry;
112 } volume;
113
114 typedef struct _fcb_nonpaged {
115 FAST_MUTEX HeaderMutex;
116 SECTION_OBJECT_POINTERS segment_object;
117 ERESOURCE resource;
118 ERESOURCE paging_resource;
119 ERESOURCE index_lock;
120 } fcb_nonpaged;
121
122 struct _root;
123
124 typedef struct {
125 UINT64 offset;
126 EXTENT_DATA* data;
127 ULONG datalen;
128 BOOL unique;
129 BOOL ignore;
130
131 LIST_ENTRY list_entry;
132 } extent;
133
134 typedef struct {
135 UINT32 hash;
136 KEY key;
137 UINT8 type;
138 UINT64 index;
139 ANSI_STRING utf8;
140 UNICODE_STRING filepart_uc;
141
142 LIST_ENTRY list_entry;
143 } index_entry;
144
145 typedef struct {
146 UINT64 parent;
147 UINT64 index;
148 UNICODE_STRING name;
149 ANSI_STRING utf8;
150 LIST_ENTRY list_entry;
151 } hardlink;
152
153 struct _file_ref;
154
155 typedef struct _fcb {
156 FSRTL_ADVANCED_FCB_HEADER Header;
157 struct _fcb_nonpaged* nonpaged;
158 LONG refcount;
159 struct _device_extension* Vcb;
160 struct _root* subvol;
161 UINT64 inode;
162 UINT8 type;
163 INODE_ITEM inode_item;
164 SECURITY_DESCRIPTOR* sd;
165 FILE_LOCK lock;
166 BOOL deleted;
167 PKTHREAD lazy_writer_thread;
168 ULONG atts;
169 SHARE_ACCESS share_access;
170 WCHAR* debug_desc;
171 LIST_ENTRY extents;
172 UINT64 last_dir_index;
173 ANSI_STRING reparse_xattr;
174 ANSI_STRING ea_xattr;
175 ULONG ealen;
176 LIST_ENTRY hardlinks;
177 struct _file_ref* fileref;
178 BOOL inode_item_changed;
179
180 BOOL index_loaded;
181 LIST_ENTRY index_list;
182
183 BOOL dirty;
184 BOOL sd_dirty;
185 BOOL atts_changed, atts_deleted;
186 BOOL extents_changed;
187 BOOL reparse_xattr_changed;
188 BOOL ea_changed;
189 BOOL created;
190
191 BOOL ads;
192 UINT32 adshash;
193 ULONG adsmaxlen;
194 ANSI_STRING adsxattr;
195 ANSI_STRING adsdata;
196
197 LIST_ENTRY list_entry;
198 LIST_ENTRY list_entry_all;
199 } fcb;
200
201 typedef struct {
202 fcb* fcb;
203 LIST_ENTRY list_entry;
204 } dirty_fcb;
205
206 typedef struct {
207 ERESOURCE children_lock;
208 } file_ref_nonpaged;
209
210 typedef struct _file_ref {
211 fcb* fcb;
212 UNICODE_STRING filepart;
213 UNICODE_STRING filepart_uc;
214 ANSI_STRING utf8;
215 ANSI_STRING oldutf8;
216 UINT64 index;
217 BOOL delete_on_close;
218 BOOL deleted;
219 BOOL created;
220 file_ref_nonpaged* nonpaged;
221 LIST_ENTRY children;
222 LONG refcount;
223 LONG open_count;
224 struct _file_ref* parent;
225 WCHAR* debug_desc;
226
227 BOOL dirty;
228
229 LIST_ENTRY list_entry;
230 } file_ref;
231
232 typedef struct {
233 file_ref* fileref;
234 LIST_ENTRY list_entry;
235 } dirty_fileref;
236
237 typedef struct _ccb {
238 USHORT NodeType;
239 CSHORT NodeSize;
240 ULONG disposition;
241 ULONG options;
242 UINT64 query_dir_offset;
243 // char* query_string;
244 UNICODE_STRING query_string;
245 BOOL has_wildcard;
246 BOOL specific_file;
247 ACCESS_MASK access;
248 file_ref* fileref;
249 UNICODE_STRING filename;
250 ULONG ea_index;
251 BOOL case_sensitive;
252 BOOL user_set_creation_time;
253 BOOL user_set_access_time;
254 BOOL user_set_write_time;
255 BOOL user_set_change_time;
256 } ccb;
257
258 // typedef struct _log_to_phys {
259 // UINT64 address;
260 // UINT64 size;
261 // UINT64 physaddr;
262 // UINT32 sector_size;
263 // struct _log_to_phys* next;
264 // } log_to_phys;
265
266 struct _device_extension;
267
268 // enum tree_holder_status {
269 // tree_holder_unloaded,
270 // tree_holder_loading,
271 // tree_holder_loaded,
272 // tree_holder_unloading
273 // };
274
275 // typedef struct {
276 // enum tree_holder_status status;
277 // KSPIN_LOCK spin_lock;
278 // ERESOURCE lock;
279 // } tree_holder_nonpaged;
280
281 typedef struct {
282 UINT64 address;
283 UINT64 generation;
284 struct _tree* tree;
285 // tree_holder_nonpaged* nonpaged;
286 } tree_holder;
287
288 typedef struct _tree_data {
289 KEY key;
290 LIST_ENTRY list_entry;
291 BOOL ignore;
292 BOOL inserted;
293
294 union {
295 tree_holder treeholder;
296
297 struct {
298 UINT32 size;
299 UINT8* data;
300 };
301 };
302 } tree_data;
303
304 // typedef struct _tree_nonpaged {
305 // ERESOURCE load_tree_lock;
306 // } tree_nonpaged;
307
308 typedef struct _tree {
309 // UINT64 address;
310 // UINT8 level;
311 tree_header header;
312 BOOL has_address;
313 UINT32 size;
314 struct _device_extension* Vcb;
315 struct _tree* parent;
316 tree_data* paritem;
317 struct _root* root;
318 // tree_nonpaged* nonpaged;
319 LIST_ENTRY itemlist;
320 LIST_ENTRY list_entry;
321 UINT64 new_address;
322 BOOL has_new_address;
323 BOOL updated_extents;
324 UINT64 flags;
325 BOOL write;
326 } tree;
327
328 typedef struct {
329 // KSPIN_LOCK load_tree_lock;
330 ERESOURCE load_tree_lock;
331 } root_nonpaged;
332
333 typedef struct _root {
334 UINT64 id;
335 LONGLONG lastinode; // signed so we can use InterlockedIncrement64
336 tree_holder treeholder;
337 root_nonpaged* nonpaged;
338 ROOT_ITEM root_item;
339 UNICODE_STRING path;
340 LIST_ENTRY fcbs;
341 LIST_ENTRY list_entry;
342 } root;
343
344 enum batch_operation {
345 Batch_Insert,
346 Batch_SetXattr,
347 Batch_DirItem,
348 Batch_InodeRef,
349 Batch_InodeExtRef,
350 };
351
352 typedef struct {
353 KEY key;
354 void* data;
355 UINT16 datalen;
356 enum batch_operation operation;
357 LIST_ENTRY list_entry;
358 } batch_item;
359
360 typedef struct {
361 root* r;
362 LIST_ENTRY items;
363 LIST_ENTRY list_entry;
364 } batch_root;
365
366 typedef struct {
367 tree* tree;
368 tree_data* item;
369 } traverse_ptr;
370
371 typedef struct _root_cache {
372 root* root;
373 struct _root_cache* next;
374 } root_cache;
375
376 typedef struct {
377 UINT64 address;
378 UINT64 size;
379 LIST_ENTRY list_entry;
380 LIST_ENTRY list_entry_size;
381 } space;
382
383 typedef struct {
384 PDEVICE_OBJECT devobj;
385 DEV_ITEM devitem;
386 BOOL removable;
387 BOOL seeding;
388 BOOL readonly;
389 BOOL ssd;
390 BOOL trim;
391 ULONG change_count;
392 UINT64 length;
393 LIST_ENTRY space;
394 } device;
395
396 typedef struct {
397 UINT64 start;
398 UINT64 length;
399 PETHREAD thread;
400 LIST_ENTRY list_entry;
401 } range_lock;
402
403 typedef struct {
404 CHUNK_ITEM* chunk_item;
405 UINT32 size;
406 UINT64 offset;
407 UINT64 used;
408 UINT32 oldused;
409 device** devices;
410 fcb* cache;
411 LIST_ENTRY space;
412 LIST_ENTRY space_size;
413 LIST_ENTRY deleting;
414 LIST_ENTRY changed_extents;
415 LIST_ENTRY range_locks;
416 KSPIN_LOCK range_locks_spinlock;
417 KEVENT range_locks_event;
418 ERESOURCE lock;
419 ERESOURCE changed_extents_lock;
420 BOOL created;
421 BOOL readonly;
422
423 LIST_ENTRY list_entry;
424 LIST_ENTRY list_entry_changed;
425 } chunk;
426
427 typedef struct {
428 UINT64 address;
429 UINT64 size;
430 UINT64 old_size;
431 UINT64 count;
432 UINT64 old_count;
433 BOOL no_csum;
434 BOOL superseded;
435 LIST_ENTRY refs;
436 LIST_ENTRY old_refs;
437 LIST_ENTRY list_entry;
438 } changed_extent;
439
440 typedef struct {
441 UINT8 type;
442
443 union {
444 EXTENT_DATA_REF edr;
445 SHARED_DATA_REF sdr;
446 };
447
448 LIST_ENTRY list_entry;
449 } changed_extent_ref;
450
451 typedef struct {
452 KEY key;
453 void* data;
454 USHORT size;
455 LIST_ENTRY list_entry;
456 } sys_chunk;
457
458 typedef struct {
459 BOOL ignore;
460 BOOL compress;
461 BOOL compress_force;
462 UINT8 compress_type;
463 BOOL readonly;
464 UINT32 zlib_level;
465 UINT32 flush_interval;
466 UINT32 max_inline;
467 UINT64 subvol_id;
468 UINT32 raid5_recalculation;
469 UINT32 raid6_recalculation;
470 } mount_options;
471
472 #define VCB_TYPE_VOLUME 1
473 #define VCB_TYPE_PARTITION0 2
474
475 #ifdef DEBUG_STATS
476 typedef struct {
477 UINT64 num_reads;
478 UINT64 data_read;
479 UINT64 read_total_time;
480 UINT64 read_csum_time;
481 UINT64 read_disk_time;
482 } debug_stats;
483 #endif
484
485 typedef struct _device_extension {
486 UINT32 type;
487 mount_options options;
488 PVPB Vpb;
489 device* devices;
490 #ifdef DEBUG_STATS
491 debug_stats stats;
492 #endif
493 UINT64 devices_loaded;
494 // DISK_GEOMETRY geometry;
495 superblock superblock;
496 // WCHAR label[MAX_LABEL_SIZE];
497 BOOL readonly;
498 BOOL removing;
499 BOOL locked;
500 BOOL disallow_dismount;
501 BOOL trim;
502 PFILE_OBJECT locked_fileobj;
503 fcb* volume_fcb;
504 file_ref* root_fileref;
505 LONG open_files;
506 ERESOURCE DirResource;
507 KSPIN_LOCK FcbListLock;
508 ERESOURCE fcb_lock;
509 ERESOURCE load_lock;
510 ERESOURCE tree_lock;
511 PNOTIFY_SYNC NotifySync;
512 LIST_ENTRY DirNotifyList;
513 LONG open_trees;
514 BOOL need_write;
515 // ERESOURCE LogToPhysLock;
516 // UINT64 chunk_root_phys_addr;
517 UINT64 root_tree_phys_addr;
518 UINT64 data_flags;
519 // log_to_phys* log_to_phys;
520 LIST_ENTRY roots;
521 LIST_ENTRY drop_roots;
522 root* chunk_root;
523 root* root_root;
524 root* extent_root;
525 root* checksum_root;
526 root* dev_root;
527 root* uuid_root;
528 root* data_reloc_root;
529 BOOL log_to_phys_loaded;
530 LIST_ENTRY sys_chunks;
531 LIST_ENTRY chunks;
532 LIST_ENTRY chunks_changed;
533 LIST_ENTRY trees;
534 LIST_ENTRY all_fcbs;
535 LIST_ENTRY dirty_fcbs;
536 KSPIN_LOCK dirty_fcbs_lock;
537 LIST_ENTRY dirty_filerefs;
538 KSPIN_LOCK dirty_filerefs_lock;
539 ERESOURCE checksum_lock;
540 ERESOURCE chunk_lock;
541 LIST_ENTRY sector_checksums;
542 HANDLE flush_thread_handle;
543 KTIMER flush_thread_timer;
544 KEVENT flush_thread_finished;
545 PFILE_OBJECT root_file;
546 PAGED_LOOKASIDE_LIST tree_data_lookaside;
547 PAGED_LOOKASIDE_LIST traverse_ptr_lookaside;
548 PAGED_LOOKASIDE_LIST rollback_item_lookaside;
549 PAGED_LOOKASIDE_LIST batch_item_lookaside;
550 NPAGED_LOOKASIDE_LIST range_lock_lookaside;
551 LIST_ENTRY list_entry;
552 } device_extension;
553
554 typedef struct {
555 UINT32 type;
556 PDEVICE_OBJECT devobj;
557 BTRFS_UUID uuid;
558 UNICODE_STRING name;
559 } part0_device_extension;
560
561 typedef struct {
562 LIST_ENTRY listentry;
563 PSID sid;
564 UINT32 uid;
565 } uid_map;
566
567 typedef struct {
568 LIST_ENTRY list_entry;
569 UINT64 key;
570 } ordered_list;
571
572 typedef struct {
573 ordered_list ol;
574 ULONG length;
575 UINT32* checksums;
576 BOOL deleted;
577 } changed_sector;
578
579 enum write_data_status {
580 WriteDataStatus_Pending,
581 WriteDataStatus_Success,
582 WriteDataStatus_Error,
583 WriteDataStatus_Cancelling,
584 WriteDataStatus_Cancelled,
585 WriteDataStatus_Ignore
586 };
587
588 struct _write_data_context;
589
590 typedef struct {
591 struct _write_data_context* context;
592 UINT8* buf;
593 BOOL need_free;
594 device* device;
595 PIRP Irp;
596 IO_STATUS_BLOCK iosb;
597 enum write_data_status status;
598 LIST_ENTRY list_entry;
599 } write_data_stripe;
600
601 typedef struct _write_data_context {
602 KEVENT Event;
603 LIST_ENTRY stripes;
604 LONG stripes_left;
605 BOOL tree;
606 } write_data_context;
607
608 // #pragma pack(pop)
609
610 static __inline void* map_user_buffer(PIRP Irp) {
611 if (!Irp->MdlAddress) {
612 return Irp->UserBuffer;
613 } else {
614 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
615 }
616 }
617
618 static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
619 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
620 }
621
622 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
623 ULONGLONG l = t.QuadPart - 116444736000000000;
624
625 out->seconds = l / 10000000;
626 out->nanoseconds = (l % 10000000) * 100;
627 }
628
629 static __inline void insert_into_ordered_list(LIST_ENTRY* list, ordered_list* ins) {
630 LIST_ENTRY* le = list->Flink;
631 ordered_list* ol;
632
633 while (le != list) {
634 ol = (ordered_list*)le;
635
636 if (ol->key > ins->key) {
637 le->Blink->Flink = &ins->list_entry;
638 ins->list_entry.Blink = le->Blink;
639 le->Blink = &ins->list_entry;
640 ins->list_entry.Flink = le;
641 return;
642 }
643
644 le = le->Flink;
645 }
646
647 InsertTailList(list, &ins->list_entry);
648 }
649
650 static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 num_stripes, UINT64* stripeoff, UINT16* stripe) {
651 UINT64 initoff, startoff;
652
653 startoff = off % (num_stripes * stripe_length);
654 initoff = (off / (num_stripes * stripe_length)) * stripe_length;
655
656 *stripe = (UINT16)(startoff / stripe_length);
657 *stripeoff = initoff + startoff - (*stripe * stripe_length);
658 }
659
660 /* We only have 64 bits for a file ID, which isn't technically enough to be
661 * unique on Btrfs. We fudge it by having three bytes for the subvol and
662 * five for the inode, which should be good enough.
663 * Inodes are also 64 bits on Linux, but the Linux driver seems to get round
664 * this by tricking it into thinking subvols are separate volumes. */
665 #ifdef __REACTOS__
666 static __inline UINT64 make_file_id(root* r, UINT64 inode) {
667 #else
668 static UINT64 __inline make_file_id(root* r, UINT64 inode) {
669 #endif
670 return (r->id << 40) | (inode & 0xffffffffff);
671 }
672
673 #define keycmp(key1, key2)\
674 ((key1.obj_id < key2.obj_id) ? -1 :\
675 ((key1.obj_id > key2.obj_id) ? 1 :\
676 ((key1.obj_type < key2.obj_type) ? -1 :\
677 ((key1.obj_type > key2.obj_type) ? 1 :\
678 ((key1.offset < key2.offset) ? -1 :\
679 ((key1.offset > key2.offset) ? 1 :\
680 0))))))
681
682 // in btrfs.c
683 device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
684 UINT64 sector_align( UINT64 NumberToBeAligned, UINT64 Alignment );
685 ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa, PIRP Irp);
686 BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen, PIRP Irp);
687 void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
688 void _free_fileref(file_ref* fr, const char* func, const char* file, unsigned int line);
689 NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback);
690 NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback);
691 fcb* create_fcb(POOL_TYPE pool_type);
692 file_ref* create_fileref();
693 void protect_superblocks(device_extension* Vcb, chunk* c);
694 BOOL is_top_level(PIRP Irp);
695 NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, PIRP Irp, LIST_ENTRY* rollback);
696 void STDCALL uninit(device_extension* Vcb, BOOL flush);
697 NTSTATUS STDCALL dev_ioctl(PDEVICE_OBJECT DeviceObject, ULONG ControlCode, PVOID InputBuffer,
698 ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, BOOLEAN Override, IO_STATUS_BLOCK* iosb);
699 BOOL is_file_name_valid(PUNICODE_STRING us);
700 void send_notification_fileref(file_ref* fileref, ULONG filter_match, ULONG action);
701 void send_notification_fcb(file_ref* fileref, ULONG filter_match, ULONG action);
702 WCHAR* file_desc(PFILE_OBJECT FileObject);
703 WCHAR* file_desc_fileref(file_ref* fileref);
704 BOOL add_thread_job(device_extension* Vcb, PIRP Irp);
705 NTSTATUS part0_passthrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
706 void mark_fcb_dirty(fcb* fcb);
707 void mark_fileref_dirty(file_ref* fileref);
708 NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, PIRP Irp, LIST_ENTRY* rollback);
709 void chunk_lock_range(device_extension* Vcb, chunk* c, UINT64 start, UINT64 length);
710 void chunk_unlock_range(device_extension* Vcb, chunk* c, UINT64 start, UINT64 length);
711
712 #ifdef _MSC_VER
713 #define funcname __FUNCTION__
714 #else
715 #define funcname __func__
716 #endif
717
718 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
719 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
720 #define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
721
722 extern BOOL have_sse2;
723
724 extern UINT32 mount_compress;
725 extern UINT32 mount_compress_force;
726 extern UINT32 mount_compress_type;
727 extern UINT32 mount_zlib_level;
728 extern UINT32 mount_flush_interval;
729 extern UINT32 mount_max_inline;
730 extern UINT32 mount_raid5_recalculation;
731 extern UINT32 mount_raid6_recalculation;
732
733 #ifdef _DEBUG
734
735 extern BOOL log_started;
736 extern UINT32 debug_log_level;
737
738 #ifdef DEBUG_LONG_MESSAGES
739
740 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
741
742 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
743 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
744 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
745 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
746
747 void STDCALL _debug_message(const char* func, const char* file, unsigned int line, char* s, ...);
748
749 #else
750
751 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
752
753 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
754 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
755 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
756 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
757
758 void STDCALL _debug_message(const char* func, char* s, ...);
759
760 #endif
761
762 #else
763
764 #define TRACE(s, ...)
765 #define WARN(s, ...)
766 #ifndef __REACTOS__
767 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
768 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
769 #else
770 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
771 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
772 #endif
773
774 #endif
775
776 static __inline void increase_chunk_usage(chunk* c, UINT64 delta) {
777 c->used += delta;
778
779 TRACE("increasing size of chunk %llx by %llx\n", c->offset, delta);
780 }
781
782 // in fastio.c
783 void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
784
785 // in crc32c.c
786 UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
787
788 typedef struct {
789 LIST_ENTRY* list;
790 LIST_ENTRY* list_size;
791 UINT64 address;
792 UINT64 length;
793 chunk* chunk;
794 } rollback_space;
795
796 typedef struct {
797 fcb* fcb;
798 extent* ext;
799 } rollback_extent;
800
801 enum rollback_type {
802 ROLLBACK_INSERT_ITEM,
803 ROLLBACK_DELETE_ITEM,
804 ROLLBACK_INSERT_EXTENT,
805 ROLLBACK_DELETE_EXTENT,
806 ROLLBACK_ADD_SPACE,
807 ROLLBACK_SUBTRACT_SPACE
808 };
809
810 typedef struct {
811 enum rollback_type type;
812 void* ptr;
813 LIST_ENTRY list_entry;
814 } rollback_item;
815
816 // in treefuncs.c
817 NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
818 BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
819 BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
820 void STDCALL free_trees(device_extension* Vcb);
821 BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, PIRP Irp, LIST_ENTRY* rollback);
822 void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
823 tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
824 NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, PIRP Irp, const char* func, const char* file, unsigned int line);
825 NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp,
826 const char* func, const char* file, unsigned int line);
827 void clear_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
828 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
829 void free_trees_root(device_extension* Vcb, root* r);
830 void add_rollback(device_extension* Vcb, LIST_ENTRY* rollback, enum rollback_type type, void* ptr);
831 void commit_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp, LIST_ENTRY* rollback);
832 void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist);
833
834 #define find_item(Vcb, r, tp, searchkey, ignore, Irp) _find_item(Vcb, r, tp, searchkey, ignore, Irp, funcname, __FILE__, __LINE__)
835 #define find_next_item(Vcb, tp, next_tp, ignore, Irp) _find_next_item(Vcb, tp, next_tp, ignore, Irp, funcname, __FILE__, __LINE__)
836 #define find_prev_item(Vcb, tp, prev_tp, ignore, Irp) _find_prev_item(Vcb, tp, prev_tp, ignore, Irp, funcname, __FILE__, __LINE__)
837 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
838 #define load_tree(t, addr, r, pt, parent, Irp) _load_tree(t, addr, r, pt, parent, Irp, funcname, __FILE__, __LINE__)
839 #define do_load_tree(Vcb, th, r, t, td, loaded, Irp) _do_load_tree(Vcb, th, r, t, td, loaded, Irp, funcname, __FILE__, __LINE__)
840
841 // in search.c
842 void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes);
843
844 // in cache.c
845 NTSTATUS STDCALL init_cache();
846 void STDCALL free_cache();
847 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
848
849 // in write.c
850 NTSTATUS write_file(device_extension* Vcb, PIRP Irp, BOOL wait, BOOL deferred_write);
851 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache,
852 BOOL wait, BOOL deferred_write, LIST_ENTRY* rollback);
853 NTSTATUS truncate_file(fcb* fcb, UINT64 end, PIRP Irp, LIST_ENTRY* rollback);
854 NTSTATUS extend_file(fcb* fcb, file_ref* fileref, UINT64 end, BOOL prealloc, PIRP Irp, LIST_ENTRY* rollback);
855 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, PIRP Irp, LIST_ENTRY* rollback);
856 void commit_checksum_changes(device_extension* Vcb, LIST_ENTRY* changed_sector_list);
857 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
858 chunk* alloc_chunk(device_extension* Vcb, UINT64 flags);
859 NTSTATUS STDCALL write_data(device_extension* Vcb, UINT64 address, void* data, BOOL need_free, UINT32 length, write_data_context* wtc, PIRP Irp, chunk* c);
860 NTSTATUS STDCALL write_data_complete(device_extension* Vcb, UINT64 address, void* data, UINT32 length, PIRP Irp, chunk* c);
861 void free_write_data_stripes(write_data_context* wtc);
862 NTSTATUS STDCALL drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
863 BOOL insert_extent_chunk(device_extension* Vcb, fcb* fcb, chunk* c, UINT64 start_data, UINT64 length, BOOL prealloc, void* data, LIST_ENTRY* changed_sector_list,
864 PIRP Irp, LIST_ENTRY* rollback, UINT8 compression, UINT64 decoded_size);
865 NTSTATUS insert_extent(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 length, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
866 NTSTATUS do_write_file(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
867 NTSTATUS write_compressed(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
868 BOOL find_address_in_chunk(device_extension* Vcb, chunk* c, UINT64 length, UINT64* address);
869 void get_raid56_lock_range(chunk* c, UINT64 address, UINT64 length, UINT64* lockaddr, UINT64* locklen);
870
871 // in dirctrl.c
872 NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
873 ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts, PIRP Irp);
874
875 // in security.c
876 NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
877 NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
878 void fcb_get_sd(fcb* fcb, struct _fcb* parent, PIRP Irp);
879 // UINT32 STDCALL get_uid();
880 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
881 UINT32 sid_to_uid(PSID sid);
882 void uid_to_sid(UINT32 uid, PSID* sid);
883 NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as);
884
885 // in fileinfo.c
886 NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
887 NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
888 BOOL has_open_children(file_ref* fileref);
889 NTSTATUS STDCALL stream_set_end_of_file_information(device_extension* Vcb, UINT64 end, fcb* fcb, file_ref* fileref, PFILE_OBJECT FileObject, BOOL advance_only, LIST_ENTRY* rollback);
890 NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset);
891 NTSTATUS open_fileref_by_inode(device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
892 NTSTATUS STDCALL drv_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
893 NTSTATUS STDCALL drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
894
895 // in reparse.c
896 NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen);
897 NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
898 NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
899
900 // in create.c
901 NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
902 NTSTATUS STDCALL find_file_in_dir(device_extension* Vcb, PUNICODE_STRING filename, file_ref* fr,
903 root** subvol, UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8, BOOL case_sensitive, PIRP Irp);
904 NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed, ULONG* fn_offset,
905 POOL_TYPE pooltype, BOOL case_sensitive, PIRP Irp);
906 NTSTATUS open_fcb(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
907 NTSTATUS open_fcb_stream(device_extension* Vcb, root* subvol, UINT64 inode, ANSI_STRING* xattr, UINT32 streamhash, fcb* parent, fcb** pfcb, PIRP Irp);
908 void insert_fileref_child(file_ref* parent, file_ref* child, BOOL do_lock);
909 NTSTATUS fcb_get_last_dir_index(fcb* fcb, UINT64* index, PIRP Irp);
910 NTSTATUS verify_vcb(device_extension* Vcb, PIRP Irp);
911
912 // in fsctl.c
913 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
914 void do_unlock_volume(device_extension* Vcb);
915
916 // in flushthread.c
917 void STDCALL flush_thread(void* context);
918 NTSTATUS STDCALL do_write(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
919 NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, PIRP Irp, LIST_ENTRY* rollback);
920 void flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* batchlist, PIRP Irp, LIST_ENTRY* rollback);
921 NTSTATUS STDCALL write_data_phys(PDEVICE_OBJECT device, UINT64 address, void* data, UINT32 length);
922 BOOL is_tree_unique(device_extension* Vcb, tree* t, PIRP Irp);
923
924 // in read.c
925 NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
926 NTSTATUS STDCALL read_data(device_extension* Vcb, UINT64 addr, UINT32 length, UINT32* csum, BOOL is_tree, UINT8* buf, chunk* c, chunk** pc, PIRP Irp);
927 NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr, PIRP Irp);
928 NTSTATUS do_read(PIRP Irp, BOOL wait, ULONG* bytes_read);
929
930 // in pnp.c
931 NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
932
933 // in free-space.c
934 NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp);
935 NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp);
936 NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, PIRP Irp, LIST_ENTRY* rollback);
937 NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
938 NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 offset, UINT64 size);
939 void _space_list_add(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
940 void _space_list_add2(device_extension* Vcb, LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
941 void _space_list_subtract(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
942 void _space_list_subtract2(device_extension* Vcb, LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
943
944 #define space_list_add(Vcb, c, deleting, address, length, rollback) _space_list_add(Vcb, c, deleting, address, length, rollback, funcname)
945 #define space_list_add2(Vcb, list, list_size, address, length, rollback) _space_list_add2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
946 #define space_list_subtract(Vcb, c, deleting, address, length, rollback) _space_list_subtract(Vcb, c, deleting, address, length, rollback, funcname)
947 #define space_list_subtract2(Vcb, list, list_size, address, length, rollback) _space_list_subtract2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
948
949 // in extent-tree.c
950 NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback);
951 NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback);
952 NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT8 level, PIRP Irp, LIST_ENTRY* rollback);
953 void decrease_chunk_usage(chunk* c, UINT64 delta);
954 // NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp, LIST_ENTRY* rollback);
955 UINT64 get_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp);
956 BOOL is_extent_unique(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp);
957 NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem, UINT8 level, PIRP Irp, LIST_ENTRY* rollback);
958 UINT64 get_extent_flags(device_extension* Vcb, UINT64 address, PIRP Irp);
959 void update_extent_flags(device_extension* Vcb, UINT64 address, UINT64 flags, PIRP Irp);
960 NTSTATUS update_changed_extent_ref(device_extension* Vcb, chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset,
961 signed long long count, BOOL no_csum, BOOL superseded, PIRP Irp);
962 void add_changed_extent_ref(chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, UINT32 count, BOOL no_csum);
963 UINT64 find_extent_shared_tree_refcount(device_extension* Vcb, UINT64 address, UINT64 parent, PIRP Irp);
964 UINT64 find_extent_shared_data_refcount(device_extension* Vcb, UINT64 address, UINT64 parent, PIRP Irp);
965 NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem,
966 UINT8 level, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback);
967
968 // in worker-thread.c
969 void do_read_job(PIRP Irp);
970 void do_write_job(device_extension* Vcb, PIRP Irp);
971
972 // in registry.c
973 void STDCALL read_registry(PUNICODE_STRING regpath);
974 NTSTATUS registry_mark_volume_mounted(BTRFS_UUID* uuid);
975 NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID* uuid);
976 NTSTATUS registry_load_volume_options(device_extension* Vcb);
977
978 // in compress.c
979 NTSTATUS decompress(UINT8 type, UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen);
980 NTSTATUS write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
981
982 // in galois.c
983 void galois_double(UINT8* data, UINT32 len);
984 void galois_divpower(UINT8* data, UINT8 div, UINT32 readlen);
985 UINT8 gpow2(UINT8 e);
986 UINT8 gmul(UINT8 a, UINT8 b);
987 UINT8 gdiv(UINT8 a, UINT8 b);
988
989 // in devctrl.c
990 NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
991
992 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
993
994 static __inline void print_open_trees(device_extension* Vcb) {
995 LIST_ENTRY* le = Vcb->trees.Flink;
996 while (le != &Vcb->trees) {
997 tree* t = CONTAINING_RECORD(le, tree, list_entry);
998 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
999 ERR("tree %p: root %llx, level %u, first key (%llx,%x,%llx)\n",
1000 t, t->root->id, t->header.level, td->key.obj_id, td->key.obj_type, td->key.offset);
1001
1002 le = le->Flink;
1003 }
1004 }
1005
1006 static __inline BOOL write_fcb_compressed(fcb* fcb) {
1007 // make sure we don't accidentally write the cache inodes or pagefile compressed
1008 if (fcb->subvol->id == BTRFS_ROOT_ROOT || fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE)
1009 return FALSE;
1010
1011 if (fcb->Vcb->options.compress_force)
1012 return TRUE;
1013
1014 if (fcb->inode_item.flags & BTRFS_INODE_NOCOMPRESS)
1015 return FALSE;
1016
1017 if (fcb->inode_item.flags & BTRFS_INODE_COMPRESS || fcb->Vcb->options.compress)
1018 return TRUE;
1019
1020 return FALSE;
1021 }
1022
1023 static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
1024 UINT32 j;
1025 #ifndef __REACTOS__
1026 __m128i x1, x2;
1027 #endif
1028
1029 #ifndef __REACTOS__
1030 if (have_sse2 && ((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
1031 while (len >= 16) {
1032 x1 = _mm_load_si128((__m128i*)buf1);
1033 x2 = _mm_load_si128((__m128i*)buf2);
1034 x1 = _mm_xor_si128(x1, x2);
1035 _mm_store_si128((__m128i*)buf1, x1);
1036
1037 buf1 += 16;
1038 buf2 += 16;
1039 len -= 16;
1040 }
1041 }
1042 #endif
1043
1044 for (j = 0; j < len; j++) {
1045 *buf1 ^= *buf2;
1046 buf1++;
1047 buf2++;
1048 }
1049 }
1050
1051 #ifdef DEBUG_FCB_REFCOUNTS
1052 #ifdef DEBUG_LONG_MESSAGES
1053 #define increase_fileref_refcount(fileref) {\
1054 LONG rc = InterlockedIncrement(&fileref->refcount);\
1055 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1056 }
1057 #else
1058 #define increase_fileref_refcount(fileref) {\
1059 LONG rc = InterlockedIncrement(&fileref->refcount);\
1060 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1061 }
1062 #endif
1063 #else
1064 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount)
1065 #endif
1066
1067 #ifdef _MSC_VER
1068 // #define int3 __asm { int 3 }
1069 #define int3 __debugbreak()
1070 #else
1071 #define int3 asm("int3;")
1072 #endif
1073
1074 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
1075 // else TRACE("open tree count = %i\n", Vcb->open_trees);
1076
1077 // FIXME - find a way to catch unfreed trees again
1078
1079 // from sys/stat.h
1080 #define __S_IFMT 0170000 /* These bits determine file type. */
1081 #define __S_IFDIR 0040000 /* Directory. */
1082 #define __S_IFCHR 0020000 /* Character device. */
1083 #define __S_IFBLK 0060000 /* Block device. */
1084 #define __S_IFREG 0100000 /* Regular file. */
1085 #define __S_IFIFO 0010000 /* FIFO. */
1086 #define __S_IFLNK 0120000 /* Symbolic link. */
1087 #define __S_IFSOCK 0140000 /* Socket. */
1088 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
1089
1090 #ifndef S_ISDIR
1091 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
1092 #endif
1093
1094 #ifndef S_IRUSR
1095 #define S_IRUSR 0000400
1096 #endif
1097
1098 #ifndef S_IWUSR
1099 #define S_IWUSR 0000200
1100 #endif
1101
1102 #ifndef S_IXUSR
1103 #define S_IXUSR 0000100
1104 #endif
1105
1106 #ifdef __REACTOS__
1107 #define S_IFDIR __S_IFDIR
1108 #define S_IFREG __S_IFREG
1109 #endif /* __REACTOS__ */
1110
1111 #ifndef S_IRGRP
1112 #define S_IRGRP (S_IRUSR >> 3)
1113 #endif
1114
1115 #ifndef S_IWGRP
1116 #define S_IWGRP (S_IWUSR >> 3)
1117 #endif
1118
1119 #ifndef S_IXGRP
1120 #define S_IXGRP (S_IXUSR >> 3)
1121 #endif
1122
1123 #ifndef S_IROTH
1124 #define S_IROTH (S_IRGRP >> 3)
1125 #endif
1126
1127 #ifndef S_IWOTH
1128 #define S_IWOTH (S_IWGRP >> 3)
1129 #endif
1130
1131 #ifndef S_IXOTH
1132 #define S_IXOTH (S_IXGRP >> 3)
1133 #endif
1134
1135 // LXSS programs can be distinguished by the fact they have a NULL PEB.
1136 #ifdef _AMD64_
1137 static __inline BOOL called_from_lxss() {
1138 UINT8* proc = (UINT8*)PsGetCurrentProcess();
1139 ULONG_PTR* peb = (ULONG_PTR*)&proc[0x3f8];
1140
1141 return !*peb;
1142 }
1143 #else
1144 #define called_from_lxss() FALSE
1145 #endif
1146
1147 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
1148 NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
1149 ULONG *utf8_bytes_written,
1150 const WCHAR *uni_src, ULONG uni_bytes);
1151 NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
1152 ULONG *uni_bytes_written,
1153 const CHAR *utf8_src, ULONG utf8_bytes);
1154 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
1155 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
1156 NTSTATUS NTAPI FsRtlRemoveDotsFromPath(PWSTR OriginalString,
1157 USHORT PathLength, USHORT *NewLength);
1158 NTSTATUS NTAPI FsRtlValidateReparsePointBuffer(ULONG BufferLength,
1159 PREPARSE_DATA_BUFFER ReparseBuffer);
1160 ULONG NTAPI KeQueryActiveProcessorCount(PKAFFINITY ActiveProcessors);
1161 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA) */
1162
1163 #endif