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,
58 NTSTATUS ntStatus = STATUS_SUCCESS;
59 ULONG ulRequestType = 0;
60 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
66 switch( pIrpSp->MinorFunction )
69 case IRP_MN_QUERY_DIRECTORY:
72 ntStatus = AFSQueryDirectory( Irp);
77 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
80 ntStatus = AFSNotifyChangeDirectory( Irp);
87 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
92 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
97 "EXCEPTION - AFSDirControl\n");
99 AFSDumpTraceFilesFnc();
102 if( ntStatus != STATUS_PENDING)
105 AFSCompleteRequest( Irp,
113 AFSQueryDirectory( IN PIRP Irp)
116 NTSTATUS ntStatus = STATUS_SUCCESS;
117 NTSTATUS dStatus = STATUS_SUCCESS;
118 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
119 PIO_STACK_LOCATION pIrpSp;
122 BOOLEAN bInitialQuery = FALSE;
125 ULONG ulUserBufferLength;
126 PUNICODE_STRING puniArgFileName = NULL;
127 UNICODE_STRING uniTmpMaskName;
128 UNICODE_STRING uniDirUniBuf;
129 WCHAR wchMaskBuffer[ 4];
130 FILE_INFORMATION_CLASS FileInformationClass;
131 ULONG ulFileIndex, ulDOSFileIndex;
132 BOOLEAN bRestartScan;
133 BOOLEAN bReturnSingleEntry;
134 BOOLEAN bIndexSpecified;
135 ULONG ulNextEntry = 0;
136 ULONG ulLastEntry = 0;
138 PFILE_DIRECTORY_INFORMATION pDirInfo;
139 PFILE_FULL_DIR_INFORMATION pFullDirInfo;
140 PFILE_BOTH_DIR_INFORMATION pBothDirInfo;
141 PFILE_NAMES_INFORMATION pNamesInfo;
143 ULONG ulBytesConverted;
144 AFSDirectoryCB *pDirEntry = NULL;
145 BOOLEAN bReleaseMain = FALSE;
146 BOOLEAN bReleaseFcb = FALSE;
147 ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN;
148 AFSFileInfoCB stFileInfo;
149 BOOLEAN bUseFileInfo = TRUE;
150 AFSObjectInfoCB *pObjectInfo = NULL;
151 ULONG ulAdditionalAttributes = 0;
157 // Get the current Stack location
158 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
160 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
161 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
166 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
167 AFS_TRACE_LEVEL_ERROR,
168 "AFSQueryDirectory Attempted access (%08lX) when pFcb == NULL\n",
171 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
174 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
175 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
176 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
179 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
180 AFS_TRACE_LEVEL_ERROR,
181 "AFSQueryDirectory Attempted access (%08lX) to non-directory Fcb %08lX NodeType %u\n",
184 pFcb->Header.NodeTypeCode);
188 try_return( ntStatus = STATUS_INVALID_PARAMETER);
192 // Set the enumeration event ...
195 AFSSetEnumerationEvent( pFcb);
197 // Reference our input parameters to make things easier
198 ulUserBufferLength = pIrpSp->Parameters.QueryDirectory.Length;
200 FileInformationClass = pIrpSp->Parameters.QueryDirectory.FileInformationClass;
201 ulFileIndex = pIrpSp->Parameters.QueryDirectory.FileIndex;
203 puniArgFileName = (PUNICODE_STRING)pIrpSp->Parameters.QueryDirectory.FileName;
205 bRestartScan = BooleanFlagOn( pIrpSp->Flags, SL_RESTART_SCAN);
206 bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
207 bIndexSpecified = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
209 bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED));
214 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
215 AFS_TRACE_LEVEL_VERBOSE,
216 "AFSQueryDirectory Enumerating content for parent %wZ Initial Query\n",
217 &pCcb->DirectoryCB->NameInformation.FileName);
219 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
220 AFS_TRACE_LEVEL_VERBOSE,
221 "AFSQueryDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
222 &pFcb->NPFcb->Resource,
223 PsGetCurrentThread());
225 AFSAcquireExcl( &pFcb->NPFcb->Resource,
233 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
234 AFS_TRACE_LEVEL_VERBOSE,
235 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
236 &pCcb->DirectoryCB->NameInformation.FileName);
238 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
239 AFS_TRACE_LEVEL_VERBOSE,
240 "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
241 &pFcb->NPFcb->Resource,
242 PsGetCurrentThread());
244 AFSAcquireShared( &pFcb->NPFcb->Resource,
251 // Grab the directory node hdr tree lock while parsing the directory
255 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
261 // Before attempting to insert the new entry, check if we need to validate the parent
264 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
267 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
268 AFS_TRACE_LEVEL_VERBOSE,
269 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
270 &pCcb->DirectoryCB->NameInformation.FileName,
271 pFcb->ObjectInformation->FileId.Cell,
272 pFcb->ObjectInformation->FileId.Volume,
273 pFcb->ObjectInformation->FileId.Vnode,
274 pFcb->ObjectInformation->FileId.Unique);
276 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
279 if( !NT_SUCCESS( ntStatus))
282 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
283 AFS_TRACE_LEVEL_ERROR,
284 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
285 &pCcb->DirectoryCB->NameInformation.FileName,
286 pFcb->ObjectInformation->FileId.Cell,
287 pFcb->ObjectInformation->FileId.Volume,
288 pFcb->ObjectInformation->FileId.Vnode,
289 pFcb->ObjectInformation->FileId.Unique,
292 try_return( ntStatus);
296 // Perform a new snapshot of the directory
299 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
302 ntStatus = AFSSnapshotDirectory( pFcb,
306 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
308 if( !NT_SUCCESS( ntStatus))
311 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
312 AFS_TRACE_LEVEL_ERROR,
313 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
314 &pCcb->DirectoryCB->NameInformation.FileName,
318 try_return( ntStatus);
322 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
325 // We can now safely drop the lock on the node
328 AFSReleaseResource( &pFcb->NPFcb->Resource);
333 // Start processing the data
336 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
342 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
345 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
348 // Check if initial on this map
352 ntStatus = AFSSnapshotDirectory( pFcb,
356 if( !NT_SUCCESS( ntStatus))
359 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
361 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
362 AFS_TRACE_LEVEL_ERROR,
363 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
364 &pCcb->DirectoryCB->NameInformation.FileName,
368 try_return( ntStatus);
371 SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
373 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
375 // build mask if none
376 if( puniArgFileName == NULL)
378 puniArgFileName = &uniTmpMaskName;
379 puniArgFileName->Length = 0;
380 puniArgFileName->Buffer = NULL;
383 if( puniArgFileName->Length == 0)
386 puniArgFileName->Length = sizeof(WCHAR);
387 puniArgFileName->MaximumLength = (USHORT)4;
390 if( puniArgFileName->Buffer == NULL)
393 puniArgFileName->Buffer = wchMaskBuffer;
395 RtlZeroMemory( wchMaskBuffer,
398 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
403 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
404 ( puniArgFileName->Buffer[0] == L'*')))
407 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
412 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
413 ( puniArgFileName->Buffer[0] == L'<')) ||
414 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
415 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
418 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
422 // Build the name for procesisng
425 pCcb->MaskName.Length = puniArgFileName->Length;
426 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
428 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
429 pCcb->MaskName.Length,
430 AFS_GENERIC_MEMORY_6_TAG);
432 if( pCcb->MaskName.Buffer == NULL)
435 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
438 if( FsRtlDoesNameContainWildCards( puniArgFileName))
441 RtlUpcaseUnicodeString( &pCcb->MaskName,
445 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
447 if( FsRtlIsNameInExpression( &pCcb->MaskName,
452 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
458 RtlCopyMemory( pCcb->MaskName.Buffer,
459 puniArgFileName->Buffer,
460 pCcb->MaskName.Length);
462 if( RtlCompareUnicodeString( &AFSPIOCtlName,
466 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
470 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
472 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
475 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
477 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
479 bReleaseMain = FALSE;
481 AFSAcquireExcl( &pFcb->NPFcb->Resource,
484 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
487 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
489 if( !NT_SUCCESS( ntStatus))
492 AFSReleaseResource( &pFcb->NPFcb->Resource);
494 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
495 AFS_TRACE_LEVEL_ERROR,
496 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
497 &pCcb->DirectoryCB->NameInformation.FileName,
501 try_return( ntStatus);
505 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
510 AFSReleaseResource( &pFcb->NPFcb->Resource);
512 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
517 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
518 AFS_TRACE_LEVEL_VERBOSE,
519 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
520 &pCcb->DirectoryCB->NameInformation.FileName,
525 // Check if we need to start from index
530 // Need to set up the initial point for the query
533 pCcb->CurrentDirIndex = ulFileIndex - 1;
536 // Check if we need to restart the scan
537 else if( bRestartScan)
541 // Reset the current scan processing
544 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
547 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
552 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
556 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
558 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
560 bReleaseMain = FALSE;
562 switch( FileInformationClass)
565 case FileDirectoryInformation:
567 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
571 case FileFullDirectoryInformation:
573 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
577 case FileNamesInformation:
579 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
583 case FileBothDirectoryInformation:
585 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
589 case FileIdBothDirectoryInformation:
591 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
596 case FileIdFullDirectoryInformation:
598 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
605 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
606 AFS_TRACE_LEVEL_ERROR,
607 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
609 FileInformationClass);
611 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
617 ULONG ulBytesRemainingInBuffer;
621 // If the user had requested only a single match and we have
622 // returned that, then we stop at this point.
625 if( bReturnSingleEntry && ulNextEntry != 0)
628 try_return( ntStatus);
631 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
634 if( pDirEntry == NULL)
637 if( ulNextEntry == 0)
640 if( ( bInitialQuery ||
642 pCcb->MaskName.Buffer != NULL)
644 ntStatus = STATUS_NO_SUCH_FILE;
648 ntStatus = STATUS_NO_MORE_FILES;
652 try_return( ntStatus);
656 // Skip the entry if it is pending delete or deleted
659 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
660 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
663 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
668 pObjectInfo = pDirEntry->ObjectInformation;
671 // Apply the name filter if there is one
674 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
678 // Only returning directories?
681 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
684 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
687 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
692 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
696 // Are we doing a wild card search?
699 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
702 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
703 &pDirEntry->NameInformation.FileName,
708 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
716 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
722 // See if this is a match for a case insensitive search
725 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
730 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
740 // Be sure the information is valid
741 // We don't worry about entries while enumerating the directory
744 AFSValidateEntry( pDirEntry,
748 pObjectInfo = pDirEntry->ObjectInformation;
750 bUseFileInfo = FALSE;
752 ulAdditionalAttributes = 0;
754 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
758 // Go grab the file information for this entry
759 // No worries on failures since we will just display
760 // pseudo information
763 RtlZeroMemory( &stFileInfo,
764 sizeof( AFSFileInfoCB));
766 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
774 ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
780 // Here are the rules concerning filling up the buffer:
782 // 1. The Io system guarantees that there will always be
783 // enough room for at least one base record.
785 // 2. If the full first record (including file name) cannot
786 // fit, as much of the name as possible is copied and
787 // STATUS_BUFFER_OVERFLOW is returned.
789 // 3. If a subsequent record cannot completely fit into the
790 // buffer, none of it (as in 0 bytes) is copied, and
791 // STATUS_SUCCESS is returned. A subsequent query will
792 // pick up with this record.
794 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
796 if( ( ulNextEntry != 0) &&
797 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
798 ( ulUserBufferLength < ulNextEntry) ) )
802 // Back off our current index
805 pCcb->CurrentDirIndex--;
807 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
809 try_return( ntStatus = STATUS_SUCCESS);
812 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
813 AFS_TRACE_LEVEL_VERBOSE,
814 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
815 &pCcb->DirectoryCB->NameInformation.FileName,
816 &pDirEntry->NameInformation.FileName);
818 // Zero the base part of the structure.
819 RtlZeroMemory( &pBuffer[ ulNextEntry],
822 switch( FileInformationClass)
825 // Now fill the base parts of the structure that are applicable.
826 case FileIdBothDirectoryInformation:
827 case FileBothDirectoryInformation:
829 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
831 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
833 if( pDirEntry->NameInformation.ShortNameLength > 0)
835 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
836 &pDirEntry->NameInformation.ShortName[ 0],
837 pBothDirInfo->ShortNameLength);
840 case FileIdFullDirectoryInformation:
841 case FileFullDirectoryInformation:
843 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
844 pFullDirInfo->EaSize = 0;
846 case FileDirectoryInformation:
848 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
853 pDirInfo->CreationTime = stFileInfo.CreationTime;
854 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
855 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
856 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
858 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
859 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
861 pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
863 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
866 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
867 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
868 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
869 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
871 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
872 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
874 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
876 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
880 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
886 pDirInfo->CreationTime = pObjectInfo->CreationTime;
887 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
888 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
889 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
891 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
892 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
894 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
898 // Check if the name begins with a . and we are hiding them
901 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
902 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
903 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
906 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
909 pDirInfo->FileIndex = pDirEntry->FileIndex;
910 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
915 case FileNamesInformation:
917 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
918 pNamesInfo->FileIndex = pDirEntry->FileIndex;
919 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
925 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
926 AFS_TRACE_LEVEL_ERROR,
927 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
929 FileInformationClass);
931 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
933 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
939 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
940 pDirEntry->NameInformation.FileName.Length :
941 ulBytesRemainingInBuffer - ulBaseLength;
943 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
944 pDirEntry->NameInformation.FileName.Buffer,
947 // Set up the previous next entry offset
948 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
950 // And indicate how much of the user buffer we have currently
952 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
954 // Check for the case that a single entry doesn't fit.
955 // This should only get this far on the first entry.
956 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
959 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
961 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
964 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
966 dStatus = STATUS_SUCCESS;
968 // Set ourselves up for the next iteration
969 ulLastEntry = ulNextEntry;
970 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
978 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
984 AFSReleaseResource( &pFcb->NPFcb->Resource);
990 AFSClearEnumerationEvent( pFcb);
998 AFSNotifyChangeDirectory( IN PIRP Irp)
1001 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1002 PIO_STACK_LOCATION pIrpSp;
1003 AFSFcb *pFcb = NULL;
1004 AFSCcb *pCcb = NULL;
1005 ULONG ulCompletionFilter;
1007 BOOLEAN bReleaseLock = FALSE;
1012 // Get the current Stack location
1013 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
1015 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1016 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1021 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1022 AFS_TRACE_LEVEL_ERROR,
1023 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1026 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1029 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1030 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1031 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1035 AFS_TRACE_LEVEL_ERROR,
1036 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1037 &pCcb->DirectoryCB->NameInformation.FileName,
1038 pFcb->Header.NodeTypeCode);
1040 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1043 // Reference our input parameter to make things easier
1044 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1045 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1047 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1048 AFS_TRACE_LEVEL_VERBOSE,
1049 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1050 &pFcb->NPFcb->Resource,
1051 PsGetCurrentThread());
1053 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1056 bReleaseLock = TRUE;
1059 // Check if the node has already been deleted
1062 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1065 try_return( ntStatus = STATUS_FILE_DELETED);
1067 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1070 try_return( ntStatus = STATUS_DELETE_PENDING);
1073 // Call the Fsrtl package to process the request.
1074 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1080 if( !NT_SUCCESS( ntStatus))
1082 try_return( ntStatus);
1085 ntStatus = STATUS_PENDING;
1092 AFSReleaseResource( &pFcb->NPFcb->Resource);
1100 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1104 AFSDirectoryCB *pDirEntry = NULL;
1105 NTSTATUS ntStatus = STATUS_SUCCESS;
1106 AFSSnapshotHdr *pSnapshotHdr = NULL;
1107 AFSSnapshotEntry *pSnapshotEntry = NULL;
1114 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1117 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1121 // Is this a PIOCtl query
1124 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1127 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1128 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1131 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1133 if( pDirEntry != NULL)
1136 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1139 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1140 AFS_TRACE_LEVEL_VERBOSE,
1141 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1142 &pDirEntry->NameInformation.FileName,
1143 ObjectInfo->FileId.Cell,
1144 ObjectInfo->FileId.Volume,
1145 ObjectInfo->FileId.Vnode,
1146 ObjectInfo->FileId.Unique);
1149 Ccb->CurrentDirIndex++;
1151 try_return( ntStatus);
1154 Ccb->CurrentDirIndex++;
1156 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1160 // Return the .. entry
1163 pDirEntry = AFSGlobalDotDirEntry;
1165 if( pDirEntry != NULL)
1168 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1171 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1172 AFS_TRACE_LEVEL_VERBOSE,
1173 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1174 &pDirEntry->NameInformation.FileName,
1175 ObjectInfo->FileId.Cell,
1176 ObjectInfo->FileId.Volume,
1177 ObjectInfo->FileId.Vnode,
1178 ObjectInfo->FileId.Unique);
1180 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1184 // Return the .. entry
1187 pDirEntry = AFSGlobalDotDotDirEntry;
1189 if( pDirEntry != NULL)
1192 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1195 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1196 AFS_TRACE_LEVEL_VERBOSE,
1197 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1198 &pDirEntry->NameInformation.FileName,
1199 ObjectInfo->FileId.Cell,
1200 ObjectInfo->FileId.Volume,
1201 ObjectInfo->FileId.Vnode,
1202 ObjectInfo->FileId.Unique);
1207 pSnapshotHdr = Ccb->DirectorySnapshot;
1209 if( pSnapshotHdr == NULL ||
1210 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1213 try_return( ntStatus);
1216 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1218 ulCount = Ccb->CurrentDirIndex;
1220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1221 AFS_TRACE_LEVEL_VERBOSE,
1222 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1226 // Get to a valid entry
1229 while( ulCount < pSnapshotHdr->EntryCount)
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1237 pSnapshotEntry->NameHash);
1239 if( pSnapshotEntry->NameHash == 0)
1245 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1246 pSnapshotEntry->NameHash,
1249 if( !NT_SUCCESS( ntStatus) ||
1253 if( pDirEntry != NULL)
1256 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1257 AFS_TRACE_LEVEL_VERBOSE,
1258 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1259 &pDirEntry->NameInformation.FileName,
1260 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1261 ObjectInfo->FileId.Cell,
1262 ObjectInfo->FileId.Volume,
1263 ObjectInfo->FileId.Vnode,
1264 ObjectInfo->FileId.Unique);
1266 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1272 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1273 AFS_TRACE_LEVEL_VERBOSE,
1274 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1275 ObjectInfo->FileId.Cell,
1276 ObjectInfo->FileId.Volume,
1277 ObjectInfo->FileId.Vnode,
1278 ObjectInfo->FileId.Unique);
1284 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1287 pSnapshotEntry->NameHash,
1288 ObjectInfo->FileId.Cell,
1289 ObjectInfo->FileId.Volume,
1290 ObjectInfo->FileId.Vnode,
1291 ObjectInfo->FileId.Unique);
1297 Ccb->CurrentDirIndex++;
1303 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1305 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1312 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1317 AFSDirectoryCB *pDirEntry = NULL;
1318 NTSTATUS ntStatus = STATUS_SUCCESS;
1319 AFSSnapshotHdr *pSnapshotHdr = NULL;
1320 AFSSnapshotEntry *pSnapshotEntry = NULL;
1326 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1329 Ccb->CurrentDirIndex = DirIndex;
1331 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1335 // Return the .. entry
1338 pDirEntry = AFSGlobalDotDirEntry;
1340 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1344 // Return the .. entry
1347 pDirEntry = AFSGlobalDotDotDirEntry;
1352 pSnapshotHdr = Ccb->DirectorySnapshot;
1354 if( pSnapshotHdr == NULL ||
1355 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1358 try_return( ntStatus);
1361 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1363 ulCount = Ccb->CurrentDirIndex;
1366 // Get to a valid entry
1369 while( ulCount < pSnapshotHdr->EntryCount)
1374 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1375 pSnapshotEntry->NameHash,
1378 if( !NT_SUCCESS( ntStatus) ||
1379 ( pDirEntry != NULL &&
1380 pDirEntry->FileIndex == DirIndex))
1391 if( pDirEntry != NULL)
1394 Ccb->CurrentDirIndex = ulCount;
1400 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1407 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1409 IN BOOLEAN ResetIndex)
1412 NTSTATUS ntStatus = STATUS_SUCCESS;
1413 AFSSnapshotHdr *pSnapshotHdr = NULL;
1414 AFSSnapshotEntry *pSnapshotEntry = NULL;
1415 AFSDirectoryCB *pDirEntry = NULL;
1424 // Set it up so we still get the . and .. entries for empty directories
1427 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1430 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1435 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1439 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1443 // If we have a snapshot then clear it out
1446 if( Ccb->DirectorySnapshot != NULL)
1449 AFSExFreePool( Ccb->DirectorySnapshot);
1451 Ccb->DirectorySnapshot = NULL;
1454 try_return( ntStatus);
1458 // Allocate our snapshot buffer for this enumeration
1461 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1462 sizeof( AFSSnapshotHdr) +
1463 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1464 sizeof( AFSSnapshotEntry)),
1465 AFS_DIR_SNAPSHOT_TAG);
1467 if( pSnapshotHdr == NULL)
1470 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1473 RtlZeroMemory( pSnapshotHdr,
1474 sizeof( AFSSnapshotHdr) +
1475 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1476 sizeof( AFSSnapshotEntry)));
1478 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1480 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1483 // Populate our snapshot
1486 pSnapshotEntry = pSnapshotHdr->TopEntry;
1488 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1490 while( pDirEntry != NULL)
1493 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1494 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1495 !AFSIsNameInSnapshot( pSnapshotHdr,
1496 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1500 AFS_TRACE_LEVEL_VERBOSE,
1501 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1502 pSnapshotHdr->EntryCount,
1503 &pDirEntry->NameInformation.FileName,
1504 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1506 Fcb->ObjectInformation->FileId.Cell,
1507 Fcb->ObjectInformation->FileId.Volume,
1508 Fcb->ObjectInformation->FileId.Vnode,
1509 Fcb->ObjectInformation->FileId.Unique);
1511 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1518 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1519 AFS_TRACE_LEVEL_VERBOSE,
1520 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1521 pSnapshotHdr->EntryCount,
1522 &pDirEntry->NameInformation.FileName,
1523 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1525 Fcb->ObjectInformation->FileId.Cell,
1526 Fcb->ObjectInformation->FileId.Volume,
1527 Fcb->ObjectInformation->FileId.Vnode,
1528 Fcb->ObjectInformation->FileId.Unique);
1531 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1534 if( Ccb->DirectorySnapshot != NULL)
1537 AFSExFreePool( Ccb->DirectorySnapshot);
1539 Ccb->DirectorySnapshot = NULL;
1542 Ccb->DirectorySnapshot = pSnapshotHdr;
1553 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1555 IN BOOLEAN WatchTree,
1556 IN ULONG CompletionFilter,
1560 NTSTATUS ntStatus = STATUS_SUCCESS;
1561 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1567 AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
1571 // Build a dir name based on the FID of the file
1574 if( Ccb->NotifyMask.Buffer == NULL)
1577 Ccb->NotifyMask.Length = 0;
1578 Ccb->NotifyMask.MaximumLength = 1024;
1580 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1581 Ccb->NotifyMask.MaximumLength,
1582 AFS_GENERIC_MEMORY_7_TAG);
1584 if( Ccb->NotifyMask.Buffer == NULL)
1587 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1590 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1591 Ccb->NotifyMask.MaximumLength,
1592 L"\\%08lX.%08lX.%08lX.%08lX",
1593 ObjectInfo->FileId.Cell,
1594 ObjectInfo->FileId.Volume,
1595 ObjectInfo->FileId.Vnode,
1596 ObjectInfo->FileId.Unique);
1598 if( !NT_SUCCESS( ntStatus))
1601 try_return( ntStatus);
1604 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1605 (size_t)Ccb->NotifyMask.MaximumLength,
1608 if( !NT_SUCCESS( ntStatus))
1611 try_return( ntStatus);
1614 Ccb->NotifyMask.Length = (USHORT)sztLength;
1617 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1618 AFS_TRACE_LEVEL_VERBOSE,
1619 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1625 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1626 &pDeviceExt->Specific.Control.DirNotifyList,
1628 (PSTRING)&Ccb->NotifyMask,
1639 if( !NT_SUCCESS( ntStatus))
1642 if( Ccb->NotifyMask.Buffer != NULL)
1645 AFSExFreePool( Ccb->NotifyMask.Buffer);
1647 Ccb->NotifyMask.Buffer = NULL;
1651 AFSReleaseResource( &Ccb->NPCcb->CcbLock);
1658 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1660 IN ULONG NotifyFilter,
1661 IN ULONG NotificationAction)
1664 NTSTATUS ntStatus = STATUS_SUCCESS;
1665 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1666 UNICODE_STRING uniName, uniComponentName;
1668 USHORT usNameOffset = 0;
1673 uniName.Buffer = NULL;
1675 if( ParentObjectInfo == NULL ||
1676 AFSGlobalRoot == NULL)
1679 try_return( ntStatus);
1685 RtlInitUnicodeString( &uniComponentName,
1691 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1695 // Build a dir name based on the FID of the file
1699 uniName.MaximumLength = 1024 + uniComponentName.Length;
1701 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1702 uniName.MaximumLength,
1703 AFS_GENERIC_MEMORY_8_TAG);
1705 if( uniName.Buffer == NULL)
1708 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1711 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1712 uniName.MaximumLength,
1713 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1714 ParentObjectInfo->FileId.Cell,
1715 ParentObjectInfo->FileId.Volume,
1716 ParentObjectInfo->FileId.Vnode,
1717 ParentObjectInfo->FileId.Unique,
1720 if( !NT_SUCCESS( ntStatus))
1723 try_return( ntStatus);
1726 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1727 (size_t)uniName.MaximumLength,
1730 if( !NT_SUCCESS( ntStatus))
1733 try_return( ntStatus);
1736 uniName.Length = (USHORT)sztLength;
1738 usNameOffset = uniName.Length - uniComponentName.Length;
1740 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1741 AFS_TRACE_LEVEL_VERBOSE,
1742 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1748 uniComponentName.Length);
1750 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1751 &pDeviceExt->Specific.Control.DirNotifyList,
1763 if( uniName.Buffer != NULL)
1766 AFSExFreePool( uniName.Buffer);
1773 // For use with FsRtlNotifyFilterChangeDirectory but must
1774 // be implemented in the Framework because the library can
1778 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1779 IN void *FilterContext)
1782 BOOLEAN bReturn = TRUE;
1783 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1784 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1795 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1799 BOOLEAN bIsInSnapshot = FALSE;
1800 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1803 while( ulCount < SnapshotHdr->EntryCount)
1806 if( pSnapshotEntry->NameHash == HashIndex)
1809 bIsInSnapshot = TRUE;
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_VERBOSE,
1813 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1818 else if( pSnapshotEntry->NameHash == 0)
1829 return bIsInSnapshot;