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 ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN;
145 AFSFileInfoCB stFileInfo;
146 BOOLEAN bUseFileInfo = TRUE;
147 AFSObjectInfoCB *pObjectInfo = NULL;
148 ULONG ulAdditionalAttributes = 0;
153 // Get the current Stack location
154 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
156 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
157 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
162 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
163 AFS_TRACE_LEVEL_ERROR,
164 "AFSQueryDirectory Attempted access (%08lX) when pFcb == NULL\n",
167 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
170 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
171 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
172 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
175 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
176 AFS_TRACE_LEVEL_ERROR,
177 "AFSQueryDirectory Attempted access (%08lX) to non-directory Fcb %08lX NodeType %u\n",
180 pFcb->Header.NodeTypeCode);
184 try_return( ntStatus = STATUS_INVALID_PARAMETER);
188 // Set the enumeration event ...
191 AFSSetEnumerationEvent( pFcb);
193 // Reference our input parameters to make things easier
194 ulUserBufferLength = pIrpSp->Parameters.QueryDirectory.Length;
196 FileInformationClass = pIrpSp->Parameters.QueryDirectory.FileInformationClass;
197 ulFileIndex = pIrpSp->Parameters.QueryDirectory.FileIndex;
199 puniArgFileName = (PUNICODE_STRING)pIrpSp->Parameters.QueryDirectory.FileName;
201 bRestartScan = BooleanFlagOn( pIrpSp->Flags, SL_RESTART_SCAN);
202 bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
203 bIndexSpecified = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
205 bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED));
210 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
211 AFS_TRACE_LEVEL_VERBOSE,
212 "AFSQueryDirectory Enumerating content for parent %wZ Initial Query\n",
213 &pCcb->DirectoryCB->NameInformation.FileName);
215 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
216 AFS_TRACE_LEVEL_VERBOSE,
217 "AFSQueryDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
218 &pFcb->NPFcb->Resource,
219 PsGetCurrentThread());
221 AFSAcquireExcl( &pFcb->NPFcb->Resource,
225 // Tell the service to prime the cache of the directory content
228 ntStatus = AFSEnumerateDirectoryNoResponse( &pFcb->AuthGroup,
229 &pFcb->ObjectInformation->FileId);
231 if( !NT_SUCCESS( ntStatus))
234 AFSReleaseResource( &pFcb->NPFcb->Resource);
236 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
237 AFS_TRACE_LEVEL_ERROR,
238 "AFSQueryDirectory Enumerate directory failure for parent %wZ Mask %wZ Status %08lX\n",
239 &pCcb->DirectoryCB->NameInformation.FileName,
243 try_return( ntStatus);
249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
250 AFS_TRACE_LEVEL_VERBOSE,
251 "AFSQueryDirectory Enumerating content for parent %wZ Subsequent\n",
252 &pCcb->DirectoryCB->NameInformation.FileName);
254 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
255 AFS_TRACE_LEVEL_VERBOSE,
256 "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
257 &pFcb->NPFcb->Resource,
258 PsGetCurrentThread());
260 AFSAcquireShared( &pFcb->NPFcb->Resource,
265 // Grab the directory node hdr tree lock while parsing the directory
269 AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
275 // Before attempting to insert the new entry, check if we need to validate the parent
278 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
281 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
282 AFS_TRACE_LEVEL_VERBOSE,
283 "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
284 &pCcb->DirectoryCB->NameInformation.FileName,
285 pFcb->ObjectInformation->FileId.Cell,
286 pFcb->ObjectInformation->FileId.Volume,
287 pFcb->ObjectInformation->FileId.Vnode,
288 pFcb->ObjectInformation->FileId.Unique);
290 ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
293 if( !NT_SUCCESS( ntStatus))
296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
297 AFS_TRACE_LEVEL_ERROR,
298 "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
299 &pCcb->DirectoryCB->NameInformation.FileName,
300 pFcb->ObjectInformation->FileId.Cell,
301 pFcb->ObjectInformation->FileId.Volume,
302 pFcb->ObjectInformation->FileId.Vnode,
303 pFcb->ObjectInformation->FileId.Unique,
306 try_return( ntStatus);
310 // Perform a new snapshot of the directory
313 ntStatus = AFSSnapshotDirectory( pFcb,
317 if( !NT_SUCCESS( ntStatus))
320 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
321 AFS_TRACE_LEVEL_ERROR,
322 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
323 &pCcb->DirectoryCB->NameInformation.FileName,
327 try_return( ntStatus);
331 AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
334 // We can now safely drop the lock on the node
337 AFSReleaseResource( &pFcb->NPFcb->Resource);
340 // Start processing the data
343 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
349 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
352 // Check if initial on this map
356 ntStatus = AFSSnapshotDirectory( pFcb,
360 if( !NT_SUCCESS( ntStatus))
363 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
364 AFS_TRACE_LEVEL_ERROR,
365 "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
366 &pCcb->DirectoryCB->NameInformation.FileName,
370 try_return( ntStatus);
373 SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
375 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
377 // build mask if none
378 if( puniArgFileName == NULL)
380 puniArgFileName = &uniTmpMaskName;
381 puniArgFileName->Length = 0;
382 puniArgFileName->Buffer = NULL;
385 if( puniArgFileName->Length == 0)
388 puniArgFileName->Length = sizeof(WCHAR);
389 puniArgFileName->MaximumLength = (USHORT)4;
392 if( puniArgFileName->Buffer == NULL)
395 puniArgFileName->Buffer = wchMaskBuffer;
397 RtlZeroMemory( wchMaskBuffer,
400 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
405 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
406 ( puniArgFileName->Buffer[0] == L'*')))
409 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
414 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
415 ( puniArgFileName->Buffer[0] == L'<')) ||
416 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
417 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
420 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
424 // Build the name for procesisng
427 pCcb->MaskName.Length = puniArgFileName->Length;
428 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
430 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
431 pCcb->MaskName.Length,
432 AFS_GENERIC_MEMORY_6_TAG);
434 if( pCcb->MaskName.Buffer == NULL)
437 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
440 if( FsRtlDoesNameContainWildCards( puniArgFileName))
443 RtlUpcaseUnicodeString( &pCcb->MaskName,
447 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
449 if( FsRtlIsNameInExpression( &pCcb->MaskName,
454 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
460 RtlCopyMemory( pCcb->MaskName.Buffer,
461 puniArgFileName->Buffer,
462 pCcb->MaskName.Length);
464 if( RtlCompareUnicodeString( &AFSPIOCtlName,
468 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
472 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
474 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
477 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
479 bReleaseMain = FALSE;
481 AFSAcquireExcl( &pFcb->NPFcb->Resource,
484 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
487 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
489 if( !NT_SUCCESS( ntStatus))
492 AFSReleaseResource( &pFcb->NPFcb->Resource);
494 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
495 AFS_TRACE_LEVEL_ERROR,
496 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
497 &pCcb->DirectoryCB->NameInformation.FileName,
501 try_return( ntStatus);
505 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
510 AFSReleaseResource( &pFcb->NPFcb->Resource);
514 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
515 AFS_TRACE_LEVEL_VERBOSE,
516 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
517 &pCcb->DirectoryCB->NameInformation.FileName,
522 // Check if we need to start from index
527 // Need to set up the initial point for the query
530 pCcb->CurrentDirIndex = ulFileIndex - 1;
533 // Check if we need to restart the scan
534 else if( bRestartScan)
538 // Reset the current scan processing
541 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
544 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
549 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
553 switch( FileInformationClass)
556 case FileDirectoryInformation:
558 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
562 case FileFullDirectoryInformation:
564 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
568 case FileNamesInformation:
570 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
574 case FileBothDirectoryInformation:
576 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
580 case FileIdBothDirectoryInformation:
582 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
587 case FileIdFullDirectoryInformation:
589 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
596 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
597 AFS_TRACE_LEVEL_ERROR,
598 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
600 FileInformationClass);
602 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
605 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
607 bReleaseMain = FALSE;
612 ULONG ulBytesRemainingInBuffer;
616 // If the user had requested only a single match and we have
617 // returned that, then we stop at this point.
620 if( bReturnSingleEntry && ulNextEntry != 0)
623 try_return( ntStatus);
626 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
629 if( pDirEntry == NULL)
632 if( ulNextEntry == 0)
635 if( ( bInitialQuery ||
637 pCcb->MaskName.Buffer != NULL)
639 ntStatus = STATUS_NO_SUCH_FILE;
643 ntStatus = STATUS_NO_MORE_FILES;
647 try_return( ntStatus);
651 // Skip the entry if it is pending delete or deleted
654 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
655 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
658 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
663 pObjectInfo = pDirEntry->ObjectInformation;
666 // Apply the name filter if there is one
669 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
673 // Only returning directories?
676 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
679 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
682 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
687 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
691 // Are we doing a wild card search?
694 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
697 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
698 &pDirEntry->NameInformation.FileName,
703 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
711 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
717 // See if this is a match for a case insensitive search
720 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
725 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
735 // Be sure the information is valid
736 // We don't worry about entries while enumerating the directory
739 AFSValidateEntry( pDirEntry,
744 pObjectInfo = pDirEntry->ObjectInformation;
746 bUseFileInfo = FALSE;
748 ulAdditionalAttributes = 0;
750 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
754 // Go grab the file information for this entry
755 // No worries on failures since we will just display
756 // pseudo information
759 RtlZeroMemory( &stFileInfo,
760 sizeof( AFSFileInfoCB));
762 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
769 ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
775 // Here are the rules concerning filling up the buffer:
777 // 1. The Io system guarantees that there will always be
778 // enough room for at least one base record.
780 // 2. If the full first record (including file name) cannot
781 // fit, as much of the name as possible is copied and
782 // STATUS_BUFFER_OVERFLOW is returned.
784 // 3. If a subsequent record cannot completely fit into the
785 // buffer, none of it (as in 0 bytes) is copied, and
786 // STATUS_SUCCESS is returned. A subsequent query will
787 // pick up with this record.
789 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
791 if( ( ulNextEntry != 0) &&
792 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
793 ( ulUserBufferLength < ulNextEntry) ) )
797 // Back off our current index
800 pCcb->CurrentDirIndex--;
802 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
804 try_return( ntStatus = STATUS_SUCCESS);
807 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
808 AFS_TRACE_LEVEL_VERBOSE,
809 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
810 &pCcb->DirectoryCB->NameInformation.FileName,
811 &pDirEntry->NameInformation.FileName);
813 // Zero the base part of the structure.
814 RtlZeroMemory( &pBuffer[ ulNextEntry],
817 switch( FileInformationClass)
820 // Now fill the base parts of the structure that are applicable.
821 case FileIdBothDirectoryInformation:
822 case FileBothDirectoryInformation:
824 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
826 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
828 if( pDirEntry->NameInformation.ShortNameLength > 0)
830 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
831 &pDirEntry->NameInformation.ShortName[ 0],
832 pBothDirInfo->ShortNameLength);
835 case FileIdFullDirectoryInformation:
836 case FileFullDirectoryInformation:
838 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
839 pFullDirInfo->EaSize = 0;
841 case FileDirectoryInformation:
843 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
848 pDirInfo->CreationTime = stFileInfo.CreationTime;
849 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
850 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
851 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
853 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
854 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
856 pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
858 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
861 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
862 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
863 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
864 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
866 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
867 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
869 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
871 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
875 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
881 pDirInfo->CreationTime = pObjectInfo->CreationTime;
882 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
883 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
884 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
886 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
887 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
889 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
893 // Check if the name begins with a . and we are hiding them
896 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
897 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
898 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
901 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
904 pDirInfo->FileIndex = pDirEntry->FileIndex;
905 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
910 case FileNamesInformation:
912 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
913 pNamesInfo->FileIndex = pDirEntry->FileIndex;
914 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
920 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
921 AFS_TRACE_LEVEL_ERROR,
922 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
924 FileInformationClass);
926 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
928 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
934 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
935 pDirEntry->NameInformation.FileName.Length :
936 ulBytesRemainingInBuffer - ulBaseLength;
938 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
939 pDirEntry->NameInformation.FileName.Buffer,
942 // Set up the previous next entry offset
943 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
945 // And indicate how much of the user buffer we have currently
947 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
949 // Check for the case that a single entry doesn't fit.
950 // This should only get this far on the first entry.
951 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
954 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
956 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
959 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
961 dStatus = STATUS_SUCCESS;
963 // Set ourselves up for the next iteration
964 ulLastEntry = ulNextEntry;
965 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
973 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
979 AFSClearEnumerationEvent( pFcb);
987 AFSNotifyChangeDirectory( IN PIRP Irp)
990 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
991 PIO_STACK_LOCATION pIrpSp;
994 ULONG ulCompletionFilter;
996 BOOLEAN bReleaseLock = FALSE;
1001 // Get the current Stack location
1002 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
1004 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1005 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1010 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1011 AFS_TRACE_LEVEL_ERROR,
1012 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1015 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1018 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1019 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1020 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1023 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1024 AFS_TRACE_LEVEL_ERROR,
1025 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1026 &pCcb->DirectoryCB->NameInformation.FileName,
1027 pFcb->Header.NodeTypeCode);
1029 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1032 // Reference our input parameter to make things easier
1033 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1034 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1036 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1037 AFS_TRACE_LEVEL_VERBOSE,
1038 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1039 &pFcb->NPFcb->Resource,
1040 PsGetCurrentThread());
1042 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1045 bReleaseLock = TRUE;
1048 // Check if the node has already been deleted
1051 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1054 try_return( ntStatus = STATUS_FILE_DELETED);
1056 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1059 try_return( ntStatus = STATUS_DELETE_PENDING);
1062 // Call the Fsrtl package to process the request.
1063 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1069 if( !NT_SUCCESS( ntStatus))
1071 try_return( ntStatus);
1074 ntStatus = STATUS_PENDING;
1081 AFSReleaseResource( &pFcb->NPFcb->Resource);
1089 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1093 AFSDirectoryCB *pDirEntry = NULL;
1094 NTSTATUS ntStatus = STATUS_SUCCESS;
1095 AFSSnapshotHdr *pSnapshotHdr = NULL;
1096 AFSSnapshotEntry *pSnapshotEntry = NULL;
1103 // Is this a PIOCtl query
1106 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1109 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1110 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1113 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
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 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1142 AFS_TRACE_LEVEL_VERBOSE,
1143 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1144 &pDirEntry->NameInformation.FileName,
1145 ObjectInfo->FileId.Cell,
1146 ObjectInfo->FileId.Volume,
1147 ObjectInfo->FileId.Vnode,
1148 ObjectInfo->FileId.Unique);
1150 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1154 // Return the .. entry
1157 pDirEntry = AFSGlobalDotDotDirEntry;
1159 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1160 AFS_TRACE_LEVEL_VERBOSE,
1161 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1162 &pDirEntry->NameInformation.FileName,
1163 ObjectInfo->FileId.Cell,
1164 ObjectInfo->FileId.Volume,
1165 ObjectInfo->FileId.Vnode,
1166 ObjectInfo->FileId.Unique);
1171 pSnapshotHdr = Ccb->DirectorySnapshot;
1173 if( pSnapshotHdr == NULL ||
1174 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1177 try_return( ntStatus);
1180 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1182 ulCount = Ccb->CurrentDirIndex;
1184 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1185 AFS_TRACE_LEVEL_VERBOSE,
1186 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1190 // Get to a valid entry
1193 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1196 while( ulCount < pSnapshotHdr->EntryCount)
1201 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1202 AFS_TRACE_LEVEL_VERBOSE,
1203 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1204 pSnapshotEntry->NameHash);
1206 if( pSnapshotEntry->NameHash == 0)
1212 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1213 pSnapshotEntry->NameHash,
1216 if( !NT_SUCCESS( ntStatus) ||
1220 if( pDirEntry != NULL)
1223 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1224 AFS_TRACE_LEVEL_VERBOSE,
1225 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1226 &pDirEntry->NameInformation.FileName,
1227 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1228 ObjectInfo->FileId.Cell,
1229 ObjectInfo->FileId.Volume,
1230 ObjectInfo->FileId.Vnode,
1231 ObjectInfo->FileId.Unique);
1233 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1239 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1240 AFS_TRACE_LEVEL_VERBOSE,
1241 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1242 ObjectInfo->FileId.Cell,
1243 ObjectInfo->FileId.Volume,
1244 ObjectInfo->FileId.Vnode,
1245 ObjectInfo->FileId.Unique);
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252 AFS_TRACE_LEVEL_VERBOSE,
1253 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1254 pSnapshotEntry->NameHash,
1255 ObjectInfo->FileId.Cell,
1256 ObjectInfo->FileId.Volume,
1257 ObjectInfo->FileId.Vnode,
1258 ObjectInfo->FileId.Unique);
1264 Ccb->CurrentDirIndex++;
1267 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1279 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1284 AFSDirectoryCB *pDirEntry = NULL;
1285 NTSTATUS ntStatus = STATUS_SUCCESS;
1286 AFSSnapshotHdr *pSnapshotHdr = NULL;
1287 AFSSnapshotEntry *pSnapshotEntry = NULL;
1293 Ccb->CurrentDirIndex = DirIndex;
1295 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1299 // Return the .. entry
1302 pDirEntry = AFSGlobalDotDirEntry;
1304 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1308 // Return the .. entry
1311 pDirEntry = AFSGlobalDotDotDirEntry;
1316 pSnapshotHdr = Ccb->DirectorySnapshot;
1318 if( pSnapshotHdr == NULL ||
1319 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1322 try_return( ntStatus);
1325 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1327 ulCount = Ccb->CurrentDirIndex;
1330 // Get to a valid entry
1333 while( ulCount < pSnapshotHdr->EntryCount)
1338 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1339 pSnapshotEntry->NameHash,
1342 if( !NT_SUCCESS( ntStatus) ||
1343 ( pDirEntry != NULL &&
1344 pDirEntry->FileIndex == DirIndex))
1355 if( pDirEntry != NULL)
1358 Ccb->CurrentDirIndex = ulCount;
1371 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1373 IN BOOLEAN ResetIndex)
1376 NTSTATUS ntStatus = STATUS_SUCCESS;
1377 AFSSnapshotHdr *pSnapshotHdr = NULL;
1378 AFSSnapshotEntry *pSnapshotEntry = NULL;
1379 AFSDirectoryCB *pDirEntry = NULL;
1388 // Set it up so we still get the . and .. entries for empty directories
1391 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1394 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1399 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1403 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1407 // If we have a snapshot then clear it out
1410 if( Ccb->DirectorySnapshot != NULL)
1413 AFSExFreePool( Ccb->DirectorySnapshot);
1415 Ccb->DirectorySnapshot = NULL;
1418 try_return( ntStatus);
1422 // Allocate our snapshot buffer for this enumeration
1425 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1426 sizeof( AFSSnapshotHdr) +
1427 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1428 sizeof( AFSSnapshotEntry)),
1429 AFS_DIR_SNAPSHOT_TAG);
1431 if( pSnapshotHdr == NULL)
1434 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1437 RtlZeroMemory( pSnapshotHdr,
1438 sizeof( AFSSnapshotHdr) +
1439 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1440 sizeof( AFSSnapshotEntry)));
1442 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1444 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1447 // Populate our snapshot
1450 pSnapshotEntry = pSnapshotHdr->TopEntry;
1452 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1454 while( pDirEntry != NULL)
1457 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1458 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1459 !AFSIsNameInSnapshot( pSnapshotHdr,
1460 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1463 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1464 AFS_TRACE_LEVEL_VERBOSE,
1465 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1466 pSnapshotHdr->EntryCount,
1467 &pDirEntry->NameInformation.FileName,
1468 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1470 Fcb->ObjectInformation->FileId.Cell,
1471 Fcb->ObjectInformation->FileId.Volume,
1472 Fcb->ObjectInformation->FileId.Vnode,
1473 Fcb->ObjectInformation->FileId.Unique);
1475 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1482 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1483 AFS_TRACE_LEVEL_VERBOSE,
1484 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1485 pSnapshotHdr->EntryCount,
1486 &pDirEntry->NameInformation.FileName,
1487 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1489 Fcb->ObjectInformation->FileId.Cell,
1490 Fcb->ObjectInformation->FileId.Volume,
1491 Fcb->ObjectInformation->FileId.Vnode,
1492 Fcb->ObjectInformation->FileId.Unique);
1495 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1498 if( Ccb->DirectorySnapshot != NULL)
1501 AFSExFreePool( Ccb->DirectorySnapshot);
1503 Ccb->DirectorySnapshot = NULL;
1506 Ccb->DirectorySnapshot = pSnapshotHdr;
1517 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1519 IN BOOLEAN WatchTree,
1520 IN ULONG CompletionFilter,
1524 NTSTATUS ntStatus = STATUS_SUCCESS;
1525 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1532 // Build a dir name based on the FID of the file
1535 if( Ccb->NotifyMask.Buffer == NULL)
1538 Ccb->NotifyMask.Length = 0;
1539 Ccb->NotifyMask.MaximumLength = 1024;
1541 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1542 Ccb->NotifyMask.MaximumLength,
1543 AFS_GENERIC_MEMORY_7_TAG);
1545 if( Ccb->NotifyMask.Buffer == NULL)
1548 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1551 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1552 Ccb->NotifyMask.MaximumLength,
1553 L"\\%08lX.%08lX.%08lX.%08lX",
1554 ObjectInfo->FileId.Cell,
1555 ObjectInfo->FileId.Volume,
1556 ObjectInfo->FileId.Vnode,
1557 ObjectInfo->FileId.Unique);
1559 if( !NT_SUCCESS( ntStatus))
1562 try_return( ntStatus);
1565 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1566 (size_t)Ccb->NotifyMask.MaximumLength,
1569 if( !NT_SUCCESS( ntStatus))
1572 try_return( ntStatus);
1575 Ccb->NotifyMask.Length = (USHORT)sztLength;
1578 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1579 AFS_TRACE_LEVEL_VERBOSE,
1580 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1586 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1587 &pDeviceExt->Specific.Control.DirNotifyList,
1589 (PSTRING)&Ccb->NotifyMask,
1600 if( !NT_SUCCESS( ntStatus))
1603 if( Ccb->NotifyMask.Buffer != NULL)
1606 AFSExFreePool( Ccb->NotifyMask.Buffer);
1608 Ccb->NotifyMask.Buffer = NULL;
1617 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1619 IN ULONG NotifyFilter,
1620 IN ULONG NotificationAction)
1623 NTSTATUS ntStatus = STATUS_SUCCESS;
1624 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1625 UNICODE_STRING uniName, uniComponentName;
1627 USHORT usNameOffset = 0;
1632 uniName.Buffer = NULL;
1634 if( ParentObjectInfo == NULL ||
1635 AFSGlobalRoot == NULL)
1638 try_return( ntStatus);
1644 RtlInitUnicodeString( &uniComponentName,
1650 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1654 // Build a dir name based on the FID of the file
1658 uniName.MaximumLength = 1024 + uniComponentName.Length;
1660 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1661 uniName.MaximumLength,
1662 AFS_GENERIC_MEMORY_8_TAG);
1664 if( uniName.Buffer == NULL)
1667 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1670 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1671 uniName.MaximumLength,
1672 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1673 ParentObjectInfo->FileId.Cell,
1674 ParentObjectInfo->FileId.Volume,
1675 ParentObjectInfo->FileId.Vnode,
1676 ParentObjectInfo->FileId.Unique,
1679 if( !NT_SUCCESS( ntStatus))
1682 try_return( ntStatus);
1685 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1686 (size_t)uniName.MaximumLength,
1689 if( !NT_SUCCESS( ntStatus))
1692 try_return( ntStatus);
1695 uniName.Length = (USHORT)sztLength;
1697 usNameOffset = uniName.Length - uniComponentName.Length;
1699 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1700 AFS_TRACE_LEVEL_VERBOSE,
1701 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1707 uniComponentName.Length);
1709 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1710 &pDeviceExt->Specific.Control.DirNotifyList,
1722 if( uniName.Buffer != NULL)
1725 AFSExFreePool( uniName.Buffer);
1732 // For use with FsRtlNotifyFilterChangeDirectory but must
1733 // be implemented in the Framework because the library can
1737 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1738 IN void *FilterContext)
1741 BOOLEAN bReturn = TRUE;
1742 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1743 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1754 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1758 BOOLEAN bIsInSnapshot = FALSE;
1759 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1762 while( ulCount < SnapshotHdr->EntryCount)
1765 if( pSnapshotEntry->NameHash == HashIndex)
1768 bIsInSnapshot = TRUE;
1770 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1771 AFS_TRACE_LEVEL_VERBOSE,
1772 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1777 else if( pSnapshotEntry->NameHash == 0)
1788 return bIsInSnapshot;