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( GetExceptionCode(), GetExceptionInformation()) )
97 "EXCEPTION - AFSDirControl\n");
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;
123 ULONG ulUserBufferLength;
124 PUNICODE_STRING puniArgFileName = NULL;
125 UNICODE_STRING uniTmpMaskName;
126 UNICODE_STRING uniDirUniBuf;
127 WCHAR wchMaskBuffer[ 4];
128 FILE_INFORMATION_CLASS FileInformationClass;
129 ULONG ulFileIndex, ulDOSFileIndex;
130 BOOLEAN bRestartScan;
131 BOOLEAN bReturnSingleEntry;
132 BOOLEAN bIndexSpecified;
133 ULONG ulNextEntry = 0;
134 ULONG ulLastEntry = 0;
136 PFILE_DIRECTORY_INFORMATION pDirInfo;
137 PFILE_FULL_DIR_INFORMATION pFullDirInfo;
138 PFILE_BOTH_DIR_INFORMATION pBothDirInfo;
139 PFILE_NAMES_INFORMATION pNamesInfo;
141 ULONG ulBytesConverted;
142 AFSDirectoryCB *pDirEntry = NULL;
143 BOOLEAN bReleaseMain = FALSE;
144 BOOLEAN bReleaseFcb = FALSE;
145 ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN;
146 AFSFileInfoCB stFileInfo;
147 BOOLEAN bUseFileInfo = TRUE;
148 AFSObjectInfoCB *pObjectInfo = NULL;
149 ULONG ulAdditionalAttributes = 0;
154 // Get the current Stack location
155 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
157 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
158 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
163 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
164 AFS_TRACE_LEVEL_ERROR,
165 "AFSQueryDirectory Attempted access (%08lX) when pFcb == NULL\n",
168 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
171 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
172 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
173 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
176 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
177 AFS_TRACE_LEVEL_ERROR,
178 "AFSQueryDirectory Attempted access (%08lX) to non-directory Fcb %08lX NodeType %u\n",
181 pFcb->Header.NodeTypeCode);
185 try_return( ntStatus = STATUS_INVALID_PARAMETER);
189 // Set the enumeration event ...
192 AFSSetEnumerationEvent( pFcb);
194 // Reference our input parameters to make things easier
195 ulUserBufferLength = pIrpSp->Parameters.QueryDirectory.Length;
197 FileInformationClass = pIrpSp->Parameters.QueryDirectory.FileInformationClass;
198 ulFileIndex = pIrpSp->Parameters.QueryDirectory.FileIndex;
200 puniArgFileName = (PUNICODE_STRING)pIrpSp->Parameters.QueryDirectory.FileName;
202 bRestartScan = BooleanFlagOn( pIrpSp->Flags, SL_RESTART_SCAN);
203 bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
204 bIndexSpecified = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
206 bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED));
211 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
212 AFS_TRACE_LEVEL_VERBOSE,
213 "AFSQueryDirectory Enumerating content for parent %wZ Initial Query\n",
214 &pCcb->DirectoryCB->NameInformation.FileName);
216 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
217 AFS_TRACE_LEVEL_VERBOSE,
218 "AFSQueryDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
219 &pFcb->NPFcb->Resource,
220 PsGetCurrentThread());
222 AFSAcquireExcl( &pFcb->NPFcb->Resource,
228 // Tell the service to prime the cache of the directory content
231 ntStatus = AFSEnumerateDirectoryNoResponse( &pFcb->AuthGroup,
232 &pFcb->ObjectInformation->FileId);
234 if( !NT_SUCCESS( ntStatus))
237 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
238 AFS_TRACE_LEVEL_ERROR,
239 "AFSQueryDirectory Enumerate directory failure for parent %wZ Mask %wZ Status %08lX\n",
240 &pCcb->DirectoryCB->NameInformation.FileName,
244 try_return( ntStatus);
250 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
251 AFS_TRACE_LEVEL_VERBOSE,
252 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
253 &pCcb->DirectoryCB->NameInformation.FileName);
255 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
256 AFS_TRACE_LEVEL_VERBOSE,
257 "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
258 &pFcb->NPFcb->Resource,
259 PsGetCurrentThread());
261 AFSAcquireShared( &pFcb->NPFcb->Resource,
268 // Grab the directory node hdr tree lock while parsing the directory
272 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
278 // Before attempting to insert the new entry, check if we need to validate the parent
281 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
284 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
285 AFS_TRACE_LEVEL_VERBOSE,
286 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
287 &pCcb->DirectoryCB->NameInformation.FileName,
288 pFcb->ObjectInformation->FileId.Cell,
289 pFcb->ObjectInformation->FileId.Volume,
290 pFcb->ObjectInformation->FileId.Vnode,
291 pFcb->ObjectInformation->FileId.Unique);
293 ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
296 if( !NT_SUCCESS( ntStatus))
299 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
300 AFS_TRACE_LEVEL_ERROR,
301 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
302 &pCcb->DirectoryCB->NameInformation.FileName,
303 pFcb->ObjectInformation->FileId.Cell,
304 pFcb->ObjectInformation->FileId.Volume,
305 pFcb->ObjectInformation->FileId.Vnode,
306 pFcb->ObjectInformation->FileId.Unique,
309 try_return( ntStatus);
313 // Perform a new snapshot of the directory
316 ntStatus = AFSSnapshotDirectory( pFcb,
320 if( !NT_SUCCESS( ntStatus))
323 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
324 AFS_TRACE_LEVEL_ERROR,
325 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
326 &pCcb->DirectoryCB->NameInformation.FileName,
330 try_return( ntStatus);
334 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
337 // We can now safely drop the lock on the node
340 AFSReleaseResource( &pFcb->NPFcb->Resource);
345 // Start processing the data
348 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
354 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
357 // Check if initial on this map
361 ntStatus = AFSSnapshotDirectory( pFcb,
365 if( !NT_SUCCESS( ntStatus))
368 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
369 AFS_TRACE_LEVEL_ERROR,
370 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
371 &pCcb->DirectoryCB->NameInformation.FileName,
375 try_return( ntStatus);
378 SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
380 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
382 // build mask if none
383 if( puniArgFileName == NULL)
385 puniArgFileName = &uniTmpMaskName;
386 puniArgFileName->Length = 0;
387 puniArgFileName->Buffer = NULL;
390 if( puniArgFileName->Length == 0)
393 puniArgFileName->Length = sizeof(WCHAR);
394 puniArgFileName->MaximumLength = (USHORT)4;
397 if( puniArgFileName->Buffer == NULL)
400 puniArgFileName->Buffer = wchMaskBuffer;
402 RtlZeroMemory( wchMaskBuffer,
405 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
410 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
411 ( puniArgFileName->Buffer[0] == L'*')))
414 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
419 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
420 ( puniArgFileName->Buffer[0] == L'<')) ||
421 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
422 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
425 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
429 // Build the name for procesisng
432 pCcb->MaskName.Length = puniArgFileName->Length;
433 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
435 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
436 pCcb->MaskName.Length,
437 AFS_GENERIC_MEMORY_6_TAG);
439 if( pCcb->MaskName.Buffer == NULL)
442 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
445 if( FsRtlDoesNameContainWildCards( puniArgFileName))
448 RtlUpcaseUnicodeString( &pCcb->MaskName,
452 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
454 if( FsRtlIsNameInExpression( &pCcb->MaskName,
459 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
465 RtlCopyMemory( pCcb->MaskName.Buffer,
466 puniArgFileName->Buffer,
467 pCcb->MaskName.Length);
469 if( RtlCompareUnicodeString( &AFSPIOCtlName,
473 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
477 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
479 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
482 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
484 bReleaseMain = FALSE;
486 AFSAcquireExcl( &pFcb->NPFcb->Resource,
489 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
492 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
494 if( !NT_SUCCESS( ntStatus))
497 AFSReleaseResource( &pFcb->NPFcb->Resource);
499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
500 AFS_TRACE_LEVEL_ERROR,
501 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
502 &pCcb->DirectoryCB->NameInformation.FileName,
506 try_return( ntStatus);
510 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
515 AFSReleaseResource( &pFcb->NPFcb->Resource);
519 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
520 AFS_TRACE_LEVEL_VERBOSE,
521 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
522 &pCcb->DirectoryCB->NameInformation.FileName,
527 // Check if we need to start from index
532 // Need to set up the initial point for the query
535 pCcb->CurrentDirIndex = ulFileIndex - 1;
538 // Check if we need to restart the scan
539 else if( bRestartScan)
543 // Reset the current scan processing
546 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
549 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
554 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
558 switch( FileInformationClass)
561 case FileDirectoryInformation:
563 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
567 case FileFullDirectoryInformation:
569 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
573 case FileNamesInformation:
575 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
579 case FileBothDirectoryInformation:
581 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
585 case FileIdBothDirectoryInformation:
587 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
592 case FileIdFullDirectoryInformation:
594 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
601 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
602 AFS_TRACE_LEVEL_ERROR,
603 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
605 FileInformationClass);
607 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
610 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
612 bReleaseMain = FALSE;
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 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 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 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 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
740 // Be sure the information is valid
741 // We don't worry about entries while enumerating the directory
744 AFSValidateEntry( pDirEntry,
749 pObjectInfo = pDirEntry->ObjectInformation;
751 bUseFileInfo = FALSE;
753 ulAdditionalAttributes = 0;
755 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
759 // Go grab the file information for this entry
760 // No worries on failures since we will just display
761 // pseudo information
764 RtlZeroMemory( &stFileInfo,
765 sizeof( AFSFileInfoCB));
767 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 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 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 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
961 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
964 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 // Is this a PIOCtl query
1117 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1120 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1121 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1124 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1126 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1127 AFS_TRACE_LEVEL_VERBOSE,
1128 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1129 &pDirEntry->NameInformation.FileName,
1130 ObjectInfo->FileId.Cell,
1131 ObjectInfo->FileId.Volume,
1132 ObjectInfo->FileId.Vnode,
1133 ObjectInfo->FileId.Unique);
1136 Ccb->CurrentDirIndex++;
1138 try_return( ntStatus);
1141 Ccb->CurrentDirIndex++;
1143 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1147 // Return the .. entry
1150 pDirEntry = AFSGlobalDotDirEntry;
1152 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1153 AFS_TRACE_LEVEL_VERBOSE,
1154 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1155 &pDirEntry->NameInformation.FileName,
1156 ObjectInfo->FileId.Cell,
1157 ObjectInfo->FileId.Volume,
1158 ObjectInfo->FileId.Vnode,
1159 ObjectInfo->FileId.Unique);
1161 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1165 // Return the .. entry
1168 pDirEntry = AFSGlobalDotDotDirEntry;
1170 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1171 AFS_TRACE_LEVEL_VERBOSE,
1172 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1173 &pDirEntry->NameInformation.FileName,
1174 ObjectInfo->FileId.Cell,
1175 ObjectInfo->FileId.Volume,
1176 ObjectInfo->FileId.Vnode,
1177 ObjectInfo->FileId.Unique);
1182 pSnapshotHdr = Ccb->DirectorySnapshot;
1184 if( pSnapshotHdr == NULL ||
1185 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1188 try_return( ntStatus);
1191 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1193 ulCount = Ccb->CurrentDirIndex;
1195 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1196 AFS_TRACE_LEVEL_VERBOSE,
1197 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1201 // Get to a valid entry
1204 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1207 while( ulCount < pSnapshotHdr->EntryCount)
1212 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1213 AFS_TRACE_LEVEL_VERBOSE,
1214 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1215 pSnapshotEntry->NameHash);
1217 if( pSnapshotEntry->NameHash == 0)
1223 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1224 pSnapshotEntry->NameHash,
1227 if( !NT_SUCCESS( ntStatus) ||
1231 if( pDirEntry != NULL)
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1237 &pDirEntry->NameInformation.FileName,
1238 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1239 ObjectInfo->FileId.Cell,
1240 ObjectInfo->FileId.Volume,
1241 ObjectInfo->FileId.Vnode,
1242 ObjectInfo->FileId.Unique);
1244 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1250 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1251 AFS_TRACE_LEVEL_VERBOSE,
1252 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1253 ObjectInfo->FileId.Cell,
1254 ObjectInfo->FileId.Volume,
1255 ObjectInfo->FileId.Vnode,
1256 ObjectInfo->FileId.Unique);
1262 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1263 AFS_TRACE_LEVEL_VERBOSE,
1264 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1265 pSnapshotEntry->NameHash,
1266 ObjectInfo->FileId.Cell,
1267 ObjectInfo->FileId.Volume,
1268 ObjectInfo->FileId.Vnode,
1269 ObjectInfo->FileId.Unique);
1275 Ccb->CurrentDirIndex++;
1278 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1290 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1295 AFSDirectoryCB *pDirEntry = NULL;
1296 NTSTATUS ntStatus = STATUS_SUCCESS;
1297 AFSSnapshotHdr *pSnapshotHdr = NULL;
1298 AFSSnapshotEntry *pSnapshotEntry = NULL;
1304 Ccb->CurrentDirIndex = DirIndex;
1306 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1310 // Return the .. entry
1313 pDirEntry = AFSGlobalDotDirEntry;
1315 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1319 // Return the .. entry
1322 pDirEntry = AFSGlobalDotDotDirEntry;
1327 pSnapshotHdr = Ccb->DirectorySnapshot;
1329 if( pSnapshotHdr == NULL ||
1330 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1333 try_return( ntStatus);
1336 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1338 ulCount = Ccb->CurrentDirIndex;
1341 // Get to a valid entry
1344 while( ulCount < pSnapshotHdr->EntryCount)
1349 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1350 pSnapshotEntry->NameHash,
1353 if( !NT_SUCCESS( ntStatus) ||
1354 ( pDirEntry != NULL &&
1355 pDirEntry->FileIndex == DirIndex))
1366 if( pDirEntry != NULL)
1369 Ccb->CurrentDirIndex = ulCount;
1382 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1384 IN BOOLEAN ResetIndex)
1387 NTSTATUS ntStatus = STATUS_SUCCESS;
1388 AFSSnapshotHdr *pSnapshotHdr = NULL;
1389 AFSSnapshotEntry *pSnapshotEntry = NULL;
1390 AFSDirectoryCB *pDirEntry = NULL;
1399 // Set it up so we still get the . and .. entries for empty directories
1402 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1405 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1410 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1414 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1418 // If we have a snapshot then clear it out
1421 if( Ccb->DirectorySnapshot != NULL)
1424 AFSExFreePool( Ccb->DirectorySnapshot);
1426 Ccb->DirectorySnapshot = NULL;
1429 try_return( ntStatus);
1433 // Allocate our snapshot buffer for this enumeration
1436 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1437 sizeof( AFSSnapshotHdr) +
1438 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1439 sizeof( AFSSnapshotEntry)),
1440 AFS_DIR_SNAPSHOT_TAG);
1442 if( pSnapshotHdr == NULL)
1445 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1448 RtlZeroMemory( pSnapshotHdr,
1449 sizeof( AFSSnapshotHdr) +
1450 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1451 sizeof( AFSSnapshotEntry)));
1453 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1455 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1458 // Populate our snapshot
1461 pSnapshotEntry = pSnapshotHdr->TopEntry;
1463 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1465 while( pDirEntry != NULL)
1468 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1469 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1470 !AFSIsNameInSnapshot( pSnapshotHdr,
1471 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1474 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1475 AFS_TRACE_LEVEL_VERBOSE,
1476 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1477 pSnapshotHdr->EntryCount,
1478 &pDirEntry->NameInformation.FileName,
1479 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1481 Fcb->ObjectInformation->FileId.Cell,
1482 Fcb->ObjectInformation->FileId.Volume,
1483 Fcb->ObjectInformation->FileId.Vnode,
1484 Fcb->ObjectInformation->FileId.Unique);
1486 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1493 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1494 AFS_TRACE_LEVEL_VERBOSE,
1495 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1496 pSnapshotHdr->EntryCount,
1497 &pDirEntry->NameInformation.FileName,
1498 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1500 Fcb->ObjectInformation->FileId.Cell,
1501 Fcb->ObjectInformation->FileId.Volume,
1502 Fcb->ObjectInformation->FileId.Vnode,
1503 Fcb->ObjectInformation->FileId.Unique);
1506 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1509 if( Ccb->DirectorySnapshot != NULL)
1512 AFSExFreePool( Ccb->DirectorySnapshot);
1514 Ccb->DirectorySnapshot = NULL;
1517 Ccb->DirectorySnapshot = pSnapshotHdr;
1528 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1530 IN BOOLEAN WatchTree,
1531 IN ULONG CompletionFilter,
1535 NTSTATUS ntStatus = STATUS_SUCCESS;
1536 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1543 // Build a dir name based on the FID of the file
1546 if( Ccb->NotifyMask.Buffer == NULL)
1549 Ccb->NotifyMask.Length = 0;
1550 Ccb->NotifyMask.MaximumLength = 1024;
1552 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1553 Ccb->NotifyMask.MaximumLength,
1554 AFS_GENERIC_MEMORY_7_TAG);
1556 if( Ccb->NotifyMask.Buffer == NULL)
1559 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1562 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1563 Ccb->NotifyMask.MaximumLength,
1564 L"\\%08lX.%08lX.%08lX.%08lX",
1565 ObjectInfo->FileId.Cell,
1566 ObjectInfo->FileId.Volume,
1567 ObjectInfo->FileId.Vnode,
1568 ObjectInfo->FileId.Unique);
1570 if( !NT_SUCCESS( ntStatus))
1573 try_return( ntStatus);
1576 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1577 (size_t)Ccb->NotifyMask.MaximumLength,
1580 if( !NT_SUCCESS( ntStatus))
1583 try_return( ntStatus);
1586 Ccb->NotifyMask.Length = (USHORT)sztLength;
1589 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1590 AFS_TRACE_LEVEL_VERBOSE,
1591 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1597 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1598 &pDeviceExt->Specific.Control.DirNotifyList,
1600 (PSTRING)&Ccb->NotifyMask,
1611 if( !NT_SUCCESS( ntStatus))
1614 if( Ccb->NotifyMask.Buffer != NULL)
1617 AFSExFreePool( Ccb->NotifyMask.Buffer);
1619 Ccb->NotifyMask.Buffer = NULL;
1628 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1630 IN ULONG NotifyFilter,
1631 IN ULONG NotificationAction)
1634 NTSTATUS ntStatus = STATUS_SUCCESS;
1635 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1636 UNICODE_STRING uniName, uniComponentName;
1638 USHORT usNameOffset = 0;
1643 uniName.Buffer = NULL;
1645 if( ParentObjectInfo == NULL ||
1646 AFSGlobalRoot == NULL)
1649 try_return( ntStatus);
1655 RtlInitUnicodeString( &uniComponentName,
1661 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1665 // Build a dir name based on the FID of the file
1669 uniName.MaximumLength = 1024 + uniComponentName.Length;
1671 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1672 uniName.MaximumLength,
1673 AFS_GENERIC_MEMORY_8_TAG);
1675 if( uniName.Buffer == NULL)
1678 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1681 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1682 uniName.MaximumLength,
1683 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1684 ParentObjectInfo->FileId.Cell,
1685 ParentObjectInfo->FileId.Volume,
1686 ParentObjectInfo->FileId.Vnode,
1687 ParentObjectInfo->FileId.Unique,
1690 if( !NT_SUCCESS( ntStatus))
1693 try_return( ntStatus);
1696 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1697 (size_t)uniName.MaximumLength,
1700 if( !NT_SUCCESS( ntStatus))
1703 try_return( ntStatus);
1706 uniName.Length = (USHORT)sztLength;
1708 usNameOffset = uniName.Length - uniComponentName.Length;
1710 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1711 AFS_TRACE_LEVEL_VERBOSE,
1712 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1718 uniComponentName.Length);
1720 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1721 &pDeviceExt->Specific.Control.DirNotifyList,
1733 if( uniName.Buffer != NULL)
1736 AFSExFreePool( uniName.Buffer);
1743 // For use with FsRtlNotifyFilterChangeDirectory but must
1744 // be implemented in the Framework because the library can
1748 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1749 IN void *FilterContext)
1752 BOOLEAN bReturn = TRUE;
1753 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1754 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1765 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1769 BOOLEAN bIsInSnapshot = FALSE;
1770 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1773 while( ulCount < SnapshotHdr->EntryCount)
1776 if( pSnapshotEntry->NameHash == HashIndex)
1779 bIsInSnapshot = TRUE;
1781 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1782 AFS_TRACE_LEVEL_VERBOSE,
1783 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1788 else if( pSnapshotEntry->NameHash == 0)
1799 return bIsInSnapshot;