1 /* Copyright (c) Mark Harmstone 2016
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/>. */
18 #ifndef BTRFS_DRV_H_DEFINED
19 #define BTRFS_DRV_H_DEFINED
25 #define _WIN32_WINNT 0x0600
26 #define NTDDI_VERSION 0x06010000 // Win 7
27 #define _CRT_SECURE_NO_WARNINGS
28 #endif /* __REACTOS__ */
34 #endif /* __REACTOS__ */
39 #endif /* __REACTOS__ */
40 //#include <windows.h>
49 // #define DEBUG_TREE_REFCOUNTS
50 // #define DEBUG_FCB_REFCOUNTS
51 // #define DEBUG_LONG_MESSAGES
52 #define DEBUG_PARANOID
55 #define BTRFS_NODE_TYPE_CCB 0x2295
56 #define BTRFS_NODE_TYPE_FCB 0x2296
58 #define ALLOC_TAG 0x7442484D //'MHBt'
60 #define STDCALL __stdcall
62 #define UID_NOBODY 65534
63 #define GID_NOBODY 65534
65 #define EA_NTACL "security.NTACL"
66 #define EA_NTACL_HASH 0x45922146
68 #define EA_DOSATTRIB "user.DOSATTRIB"
69 #define EA_DOSATTRIB_HASH 0x914f9939
71 #define READ_AHEAD_GRANULARITY 0x10000 // 64 KB
75 #define except __except
76 #define finally __finally
79 #define except(x) if (0 && (x))
80 #define finally if (1)
83 // #pragma pack(push, 1)
85 struct device_extension
;
88 PDEVICE_OBJECT devobj
;
92 UNICODE_STRING devpath
;
94 LIST_ENTRY list_entry
;
97 typedef struct _fcb_nonpaged
{
98 FAST_MUTEX HeaderMutex
;
99 SECTION_OBJECT_POINTERS segment_object
;
101 ERESOURCE paging_resource
;
106 typedef struct _fcb
{
107 FSRTL_ADVANCED_FCB_HEADER Header
;
108 struct _fcb_nonpaged
* nonpaged
;
111 UNICODE_STRING filepart
;
113 struct _device_extension
* Vcb
;
117 struct _root
* subvol
;
121 BOOL delete_on_close
;
122 INODE_ITEM inode_item
;
123 UNICODE_STRING full_filename
;
125 SECURITY_DESCRIPTOR
* sd
;
128 PKTHREAD lazy_writer_thread
;
130 SHARE_ACCESS share_access
;
135 ANSI_STRING adsxattr
;
137 LIST_ENTRY list_entry
;
140 typedef struct _ccb
{
145 UINT64 query_dir_offset
;
146 // char* query_string;
147 UNICODE_STRING query_string
;
152 // typedef struct _log_to_phys {
156 // UINT32 sector_size;
157 // struct _log_to_phys* next;
160 struct _device_extension
;
162 // enum tree_holder_status {
163 // tree_holder_unloaded,
164 // tree_holder_loading,
165 // tree_holder_loaded,
166 // tree_holder_unloading
170 // enum tree_holder_status status;
171 // KSPIN_LOCK spin_lock;
173 // } tree_holder_nonpaged;
179 // tree_holder_nonpaged* nonpaged;
182 typedef struct _tree_data
{
184 LIST_ENTRY list_entry
;
189 tree_holder treeholder
;
198 // typedef struct _tree_nonpaged {
199 // ERESOURCE load_tree_lock;
202 typedef struct _tree
{
209 struct _device_extension
* Vcb
;
210 struct _tree
* parent
;
213 // tree_nonpaged* nonpaged;
215 LIST_ENTRY list_entry
;
217 BOOL has_new_address
;
222 // KSPIN_LOCK load_tree_lock;
223 ERESOURCE load_tree_lock
;
226 typedef struct _root
{
228 tree_holder treeholder
;
229 root_nonpaged
* nonpaged
;
242 typedef struct _tree_cache
{
245 LIST_ENTRY list_entry
;
248 typedef struct _root_cache
{
250 struct _root_cache
* next
;
253 #define SPACE_TYPE_FREE 0
254 #define SPACE_TYPE_USED 1
255 #define SPACE_TYPE_DELETING 2
256 #define SPACE_TYPE_WRITING 3
262 LIST_ENTRY list_entry
;
269 LIST_ENTRY listentry
;
273 PDEVICE_OBJECT devobj
;
275 LIST_ENTRY disk_holes
;
279 CHUNK_ITEM
* chunk_item
;
287 LIST_ENTRY list_entry
;
294 LIST_ENTRY list_entry
;
297 typedef struct _device_extension
{
299 // DISK_GEOMETRY geometry;
301 superblock superblock
;
302 // WCHAR label[MAX_LABEL_SIZE];
307 ERESOURCE DirResource
;
308 KSPIN_LOCK FcbListLock
;
312 PNOTIFY_SYNC NotifySync
;
313 LIST_ENTRY DirNotifyList
;
314 LONG tree_lock_counter
;
317 // ERESOURCE LogToPhysLock;
318 // UINT64 chunk_root_phys_addr;
319 UINT64 root_tree_phys_addr
;
320 // log_to_phys* log_to_phys;
327 BOOL log_to_phys_loaded
;
329 LIST_ENTRY sys_chunks
;
332 LIST_ENTRY tree_cache
;
333 HANDLE flush_thread_handle
;
334 KTIMER flush_thread_timer
;
335 LIST_ENTRY list_entry
;
339 LIST_ENTRY listentry
;
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
352 static __inline
void* map_user_buffer(PIRP Irp
) {
353 if (!Irp
->MdlAddress
) {
354 return Irp
->UserBuffer
;
356 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
360 static __inline UINT64
unix_time_to_win(BTRFS_TIME
* t
) {
361 return (t
->seconds
* 10000000) + (t
->nanoseconds
/ 100) + 116444736000000000;
364 static __inline
void win_time_to_unix(LARGE_INTEGER t
, BTRFS_TIME
* out
) {
365 ULONGLONG l
= t
.QuadPart
- 116444736000000000;
367 out
->seconds
= l
/ 10000000;
368 out
->nanoseconds
= (l
% 10000000) * 100;
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
);
387 void protect_superblocks(device_extension
* Vcb
, chunk
* c
);
388 BOOL
is_top_level(PIRP Irp
);
391 #define funcname __FUNCTION__
393 #define funcname __func__
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__)
401 #ifdef DEBUG_LONG_MESSAGES
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__)
408 void STDCALL
_debug_message(const char* func
, UINT8 priority
, const char* file
, unsigned int line
, char* s
, ...);
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__)
417 void STDCALL
_debug_message(const char* func
, UINT8 priority
, char* s
, ...);
423 #define TRACE(s, ...)
426 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
427 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
429 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
430 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
436 void STDCALL
init_fast_io_dispatch(FAST_IO_DISPATCH
** fiod
);
439 UINT32 STDCALL
calc_crc32c(UINT32 seed
, UINT8
* msg
, ULONG msglen
);
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
);
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__)
465 void STDCALL
look_for_vols(LIST_ENTRY
* volumes
);
468 NTSTATUS STDCALL
init_cache();
469 void STDCALL
free_cache();
470 extern CACHE_MANAGER_CALLBACKS
* cache_callbacks
;
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
);
489 NTSTATUS STDCALL
drv_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
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
);
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
);
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
);
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
);
516 NTSTATUS
fsctl_request(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, UINT32 type
, BOOL user
);
519 void STDCALL
flush_thread(void* context
);
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
);
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
);
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
;
542 if (item
->Flink
!= head
)
543 item
->Flink
->Blink
= item
;
549 // #define int3 __asm { int 3 }
550 #define int3 __debugbreak()
552 #define int3 asm("int3;")
555 #define acquire_tree_lock(Vcb, exclusive) {\
556 LONG ref = InterlockedIncrement(&Vcb->tree_lock_counter); \
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); \
563 TRACE("getting tree_lock %u->%u\n", ref-1, ref); \
564 ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); \
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);
571 // FIXME - find a way to catch unfreed trees again
573 #define release_tree_lock(Vcb, exclusive) {\
574 LONG ref = InterlockedDecrement(&Vcb->tree_lock_counter); \
576 TRACE("releasing tree_lock %u->%u\n", ref+1, ref); \
578 TRACE("open tree count = %i\n", Vcb->open_trees); \
580 ExReleaseResourceLite(&Vcb->tree_lock); \
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); \
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); \
595 #define increase_tree_rc(t) _increase_tree_rc(t, funcname, __FILE__, __LINE__)
597 #define increase_tree_rc(t) InterlockedIncrement(&t->refcount);
598 #define _increase_tree_rc(t, func, file, line) increase_tree_rc(t)
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))
613 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
617 #define S_IXUSR 0000100
621 #define S_IFDIR __S_IFDIR
622 #define S_IFREG __S_IFREG
623 #endif /* __REACTOS__ */
626 #define S_IXGRP (S_IXUSR >> 3)
630 #define S_IXOTH (S_IXGRP >> 3)
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) */