ReactOS  0.4.15-dev-5463-g138eb58
dirctrl.c File Reference
#include "btrfs_drv.h"
#include "crc32c.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 25 of file dirctrl.c.

◆ FileIdExtdDirectoryInformation

#define FileIdExtdDirectoryInformation   (enum _FILE_INFORMATION_CLASS)60

Definition at line 24 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 69 of file dirctrl.c.

Function Documentation

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_DIRECTORY_CONTROL  )

Definition at line 1157 of file dirctrl.c.

1159  {
1161  NTSTATUS Status;
1162  ULONG func;
1163  bool top_level;
1164  device_extension* Vcb = DeviceObject->DeviceExtension;
1165 
1167 
1168  TRACE("directory control\n");
1169 
1170  top_level = is_top_level(Irp);
1171 
1172  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
1174  goto end;
1175  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
1177  goto end;
1178  }
1179 
1181 
1182  Irp->IoStatus.Information = 0;
1183 
1185 
1186  switch (func) {
1189  break;
1190 
1193  break;
1194 
1195  default:
1196  WARN("unknown minor %lu\n", func);
1198  Irp->IoStatus.Status = Status;
1199  break;
1200  }
1201 
1202  if (Status == STATUS_PENDING)
1203  goto exit;
1204 
1205 end:
1206  Irp->IoStatus.Status = Status;
1207 
1209 
1210 exit:
1211  TRACE("returning %08lx\n", Status);
1212 
1213  if (top_level)
1215 
1217 
1218  return Status;
1219 }
GLenum func
Definition: glext.h:6028
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
static NTSTATUS query_directory(PIRP Irp)
Definition: dirctrl.c:737
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
return STATUS_NOT_IMPLEMENTED
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
#define IoCompleteRequest
Definition: irp.c:1240
Status
Definition: gdiplustypes.h:24
#define TRACE(s)
Definition: solgame.cpp:4
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
#define Vcb
Definition: cdprocs.h:1415
GLuint GLuint end
Definition: gl.h:1545
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
static NTSTATUS notify_change_directory(device_extension *Vcb, PIRP Irp)
Definition: dirctrl.c:1080
void exit(int exitcode)
Definition: _exit.c:33
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137

◆ get_ea_len()

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

Definition at line 148 of file dirctrl.c.

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

107  {
108  fcb* fcb;
109  ULONG tag = 0;
111 
112  if (type == BTRFS_TYPE_SYMLINK)
113  return IO_REPARSE_TAG_SYMLINK;
114  else if (lxss) {
115  if (type == BTRFS_TYPE_SOCKET)
116  return IO_REPARSE_TAG_AF_UNIX;
117  else if (type == BTRFS_TYPE_FIFO)
118  return IO_REPARSE_TAG_LX_FIFO;
119  else if (type == BTRFS_TYPE_CHARDEV)
120  return IO_REPARSE_TAG_LX_CHR;
121  else if (type == BTRFS_TYPE_BLOCKDEV)
122  return IO_REPARSE_TAG_LX_BLK;
123  }
124 
126  return 0;
127 
129  return 0;
130 
131  Status = open_fcb(Vcb, subvol, inode, type, NULL, false, NULL, &fcb, PagedPool, Irp);
132  if (!NT_SUCCESS(Status)) {
133  ERR("open_fcb returned %08lx\n", Status);
134  return 0;
135  }
136 
137  ExAcquireResourceSharedLite(fcb->Header.Resource, true);
138 
140 
141  ExReleaseResourceLite(fcb->Header.Resource);
142 
143  free_fcb(fcb);
144 
145  return tag;
146 }
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1734
#define IO_REPARSE_TAG_LX_FIFO
Definition: btrfs_drv.h:121
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
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:706
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
Definition: ecma_167.h:138
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
Definition: fs.h:78
_In_ PIRP Irp
Definition: csq.h:116
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
ULONG get_reparse_tag_fcb(fcb *fcb)
Definition: dirctrl.c:83
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
struct _fcb fcb
Definition: btrfs_drv.h:1364
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#define IO_REPARSE_TAG_LX_BLK
Definition: btrfs_drv.h:123
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ERR(fmt,...)
Definition: debug.h:110
#define IO_REPARSE_TAG_AF_UNIX
Definition: btrfs_drv.h:120
struct _root * subvol
Definition: btrfs_drv.h:288
#define NULL
Definition: types.h:112
#define IO_REPARSE_TAG_LX_CHR
Definition: btrfs_drv.h:122
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BTRFS_TYPE_FILE
Definition: shellext.h:85
unsigned int ULONG
Definition: retypes.h:1
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:7240
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
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 83 of file dirctrl.c.

83  {
84  ULONG tag;
85 
86  if (fcb->type == BTRFS_TYPE_SYMLINK)
88  else if (fcb->type == BTRFS_TYPE_DIRECTORY) {
89  if (!fcb->reparse_xattr.Buffer || fcb->reparse_xattr.Length < sizeof(ULONG))
90  return 0;
91 
93  } else {
95  ULONG br;
96 
97  Status = read_file(fcb, (uint8_t*)&tag, 0, sizeof(ULONG), &br, NULL);
98  if (!NT_SUCCESS(Status)) {
99  ERR("read_file returned %08lx\n", Status);
100  return 0;
101  }
102  }
103 
104  return tag;
105 }
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
Definition: ecma_167.h:138
ANSI_STRING reparse_xattr
Definition: btrfs_drv.h:301
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
uint8_t type
Definition: btrfs_drv.h:291
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IO_REPARSE_TAG_SYMLINK
Definition: iotypes.h:7240
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
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 651 of file dirctrl.c.

