ReactOS 0.4.16-dev-91-g764881a
dircntrl.cpp
Go to the documentation of this file.
1
2// 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*************************************************************************/
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*************************************************************************/
126NTAPI
128 PtrUDFIrpContext PtrIrpContext,
129 PIRP Irp
130 )
131{
138 _SEH2_VOLATILE 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*************************************************************************/
215NTAPI
217 PtrUDFIrpContext PtrIrpContext,
218 PIRP Irp,
223 )
224{
226 BOOLEAN PostRequest = FALSE;
228 BOOLEAN CanWait = FALSE;
230 _SEH2_VOLATILE BOOLEAN AcquiredFCB = FALSE;
231 unsigned long BufferLength = 0;
232 UNICODE_STRING SearchPattern;
233 PUNICODE_STRING PtrSearchPattern;
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
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;
308 break;
310 BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION, FileName[0] );
311 break;
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
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
572try_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 }
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*/
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,
651 EntryNumber < 2) &&
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
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*************************************************************************/
682NTAPI
684 PtrUDFIrpContext PtrIrpContext,
685 PIRP Irp,
690 )
691{
694 BOOLEAN PostRequest = FALSE;
696 BOOLEAN CanWait = FALSE;
700 _SEH2_VOLATILE 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
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()
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
NTSTATUS UDFFileDirInfoToNT(IN PVCB Vcb, IN PDIR_INDEX_ITEM FileDirNdx, OUT PFILE_BOTH_DIR_INFORMATION NTFileInfo)
LONG NTSTATUS
Definition: precomp.h:26
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_return(S)
Definition: cdprocs.h:2179
struct _VCB * PVCB
Definition: fatstruc.h:557
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
#define UDF_FNM_FLAG_CONTAINS_WC
Definition: dircntrl.cpp:28
NTSTATUS NTAPI UDFDirControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: dircntrl.cpp:57
NTSTATUS NTAPI UDFCommonDirControl(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: dircntrl.cpp:127
NTSTATUS NTAPI UDFQueryDirectory(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, PFILE_OBJECT FileObject, PtrUDFFCB Fcb, PtrUDFCCB Ccb)
Definition: dircntrl.cpp:216
#define ContainsWC
#define UDF_FNM_FLAG_CAN_BE_8D3
Definition: dircntrl.cpp:26
#define IgnoreCase
Definition: cdprocs.h:461
NTSTATUS NTAPI UDFNotifyChangeDirectory(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PIO_STACK_LOCATION IrpSp, PFILE_OBJECT FileObject, PtrUDFFCB Fcb, PtrUDFCCB Ccb)
Definition: dircntrl.cpp:683
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
#define UDF_FNM_FLAG_IGNORE_CASE
Definition: dircntrl.cpp:27
#define CanBe8dot3
uint8 UDFBuildHashEntry(IN PVCB Vcb, IN PUNICODE_STRING Name, OUT PHASH_ENTRY hashes, IN uint8 Mask)
Definition: dirtree.cpp:429
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
NTSTATUS NTAPI CompleteRequest(IN PIRP Irp, IN NTSTATUS Status, IN ULONG_PTR Information)
Definition: dispatch.c:19
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
NTSTATUS UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: misc.cpp:1128
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define UDFAcquireResourceShared(Resource, CanWait)
Definition: env_spec_w32.h:658
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
#define NonPagedPool
Definition: env_spec_w32.h:307
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
#define NtReqFcb
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2243
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2241
VOID UDFFlushTryBreak(IN PVCB Vcb)
Definition: flush.cpp:625
struct _FILE_BOTH_DIR_INFORMATION * PFILE_BOTH_DIR_INFORMATION
@ FileDirectoryInformation
Definition: from_kernel.h:62
@ FileNamesInformation
Definition: from_kernel.h:73
@ FileFullDirectoryInformation
Definition: from_kernel.h:63
@ FileBothDirectoryInformation
Definition: from_kernel.h:64
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
struct _FILE_NAMES_INFORMATION * PFILE_NAMES_INFORMATION
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define NOTHING
Definition: input_list.c:10
#define MyAllocatePool__(type, size)
Definition: mem_tools.h:149
#define MyFreePool__(addr)
Definition: mem_tools.h:152
#define ASSERT(a)
Definition: mode.c:44
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
BOOLEAN __fastcall UDFIsMatchAllMask(IN PUNICODE_STRING Name, OUT BOOLEAN *DosOpen)
Definition: namesup.cpp:214
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
BOOLEAN __fastcall UDFCanNameBeA8dot3(IN PUNICODE_STRING Name)
Definition: namesup.cpp:266
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
__inline PVOID MmGetSystemAddressForMdlSafer(IN PMDL Mdl)
Definition: ntifs_ex.h:101
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
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:1487
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define UDF_NAME_LEN
Definition: osta_misc.h:314
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS UDFLockCallersBuffer(PtrUDFIrpContext PtrIrpContext, PIRP Irp, BOOLEAN IsReadOperation, uint32 Length)
Definition: read.cpp:936
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define _SEH2_VOLATILE
Definition: pseh2_64.h:169
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define UDF_CCB_CAN_BE_8_DOT_3
Definition: struct.h:169
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
struct _UDFContextControlBlock * PtrUDFCCB
#define UDF_CCB_CASE_SENSETIVE
Definition: struct.h:159
#define UDF_FCB_ROOT_DIRECTORY
Definition: struct.h:304
#define UDF_CCB_WILDCARD_PRESENT
Definition: struct.h:168
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
#define UDF_FCB_DELETE_ON_CLOSE
Definition: struct.h:309
#define UDF_FCB_DIRECTORY
Definition: struct.h:303
#define UDF_CCB_MATCH_ALL
Definition: struct.h:167
PVOID DeviceExtension
Definition: env_spec_w32.h:418
UNICODE_STRING FName
Definition: udf_rel.h:173
uint8 FI_Flags
Definition: udf_rel.h:199
HASH_ENTRY hashes
Definition: udf_rel.h:206
PVCB Vcb
Definition: cdstruc.h:933
struct _FCB::@729::@732 Fcb
WCHAR * ObjectName
Definition: ntfs.h:524
Definition: udf_rel.h:128
uint32 hLfn
Definition: udf_rel.h:130
uint32 hDos
Definition: udf_rel.h:129
uint32 hPosix
Definition: udf_rel.h:131
struct _IO_STACK_LOCATION::@3974::@3981 NotifyDirectory
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1575 Parameters
struct _IO_STACK_LOCATION::@3974::@3980 QueryDirectory
UNICODE_STRING UnicodeStrRoot
Definition: udf_common.h:616
uint32 IrpContextFlags
Definition: struct.h:364
PDEVICE_OBJECT TargetDeviceObject
Definition: struct.h:374
PDIR_INDEX_HDR DirIndex
Definition: udf_rel.h:312
PUDF_DATALOC_INFO Dloc
Definition: udf_rel.h:367
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define HASH_ULFN
Definition: udf_info.h:76
#define UDFIsDeleted(DirNdx)
Definition: udf_info.h:788
__inline PDIR_INDEX_ITEM UDFDirIndex(IN PDIR_INDEX_HDR hDirNdx, IN uint_di i)
Definition: udf_info.h:1105
#define UDFIsADirectory(FileInfo)
Definition: udf_info.h:792
#define HASH_POSIX
Definition: udf_info.h:75
uint32 uint_di
Definition: udf_rel.h:29
#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 UDF_FI_FLAG_DOS
Definition: udf_rel.h:225
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
#define UDFQuadAlign(Value)
Definition: udffs.h:194
UDFData UDFGlobalData
Definition: udfinit.cpp:25
#define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB)
Definition: udffs.h:260
#define UDFPrint(Args)
Definition: udffs.h:223
#define PEXTENDED_IO_STACK_LOCATION
Definition: udffs.h:119
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
#define SL_WATCH_TREE
Definition: iotypes.h:1839
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1837
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1836
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define SL_RESTART_SCAN
Definition: iotypes.h:1835
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180