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,
230 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
231 AFS_TRACE_LEVEL_VERBOSE,
232 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
233 &pCcb->DirectoryCB->NameInformation.FileName);
235 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
236 AFS_TRACE_LEVEL_VERBOSE,
237 "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
238 &pFcb->NPFcb->Resource,
239 PsGetCurrentThread());
241 AFSAcquireShared( &pFcb->NPFcb->Resource,
248 // Grab the directory node hdr tree lock while parsing the directory
252 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
258 // Before attempting to insert the new entry, check if we need to validate the parent
261 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
264 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
265 AFS_TRACE_LEVEL_VERBOSE,
266 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
267 &pCcb->DirectoryCB->NameInformation.FileName,
268 pFcb->ObjectInformation->FileId.Cell,
269 pFcb->ObjectInformation->FileId.Volume,
270 pFcb->ObjectInformation->FileId.Vnode,
271 pFcb->ObjectInformation->FileId.Unique);
273 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
276 if( !NT_SUCCESS( ntStatus))
279 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
280 AFS_TRACE_LEVEL_ERROR,
281 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
282 &pCcb->DirectoryCB->NameInformation.FileName,
283 pFcb->ObjectInformation->FileId.Cell,
284 pFcb->ObjectInformation->FileId.Volume,
285 pFcb->ObjectInformation->FileId.Vnode,
286 pFcb->ObjectInformation->FileId.Unique,
289 try_return( ntStatus);
293 // Perform a new snapshot of the directory
296 ntStatus = AFSSnapshotDirectory( pFcb,
300 if( !NT_SUCCESS( ntStatus))
303 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
304 AFS_TRACE_LEVEL_ERROR,
305 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
306 &pCcb->DirectoryCB->NameInformation.FileName,
310 try_return( ntStatus);
314 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
317 // We can now safely drop the lock on the node
320 AFSReleaseResource( &pFcb->NPFcb->Resource);
325 // Start processing the data
328 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
334 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
337 // Check if initial on this map
341 ntStatus = AFSSnapshotDirectory( pFcb,
345 if( !NT_SUCCESS( ntStatus))
348 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
349 AFS_TRACE_LEVEL_ERROR,
350 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
351 &pCcb->DirectoryCB->NameInformation.FileName,
355 try_return( ntStatus);
358 SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
360 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
362 // build mask if none
363 if( puniArgFileName == NULL)
365 puniArgFileName = &uniTmpMaskName;
366 puniArgFileName->Length = 0;
367 puniArgFileName->Buffer = NULL;
370 if( puniArgFileName->Length == 0)
373 puniArgFileName->Length = sizeof(WCHAR);
374 puniArgFileName->MaximumLength = (USHORT)4;
377 if( puniArgFileName->Buffer == NULL)
380 puniArgFileName->Buffer = wchMaskBuffer;
382 RtlZeroMemory( wchMaskBuffer,
385 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
390 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
391 ( puniArgFileName->Buffer[0] == L'*')))
394 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
399 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
400 ( puniArgFileName->Buffer[0] == L'<')) ||
401 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
402 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
405 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
409 // Build the name for procesisng
412 pCcb->MaskName.Length = puniArgFileName->Length;
413 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
415 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
416 pCcb->MaskName.Length,
417 AFS_GENERIC_MEMORY_6_TAG);
419 if( pCcb->MaskName.Buffer == NULL)
422 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
425 if( FsRtlDoesNameContainWildCards( puniArgFileName))
428 RtlUpcaseUnicodeString( &pCcb->MaskName,
432 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
434 if( FsRtlIsNameInExpression( &pCcb->MaskName,
439 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
445 RtlCopyMemory( pCcb->MaskName.Buffer,
446 puniArgFileName->Buffer,
447 pCcb->MaskName.Length);
449 if( RtlCompareUnicodeString( &AFSPIOCtlName,
453 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
457 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
459 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
462 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
464 bReleaseMain = FALSE;
466 AFSAcquireExcl( &pFcb->NPFcb->Resource,
469 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
472 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
474 if( !NT_SUCCESS( ntStatus))
477 AFSReleaseResource( &pFcb->NPFcb->Resource);
479 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
480 AFS_TRACE_LEVEL_ERROR,
481 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
482 &pCcb->DirectoryCB->NameInformation.FileName,
486 try_return( ntStatus);
490 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
495 AFSReleaseResource( &pFcb->NPFcb->Resource);
499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
500 AFS_TRACE_LEVEL_VERBOSE,
501 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
502 &pCcb->DirectoryCB->NameInformation.FileName,
507 // Check if we need to start from index
512 // Need to set up the initial point for the query
515 pCcb->CurrentDirIndex = ulFileIndex - 1;
518 // Check if we need to restart the scan
519 else if( bRestartScan)
523 // Reset the current scan processing
526 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
529 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
534 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
538 switch( FileInformationClass)
541 case FileDirectoryInformation:
543 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
547 case FileFullDirectoryInformation:
549 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
553 case FileNamesInformation:
555 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
559 case FileBothDirectoryInformation:
561 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
565 case FileIdBothDirectoryInformation:
567 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
572 case FileIdFullDirectoryInformation:
574 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
581 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
582 AFS_TRACE_LEVEL_ERROR,
583 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
585 FileInformationClass);
587 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
590 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
592 bReleaseMain = FALSE;
597 ULONG ulBytesRemainingInBuffer;
601 // If the user had requested only a single match and we have
602 // returned that, then we stop at this point.
605 if( bReturnSingleEntry && ulNextEntry != 0)
608 try_return( ntStatus);
611 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
614 if( pDirEntry == NULL)
617 if( ulNextEntry == 0)
620 if( ( bInitialQuery ||
622 pCcb->MaskName.Buffer != NULL)
624 ntStatus = STATUS_NO_SUCH_FILE;
628 ntStatus = STATUS_NO_MORE_FILES;
632 try_return( ntStatus);
636 // Skip the entry if it is pending delete or deleted
639 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
640 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
643 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
648 pObjectInfo = pDirEntry->ObjectInformation;
651 // Apply the name filter if there is one
654 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
658 // Only returning directories?
661 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
664 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
667 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
672 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
676 // Are we doing a wild card search?
679 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
682 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
683 &pDirEntry->NameInformation.FileName,
688 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
696 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
702 // See if this is a match for a case insensitive search
705 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
710 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
720 // Be sure the information is valid
721 // We don't worry about entries while enumerating the directory
724 AFSValidateEntry( pDirEntry,
729 pObjectInfo = pDirEntry->ObjectInformation;
731 bUseFileInfo = FALSE;
733 ulAdditionalAttributes = 0;
735 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
739 // Go grab the file information for this entry
740 // No worries on failures since we will just display
741 // pseudo information
744 RtlZeroMemory( &stFileInfo,
745 sizeof( AFSFileInfoCB));
747 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
755 ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
761 // Here are the rules concerning filling up the buffer:
763 // 1. The Io system guarantees that there will always be
764 // enough room for at least one base record.
766 // 2. If the full first record (including file name) cannot
767 // fit, as much of the name as possible is copied and
768 // STATUS_BUFFER_OVERFLOW is returned.
770 // 3. If a subsequent record cannot completely fit into the
771 // buffer, none of it (as in 0 bytes) is copied, and
772 // STATUS_SUCCESS is returned. A subsequent query will
773 // pick up with this record.
775 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
777 if( ( ulNextEntry != 0) &&
778 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
779 ( ulUserBufferLength < ulNextEntry) ) )
783 // Back off our current index
786 pCcb->CurrentDirIndex--;
788 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
790 try_return( ntStatus = STATUS_SUCCESS);
793 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
794 AFS_TRACE_LEVEL_VERBOSE,
795 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
796 &pCcb->DirectoryCB->NameInformation.FileName,
797 &pDirEntry->NameInformation.FileName);
799 // Zero the base part of the structure.
800 RtlZeroMemory( &pBuffer[ ulNextEntry],
803 switch( FileInformationClass)
806 // Now fill the base parts of the structure that are applicable.
807 case FileIdBothDirectoryInformation:
808 case FileBothDirectoryInformation:
810 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
812 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
814 if( pDirEntry->NameInformation.ShortNameLength > 0)
816 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
817 &pDirEntry->NameInformation.ShortName[ 0],
818 pBothDirInfo->ShortNameLength);
821 case FileIdFullDirectoryInformation:
822 case FileFullDirectoryInformation:
824 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
825 pFullDirInfo->EaSize = 0;
827 case FileDirectoryInformation:
829 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
834 pDirInfo->CreationTime = stFileInfo.CreationTime;
835 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
836 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
837 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
839 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
840 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
842 pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
844 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
847 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
848 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
849 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
850 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
852 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
853 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
855 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
857 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
861 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
867 pDirInfo->CreationTime = pObjectInfo->CreationTime;
868 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
869 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
870 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
872 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
873 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
875 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
879 // Check if the name begins with a . and we are hiding them
882 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
883 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
884 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
887 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
890 pDirInfo->FileIndex = pDirEntry->FileIndex;
891 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
896 case FileNamesInformation:
898 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
899 pNamesInfo->FileIndex = pDirEntry->FileIndex;
900 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
906 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
907 AFS_TRACE_LEVEL_ERROR,
908 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
910 FileInformationClass);
912 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
914 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
920 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
921 pDirEntry->NameInformation.FileName.Length :
922 ulBytesRemainingInBuffer - ulBaseLength;
924 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
925 pDirEntry->NameInformation.FileName.Buffer,
928 // Set up the previous next entry offset
929 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
931 // And indicate how much of the user buffer we have currently
933 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
935 // Check for the case that a single entry doesn't fit.
936 // This should only get this far on the first entry.
937 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
940 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
942 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
945 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
947 dStatus = STATUS_SUCCESS;
949 // Set ourselves up for the next iteration
950 ulLastEntry = ulNextEntry;
951 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
959 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
965 AFSReleaseResource( &pFcb->NPFcb->Resource);
971 AFSClearEnumerationEvent( pFcb);
979 AFSNotifyChangeDirectory( IN PIRP Irp)
982 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
983 PIO_STACK_LOCATION pIrpSp;
986 ULONG ulCompletionFilter;
988 BOOLEAN bReleaseLock = FALSE;
993 // Get the current Stack location
994 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
996 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
997 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1002 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1003 AFS_TRACE_LEVEL_ERROR,
1004 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1007 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1010 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1011 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1012 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1015 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1016 AFS_TRACE_LEVEL_ERROR,
1017 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1018 &pCcb->DirectoryCB->NameInformation.FileName,
1019 pFcb->Header.NodeTypeCode);
1021 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1024 // Reference our input parameter to make things easier
1025 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1026 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1028 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1029 AFS_TRACE_LEVEL_VERBOSE,
1030 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1031 &pFcb->NPFcb->Resource,
1032 PsGetCurrentThread());
1034 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1037 bReleaseLock = TRUE;
1040 // Check if the node has already been deleted
1043 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1046 try_return( ntStatus = STATUS_FILE_DELETED);
1048 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1051 try_return( ntStatus = STATUS_DELETE_PENDING);
1054 // Call the Fsrtl package to process the request.
1055 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1061 if( !NT_SUCCESS( ntStatus))
1063 try_return( ntStatus);
1066 ntStatus = STATUS_PENDING;
1073 AFSReleaseResource( &pFcb->NPFcb->Resource);
1081 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1085 AFSDirectoryCB *pDirEntry = NULL;
1086 NTSTATUS ntStatus = STATUS_SUCCESS;
1087 AFSSnapshotHdr *pSnapshotHdr = NULL;
1088 AFSSnapshotEntry *pSnapshotEntry = NULL;
1095 // Is this a PIOCtl query
1098 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1101 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1102 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1105 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1107 if( pDirEntry != NULL)
1109 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1112 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1113 AFS_TRACE_LEVEL_VERBOSE,
1114 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1115 &pDirEntry->NameInformation.FileName,
1116 ObjectInfo->FileId.Cell,
1117 ObjectInfo->FileId.Volume,
1118 ObjectInfo->FileId.Vnode,
1119 ObjectInfo->FileId.Unique);
1122 Ccb->CurrentDirIndex++;
1124 try_return( ntStatus);
1127 Ccb->CurrentDirIndex++;
1129 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1133 // Return the .. entry
1136 pDirEntry = AFSGlobalDotDirEntry;
1138 if( pDirEntry != NULL)
1140 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1143 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144 AFS_TRACE_LEVEL_VERBOSE,
1145 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1146 &pDirEntry->NameInformation.FileName,
1147 ObjectInfo->FileId.Cell,
1148 ObjectInfo->FileId.Volume,
1149 ObjectInfo->FileId.Vnode,
1150 ObjectInfo->FileId.Unique);
1152 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1156 // Return the .. entry
1159 pDirEntry = AFSGlobalDotDotDirEntry;
1161 if( pDirEntry != NULL)
1163 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1166 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1167 AFS_TRACE_LEVEL_VERBOSE,
1168 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1169 &pDirEntry->NameInformation.FileName,
1170 ObjectInfo->FileId.Cell,
1171 ObjectInfo->FileId.Volume,
1172 ObjectInfo->FileId.Vnode,
1173 ObjectInfo->FileId.Unique);
1178 pSnapshotHdr = Ccb->DirectorySnapshot;
1180 if( pSnapshotHdr == NULL ||
1181 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1184 try_return( ntStatus);
1187 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1189 ulCount = Ccb->CurrentDirIndex;
1191 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1192 AFS_TRACE_LEVEL_VERBOSE,
1193 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1197 // Get to a valid entry
1200 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1203 while( ulCount < pSnapshotHdr->EntryCount)
1208 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1209 AFS_TRACE_LEVEL_VERBOSE,
1210 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1211 pSnapshotEntry->NameHash);
1213 if( pSnapshotEntry->NameHash == 0)
1219 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1220 pSnapshotEntry->NameHash,
1223 if( !NT_SUCCESS( ntStatus) ||
1227 if( pDirEntry != NULL)
1230 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1231 AFS_TRACE_LEVEL_VERBOSE,
1232 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1233 &pDirEntry->NameInformation.FileName,
1234 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1235 ObjectInfo->FileId.Cell,
1236 ObjectInfo->FileId.Volume,
1237 ObjectInfo->FileId.Vnode,
1238 ObjectInfo->FileId.Unique);
1240 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1246 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1247 AFS_TRACE_LEVEL_VERBOSE,
1248 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1249 ObjectInfo->FileId.Cell,
1250 ObjectInfo->FileId.Volume,
1251 ObjectInfo->FileId.Vnode,
1252 ObjectInfo->FileId.Unique);
1258 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1259 AFS_TRACE_LEVEL_VERBOSE,
1260 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1261 pSnapshotEntry->NameHash,
1262 ObjectInfo->FileId.Cell,
1263 ObjectInfo->FileId.Volume,
1264 ObjectInfo->FileId.Vnode,
1265 ObjectInfo->FileId.Unique);
1271 Ccb->CurrentDirIndex++;
1274 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1286 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1291 AFSDirectoryCB *pDirEntry = NULL;
1292 NTSTATUS ntStatus = STATUS_SUCCESS;
1293 AFSSnapshotHdr *pSnapshotHdr = NULL;
1294 AFSSnapshotEntry *pSnapshotEntry = NULL;
1300 Ccb->CurrentDirIndex = DirIndex;
1302 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1306 // Return the .. entry
1309 pDirEntry = AFSGlobalDotDirEntry;
1311 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1315 // Return the .. entry
1318 pDirEntry = AFSGlobalDotDotDirEntry;
1323 pSnapshotHdr = Ccb->DirectorySnapshot;
1325 if( pSnapshotHdr == NULL ||
1326 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1329 try_return( ntStatus);
1332 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1334 ulCount = Ccb->CurrentDirIndex;
1337 // Get to a valid entry
1340 while( ulCount < pSnapshotHdr->EntryCount)
1345 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1346 pSnapshotEntry->NameHash,
1349 if( !NT_SUCCESS( ntStatus) ||
1350 ( pDirEntry != NULL &&
1351 pDirEntry->FileIndex == DirIndex))
1362 if( pDirEntry != NULL)
1365 Ccb->CurrentDirIndex = ulCount;
1378 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1380 IN BOOLEAN ResetIndex)
1383 NTSTATUS ntStatus = STATUS_SUCCESS;
1384 AFSSnapshotHdr *pSnapshotHdr = NULL;
1385 AFSSnapshotEntry *pSnapshotEntry = NULL;
1386 AFSDirectoryCB *pDirEntry = NULL;
1395 // Set it up so we still get the . and .. entries for empty directories
1398 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1401 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1406 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1410 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1414 // If we have a snapshot then clear it out
1417 if( Ccb->DirectorySnapshot != NULL)
1420 AFSExFreePool( Ccb->DirectorySnapshot);
1422 Ccb->DirectorySnapshot = NULL;
1425 try_return( ntStatus);
1429 // Allocate our snapshot buffer for this enumeration
1432 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1433 sizeof( AFSSnapshotHdr) +
1434 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1435 sizeof( AFSSnapshotEntry)),
1436 AFS_DIR_SNAPSHOT_TAG);
1438 if( pSnapshotHdr == NULL)
1441 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1444 RtlZeroMemory( pSnapshotHdr,
1445 sizeof( AFSSnapshotHdr) +
1446 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1447 sizeof( AFSSnapshotEntry)));
1449 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1451 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1454 // Populate our snapshot
1457 pSnapshotEntry = pSnapshotHdr->TopEntry;
1459 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1461 while( pDirEntry != NULL)
1464 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1465 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1466 !AFSIsNameInSnapshot( pSnapshotHdr,
1467 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1470 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1471 AFS_TRACE_LEVEL_VERBOSE,
1472 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1473 pSnapshotHdr->EntryCount,
1474 &pDirEntry->NameInformation.FileName,
1475 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1477 Fcb->ObjectInformation->FileId.Cell,
1478 Fcb->ObjectInformation->FileId.Volume,
1479 Fcb->ObjectInformation->FileId.Vnode,
1480 Fcb->ObjectInformation->FileId.Unique);
1482 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1489 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1490 AFS_TRACE_LEVEL_VERBOSE,
1491 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1492 pSnapshotHdr->EntryCount,
1493 &pDirEntry->NameInformation.FileName,
1494 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1496 Fcb->ObjectInformation->FileId.Cell,
1497 Fcb->ObjectInformation->FileId.Volume,
1498 Fcb->ObjectInformation->FileId.Vnode,
1499 Fcb->ObjectInformation->FileId.Unique);
1502 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1505 if( Ccb->DirectorySnapshot != NULL)
1508 AFSExFreePool( Ccb->DirectorySnapshot);
1510 Ccb->DirectorySnapshot = NULL;
1513 Ccb->DirectorySnapshot = pSnapshotHdr;
1524 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1526 IN BOOLEAN WatchTree,
1527 IN ULONG CompletionFilter,
1531 NTSTATUS ntStatus = STATUS_SUCCESS;
1532 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1539 // Build a dir name based on the FID of the file
1542 if( Ccb->NotifyMask.Buffer == NULL)
1545 Ccb->NotifyMask.Length = 0;
1546 Ccb->NotifyMask.MaximumLength = 1024;
1548 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1549 Ccb->NotifyMask.MaximumLength,
1550 AFS_GENERIC_MEMORY_7_TAG);
1552 if( Ccb->NotifyMask.Buffer == NULL)
1555 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1558 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1559 Ccb->NotifyMask.MaximumLength,
1560 L"\\%08lX.%08lX.%08lX.%08lX",
1561 ObjectInfo->FileId.Cell,
1562 ObjectInfo->FileId.Volume,
1563 ObjectInfo->FileId.Vnode,
1564 ObjectInfo->FileId.Unique);
1566 if( !NT_SUCCESS( ntStatus))
1569 try_return( ntStatus);
1572 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1573 (size_t)Ccb->NotifyMask.MaximumLength,
1576 if( !NT_SUCCESS( ntStatus))
1579 try_return( ntStatus);
1582 Ccb->NotifyMask.Length = (USHORT)sztLength;
1585 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1586 AFS_TRACE_LEVEL_VERBOSE,
1587 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1593 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1594 &pDeviceExt->Specific.Control.DirNotifyList,
1596 (PSTRING)&Ccb->NotifyMask,
1607 if( !NT_SUCCESS( ntStatus))
1610 if( Ccb->NotifyMask.Buffer != NULL)
1613 AFSExFreePool( Ccb->NotifyMask.Buffer);
1615 Ccb->NotifyMask.Buffer = NULL;
1624 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1626 IN ULONG NotifyFilter,
1627 IN ULONG NotificationAction)
1630 NTSTATUS ntStatus = STATUS_SUCCESS;
1631 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1632 UNICODE_STRING uniName, uniComponentName;
1634 USHORT usNameOffset = 0;
1639 uniName.Buffer = NULL;
1641 if( ParentObjectInfo == NULL ||
1642 AFSGlobalRoot == NULL)
1645 try_return( ntStatus);
1651 RtlInitUnicodeString( &uniComponentName,
1657 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1661 // Build a dir name based on the FID of the file
1665 uniName.MaximumLength = 1024 + uniComponentName.Length;
1667 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1668 uniName.MaximumLength,
1669 AFS_GENERIC_MEMORY_8_TAG);
1671 if( uniName.Buffer == NULL)
1674 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1677 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1678 uniName.MaximumLength,
1679 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1680 ParentObjectInfo->FileId.Cell,
1681 ParentObjectInfo->FileId.Volume,
1682 ParentObjectInfo->FileId.Vnode,
1683 ParentObjectInfo->FileId.Unique,
1686 if( !NT_SUCCESS( ntStatus))
1689 try_return( ntStatus);
1692 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1693 (size_t)uniName.MaximumLength,
1696 if( !NT_SUCCESS( ntStatus))
1699 try_return( ntStatus);
1702 uniName.Length = (USHORT)sztLength;
1704 usNameOffset = uniName.Length - uniComponentName.Length;
1706 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1707 AFS_TRACE_LEVEL_VERBOSE,
1708 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1714 uniComponentName.Length);
1716 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1717 &pDeviceExt->Specific.Control.DirNotifyList,
1729 if( uniName.Buffer != NULL)
1732 AFSExFreePool( uniName.Buffer);
1739 // For use with FsRtlNotifyFilterChangeDirectory but must
1740 // be implemented in the Framework because the library can
1744 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1745 IN void *FilterContext)
1748 BOOLEAN bReturn = TRUE;
1749 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1750 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1761 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1765 BOOLEAN bIsInSnapshot = FALSE;
1766 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1769 while( ulCount < SnapshotHdr->EntryCount)
1772 if( pSnapshotEntry->NameHash == HashIndex)
1775 bIsInSnapshot = TRUE;
1777 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1778 AFS_TRACE_LEVEL_VERBOSE,
1779 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1784 else if( pSnapshotEntry->NameHash == 0)
1795 return bIsInSnapshot;