651  {
652  LIST_ENTRY* le;
653  dir_child* dc;
654 
655  if (*pdc) {
656  dir_child* dc2 = *pdc;
657 
658  if (dc2->list_entry_index.Flink != &fileref->fcb->dir_children_index)
659  dc = CONTAINING_RECORD(dc2->list_entry_index.Flink, dir_child, list_entry_index);
660  else
661  dc = NULL;
662 
663  goto next;
664  }
665 
666  if (fileref->parent) { // don't return . and .. if root directory
667  if (*offset == 0) {
668  de->key.obj_id = fileref->fcb->inode;
670  de->key.offset = 0;
672  de->name.Buffer = L".";
673  de->name.Length = de->name.MaximumLength = sizeof(WCHAR);
675 
676  *offset = 1;
677  *pdc = NULL;
678 
679  return STATUS_SUCCESS;
680  } else if (*offset == 1) {
681  de->key.obj_id = fileref->parent->fcb->inode;
683  de->key.offset = 0;
685  de->name.Buffer = L"..";
686  de->name.Length = de->name.MaximumLength = sizeof(WCHAR) * 2;
688 
689  *offset = 2;
690  *pdc = NULL;
691 
692  return STATUS_SUCCESS;
693  }
694  }
695 
696  if (*offset < 2)
697  *offset = 2;
698 
699  dc = NULL;
700  le = fileref->fcb->dir_children_index.Flink;
701 
702  // skip entries before offset
703  while (le != &fileref->fcb->dir_children_index) {
704  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
705 
706  if (dc2->index >= *offset) {
707  dc = dc2;
708  break;
709  }
710 
711  le = le->Flink;
712  }
713 
714 next:
715  if (!dc)
716  return STATUS_NO_MORE_FILES;
717 
718  if (dc->root_dir && fileref->parent) { // hide $Root dir unless in apparent root, to avoid recursion
719  if (dc->list_entry_index.Flink == &fileref->fcb->dir_children_index)
720  return STATUS_NO_MORE_FILES;
721 
722  dc = CONTAINING_RECORD(dc->list_entry_index.Flink, dir_child, list_entry_index);
723  }
724 
725  de->key = dc->key;
726  de->name = dc->name;
727  de->type = dc->type;
729  de->dc = dc;
730 
731  *offset = dc->index + 1;
732  *pdc = dc;
733 
734  return STATUS_SUCCESS;
735 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint8_t type
Definition: dirctrl.c:78
enum DirEntryType dir_entry_type
Definition: dirctrl.c:79
uint64_t offset
Definition: btrfs.h:146
#define L(x)
Definition: ntvdm.h:50
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
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:121
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
GLintptr offset
Definition: glext.h:5920
struct _file_ref * fileref
Definition: btrfs_drv.h:305
LIST_ENTRY list_entry_index
Definition: btrfs_drv.h:262
uint64_t index
Definition: btrfs_drv.h:252
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
Definition: typedefs.h:119
dir_child * dc
Definition: dirctrl.c:80
static unsigned __int64 next
Definition: rand_nt.c:6
KEY key
Definition: dirctrl.c:76
#define NULL
Definition: types.h:112
static const WCHAR dc[]
#define STATUS_SUCCESS
Definition: shellext.h:65
UNICODE_STRING name
Definition: dirctrl.c:77

Referenced by query_directory().

◆ notify_change_directory()

static NTSTATUS notify_change_directory ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 1080 of file dirctrl.c.

1080  {
1083  fcb* fcb = FileObject->FsContext;
1084  ccb* ccb = FileObject->FsContext2;
1085  file_ref* fileref = ccb ? ccb->fileref : NULL;
1086  NTSTATUS Status;
1087 
1088  TRACE("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
1089 
1090  if (!ccb) {
1091  ERR("ccb was NULL\n");
1092  return STATUS_INVALID_PARAMETER;
1093  }
1094 
1095  if (!fileref) {
1096  ERR("no fileref\n");
1097  return STATUS_INVALID_PARAMETER;
1098  }
1099 
1100  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_LIST_DIRECTORY)) {
1101  WARN("insufficient privileges\n");
1102  return STATUS_ACCESS_DENIED;
1103  }
1104 
1105  ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
1106  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
1107 
1108  if (fcb->type != BTRFS_TYPE_DIRECTORY) {
1110  goto end;
1111  }
1112 
1113  // FIXME - raise exception if FCB marked for deletion?
1114 
1115  TRACE("FileObject %p\n", FileObject);
1116 
1117  if (ccb->filename.Length == 0) {
1118  ULONG reqlen;
1119 
1121 
1123  if (Status == STATUS_BUFFER_OVERFLOW) {
1125  if (!ccb->filename.Buffer) {
1126  ERR("out of memory\n");
1128  goto end;
1129  }
1130 
1131  ccb->filename.MaximumLength = (uint16_t)reqlen;
1132 
1134  if (!NT_SUCCESS(Status)) {
1135  ERR("fileref_get_filename returned %08lx\n", Status);
1136  goto end;
1137  }
1138  } else {
1139  ERR("fileref_get_filename returned %08lx\n", Status);
1140  goto end;
1141  }
1142  }
1143 
1144  FsRtlNotifyFilterChangeDirectory(Vcb->NotifySync, &Vcb->DirNotifyList, FileObject->FsContext2, (PSTRING)&ccb->filename,
1145  IrpSp->Flags & SL_WATCH_TREE, false, IrpSp->Parameters.NotifyDirectory.CompletionFilter, Irp,
1146  NULL, NULL, NULL);
1147 
1149 
1150 end:
1151  ExReleaseResourceLite(fcb->Header.Resource);
1152  ExReleaseResourceLite(&fcb->Vcb->tree_lock);
1153 
1154  return Status;
1155 }
#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:4245
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
ACCESS_MASK access
Definition: btrfs_drv.h:382
#define uint16_t
Definition: nsiface.idl:60
UNICODE_STRING filename
Definition: btrfs_drv.h:384
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
uint8_t type
Definition: btrfs_drv.h:291
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
#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:1415
struct _file_ref * fileref
Definition: btrfs_drv.h:305
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define SL_WATCH_TREE
Definition: iotypes.h:1839
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define NULL
Definition: types.h:112
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:383
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
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:773

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 185 of file dirctrl.c.

