ReactOS  0.4.14-dev-293-g2b39b42
dirctrl.c File Reference
#include "btrfs_drv.h"
Include dependency graph for dirctrl.c:

Go to the source code of this file.

Classes

struct  _FILE_ID_EXTD_DIR_INFORMATION
 
struct  _FILE_ID_EXTD_BOTH_DIR_INFORMATION
 
struct  dir_entry
 

Macros

#define FileIdExtdDirectoryInformation   (enum _FILE_INFORMATION_CLASS)60
 
#define FileIdExtdBothDirectoryInformation   (enum _FILE_INFORMATION_CLASS)63
 

Typedefs

typedef struct _FILE_ID_EXTD_DIR_INFORMATION FILE_ID_EXTD_DIR_INFORMATION
 
typedef struct _FILE_ID_EXTD_DIR_INFORMATIONPFILE_ID_EXTD_DIR_INFORMATION
 
typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATION FILE_ID_EXTD_BOTH_DIR_INFORMATION
 
typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATIONPFILE_ID_EXTD_BOTH_DIR_INFORMATION
 

Enumerations

enum  DirEntryType { DirEntryType_File, DirEntryType_Self, DirEntryType_Parent }
 

Functions

ULONG get_reparse_tag_fcb (fcb *fcb)
 
ULONG get_reparse_tag (device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, ULONG atts, bool lxss, PIRP Irp)
 
static ULONG get_ea_len (device_extension *Vcb, root *subvol, uint64_t inode, PIRP Irp)
 
static NTSTATUS query_dir_item (fcb *fcb, ccb *ccb, void *buf, LONG *len, PIRP Irp, dir_entry *de, root *r)
 
static NTSTATUS next_dir_entry (file_ref *fileref, uint64_t *offset, dir_entry *de, dir_child **pdc)
 
static NTSTATUS query_directory (PIRP Irp)
 
static NTSTATUS notify_change_directory (device_extension *Vcb, PIRP Irp)
 
 _Dispatch_type_ (IRP_MJ_DIRECTORY_CONTROL)
 

Macro Definition Documentation

◆ FileIdExtdBothDirectoryInformation

#define FileIdExtdBothDirectoryInformation   (enum _FILE_INFORMATION_CLASS)63

Definition at line 24 of file dirctrl.c.

◆ FileIdExtdDirectoryInformation

#define FileIdExtdDirectoryInformation   (enum _FILE_INFORMATION_CLASS)60

Definition at line 23 of file dirctrl.c.

Typedef Documentation

◆ FILE_ID_EXTD_BOTH_DIR_INFORMATION

◆ FILE_ID_EXTD_DIR_INFORMATION

◆ PFILE_ID_EXTD_BOTH_DIR_INFORMATION

◆ PFILE_ID_EXTD_DIR_INFORMATION

Enumeration Type Documentation

◆ DirEntryType

Enumerator
DirEntryType_File 
DirEntryType_Self 
DirEntryType_Parent 

Definition at line 68 of file dirctrl.c.

Function Documentation

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_DIRECTORY_CONTROL  )

Definition at line 1160 of file dirctrl.c.

1162  {
1164  NTSTATUS Status;
1165  ULONG func;
1166  bool top_level;
1168 
1170 
1171  TRACE("directory control\n");
1172 
1173  top_level = is_top_level(Irp);
1174 
1175  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
1177  goto end;
1178  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
1180  goto end;
1181  }
1182 
1184 
1185  Irp->IoStatus.Information = 0;
1186 
1188 
1189  switch (func) {
1192  break;
1193 
1196  break;
1197 
1198  default:
1199  WARN("unknown minor %u\n", func);
1201  Irp->IoStatus.Status = Status;
1202  break;
1203  }
1204 
1205  if (Status == STATUS_PENDING)
1206  goto exit;
1207 
1208 end:
1209  Irp->IoStatus.Status = Status;
1210 
1212 
1213 exit:
1214  TRACE("returning %08x\n", Status);
1215 
1216  if (top_level)
1218 
1220 
1221  return Status;
1222 }
GLenum func
Definition: glext.h:6028
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define VCB_TYPE_FS
Definition: btrfs_drv.h:657
static NTSTATUS query_directory(PIRP Irp)
Definition: dirctrl.c:741
GLuint GLuint end
Definition: gl.h:1545
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:272
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
#define TRACE(s)
Definition: solgame.cpp:4
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:659
#define Vcb
Definition: cdprocs.h:1425
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
unsigned int ULONG
Definition: retypes.h:1
static NTSTATUS notify_change_directory(device_extension *Vcb, PIRP Irp)
Definition: dirctrl.c:1083
void exit(int exitcode)
Definition: _exit.c:33
NTSTATUS vol_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:335

◆ get_ea_len()

static ULONG get_ea_len ( device_extension Vcb,
root subvol,
uint64_t  inode,
PIRP  Irp 
)
static

Definition at line 147 of file dirctrl.c.

147  {
148  uint8_t* eadata;
149  uint16_t len;
150 
151  if (get_xattr(Vcb, subvol, inode, EA_EA, EA_EA_HASH, &eadata, &len, Irp)) {
152  ULONG offset;
154 
156 
157  if (!NT_SUCCESS(Status)) {
158  WARN("IoCheckEaBufferValidity returned %08x (error at offset %u)\n", Status, offset);
159  ExFreePool(eadata);
160  return 0;
161  } else {
162  FILE_FULL_EA_INFORMATION* eainfo;
163  ULONG ealen;
164 
165  ealen = 4;
166  eainfo = (FILE_FULL_EA_INFORMATION*)eadata;
167  do {
168  ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
169 
170  if (eainfo->NextEntryOffset == 0)
171  break;
172 
173  eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
174  } while (true);
175 
176  ExFreePool(eadata);
177 
178  return ealen;
179  }
180  } else
181  return 0;
182 }
_In_ PIRP Irp
Definition: csq.h:116
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
unsigned short int uint16_t
Definition: acefiex.h:54
Definition: fs.h:78
NTSTATUS NTAPI IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: util.c:191
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
const string EA_EA
Definition: recv.cpp:40
#define EA_EA_HASH
Definition: btrfs_drv.h:107
unsigned int ULONG
Definition: retypes.h:1
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by query_dir_item().

