2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSDirControl.cpp
39 #include "AFSCommon.h"
42 // Function: AFSDirControl
46 // This function is the IRP_MJ_DIRECTORY_CONTROL dispatch handler
50 // A status is returned for the handling of this request
54 AFSDirControl( IN PDEVICE_OBJECT LibDeviceObject,
57 UNREFERENCED_PARAMETER(LibDeviceObject);
58 NTSTATUS ntStatus = STATUS_SUCCESS;
59 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
64 switch( pIrpSp->MinorFunction )
67 case IRP_MN_QUERY_DIRECTORY:
70 ntStatus = AFSQueryDirectory( Irp);
75 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
78 ntStatus = AFSNotifyChangeDirectory( Irp);
85 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
90 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
95 "EXCEPTION - AFSDirControl\n");
97 AFSDumpTraceFilesFnc();
100 if( ntStatus != STATUS_PENDING)
103 AFSCompleteRequest( Irp,
111 AFSQueryDirectory( IN PIRP Irp)
114 NTSTATUS ntStatus = STATUS_SUCCESS;
115 NTSTATUS dStatus = STATUS_SUCCESS;
116 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
117 PIO_STACK_LOCATION pIrpSp;
120 BOOLEAN bInitialQuery = FALSE;
122 ULONG ulUserBufferLength;
123 PUNICODE_STRING puniArgFileName = NULL;
124 UNICODE_STRING uniTmpMaskName;
125 WCHAR wchMaskBuffer[ 4];
126 FILE_INFORMATION_CLASS FileInformationClass;
128 BOOLEAN bRestartScan;
129 BOOLEAN bReturnSingleEntry;
130 BOOLEAN bIndexSpecified;
131 ULONG ulNextEntry = 0;
132 ULONG ulLastEntry = 0;
133 PFILE_DIRECTORY_INFORMATION pDirInfo;
134 PFILE_FULL_DIR_INFORMATION pFullDirInfo;
135 PFILE_BOTH_DIR_INFORMATION pBothDirInfo;
136 PFILE_NAMES_INFORMATION pNamesInfo;
138 ULONG ulBytesConverted;
139 AFSDirectoryCB *pDirEntry = NULL;
140 BOOLEAN bReleaseMain = FALSE;
141 BOOLEAN bReleaseFcb = FALSE;
142 AFSFileInfoCB stFileInfo;
143 AFSObjectInfoCB *pObjectInfo = NULL;
144 ULONG ulAdditionalAttributes = 0;
150 // Get the current Stack location
151 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
153 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
154 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
159 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
160 AFS_TRACE_LEVEL_ERROR,
161 "AFSQueryDirectory Attempted access (%p) when pFcb == NULL\n",
164 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
167 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
168 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
169 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
173 AFS_TRACE_LEVEL_ERROR,
174 "AFSQueryDirectory Attempted access (%p) to non-directory Fcb %p NodeType %u\n",
177 pFcb->Header.NodeTypeCode);
181 try_return( ntStatus = STATUS_INVALID_PARAMETER);
185 // Set the enumeration event ...
188 AFSSetEnumerationEvent( pFcb);
190 // Reference our input parameters to make things easier
191 ulUserBufferLength = pIrpSp->Parameters.QueryDirectory.Length;
193 FileInformationClass = pIrpSp->Parameters.QueryDirectory.FileInformationClass;
194 ulFileIndex = pIrpSp->Parameters.QueryDirectory.FileIndex;
196 puniArgFileName = (PUNICODE_STRING)pIrpSp->Parameters.QueryDirectory.FileName;
198 bRestartScan = BooleanFlagOn( pIrpSp->Flags, SL_RESTART_SCAN);
199 bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
200 bIndexSpecified = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
202 bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED));
207 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
208 AFS_TRACE_LEVEL_VERBOSE,
209 "AFSQueryDirectory Enumerating content for parent %wZ Initial Query\n",
210 &pCcb->DirectoryCB->NameInformation.FileName);
212 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
213 AFS_TRACE_LEVEL_VERBOSE,
214 "AFSQueryDirectory Acquiring Dcb lock %p EXCL %08lX\n",
215 &pFcb->NPFcb->Resource,
216 PsGetCurrentThread());
218 AFSAcquireExcl( &pFcb->NPFcb->Resource,
226 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
227 AFS_TRACE_LEVEL_VERBOSE,
228 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
229 &pCcb->DirectoryCB->NameInformation.FileName);
231 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
232 AFS_TRACE_LEVEL_VERBOSE,
233 "AFSQueryDirectory Acquiring Dcb lock %p SHARED %08lX\n",
234 &pFcb->NPFcb->Resource,
235 PsGetCurrentThread());
237 AFSAcquireShared( &pFcb->NPFcb->Resource,
244 // Grab the directory node hdr tree lock while parsing the directory
248 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
254 // Before attempting to insert the new entry, check if we need to validate the parent
257 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
260 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
261 AFS_TRACE_LEVEL_VERBOSE,
262 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
263 &pCcb->DirectoryCB->NameInformation.FileName,
264 pFcb->ObjectInformation->FileId.Cell,
265 pFcb->ObjectInformation->FileId.Volume,
266 pFcb->ObjectInformation->FileId.Vnode,
267 pFcb->ObjectInformation->FileId.Unique);
269 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
272 if( !NT_SUCCESS( ntStatus))
275 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
276 AFS_TRACE_LEVEL_ERROR,
277 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
278 &pCcb->DirectoryCB->NameInformation.FileName,
279 pFcb->ObjectInformation->FileId.Cell,
280 pFcb->ObjectInformation->FileId.Volume,
281 pFcb->ObjectInformation->FileId.Vnode,
282 pFcb->ObjectInformation->FileId.Unique,
285 try_return( ntStatus);
289 // Perform a new snapshot of the directory
292 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
295 ntStatus = AFSSnapshotDirectory( pFcb,
299 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
301 if( !NT_SUCCESS( ntStatus))
304 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
305 AFS_TRACE_LEVEL_ERROR,
306 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
307 &pCcb->DirectoryCB->NameInformation.FileName,
311 try_return( ntStatus);
315 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
318 // We can now safely drop the lock on the node
321 AFSReleaseResource( &pFcb->NPFcb->Resource);
326 // Start processing the data
329 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
335 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
338 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
341 // Check if initial on this map
345 ntStatus = AFSSnapshotDirectory( pFcb,
349 if( !NT_SUCCESS( ntStatus))
352 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
354 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
355 AFS_TRACE_LEVEL_ERROR,
356 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
357 &pCcb->DirectoryCB->NameInformation.FileName,
361 try_return( ntStatus);
364 SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
366 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
368 // build mask if none
369 if( puniArgFileName == NULL)
371 puniArgFileName = &uniTmpMaskName;
372 puniArgFileName->Length = 0;
373 puniArgFileName->Buffer = NULL;
376 if( puniArgFileName->Length == 0)
379 puniArgFileName->Length = sizeof(WCHAR);
380 puniArgFileName->MaximumLength = (USHORT)4;
383 if( puniArgFileName->Buffer == NULL)
386 puniArgFileName->Buffer = wchMaskBuffer;
388 RtlZeroMemory( wchMaskBuffer,
391 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
396 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
397 ( puniArgFileName->Buffer[0] == L'*')))
400 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
405 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
406 ( puniArgFileName->Buffer[0] == L'<')) ||
407 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
408 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
411 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
415 // Build the name for procesisng
418 pCcb->MaskName.Length = puniArgFileName->Length;
419 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
421 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
422 pCcb->MaskName.Length,
423 AFS_GENERIC_MEMORY_6_TAG);
425 if( pCcb->MaskName.Buffer == NULL)
428 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
431 if( FsRtlDoesNameContainWildCards( puniArgFileName))
434 RtlUpcaseUnicodeString( &pCcb->MaskName,
438 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
440 if( FsRtlIsNameInExpression( &pCcb->MaskName,
445 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
451 RtlCopyMemory( pCcb->MaskName.Buffer,
452 puniArgFileName->Buffer,
453 pCcb->MaskName.Length);
455 if( RtlCompareUnicodeString( &AFSPIOCtlName,
459 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
463 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
465 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
468 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
470 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
472 bReleaseMain = FALSE;
474 AFSAcquireExcl( &pFcb->NPFcb->Resource,
477 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
480 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
482 if( !NT_SUCCESS( ntStatus))
485 AFSReleaseResource( &pFcb->NPFcb->Resource);
487 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
488 AFS_TRACE_LEVEL_ERROR,
489 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
490 &pCcb->DirectoryCB->NameInformation.FileName,
494 try_return( ntStatus);
498 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
503 AFSReleaseResource( &pFcb->NPFcb->Resource);
505 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
510 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
511 AFS_TRACE_LEVEL_VERBOSE,
512 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
513 &pCcb->DirectoryCB->NameInformation.FileName,
518 // Check if we need to start from index
523 // Need to set up the initial point for the query
526 pCcb->CurrentDirIndex = ulFileIndex - 1;
529 // Check if we need to restart the scan
530 else if( bRestartScan)
534 // Reset the current scan processing
537 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
540 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
545 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
549 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
551 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
553 bReleaseMain = FALSE;
555 switch( FileInformationClass)
558 case FileDirectoryInformation:
560 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
564 case FileFullDirectoryInformation:
566 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
570 case FileNamesInformation:
572 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
576 case FileBothDirectoryInformation:
578 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
582 case FileIdBothDirectoryInformation:
584 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
589 case FileIdFullDirectoryInformation:
591 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
598 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
599 AFS_TRACE_LEVEL_ERROR,
600 "AFSQueryDirectory (%p) Unknown FileInformationClass %u\n",
602 FileInformationClass);
604 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
610 ULONG ulBytesRemainingInBuffer;
613 // Drop the DirOpenReferenceCount held during a prior
614 // execution of the loop
617 if ( pDirEntry != NULL)
620 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
622 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
623 AFS_TRACE_LEVEL_VERBOSE,
624 "AFSQueryDirectory Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
625 &pDirEntry->NameInformation.FileName,
630 ASSERT( lCount >= 0);
635 ulAdditionalAttributes = 0;
638 // If the user had requested only a single match and we have
639 // returned that, then we stop at this point.
642 if( bReturnSingleEntry && ulNextEntry != 0)
645 try_return( ntStatus);
649 // On Success, pDirEntry has a held DirOpenReferenceCount
652 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
655 if( pDirEntry == NULL)
658 if( ulNextEntry == 0)
661 if( ( bInitialQuery ||
663 pCcb->MaskName.Buffer != NULL)
665 ntStatus = STATUS_NO_SUCH_FILE;
669 ntStatus = STATUS_NO_MORE_FILES;
673 try_return( ntStatus);
677 // Skip the entry if it is pending delete or deleted
680 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
681 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
687 pObjectInfo = pDirEntry->ObjectInformation;
690 // Apply the name filter if there is one
693 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
697 // Only returning directories?
700 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
703 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
709 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
713 // Are we doing a wild card search?
716 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
719 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
720 &pDirEntry->NameInformation.FileName,
731 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
737 // See if this is a match for a case insensitive search
740 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
753 // Be sure the information is valid
754 // We don't worry about entries while enumerating the directory
757 if ( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
760 ntStatus = AFSValidateEntry( pDirEntry,
764 if ( NT_SUCCESS( ntStatus))
767 ClearFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
772 ntStatus = STATUS_SUCCESS;
776 pObjectInfo = pDirEntry->ObjectInformation;
778 // Here are the rules concerning filling up the buffer:
780 // 1. The Io system guarantees that there will always be
781 // enough room for at least one base record.
783 // 2. If the full first record (including file name) cannot
784 // fit, as much of the name as possible is copied and
785 // STATUS_BUFFER_OVERFLOW is returned.
787 // 3. If a subsequent record cannot completely fit into the
788 // buffer, none of it (as in 0 bytes) is copied, and
789 // STATUS_SUCCESS is returned. A subsequent query will
790 // pick up with this record.
792 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
794 if( ( ulNextEntry != 0) &&
795 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
796 ( ulUserBufferLength < ulNextEntry) ) )
800 // Back off our current index
803 pCcb->CurrentDirIndex--;
805 try_return( ntStatus = STATUS_SUCCESS);
810 // For Symlinks and Mount Points the reparse point attribute
811 // must be associated with the directory entry. In addition,
812 // for Symlinks it must be determined if the target object is
813 // a directory or not. If so, the directory attribute must be
814 // specified. Mount points always refer to directories and
815 // must have the directory attribute set.
818 switch( pObjectInfo->FileType)
821 case AFS_FILE_TYPE_MOUNTPOINT:
822 case AFS_FILE_TYPE_DFSLINK:
825 ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
830 case AFS_FILE_TYPE_SYMLINK:
834 // Go grab the file information for this entry
835 // No worries on failures since we will just display
836 // pseudo information
839 RtlZeroMemory( &stFileInfo,
840 sizeof( AFSFileInfoCB));
842 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
850 if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
853 ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY;
857 ulAdditionalAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
864 // Check if the name begins with a . and we are hiding them
867 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
868 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
869 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
872 ulAdditionalAttributes |= FILE_ATTRIBUTE_HIDDEN;
876 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
877 AFS_TRACE_LEVEL_VERBOSE,
878 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
879 &pCcb->DirectoryCB->NameInformation.FileName,
880 &pDirEntry->NameInformation.FileName);
882 // Zero the base part of the structure.
883 RtlZeroMemory( &pBuffer[ ulNextEntry],
886 switch( FileInformationClass)
889 // Now fill the base parts of the structure that are applicable.
890 case FileIdBothDirectoryInformation:
891 case FileBothDirectoryInformation:
893 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
895 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
897 if( pDirEntry->NameInformation.ShortNameLength > 0)
899 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
900 &pDirEntry->NameInformation.ShortName[ 0],
901 pBothDirInfo->ShortNameLength);
904 case FileIdFullDirectoryInformation:
905 case FileFullDirectoryInformation:
907 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
908 pFullDirInfo->EaSize = 0;
910 case FileDirectoryInformation:
912 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
914 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
917 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
918 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
919 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
920 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
922 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
923 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
925 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
927 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
931 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
937 pDirInfo->CreationTime = pObjectInfo->CreationTime;
938 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
939 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
940 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
942 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
943 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
945 if ( ulAdditionalAttributes && pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
948 pDirInfo->FileAttributes = ulAdditionalAttributes;
953 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
957 pDirInfo->FileIndex = pDirEntry->FileIndex;
958 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
963 case FileNamesInformation:
965 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
966 pNamesInfo->FileIndex = pDirEntry->FileIndex;
967 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
974 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
975 AFS_TRACE_LEVEL_ERROR,
976 "AFSQueryDirectory (%p) Unknown FileInformationClass %u\n",
978 FileInformationClass);
980 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
984 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
985 pDirEntry->NameInformation.FileName.Length :
986 ulBytesRemainingInBuffer - ulBaseLength;
988 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
989 pDirEntry->NameInformation.FileName.Buffer,
992 // Set up the previous next entry offset
993 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
995 // And indicate how much of the user buffer we have currently
997 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
999 // Check for the case that a single entry doesn't fit.
1000 // This should only get this far on the first entry.
1001 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
1004 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
1007 dStatus = STATUS_SUCCESS;
1009 // Set ourselves up for the next iteration
1010 ulLastEntry = ulNextEntry;
1011 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
1016 if ( pDirEntry != NULL)
1019 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1021 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1022 AFS_TRACE_LEVEL_VERBOSE,
1023 "AFSQueryDirectory Decrement8 count on %wZ DE %p Ccb %p Cnt %d\n",
1024 &pDirEntry->NameInformation.FileName,
1029 ASSERT( lCount >= 0);
1035 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1041 AFSReleaseResource( &pFcb->NPFcb->Resource);
1047 AFSClearEnumerationEvent( pFcb);
1055 AFSNotifyChangeDirectory( IN PIRP Irp)
1058 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1059 PIO_STACK_LOCATION pIrpSp;
1060 AFSFcb *pFcb = NULL;
1061 AFSCcb *pCcb = NULL;
1062 ULONG ulCompletionFilter;
1064 BOOLEAN bReleaseLock = FALSE;
1069 // Get the current Stack location
1070 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
1072 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1073 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1079 AFS_TRACE_LEVEL_ERROR,
1080 "AFSNotifyChangeDirectory Attempted access (%p) when pFcb == NULL\n",
1083 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1086 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1087 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1088 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1091 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1092 AFS_TRACE_LEVEL_ERROR,
1093 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1094 &pCcb->DirectoryCB->NameInformation.FileName,
1095 pFcb->Header.NodeTypeCode);
1097 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1100 // Reference our input parameter to make things easier
1101 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1102 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1104 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1105 AFS_TRACE_LEVEL_VERBOSE,
1106 "AFSNotifyChangeDirectory Acquiring Dcb lock %p EXCL %08lX\n",
1107 &pFcb->NPFcb->Resource,
1108 PsGetCurrentThread());
1110 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1113 bReleaseLock = TRUE;
1116 // Check if the node has already been deleted
1119 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1122 try_return( ntStatus = STATUS_FILE_DELETED);
1124 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1127 try_return( ntStatus = STATUS_DELETE_PENDING);
1130 // Call the Fsrtl package to process the request.
1131 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1137 if( !NT_SUCCESS( ntStatus))
1139 try_return( ntStatus);
1142 ntStatus = STATUS_PENDING;
1149 AFSReleaseResource( &pFcb->NPFcb->Resource);
1157 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1161 AFSDirectoryCB *pDirEntry = NULL;
1162 NTSTATUS ntStatus = STATUS_SUCCESS;
1163 AFSSnapshotHdr *pSnapshotHdr = NULL;
1164 AFSSnapshotEntry *pSnapshotEntry = NULL;
1171 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1174 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1178 // Is this a PIOCtl query
1181 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1184 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1185 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1188 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1190 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1191 AFS_TRACE_LEVEL_VERBOSE,
1192 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1193 &pDirEntry->NameInformation.FileName,
1194 ObjectInfo->FileId.Cell,
1195 ObjectInfo->FileId.Volume,
1196 ObjectInfo->FileId.Vnode,
1197 ObjectInfo->FileId.Unique);
1200 Ccb->CurrentDirIndex++;
1202 try_return( ntStatus);
1205 Ccb->CurrentDirIndex++;
1207 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1211 // Return the .. entry
1214 pDirEntry = AFSGlobalDotDirEntry;
1216 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1217 AFS_TRACE_LEVEL_VERBOSE,
1218 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1219 &pDirEntry->NameInformation.FileName,
1220 ObjectInfo->FileId.Cell,
1221 ObjectInfo->FileId.Volume,
1222 ObjectInfo->FileId.Vnode,
1223 ObjectInfo->FileId.Unique);
1225 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1229 // Return the .. entry
1232 pDirEntry = AFSGlobalDotDotDirEntry;
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1237 &pDirEntry->NameInformation.FileName,
1238 ObjectInfo->FileId.Cell,
1239 ObjectInfo->FileId.Volume,
1240 ObjectInfo->FileId.Vnode,
1241 ObjectInfo->FileId.Unique);
1246 pSnapshotHdr = Ccb->DirectorySnapshot;
1248 if( pSnapshotHdr == NULL ||
1249 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1252 try_return( ntStatus);
1255 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1257 ulCount = Ccb->CurrentDirIndex;
1259 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1260 AFS_TRACE_LEVEL_VERBOSE,
1261 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1265 // Get to a valid entry
1268 while( ulCount < pSnapshotHdr->EntryCount)
1273 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1274 AFS_TRACE_LEVEL_VERBOSE,
1275 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1276 pSnapshotEntry->NameHash);
1278 if( pSnapshotEntry->NameHash == 0)
1284 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1285 pSnapshotEntry->NameHash,
1288 if( !NT_SUCCESS( ntStatus) ||
1292 if( pDirEntry != NULL)
1295 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1296 AFS_TRACE_LEVEL_VERBOSE,
1297 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1298 &pDirEntry->NameInformation.FileName,
1299 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1300 ObjectInfo->FileId.Cell,
1301 ObjectInfo->FileId.Volume,
1302 ObjectInfo->FileId.Vnode,
1303 ObjectInfo->FileId.Unique);
1309 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1310 AFS_TRACE_LEVEL_VERBOSE,
1311 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1312 ObjectInfo->FileId.Cell,
1313 ObjectInfo->FileId.Volume,
1314 ObjectInfo->FileId.Vnode,
1315 ObjectInfo->FileId.Unique);
1321 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1322 AFS_TRACE_LEVEL_VERBOSE,
1323 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1324 pSnapshotEntry->NameHash,
1325 ObjectInfo->FileId.Cell,
1326 ObjectInfo->FileId.Volume,
1327 ObjectInfo->FileId.Vnode,
1328 ObjectInfo->FileId.Unique);
1334 Ccb->CurrentDirIndex++;
1340 if( pDirEntry != NULL)
1343 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1345 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1346 AFS_TRACE_LEVEL_VERBOSE,
1347 "AFSLocateNextDirEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1348 &pDirEntry->NameInformation.FileName,
1353 ASSERT( lCount >= 0);
1356 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1358 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1365 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1370 AFSDirectoryCB *pDirEntry = NULL;
1371 NTSTATUS ntStatus = STATUS_SUCCESS;
1372 AFSSnapshotHdr *pSnapshotHdr = NULL;
1373 AFSSnapshotEntry *pSnapshotEntry = NULL;
1379 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1382 Ccb->CurrentDirIndex = DirIndex;
1384 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1388 // Return the .. entry
1391 pDirEntry = AFSGlobalDotDirEntry;
1393 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1397 // Return the .. entry
1400 pDirEntry = AFSGlobalDotDotDirEntry;
1405 pSnapshotHdr = Ccb->DirectorySnapshot;
1407 if( pSnapshotHdr == NULL ||
1408 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1411 try_return( ntStatus);
1414 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1416 ulCount = Ccb->CurrentDirIndex;
1419 // Get to a valid entry
1422 while( ulCount < pSnapshotHdr->EntryCount)
1427 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1428 pSnapshotEntry->NameHash,
1431 if( !NT_SUCCESS( ntStatus) ||
1432 ( pDirEntry != NULL &&
1433 pDirEntry->FileIndex == DirIndex))
1444 if( pDirEntry != NULL)
1447 Ccb->CurrentDirIndex = ulCount;
1453 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1460 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1462 IN BOOLEAN ResetIndex)
1465 NTSTATUS ntStatus = STATUS_SUCCESS;
1466 AFSSnapshotHdr *pSnapshotHdr = NULL;
1467 AFSSnapshotEntry *pSnapshotEntry = NULL;
1468 AFSDirectoryCB *pDirEntry = NULL;
1477 // Set it up so we still get the . and .. entries for empty directories
1480 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1483 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1488 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1492 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1496 // If we have a snapshot then clear it out
1499 if( Ccb->DirectorySnapshot != NULL)
1502 AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
1504 Ccb->DirectorySnapshot = NULL;
1507 try_return( ntStatus);
1511 // Allocate our snapshot buffer for this enumeration
1514 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1515 sizeof( AFSSnapshotHdr) +
1516 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1517 sizeof( AFSSnapshotEntry)),
1518 AFS_DIR_SNAPSHOT_TAG);
1520 if( pSnapshotHdr == NULL)
1523 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1526 RtlZeroMemory( pSnapshotHdr,
1527 sizeof( AFSSnapshotHdr) +
1528 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1529 sizeof( AFSSnapshotEntry)));
1531 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1533 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1536 // Populate our snapshot
1539 pSnapshotEntry = pSnapshotHdr->TopEntry;
1541 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1543 while( pDirEntry != NULL)
1546 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1547 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1548 !AFSIsNameInSnapshot( pSnapshotHdr,
1549 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1552 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1553 AFS_TRACE_LEVEL_VERBOSE,
1554 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1555 pSnapshotHdr->EntryCount,
1556 &pDirEntry->NameInformation.FileName,
1557 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1559 Fcb->ObjectInformation->FileId.Cell,
1560 Fcb->ObjectInformation->FileId.Volume,
1561 Fcb->ObjectInformation->FileId.Vnode,
1562 Fcb->ObjectInformation->FileId.Unique);
1564 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1571 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1572 AFS_TRACE_LEVEL_VERBOSE,
1573 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1574 pSnapshotHdr->EntryCount,
1575 &pDirEntry->NameInformation.FileName,
1576 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1578 Fcb->ObjectInformation->FileId.Cell,
1579 Fcb->ObjectInformation->FileId.Volume,
1580 Fcb->ObjectInformation->FileId.Vnode,
1581 Fcb->ObjectInformation->FileId.Unique);
1584 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1587 if( Ccb->DirectorySnapshot != NULL)
1590 AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
1592 Ccb->DirectorySnapshot = NULL;
1595 Ccb->DirectorySnapshot = pSnapshotHdr;
1606 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1608 IN BOOLEAN WatchTree,
1609 IN ULONG CompletionFilter,
1613 NTSTATUS ntStatus = STATUS_SUCCESS;
1614 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1620 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1624 // Build a dir name based on the FID of the file
1627 if( Ccb->NotifyMask.Buffer == NULL)
1630 Ccb->NotifyMask.Length = 0;
1631 Ccb->NotifyMask.MaximumLength = 1024;
1633 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1634 Ccb->NotifyMask.MaximumLength,
1635 AFS_GENERIC_MEMORY_7_TAG);
1637 if( Ccb->NotifyMask.Buffer == NULL)
1640 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1643 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1644 Ccb->NotifyMask.MaximumLength,
1645 L"\\%08lX.%08lX.%08lX.%08lX",
1646 ObjectInfo->FileId.Cell,
1647 ObjectInfo->FileId.Volume,
1648 ObjectInfo->FileId.Vnode,
1649 ObjectInfo->FileId.Unique);
1651 if( !NT_SUCCESS( ntStatus))
1654 try_return( ntStatus);
1657 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1658 (size_t)Ccb->NotifyMask.MaximumLength,
1661 if( !NT_SUCCESS( ntStatus))
1664 try_return( ntStatus);
1667 Ccb->NotifyMask.Length = (USHORT)sztLength;
1670 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1671 AFS_TRACE_LEVEL_VERBOSE,
1672 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %p Filter %08lX Tree %02lX\n",
1678 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1679 &pDeviceExt->Specific.Control.DirNotifyList,
1681 (PSTRING)&Ccb->NotifyMask,
1692 if( !NT_SUCCESS( ntStatus))
1695 if( Ccb->NotifyMask.Buffer != NULL)
1698 AFSExFreePoolWithTag( Ccb->NotifyMask.Buffer, AFS_GENERIC_MEMORY_7_TAG);
1700 Ccb->NotifyMask.Buffer = NULL;
1704 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1711 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1713 IN ULONG NotifyFilter,
1714 IN ULONG NotificationAction)
1717 NTSTATUS ntStatus = STATUS_SUCCESS;
1718 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1719 UNICODE_STRING uniName, uniComponentName;
1721 USHORT usNameOffset = 0;
1726 uniName.Buffer = NULL;
1728 if( ParentObjectInfo == NULL ||
1729 AFSGlobalRoot == NULL)
1732 try_return( ntStatus);
1738 RtlInitUnicodeString( &uniComponentName,
1744 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1748 // Build a dir name based on the FID of the file
1752 uniName.MaximumLength = 1024 + uniComponentName.Length;
1754 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1755 uniName.MaximumLength,
1756 AFS_GENERIC_MEMORY_8_TAG);
1758 if( uniName.Buffer == NULL)
1761 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1764 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1765 uniName.MaximumLength,
1766 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1767 ParentObjectInfo->FileId.Cell,
1768 ParentObjectInfo->FileId.Volume,
1769 ParentObjectInfo->FileId.Vnode,
1770 ParentObjectInfo->FileId.Unique,
1773 if( !NT_SUCCESS( ntStatus))
1776 try_return( ntStatus);
1779 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1780 (size_t)uniName.MaximumLength,
1783 if( !NT_SUCCESS( ntStatus))
1786 try_return( ntStatus);
1789 uniName.Length = (USHORT)sztLength;
1791 usNameOffset = uniName.Length - uniComponentName.Length;
1793 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1794 AFS_TRACE_LEVEL_VERBOSE,
1795 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1801 uniComponentName.Length);
1803 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1804 &pDeviceExt->Specific.Control.DirNotifyList,
1816 if( uniName.Buffer != NULL)
1819 AFSExFreePoolWithTag( uniName.Buffer, AFS_GENERIC_MEMORY_8_TAG);
1826 // For use with FsRtlNotifyFilterChangeDirectory but must
1827 // be implemented in the Framework because the library can
1831 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1832 IN void *FilterContext)
1834 UNREFERENCED_PARAMETER(NotifyContext);
1835 UNREFERENCED_PARAMETER(FilterContext);
1836 BOOLEAN bReturn = TRUE;
1847 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1851 BOOLEAN bIsInSnapshot = FALSE;
1852 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1855 while( ulCount < SnapshotHdr->EntryCount)
1858 if( pSnapshotEntry->NameHash == HashIndex)
1861 bIsInSnapshot = TRUE;
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1870 else if( pSnapshotEntry->NameHash == 0)
1881 return bIsInSnapshot;