[BTRFS]
[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 #endif /* __REACTOS__ */
40 //#include <windows.h>
41 #include <windef.h>
42 #include <wdm.h>
43 #include <stdio.h>
44 #include <stdarg.h>
45 #include <stddef.h>
46 #include "btrfs.h"
47
48 #ifdef _DEBUG
49 // #define DEBUG_TREE_REFCOUNTS
50 // #define DEBUG_FCB_REFCOUNTS
51 // #define DEBUG_LONG_MESSAGES
52 #define DEBUG_PARANOID
53 #endif
54
55 #define BTRFS_NODE_TYPE_CCB 0x2295
56 #define BTRFS_NODE_TYPE_FCB 0x2296
57
58 #define ALLOC_TAG 0x7442484D //'MHBt'
59
60 #define STDCALL __stdcall
61
62 #define UID_NOBODY 65534
63 #define GID_NOBODY 65534
64
65 #define EA_NTACL "security.NTACL"
66 #define EA_NTACL_HASH 0x45922146
67
68 #define EA_DOSATTRIB "user.DOSATTRIB"
69 #define EA_DOSATTRIB_HASH 0x914f9939
70
71 #define READ_AHEAD_GRANULARITY 0x10000 // 64 KB
72
73 #ifdef _MSC_VER
74 #define try __try
75 #define except __except
76 #define finally __finally
77 #else
78 #define try if (1)
79 #define except(x) if (0 && (x))
80 #define finally if (1)
81 #endif
82
83 // #pragma pack(push, 1)
84
85 struct device_extension;
86
87 typedef struct {
88 PDEVICE_OBJECT devobj;
89 BTRFS_UUID fsuuid;
90 BTRFS_UUID devuuid;
91 UINT64 devnum;
92 UNICODE_STRING devpath;
93 BOOL processed;
94 LIST_ENTRY list_entry;
95 } volume;
96
97 typedef struct _fcb_nonpaged {
98 FAST_MUTEX HeaderMutex;
99 SECTION_OBJECT_POINTERS segment_object;
100 ERESOURCE resource;
101 ERESOURCE paging_resource;
102 } fcb_nonpaged;
103
104 struct _root;
105
106 typedef struct _fcb {
107 FSRTL_ADVANCED_FCB_HEADER Header;
108 struct _fcb_nonpaged* nonpaged;
109 LONG refcount;
110 LONG open_count;
111 UNICODE_STRING filepart;
112 ANSI_STRING utf8;
113 struct _device_extension* Vcb;
114 struct _fcb* par;
115 struct _fcb* prev;
116 struct _fcb* next;
117 struct _root* subvol;
118 LIST_ENTRY children;
119 UINT64 inode;
120 UINT8 type;
121 BOOL delete_on_close;
122 INODE_ITEM inode_item;
123 UNICODE_STRING full_filename;
124 ULONG name_offset;
125 SECURITY_DESCRIPTOR* sd;
126 FILE_LOCK lock;
127 BOOL deleted;
128 PKTHREAD lazy_writer_thread;
129 ULONG atts;
130 SHARE_ACCESS share_access;
131
132 BOOL ads;
133 UINT32 adssize;
134 UINT32 adshash;
135 ANSI_STRING adsxattr;
136
137 LIST_ENTRY list_entry;
138 } fcb;
139
140 typedef struct _ccb {
141 USHORT NodeType;
142 CSHORT NodeSize;
143 ULONG disposition;
144 ULONG options;
145 UINT64 query_dir_offset;
146 // char* query_string;
147 UNICODE_STRING query_string;
148 BOOL has_wildcard;
149 BOOL specific_file;
150 } ccb;
151
152 // typedef struct _log_to_phys {
153 // UINT64 address;
154 // UINT64 size;
155 // UINT64 physaddr;
156 // UINT32 sector_size;
157 // struct _log_to_phys* next;
158 // } log_to_phys;
159
160 struct _device_extension;
161
162 // enum tree_holder_status {
163 // tree_holder_unloaded,
164 // tree_holder_loading,
165 // tree_holder_loaded,
166 // tree_holder_unloading
167 // };
168
169 // typedef struct {
170 // enum tree_holder_status status;
171 // KSPIN_LOCK spin_lock;
172 // ERESOURCE lock;
173 // } tree_holder_nonpaged;
174
175 typedef struct {
176 UINT64 address;
177 UINT64 generation;
178 struct _tree* tree;
179 // tree_holder_nonpaged* nonpaged;
180 } tree_holder;
181
182 typedef struct _tree_data {
183 KEY key;
184 LIST_ENTRY list_entry;
185 BOOL ignore;
186 BOOL inserted;
187
188 union {
189 tree_holder treeholder;
190
191 struct {
192 UINT32 size;
193 UINT8* data;
194 };
195 };
196 } tree_data;
197
198 // typedef struct _tree_nonpaged {
199 // ERESOURCE load_tree_lock;
200 // } tree_nonpaged;
201
202 typedef struct _tree {
203 // UINT64 address;
204 // UINT8 level;
205 tree_header header;
206 LONG refcount;
207 BOOL has_address;
208 UINT32 size;
209 struct _device_extension* Vcb;
210 struct _tree* parent;
211 tree_data* paritem;
212 struct _root* root;
213 // tree_nonpaged* nonpaged;
214 LIST_ENTRY itemlist;
215 LIST_ENTRY list_entry;
216 UINT64 new_address;
217 BOOL has_new_address;
218 UINT64 flags;
219 } tree;
220
221 typedef struct {
222 // KSPIN_LOCK load_tree_lock;
223 ERESOURCE load_tree_lock;
224 } root_nonpaged;
225
226 typedef struct _root {
227 UINT64 id;
228 tree_holder treeholder;
229 root_nonpaged* nonpaged;
230 UINT64 lastinode;
231 ROOT_ITEM root_item;
232
233 struct _root* prev;
234 struct _root* next;
235 } root;
236
237 typedef struct {
238 tree* tree;
239 tree_data* item;
240 } traverse_ptr;
241
242 typedef struct _tree_cache {
243 tree* tree;
244 BOOL write;
245 LIST_ENTRY list_entry;
246 } tree_cache;
247
248 typedef struct _root_cache {
249 root* root;
250 struct _root_cache* next;
251 } root_cache;
252
253 #define SPACE_TYPE_FREE 0
254 #define SPACE_TYPE_USED 1
255 #define SPACE_TYPE_DELETING 2
256 #define SPACE_TYPE_WRITING 3
257
258 typedef struct {
259 UINT64 offset;
260 UINT64 size;
261 UINT8 type;
262 LIST_ENTRY list_entry;
263 } space;
264
265 typedef struct {
266 UINT64 address;
267 UINT64 size;
268 BOOL provisional;
269 LIST_ENTRY listentry;
270 } disk_hole;
271
272 typedef struct {
273 PDEVICE_OBJECT devobj;
274 DEV_ITEM devitem;
275 LIST_ENTRY disk_holes;
276 } device;
277
278 typedef struct {
279 CHUNK_ITEM* chunk_item;
280 UINT32 size;
281 UINT64 offset;
282 UINT64 used;
283 UINT32 oldused;
284 BOOL space_changed;
285 device** devices;
286 LIST_ENTRY space;
287 LIST_ENTRY list_entry;
288 } chunk;
289
290 typedef struct {
291 KEY key;
292 void* data;
293 USHORT size;
294 LIST_ENTRY list_entry;
295 } sys_chunk;
296
297 typedef struct _device_extension {
298 device* devices;
299 // DISK_GEOMETRY geometry;
300 UINT64 length;
301 superblock superblock;
302 // WCHAR label[MAX_LABEL_SIZE];
303 BOOL readonly;
304 fcb* fcbs;
305 fcb* volume_fcb;
306 fcb* root_fcb;
307 ERESOURCE DirResource;
308 KSPIN_LOCK FcbListLock;
309 ERESOURCE fcb_lock;
310 ERESOURCE load_lock;
311 ERESOURCE tree_lock;
312 PNOTIFY_SYNC NotifySync;
313 LIST_ENTRY DirNotifyList;
314 LONG tree_lock_counter;
315 LONG open_trees;
316 ULONG write_trees;
317 // ERESOURCE LogToPhysLock;
318 // UINT64 chunk_root_phys_addr;
319 UINT64 root_tree_phys_addr;
320 // log_to_phys* log_to_phys;
321 root* roots;
322 root* chunk_root;
323 root* root_root;
324 root* extent_root;
325 root* checksum_root;
326 root* dev_root;
327 BOOL log_to_phys_loaded;
328 UINT32 max_inline;
329 LIST_ENTRY sys_chunks;
330 LIST_ENTRY chunks;
331 LIST_ENTRY trees;
332 LIST_ENTRY tree_cache;
333 HANDLE flush_thread_handle;
334 KTIMER flush_thread_timer;
335 LIST_ENTRY list_entry;
336 } device_extension;
337
338 typedef struct {
339 LIST_ENTRY listentry;
340 PSID sid;
341 UINT32 uid;
342 } uid_map;
343
344 // #pragma pack(pop)
345
346 static __inline void init_tree_holder(tree_holder* th) {
347 // th->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_holder_nonpaged), ALLOC_TAG);
348 // KeInitializeSpinLock(&th->nonpaged->spin_lock);
349 // ExInitializeResourceLite(&th->nonpaged->lock); // FIXME - delete this later
350 }
351
352 static __inline void* map_user_buffer(PIRP Irp) {
353 if (!Irp->MdlAddress) {
354 return Irp->UserBuffer;
355 } else {
356 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
357 }
358 }
359
360 static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
361 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
362 }
363
364 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
365 ULONGLONG l = t.QuadPart - 116444736000000000;
366
367 out->seconds = l / 10000000;
368 out->nanoseconds = (l % 10000000) * 100;
369 }
370
371 // in btrfs.c
372 device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
373 ULONG sector_align( ULONG NumberToBeAligned, ULONG Alignment );
374 int keycmp(const KEY* key1, const KEY* key2);
375 ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa);
376 BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen);
377 NTSTATUS STDCALL set_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8* data, UINT16 datalen, LIST_ENTRY* rollback);
378 BOOL STDCALL delete_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, LIST_ENTRY* rollback);
379 void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
380 BOOL STDCALL get_last_inode(device_extension* Vcb, root* r);
381 NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback);
382 NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback);
383 UINT64 find_next_dir_index(device_extension* Vcb, root* subvol, UINT64 inode);
384 NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, UINT64* index, LIST_ENTRY* rollback);
385 NTSTATUS delete_fcb(fcb* fcb, PFILE_OBJECT FileObject, LIST_ENTRY* rollback);
386 fcb* create_fcb();
387 void protect_superblocks(device_extension* Vcb, chunk* c);
388 BOOL is_top_level(PIRP Irp);
389
390 #ifdef _MSC_VER
391 #define funcname __FUNCTION__
392 #else
393 #define funcname __func__
394 #endif
395
396 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
397 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
398
399 #ifdef _DEBUG
400
401 #ifdef DEBUG_LONG_MESSAGES
402
403 #define TRACE(s, ...) _debug_message(funcname, 3, __FILE__, __LINE__, s, ##__VA_ARGS__)
404 #define WARN(s, ...) _debug_message(funcname, 2, __FILE__, __LINE__, s, ##__VA_ARGS__)
405 #define FIXME(s, ...) _debug_message(funcname, 1, __FILE__, __LINE__, s, ##__VA_ARGS__)
406 #define ERR(s, ...) _debug_message(funcname, 1, __FILE__, __LINE__, s, ##__VA_ARGS__)
407
408 void STDCALL _debug_message(const char* func, UINT8 priority, const char* file, unsigned int line, char* s, ...);
409
410 #else
411
412 #define TRACE(s, ...) _debug_message(funcname, 3, s, ##__VA_ARGS__)
413 #define WARN(s, ...) _debug_message(funcname, 2, s, ##__VA_ARGS__)
414 #define FIXME(s, ...) _debug_message(funcname, 1, s, ##__VA_ARGS__)
415 #define ERR(s, ...) _debug_message(funcname, 1, s, ##__VA_ARGS__)
416
417 void STDCALL _debug_message(const char* func, UINT8 priority, char* s, ...);
418
419 #endif
420
421 #else
422
423 #define TRACE(s, ...)
424 #define WARN(s, ...)
425 #ifndef __REACTOS__
426 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
427 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
428 #else
429 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
430 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
431 #endif
432
433 #endif
434
435 // in fastio.c
436 void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
437
438 // in crc32c.c
439 UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
440
441 // in treefuncs.c
442 NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, const char* func, const char* file, unsigned int line);
443 BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, const char* func, const char* file, unsigned int line);
444 BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, const char* func, const char* file, unsigned int line);
445 void STDCALL _free_traverse_ptr(traverse_ptr* tp, const char* func, const char* file, unsigned int line);
446 void STDCALL free_tree_cache(LIST_ENTRY* tc);
447 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, LIST_ENTRY* rollback);
448 void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
449 void STDCALL add_to_tree_cache(device_extension* Vcb, tree* t, BOOL write);
450 tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
451 NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, const char* func, const char* file, unsigned int line);
452 NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, const char* func, const char* file, unsigned int line);
453 void clear_rollback(LIST_ENTRY* rollback);
454 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
455
456 #define find_item(Vcb, r, tp, searchkey, ignore) _find_item(Vcb, r, tp, searchkey, ignore, funcname, __FILE__, __LINE__)
457 #define find_next_item(Vcb, tp, next_tp, ignore) _find_next_item(Vcb, tp, next_tp, ignore, funcname, __FILE__, __LINE__)
458 #define find_prev_item(Vcb, tp, prev_tp, ignore) _find_prev_item(Vcb, tp, prev_tp, ignore, funcname, __FILE__, __LINE__)
459 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
460 #define load_tree(t, addr, r, pt) _load_tree(t, addr, r, pt, funcname, __FILE__, __LINE__)
461 #define free_traverse_ptr(tp) _free_traverse_ptr(tp, funcname, __FILE__, __LINE__)
462 #define do_load_tree(Vcb, th, r, t, td, loaded) _do_load_tree(Vcb, th, r, t, td, loaded, funcname, __FILE__, __LINE__)
463
464 // in search.c
465 void STDCALL look_for_vols(LIST_ENTRY* volumes);
466
467 // in cache.c
468 NTSTATUS STDCALL init_cache();
469 void STDCALL free_cache();
470 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
471
472 // in write.c
473 NTSTATUS STDCALL do_write(device_extension* Vcb, LIST_ENTRY* rollback);
474 NTSTATUS write_file(PDEVICE_OBJECT DeviceObject, PIRP Irp);
475 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache, LIST_ENTRY* rollback);
476 NTSTATUS truncate_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
477 NTSTATUS extend_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
478 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
479 void update_checksum_tree(device_extension* Vcb, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
480 NTSTATUS insert_sparse_extent(device_extension* Vcb, root* r, UINT64 inode, UINT64 start, UINT64 length, LIST_ENTRY* rollback);
481 NTSTATUS STDCALL add_extent_ref(device_extension* Vcb, UINT64 address, UINT64 size, root* subvol, UINT64 inode, UINT64 offset, LIST_ENTRY* rollback);
482 NTSTATUS STDCALL remove_extent_ref(device_extension* Vcb, UINT64 address, UINT64 size, root* subvol, UINT64 inode, UINT64 offset, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
483 void print_trees(LIST_ENTRY* tc);
484 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
485 void add_to_space_list(chunk* c, UINT64 offset, UINT64 size, UINT8 type);
486 NTSTATUS consider_write(device_extension* Vcb);
487
488 // in dirctrl.c
489 NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
490
491 // in security.c
492 NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
493 NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
494 void fcb_get_sd(fcb* fcb);
495 // UINT32 STDCALL get_uid();
496 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
497 NTSTATUS fcb_get_new_sd(fcb* fcb, ACCESS_STATE* as);
498
499 // in fileinfo.c
500 NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
501 NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
502 NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, LIST_ENTRY* rollback);
503
504 // in reparse.c
505 BOOL follow_symlink(fcb* fcb, PFILE_OBJECT FileObject);
506 NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, DWORD* retlen);
507 NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
508
509 // in create.c
510 NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
511 NTSTATUS get_fcb(device_extension* Vcb, fcb** pfcb, PUNICODE_STRING fnus, fcb* relatedfcb, BOOL parent);
512 BOOL STDCALL find_file_in_dir_with_crc32(device_extension* Vcb, PUNICODE_STRING filename, UINT32 crc32, root* r, UINT64 parinode, root** subvol,
513 UINT64* inode, UINT8* type, PANSI_STRING utf8);
514
515 // in fsctl.c
516 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
517
518 // in flushthread.c
519 void STDCALL flush_thread(void* context);
520
521 // in read.c
522 NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
523 NTSTATUS STDCALL read_file(device_extension* Vcb, root* subvol, UINT64 inode, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr);
524
525 static __inline void print_open_trees(device_extension* Vcb) {
526 LIST_ENTRY* le = Vcb->trees.Flink;
527 while (le != &Vcb->trees) {
528 tree* t = CONTAINING_RECORD(le, tree, list_entry);
529 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
530 ERR("tree %p: root %llx, level %u, refcount %u, first key (%llx,%x,%llx)\n",
531 t, t->root->id, t->header.level, t->refcount, td->key.obj_id, td->key.obj_type, td->key.offset);
532
533 le = le->Flink;
534 }
535 }
536
537 static __inline void InsertAfter(LIST_ENTRY* head, LIST_ENTRY* item, LIST_ENTRY* before) {
538 item->Flink = before->Flink;
539 before->Flink = item;
540 item->Blink = before;
541
542 if (item->Flink != head)
543 item->Flink->Blink = item;
544 else
545 head->Blink = item;
546 }
547
548 #ifdef _MSC_VER
549 // #define int3 __asm { int 3 }
550 #define int3 __debugbreak()
551 #else
552 #define int3 asm("int3;")
553 #endif
554
555 #define acquire_tree_lock(Vcb, exclusive) {\
556 LONG ref = InterlockedIncrement(&Vcb->tree_lock_counter); \
557 ref = ref; \
558 if (exclusive) { \
559 TRACE("getting tree_lock (exclusive) %u->%u\n", ref-1, ref); \
560 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); \
561 TRACE("open tree count = %i\n", Vcb->open_trees); \
562 } else { \
563 TRACE("getting tree_lock %u->%u\n", ref-1, ref); \
564 ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); \
565 } \
566 }
567
568 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
569 // else TRACE("open tree count = %i\n", Vcb->open_trees);
570
571 // FIXME - find a way to catch unfreed trees again
572
573 #define release_tree_lock(Vcb, exclusive) {\
574 LONG ref = InterlockedDecrement(&Vcb->tree_lock_counter); \
575 ref = ref; \
576 TRACE("releasing tree_lock %u->%u\n", ref+1, ref); \
577 if (exclusive) {\
578 TRACE("open tree count = %i\n", Vcb->open_trees); \
579 } \
580 ExReleaseResourceLite(&Vcb->tree_lock); \
581 }
582
583 #ifdef DEBUG_TREE_REFCOUNTS
584 #ifdef DEBUG_LONG_MESSAGES
585 #define _increase_tree_rc(t, func, file, line) { \
586 LONG rc = InterlockedIncrement(&t->refcount); \
587 _debug_message(func, file, line, "tree %p: refcount increased to %i (increase_tree_rc)\n", t, rc); \
588 }
589 #else
590 #define _increase_tree_rc(t, func, file, line) { \
591 LONG rc = InterlockedIncrement(&t->refcount); \
592 _debug_message(func, "tree %p: refcount increased to %i (increase_tree_rc)\n", t, rc); \
593 }
594 #endif
595 #define increase_tree_rc(t) _increase_tree_rc(t, funcname, __FILE__, __LINE__)
596 #else
597 #define increase_tree_rc(t) InterlockedIncrement(&t->refcount);
598 #define _increase_tree_rc(t, func, file, line) increase_tree_rc(t)
599 #endif
600
601 // from sys/stat.h
602 #define __S_IFMT 0170000 /* These bits determine file type. */
603 #define __S_IFDIR 0040000 /* Directory. */
604 #define __S_IFCHR 0020000 /* Character device. */
605 #define __S_IFBLK 0060000 /* Block device. */
606 #define __S_IFREG 0100000 /* Regular file. */
607 #define __S_IFIFO 0010000 /* FIFO. */
608 #define __S_IFLNK 0120000 /* Symbolic link. */
609 #define __S_IFSOCK 0140000 /* Socket. */
610 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
611
612 #ifndef S_ISDIR
613 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
614 #endif
615
616 #ifndef S_IXUSR
617 #define S_IXUSR 0000100
618 #endif
619
620 #ifdef __REACTOS__
621 #define S_IFDIR __S_IFDIR
622 #define S_IFREG __S_IFREG
623 #endif /* __REACTOS__ */
624
625 #ifndef S_IXGRP
626 #define S_IXGRP (S_IXUSR >> 3)
627 #endif
628
629 #ifndef S_IXOTH
630 #define S_IXOTH (S_IXGRP >> 3)
631 #endif
632
633 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
634 NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
635 ULONG *utf8_bytes_written,
636 const WCHAR *uni_src, ULONG uni_bytes);
637 NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
638 ULONG *uni_bytes_written,
639 const CHAR *utf8_src, ULONG utf8_bytes);
640 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
641 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
642 NTSTATUS NTAPI FsRtlRemoveDotsFromPath(PWSTR OriginalString,
643 USHORT PathLength, USHORT *NewLength);
644 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
645
646 #endif