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 shared while parsing the directory
269 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
275 // We can now safely drop the lock on the node
278 AFSReleaseResource( &pFcb->NPFcb->Resource);
281 // Start processing the data
284 pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
290 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
293 // Check if initial on this map
297 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);
313 SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
315 ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
317 // build mask if none
318 if( puniArgFileName == NULL)
320 puniArgFileName = &uniTmpMaskName;
321 puniArgFileName->Length = 0;
322 puniArgFileName->Buffer = NULL;
325 if( puniArgFileName->Length == 0)
328 puniArgFileName->Length = sizeof(WCHAR);
329 puniArgFileName->MaximumLength = (USHORT)4;
332 if( puniArgFileName->Buffer == NULL)
335 puniArgFileName->Buffer = wchMaskBuffer;
337 RtlZeroMemory( wchMaskBuffer,
340 RtlCopyMemory( &puniArgFileName->Buffer[ 0],
345 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
346 ( puniArgFileName->Buffer[0] == L'*')))
349 SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
354 if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
355 ( puniArgFileName->Buffer[0] == L'<')) ||
356 (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
357 ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
360 SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
364 // Build the name for procesisng
367 pCcb->MaskName.Length = puniArgFileName->Length;
368 pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
370 pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
371 pCcb->MaskName.Length,
372 AFS_GENERIC_MEMORY_6_TAG);
374 if( pCcb->MaskName.Buffer == NULL)
377 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
380 if( FsRtlDoesNameContainWildCards( puniArgFileName))
383 RtlUpcaseUnicodeString( &pCcb->MaskName,
387 SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
389 if( FsRtlIsNameInExpression( &pCcb->MaskName,
394 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
400 RtlCopyMemory( pCcb->MaskName.Buffer,
401 puniArgFileName->Buffer,
402 pCcb->MaskName.Length);
404 if( RtlCompareUnicodeString( &AFSPIOCtlName,
408 SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
412 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
414 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
417 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
419 bReleaseMain = FALSE;
421 AFSAcquireExcl( &pFcb->NPFcb->Resource,
424 if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
427 ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
429 if( !NT_SUCCESS( ntStatus))
432 AFSReleaseResource( &pFcb->NPFcb->Resource);
434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
435 AFS_TRACE_LEVEL_ERROR,
436 "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
437 &pCcb->DirectoryCB->NameInformation.FileName,
441 try_return( ntStatus);
445 AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
450 AFSReleaseResource( &pFcb->NPFcb->Resource);
454 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
455 AFS_TRACE_LEVEL_VERBOSE,
456 "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
457 &pCcb->DirectoryCB->NameInformation.FileName,
462 // Check if we need to start from index
467 // Need to set up the initial point for the query
470 pCcb->CurrentDirIndex = ulFileIndex - 1;
473 // Check if we need to restart the scan
474 else if( bRestartScan)
478 // Reset the current scan processing
481 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
484 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
489 pCcb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
493 switch( FileInformationClass)
496 case FileDirectoryInformation:
498 ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
502 case FileFullDirectoryInformation:
504 ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
508 case FileNamesInformation:
510 ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
514 case FileBothDirectoryInformation:
516 ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
520 case FileIdBothDirectoryInformation:
522 ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
527 case FileIdFullDirectoryInformation:
529 ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
536 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
537 AFS_TRACE_LEVEL_ERROR,
538 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
540 FileInformationClass);
542 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
545 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
547 bReleaseMain = FALSE;
552 ULONG ulBytesRemainingInBuffer;
556 // If the user had requested only a single match and we have
557 // returned that, then we stop at this point.
560 if( bReturnSingleEntry && ulNextEntry != 0)
563 try_return( ntStatus);
566 pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
569 if( pDirEntry == NULL)
572 if( ulNextEntry == 0)
575 if( ( bInitialQuery ||
577 pCcb->MaskName.Buffer != NULL)
579 ntStatus = STATUS_NO_SUCH_FILE;
583 ntStatus = STATUS_NO_MORE_FILES;
587 try_return( ntStatus);
591 // Skip the entry if it is pending delete or deleted
594 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) ||
595 BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
601 pObjectInfo = pDirEntry->ObjectInformation;
604 // Apply the name filter if there is one
607 if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY))
611 // Only returning directories?
614 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY))
617 if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
623 else if( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
627 // Are we doing a wild card search?
630 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS))
633 if( !FsRtlIsNameInExpression( &pCcb->MaskName,
634 &pDirEntry->NameInformation.FileName,
645 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
651 // See if this is a match for a case insensitive search
654 if( RtlCompareUnicodeString( &pDirEntry->NameInformation.FileName,
667 // Be sure the information is valid
668 // We don't worry about entries while enumerating the directory
671 AFSValidateEntry( pDirEntry,
676 pObjectInfo = pDirEntry->ObjectInformation;
678 bUseFileInfo = FALSE;
680 ulAdditionalAttributes = 0;
682 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
686 // Go grab the file information for this entry
687 // No worries on failures since we will just display
688 // pseudo information
691 RtlZeroMemory( &stFileInfo,
692 sizeof( AFSFileInfoCB));
694 if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
705 // Here are the rules concerning filling up the buffer:
707 // 1. The Io system guarantees that there will always be
708 // enough room for at least one base record.
710 // 2. If the full first record (including file name) cannot
711 // fit, as much of the name as possible is copied and
712 // STATUS_BUFFER_OVERFLOW is returned.
714 // 3. If a subsequent record cannot completely fit into the
715 // buffer, none of it (as in 0 bytes) is copied, and
716 // STATUS_SUCCESS is returned. A subsequent query will
717 // pick up with this record.
719 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
721 if( ( ulNextEntry != 0) &&
722 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
723 ( ulUserBufferLength < ulNextEntry) ) )
727 // Back off our current index
730 pCcb->CurrentDirIndex--;
732 try_return( ntStatus = STATUS_SUCCESS);
735 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
736 AFS_TRACE_LEVEL_VERBOSE,
737 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
738 &pCcb->DirectoryCB->NameInformation.FileName,
739 &pDirEntry->NameInformation.FileName);
741 // Zero the base part of the structure.
742 RtlZeroMemory( &pBuffer[ ulNextEntry],
745 switch( FileInformationClass)
748 // Now fill the base parts of the structure that are applicable.
749 case FileIdBothDirectoryInformation:
750 case FileBothDirectoryInformation:
752 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
754 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
756 if( pDirEntry->NameInformation.ShortNameLength > 0)
758 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
759 &pDirEntry->NameInformation.ShortName[ 0],
760 pBothDirInfo->ShortNameLength);
762 case FileIdFullDirectoryInformation:
763 case FileFullDirectoryInformation:
765 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
766 pFullDirInfo->EaSize = 0;
768 case FileDirectoryInformation:
770 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
775 pDirInfo->CreationTime = stFileInfo.CreationTime;
776 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
777 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
778 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
780 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
781 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
783 pDirInfo->FileAttributes = stFileInfo.FileAttributes;
785 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
788 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
789 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
790 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
791 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
793 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
794 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
796 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
798 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
802 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
808 pDirInfo->CreationTime = pObjectInfo->CreationTime;
809 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
810 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
811 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
813 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
814 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
816 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
820 // Check if the name begins with a . and we are hiding them
823 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
824 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
825 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
828 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
831 pDirInfo->FileIndex = pDirEntry->FileIndex;
832 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
836 case FileNamesInformation:
838 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
839 pNamesInfo->FileIndex = pDirEntry->FileIndex;
840 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
846 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
847 AFS_TRACE_LEVEL_ERROR,
848 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
850 FileInformationClass);
852 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
857 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
858 pDirEntry->NameInformation.FileName.Length :
859 ulBytesRemainingInBuffer - ulBaseLength;
861 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
862 pDirEntry->NameInformation.FileName.Buffer,
865 // Set up the previous next entry offset
866 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
868 // And indicate how much of the user buffer we have currently
870 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
872 // Check for the case that a single entry doesn't fit.
873 // This should only get this far on the first entry.
874 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
877 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
880 dStatus = STATUS_SUCCESS;
882 // Set ourselves up for the next iteration
883 ulLastEntry = ulNextEntry;
884 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
892 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
898 AFSClearEnumerationEvent( pFcb);
906 AFSNotifyChangeDirectory( IN PIRP Irp)
909 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
910 PIO_STACK_LOCATION pIrpSp;
913 ULONG ulCompletionFilter;
915 BOOLEAN bReleaseLock = FALSE;
920 // Get the current Stack location
921 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
923 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
924 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
929 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
930 AFS_TRACE_LEVEL_ERROR,
931 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
934 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
937 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
938 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
939 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
942 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
943 AFS_TRACE_LEVEL_ERROR,
944 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
945 &pCcb->DirectoryCB->NameInformation.FileName,
946 pFcb->Header.NodeTypeCode);
948 try_return( ntStatus = STATUS_INVALID_PARAMETER);
951 // Reference our input parameter to make things easier
952 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
953 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
955 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
956 AFS_TRACE_LEVEL_VERBOSE,
957 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
958 &pFcb->NPFcb->Resource,
959 PsGetCurrentThread());
961 AFSAcquireExcl( &pFcb->NPFcb->Resource,
967 // Check if the node has already been deleted
970 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
973 try_return( ntStatus = STATUS_FILE_DELETED);
975 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
978 try_return( ntStatus = STATUS_DELETE_PENDING);
981 // Call the Fsrtl package to process the request.
982 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
988 if( !NT_SUCCESS( ntStatus))
990 try_return( ntStatus);
993 ntStatus = STATUS_PENDING;
1000 AFSReleaseResource( &pFcb->NPFcb->Resource);
1008 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1012 AFSDirectoryCB *pDirEntry = NULL;
1013 NTSTATUS ntStatus = STATUS_SUCCESS;
1014 AFSSnapshotHdr *pSnapshotHdr = NULL;
1015 AFSSnapshotEntry *pSnapshotEntry = NULL;
1022 // Is this a PIOCtl query
1025 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1028 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1029 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1032 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1035 AFS_TRACE_LEVEL_VERBOSE,
1036 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1037 &pDirEntry->NameInformation.FileName,
1038 ObjectInfo->FileId.Cell,
1039 ObjectInfo->FileId.Volume,
1040 ObjectInfo->FileId.Vnode,
1041 ObjectInfo->FileId.Unique);
1044 Ccb->CurrentDirIndex++;
1046 try_return( ntStatus);
1049 Ccb->CurrentDirIndex++;
1051 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1055 // Return the .. entry
1058 pDirEntry = AFSGlobalDotDirEntry;
1060 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1061 AFS_TRACE_LEVEL_VERBOSE,
1062 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1063 &pDirEntry->NameInformation.FileName,
1064 ObjectInfo->FileId.Cell,
1065 ObjectInfo->FileId.Volume,
1066 ObjectInfo->FileId.Vnode,
1067 ObjectInfo->FileId.Unique);
1069 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1073 // Return the .. entry
1076 pDirEntry = AFSGlobalDotDotDirEntry;
1078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1079 AFS_TRACE_LEVEL_VERBOSE,
1080 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1081 &pDirEntry->NameInformation.FileName,
1082 ObjectInfo->FileId.Cell,
1083 ObjectInfo->FileId.Volume,
1084 ObjectInfo->FileId.Vnode,
1085 ObjectInfo->FileId.Unique);
1090 pSnapshotHdr = Ccb->DirectorySnapshot;
1092 if( pSnapshotHdr == NULL ||
1093 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1096 try_return( ntStatus);
1099 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1101 ulCount = Ccb->CurrentDirIndex;
1103 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1104 AFS_TRACE_LEVEL_VERBOSE,
1105 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1109 // Get to a valid entry
1112 while( ulCount < pSnapshotHdr->EntryCount)
1117 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1118 AFS_TRACE_LEVEL_VERBOSE,
1119 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1120 pSnapshotEntry->NameHash);
1122 if( pSnapshotEntry->NameHash == 0)
1128 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1129 pSnapshotEntry->NameHash,
1132 if( !NT_SUCCESS( ntStatus) ||
1136 if( pDirEntry != NULL)
1139 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1140 AFS_TRACE_LEVEL_VERBOSE,
1141 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1142 &pDirEntry->NameInformation.FileName,
1143 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1144 ObjectInfo->FileId.Cell,
1145 ObjectInfo->FileId.Volume,
1146 ObjectInfo->FileId.Vnode,
1147 ObjectInfo->FileId.Unique);
1153 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1154 AFS_TRACE_LEVEL_VERBOSE,
1155 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1156 ObjectInfo->FileId.Cell,
1157 ObjectInfo->FileId.Volume,
1158 ObjectInfo->FileId.Vnode,
1159 ObjectInfo->FileId.Unique);
1165 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1166 AFS_TRACE_LEVEL_VERBOSE,
1167 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1168 pSnapshotEntry->NameHash,
1169 ObjectInfo->FileId.Cell,
1170 ObjectInfo->FileId.Volume,
1171 ObjectInfo->FileId.Vnode,
1172 ObjectInfo->FileId.Unique);
1178 Ccb->CurrentDirIndex++;
1191 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1196 AFSDirectoryCB *pDirEntry = NULL;
1197 NTSTATUS ntStatus = STATUS_SUCCESS;
1198 AFSSnapshotHdr *pSnapshotHdr = NULL;
1199 AFSSnapshotEntry *pSnapshotEntry = NULL;
1205 Ccb->CurrentDirIndex = DirIndex;
1207 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1211 // Return the .. entry
1214 pDirEntry = AFSGlobalDotDirEntry;
1216 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1220 // Return the .. entry
1223 pDirEntry = AFSGlobalDotDotDirEntry;
1228 pSnapshotHdr = Ccb->DirectorySnapshot;
1230 if( pSnapshotHdr == NULL ||
1231 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1234 try_return( ntStatus);
1237 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1239 ulCount = Ccb->CurrentDirIndex;
1242 // Get to a valid entry
1245 while( ulCount < pSnapshotHdr->EntryCount)
1250 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1251 pSnapshotEntry->NameHash,
1254 if( !NT_SUCCESS( ntStatus) ||
1255 ( pDirEntry != NULL &&
1256 pDirEntry->FileIndex == DirIndex))
1267 if( pDirEntry != NULL)
1270 Ccb->CurrentDirIndex = ulCount;
1283 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1287 NTSTATUS ntStatus = STATUS_SUCCESS;
1288 AFSSnapshotHdr *pSnapshotHdr = NULL;
1289 AFSSnapshotEntry *pSnapshotEntry = NULL;
1290 AFSDirectoryCB *pDirEntry = NULL;
1296 // Set it up so we still get the . and .. entries for empty directories
1299 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1302 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1307 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1310 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1314 // If we have a snapshot then clear it out
1317 if( Ccb->DirectorySnapshot != NULL)
1320 AFSExFreePool( Ccb->DirectorySnapshot);
1322 Ccb->DirectorySnapshot = NULL;
1325 try_return( ntStatus);
1329 // Allocate our snapshot buffer for this enumeration
1332 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1333 sizeof( AFSSnapshotHdr) +
1334 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1335 sizeof( AFSSnapshotEntry)),
1336 AFS_DIR_SNAPSHOT_TAG);
1338 if( pSnapshotHdr == NULL)
1341 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1344 RtlZeroMemory( pSnapshotHdr,
1345 sizeof( AFSSnapshotHdr) +
1346 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1347 sizeof( AFSSnapshotEntry)));
1349 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1351 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1354 // Populate our snapshot
1357 pSnapshotEntry = pSnapshotHdr->TopEntry;
1359 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1361 while( pDirEntry != NULL)
1364 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1365 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1366 !AFSIsNameInSnapshot( pSnapshotHdr,
1367 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1370 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1371 AFS_TRACE_LEVEL_VERBOSE,
1372 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1373 pSnapshotHdr->EntryCount,
1374 &pDirEntry->NameInformation.FileName,
1375 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1377 Fcb->ObjectInformation->FileId.Cell,
1378 Fcb->ObjectInformation->FileId.Volume,
1379 Fcb->ObjectInformation->FileId.Vnode,
1380 Fcb->ObjectInformation->FileId.Unique);
1382 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1389 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1390 AFS_TRACE_LEVEL_VERBOSE,
1391 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1392 pSnapshotHdr->EntryCount,
1393 &pDirEntry->NameInformation.FileName,
1394 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1396 Fcb->ObjectInformation->FileId.Cell,
1397 Fcb->ObjectInformation->FileId.Volume,
1398 Fcb->ObjectInformation->FileId.Vnode,
1399 Fcb->ObjectInformation->FileId.Unique);
1402 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1405 if( Ccb->DirectorySnapshot != NULL)
1408 AFSExFreePool( Ccb->DirectorySnapshot);
1410 Ccb->DirectorySnapshot = NULL;
1413 Ccb->DirectorySnapshot = pSnapshotHdr;
1424 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1426 IN BOOLEAN WatchTree,
1427 IN ULONG CompletionFilter,
1431 NTSTATUS ntStatus = STATUS_SUCCESS;
1432 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1439 // Build a dir name based on the FID of the file
1442 if( Ccb->NotifyMask.Buffer == NULL)
1445 Ccb->NotifyMask.Length = 0;
1446 Ccb->NotifyMask.MaximumLength = 1024;
1448 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1449 Ccb->NotifyMask.MaximumLength,
1450 AFS_GENERIC_MEMORY_7_TAG);
1452 if( Ccb->NotifyMask.Buffer == NULL)
1455 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1458 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1459 Ccb->NotifyMask.MaximumLength,
1460 L"\\%08lX.%08lX.%08lX.%08lX",
1461 ObjectInfo->FileId.Cell,
1462 ObjectInfo->FileId.Volume,
1463 ObjectInfo->FileId.Vnode,
1464 ObjectInfo->FileId.Unique);
1466 if( !NT_SUCCESS( ntStatus))
1469 try_return( ntStatus);
1472 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1473 (size_t)Ccb->NotifyMask.MaximumLength,
1476 if( !NT_SUCCESS( ntStatus))
1479 try_return( ntStatus);
1482 Ccb->NotifyMask.Length = (USHORT)sztLength;
1485 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1486 AFS_TRACE_LEVEL_VERBOSE,
1487 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1493 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1494 &pDeviceExt->Specific.Control.DirNotifyList,
1496 (PSTRING)&Ccb->NotifyMask,
1507 if( !NT_SUCCESS( ntStatus))
1510 if( Ccb->NotifyMask.Buffer != NULL)
1513 AFSExFreePool( Ccb->NotifyMask.Buffer);
1515 Ccb->NotifyMask.Buffer = NULL;
1524 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1526 IN ULONG NotifyFilter,
1527 IN ULONG NotificationAction)
1530 NTSTATUS ntStatus = STATUS_SUCCESS;
1531 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1532 UNICODE_STRING uniName, uniComponentName;
1534 USHORT usNameOffset = 0;
1539 uniName.Buffer = NULL;
1541 if( ParentObjectInfo == NULL ||
1542 AFSGlobalRoot == NULL)
1545 try_return( ntStatus);
1551 RtlInitUnicodeString( &uniComponentName,
1557 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1561 // Build a dir name based on the FID of the file
1565 uniName.MaximumLength = 1024 + uniComponentName.Length;
1567 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1568 uniName.MaximumLength,
1569 AFS_GENERIC_MEMORY_8_TAG);
1571 if( uniName.Buffer == NULL)
1574 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1577 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1578 uniName.MaximumLength,
1579 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1580 ParentObjectInfo->FileId.Cell,
1581 ParentObjectInfo->FileId.Volume,
1582 ParentObjectInfo->FileId.Vnode,
1583 ParentObjectInfo->FileId.Unique,
1586 if( !NT_SUCCESS( ntStatus))
1589 try_return( ntStatus);
1592 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1593 (size_t)uniName.MaximumLength,
1596 if( !NT_SUCCESS( ntStatus))
1599 try_return( ntStatus);
1602 uniName.Length = (USHORT)sztLength;
1604 usNameOffset = uniName.Length - uniComponentName.Length;
1606 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1607 AFS_TRACE_LEVEL_VERBOSE,
1608 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1614 uniComponentName.Length);
1616 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1617 &pDeviceExt->Specific.Control.DirNotifyList,
1629 if( uniName.Buffer != NULL)
1632 AFSExFreePool( uniName.Buffer);
1639 // For use with FsRtlNotifyFilterChangeDirectory but must
1640 // be implemented in the Framework because the library can
1644 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1645 IN void *FilterContext)
1648 BOOLEAN bReturn = TRUE;
1649 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1650 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1661 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1665 BOOLEAN bIsInSnapshot = FALSE;
1666 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1669 while( ulCount < SnapshotHdr->EntryCount)
1672 if( pSnapshotEntry->NameHash == HashIndex)
1675 bIsInSnapshot = TRUE;
1677 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1678 AFS_TRACE_LEVEL_VERBOSE,
1679 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1684 else if( pSnapshotEntry->NameHash == 0)
1695 return bIsInSnapshot;