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;
155 // Get the current Stack location
156 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
158 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
159 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
164 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
165 AFS_TRACE_LEVEL_ERROR,
166 "AFSQueryDirectory Attempted access (%08lX) when pFcb == NULL\n",
169 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
172 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
173 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
174 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
177 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
178 AFS_TRACE_LEVEL_ERROR,
179 "AFSQueryDirectory Attempted access (%08lX) to non-directory Fcb %08lX NodeType %u\n",
182 pFcb->Header.NodeTypeCode);
186 try_return( ntStatus = STATUS_INVALID_PARAMETER);
190 // Set the enumeration event ...
193 AFSSetEnumerationEvent( pFcb);
195 // Reference our input parameters to make things easier
196 ulUserBufferLength = pIrpSp->Parameters.QueryDirectory.Length;
198 FileInformationClass = pIrpSp->Parameters.QueryDirectory.FileInformationClass;
199 ulFileIndex = pIrpSp->Parameters.QueryDirectory.FileIndex;
201 puniArgFileName = (PUNICODE_STRING)pIrpSp->Parameters.QueryDirectory.FileName;
203 bRestartScan = BooleanFlagOn( pIrpSp->Flags, SL_RESTART_SCAN);
204 bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
205 bIndexSpecified = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
207 bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED));
212 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
213 AFS_TRACE_LEVEL_VERBOSE,
214 "AFSQueryDirectory Enumerating content for parent %wZ Initial Query\n",
215 &pCcb->DirectoryCB->NameInformation.FileName);
217 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
218 AFS_TRACE_LEVEL_VERBOSE,
219 "AFSQueryDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
220 &pFcb->NPFcb->Resource,
221 PsGetCurrentThread());
223 AFSAcquireExcl( &pFcb->NPFcb->Resource,
231 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
232 AFS_TRACE_LEVEL_VERBOSE,
233 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
234 &pCcb->DirectoryCB->NameInformation.FileName);
236 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
237 AFS_TRACE_LEVEL_VERBOSE,
238 "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
239 &pFcb->NPFcb->Resource,
240 PsGetCurrentThread());
242 AFSAcquireShared( &pFcb->NPFcb->Resource,
249 // Grab the directory node hdr tree lock while parsing the directory
253 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
259 // Before attempting to insert the new entry, check if we need to validate the parent
262 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
265 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
266 AFS_TRACE_LEVEL_VERBOSE,
267 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
268 &pCcb->DirectoryCB->NameInformation.FileName,
269 pFcb->ObjectInformation->FileId.Cell,
270 pFcb->ObjectInformation->FileId.Volume,
271 pFcb->ObjectInformation->FileId.Vnode,
272 pFcb->ObjectInformation->FileId.Unique);
274 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
277 if( !NT_SUCCESS( ntStatus))
280 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
281 AFS_TRACE_LEVEL_ERROR,
282 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
283 &pCcb->DirectoryCB->NameInformation.FileName,
284 pFcb->ObjectInformation->FileId.Cell,
285 pFcb->ObjectInformation->FileId.Volume,
286 pFcb->ObjectInformation->FileId.Vnode,
287 pFcb->ObjectInformation->FileId.Unique,
290 try_return( ntStatus);
294 // Perform a new snapshot of the directory
297 ntStatus = AFSSnapshotDirectory( pFcb,
301 if( !NT_SUCCESS( ntStatus))
304 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
305 AFS_TRACE_LEVEL_ERROR,
306 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
307 &pCcb->DirectoryCB->NameInformation.FileName,
311 try_return( ntStatus);
315 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
318 // We can now safely drop the lock on the node
321 AFSReleaseResource( &pFcb->NPFcb->Resource);
326 // Start processing the data
329 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
335 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
338 // Check if initial on this map
342 ntStatus = AFSSnapshotDirectory( pFcb,
346 if( !NT_SUCCESS( ntStatus))
349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
350 AFS_TRACE_LEVEL_ERROR,
351 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
352 &pCcb->DirectoryCB->NameInformation.FileName,
356 try_return( ntStatus);
359 SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
361 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
363 // build mask if none
364 if( puniArgFileName == NULL)
366 puniArgFileName = &uniTmpMaskName;
367 puniArgFileName->Length = 0;
368 puniArgFileName->Buffer = NULL;
371 if( puniArgFileName->Length == 0)
374 puniArgFileName->Length = sizeof(WCHAR);
375 puniArgFileName->MaximumLength = (USHORT)4;
378 if( puniArgFileName->Buffer == NULL)
381 puniArgFileName->Buffer = wchMaskBuffer;
383 RtlZeroMemory( wchMaskBuffer,
386 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
391 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
392 ( puniArgFileName->Buffer[0] == L'*')))
395 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
400 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
401 ( puniArgFileName->Buffer[0] == L'<')) ||
402 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
403 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
406 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
410 // Build the name for procesisng
413 pCcb->MaskName.Length = puniArgFileName->Length;
414 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
416 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
417 pCcb->MaskName.Length,
418 AFS_GENERIC_MEMORY_6_TAG);
420 if( pCcb->MaskName.Buffer == NULL)
423 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
426 if( FsRtlDoesNameContainWildCards( puniArgFileName))
429 RtlUpcaseUnicodeString( &pCcb->MaskName,
433 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
435 if( FsRtlIsNameInExpression( &pCcb->MaskName,
440 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
446 RtlCopyMemory( pCcb->MaskName.Buffer,
447 puniArgFileName->Buffer,
448 pCcb->MaskName.Length);
450 if( RtlCompareUnicodeString( &AFSPIOCtlName,
454 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
458 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
460 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
463 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
465 bReleaseMain = FALSE;
467 AFSAcquireExcl( &pFcb->NPFcb->Resource,
470 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
473 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
475 if( !NT_SUCCESS( ntStatus))
478 AFSReleaseResource( &pFcb->NPFcb->Resource);
480 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
481 AFS_TRACE_LEVEL_ERROR,
482 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
483 &pCcb->DirectoryCB->NameInformation.FileName,
487 try_return( ntStatus);
491 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
496 AFSReleaseResource( &pFcb->NPFcb->Resource);
500 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
501 AFS_TRACE_LEVEL_VERBOSE,
502 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
503 &pCcb->DirectoryCB->NameInformation.FileName,
508 // Check if we need to start from index
513 // Need to set up the initial point for the query
516 pCcb->CurrentDirIndex = ulFileIndex - 1;
519 // Check if we need to restart the scan
520 else if( bRestartScan)
524 // Reset the current scan processing
527 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
530 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
535 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
539 switch( FileInformationClass)
542 case FileDirectoryInformation:
544 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
548 case FileFullDirectoryInformation:
550 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
554 case FileNamesInformation:
556 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
560 case FileBothDirectoryInformation:
562 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
566 case FileIdBothDirectoryInformation:
568 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
573 case FileIdFullDirectoryInformation:
575 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
582 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
583 AFS_TRACE_LEVEL_ERROR,
584 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
586 FileInformationClass);
588 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
591 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
593 bReleaseMain = FALSE;
598 ULONG ulBytesRemainingInBuffer;
602 // If the user had requested only a single match and we have
603 // returned that, then we stop at this point.
606 if( bReturnSingleEntry && ulNextEntry != 0)
609 try_return( ntStatus);
612 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
615 if( pDirEntry == NULL)
618 if( ulNextEntry == 0)
621 if( ( bInitialQuery ||
623 pCcb->MaskName.Buffer != NULL)
625 ntStatus = STATUS_NO_SUCH_FILE;
629 ntStatus = STATUS_NO_MORE_FILES;
633 try_return( ntStatus);
637 // Skip the entry if it is pending delete or deleted
640 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
641 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
644 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
649 pObjectInfo = pDirEntry->ObjectInformation;
652 // Apply the name filter if there is one
655 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
659 // Only returning directories?
662 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
665 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
668 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
673 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
677 // Are we doing a wild card search?
680 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
683 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
684 &pDirEntry->NameInformation.FileName,
689 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
697 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
703 // See if this is a match for a case insensitive search
706 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
711 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
721 // Be sure the information is valid
722 // We don't worry about entries while enumerating the directory
725 AFSValidateEntry( pDirEntry,
730 pObjectInfo = pDirEntry->ObjectInformation;
732 bUseFileInfo = FALSE;
734 ulAdditionalAttributes = 0;
736 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
740 // Go grab the file information for this entry
741 // No worries on failures since we will just display
742 // pseudo information
745 RtlZeroMemory( &stFileInfo,
746 sizeof( AFSFileInfoCB));
748 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
756 ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
762 // Here are the rules concerning filling up the buffer:
764 // 1. The Io system guarantees that there will always be
765 // enough room for at least one base record.
767 // 2. If the full first record (including file name) cannot
768 // fit, as much of the name as possible is copied and
769 // STATUS_BUFFER_OVERFLOW is returned.
771 // 3. If a subsequent record cannot completely fit into the
772 // buffer, none of it (as in 0 bytes) is copied, and
773 // STATUS_SUCCESS is returned. A subsequent query will
774 // pick up with this record.
776 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
778 if( ( ulNextEntry != 0) &&
779 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
780 ( ulUserBufferLength < ulNextEntry) ) )
784 // Back off our current index
787 pCcb->CurrentDirIndex--;
789 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
791 try_return( ntStatus = STATUS_SUCCESS);
794 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
795 AFS_TRACE_LEVEL_VERBOSE,
796 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
797 &pCcb->DirectoryCB->NameInformation.FileName,
798 &pDirEntry->NameInformation.FileName);
800 // Zero the base part of the structure.
801 RtlZeroMemory( &pBuffer[ ulNextEntry],
804 switch( FileInformationClass)
807 // Now fill the base parts of the structure that are applicable.
808 case FileIdBothDirectoryInformation:
809 case FileBothDirectoryInformation:
811 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
813 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
815 if( pDirEntry->NameInformation.ShortNameLength > 0)
817 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
818 &pDirEntry->NameInformation.ShortName[ 0],
819 pBothDirInfo->ShortNameLength);
822 case FileIdFullDirectoryInformation:
823 case FileFullDirectoryInformation:
825 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
826 pFullDirInfo->EaSize = 0;
828 case FileDirectoryInformation:
830 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
835 pDirInfo->CreationTime = stFileInfo.CreationTime;
836 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
837 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
838 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
840 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
841 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
843 pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
845 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
848 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
849 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
850 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
851 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
853 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
854 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
856 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
858 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
862 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
868 pDirInfo->CreationTime = pObjectInfo->CreationTime;
869 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
870 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
871 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
873 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
874 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
876 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
880 // Check if the name begins with a . and we are hiding them
883 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
884 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
885 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
888 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
891 pDirInfo->FileIndex = pDirEntry->FileIndex;
892 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
897 case FileNamesInformation:
899 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
900 pNamesInfo->FileIndex = pDirEntry->FileIndex;
901 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
907 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
908 AFS_TRACE_LEVEL_ERROR,
909 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
911 FileInformationClass);
913 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
915 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
921 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
922 pDirEntry->NameInformation.FileName.Length :
923 ulBytesRemainingInBuffer - ulBaseLength;
925 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
926 pDirEntry->NameInformation.FileName.Buffer,
929 // Set up the previous next entry offset
930 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
932 // And indicate how much of the user buffer we have currently
934 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
936 // Check for the case that a single entry doesn't fit.
937 // This should only get this far on the first entry.
938 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
941 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
943 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
946 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
948 dStatus = STATUS_SUCCESS;
950 // Set ourselves up for the next iteration
951 ulLastEntry = ulNextEntry;
952 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
960 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
966 AFSReleaseResource( &pFcb->NPFcb->Resource);
972 AFSClearEnumerationEvent( pFcb);
980 AFSNotifyChangeDirectory( IN PIRP Irp)
983 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
984 PIO_STACK_LOCATION pIrpSp;
987 ULONG ulCompletionFilter;
989 BOOLEAN bReleaseLock = FALSE;
994 // Get the current Stack location
995 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
997 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
998 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1003 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1004 AFS_TRACE_LEVEL_ERROR,
1005 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1008 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1011 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1012 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1013 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1016 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1017 AFS_TRACE_LEVEL_ERROR,
1018 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1019 &pCcb->DirectoryCB->NameInformation.FileName,
1020 pFcb->Header.NodeTypeCode);
1022 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1025 // Reference our input parameter to make things easier
1026 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1027 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1032 &pFcb->NPFcb->Resource,
1033 PsGetCurrentThread());
1035 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1038 bReleaseLock = TRUE;
1041 // Check if the node has already been deleted
1044 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1047 try_return( ntStatus = STATUS_FILE_DELETED);
1049 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1052 try_return( ntStatus = STATUS_DELETE_PENDING);
1055 // Call the Fsrtl package to process the request.
1056 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1062 if( !NT_SUCCESS( ntStatus))
1064 try_return( ntStatus);
1067 ntStatus = STATUS_PENDING;
1074 AFSReleaseResource( &pFcb->NPFcb->Resource);
1082 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1086 AFSDirectoryCB *pDirEntry = NULL;
1087 NTSTATUS ntStatus = STATUS_SUCCESS;
1088 AFSSnapshotHdr *pSnapshotHdr = NULL;
1089 AFSSnapshotEntry *pSnapshotEntry = NULL;
1097 // Is this a PIOCtl query
1100 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1103 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1104 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1107 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1109 if( pDirEntry != NULL)
1112 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1115 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1116 AFS_TRACE_LEVEL_VERBOSE,
1117 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1118 &pDirEntry->NameInformation.FileName,
1119 ObjectInfo->FileId.Cell,
1120 ObjectInfo->FileId.Volume,
1121 ObjectInfo->FileId.Vnode,
1122 ObjectInfo->FileId.Unique);
1125 Ccb->CurrentDirIndex++;
1127 try_return( ntStatus);
1130 Ccb->CurrentDirIndex++;
1132 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1136 // Return the .. entry
1139 pDirEntry = AFSGlobalDotDirEntry;
1141 if( pDirEntry != NULL)
1144 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1147 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1148 AFS_TRACE_LEVEL_VERBOSE,
1149 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1150 &pDirEntry->NameInformation.FileName,
1151 ObjectInfo->FileId.Cell,
1152 ObjectInfo->FileId.Volume,
1153 ObjectInfo->FileId.Vnode,
1154 ObjectInfo->FileId.Unique);
1156 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1160 // Return the .. entry
1163 pDirEntry = AFSGlobalDotDotDirEntry;
1165 if( pDirEntry != NULL)
1168 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1171 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1172 AFS_TRACE_LEVEL_VERBOSE,
1173 "AFSLocateNextDirEntry Returning2 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);
1183 pSnapshotHdr = Ccb->DirectorySnapshot;
1185 if( pSnapshotHdr == NULL ||
1186 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1189 try_return( ntStatus);
1192 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1194 ulCount = Ccb->CurrentDirIndex;
1196 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1197 AFS_TRACE_LEVEL_VERBOSE,
1198 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1202 // Get to a valid entry
1205 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1208 while( ulCount < pSnapshotHdr->EntryCount)
1213 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1214 AFS_TRACE_LEVEL_VERBOSE,
1215 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1216 pSnapshotEntry->NameHash);
1218 if( pSnapshotEntry->NameHash == 0)
1224 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1225 pSnapshotEntry->NameHash,
1228 if( !NT_SUCCESS( ntStatus) ||
1232 if( pDirEntry != NULL)
1235 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1236 AFS_TRACE_LEVEL_VERBOSE,
1237 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1238 &pDirEntry->NameInformation.FileName,
1239 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1240 ObjectInfo->FileId.Cell,
1241 ObjectInfo->FileId.Volume,
1242 ObjectInfo->FileId.Vnode,
1243 ObjectInfo->FileId.Unique);
1245 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252 AFS_TRACE_LEVEL_VERBOSE,
1253 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1254 ObjectInfo->FileId.Cell,
1255 ObjectInfo->FileId.Volume,
1256 ObjectInfo->FileId.Vnode,
1257 ObjectInfo->FileId.Unique);
1263 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1264 AFS_TRACE_LEVEL_VERBOSE,
1265 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1266 pSnapshotEntry->NameHash,
1267 ObjectInfo->FileId.Cell,
1268 ObjectInfo->FileId.Volume,
1269 ObjectInfo->FileId.Vnode,
1270 ObjectInfo->FileId.Unique);
1276 Ccb->CurrentDirIndex++;
1279 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1291 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1296 AFSDirectoryCB *pDirEntry = NULL;
1297 NTSTATUS ntStatus = STATUS_SUCCESS;
1298 AFSSnapshotHdr *pSnapshotHdr = NULL;
1299 AFSSnapshotEntry *pSnapshotEntry = NULL;
1305 Ccb->CurrentDirIndex = DirIndex;
1307 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1311 // Return the .. entry
1314 pDirEntry = AFSGlobalDotDirEntry;
1316 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1320 // Return the .. entry
1323 pDirEntry = AFSGlobalDotDotDirEntry;
1328 pSnapshotHdr = Ccb->DirectorySnapshot;
1330 if( pSnapshotHdr == NULL ||
1331 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1334 try_return( ntStatus);
1337 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1339 ulCount = Ccb->CurrentDirIndex;
1342 // Get to a valid entry
1345 while( ulCount < pSnapshotHdr->EntryCount)
1350 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1351 pSnapshotEntry->NameHash,
1354 if( !NT_SUCCESS( ntStatus) ||
1355 ( pDirEntry != NULL &&
1356 pDirEntry->FileIndex == DirIndex))
1367 if( pDirEntry != NULL)
1370 Ccb->CurrentDirIndex = ulCount;
1383 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1385 IN BOOLEAN ResetIndex)
1388 NTSTATUS ntStatus = STATUS_SUCCESS;
1389 AFSSnapshotHdr *pSnapshotHdr = NULL;
1390 AFSSnapshotEntry *pSnapshotEntry = NULL;
1391 AFSDirectoryCB *pDirEntry = NULL;
1400 // Set it up so we still get the . and .. entries for empty directories
1403 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1406 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1411 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1415 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1419 // If we have a snapshot then clear it out
1422 if( Ccb->DirectorySnapshot != NULL)
1425 AFSExFreePool( Ccb->DirectorySnapshot);
1427 Ccb->DirectorySnapshot = NULL;
1430 try_return( ntStatus);
1434 // Allocate our snapshot buffer for this enumeration
1437 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1438 sizeof( AFSSnapshotHdr) +
1439 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1440 sizeof( AFSSnapshotEntry)),
1441 AFS_DIR_SNAPSHOT_TAG);
1443 if( pSnapshotHdr == NULL)
1446 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1449 RtlZeroMemory( pSnapshotHdr,
1450 sizeof( AFSSnapshotHdr) +
1451 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1452 sizeof( AFSSnapshotEntry)));
1454 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1456 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1459 // Populate our snapshot
1462 pSnapshotEntry = pSnapshotHdr->TopEntry;
1464 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1466 while( pDirEntry != NULL)
1469 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1470 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1471 !AFSIsNameInSnapshot( pSnapshotHdr,
1472 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1475 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1476 AFS_TRACE_LEVEL_VERBOSE,
1477 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1478 pSnapshotHdr->EntryCount,
1479 &pDirEntry->NameInformation.FileName,
1480 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1482 Fcb->ObjectInformation->FileId.Cell,
1483 Fcb->ObjectInformation->FileId.Volume,
1484 Fcb->ObjectInformation->FileId.Vnode,
1485 Fcb->ObjectInformation->FileId.Unique);
1487 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1494 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1495 AFS_TRACE_LEVEL_VERBOSE,
1496 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1497 pSnapshotHdr->EntryCount,
1498 &pDirEntry->NameInformation.FileName,
1499 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1501 Fcb->ObjectInformation->FileId.Cell,
1502 Fcb->ObjectInformation->FileId.Volume,
1503 Fcb->ObjectInformation->FileId.Vnode,
1504 Fcb->ObjectInformation->FileId.Unique);
1507 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1510 if( Ccb->DirectorySnapshot != NULL)
1513 AFSExFreePool( Ccb->DirectorySnapshot);
1515 Ccb->DirectorySnapshot = NULL;
1518 Ccb->DirectorySnapshot = pSnapshotHdr;
1529 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1531 IN BOOLEAN WatchTree,
1532 IN ULONG CompletionFilter,
1536 NTSTATUS ntStatus = STATUS_SUCCESS;
1537 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1544 // Build a dir name based on the FID of the file
1547 if( Ccb->NotifyMask.Buffer == NULL)
1550 Ccb->NotifyMask.Length = 0;
1551 Ccb->NotifyMask.MaximumLength = 1024;
1553 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1554 Ccb->NotifyMask.MaximumLength,
1555 AFS_GENERIC_MEMORY_7_TAG);
1557 if( Ccb->NotifyMask.Buffer == NULL)
1560 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1563 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1564 Ccb->NotifyMask.MaximumLength,
1565 L"\\%08lX.%08lX.%08lX.%08lX",
1566 ObjectInfo->FileId.Cell,
1567 ObjectInfo->FileId.Volume,
1568 ObjectInfo->FileId.Vnode,
1569 ObjectInfo->FileId.Unique);
1571 if( !NT_SUCCESS( ntStatus))
1574 try_return( ntStatus);
1577 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1578 (size_t)Ccb->NotifyMask.MaximumLength,
1581 if( !NT_SUCCESS( ntStatus))
1584 try_return( ntStatus);
1587 Ccb->NotifyMask.Length = (USHORT)sztLength;
1590 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1591 AFS_TRACE_LEVEL_VERBOSE,
1592 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1598 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1599 &pDeviceExt->Specific.Control.DirNotifyList,
1601 (PSTRING)&Ccb->NotifyMask,
1612 if( !NT_SUCCESS( ntStatus))
1615 if( Ccb->NotifyMask.Buffer != NULL)
1618 AFSExFreePool( Ccb->NotifyMask.Buffer);
1620 Ccb->NotifyMask.Buffer = NULL;
1629 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1631 IN ULONG NotifyFilter,
1632 IN ULONG NotificationAction)
1635 NTSTATUS ntStatus = STATUS_SUCCESS;
1636 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1637 UNICODE_STRING uniName, uniComponentName;
1639 USHORT usNameOffset = 0;
1644 uniName.Buffer = NULL;
1646 if( ParentObjectInfo == NULL ||
1647 AFSGlobalRoot == NULL)
1650 try_return( ntStatus);
1656 RtlInitUnicodeString( &uniComponentName,
1662 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1666 // Build a dir name based on the FID of the file
1670 uniName.MaximumLength = 1024 + uniComponentName.Length;
1672 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1673 uniName.MaximumLength,
1674 AFS_GENERIC_MEMORY_8_TAG);
1676 if( uniName.Buffer == NULL)
1679 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1682 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1683 uniName.MaximumLength,
1684 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1685 ParentObjectInfo->FileId.Cell,
1686 ParentObjectInfo->FileId.Volume,
1687 ParentObjectInfo->FileId.Vnode,
1688 ParentObjectInfo->FileId.Unique,
1691 if( !NT_SUCCESS( ntStatus))
1694 try_return( ntStatus);
1697 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1698 (size_t)uniName.MaximumLength,
1701 if( !NT_SUCCESS( ntStatus))
1704 try_return( ntStatus);
1707 uniName.Length = (USHORT)sztLength;
1709 usNameOffset = uniName.Length - uniComponentName.Length;
1711 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1712 AFS_TRACE_LEVEL_VERBOSE,
1713 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1719 uniComponentName.Length);
1721 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1722 &pDeviceExt->Specific.Control.DirNotifyList,
1734 if( uniName.Buffer != NULL)
1737 AFSExFreePool( uniName.Buffer);
1744 // For use with FsRtlNotifyFilterChangeDirectory but must
1745 // be implemented in the Framework because the library can
1749 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1750 IN void *FilterContext)
1753 BOOLEAN bReturn = TRUE;
1754 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1755 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1766 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1770 BOOLEAN bIsInSnapshot = FALSE;
1771 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1774 while( ulCount < SnapshotHdr->EntryCount)
1777 if( pSnapshotEntry->NameHash == HashIndex)
1780 bIsInSnapshot = TRUE;
1782 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1783 AFS_TRACE_LEVEL_VERBOSE,
1784 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1789 else if( pSnapshotEntry->NameHash == 0)
1800 return bIsInSnapshot;