ReactOS  0.4.13-dev-982-g9853eab
dircntrl.cpp
Go to the documentation of this file.
1 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
6 /*************************************************************************
7 *
8 * File: DirCntrl.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 * Contains code to handle the "directory control" dispatch entry point.
14 *
15 *************************************************************************/
16 
17 #include "udffs.h"
18 
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_DIR_CONTROL
21 
22 /*
23 // Local support routine(s):
24 */
25 
26 #define UDF_FNM_FLAG_CAN_BE_8D3 0x01
27 #define UDF_FNM_FLAG_IGNORE_CASE 0x02
28 #define UDF_FNM_FLAG_CONTAINS_WC 0x04
29 
31  IN PVCB Vcb,
32  IN PDIR_INDEX_HDR hDirIndex,
33  IN PLONG CurrentNumber, // Must be modified
34  IN PUNICODE_STRING PtrSearchPattern,
35  IN UCHAR FNM_Flags,
36  IN PHASH_ENTRY hashes,
37  OUT PDIR_INDEX_ITEM* _DirNdx);
38 
39 /*************************************************************************
40 *
41 * Function: UDFDirControl()
42 *
43 * Description:
44 * The I/O Manager will invoke this routine to handle a directory control
45 * request
46 *
47 * Expected Interrupt Level (for execution) :
48 *
49 * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
50 * to be deferred to a worker thread context)
51 *
52 * Return Value: STATUS_SUCCESS/Error
53 *
54 *************************************************************************/
56 NTAPI
58  PDEVICE_OBJECT DeviceObject, // the logical volume device object
59  PIRP Irp // I/O Request Packet
60  )
61 {
63  PtrUDFIrpContext PtrIrpContext = NULL;
64  BOOLEAN AreWeTopLevel = FALSE;
65 
66  TmPrint(("UDFDirControl: \n"));
67 
70  ASSERT(Irp);
71 
72  // set the top level context
73  AreWeTopLevel = UDFIsIrpTopLevel(Irp);
74  ASSERT(!UDFIsFSDevObj(DeviceObject));
75 
76  _SEH2_TRY {
77 
78  // get an IRP context structure and issue the request
79  PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
80  if(PtrIrpContext) {
81  RC = UDFCommonDirControl(PtrIrpContext, Irp);
82  } else {
84  Irp->IoStatus.Status = RC;
85  Irp->IoStatus.Information = 0;
86  // complete the IRP
88  }
89 
91 
92  RC = UDFExceptionHandler(PtrIrpContext, Irp);
93 
95  } _SEH2_END;
96 
97  if (AreWeTopLevel) {
99  }
100 
102 
103  return(RC);
104 } // end UDFDirControl()
105 
106 
107 
108 /*************************************************************************
109 *
110 * Function: UDFCommonDirControl()
111 *
112 * Description:
113 * The actual work is performed here. This routine may be invoked in one'
114 * of the two possible contexts:
115 * (a) in the context of a system worker thread
116 * (b) in the context of the original caller
117 *
118 * Expected Interrupt Level (for execution) :
119 *
120 * IRQL_PASSIVE_LEVEL
121 *
122 * Return Value: STATUS_SUCCESS/Error
123 *
124 *************************************************************************/
125 NTSTATUS
126 NTAPI
128  PtrUDFIrpContext PtrIrpContext,
129  PIRP Irp
130  )
131 {
135  PtrUDFFCB Fcb = NULL;
136  PtrUDFCCB Ccb = NULL;
137  PVCB Vcb = NULL;
138  BOOLEAN AcquiredVcb = FALSE;
139 
140  TmPrint(("UDFCommonDirControl: \n"));
141 // BrutePoint();
142 
143  _SEH2_TRY {
144  // First, get a pointer to the current I/O stack location
146  ASSERT(IrpSp);
147 
150 
151  // Get the FCB and CCB pointers
152  Ccb = (PtrUDFCCB)(FileObject->FsContext2);
153  ASSERT(Ccb);
154  Fcb = Ccb->Fcb;
155  ASSERT(Fcb);
156 
157  Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
158  ASSERT(Vcb);
159  ASSERT(Vcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB);
160 // Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
161 
163  UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
164  AcquiredVcb = TRUE;
165  // Get some of the parameters supplied to us
166  switch (IrpSp->MinorFunction) {
168  RC = UDFQueryDirectory(PtrIrpContext, Irp, IrpSp, FileObject, Fcb, Ccb);
169  break;
171  RC = UDFNotifyChangeDirectory(PtrIrpContext, Irp, IrpSp, FileObject, Fcb, Ccb);
172  break;
173  default:
174  // This should not happen.
176  Irp->IoStatus.Status = RC;
177  Irp->IoStatus.Information = 0;
178 
179  // Free up the Irp Context
180  UDFReleaseIrpContext(PtrIrpContext);
181 
182  // complete the IRP
184  break;
185  }
186 
187 //try_exit: NOTHING;
188 
189  } _SEH2_FINALLY {
190 
191  if(AcquiredVcb) {
192  UDFReleaseResource(&(Vcb->VCBResource));
193  AcquiredVcb = FALSE;
194  }
195  } _SEH2_END;
196  return(RC);
197 } // end UDFCommonDirControl()
198 
199 
200 /*************************************************************************
201 *
202 * Function: UDFQueryDirectory()
203 *
204 * Description:
205 * Query directory request.
206 *
207 * Expected Interrupt Level (for execution) :
208 *
209 * IRQL_PASSIVE_LEVEL
210 *
211 * Return Value: STATUS_SUCCESS/Error
212 *
213 *************************************************************************/
214 NTSTATUS
215 NTAPI
217  PtrUDFIrpContext PtrIrpContext,
218  PIRP Irp,
221  PtrUDFFCB Fcb,
222  PtrUDFCCB Ccb
223  )
224 {
226  BOOLEAN PostRequest = FALSE;
228  BOOLEAN CanWait = FALSE;
229  PVCB Vcb = NULL;
230  BOOLEAN AcquiredFCB = FALSE;
231  unsigned long BufferLength = 0;
232  UNICODE_STRING SearchPattern;
233  PUNICODE_STRING PtrSearchPattern;
236  PUCHAR Buffer = NULL;
237  BOOLEAN FirstTimeQuery = FALSE;
238  LONG NextMatch;
239  LONG PrevMatch = -1;
240  ULONG CurrentOffset;
241  ULONG BaseLength;
242  ULONG FileNameBytes;
243  ULONG Information = 0;
244  ULONG LastOffset = 0;
245  BOOLEAN AtLeastOneFound = FALSE;
247  PUDF_FILE_INFO DirFileInfo = NULL;
248  PDIR_INDEX_HDR hDirIndex = NULL;
249  PFILE_BOTH_DIR_INFORMATION DirInformation = NULL; // Returned from udf_info module
250  PFILE_BOTH_DIR_INFORMATION BothDirInformation = NULL; // Pointer in callers buffer
251  PFILE_NAMES_INFORMATION NamesInfo;
252  ULONG BytesRemainingInBuffer;
253  UCHAR FNM_Flags = 0;
254  PHASH_ENTRY cur_hashes = NULL;
255  PDIR_INDEX_ITEM DirNdx;
256  // do some pre-init...
257  SearchPattern.Buffer = NULL;
258 
259  UDFPrint(("UDFQueryDirectory: @=%#x\n", &PtrIrpContext));
260 
261 #define CanBe8dot3 (FNM_Flags & UDF_FNM_FLAG_CAN_BE_8D3)
262 #define IgnoreCase (FNM_Flags & UDF_FNM_FLAG_IGNORE_CASE)
263 #define ContainsWC (FNM_Flags & UDF_FNM_FLAG_CONTAINS_WC)
264 
265  _SEH2_TRY
266  {
267 
268  // Validate the sent-in FCB
269  if ((Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || !(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
270  // We will only allow notify requests on directories.
272  }
273 
274  // Obtain the callers parameters
275  NtReqFcb = Fcb->NTRequiredFCB;
276  CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
277  Vcb = Fcb->Vcb;
278  //Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
279  FNM_Flags |= (Ccb->CCBFlags & UDF_CCB_CASE_SENSETIVE) ? 0 : UDF_FNM_FLAG_IGNORE_CASE;
280  DirFileInfo = Fcb->FileInfo;
281  BufferLength = pStackLocation->Parameters.QueryDirectory.Length;
282 
283  // If the caller does not want to block, it would be easier to
284  // simply post the request now.
285  if (!CanWait) {
286  PostRequest = TRUE;
288  }
289 
290  // Continue obtaining the callers parameters...
291  if(IgnoreCase && pStackLocation->Parameters.QueryDirectory.FileName) {
292  PtrSearchPattern = &SearchPattern;
293  if(!NT_SUCCESS(RC = RtlUpcaseUnicodeString(PtrSearchPattern, (PUNICODE_STRING)(pStackLocation->Parameters.QueryDirectory.FileName), TRUE)))
294  try_return(RC);
295  } else {
296  PtrSearchPattern = (PUNICODE_STRING)(pStackLocation->Parameters.QueryDirectory.FileName);
297  }
298  FileInformationClass = pStackLocation->Parameters.QueryDirectory.FileInformationClass;
299 
300  // Calculate baselength (without name) for each InfoClass
301  switch (FileInformationClass) {
302 
305  break;
307  BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION, FileName[0] );
308  break;
310  BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION, FileName[0] );
311  break;
313  BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName[0] );
314  break;
315  default:
317  }
318 
319  // Some additional arguments that affect the FSD behavior
321 
323  UDFAcquireResourceShared(&(NtReqFcb->MainResource), TRUE);
324  AcquiredFCB = TRUE;
325 
326  // We must determine the buffer pointer to be used. Since this
327  // routine could either be invoked directly in the context of the
328  // calling thread, or in the context of a worker thread, here is
329  // a general way of determining what we should use.
330  if(Irp->MdlAddress) {
332  if(!Buffer)
334  } else {
335  Buffer = (PUCHAR) Irp->UserBuffer;
336  if(!Buffer)
338  }
339 
340  // The method of determining where to look from and what to look for is
341  // unfortunately extremely confusing. However, here is a methodology
342  // we broadly adopt:
343  // (a) We have to maintain a search buffer per CCB structure.
344  // (b) This search buffer is initialized the very first time
345  // a query directory operation is performed using the file object.
346  // (For the UDF FSD, the search buffer is stored in the
347  // DirectorySearchPattern field)
348  // However, the caller still has the option of "overriding" this stored
349  // search pattern by supplying a new one in a query directory operation.
350  if(PtrSearchPattern &&
351  PtrSearchPattern->Buffer &&
352  !(PtrSearchPattern->Buffer[PtrSearchPattern->Length/sizeof(WCHAR) - 1])) {
353  PtrSearchPattern->Length -= sizeof(WCHAR);
354  }
355 
357  // Good idea from M$: we should continue search from NEXT item
358  // when FileIndex specified...
359  // Strange idea from M$: we should do it with EMPTY pattern...
360  PtrSearchPattern = NULL;
361  Ccb->CCBFlags |= UDF_CCB_MATCH_ALL;
362  } else if(PtrSearchPattern &&
363  PtrSearchPattern->Buffer &&
364  !UDFIsMatchAllMask(PtrSearchPattern, NULL) ) {
365 
366  Ccb->CCBFlags &= ~(UDF_CCB_MATCH_ALL |
369  // Once we have validated the search pattern, we must
370  // check whether we need to store this search pattern in
371  // the CCB.
372  if(Ccb->DirectorySearchPattern) {
373  MyFreePool__(Ccb->DirectorySearchPattern->Buffer);
374  MyFreePool__(Ccb->DirectorySearchPattern);
375  Ccb->DirectorySearchPattern = NULL;
376  }
377  // This must be the very first query request.
378  FirstTimeQuery = TRUE;
379 
380  // Now, allocate enough memory to contain the caller
381  // supplied search pattern and fill in the DirectorySearchPattern
382  // field in the CCB
383  Ccb->DirectorySearchPattern = (PUNICODE_STRING)MyAllocatePool__(NonPagedPool,sizeof(UNICODE_STRING));
384  if(!(Ccb->DirectorySearchPattern)) {
386  }
387  Ccb->DirectorySearchPattern->Length = PtrSearchPattern->Length;
388  Ccb->DirectorySearchPattern->MaximumLength = PtrSearchPattern->MaximumLength;
389  Ccb->DirectorySearchPattern->Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool,PtrSearchPattern->MaximumLength);
390  if(!(Ccb->DirectorySearchPattern->Buffer)) {
392  }
393  RtlCopyMemory(Ccb->DirectorySearchPattern->Buffer,PtrSearchPattern->Buffer,
394  PtrSearchPattern->MaximumLength);
395  if(FsRtlDoesNameContainWildCards(PtrSearchPattern)) {
396  Ccb->CCBFlags |= UDF_CCB_WILDCARD_PRESENT;
397  } else {
398  UDFBuildHashEntry(Vcb, PtrSearchPattern, cur_hashes = &(Ccb->hashes), HASH_POSIX | HASH_ULFN);
399  }
400  if(UDFCanNameBeA8dot3(PtrSearchPattern))
401  Ccb->CCBFlags |= UDF_CCB_CAN_BE_8_DOT_3;
402 
403  } else if(!Ccb->DirectorySearchPattern &&
404  !(Ccb->CCBFlags & UDF_CCB_MATCH_ALL) ) {
405 
406  // If the filename is not specified or is a single '*' then we will
407  // match all names.
408  FirstTimeQuery = TRUE;
409  PtrSearchPattern = NULL;
410  Ccb->CCBFlags |= UDF_CCB_MATCH_ALL;
411 
412  } else {
413  // The caller has not supplied any search pattern that we are
414  // forced to use. However, the caller had previously supplied
415  // a pattern (or we must have invented one) and we will use it.
416  // This is definitely not the first query operation on this
417  // directory using this particular file object.
418  if(Ccb->CCBFlags & UDF_CCB_MATCH_ALL) {
419  PtrSearchPattern = NULL;
420 /* if(Ccb->CurrentIndex)
421  Ccb->CurrentIndex++;*/
422  } else {
423  PtrSearchPattern = Ccb->DirectorySearchPattern;
424  if(!(Ccb->CCBFlags & UDF_CCB_WILDCARD_PRESENT)) {
425  cur_hashes = &(Ccb->hashes);
426  }
427  }
428  }
429 
431  // Caller has told us wherefrom to begin.
432  // We may need to round this to an appropriate directory entry
433  // entry alignment value.
434  NextMatch = pStackLocation->Parameters.QueryDirectory.FileIndex + 1;
435  } else if(IrpSp->Flags & SL_RESTART_SCAN) {
436  NextMatch = 0;
437  } else {
438  // Get the starting offset from the CCB.
439  // Remember to update this value on our way out from this function.
440  // But, do not update the CCB CurrentByteOffset field if our reach
441  // the end of the directory (or get an error reading the directory)
442  // while performing the search.
443  NextMatch = Ccb->CurrentIndex + 1; // Last good index
444  }
445 
446  FNM_Flags |= (Ccb->CCBFlags & UDF_CCB_WILDCARD_PRESENT) ? UDF_FNM_FLAG_CONTAINS_WC : 0;
447  // this is used only when mask is supplied
448  FNM_Flags |= (Ccb->CCBFlags & UDF_CCB_CAN_BE_8_DOT_3) ? UDF_FNM_FLAG_CAN_BE_8D3 : 0;
449 
450  // This is an additional verifying
451  if(!UDFIsADirectory(DirFileInfo)) {
453  }
454 
455  hDirIndex = DirFileInfo->Dloc->DirIndex;
456  if(!hDirIndex) {
458  }
459 
460  RC = STATUS_SUCCESS;
461  // Allocate buffer enough to save both DirInformation and FileName
463  sizeof(FILE_BOTH_DIR_INFORMATION)+((ULONG)UDF_NAME_LEN*sizeof(WCHAR)) );
464  if(!DirInformation) {
466  }
467  CurrentOffset=0;
468  BytesRemainingInBuffer = pStackLocation->Parameters.QueryDirectory.Length;
469  RtlZeroMemory(Buffer,BytesRemainingInBuffer);
470 
471  if((!FirstTimeQuery) && !UDFDirIndex(hDirIndex, (uint_di)NextMatch) ) {
473  }
474 
475  // One final note though:
476  // If we do not find a directory entry OR while searching we reach the
477  // end of the directory, then the return code should be set as follows:
478 
479  // (a) If any files have been returned (i.e. ReturnSingleEntry was FALSE
480  // and we did find at least one match), then return STATUS_SUCCESS
481  // (b) If no entry is being returned then:
482  // (i) If this is the first query i.e. FirstTimeQuery is TRUE
483  // then return STATUS_NO_SUCH_FILE
484  // (ii) Otherwise, return STATUS_NO_MORE_FILES
485 
486  while(TRUE) {
487  // If the user had requested only a single match and we have
488  // returned that, then we stop at this point.
489  if(ReturnSingleEntry && AtLeastOneFound) {
490  try_return(RC);
491  }
492  // We call UDFFindNextMatch to look down the next matching dirent.
493  RC = UDFFindNextMatch(Vcb, hDirIndex,&NextMatch,PtrSearchPattern, FNM_Flags, cur_hashes, &DirNdx);
494  // If we didn't receive next match, then we are at the end of the
495  // directory. If we have returned any files, we exit with
496  // success, otherwise we return STATUS_NO_MORE_FILES.
497  if(!NT_SUCCESS(RC)) {
498  RC = AtLeastOneFound ? STATUS_SUCCESS :
499  (FirstTimeQuery ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES);
500  try_return(RC);
501  }
502  // We found at least one matching file entry
503  AtLeastOneFound = TRUE;
504  if(!NT_SUCCESS(RC = UDFFileDirInfoToNT(Vcb, DirNdx, DirInformation))) {
505  // this happends when we can't allocate tmp buffers
506  try_return(RC);
507  }
508  DirInformation->FileIndex = NextMatch;
509  FileNameBytes = DirInformation->FileNameLength;
510 
511  if ((BaseLength + FileNameBytes) > BytesRemainingInBuffer) {
512  // We haven't successfully transfered current data &
513  // later NextMatch will be incremented. Thus we should
514  // prevent loosing information in such a way:
515  if(NextMatch) NextMatch --;
516  // If this won't fit and we have returned a previous entry then just
517  // return STATUS_SUCCESS. Otherwise
518  // use a status code of STATUS_BUFFER_OVERFLOW.
519  if(CurrentOffset) {
521  }
522  // strange policy...
524  FileNameBytes = BaseLength + FileNameBytes - BytesRemainingInBuffer;
526  }
527  // Now we have an entry to return to our caller.
528  // We'll case on the type of information requested and fill up
529  // the user buffer if everything fits.
530  switch (FileInformationClass) {
531 
535 
536  BothDirInformation = (PFILE_BOTH_DIR_INFORMATION)(Buffer + CurrentOffset);
537  RtlCopyMemory(BothDirInformation,DirInformation,BaseLength);
538  BothDirInformation->FileIndex = NextMatch;
539  BothDirInformation->FileNameLength = FileNameBytes;
540  break;
541 
543 
544  NamesInfo = (PFILE_NAMES_INFORMATION)(Buffer + CurrentOffset);
545  NamesInfo->FileIndex = NextMatch;
546  NamesInfo->FileNameLength = FileNameBytes;
547  break;
548 
549  default:
550  break;
551  }
552  if (FileNameBytes) {
553  // This is a Unicode name, we can copy the bytes directly.
554  RtlCopyMemory( (PVOID)(Buffer + CurrentOffset + BaseLength),
555  DirInformation->FileName, FileNameBytes );
556  }
557 
558  Information = CurrentOffset + BaseLength + FileNameBytes;
559 
560  // ((..._INFORMATION)(PointerToPreviousEntryInBuffer))->NextEntryOffset = CurrentOffset - LastOffset;
561  *((PULONG)(Buffer+LastOffset)) = CurrentOffset - LastOffset;
562  // Set up our variables for the next dirent.
563  FirstTimeQuery = FALSE;
564 
565  LastOffset = CurrentOffset;
566  PrevMatch = NextMatch;
567  NextMatch++;
568  CurrentOffset = UDFQuadAlign(Information);
569  BytesRemainingInBuffer = BufferLength - CurrentOffset;
570  }
571 
572 try_exit: NOTHING;
573 
574 
575  } _SEH2_FINALLY {
576 
577  if (PostRequest) {
578 
579  if (AcquiredFCB) {
581  UDFReleaseResource(&(NtReqFcb->MainResource));
582  }
583  // Map the users buffer and then post the request.
584  RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, BufferLength);
585  ASSERT(NT_SUCCESS(RC));
586 
587  RC = UDFPostRequest(PtrIrpContext, Irp);
588 
589  } else {
590 #ifdef UDF_DBG
591  if(!NT_SUCCESS(RC)) {
592  UDFPrint((" Not found\n"));
593  }
594 #endif // UDF_DBG
595  // Remember to update the CurrentByteOffset field in the CCB if required.
596  if(Ccb) Ccb->CurrentIndex = PrevMatch;
597 
598  if (AcquiredFCB) {
600  UDFReleaseResource(&(NtReqFcb->MainResource));
601  }
602  if (!_SEH2_AbnormalTermination()) {
603  // complete the IRP
604  Irp->IoStatus.Status = RC;
605  Irp->IoStatus.Information = Information;
607  // Free up the Irp Context
608  UDFReleaseIrpContext(PtrIrpContext);
609  }
610  }
611 
612  if(SearchPattern.Buffer) RtlFreeUnicodeString(&SearchPattern);
613  if(DirInformation) MyFreePool__(DirInformation);
614  } _SEH2_END;
615 
616  return(RC);
617 } // end UDFQueryDirectory()
618 
619 /*
620  Return: STATUS_NO_SUCH_FILE if no more files found
621 */
622 NTSTATUS
624  IN PVCB Vcb,
625  IN PDIR_INDEX_HDR hDirIndex,
626  IN PLONG CurrentNumber, // Must be modified in case, when we found next match
627  IN PUNICODE_STRING PtrSearchPattern,
628  IN UCHAR FNM_Flags,
629  IN PHASH_ENTRY hashes,
630  OUT PDIR_INDEX_ITEM* _DirNdx
631  )
632 {
633  LONG EntryNumber = (*CurrentNumber);
634  PDIR_INDEX_ITEM DirNdx;
635 
636 #define CanBe8dot3 (FNM_Flags & UDF_FNM_FLAG_CAN_BE_8D3)
637 #define IgnoreCase (FNM_Flags & UDF_FNM_FLAG_IGNORE_CASE)
638 #define ContainsWC (FNM_Flags & UDF_FNM_FLAG_CONTAINS_WC)
639 
640  for(;(DirNdx = UDFDirIndex(hDirIndex, EntryNumber));EntryNumber++) {
641  if(!DirNdx->FName.Buffer ||
642  UDFIsDeleted(DirNdx))
643  continue;
644  if(hashes &&
645  (DirNdx->hashes.hLfn != hashes->hLfn) &&
646  (DirNdx->hashes.hPosix != hashes->hPosix) &&
647  (!CanBe8dot3 || ((DirNdx->hashes.hDos != hashes->hLfn) && (DirNdx->hashes.hDos != hashes->hPosix))) )
648  continue;
649  if(UDFIsNameInExpression(Vcb, &(DirNdx->FName),PtrSearchPattern, NULL,IgnoreCase,
650  ContainsWC, CanBe8dot3 && !(DirNdx->FI_Flags & UDF_FI_FLAG_DOS),
651  EntryNumber < 2) &&
652  !(DirNdx->FI_Flags & UDF_FI_FLAG_FI_INTERNAL))
653  break;
654  }
655 
656  if(DirNdx) {
657  // Modify CurrentNumber to appropriate value
658  *CurrentNumber = EntryNumber;
659  *_DirNdx = DirNdx;
660  return STATUS_SUCCESS;
661  } else {
662  // Do not modify CurrentNumber because we have not found next match entry
663  return STATUS_NO_MORE_FILES;
664  }
665 } // end UDFFindNextMatch()
666 
667 /*************************************************************************
668 *
669 * Function: UDFNotifyChangeDirectory()
670 *
671 * Description:
672 * Handle the notify request.
673 *
674 * Expected Interrupt Level (for execution) :
675 *
676 * IRQL_PASSIVE_LEVEL
677 *
678 * Return Value: STATUS_SUCCESS/Error
679 *
680 *************************************************************************/
681 NTSTATUS
682 NTAPI
684  PtrUDFIrpContext PtrIrpContext,
685  PIRP Irp,
688  PtrUDFFCB Fcb,
689  PtrUDFCCB Ccb
690  )
691 {
694  BOOLEAN PostRequest = FALSE;
696  BOOLEAN CanWait = FALSE;
699  PVCB Vcb = NULL;
700  BOOLEAN AcquiredFCB = FALSE;
702 
703  UDFPrint(("UDFNotifyChangeDirectory\n"));
704 
705  _SEH2_TRY {
706 
707  // Validate the sent-in FCB
708  if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
709  !(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
710 
713  }
714 
715  NtReqFcb = Fcb->NTRequiredFCB;
716  CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
717  Vcb = Fcb->Vcb;
718 
719  // Acquire the FCB resource shared
721  if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), CanWait)) {
722  PostRequest = TRUE;
724  }
725  AcquiredFCB = TRUE;
726 
727  // If the file is marked as DELETE_PENDING then complete this
728  // request immediately.
729  if(Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) {
730  ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
732  }
733 
734  // Obtain some parameters sent by the caller
735  CompletionFilter = pStackLocation ->Parameters.NotifyDirectory.CompletionFilter;
737 
738  // If we wish to capture the subject context, we can do so as
739  // follows:
740  // {
741  // PSECURITY_SUBJECT_CONTEXT SubjectContext;
742  // SubjectContext = MyAllocatePool__(PagedPool,
743  // sizeof(SECURITY_SUBJECT_CONTEXT));
744  // SeCaptureSubjectContext(SubjectContext);
745  // }
746 
747  FsRtlNotifyFullChangeDirectory(Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), (PVOID)Ccb,
748  (Fcb->FileInfo->ParentFile) ? (PSTRING)&(Fcb->FCBName->ObjectName) : (PSTRING)&(UDFGlobalData.UnicodeStrRoot),
750  NULL, // UDFTraverseAccessCheck(...) ?
751  NULL); // SubjectContext ?
752 
753  RC = STATUS_PENDING;
754 
755  try_exit: NOTHING;
756 
757  } _SEH2_FINALLY {
758 
759  if (PostRequest) {
760  // Perform appropriate related post processing here
761  if (AcquiredFCB) {
763  UDFReleaseResource(&(NtReqFcb->MainResource));
764  AcquiredFCB = FALSE;
765  }
766  RC = UDFPostRequest(PtrIrpContext, Irp);
767  } else if (CompleteRequest) {
768 
769  if (!_SEH2_AbnormalTermination()) {
770  Irp->IoStatus.Status = RC;
771  Irp->IoStatus.Information = 0;
772  // Free up the Irp Context
773  UDFReleaseIrpContext(PtrIrpContext);
774  // complete the IRP
776  }
777 
778  } else {
779  // Simply free up the IrpContext since the IRP has been queued
781  UDFReleaseIrpContext(PtrIrpContext);
782  }
783 
784  // Release the FCB resources if acquired.
785  if (AcquiredFCB) {
787  UDFReleaseResource(&(NtReqFcb->MainResource));
788  AcquiredFCB = FALSE;
789  }
790 
791  } _SEH2_END;
792 
793  return(RC);
794 } // end UDFNotifyChangeDirectory()
#define UDF_CCB_CAN_BE_8_DOT_3
Definition: struct.h:169
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
UNICODE_STRING FName
Definition: udf_rel.h:173
UNICODE_STRING UnicodeStrRoot
Definition: udf_common.h:616
#define IN
Definition: typedefs.h:38
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
struct _FILE_BOTH_DIR_INFORMATION * PFILE_BOTH_DIR_INFORMATION
#define UDFPrint(Args)
Definition: udffs.h:225
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _UDFContextControlBlock * PtrUDFCCB
#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 FsRtlEnterFileSystem
uint8 UDFBuildHashEntry(IN PVCB Vcb, IN PUNICODE_STRING Name, OUT PHASH_ENTRY hashes, IN uint8 Mask)
Definition: dirtree.cpp:429
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1793
NTSTATUS NTAPI UDFDirControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dircntrl.cpp:57
#define FsRtlExitFileSystem
#define UDF_NAME_LEN
Definition: osta_misc.h:314
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID NTAPI FsRtlNotifyFullChangeDirectory(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)
Definition: notify.c:1458
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
unsigned char * PUCHAR
Definition: retypes.h:3
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
PDIR_INDEX_HDR DirIndex
Definition: udf_rel.h:312
LONG NTSTATUS
Definition: precomp.h:26
#define UDF_FCB_DELETE_ON_CLOSE
Definition: struct.h:309
__inline PDIR_INDEX_ITEM UDFDirIndex(IN PDIR_INDEX_HDR hDirNdx, IN uint_di i)
Definition: udf_info.h:1105
NTSTATUS UDFFileDirInfoToNT(IN PVCB Vcb, IN PDIR_INDEX_ITEM FileDirNdx, OUT PFILE_BOTH_DIR_INFORMATION NTFileInfo)
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
Definition: udf_rel.h:128
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define UDF_CCB_CASE_SENSETIVE
Definition: struct.h:159
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
Definition: cdstruc.h:504
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2239
#define HASH_POSIX
Definition: udf_info.h:75
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
NTSTATUS NTAPI UDFCommonDirControl(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: dircntrl.cpp:127
PUDF_DATALOC_INFO Dloc
Definition: udf_rel.h:367
uint16_t * PWCHAR
Definition: typedefs.h:54
PDEVICE_OBJECT TargetDeviceObject
Definition: struct.h:374
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
uint32 uint_di
Definition: udf_rel.h:29
_SEH2_TRY
Definition: create.c:4250
BOOLEAN __fastcall UDFCanNameBeA8dot3(IN PUNICODE_STRING Name)
Definition: namesup.cpp:266
#define IO_DISK_INCREMENT
Definition: iotypes.h:567
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define UDFIsADirectory(FileInfo)
Definition: udf_info.h:792
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define IoCompleteRequest
Definition: irp.c:1240
WCHAR * ObjectName
Definition: ntfs.h:520
struct _FILE_NAMES_INFORMATION * PFILE_NAMES_INFORMATION
Definition: bufpool.h:45
__inline PVOID MmGetSystemAddressForMdlSafer(IN PMDL Mdl)
Definition: ntifs_ex.h:101
uint32 IrpContextFlags
Definition: struct.h:364
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
#define MyAllocatePool__(type, size)
Definition: mem_tools.h:149
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define UDF_CCB_MATCH_ALL
Definition: struct.h:167
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
#define try_return(S)
Definition: cdprocs.h:2189
HASH_ENTRY hashes
Definition: udf_rel.h:206
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS NTAPI UDFQueryDirectory(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, PFILE_OBJECT FileObject, PtrUDFFCB Fcb, PtrUDFCCB Ccb)
Definition: dircntrl.cpp:216
#define MyFreePool__(addr)
Definition: mem_tools.h:152
#define UDF_FCB_DIRECTORY
Definition: struct.h:303
BOOLEAN UDFIsNameInExpression(IN PVCB Vcb, IN PUNICODE_STRING FileName, IN PUNICODE_STRING PtrSearchPattern, OUT PBOOLEAN DosOpen, IN BOOLEAN IgnoreCase, IN BOOLEAN ContainsWC, IN BOOLEAN CanBe8dot3, IN BOOLEAN KeepIntact)
Definition: namesup.cpp:156
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
* PFILE_OBJECT
Definition: iotypes.h:1954
#define UDF_FNM_FLAG_IGNORE_CASE
Definition: dircntrl.cpp:27
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
#define UDF_FCB_ROOT_DIRECTORY
Definition: struct.h:304
NTSTATUS NTAPI CompleteRequest(IN PIRP Irp, IN NTSTATUS Status, IN ULONG_PTR Information)
Definition: dispatch.c:19
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NtReqFcb
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:226
UDFData UDFGlobalData
Definition: udfinit.cpp:25
#define SL_WATCH_TREE
Definition: iotypes.h:1795
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
NTSTATUS NTAPI UDFNotifyChangeDirectory(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, PFILE_OBJECT FileObject, PtrUDFFCB Fcb, PtrUDFCCB Ccb)
Definition: dircntrl.cpp:683
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
struct _VCB * PVCB
Definition: fatstruc.h:556
#define UDFQuadAlign(Value)
Definition: udffs.h:196
#define UDFAcquireResourceShared(Resource, CanWait)
Definition: env_spec_w32.h:658
VOID UDFFlushTryBreak(IN PVCB Vcb)
Definition: flush.cpp:625
NTSTATUS UDFFindNextMatch(IN PVCB Vcb, IN PDIR_INDEX_HDR hDirIndex, IN PLONG CurrentNumber, IN PUNICODE_STRING PtrSearchPattern, IN UCHAR FNM_Flags, IN PHASH_ENTRY hashes, OUT PDIR_INDEX_ITEM *_DirNdx)
Definition: dircntrl.cpp:623
BOOLEAN __fastcall UDFIsMatchAllMask(IN PUNICODE_STRING Name, OUT BOOLEAN *DosOpen)
Definition: namesup.cpp:214
struct _FCB::@691::@694 Fcb
uint32 hPosix
Definition: udf_rel.h:131
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
NTSTATUS UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: misc.cpp:1128
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1792
_SEH2_END
Definition: create.c:4424
#define CanBe8dot3
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define UDF_FNM_FLAG_CONTAINS_WC
Definition: dircntrl.cpp:28
#define IgnoreCase
Definition: cdprocs.h:464
#define UDF_FI_FLAG_FI_INTERNAL
Given entry represents the file used for internal FS purposes & must be invisible.
Definition: udf_rel.h:221
#define HASH_ULFN
Definition: udf_info.h:76
#define ContainsWC
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB)
Definition: udffs.h:262
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
_SEH2_FINALLY
Definition: create.c:4395
#define UDF_FI_FLAG_DOS
Definition: udf_rel.h:225
unsigned int * PULONG
Definition: retypes.h:1
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2239
#define SL_RESTART_SCAN
Definition: iotypes.h:1791
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PVCB Vcb
Definition: cdstruc.h:939
uint32 hDos
Definition: udf_rel.h:129
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
IO_STACK_LOCATION * PEXTENDED_IO_STACK_LOCATION
Definition: ext2fs.h:174
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
_In_ PFCB Fcb
Definition: cdprocs.h:151
uint32 hLfn
Definition: udf_rel.h:130
uint8 FI_Flags
Definition: udf_rel.h:199
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define UDF_CCB_WILDCARD_PRESENT
Definition: struct.h:168
signed int * PLONG
Definition: retypes.h:5
#define UDFIsDeleted(DirNdx)
Definition: udf_info.h:788
Iosb Information
Definition: create.c:4377
NTSTATUS UDFLockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, BOOLEAN IsReadOperation, uint32 Length)
Definition: read.cpp:936
#define UDF_FNM_FLAG_CAN_BE_8D3
Definition: dircntrl.cpp:26