[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 UINT32 size;
208 struct _device_extension* Vcb;
209 struct _tree* parent;
210 tree_data* paritem;
211 struct _root* root;
212 // tree_nonpaged* nonpaged;
213 LIST_ENTRY itemlist;
214 LIST_ENTRY list_entry;
215 UINT64 new_address;
216 UINT64 flags;
217 } tree;
218
219 typedef struct {
220 // KSPIN_LOCK load_tree_lock;
221 ERESOURCE load_tree_lock;
222 } root_nonpaged;
223
224 typedef struct _root {
225 UINT64 id;
226 tree_holder treeholder;
227 root_nonpaged* nonpaged;
228 UINT64 lastinode;
229 ROOT_ITEM root_item;
230
231 struct _root* prev;
232 struct _root* next;
233 } root;
234
235 typedef struct {
236 tree* tree;
237 tree_data* item;
238 } traverse_ptr;
239
240 typedef struct _tree_cache {
241 tree* tree;
242 BOOL write;
243 LIST_ENTRY list_entry;
244 } tree_cache;
245
246 typedef struct _root_cache {
247 root* root;
248 struct _root_cache* next;
249 } root_cache;
250
251 #define SPACE_TYPE_FREE 0
252 #define SPACE_TYPE_USED 1
253 #define SPACE_TYPE_DELETING 2
254 #define SPACE_TYPE_WRITING 3
255
256 typedef struct {
257 UINT64 offset;
258 UINT64 size;
259 UINT8 type;
260 LIST_ENTRY list_entry;
261 } space;
262
263 typedef struct {
264 UINT64 address;
265 UINT64 size;
266 BOOL provisional;
267 LIST_ENTRY listentry;
268 } disk_hole;
269
270 typedef struct {
271 PDEVICE_OBJECT devobj;
272 DEV_ITEM devitem;
273 LIST_ENTRY disk_holes;
274 } device;
275
276 typedef struct {
277 CHUNK_ITEM* chunk_item;
278 UINT32 size;
279 UINT64 offset;
280 UINT64 used;
281 UINT32 oldused;
282 BOOL space_changed;
283 device** devices;
284 LIST_ENTRY space;
285 LIST_ENTRY list_entry;
286 } chunk;
287
288 typedef struct {
289 KEY key;
290 void* data;
291 USHORT size;
292 LIST_ENTRY list_entry;
293 } sys_chunk;
294
295 typedef struct _device_extension {
296 device* devices;
297 // DISK_GEOMETRY geometry;
298 UINT64 length;
299 superblock superblock;
300 // WCHAR label[MAX_LABEL_SIZE];
301 BOOL readonly;
302 fcb* fcbs;
303 fcb* volume_fcb;
304 fcb* root_fcb;
305 ERESOURCE DirResource;
306 KSPIN_LOCK FcbListLock;
307 ERESOURCE fcb_lock;
308 ERESOURCE load_lock;
309 ERESOURCE tree_lock;
310 PNOTIFY_SYNC NotifySync;
311 LIST_ENTRY DirNotifyList;
312 LONG tree_lock_counter;
313 LONG open_trees;
314 ULONG write_trees;
315 // ERESOURCE LogToPhysLock;
316 // UINT64 chunk_root_phys_addr;
317 UINT64 root_tree_phys_addr;
318 // log_to_phys* log_to_phys;
319 root* roots;
320 root* chunk_root;
321 root* root_root;
322 root* extent_root;
323 root* checksum_root;
324 root* dev_root;
325 BOOL log_to_phys_loaded;
326 UINT32 max_inline;
327 LIST_ENTRY sys_chunks;
328 LIST_ENTRY chunks;
329 LIST_ENTRY trees;
330 LIST_ENTRY tree_cache;
331 HANDLE flush_thread_handle;
332 KTIMER flush_thread_timer;
333 LIST_ENTRY list_entry;
334 } device_extension;
335
336 typedef struct {
337 LIST_ENTRY listentry;
338 PSID sid;
339 UINT32 uid;
340 } uid_map;
341
342 // #pragma pack(pop)
343
344 static __inline void init_tree_holder(tree_holder* th) {
345 // th->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_holder_nonpaged), ALLOC_TAG);
346 // KeInitializeSpinLock(&th->nonpaged->spin_lock);
347 // ExInitializeResourceLite(&th->nonpaged->lock); // FIXME - delete this later
348 }
349
350 static __inline void* map_user_buffer(PIRP Irp) {
351 if (!Irp->MdlAddress) {
352 return Irp->UserBuffer;
353 } else {
354 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
355 }
356 }
357
358 static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
359 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000;
360 }
361
362 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
363 ULONGLONG l = t.QuadPart - 116444736000000000;
364
365 out->seconds = l / 10000000;
366 out->nanoseconds = (l % 10000000) * 100;
367 }
368
369 // in btrfs.c
370 device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
371 ULONG sector_align( ULONG NumberToBeAligned, ULONG Alignment );
372 int keycmp(const KEY* key1, const KEY* key2);
373 ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa);
374 BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen);
375 NTSTATUS STDCALL set_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8* data, UINT16 datalen, LIST_ENTRY* rollback);
376 BOOL STDCALL delete_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, LIST_ENTRY* rollback);
377 void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
378 BOOL STDCALL get_last_inode(device_extension* Vcb, root* r);
379 NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback);
380 NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback);
381 UINT64 find_next_dir_index(device_extension* Vcb, root* subvol, UINT64 inode);
382 NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, UINT64* index, LIST_ENTRY* rollback);
383 NTSTATUS delete_fcb(fcb* fcb, PFILE_OBJECT FileObject, LIST_ENTRY* rollback);
384 fcb* create_fcb();
385 void protect_superblocks(device_extension* Vcb, chunk* c);
386 BOOL is_top_level(PIRP Irp);
387
388 #ifdef _MSC_VER
389 #define funcname __FUNCTION__
390 #else
391 #define funcname __func__
392 #endif
393
394 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
395 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
396
397 #ifdef _DEBUG
398
399 #ifdef DEBUG_LONG_MESSAGES
400
401 #define TRACE(s, ...) _debug_message(funcname, 3, __FILE__, __LINE__, s, ##__VA_ARGS__)
402 #define WARN(s, ...) _debug_message(funcname, 2, __FILE__, __LINE__, s, ##__VA_ARGS__)
403 #define FIXME(s, ...) _debug_message(funcname, 1, __FILE__, __LINE__, s, ##__VA_ARGS__)
404 #define ERR(s, ...) _debug_message(funcname, 1, __FILE__, __LINE__, s, ##__VA_ARGS__)
405
406 void STDCALL _debug_message(const char* func, UINT8 priority, const char* file, unsigned int line, char* s, ...);
407
408 #else
409
410 #define TRACE(s, ...) _debug_message(funcname, 3, s, ##__VA_ARGS__)
411 #define WARN(s, ...) _debug_message(funcname, 2, s, ##__VA_ARGS__)
412 #define FIXME(s, ...) _debug_message(funcname, 1, s, ##__VA_ARGS__)
413 #define ERR(s, ...) _debug_message(funcname, 1, s, ##__VA_ARGS__)
414
415 void STDCALL _debug_message(const char* func, UINT8 priority, char* s, ...);
416
417 #endif
418
419 #else
420
421 #define TRACE(s, ...)
422 #define WARN(s, ...)
423 #ifndef __REACTOS__
424 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
425 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
426 #else
427 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
428 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
429 #endif
430
431 #endif
432
433 // in fastio.c
434 void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
435
436 // in crc32c.c
437 UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
438
439 // in treefuncs.c
440 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);
441 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);
442 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);
443 void STDCALL _free_traverse_ptr(traverse_ptr* tp, const char* func, const char* file, unsigned int line);
444 void STDCALL free_tree_cache(LIST_ENTRY* tc);
445 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);
446 void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
447 void STDCALL add_to_tree_cache(device_extension* Vcb, tree* t, BOOL write);
448 tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
449 NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, const char* func, const char* file, unsigned int line);
450 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);
451 void clear_rollback(LIST_ENTRY* rollback);
452 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
453
454 #define find_item(Vcb, r, tp, searchkey, ignore) _find_item(Vcb, r, tp, searchkey, ignore, funcname, __FILE__, __LINE__)
455 #define find_next_item(Vcb, tp, next_tp, ignore) _find_next_item(Vcb, tp, next_tp, ignore, funcname, __FILE__, __LINE__)
456 #define find_prev_item(Vcb, tp, prev_tp, ignore) _find_prev_item(Vcb, tp, prev_tp, ignore, funcname, __FILE__, __LINE__)
457 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
458 #define load_tree(t, addr, r, pt) _load_tree(t, addr, r, pt, funcname, __FILE__, __LINE__)
459 #define free_traverse_ptr(tp) _free_traverse_ptr(tp, funcname, __FILE__, __LINE__)
460 #define do_load_tree(Vcb, th, r, t, td, loaded) _do_load_tree(Vcb, th, r, t, td, loaded, funcname, __FILE__, __LINE__)
461
462 // in search.c
463 void STDCALL look_for_vols(LIST_ENTRY* volumes);
464
465 // in cache.c
466 NTSTATUS STDCALL init_cache();
467 void STDCALL free_cache();
468 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
469
470 // in write.c
471 NTSTATUS STDCALL do_write(device_extension* Vcb, LIST_ENTRY* rollback);
472 NTSTATUS write_file(PDEVICE_OBJECT DeviceObject, PIRP Irp);
473 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache, LIST_ENTRY* rollback);
474 NTSTATUS truncate_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
475 NTSTATUS extend_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
476 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
477 void update_checksum_tree(device_extension* Vcb, LIST_ENTRY* changed_sector_list, LIST_ENTRY* rollback);
478 NTSTATUS insert_sparse_extent(device_extension* Vcb, root* r, UINT64 inode, UINT64 start, UINT64 length, LIST_ENTRY* rollback);
479 NTSTATUS STDCALL add_extent_ref(device_extension* Vcb, UINT64 address, UINT64 size, root* subvol, UINT64 inode, UINT64 offset, LIST_ENTRY* rollback);
480 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);
481 void print_trees(LIST_ENTRY* tc);
482 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
483 void add_to_space_list(chunk* c, UINT64 offset, UINT64 size, UINT8 type);
484 NTSTATUS consider_write(device_extension* Vcb);
485
486 // in dirctrl.c
487 NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
488
489 // in security.c
490 NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
491 NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
492 void fcb_get_sd(fcb* fcb);
493 // UINT32 STDCALL get_uid();
494 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
495 NTSTATUS fcb_get_new_sd(fcb* fcb, ACCESS_STATE* as);
496
497 // in fileinfo.c
498 NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
499 NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
500 NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, LIST_ENTRY* rollback);
501
502 // in reparse.c
503 BOOL follow_symlink(fcb* fcb, PFILE_OBJECT FileObject);
504 NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, DWORD* retlen);
505 NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
506
507 // in create.c
508 NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
509 NTSTATUS get_fcb(device_extension* Vcb, fcb** pfcb, PUNICODE_STRING fnus, fcb* relatedfcb, BOOL parent);
510 BOOL STDCALL find_file_in_dir_with_crc32(device_extension* Vcb, PUNICODE_STRING filename, UINT32 crc32, root* r, UINT64 parinode, root** subvol,
511 UINT64* inode, UINT8* type, PANSI_STRING utf8);
512
513 // in fsctl.c
514 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
515
516 // in flushthread.c
517 void STDCALL flush_thread(void* context);
518
519 // in read.c
520 NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
521 NTSTATUS STDCALL read_file(device_extension* Vcb, root* subvol, UINT64 inode, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr);
522
523 static __inline void print_open_trees(device_extension* Vcb) {
524 LIST_ENTRY* le = Vcb->trees.Flink;
525 while (le != &Vcb->trees) {
526 tree* t = CONTAINING_RECORD(le, tree, list_entry);
527 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry);
528 ERR("tree %p: root %llx, level %u, refcount %u, first key (%llx,%x,%llx)\n",
529 t, t->root->id, t->header.level, t->refcount, td->key.obj_id, td->key.obj_type, td->key.offset);
530
531 le = le->Flink;
532 }
533 }
534
535 static __inline void InsertAfter(LIST_ENTRY* head, LIST_ENTRY* item, LIST_ENTRY* before) {
536 item->Flink = before->Flink;
537 before->Flink = item;
538 item->Blink = before;
539
540 if (item->Flink != head)
541 item->Flink->Blink = item;
542 else
543 head->Blink = item;
544 }
545
546 #ifdef _MSC_VER
547 // #define int3 __asm { int 3 }
548 #define int3 __debugbreak()
549 #else
550 #define int3 asm("int3;")
551 #endif
552
553 #define acquire_tree_lock(Vcb, exclusive) {\
554 LONG ref = InterlockedIncrement(&Vcb->tree_lock_counter); \
555 ref = ref; \
556 if (exclusive) { \
557 TRACE("getting tree_lock (exclusive) %u->%u\n", ref-1, ref); \
558 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); \
559 TRACE("open tree count = %i\n", Vcb->open_trees); \
560 } else { \
561 TRACE("getting tree_lock %u->%u\n", ref-1, ref); \
562 ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); \
563 } \
564 }
565
566 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
567 // else TRACE("open tree count = %i\n", Vcb->open_trees);
568
569 // FIXME - find a way to catch unfreed trees again
570
571 #define release_tree_lock(Vcb, exclusive) {\
572 LONG ref = InterlockedDecrement(&Vcb->tree_lock_counter); \
573 ref = ref; \
574 TRACE("releasing tree_lock %u->%u\n", ref+1, ref); \
575 if (exclusive) {\
576 TRACE("open tree count = %i\n", Vcb->open_trees); \
577 } \
578 ExReleaseResourceLite(&Vcb->tree_lock); \
579 }
580
581 #ifdef DEBUG_TREE_REFCOUNTS
582 #ifdef DEBUG_LONG_MESSAGES
583 #define _increase_tree_rc(t, func, file, line) { \
584 LONG rc = InterlockedIncrement(&t->refcount); \
585 _debug_message(func, file, line, "tree %p: refcount increased to %i (increase_tree_rc)\n", t, rc); \
586 }
587 #else
588 #define _increase_tree_rc(t, func, file, line) { \
589 LONG rc = InterlockedIncrement(&t->refcount); \
590 _debug_message(func, "tree %p: refcount increased to %i (increase_tree_rc)\n", t, rc); \
591 }
592 #endif
593 #define increase_tree_rc(t) _increase_tree_rc(t, funcname, __FILE__, __LINE__)
594 #else
595 #define increase_tree_rc(t) InterlockedIncrement(&t->refcount);
596 #define _increase_tree_rc(t, func, file, line) increase_tree_rc(t)
597 #endif
598
599 // from sys/stat.h
600 #define __S_IFMT 0170000 /* These bits determine file type. */
601 #define __S_IFDIR 0040000 /* Directory. */
602 #define __S_IFCHR 0020000 /* Character device. */
603 #define __S_IFBLK 0060000 /* Block device. */
604 #define __S_IFREG 0100000 /* Regular file. */
605 #define __S_IFIFO 0010000 /* FIFO. */
606 #define __S_IFLNK 0120000 /* Symbolic link. */
607 #define __S_IFSOCK 0140000 /* Socket. */
608 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
609
610 #ifndef S_ISDIR
611 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
612 #endif
613
614 #ifndef S_IXUSR
615 #define S_IXUSR 0000100
616 #endif
617
618 #ifdef __REACTOS__
619 #define S_IFDIR __S_IFDIR
620 #define S_IFREG __S_IFREG
621 #endif /* __REACTOS__ */
622
623 #ifndef S_IXGRP
624 #define S_IXGRP (S_IXUSR >> 3)
625 #endif
626
627 #ifndef S_IXOTH
628 #define S_IXOTH (S_IXGRP >> 3)
629 #endif
630
631 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
632 NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
633 ULONG *utf8_bytes_written,
634 const WCHAR *uni_src, ULONG uni_bytes);
635 NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
636 ULONG *uni_bytes_written,
637 const CHAR *utf8_src, ULONG utf8_bytes);
638 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
639 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
640 NTSTATUS NTAPI FsRtlRemoveDotsFromPath(PWSTR OriginalString,
641 USHORT PathLength, USHORT *NewLength);
642 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
643
644 #endif