◆ get_reparse_tag()

ULONG get_reparse_tag ( device_extension Vcb,
root subvol,
uint64_t  inode,
uint8_t  type,
ULONG  atts,
bool  lxss,
PIRP  Irp 
)

Definition at line 106 of file dirctrl.c.

106  {
107  fcb* fcb;
108  ULONG tag = 0;
110 
111  if (type == BTRFS_TYPE_SYMLINK)
112  return IO_REPARSE_TAG_SYMLINK;
113  else if (lxss) {
114  if (type == BTRFS_TYPE_SOCKET)
116  else if (type == BTRFS_TYPE_FIFO)
118  else if (type == BTRFS_TYPE_CHARDEV)
120  else if (type == BTRFS_TYPE_BLOCKDEV)
122  }
123 
125  return 0;
126 
128  return 0;
129 
130  Status = open_fcb(Vcb, subvol, inode, type, NULL, false, NULL, &fcb, PagedPool, Irp);
131  if (!NT_SUCCESS(Status)) {
132  ERR("open_fcb returned %08x\n", Status);
133  return 0;
134  }
135 
136  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
137 
139 
140  ExReleaseResourceLite(fcb->Header.Resource);
141 
142  free_fcb(fcb);
143 
144  return tag;
145 }
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:85
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1703
#define IO_REPARSE_TAG_LXSS_FIFO
Definition: btrfs_drv.h:123
_In_ PIRP Irp
Definition: csq.h:116
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:83
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:598
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_TYPE_FIFO
Definition: shellext.h:84
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
Definition: ecma_167.h:138
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:82
Definition: fs.h:78
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
ULONG get_reparse_tag_fcb(fcb *fcb)
Definition: dirctrl.c:82
smooth NULL
Definition: ftsmooth.c:416
#define IO_REPARSE_TAG_LXSS_CHARDEV
Definition: btrfs_drv.h:124
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define IO_REPARSE_TAG_LXSS_SOCKET
Definition: btrfs_drv.h:122
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:272
struct _fcb fcb
Definition: btrfs_drv.h:1301
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
#define IO_REPARSE_TAG_LXSS_BLOCKDEV
Definition: btrfs_drv.h:125
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:80
unsigned int ULONG
Definition: retypes.h:1
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6884
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1065
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:86
char * tag
Definition: main.c:59

Referenced by query_dir_item().

◆ get_reparse_tag_fcb()

ULONG get_reparse_tag_fcb ( fcb fcb)

Definition at line 82 of file dirctrl.c.

82  {
83  ULONG tag;
84 
85  if (fcb->type == BTRFS_TYPE_SYMLINK)
87  else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
88  if (!fcb->reparse_xattr.Buffer || fcb->reparse_xattr.Length < sizeof(ULONG))
89  return 0;
90 
92  } else {
94  ULONG br;
95 
96  Status = read_file(fcb, (uint8_t*)&tag, 0, sizeof(ULONG), &br, NULL);
97  if (!NT_SUCCESS(Status)) {
98  ERR("read_file returned %08x\n", Status);
99  return 0;
100  }
101  }
102 
103  return tag;
104 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
LONG NTSTATUS
Definition: precomp.h:26
Definition: ecma_167.h:138
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:291
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2715
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:280
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
unsigned int ULONG
Definition: retypes.h:1
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:6884
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:86
char * tag
Definition: main.c:59

Referenced by fill_in_file_attribute_information(), fill_in_file_stat_information(), fill_in_file_stat_lx_information(), and get_reparse_tag().

◆ next_dir_entry()

static NTSTATUS next_dir_entry ( file_ref fileref,
uint64_t offset,
dir_entry de,
dir_child **  pdc 
)
static

Definition at line 662 of file dirctrl.c.

662  {
663  LIST_ENTRY* le;
664  dir_child* dc;
665 
666  if (*pdc) {
667  dir_child* dc2 = *pdc;
668 
669  if (dc2->list_entry_index.Flink != &fileref->fcb->dir_children_index)
670  dc = CONTAINING_RECORD(dc2->list_entry_index.Flink, dir_child, list_entry_index);
671  else
672  dc = NULL;
673 
674  goto next;
675  }
676 
677  if (fileref->parent) { // don't return . and .. if root directory
678  if (*offset == 0) {
679  de->key.obj_id = fileref->fcb->inode;
681  de->key.offset = 0;
683  de->name.Buffer = L".";
684  de->name.Length = de->name.MaximumLength = sizeof(WCHAR);
686 
687  *offset = 1;
688  *pdc = NULL;
689 
690  return STATUS_SUCCESS;
691  } else if (*offset == 1) {
692  de->key.obj_id = fileref->parent->fcb->inode;
694  de->key.offset = 0;
696  de->name.Buffer = L"..";
697  de->name.Length = de->name.MaximumLength = sizeof(WCHAR) * 2;
699 
700  *offset = 2;
701  *pdc = NULL;
702 
703  return STATUS_SUCCESS;
704  }
705  }
706 
707  if (*offset < 2)
708  *offset = 2;
709 
710  dc = NULL;
711  le = fileref->fcb->dir_children_index.Flink;
712 
713  // skip entries before offset
714  while (le != &fileref->fcb->dir_children_index) {
715  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
716 
717  if (dc2->index >= *offset) {
718  dc = dc2;
719  break;
720  }
721 
722  le = le->Flink;
723  }
724 
725 next:
726  if (!dc)
727  return STATUS_NO_MORE_FILES;
728 
729  de->key = dc->key;
730  de->name = dc->name;
731  de->type = dc->type;
733  de->dc = dc;
734 
735  *offset = dc->index + 1;
736  *pdc = dc;
737 
738  return STATUS_SUCCESS;
739 }
struct _file_ref * parent
Definition: btrfs_drv.h:346
uint64_t obj_id
Definition: btrfs.h:127
uint8_t obj_type
Definition: btrfs.h:128
USHORT MaximumLength
Definition: env_spec_w32.h:370
GLintptr offset
Definition: glext.h:5920
uint8_t type
Definition: dirctrl.c:77
enum DirEntryType dir_entry_type
Definition: dirctrl.c:78
HDC dc
Definition: cylfrac.c:34
uint64_t offset
Definition: btrfs.h:129
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LIST_ENTRY dir_children_index
Definition: btrfs_drv.h:303
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
uint64_t inode
Definition: btrfs_drv.h:278
LIST_ENTRY list_entry_index
Definition: btrfs_drv.h:251
static const WCHAR L[]
Definition: oid.c:1250
uint64_t index
Definition: btrfs_drv.h:242
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
fcb * fcb
Definition: btrfs_drv.h:335
Definition: typedefs.h:117
dir_child * dc
Definition: dirctrl.c:79
static unsigned __int64 next
Definition: rand_nt.c:6
KEY key
Definition: dirctrl.c:75
return STATUS_SUCCESS
Definition: btrfs.c:2966
UNICODE_STRING name
Definition: dirctrl.c:76