185  {
187  LONG needed;
188  uint64_t inode;
189  INODE_ITEM ii;
191  ULONG atts = 0, ealen = 0;
193 
195 
196  if (de->key.obj_type == TYPE_ROOT_ITEM) { // subvol
197  LIST_ENTRY* le;
198 
199  r = NULL;
200 
201  le = fcb->Vcb->roots.Flink;
202  while (le != &fcb->Vcb->roots) {
204 
205  if (subvol->id == de->key.obj_id) {
206  r = subvol;
207  break;
208  }
209 
210  le = le->Flink;
211  }
212 
213  if (r && r->parent != fcb->subvol->id && (!de->dc || !de->dc->root_dir))
214  r = NULL;
215 
217  } else {
218  inode = de->key.obj_id;
219  }
220 
221  if (IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation) { // FIXME - object ID and reparse point classes too?
222  switch (de->dir_entry_type) {
223  case DirEntryType_File:
224  {
225  if (!r) {
227 
228  ii = fcb->Vcb->dummy_fcb->inode_item;
229  atts = fcb->Vcb->dummy_fcb->atts;
230  ealen = fcb->Vcb->dummy_fcb->ealen;
231 
234  ii.st_atime = ii.st_mtime = ii.st_ctime = ii.otime;
235  } else {
236  bool found = false;
237 
238  if (de->dc && de->dc->fileref && de->dc->fileref->fcb) {
239  ii = de->dc->fileref->fcb->inode_item;
240  atts = de->dc->fileref->fcb->atts;
241  ealen = de->dc->fileref->fcb->ealen;
242  found = true;
243  }
244 
245  if (!found) {
246  KEY searchkey;
248 
249  searchkey.obj_id = inode;
250  searchkey.obj_type = TYPE_INODE_ITEM;
251  searchkey.offset = 0xffffffffffffffff;
252 
253  Status = find_item(fcb->Vcb, r, &tp, &searchkey, false, Irp);
254  if (!NT_SUCCESS(Status)) {
255  ERR("error - find_item returned %08lx\n", Status);
256  return Status;
257  }
258 
259  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
260  ERR("could not find inode item for inode %I64x in root %I64x\n", inode, r->id);
261  return STATUS_INTERNAL_ERROR;
262  }
263 
264  RtlZeroMemory(&ii, sizeof(INODE_ITEM));
265 
266  if (tp.item->size > 0)
267  RtlCopyMemory(&ii, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size));
268 
269  if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
270  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation ||
271  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
272  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
273  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
274  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
275  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
276 
277  bool dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.';
278 
279  atts = get_file_attributes(fcb->Vcb, r, inode, de->type, dotfile, false, Irp);
280  }
281 
282  if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
283  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
284  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
285  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
286  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdDirectoryInformation ||
287  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdExtdBothDirectoryInformation) {
288  ealen = get_ea_len(fcb->Vcb, r, inode, Irp);
289  }
290  }
291  }
292 
293  break;
294  }
295 
296  case DirEntryType_Self:
297  ii = fcb->inode_item;
298  r = fcb->subvol;
299  inode = fcb->inode;
300  atts = fcb->atts;
301  ealen = fcb->ealen;
302  break;
303 
304  case DirEntryType_Parent:
305  if (fileref && fileref->parent) {
306  ii = fileref->parent->fcb->inode_item;
307  r = fileref->parent->fcb->subvol;
308  inode = fileref->parent->fcb->inode;
309  atts = fileref->parent->fcb->atts;
310  ealen = fileref->parent->fcb->ealen;
311  } else {
312  ERR("no fileref\n");
313  return STATUS_INTERNAL_ERROR;
314  }
315  break;
316  }
317 
318  if (atts == 0)
320  }
321 
322  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
324  {
326 
327  TRACE("FileBothDirectoryInformation\n");
328 
330 
331  if (needed > *len) {
332  TRACE("buffer overflow - %li > %lu\n", needed, *len);
333  return STATUS_BUFFER_OVERFLOW;
334  }
335 
336  fbdi->NextEntryOffset = 0;
337  fbdi->FileIndex = 0;
342  fbdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
343 
344  if (de->type == BTRFS_TYPE_SYMLINK)
345  fbdi->AllocationSize.QuadPart = 0;
346  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
347  fbdi->AllocationSize.QuadPart = ii.st_blocks;
348  else
349  fbdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
350 
351  fbdi->FileAttributes = atts;
352  fbdi->FileNameLength = de->name.Length;
354  fbdi->ShortNameLength = 0;
355 
356  RtlCopyMemory(fbdi->FileName, de->name.Buffer, de->name.Length);
357 
358  *len -= needed;
359 
360  return STATUS_SUCCESS;
361  }
362 
364  {
366 
367  TRACE("FileDirectoryInformation\n");
368 
370 
371  if (needed > *len) {
372  TRACE("buffer overflow - %li > %lu\n", needed, *len);
373  return STATUS_BUFFER_OVERFLOW;
374  }
375 
376  fdi->NextEntryOffset = 0;
377  fdi->FileIndex = 0;
382  fdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
383 
384  if (de->type == BTRFS_TYPE_SYMLINK)
385  fdi->AllocationSize.QuadPart = 0;
386  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
388  else
389  fdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
390 
391  fdi->FileAttributes = atts;
392  fdi->FileNameLength = de->name.Length;
393 
394  RtlCopyMemory(fdi->FileName, de->name.Buffer, de->name.Length);
395 
396  *len -= needed;
397 
398  return STATUS_SUCCESS;
399  }
400 
402  {
404 
405  TRACE("FileFullDirectoryInformation\n");
406 
408 
409  if (needed > *len) {
410  TRACE("buffer overflow - %li > %lu\n", needed, *len);
411  return STATUS_BUFFER_OVERFLOW;
412  }
413 
414  ffdi->NextEntryOffset = 0;
415  ffdi->FileIndex = 0;
420  ffdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
421 
422  if (de->type == BTRFS_TYPE_SYMLINK)
423  ffdi->AllocationSize.QuadPart = 0;
424  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
425  ffdi->AllocationSize.QuadPart = ii.st_blocks;
426  else
427  ffdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
428 
429  ffdi->FileAttributes = atts;
430  ffdi->FileNameLength = de->name.Length;
432 
433  RtlCopyMemory(ffdi->FileName, de->name.Buffer, de->name.Length);
434 
435  *len -= needed;
436 
437  return STATUS_SUCCESS;
438  }
439 
441  {
443 
444  TRACE("FileIdBothDirectoryInformation\n");
445 
447 
448  if (needed > *len) {
449  TRACE("buffer overflow - %li > %lu\n", needed, *len);
450  return STATUS_BUFFER_OVERFLOW;
451  }
452 
453  fibdi->NextEntryOffset = 0;
454  fibdi->FileIndex = 0;
459  fibdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
460 
461  if (de->type == BTRFS_TYPE_SYMLINK)
462  fibdi->AllocationSize.QuadPart = 0;
463  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
464  fibdi->AllocationSize.QuadPart = ii.st_blocks;
465  else
466  fibdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
467 
468  fibdi->FileAttributes = atts;
469  fibdi->FileNameLength = de->name.Length;
471  fibdi->ShortNameLength = 0;
472  fibdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode);
473 
474  RtlCopyMemory(fibdi->FileName, de->name.Buffer, de->name.Length);
475 
476  *len -= needed;
477 
478  return STATUS_SUCCESS;
479  }
480 
482  {
484 
485  TRACE("FileIdFullDirectoryInformation\n");
486 
488 
489  if (needed > *len) {
490  TRACE("buffer overflow - %li > %lu\n", needed, *len);
491  return STATUS_BUFFER_OVERFLOW;
492  }
493 
494  fifdi->NextEntryOffset = 0;
495  fifdi->FileIndex = 0;
500  fifdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
501 
502  if (de->type == BTRFS_TYPE_SYMLINK)
503  fifdi->AllocationSize.QuadPart = 0;
504  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
505  fifdi->AllocationSize.QuadPart = ii.st_blocks;
506  else
507  fifdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
508 
509  fifdi->FileAttributes = atts;
510  fifdi->FileNameLength = de->name.Length;
512  fifdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode);
513 
514  RtlCopyMemory(fifdi->FileName, de->name.Buffer, de->name.Length);
515 
516  *len -= needed;
517 
518  return STATUS_SUCCESS;
519  }
520 
521 #ifndef _MSC_VER
522 #pragma GCC diagnostic push
523 #pragma GCC diagnostic ignored "-Wswitch"
524 #endif
525 #if (NTDDI_VERSION >= NTDDI_VISTA)
527  {
529 
530  TRACE("FileIdExtdDirectoryInformation\n");
531 
533 
534  if (needed > *len) {
535  TRACE("buffer overflow - %li > %lu\n", needed, *len);
536  return STATUS_BUFFER_OVERFLOW;
537  }
538 
539  fiedi->NextEntryOffset = 0;
540  fiedi->FileIndex = 0;
545  fiedi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
546 
547  if (de->type == BTRFS_TYPE_SYMLINK)
548  fiedi->AllocationSize.QuadPart = 0;
549  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
550  fiedi->AllocationSize.QuadPart = ii.st_blocks;
551  else
552  fiedi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
553 
554  fiedi->FileAttributes = atts;
555  fiedi->FileNameLength = de->name.Length;
556  fiedi->EaSize = ealen;
557  fiedi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
558 
559  RtlCopyMemory(&fiedi->FileId.Identifier[0], &fcb->inode, sizeof(uint64_t));
560  RtlCopyMemory(&fiedi->FileId.Identifier[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
561 
562  RtlCopyMemory(fiedi->FileName, de->name.Buffer, de->name.Length);
563 
564  *len -= needed;
565 
566  return STATUS_SUCCESS;
567  }
568 
570  {
572 
573  TRACE("FileIdExtdBothDirectoryInformation\n");
574 
576 
577  if (needed > *len) {
578  TRACE("buffer overflow - %li > %lu\n", needed, *len);
579  return STATUS_BUFFER_OVERFLOW;
580  }
581 
582  fiebdi->NextEntryOffset = 0;
583  fiebdi->FileIndex = 0;
588  fiebdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
589 
590  if (de->type == BTRFS_TYPE_SYMLINK)
591  fiebdi->AllocationSize.QuadPart = 0;
592  else if (atts & FILE_ATTRIBUTE_SPARSE_FILE)
593  fiebdi->AllocationSize.QuadPart = ii.st_blocks;
594  else
595  fiebdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size);
596 
597  fiebdi->FileAttributes = atts;
598  fiebdi->FileNameLength = de->name.Length;
599  fiebdi->EaSize = ealen;
600  fiebdi->ReparsePointTag = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp);
601 
602  RtlCopyMemory(&fiebdi->FileId.Identifier[0], &fcb->inode, sizeof(uint64_t));
603  RtlCopyMemory(&fiebdi->FileId.Identifier[sizeof(uint64_t)], &fcb->subvol->id, sizeof(uint64_t));
604 
605  fiebdi->ShortNameLength = 0;
606 
607  RtlCopyMemory(fiebdi->FileName, de->name.Buffer, de->name.Length);
608 
609  *len -= needed;
610 
611  return STATUS_SUCCESS;
612  }
613 #endif
614 
615 #ifndef _MSC_VER
616 #pragma GCC diagnostic pop
617 #endif
618 
620  {
622 
623  TRACE("FileNamesInformation\n");
624 
626 
627  if (needed > *len) {
628  TRACE("buffer overflow - %li > %lu\n", needed, *len);
629  return STATUS_BUFFER_OVERFLOW;
630  }
631 
632  fni->NextEntryOffset = 0;
633  fni->FileIndex = 0;
634  fni->FileNameLength = de->name.Length;
635 
636  RtlCopyMemory(fni->FileName, de->name.Buffer, de->name.Length);
637 
638  *len -= needed;
639 
640  return STATUS_SUCCESS;
641  }
642 
643  default:
644  WARN("Unknown FileInformationClass %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
645  return STATUS_NOT_IMPLEMENTED;
646  }
647 
648  return STATUS_NO_MORE_FILES;
649 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
LARGE_INTEGER AllocationSize
Definition: iotypes.h:5724
LARGE_INTEGER LastAccessTime
Definition: winternl.h:517
uint64_t obj_id
Definition: btrfs.h:144
LARGE_INTEGER AllocationSize
Definition: iotypes.h:5757
struct _file_ref * fileref
Definition: btrfs_drv.h:260
uint8_t obj_type
Definition: btrfs.h:145
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
BTRFS_TIME otime
Definition: btrfs.h:304
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
uint8_t type
Definition: dirctrl.c:78
enum DirEntryType dir_entry_type
Definition: dirctrl.c:79
__u16 time
Definition: mkdosfs.c:366
#define FileIdExtdDirectoryInformation
Definition: dirctrl.c:24
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
LARGE_INTEGER AllocationSize
Definition: dirctrl.c:35
Definition: fs.h:78
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
LARGE_INTEGER ChangeTime
Definition: dirctrl.c:33
LARGE_INTEGER ChangeTime
Definition: winternl.h:519
static __inline uint64_t make_file_id(root *r, uint64_t inode)
Definition: btrfs_drv.h:1012
return STATUS_NOT_IMPLEMENTED
LARGE_INTEGER LastWriteTime
Definition: from_kernel.h:143
_In_ PIRP Irp
Definition: csq.h:116
long LONG
Definition: pedump.c:60
LARGE_INTEGER EndOfFile
Definition: winternl.h:520
LARGE_INTEGER AllocationSize
Definition: from_kernel.h:146
bool root_dir
Definition: btrfs_drv.h:261
#define offsetof(TYPE, MEMBER)
#define FileIdExtdBothDirectoryInformation
Definition: dirctrl.c:25
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
BTRFS_TIME st_mtime
Definition: btrfs.h:303
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:1067
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
LARGE_INTEGER LastWriteTime
Definition: iotypes.h:5754
ULONG ealen
Definition: btrfs_drv.h:303
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint64_t st_size
Definition: btrfs.h:289
#define TRACE(s)
Definition: solgame.cpp:4
LARGE_INTEGER EndOfFile
Definition: dirctrl.c:34
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
__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:2664
#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:289
#define Vcb
Definition: cdprocs.h:1415
LARGE_INTEGER LastWriteTime
Definition: winternl.h:518
UCHAR Identifier[16]
Definition: btrfs_drv.h:162
struct _file_ref * fileref
Definition: btrfs_drv.h:305
BTRFS_TIME st_atime
Definition: btrfs.h:301
LARGE_INTEGER CreationTime
Definition: iotypes.h:5719
ULONG get_reparse_tag(device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, ULONG atts, bool lxss, PIRP Irp)
Definition: dirctrl.c:107
tree_data * item
Definition: btrfs_drv.h:509
LARGE_INTEGER LastAccessTime
Definition: dirctrl.c:31
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define TYPE_INODE_ITEM
Definition: btrfs.h:23
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:148
Definition: typedefs.h:119
LARGE_INTEGER CreationTime
Definition: iotypes.h:5752
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
uint64_t st_blocks
Definition: btrfs.h:290
LARGE_INTEGER CreationTime
Definition: dirctrl.c:30
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
dir_child * dc
Definition: dirctrl.c:80
UINT64 uint64_t
Definition: types.h:77
ULONG atts
Definition: btrfs_drv.h:297
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
LARGE_INTEGER LastWriteTime
Definition: dirctrl.c:32
KEY key
Definition: dirctrl.c:76
LARGE_INTEGER CreationTime
Definition: winternl.h:516
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
struct _root * subvol
Definition: btrfs_drv.h:288
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
#define NULL
Definition: types.h:112
LARGE_INTEGER CreationTime
Definition: from_kernel.h:141
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
LARGE_INTEGER LastAccessTime
Definition: from_kernel.h:142
#define STATUS_SUCCESS
Definition: shellext.h:65
bool lxss
Definition: btrfs_drv.h:391
file_ref * fileref
Definition: btrfs_drv.h:383
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
WCHAR FileName[ANYSIZE_ARRAY]
Definition: winternl.h:524
LARGE_INTEGER LastWriteTime
Definition: iotypes.h:5721
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
LARGE_INTEGER LastAccessTime
Definition: iotypes.h:5753
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
LARGE_INTEGER AllocationSize
Definition: winternl.h:521
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
_In_ uint16_t _Out_ ULONG * atts
Definition: btrfs_drv.h:1107
LONGLONG QuadPart
Definition: typedefs.h:114
#define BTRFS_TYPE_SYMLINK
Definition: shellext.h:91
UNICODE_STRING name
Definition: dirctrl.c:77
LARGE_INTEGER LastAccessTime
Definition: iotypes.h:5720
WCHAR FileName[ANYSIZE_ARRAY]
Definition: winternl.h:539

