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 ntStatus = AFSSnapshotDirectory( pFcb,
303 if( !NT_SUCCESS( ntStatus))
306 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
307 AFS_TRACE_LEVEL_ERROR,
308 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
309 &pCcb->DirectoryCB->NameInformation.FileName,
313 try_return( ntStatus);
317 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
320 // We can now safely drop the lock on the node
323 AFSReleaseResource( &pFcb->NPFcb->Resource);
328 // Start processing the data
331 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
337 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
340 // Check if initial on this map
344 ntStatus = AFSSnapshotDirectory( pFcb,
348 if( !NT_SUCCESS( ntStatus))
351 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
352 AFS_TRACE_LEVEL_ERROR,
353 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
354 &pCcb->DirectoryCB->NameInformation.FileName,
358 try_return( ntStatus);
361 SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
363 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
365 // build mask if none
366 if( puniArgFileName == NULL)
368 puniArgFileName = &uniTmpMaskName;
369 puniArgFileName->Length = 0;
370 puniArgFileName->Buffer = NULL;
373 if( puniArgFileName->Length == 0)
376 puniArgFileName->Length = sizeof(WCHAR);
377 puniArgFileName->MaximumLength = (USHORT)4;
380 if( puniArgFileName->Buffer == NULL)
383 puniArgFileName->Buffer = wchMaskBuffer;
385 RtlZeroMemory( wchMaskBuffer,
388 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
393 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
394 ( puniArgFileName->Buffer[0] == L'*')))
397 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
402 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
403 ( puniArgFileName->Buffer[0] == L'<')) ||
404 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
405 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
408 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
412 // Build the name for procesisng
415 pCcb->MaskName.Length = puniArgFileName->Length;
416 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
418 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
419 pCcb->MaskName.Length,
420 AFS_GENERIC_MEMORY_6_TAG);
422 if( pCcb->MaskName.Buffer == NULL)
425 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
428 if( FsRtlDoesNameContainWildCards( puniArgFileName))
431 RtlUpcaseUnicodeString( &pCcb->MaskName,
435 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
437 if( FsRtlIsNameInExpression( &pCcb->MaskName,
442 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
448 RtlCopyMemory( pCcb->MaskName.Buffer,
449 puniArgFileName->Buffer,
450 pCcb->MaskName.Length);
452 if( RtlCompareUnicodeString( &AFSPIOCtlName,
456 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
460 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
462 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
465 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
467 bReleaseMain = FALSE;
469 AFSAcquireExcl( &pFcb->NPFcb->Resource,
472 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
475 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
477 if( !NT_SUCCESS( ntStatus))
480 AFSReleaseResource( &pFcb->NPFcb->Resource);
482 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
483 AFS_TRACE_LEVEL_ERROR,
484 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
485 &pCcb->DirectoryCB->NameInformation.FileName,
489 try_return( ntStatus);
493 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
498 AFSReleaseResource( &pFcb->NPFcb->Resource);
502 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
503 AFS_TRACE_LEVEL_VERBOSE,
504 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
505 &pCcb->DirectoryCB->NameInformation.FileName,
510 // Check if we need to start from index
515 // Need to set up the initial point for the query
518 pCcb->CurrentDirIndex = ulFileIndex - 1;
521 // Check if we need to restart the scan
522 else if( bRestartScan)
526 // Reset the current scan processing
529 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
532 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
537 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
541 switch( FileInformationClass)
544 case FileDirectoryInformation:
546 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
550 case FileFullDirectoryInformation:
552 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
556 case FileNamesInformation:
558 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
562 case FileBothDirectoryInformation:
564 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
568 case FileIdBothDirectoryInformation:
570 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
575 case FileIdFullDirectoryInformation:
577 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
584 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
585 AFS_TRACE_LEVEL_ERROR,
586 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
588 FileInformationClass);
590 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
593 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
595 bReleaseMain = FALSE;
600 ULONG ulBytesRemainingInBuffer;
604 // If the user had requested only a single match and we have
605 // returned that, then we stop at this point.
608 if( bReturnSingleEntry && ulNextEntry != 0)
611 try_return( ntStatus);
614 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
617 if( pDirEntry == NULL)
620 if( ulNextEntry == 0)
623 if( ( bInitialQuery ||
625 pCcb->MaskName.Buffer != NULL)
627 ntStatus = STATUS_NO_SUCH_FILE;
631 ntStatus = STATUS_NO_MORE_FILES;
635 try_return( ntStatus);
639 // Skip the entry if it is pending delete or deleted
642 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
643 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
646 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
651 pObjectInfo = pDirEntry->ObjectInformation;
654 // Apply the name filter if there is one
657 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
661 // Only returning directories?
664 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
667 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
670 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
675 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
679 // Are we doing a wild card search?
682 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
685 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
686 &pDirEntry->NameInformation.FileName,
691 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
699 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
705 // See if this is a match for a case insensitive search
708 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
713 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
723 // Be sure the information is valid
724 // We don't worry about entries while enumerating the directory
727 AFSValidateEntry( pDirEntry,
731 pObjectInfo = pDirEntry->ObjectInformation;
733 bUseFileInfo = FALSE;
735 ulAdditionalAttributes = 0;
737 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
741 // Go grab the file information for this entry
742 // No worries on failures since we will just display
743 // pseudo information
746 RtlZeroMemory( &stFileInfo,
747 sizeof( AFSFileInfoCB));
749 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
757 ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
763 // Here are the rules concerning filling up the buffer:
765 // 1. The Io system guarantees that there will always be
766 // enough room for at least one base record.
768 // 2. If the full first record (including file name) cannot
769 // fit, as much of the name as possible is copied and
770 // STATUS_BUFFER_OVERFLOW is returned.
772 // 3. If a subsequent record cannot completely fit into the
773 // buffer, none of it (as in 0 bytes) is copied, and
774 // STATUS_SUCCESS is returned. A subsequent query will
775 // pick up with this record.
777 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
779 if( ( ulNextEntry != 0) &&
780 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
781 ( ulUserBufferLength < ulNextEntry) ) )
785 // Back off our current index
788 pCcb->CurrentDirIndex--;
790 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
792 try_return( ntStatus = STATUS_SUCCESS);
795 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
796 AFS_TRACE_LEVEL_VERBOSE,
797 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
798 &pCcb->DirectoryCB->NameInformation.FileName,
799 &pDirEntry->NameInformation.FileName);
801 // Zero the base part of the structure.
802 RtlZeroMemory( &pBuffer[ ulNextEntry],
805 switch( FileInformationClass)
808 // Now fill the base parts of the structure that are applicable.
809 case FileIdBothDirectoryInformation:
810 case FileBothDirectoryInformation:
812 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
814 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
816 if( pDirEntry->NameInformation.ShortNameLength > 0)
818 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
819 &pDirEntry->NameInformation.ShortName[ 0],
820 pBothDirInfo->ShortNameLength);
823 case FileIdFullDirectoryInformation:
824 case FileFullDirectoryInformation:
826 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
827 pFullDirInfo->EaSize = 0;
829 case FileDirectoryInformation:
831 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
836 pDirInfo->CreationTime = stFileInfo.CreationTime;
837 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
838 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
839 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
841 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
842 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
844 pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
846 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
849 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
850 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
851 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
852 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
854 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
855 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
857 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
859 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
863 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
869 pDirInfo->CreationTime = pObjectInfo->CreationTime;
870 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
871 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
872 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
874 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
875 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
877 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
881 // Check if the name begins with a . and we are hiding them
884 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
885 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
886 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
889 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
892 pDirInfo->FileIndex = pDirEntry->FileIndex;
893 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
898 case FileNamesInformation:
900 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
901 pNamesInfo->FileIndex = pDirEntry->FileIndex;
902 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
908 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
909 AFS_TRACE_LEVEL_ERROR,
910 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
912 FileInformationClass);
914 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
916 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
922 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
923 pDirEntry->NameInformation.FileName.Length :
924 ulBytesRemainingInBuffer - ulBaseLength;
926 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
927 pDirEntry->NameInformation.FileName.Buffer,
930 // Set up the previous next entry offset
931 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
933 // And indicate how much of the user buffer we have currently
935 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
937 // Check for the case that a single entry doesn't fit.
938 // This should only get this far on the first entry.
939 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
942 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
944 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
947 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
949 dStatus = STATUS_SUCCESS;
951 // Set ourselves up for the next iteration
952 ulLastEntry = ulNextEntry;
953 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
961 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
967 AFSReleaseResource( &pFcb->NPFcb->Resource);
973 AFSClearEnumerationEvent( pFcb);
981 AFSNotifyChangeDirectory( IN PIRP Irp)
984 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
985 PIO_STACK_LOCATION pIrpSp;
988 ULONG ulCompletionFilter;
990 BOOLEAN bReleaseLock = FALSE;
995 // Get the current Stack location
996 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
998 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
999 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1004 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1005 AFS_TRACE_LEVEL_ERROR,
1006 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1009 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1012 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1013 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1014 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1017 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1018 AFS_TRACE_LEVEL_ERROR,
1019 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1020 &pCcb->DirectoryCB->NameInformation.FileName,
1021 pFcb->Header.NodeTypeCode);
1023 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1026 // Reference our input parameter to make things easier
1027 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1028 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1030 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1031 AFS_TRACE_LEVEL_VERBOSE,
1032 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1033 &pFcb->NPFcb->Resource,
1034 PsGetCurrentThread());
1036 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1039 bReleaseLock = TRUE;
1042 // Check if the node has already been deleted
1045 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1048 try_return( ntStatus = STATUS_FILE_DELETED);
1050 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1053 try_return( ntStatus = STATUS_DELETE_PENDING);
1056 // Call the Fsrtl package to process the request.
1057 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1063 if( !NT_SUCCESS( ntStatus))
1065 try_return( ntStatus);
1068 ntStatus = STATUS_PENDING;
1075 AFSReleaseResource( &pFcb->NPFcb->Resource);
1083 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1087 AFSDirectoryCB *pDirEntry = NULL;
1088 NTSTATUS ntStatus = STATUS_SUCCESS;
1089 AFSSnapshotHdr *pSnapshotHdr = NULL;
1090 AFSSnapshotEntry *pSnapshotEntry = NULL;
1098 // Is this a PIOCtl query
1101 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1104 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1105 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1108 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1110 if( pDirEntry != NULL)
1113 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1116 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1117 AFS_TRACE_LEVEL_VERBOSE,
1118 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1119 &pDirEntry->NameInformation.FileName,
1120 ObjectInfo->FileId.Cell,
1121 ObjectInfo->FileId.Volume,
1122 ObjectInfo->FileId.Vnode,
1123 ObjectInfo->FileId.Unique);
1126 Ccb->CurrentDirIndex++;
1128 try_return( ntStatus);
1131 Ccb->CurrentDirIndex++;
1133 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1137 // Return the .. entry
1140 pDirEntry = AFSGlobalDotDirEntry;
1142 if( pDirEntry != NULL)
1145 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1149 AFS_TRACE_LEVEL_VERBOSE,
1150 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1151 &pDirEntry->NameInformation.FileName,
1152 ObjectInfo->FileId.Cell,
1153 ObjectInfo->FileId.Volume,
1154 ObjectInfo->FileId.Vnode,
1155 ObjectInfo->FileId.Unique);
1157 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1161 // Return the .. entry
1164 pDirEntry = AFSGlobalDotDotDirEntry;
1166 if( pDirEntry != NULL)
1169 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1175 &pDirEntry->NameInformation.FileName,
1176 ObjectInfo->FileId.Cell,
1177 ObjectInfo->FileId.Volume,
1178 ObjectInfo->FileId.Vnode,
1179 ObjectInfo->FileId.Unique);
1184 pSnapshotHdr = Ccb->DirectorySnapshot;
1186 if( pSnapshotHdr == NULL ||
1187 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1190 try_return( ntStatus);
1193 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1195 ulCount = Ccb->CurrentDirIndex;
1197 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1198 AFS_TRACE_LEVEL_VERBOSE,
1199 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1203 // Get to a valid entry
1206 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1209 while( ulCount < pSnapshotHdr->EntryCount)
1214 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1215 AFS_TRACE_LEVEL_VERBOSE,
1216 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1217 pSnapshotEntry->NameHash);
1219 if( pSnapshotEntry->NameHash == 0)
1225 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1226 pSnapshotEntry->NameHash,
1229 if( !NT_SUCCESS( ntStatus) ||
1233 if( pDirEntry != NULL)
1236 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1237 AFS_TRACE_LEVEL_VERBOSE,
1238 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1239 &pDirEntry->NameInformation.FileName,
1240 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1241 ObjectInfo->FileId.Cell,
1242 ObjectInfo->FileId.Volume,
1243 ObjectInfo->FileId.Vnode,
1244 ObjectInfo->FileId.Unique);
1246 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1253 AFS_TRACE_LEVEL_VERBOSE,
1254 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1255 ObjectInfo->FileId.Cell,
1256 ObjectInfo->FileId.Volume,
1257 ObjectInfo->FileId.Vnode,
1258 ObjectInfo->FileId.Unique);
1264 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1265 AFS_TRACE_LEVEL_VERBOSE,
1266 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1267 pSnapshotEntry->NameHash,
1268 ObjectInfo->FileId.Cell,
1269 ObjectInfo->FileId.Volume,
1270 ObjectInfo->FileId.Vnode,
1271 ObjectInfo->FileId.Unique);
1277 Ccb->CurrentDirIndex++;
1280 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1292 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1297 AFSDirectoryCB *pDirEntry = NULL;
1298 NTSTATUS ntStatus = STATUS_SUCCESS;
1299 AFSSnapshotHdr *pSnapshotHdr = NULL;
1300 AFSSnapshotEntry *pSnapshotEntry = NULL;
1306 Ccb->CurrentDirIndex = DirIndex;
1308 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1312 // Return the .. entry
1315 pDirEntry = AFSGlobalDotDirEntry;
1317 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1321 // Return the .. entry
1324 pDirEntry = AFSGlobalDotDotDirEntry;
1329 pSnapshotHdr = Ccb->DirectorySnapshot;
1331 if( pSnapshotHdr == NULL ||
1332 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1335 try_return( ntStatus);
1338 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1340 ulCount = Ccb->CurrentDirIndex;
1343 // Get to a valid entry
1346 while( ulCount < pSnapshotHdr->EntryCount)
1351 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1352 pSnapshotEntry->NameHash,
1355 if( !NT_SUCCESS( ntStatus) ||
1356 ( pDirEntry != NULL &&
1357 pDirEntry->FileIndex == DirIndex))
1368 if( pDirEntry != NULL)
1371 Ccb->CurrentDirIndex = ulCount;
1384 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1386 IN BOOLEAN ResetIndex)
1389 NTSTATUS ntStatus = STATUS_SUCCESS;
1390 AFSSnapshotHdr *pSnapshotHdr = NULL;
1391 AFSSnapshotEntry *pSnapshotEntry = NULL;
1392 AFSDirectoryCB *pDirEntry = NULL;
1401 // Set it up so we still get the . and .. entries for empty directories
1404 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1407 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1412 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1416 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1420 // If we have a snapshot then clear it out
1423 if( Ccb->DirectorySnapshot != NULL)
1426 AFSExFreePool( Ccb->DirectorySnapshot);
1428 Ccb->DirectorySnapshot = NULL;
1431 try_return( ntStatus);
1435 // Allocate our snapshot buffer for this enumeration
1438 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1439 sizeof( AFSSnapshotHdr) +
1440 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1441 sizeof( AFSSnapshotEntry)),
1442 AFS_DIR_SNAPSHOT_TAG);
1444 if( pSnapshotHdr == NULL)
1447 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1450 RtlZeroMemory( pSnapshotHdr,
1451 sizeof( AFSSnapshotHdr) +
1452 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1453 sizeof( AFSSnapshotEntry)));
1455 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1457 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1460 // Populate our snapshot
1463 pSnapshotEntry = pSnapshotHdr->TopEntry;
1465 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1467 while( pDirEntry != NULL)
1470 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1471 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1472 !AFSIsNameInSnapshot( pSnapshotHdr,
1473 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1476 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1477 AFS_TRACE_LEVEL_VERBOSE,
1478 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1479 pSnapshotHdr->EntryCount,
1480 &pDirEntry->NameInformation.FileName,
1481 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1483 Fcb->ObjectInformation->FileId.Cell,
1484 Fcb->ObjectInformation->FileId.Volume,
1485 Fcb->ObjectInformation->FileId.Vnode,
1486 Fcb->ObjectInformation->FileId.Unique);
1488 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1495 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1496 AFS_TRACE_LEVEL_VERBOSE,
1497 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1498 pSnapshotHdr->EntryCount,
1499 &pDirEntry->NameInformation.FileName,
1500 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1502 Fcb->ObjectInformation->FileId.Cell,
1503 Fcb->ObjectInformation->FileId.Volume,
1504 Fcb->ObjectInformation->FileId.Vnode,
1505 Fcb->ObjectInformation->FileId.Unique);
1508 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1511 if( Ccb->DirectorySnapshot != NULL)
1514 AFSExFreePool( Ccb->DirectorySnapshot);
1516 Ccb->DirectorySnapshot = NULL;
1519 Ccb->DirectorySnapshot = pSnapshotHdr;
1530 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1532 IN BOOLEAN WatchTree,
1533 IN ULONG CompletionFilter,
1537 NTSTATUS ntStatus = STATUS_SUCCESS;
1538 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1545 // Build a dir name based on the FID of the file
1548 if( Ccb->NotifyMask.Buffer == NULL)
1551 Ccb->NotifyMask.Length = 0;
1552 Ccb->NotifyMask.MaximumLength = 1024;
1554 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1555 Ccb->NotifyMask.MaximumLength,
1556 AFS_GENERIC_MEMORY_7_TAG);
1558 if( Ccb->NotifyMask.Buffer == NULL)
1561 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1564 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1565 Ccb->NotifyMask.MaximumLength,
1566 L"\\%08lX.%08lX.%08lX.%08lX",
1567 ObjectInfo->FileId.Cell,
1568 ObjectInfo->FileId.Volume,
1569 ObjectInfo->FileId.Vnode,
1570 ObjectInfo->FileId.Unique);
1572 if( !NT_SUCCESS( ntStatus))
1575 try_return( ntStatus);
1578 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1579 (size_t)Ccb->NotifyMask.MaximumLength,
1582 if( !NT_SUCCESS( ntStatus))
1585 try_return( ntStatus);
1588 Ccb->NotifyMask.Length = (USHORT)sztLength;
1591 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1592 AFS_TRACE_LEVEL_VERBOSE,
1593 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1599 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1600 &pDeviceExt->Specific.Control.DirNotifyList,
1602 (PSTRING)&Ccb->NotifyMask,
1613 if( !NT_SUCCESS( ntStatus))
1616 if( Ccb->NotifyMask.Buffer != NULL)
1619 AFSExFreePool( Ccb->NotifyMask.Buffer);
1621 Ccb->NotifyMask.Buffer = NULL;
1630 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1632 IN ULONG NotifyFilter,
1633 IN ULONG NotificationAction)
1636 NTSTATUS ntStatus = STATUS_SUCCESS;
1637 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1638 UNICODE_STRING uniName, uniComponentName;
1640 USHORT usNameOffset = 0;
1645 uniName.Buffer = NULL;
1647 if( ParentObjectInfo == NULL ||
1648 AFSGlobalRoot == NULL)
1651 try_return( ntStatus);
1657 RtlInitUnicodeString( &uniComponentName,
1663 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1667 // Build a dir name based on the FID of the file
1671 uniName.MaximumLength = 1024 + uniComponentName.Length;
1673 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1674 uniName.MaximumLength,
1675 AFS_GENERIC_MEMORY_8_TAG);
1677 if( uniName.Buffer == NULL)
1680 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1683 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1684 uniName.MaximumLength,
1685 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1686 ParentObjectInfo->FileId.Cell,
1687 ParentObjectInfo->FileId.Volume,
1688 ParentObjectInfo->FileId.Vnode,
1689 ParentObjectInfo->FileId.Unique,
1692 if( !NT_SUCCESS( ntStatus))
1695 try_return( ntStatus);
1698 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1699 (size_t)uniName.MaximumLength,
1702 if( !NT_SUCCESS( ntStatus))
1705 try_return( ntStatus);
1708 uniName.Length = (USHORT)sztLength;
1710 usNameOffset = uniName.Length - uniComponentName.Length;
1712 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1713 AFS_TRACE_LEVEL_VERBOSE,
1714 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1720 uniComponentName.Length);
1722 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1723 &pDeviceExt->Specific.Control.DirNotifyList,
1735 if( uniName.Buffer != NULL)
1738 AFSExFreePool( uniName.Buffer);
1745 // For use with FsRtlNotifyFilterChangeDirectory but must
1746 // be implemented in the Framework because the library can
1750 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1751 IN void *FilterContext)
1754 BOOLEAN bReturn = TRUE;
1755 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1756 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1767 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1771 BOOLEAN bIsInSnapshot = FALSE;
1772 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1775 while( ulCount < SnapshotHdr->EntryCount)
1778 if( pSnapshotEntry->NameHash == HashIndex)
1781 bIsInSnapshot = TRUE;
1783 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1784 AFS_TRACE_LEVEL_VERBOSE,
1785 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1790 else if( pSnapshotEntry->NameHash == 0)
1801 return bIsInSnapshot;