Referenced by query_directory().

◆ notify_change_directory()

static NTSTATUS notify_change_directory ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 1083 of file dirctrl.c.

1083  {
1086  fcb* fcb = FileObject->FsContext;
1087  ccb* ccb = FileObject->FsContext2;
1088  file_ref* fileref = ccb ? ccb->fileref : NULL;
1089  NTSTATUS Status;
1090 
1091  TRACE("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
1092 
1093  if (!ccb) {
1094  ERR("ccb was NULL\n");
1095  return STATUS_INVALID_PARAMETER;
1096  }
1097 
1098  if (!fileref) {
1099  ERR("no fileref\n");
1100  return STATUS_INVALID_PARAMETER;
1101  }
1102 
1103  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_LIST_DIRECTORY)) {
1104  WARN("insufficient privileges\n");
1105  return STATUS_ACCESS_DENIED;
1106  }
1107 
1108  ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
1109  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
1110 
1111  if (fcb->type != BTRFS_TYPE_DIRECTORY) {
1113  goto end;
1114  }
1115 
1116  // FIXME - raise exception if FCB marked for deletion?
1117 
1118  TRACE("%S\n", file_desc(FileObject));
1119 
1120  if (ccb->filename.Length == 0) {
1121  ULONG reqlen;
1122 
1124 
1125  Status = fileref_get_filename(fileref, &ccb->filename, NULL, &reqlen);
1126  if (Status == STATUS_BUFFER_OVERFLOW) {
1128  if (!ccb->filename.Buffer) {
1129  ERR("out of memory\n");
1131  goto end;
1132  }
1133 
1134  ccb->filename.MaximumLength = (uint16_t)reqlen;
1135 
1136  Status = fileref_get_filename(fileref, &ccb->filename, NULL, &reqlen);
1137  if (!NT_SUCCESS(Status)) {
1138  ERR("fileref_get_filename returned %08x\n", Status);
1139  goto end;
1140  }
1141  } else {
1142  ERR("fileref_get_filename returned %08x\n", Status);
1143  goto end;
1144  }
1145  }
1146 
1147  FsRtlNotifyFilterChangeDirectory(Vcb->NotifySync, &Vcb->DirNotifyList, FileObject->FsContext2, (PSTRING)&ccb->filename,
1148  IrpSp->Flags & SL_WATCH_TREE, false, IrpSp->Parameters.NotifyDirectory.CompletionFilter, Irp,
1149  NULL, NULL, NULL);
1150 
1152 
1153 end:
1154  ExReleaseResourceLite(fcb->Header.Resource);
1155  ExReleaseResourceLite(&fcb->Vcb->tree_lock);
1156 
1157  return Status;
1158 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS fileref_get_filename(file_ref *fileref, PUNICODE_STRING fn, USHORT *name_offset, ULONG *preqlen)
Definition: fileinfo.c:3172
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:377
#define uint16_t
Definition: nsiface.idl:60
UNICODE_STRING filename
Definition: btrfs_drv.h:379
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:81
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:280
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:272
#define TRACE(s)
Definition: solgame.cpp:4
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define Vcb
Definition: cdprocs.h:1425
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define SL_WATCH_TREE
Definition: iotypes.h:1796
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
unsigned int ULONG
Definition: retypes.h:1
file_ref * fileref
Definition: btrfs_drv.h:378
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
struct _device_extension * Vcb
Definition: btrfs_drv.h:276
_Ret_z_ WCHAR * file_desc(_In_ PFILE_OBJECT FileObject)
Definition: btrfs.c:1529
VOID NTAPI FsRtlNotifyFilterChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL, IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL)
Definition: notify.c:749

Referenced by _Dispatch_type_().

◆ query_dir_item()

static NTSTATUS query_dir_item ( fcb fcb,
ccb ccb,
void buf,
LONG len,
PIRP  Irp,
dir_entry de,
root r 
)
static

Definition at line 184 of file dirctrl.c.