Referenced by query_directory().

◆ query_directory()

static NTSTATUS query_directory ( PIRP  Irp)
static

Definition at line 737 of file dirctrl.c.

737  {
739  NTSTATUS Status, status2;
740  fcb* fcb;
741  ccb* ccb;
742  file_ref* fileref;
744  void* buf;
745  uint8_t *curitem, *lastitem;
746  LONG length;
747  ULONG count;
748  bool has_wildcard = false, specific_file = false, initial;
749  dir_entry de;
750  uint64_t newoffset;
751  dir_child* dc = NULL;
752 
753  TRACE("query directory\n");
754 
756  fcb = IrpSp->FileObject->FsContext;
757  ccb = IrpSp->FileObject->FsContext2;
758  fileref = ccb ? ccb->fileref : NULL;
759 
760  if (!fileref)
762 
763  if (!ccb) {
764  ERR("ccb was NULL\n");
766  }
767 
768  if (!fcb) {
769  ERR("fcb was NULL\n");
771  }
772 
773  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_LIST_DIRECTORY)) {
774  WARN("insufficient privileges\n");
775  return STATUS_ACCESS_DENIED;
776  }
777 
778  Vcb = fcb->Vcb;
779 
780  if (!Vcb) {
781  ERR("Vcb was NULL\n");
783  }
784 
785  if (fileref->fcb == Vcb->dummy_fcb)
786  return STATUS_NO_MORE_FILES;
787 
788  if (IrpSp->Flags == 0) {
789  TRACE("QD flags: (none)\n");
790  } else {
791  ULONG flags = IrpSp->Flags;
792 
793  TRACE("QD flags:\n");
794 
795  if (flags & SL_INDEX_SPECIFIED) {
796  TRACE(" SL_INDEX_SPECIFIED\n");
798  }
799 
800  if (flags & SL_RESTART_SCAN) {
801  TRACE(" SL_RESTART_SCAN\n");
803  }
804 
806  TRACE(" SL_RETURN_SINGLE_ENTRY\n");
808  }
809 
810  if (flags != 0)
811  TRACE(" unknown flags: %lu\n", flags);
812  }
813 
814  if (IrpSp->Flags & SL_RESTART_SCAN) {
815  ccb->query_dir_offset = 0;
816 
817  if (ccb->query_string.Buffer) {
820  }
821 
822  ccb->has_wildcard = false;
823  ccb->specific_file = false;
824  }
825 
826  initial = !ccb->query_string.Buffer;
827 
828  if (IrpSp->Parameters.QueryDirectory.FileName && IrpSp->Parameters.QueryDirectory.FileName->Length > 1) {
829  TRACE("QD filename: %.*S\n", (int)(IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR)), IrpSp->Parameters.QueryDirectory.FileName->Buffer);
830 
831  if (IrpSp->Parameters.QueryDirectory.FileName->Length > sizeof(WCHAR) || IrpSp->Parameters.QueryDirectory.FileName->Buffer[0] != L'*') {
832  specific_file = true;
833 
834  if (FsRtlDoesNameContainWildCards(IrpSp->Parameters.QueryDirectory.FileName)) {
835  has_wildcard = true;
836  specific_file = false;
837  } else if (!initial)
838  return STATUS_NO_MORE_FILES;
839  }
840 
841  if (ccb->query_string.Buffer)
843 
844  if (has_wildcard)
845  RtlUpcaseUnicodeString(&ccb->query_string, IrpSp->Parameters.QueryDirectory.FileName, true);
846  else {
847  ccb->query_string.Buffer = ExAllocatePoolWithTag(PagedPool, IrpSp->Parameters.QueryDirectory.FileName->Length, ALLOC_TAG);
848  if (!ccb->query_string.Buffer) {
849  ERR("out of memory\n");
851  }
852 
853  ccb->query_string.Length = ccb->query_string.MaximumLength = IrpSp->Parameters.QueryDirectory.FileName->Length;
854  RtlCopyMemory(ccb->query_string.Buffer, IrpSp->Parameters.QueryDirectory.FileName->Buffer, IrpSp->Parameters.QueryDirectory.FileName->Length);
855  }
856 
857  ccb->has_wildcard = has_wildcard;
858  ccb->specific_file = specific_file;
859  } else {
860  has_wildcard = ccb->has_wildcard;
861  specific_file = ccb->specific_file;
862 
863  if (!(IrpSp->Flags & SL_RESTART_SCAN)) {
864  initial = false;
865 
866  if (specific_file)
867  return STATUS_NO_MORE_FILES;
868  }
869  }
870 
871  if (ccb->query_string.Buffer) {
872  TRACE("query string = %.*S\n", (int)(ccb->query_string.Length / sizeof(WCHAR)), ccb->query_string.Buffer);
873  }
874 
875  newoffset = ccb->query_dir_offset;
876 
877  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
878 
879  ExAcquireResourceSharedLite(&fileref->fcb->nonpaged->dir_children_lock, true);
880 
881  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
882 
883  if (!NT_SUCCESS(Status)) {
884  if (Status == STATUS_NO_MORE_FILES && initial)
886  goto end;
887  }
888 
889  ccb->query_dir_offset = newoffset;
890 
892 
893  if (Irp->MdlAddress && !buf) {
894  ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
896  goto end;
897  }
898 
899  length = IrpSp->Parameters.QueryDirectory.Length;
900 
901  if (specific_file) {
902  bool found = false;
904  LIST_ENTRY* le;
905  uint32_t hash;
906  uint8_t c;
907 
908  us.Buffer = NULL;
909 
910  if (!ccb->case_sensitive) {
912  if (!NT_SUCCESS(Status)) {
913  ERR("RtlUpcaseUnicodeString returned %08lx\n", Status);
914  goto end;
915  }
916 
917  hash = calc_crc32c(0xffffffff, (uint8_t*)us.Buffer, us.Length);
918  } else
920 
921  c = hash >> 24;
922 
923  if (ccb->case_sensitive) {
924  if (fileref->fcb->hash_ptrs[c]) {
925  le = fileref->fcb->hash_ptrs[c];
926  while (le != &fileref->fcb->dir_children_hash) {
927  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash);
928 
929  if (dc2->hash == hash) {
931  found = true;
932 
933  de.key = dc2->key;
934  de.name = dc2->name;
935  de.type = dc2->type;
937  de.dc = dc2;
938 
939  break;
940  }
941  } else if (dc2->hash > hash)
942  break;
943 
944  le = le->Flink;
945  }
946  }
947  } else {
948  if (fileref->fcb->hash_ptrs_uc[c]) {
949  le = fileref->fcb->hash_ptrs_uc[c];
950  while (le != &fileref->fcb->dir_children_hash_uc) {
951  dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
952 
953  if (dc2->hash_uc == hash) {
954  if (dc2->name_uc.Length == us.Length && RtlCompareMemory(dc2->name_uc.Buffer, us.Buffer, us.Length) == us.Length) {
955  found = true;
956 
957  de.key = dc2->key;
958  de.name = dc2->name;
959  de.type = dc2->type;
961  de.dc = dc2;
962 
963  break;
964  }
965  } else if (dc2->hash_uc > hash)
966  break;
967 
968  le = le->Flink;
969  }
970  }
971  }
972 
973  if (us.Buffer)
974  ExFreePool(us.Buffer);
975 
976  if (!found) {
978  goto end;
979  }
980  } else if (has_wildcard) {
982  newoffset = ccb->query_dir_offset;
983  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
984 
985  if (NT_SUCCESS(Status))
986  ccb->query_dir_offset = newoffset;
987  else {
988  if (Status == STATUS_NO_MORE_FILES && initial)
990 
991  goto end;
992  }
993  }
994  }
995 
996  TRACE("file(0) = %.*S\n", (int)(de.name.Length / sizeof(WCHAR)), de.name.Buffer);
997  TRACE("offset = %I64u\n", ccb->query_dir_offset - 1);
998 
1000 
1001  count = 0;
1002  if (NT_SUCCESS(Status) && !(IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) && !specific_file) {
1003  lastitem = (uint8_t*)buf;
1004 
1005  while (length > 0) {
1006  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
1007 #ifndef _MSC_VER
1008 #pragma GCC diagnostic push
1009 #pragma GCC diagnostic ignored "-Wswitch"
1010 #endif
1018  length -= length % 8;
1019  break;
1020 #ifndef _MSC_VER
1021 #pragma GCC diagnostic pop
1022 #endif
1023 
1024  case FileNamesInformation:
1025  length -= length % 4;
1026  break;
1027 
1028  default:
1029  WARN("unhandled file information class %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
1030  break;
1031  }
1032 
1033  if (length > 0) {
1034  newoffset = ccb->query_dir_offset;
1035  Status = next_dir_entry(fileref, &newoffset, &de, &dc);
1036  if (NT_SUCCESS(Status)) {
1037  if (!has_wildcard || FsRtlIsNameInExpression(&ccb->query_string, &de.name, !ccb->case_sensitive, NULL)) {
1038  curitem = (uint8_t*)buf + IrpSp->Parameters.QueryDirectory.Length - length;
1039  count++;
1040 
1041  TRACE("file(%lu) %Iu = %.*S\n", count, curitem - (uint8_t*)buf, (int)(de.name.Length / sizeof(WCHAR)), de.name.Buffer);
1042  TRACE("offset = %I64u\n", ccb->query_dir_offset - 1);
1043 
1044  status2 = query_dir_item(fcb, ccb, curitem, &length, Irp, &de, fcb->subvol);
1045 
1046  if (NT_SUCCESS(status2)) {
1047  ULONG* lastoffset = (ULONG*)lastitem;
1048 
1049  *lastoffset = (ULONG)(curitem - lastitem);
1050  ccb->query_dir_offset = newoffset;
1051 
1052  lastitem = curitem;
1053  } else
1054  break;
1055  } else
1056  ccb->query_dir_offset = newoffset;
1057  } else {
1060 
1061  break;
1062  }
1063  } else
1064  break;
1065  }
1066  }
1067 
1068  Irp->IoStatus.Information = IrpSp->Parameters.QueryDirectory.Length - length;
1069 
1070 end:
1071  ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
1072 
1073  ExReleaseResourceLite(&Vcb->tree_lock);
1074 
1075  TRACE("returning %08lx\n", Status);
1076 
1077  return Status;
1078 }
#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:1837
USHORT MaximumLength
Definition: env_spec_w32.h:370
UNICODE_STRING name_uc
Definition: btrfs_drv.h:258
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:112
LONG NTSTATUS
Definition: precomp.h:26
uint8_t type
Definition: dirctrl.c:78
static NTSTATUS query_dir_item(fcb *fcb, ccb *ccb, void *buf, LONG *len, PIRP Irp, dir_entry *de, root *r)
Definition: dirctrl.c:185
uint32_t hash
Definition: btrfs_drv.h:255
enum DirEntryType dir_entry_type
Definition: dirctrl.c:79
ACCESS_MASK access
Definition: btrfs_drv.h:382
#define FileIdExtdDirectoryInformation
Definition: dirctrl.c:24
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
bool has_wildcard
Definition: btrfs_drv.h:377
UNICODE_STRING query_string
Definition: btrfs_drv.h:376
#define ALLOC_TAG
Definition: btrfs_drv.h:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint32_t hash_uc
Definition: btrfs_drv.h:257
#define L(x)
Definition: ntvdm.h:50
_In_ PIRP Irp
Definition: csq.h:116
int hash
Definition: main.c:58
long LONG
Definition: pedump.c:60
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
bool specific_file
Definition: btrfs_drv.h:378
#define FileIdExtdBothDirectoryInformation
Definition: dirctrl.c:25
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
struct _fcb fcb
Definition: btrfs_drv.h:1364
__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
#define Vcb
Definition: cdprocs.h:1415
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:977
const GLubyte * c
Definition: glext.h:8905
struct _file_ref * fileref
Definition: btrfs_drv.h:305
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:651
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
bool case_sensitive
Definition: btrfs_drv.h:386
crc_func calc_crc32c
Definition: crc32c.c:23
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1836
dir_child * dc
Definition: dirctrl.c:80
UINT64 uint64_t
Definition: types.h:77
KEY key
Definition: dirctrl.c:76
uint8_t type
Definition: btrfs_drv.h:253
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
struct _root * subvol
Definition: btrfs_drv.h:288
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
#define SL_RESTART_SCAN
Definition: iotypes.h:1835
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
Definition: dirctrl.c:75
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
static const WCHAR dc[]
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _ccb ccb
file_ref * fileref
Definition: btrfs_drv.h:383
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: _hash_fun.h:40
uint64_t query_dir_offset
Definition: btrfs_drv.h:375
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
UNICODE_STRING name
Definition: btrfs_drv.h:256
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
UNICODE_STRING name
Definition: dirctrl.c:77
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31

Referenced by _Dispatch_type_().