184  {
186  LONG needed;
187  uint64_t inode;
188  INODE_ITEM ii;
190  ULONG atts = 0, ealen = 0;
191  file_ref* fileref = ccb->fileref;
192 
194 
195  if (de->key.obj_type == TYPE_ROOT_ITEM) { // subvol
196  LIST_ENTRY* le;
197 
198  r = NULL;
199 
200  le = fcb->Vcb->roots.Flink;
201  while (le != &fcb->Vcb->roots) {
202  root* subvol = CONTAINING_RECORD(le, root, list_entry);
203 
204  if (subvol->id == de->key.obj_id) {
205  r = subvol;
206  break;
207  }
208 
209  le = le->Flink;
210  }
211 
212  if (r && r->parent != fcb->subvol->id)
213  r = NULL;
214 
216  } else {
217  inode = de->key.obj_id;
218  }
219 
220  if (IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation) { // FIXME - object ID and reparse point classes too?
221  switch (de->dir_entry_type) {
222  case DirEntryType_File:
223  {
224  if (!r) {
226 
227  ii = fcb->Vcb->dummy_fcb->inode_item;
228  atts = fcb->Vcb->dummy_fcb->atts;
229  ealen = fcb->Vcb->dummy_fcb->ealen;
230 
233  ii.st_atime = ii.st_mtime = ii.st_ctime = ii.otime;
234  } else {
235  bool found = false;
236 
237  if (de->dc && de->dc->fileref && de->dc->fileref->fcb) {
238  ii = de->dc->fileref->fcb->inode_item;
239  atts = de->dc->fileref->fcb->atts;
240  ealen = de->dc->fileref->fcb->ealen;
241  found = true;
242  }
243 
244  if (!found) {
245  KEY searchkey;
247 
248  searchkey.obj_id = inode;
249  searchkey.obj_type = TYPE_INODE_ITEM;
250  searchkey.offset = 0xffffffffffffffff;
251 
252  Status = find_item(fcb->Vcb, r, &tp, &searchkey, false, Irp);
253  if (!NT_SUCCESS(Status)) {
254  ERR("error - find_item returned %08x\n", Status);
255  return Status;
256  }
257 
258  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
259  ERR("could not find inode item for inode %I64x in root %I64x\n", inode, r->id);
260  return STATUS_INTERNAL_ERROR;
261  }
262 
263  RtlZeroMemory(&ii, sizeof(INODE_ITEM));
264 
265  if (tp.item->size > 0)
266  RtlCopyMemory(&ii, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size));
267 
268  if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
269  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation ||
270  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
271  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
272  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
273  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
274  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
275 
276  bool dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.';
277 
278  atts = get_file_attributes(fcb->Vcb, r, inode, de->type, dotfile, false, Irp);
279  }
280 
281  if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
282  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
283  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
284  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
285  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
286  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
287  ealen = get_ea_len(fcb->Vcb, r, inode, Irp);
288  }
289  }
290  }
291 
292  break;
293  }
294 
295  case DirEntryType_Self:
296  ii = fcb->inode_item;
297  r = fcb->subvol;
298  inode = fcb->inode;
299  atts = fcb->atts;
300  ealen = fcb->ealen;
301  break;
302 
303  case DirEntryType_Parent:
304  if (fileref && fileref->parent) {
305  ii = fileref->parent->fcb->inode_item;
306  r = fileref->parent->fcb->subvol;
307  inode = fileref->parent->fcb->inode;
308  atts = fileref->parent->fcb->atts;
309  ealen = fileref->parent->fcb->ealen;
310  } else {
311  ERR("no fileref\n");
312  return STATUS_INTERNAL_ERROR;
313  }
314  break;
315  }
316 
317  if (atts == 0)
319  }
320 
321  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
323  {
325 
326  TRACE("FileBothDirectoryInformation\n");
327 
328  needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
329 
330  if (needed > *len) {
331  TRACE("buffer overflow - %u > %u\n", needed, *len);
332  return STATUS_BUFFER_OVERFLOW;
333  }
334 
335  fbdi->NextEntryOffset = 0;
336  fbdi->FileIndex = 0;
341  fbdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
342 
343  if (de->type == BTRFS_TYPE_SYMLINK)
344  fbdi->AllocationSize.QuadPart = 0;
345  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
346  fbdi->AllocationSize.QuadPart = ii.st_blocks;
347  else
348  fbdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
349 
350  fbdi->FileAttributes = atts;
351  fbdi->FileNameLength = de->name.Length;
352  fbdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen;
353  fbdi->ShortNameLength = 0;
354 
355  RtlCopyMemory(fbdi->FileName, de->name.Buffer, de->name.Length);
356 
357  *len -= needed;
358 
359  return STATUS_SUCCESS;
360  }
361 
363  {
365 
366  TRACE("FileDirectoryInformation\n");
367 
368  needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + de->name.Length;
369 
370  if (needed > *len) {
371  TRACE("buffer overflow - %u > %u\n", needed, *len);
372  return STATUS_BUFFER_OVERFLOW;
373  }
374 
375  fdi->NextEntryOffset = 0;
376  fdi->FileIndex = 0;
381  fdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
382 
383  if (de->type == BTRFS_TYPE_SYMLINK)
384  fdi->AllocationSize.QuadPart = 0;
385  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
387  else
388  fdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
389 
390  fdi->FileAttributes = atts;
391  fdi->FileNameLength = de->name.Length;
392 
393  RtlCopyMemory(fdi->FileName, de->name.Buffer, de->name.Length);
394 
395  *len -= needed;
396 
397  return STATUS_SUCCESS;
398  }
399 
401  {
403 
404  TRACE("FileFullDirectoryInformation\n");
405 
406  needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
407 
408  if (needed > *len) {
409  TRACE("buffer overflow - %u > %u\n", needed, *len);
410  return STATUS_BUFFER_OVERFLOW;
411  }
412 
413  ffdi->NextEntryOffset = 0;
414  ffdi->FileIndex = 0;
419  ffdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
420 
421  if (de->type == BTRFS_TYPE_SYMLINK)
422  ffdi->AllocationSize.QuadPart = 0;
423  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
424  ffdi->AllocationSize.QuadPart = ii.st_blocks;
425  else
426  ffdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
427 
428  ffdi->FileAttributes = atts;
429  ffdi->FileNameLength = de->name.Length;
430  ffdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen;
431 
432  RtlCopyMemory(ffdi->FileName, de->name.Buffer, de->name.Length);
433 
434  *len -= needed;
435 
436  return STATUS_SUCCESS;
437  }
438 
440  {
442 
443  TRACE("FileIdBothDirectoryInformation\n");
444 
445  needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
446 
447  if (needed > *len) {
448  TRACE("buffer overflow - %u > %u\n", needed, *len);
449  return STATUS_BUFFER_OVERFLOW;
450  }
451 
452  fibdi->NextEntryOffset = 0;
453  fibdi->FileIndex = 0;
458  fibdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
459 
460  if (de->type == BTRFS_TYPE_SYMLINK)
461  fibdi->AllocationSize.QuadPart = 0;
462  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
463  fibdi->AllocationSize.QuadPart = ii.st_blocks;
464  else
465  fibdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
466 
467  fibdi->FileAttributes = atts;
468  fibdi->FileNameLength = de->name.Length;
469  fibdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen;
470  fibdi->ShortNameLength = 0;
471  fibdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode);
472 
473  RtlCopyMemory(fibdi->FileName, de->name.Buffer, de->name.Length);
474 
475  *len -= needed;
476 
477  return STATUS_SUCCESS;
478  }
479 
481  {
483 
484  TRACE("FileIdFullDirectoryInformation\n");
485 
486  needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
487 
488  if (needed > *len) {
489  TRACE("buffer overflow - %u > %u\n", needed, *len);
490  return STATUS_BUFFER_OVERFLOW;
491  }
492 
493  fifdi->NextEntryOffset = 0;
494  fifdi->FileIndex = 0;
499  fifdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
500 
501  if (de->type == BTRFS_TYPE_SYMLINK)
502  fifdi->AllocationSize.QuadPart = 0;
503  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
504  fifdi->AllocationSize.QuadPart = ii.st_blocks;
505  else
506  fifdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
507 
508  fifdi->FileAttributes = atts;
509  fifdi->FileNameLength = de->name.Length;
510  fifdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen;
511  fifdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode);
512 
513  RtlCopyMemory(fifdi->FileName, de->name.Buffer, de->name.Length);
514 
515  *len -= needed;
516 
517  return STATUS_SUCCESS;
518  }
519 
520 #ifndef _MSC_VER
521 #pragma GCC diagnostic push
522 #pragma GCC diagnostic ignored "-Wswitch"
523 #endif
524 #if (NTDDI_VERSION >= NTDDI_VISTA)
526  {
528 
529  TRACE("FileIdExtdDirectoryInformation\n");
530 
532 
533  if (needed > *len) {
534  TRACE("buffer overflow - %u > %u\n", needed, *len);
535  return STATUS_BUFFER_OVERFLOW;
536  }
537 
538  fiedi->NextEntryOffset = 0;
539  fiedi->FileIndex = 0;
544  fiedi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
545 
546  if (de->type == BTRFS_TYPE_SYMLINK)
547  fiedi->AllocationSize.QuadPart = 0;
548  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
549  fiedi->AllocationSize.QuadPart = ii.st_blocks;
550  else
551  fiedi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
552 
553  fiedi->FileAttributes = atts;
554  fiedi->FileNameLength = de->name.Length;
555  fiedi->EaSize = ealen;
556  fiedi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
557 
558  RtlCopyMemory(&fiedi->FileId.Identifier[0], &fcb->inode, sizeof(uint64_t));
559  RtlCopyMemory(&fiedi->FileId.Identifier[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
560 
561  RtlCopyMemory(fiedi->FileName, de->name.Buffer, de->name.Length);
562 
563  *len -= needed;
564 
565  return STATUS_SUCCESS;
566  }
567 
569  {
571 
572  TRACE("FileIdExtdBothDirectoryInformation\n");
573 
575 
576  if (needed > *len) {
577  TRACE("buffer overflow - %u > %u\n", needed, *len);
578  return STATUS_BUFFER_OVERFLOW;
579  }
580 
581  fiebdi->NextEntryOffset = 0;
582  fiebdi->FileIndex = 0;
587  fiebdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
588 
589  if (de->type == BTRFS_TYPE_SYMLINK)
590  fiebdi->AllocationSize.QuadPart = 0;
591  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
592  fiebdi->AllocationSize.QuadPart = ii.st_blocks;
593  else
594  fiebdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
595 
596  fiebdi->FileAttributes = atts;
597  fiebdi->FileNameLength = de->name.Length;
598  fiebdi->EaSize = ealen;
599  fiebdi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
600 
601  RtlCopyMemory(&fiebdi->FileId.Identifier[0], &fcb->inode, sizeof(uint64_t));
602  RtlCopyMemory(&fiebdi->FileId.Identifier[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
603 
604  fiebdi->ShortNameLength = 0;
605 
606  RtlCopyMemory(fiebdi->FileName, de->name.Buffer, de->name.Length);
607 
608  *len -= needed;
609 
610  return STATUS_SUCCESS;
611  }
612 #endif
613 
614 #ifndef _MSC_VER
615 #pragma GCC diagnostic pop
616 #endif
617 
619  {
621 
622  TRACE("FileNamesInformation\n");
623 
624  needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + de->name.Length;
625 
626  if (needed > *len) {
627  TRACE("buffer overflow - %u > %u\n", needed, *len);
628  return STATUS_BUFFER_OVERFLOW;
629  }
630 
631  fni->NextEntryOffset = 0;
632  fni->FileIndex = 0;
633  fni->FileNameLength = de->name.Length;
634 
635  RtlCopyMemory(fni->FileName, de->name.Buffer, de->name.Length);
636 
637  *len -= needed;
638 
639  return STATUS_SUCCESS;
640  }
641 
643  FIXME("STUB: FileObjectIdInformation\n");
644  return STATUS_NOT_IMPLEMENTED;
645 
647  FIXME("STUB: FileQuotaInformation\n");
648  return STATUS_NOT_IMPLEMENTED;
649 
651  FIXME("STUB: FileReparsePointInformation\n");
652  return STATUS_NOT_IMPLEMENTED;
653 
654  default:
655  WARN("Unknown FileInformationClass %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
656  return STATUS_NOT_IMPLEMENTED;
657  }
658 
659  return STATUS_NO_MORE_FILES;
660 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
LARGE_INTEGER AllocationSize
Definition: iotypes.h:5368
struct _file_ref * parent
Definition: btrfs_drv.h:346
LARGE_INTEGER LastAccessTime
Definition: winternl.h:517
uint64_t obj_id
Definition: btrfs.h:127
LARGE_INTEGER AllocationSize
Definition: iotypes.h:5401
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _file_ref * fileref
Definition: btrfs_drv.h:250
uint8_t obj_type
Definition: btrfs.h:128
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
BTRFS_TIME otime
Definition: btrfs.h:285
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:409
uint8_t type
Definition: dirctrl.c:77
struct _FILE_FULL_DIRECTORY_INFORMATION FILE_FULL_DIR_INFORMATION
enum DirEntryType dir_entry_type
Definition: dirctrl.c:78
__u16 time
Definition: mkdosfs.c:366
#define FileIdExtdDirectoryInformation
Definition: dirctrl.c:23
BTRFS_TIME st_ctime
Definition: btrfs.h:283
uint64_t offset
Definition: btrfs.h:129
uint8_t * data
Definition: btrfs_drv.h:410
LARGE_INTEGER AllocationSize
Definition: dirctrl.c:34
Definition: fs.h:78
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
LARGE_INTEGER ChangeTime
Definition: dirctrl.c:32
LARGE_INTEGER ChangeTime
Definition: winternl.h:519
static __inline uint64_t make_file_id(root *r, uint64_t inode)
Definition: btrfs_drv.h:976
LARGE_INTEGER LastWriteTime
Definition: from_kernel.h:143
uint64_t id
Definition: btrfs_drv.h:446
long LONG
Definition: pedump.c:60
LARGE_INTEGER EndOfFile
Definition: winternl.h:520
#define FIXME(fmt,...)
Definition: debug.h:110
LARGE_INTEGER AllocationSize
Definition: from_kernel.h:146
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define FileIdExtdBothDirectoryInformation
Definition: dirctrl.c:24
struct _FILE_BOTH_DIR_INFORMATION FILE_BOTH_DIR_INFORMATION
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
BTRFS_TIME st_mtime
Definition: btrfs.h:284
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static __inline uint64_t unix_time_to_win(BTRFS_TIME *t)
Definition: recv.cpp:1180
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2883
LARGE_INTEGER LastWriteTime
Definition: iotypes.h:5398
ULONG ealen
Definition: btrfs_drv.h:293
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
uint64_t st_size
Definition: btrfs.h:271
#define TRACE(s)
Definition: solgame.cpp:4
LARGE_INTEGER EndOfFile
Definition: dirctrl.c:33
__wchar_t WCHAR
Definition: xmlstorage.h:180
ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t inode, _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp)
Definition: btrfs.c:2603
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
uint64_t inode
Definition: btrfs_drv.h:278
#define Vcb
Definition: cdprocs.h:1425
LARGE_INTEGER LastWriteTime
Definition: winternl.h:518
UCHAR Identifier[16]
Definition: btrfs_drv.h:152
BTRFS_TIME st_atime
Definition: btrfs.h:282
LARGE_INTEGER CreationTime
Definition: iotypes.h:5363
ULONG get_reparse_tag(device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, ULONG atts, bool lxss, PIRP Irp)
Definition: dirctrl.c:106
struct _FILE_NAMES_INFORMATION FILE_NAMES_INFORMATION
tree_data * item
Definition: btrfs_drv.h:496
LARGE_INTEGER LastAccessTime
Definition: dirctrl.c:30
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define TYPE_INODE_ITEM
Definition: btrfs.h:19
GLenum GLsizei len
Definition: glext.h:6722
static ULONG get_ea_len(device_extension *Vcb, root *subvol, uint64_t inode, PIRP Irp)
Definition: dirctrl.c:147
struct _FILE_DIRECTORY_INFORMATION FILE_DIRECTORY_INFORMATION
Definition: typedefs.h:117
LARGE_INTEGER CreationTime
Definition: iotypes.h:5396
INODE_ITEM inode_item
Definition: btrfs_drv.h:281
uint64_t st_blocks
Definition: btrfs.h:272
Status
Definition: gdiplustypes.h:24
LARGE_INTEGER CreationTime
Definition: dirctrl.c:29
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:126
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
dir_child * dc
Definition: dirctrl.c:79
UINT64 uint64_t
Definition: types.h:77
ULONG atts
Definition: btrfs_drv.h:286
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
LARGE_INTEGER LastWriteTime
Definition: dirctrl.c:31
KEY key
Definition: dirctrl.c:75
LARGE_INTEGER CreationTime
Definition: winternl.h:516
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
struct _root * subvol
Definition: btrfs_drv.h:277
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
LARGE_INTEGER CreationTime
Definition: from_kernel.h:141
struct _FILE_ID_BOTH_DIR_INFORMATION FILE_ID_BOTH_DIR_INFORMATION
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:953
struct _FILE_ID_FULL_DIR_INFORMATION FILE_ID_FULL_DIR_INFORMATION
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
LARGE_INTEGER LastAccessTime
Definition: from_kernel.h:142
bool lxss
Definition: btrfs_drv.h:386
file_ref * fileref
Definition: btrfs_drv.h:378
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
WCHAR FileName[ANYSIZE_ARRAY]
Definition: winternl.h:524
return STATUS_SUCCESS
Definition: btrfs.c:2966
LARGE_INTEGER LastWriteTime
Definition: iotypes.h:5365
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
LARGE_INTEGER LastAccessTime
Definition: iotypes.h:5397
struct _device_extension * Vcb
Definition: btrfs_drv.h:276
LARGE_INTEGER AllocationSize
Definition: winternl.h:521
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1065
LONGLONG QuadPart
Definition: typedefs.h:112
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:86
UNICODE_STRING name
Definition: dirctrl.c:76
LARGE_INTEGER LastAccessTime
Definition: iotypes.h:5364
WCHAR FileName[ANYSIZE_ARRAY]
Definition: winternl.h:539

Referenced by query_directory().

◆ query_directory()

static NTSTATUS query_directory ( PIRP  Irp)
static

Definition at line 741 of file dirctrl.c.

741  {
743  NTSTATUS Status, status2;
744  fcb* fcb;
745  ccb* ccb;
746  file_ref* fileref;
748  void* buf;
749  uint8_t *curitem, *lastitem;
750  LONG length;
751  ULONG count;
752  bool has_wildcard = false, specific_file = false, initial;
753  dir_entry de;
754  uint64_t newoffset;
755  dir_child* dc = NULL;
756 
757  TRACE("query directory\n");
758 
760  fcb = IrpSp->FileObject->FsContext;
761  ccb = IrpSp->FileObject->FsContext2;
762  fileref = ccb ? ccb->fileref : NULL;
763 
764  if (!fileref)
766 
767  if (!ccb) {
768  ERR("ccb was NULL\n");
770  }
771 
772  if (!fcb) {
773  ERR("fcb was NULL\n");
775  }
776 
777  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_LIST_DIRECTORY)) {
778  WARN("insufficient privileges\n");
779  return STATUS_ACCESS_DENIED;
780  }
781 
782  Vcb = fcb->Vcb;
783 
784  if (!Vcb) {
785  ERR("Vcb was NULL\n");
787  }
788 
789  if (fileref->fcb == Vcb->dummy_fcb)
790  return STATUS_NO_MORE_FILES;
791 
792  if (IrpSp->Flags == 0) {
793  TRACE("QD flags: (none)\n");
794  } else {
795  ULONG flags = IrpSp->Flags;
796 
797  TRACE("QD flags:\n");
798 
799  if (flags & SL_INDEX_SPECIFIED) {
800  TRACE(" SL_INDEX_SPECIFIED\n");
802  }
803 
804  if (flags & SL_RESTART_SCAN) {
805  TRACE(" SL_RESTART_SCAN\n");
807  }
808 
810  TRACE(" SL_RETURN_SINGLE_ENTRY\n");
812  }
813 
814  if (flags != 0)
815  TRACE(" unknown flags: %u\n", flags);
816  }
817 
818  if (IrpSp->Flags & SL_RESTART_SCAN) {
819  ccb->query_dir_offset = 0;
820 
821  if (ccb->query_string.Buffer) {
824  }
825 
826  ccb->has_wildcard = false;
827  ccb->specific_file = false;
828  }
829 
830  initial = !ccb->query_string.Buffer;
831 
832  if (IrpSp->Parameters.QueryDirectory.FileName && IrpSp->Parameters.QueryDirectory.FileName->Length > 1) {
833  TRACE("QD filename: %.*S\n", IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR), IrpSp->Parameters.QueryDirectory.FileName->Buffer);
834 
835  if (IrpSp->Parameters.QueryDirectory.FileName->Length > sizeof(WCHAR) || IrpSp->Parameters.QueryDirectory.FileName->Buffer[0] != L'*') {
836  specific_file = true;
837 
838  if (FsRtlDoesNameContainWildCards(IrpSp->Parameters.QueryDirectory.FileName)) {
839  has_wildcard = true;
840  specific_file = false;
841  }
842  }
843 
844  if (ccb->query_string.Buffer)
846 
847  if (has_wildcard)
848  RtlUpcaseUnicodeString(&ccb->query_string, IrpSp->Parameters.QueryDirectory.FileName, true);
849  else {
850  ccb->query_string.Buffer = ExAllocatePoolWithTag(PagedPool, IrpSp->Parameters.QueryDirectory.FileName->Length, ALLOC_TAG);
851  if (!ccb->query_string.Buffer) {
852  ERR("out of memory\n");
854  }
855 
856  ccb->query_string.Length = ccb->query_string.MaximumLength = IrpSp->Parameters.QueryDirectory.FileName->Length;
857  RtlCopyMemory(ccb->query_string.Buffer, IrpSp->Parameters.QueryDirectory.FileName->Buffer, IrpSp->Parameters.QueryDirectory.FileName->Length);
858  }
859 
860  ccb->has_wildcard = has_wildcard;
861  ccb->specific_file = specific_file;
862  } else {
863  has_wildcard = ccb->has_wildcard;
864  specific_file = ccb->specific_file;
865 
866  if (!(IrpSp->Flags & SL_RESTART_SCAN)) {
867  initial = false;
868 
869  if (specific_file)
870  return STATUS_NO_MORE_FILES;
871  }
872  }
873 
874  if (ccb->query_string.Buffer) {
875  TRACE("query string = %.*S\n", ccb->query_string.Length / sizeof(WCHAR), ccb->query_string.Buffer);
876  }
877 
878  newoffset = ccb->query_dir_offset;
879 
880  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
881 
882  ExAcquireResourceSharedLite(&fileref->fcb->nonpaged->dir_children_lock, true);
883 
884  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
885 
886  if (!NT_SUCCESS(Status)) {
887  if (Status == STATUS_NO_MORE_FILES && initial)
889  goto end;
890  }
891 
892  ccb->query_dir_offset = newoffset;
893 
895 
896  if (Irp->MdlAddress && !buf) {
897  ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
899  goto end;
900  }
901 
902  length = IrpSp->Parameters.QueryDirectory.Length;
903 
904  if (specific_file) {
905  bool found = false;
907  LIST_ENTRY* le;
908  uint32_t hash;
909  uint8_t c;
910 
911  us.Buffer = NULL;
912 
913  if (!ccb->case_sensitive) {
915  if (!NT_SUCCESS(Status)) {
916  ERR("RtlUpcaseUnicodeString returned %08x\n", Status);
917  goto end;
918  }
919 
920  hash = calc_crc32c(0xffffffff, (uint8_t*)us.Buffer, us.Length);
921  } else
923 
924  c = hash >> 24;
925 
926  if (ccb->case_sensitive) {
927  if (fileref->fcb->hash_ptrs[c]) {
928  le = fileref->fcb->hash_ptrs[c];
929  while (le != &fileref->fcb->dir_children_hash) {
930  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash);
931 
932  if (dc2->hash == hash) {
934  found = true;
935 
936  de.key = dc2->key;
937  de.name = dc2->name;
938  de.type = dc2->type;
940  de.dc = dc2;
941 
942  break;
943  }
944  } else if (dc2->hash > hash)
945  break;
946 
947  le = le->Flink;
948  }
949  }
950  } else {
951  if (fileref->fcb->hash_ptrs_uc[c]) {
952  le = fileref->fcb->hash_ptrs_uc[c];
953  while (le != &fileref->fcb->dir_children_hash_uc) {
954  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
955 
956  if (dc2->hash_uc == hash) {
957  if (dc2->name_uc.Length == us.Length && RtlCompareMemory(dc2->name_uc.Buffer, us.Buffer, us.Length) == us.Length) {
958  found = true;
959 
960  de.key = dc2->key;
961  de.name = dc2->name;
962  de.type = dc2->type;
964  de.dc = dc2;
965 
966  break;
967  }
968  } else if (dc2->hash_uc > hash)
969  break;
970 
971  le = le->Flink;
972  }
973  }
974  }
975 
976  if (us.Buffer)
977  ExFreePool(us.Buffer);
978 
979  if (!found) {
981  goto end;
982  }
983  } else if (has_wildcard) {
985  newoffset = ccb->query_dir_offset;
986  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
987 
988  if (NT_SUCCESS(Status))
989  ccb->query_dir_offset = newoffset;
990  else {
991  if (Status == STATUS_NO_MORE_FILES && initial)
993 
994  goto end;
995  }
996  }
997  }
998 
999  TRACE("file(0) = %.*S\n", de.name.Length / sizeof(WCHAR), de.name.Buffer);
1000  TRACE("offset = %u\n", ccb->query_dir_offset - 1);
1001 
1002  Status = query_dir_item(fcb, ccb, buf, &length, Irp, &de, fcb->subvol);
1003 
1004  count = 0;
1005  if (NT_SUCCESS(Status) && !(IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) && !specific_file) {
1006  lastitem = (uint8_t*)buf;
1007 
1008  while (length > 0) {
1009  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
1010 #ifndef _MSC_VER
1011 #pragma GCC diagnostic push
1012 #pragma GCC diagnostic ignored "-Wswitch"
1013 #endif
1021  length -= length % 8;
1022  break;
1023 #ifndef _MSC_VER
1024 #pragma GCC diagnostic pop
1025 #endif
1026 
1027  case FileNamesInformation:
1028  length -= length % 4;
1029  break;
1030 
1031  default:
1032  WARN("unhandled file information class %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
1033  break;
1034  }
1035 
1036  if (length > 0) {
1037  newoffset = ccb->query_dir_offset;
1038  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
1039  if (NT_SUCCESS(Status)) {
1040  if (!has_wildcard || FsRtlIsNameInExpression(&ccb->query_string, &de.name, !ccb->case_sensitive, NULL)) {
1041  curitem = (uint8_t*)buf + IrpSp->Parameters.QueryDirectory.Length - length;
1042  count++;
1043 
1044  TRACE("file(%u) %u = %.*S\n", count, curitem - (uint8_t*)buf, de.name.Length / sizeof(WCHAR), de.name.Buffer);
1045  TRACE("offset = %u\n", ccb->query_dir_offset - 1);
1046 
1047  status2 = query_dir_item(fcb, ccb, curitem, &length, Irp, &de, fcb->subvol);
1048 
1049  if (NT_SUCCESS(status2)) {
1050  ULONG* lastoffset = (ULONG*)lastitem;
1051 
1052  *lastoffset = (ULONG)(curitem - lastitem);
1053  ccb->query_dir_offset = newoffset;
1054 
1055  lastitem = curitem;
1056  } else
1057  break;
1058  } else
1059  ccb->query_dir_offset = newoffset;
1060  } else {
1063 
1064  break;
1065  }
1066  } else
1067  break;
1068  }
1069  }
1070 
1071  Irp->IoStatus.Information = IrpSp->Parameters.QueryDirectory.Length - length;
1072 
1073 end:
1074  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1075 
1076  ExReleaseResourceLite(&Vcb->tree_lock);
1077 
1078  TRACE("returning %08x\n", Status);
1079 
1080  return Status;
1081 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1794
USHORT MaximumLength
Definition: env_spec_w32.h:370
UNICODE_STRING name_uc
Definition: btrfs_drv.h:248
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
static const BYTE us[]
Definition: encode.c:689
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
uint8_t type
Definition: dirctrl.c:77
static NTSTATUS query_dir_item(fcb *fcb, ccb *ccb, void *buf, LONG *len, PIRP Irp, dir_entry *de, root *r)
Definition: dirctrl.c:184
uint32_t hash
Definition: btrfs_drv.h:245
enum DirEntryType dir_entry_type
Definition: dirctrl.c:78
HDC dc
Definition: cylfrac.c:34
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:377
#define FileIdExtdDirectoryInformation
Definition: dirctrl.c:23
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
bool has_wildcard
Definition: btrfs_drv.h:372
UNICODE_STRING query_string
Definition: btrfs_drv.h:371
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint32_t hash_uc
Definition: btrfs_drv.h:247
int hash
Definition: main.c:58
long LONG
Definition: pedump.c:60
bool specific_file
Definition: btrfs_drv.h:373
LIST_ENTRY ** hash_ptrs_uc
Definition: btrfs_drv.h:307
smooth NULL
Definition: ftsmooth.c:416
#define FileIdExtdBothDirectoryInformation
Definition: dirctrl.c:24
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
LIST_ENTRY dir_children_hash_uc
Definition: btrfs_drv.h:305
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
struct _fcb fcb
Definition: btrfs_drv.h:1301
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:941
const GLubyte * c
Definition: glext.h:8905
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLbitfield flags
Definition: glext.h:7161
static NTSTATUS next_dir_entry(file_ref *fileref, uint64_t *offset, dir_entry *de, dir_child **pdc)
Definition: dirctrl.c:662
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const WCHAR L[]
Definition: oid.c:1250
bool case_sensitive
Definition: btrfs_drv.h:381
fcb * fcb
Definition: btrfs_drv.h:335
Definition: typedefs.h:117
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1793
dir_child * dc
Definition: dirctrl.c:79
UINT64 uint64_t
Definition: types.h:77
struct _fcb_nonpaged * nonpaged
Definition: btrfs_drv.h:273
KEY key
Definition: dirctrl.c:75
uint8_t type
Definition: btrfs_drv.h:243
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
struct _root * subvol
Definition: btrfs_drv.h:277
UINT32 uint32_t
Definition: types.h:75
#define SL_RESTART_SCAN
Definition: iotypes.h:1792
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
Definition: dirctrl.c:74
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
LIST_ENTRY ** hash_ptrs
Definition: btrfs_drv.h:306
LIST_ENTRY dir_children_hash
Definition: btrfs_drv.h:304
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:378
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2966
Definition: _hash_fun.h:40
uint64_t query_dir_offset
Definition: btrfs_drv.h:370
struct _device_extension * Vcb
Definition: btrfs_drv.h:276
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
UNICODE_STRING name
Definition: btrfs_drv.h:246
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
UNICODE_STRING name
Definition: dirctrl.c:76

Referenced by _Dispatch_type_().