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,
773 // Here are the rules concerning filling up the buffer:
775 // 1. The Io system guarantees that there will always be
776 // enough room for at least one base record.
778 // 2. If the full first record (including file name) cannot
779 // fit, as much of the name as possible is copied and
780 // STATUS_BUFFER_OVERFLOW is returned.
782 // 3. If a subsequent record cannot completely fit into the
783 // buffer, none of it (as in 0 bytes) is copied, and
784 // STATUS_SUCCESS is returned. A subsequent query will
785 // pick up with this record.
787 ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
789 if( ( ulNextEntry != 0) &&
790 ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
791 ( ulUserBufferLength < ulNextEntry) ) )
795 // Back off our current index
798 pCcb->CurrentDirIndex--;
800 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
802 try_return( ntStatus = STATUS_SUCCESS);
805 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
806 AFS_TRACE_LEVEL_VERBOSE,
807 "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
808 &pCcb->DirectoryCB->NameInformation.FileName,
809 &pDirEntry->NameInformation.FileName);
811 // Zero the base part of the structure.
812 RtlZeroMemory( &pBuffer[ ulNextEntry],
815 switch( FileInformationClass)
818 // Now fill the base parts of the structure that are applicable.
819 case FileIdBothDirectoryInformation:
820 case FileBothDirectoryInformation:
822 pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
824 pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
826 if( pDirEntry->NameInformation.ShortNameLength > 0)
828 RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
829 &pDirEntry->NameInformation.ShortName[ 0],
830 pBothDirInfo->ShortNameLength);
833 case FileIdFullDirectoryInformation:
834 case FileFullDirectoryInformation:
836 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
837 pFullDirInfo->EaSize = 0;
839 case FileDirectoryInformation:
841 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
846 pDirInfo->CreationTime = stFileInfo.CreationTime;
847 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
848 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
849 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
851 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
852 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
854 pDirInfo->FileAttributes = stFileInfo.FileAttributes;
856 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
859 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
860 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
861 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
862 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
864 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
865 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
867 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
869 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
873 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
879 pDirInfo->CreationTime = pObjectInfo->CreationTime;
880 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
881 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
882 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
884 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
885 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
887 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
891 // Check if the name begins with a . and we are hiding them
894 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
895 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
896 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
899 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
902 pDirInfo->FileIndex = pDirEntry->FileIndex;
903 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
908 case FileNamesInformation:
910 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
911 pNamesInfo->FileIndex = pDirEntry->FileIndex;
912 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
918 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
919 AFS_TRACE_LEVEL_ERROR,
920 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
922 FileInformationClass);
924 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
926 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
932 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
933 pDirEntry->NameInformation.FileName.Length :
934 ulBytesRemainingInBuffer - ulBaseLength;
936 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
937 pDirEntry->NameInformation.FileName.Buffer,
940 // Set up the previous next entry offset
941 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
943 // And indicate how much of the user buffer we have currently
945 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
947 // Check for the case that a single entry doesn't fit.
948 // This should only get this far on the first entry.
949 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
952 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
954 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
957 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
959 dStatus = STATUS_SUCCESS;
961 // Set ourselves up for the next iteration
962 ulLastEntry = ulNextEntry;
963 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
971 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
977 AFSClearEnumerationEvent( pFcb);
985 AFSNotifyChangeDirectory( IN PIRP Irp)
988 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
989 PIO_STACK_LOCATION pIrpSp;
992 ULONG ulCompletionFilter;
994 BOOLEAN bReleaseLock = FALSE;
999 // Get the current Stack location
1000 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
1002 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1003 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1008 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1009 AFS_TRACE_LEVEL_ERROR,
1010 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1013 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1016 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1017 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1018 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1021 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1022 AFS_TRACE_LEVEL_ERROR,
1023 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1024 &pCcb->DirectoryCB->NameInformation.FileName,
1025 pFcb->Header.NodeTypeCode);
1027 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1030 // Reference our input parameter to make things easier
1031 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1032 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1035 AFS_TRACE_LEVEL_VERBOSE,
1036 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1037 &pFcb->NPFcb->Resource,
1038 PsGetCurrentThread());
1040 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1043 bReleaseLock = TRUE;
1046 // Check if the node has already been deleted
1049 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1052 try_return( ntStatus = STATUS_FILE_DELETED);
1054 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1057 try_return( ntStatus = STATUS_DELETE_PENDING);
1060 // Call the Fsrtl package to process the request.
1061 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1067 if( !NT_SUCCESS( ntStatus))
1069 try_return( ntStatus);
1072 ntStatus = STATUS_PENDING;
1079 AFSReleaseResource( &pFcb->NPFcb->Resource);
1087 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1091 AFSDirectoryCB *pDirEntry = NULL;
1092 NTSTATUS ntStatus = STATUS_SUCCESS;
1093 AFSSnapshotHdr *pSnapshotHdr = NULL;
1094 AFSSnapshotEntry *pSnapshotEntry = NULL;
1101 // Is this a PIOCtl query
1104 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1107 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1108 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1111 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1113 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1114 AFS_TRACE_LEVEL_VERBOSE,
1115 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1116 &pDirEntry->NameInformation.FileName,
1117 ObjectInfo->FileId.Cell,
1118 ObjectInfo->FileId.Volume,
1119 ObjectInfo->FileId.Vnode,
1120 ObjectInfo->FileId.Unique);
1123 Ccb->CurrentDirIndex++;
1125 try_return( ntStatus);
1128 Ccb->CurrentDirIndex++;
1130 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1134 // Return the .. entry
1137 pDirEntry = AFSGlobalDotDirEntry;
1139 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1140 AFS_TRACE_LEVEL_VERBOSE,
1141 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1142 &pDirEntry->NameInformation.FileName,
1143 ObjectInfo->FileId.Cell,
1144 ObjectInfo->FileId.Volume,
1145 ObjectInfo->FileId.Vnode,
1146 ObjectInfo->FileId.Unique);
1148 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1152 // Return the .. entry
1155 pDirEntry = AFSGlobalDotDotDirEntry;
1157 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1158 AFS_TRACE_LEVEL_VERBOSE,
1159 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1160 &pDirEntry->NameInformation.FileName,
1161 ObjectInfo->FileId.Cell,
1162 ObjectInfo->FileId.Volume,
1163 ObjectInfo->FileId.Vnode,
1164 ObjectInfo->FileId.Unique);
1169 pSnapshotHdr = Ccb->DirectorySnapshot;
1171 if( pSnapshotHdr == NULL ||
1172 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1175 try_return( ntStatus);
1178 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1180 ulCount = Ccb->CurrentDirIndex;
1182 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1183 AFS_TRACE_LEVEL_VERBOSE,
1184 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1188 // Get to a valid entry
1191 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1194 while( ulCount < pSnapshotHdr->EntryCount)
1199 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1200 AFS_TRACE_LEVEL_VERBOSE,
1201 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1202 pSnapshotEntry->NameHash);
1204 if( pSnapshotEntry->NameHash == 0)
1210 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1211 pSnapshotEntry->NameHash,
1214 if( !NT_SUCCESS( ntStatus) ||
1218 if( pDirEntry != NULL)
1221 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1222 AFS_TRACE_LEVEL_VERBOSE,
1223 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1224 &pDirEntry->NameInformation.FileName,
1225 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1226 ObjectInfo->FileId.Cell,
1227 ObjectInfo->FileId.Volume,
1228 ObjectInfo->FileId.Vnode,
1229 ObjectInfo->FileId.Unique);
1231 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1237 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1238 AFS_TRACE_LEVEL_VERBOSE,
1239 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1240 ObjectInfo->FileId.Cell,
1241 ObjectInfo->FileId.Volume,
1242 ObjectInfo->FileId.Vnode,
1243 ObjectInfo->FileId.Unique);
1249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1250 AFS_TRACE_LEVEL_VERBOSE,
1251 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1252 pSnapshotEntry->NameHash,
1253 ObjectInfo->FileId.Cell,
1254 ObjectInfo->FileId.Volume,
1255 ObjectInfo->FileId.Vnode,
1256 ObjectInfo->FileId.Unique);
1262 Ccb->CurrentDirIndex++;
1265 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1277 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1282 AFSDirectoryCB *pDirEntry = NULL;
1283 NTSTATUS ntStatus = STATUS_SUCCESS;
1284 AFSSnapshotHdr *pSnapshotHdr = NULL;
1285 AFSSnapshotEntry *pSnapshotEntry = NULL;
1291 Ccb->CurrentDirIndex = DirIndex;
1293 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1297 // Return the .. entry
1300 pDirEntry = AFSGlobalDotDirEntry;
1302 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1306 // Return the .. entry
1309 pDirEntry = AFSGlobalDotDotDirEntry;
1314 pSnapshotHdr = Ccb->DirectorySnapshot;
1316 if( pSnapshotHdr == NULL ||
1317 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1320 try_return( ntStatus);
1323 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1325 ulCount = Ccb->CurrentDirIndex;
1328 // Get to a valid entry
1331 while( ulCount < pSnapshotHdr->EntryCount)
1336 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1337 pSnapshotEntry->NameHash,
1340 if( !NT_SUCCESS( ntStatus) ||
1341 ( pDirEntry != NULL &&
1342 pDirEntry->FileIndex == DirIndex))
1353 if( pDirEntry != NULL)
1356 Ccb->CurrentDirIndex = ulCount;
1369 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1371 IN BOOLEAN ResetIndex)
1374 NTSTATUS ntStatus = STATUS_SUCCESS;
1375 AFSSnapshotHdr *pSnapshotHdr = NULL;
1376 AFSSnapshotEntry *pSnapshotEntry = NULL;
1377 AFSDirectoryCB *pDirEntry = NULL;
1386 // Set it up so we still get the . and .. entries for empty directories
1389 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1392 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1397 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1401 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1405 // If we have a snapshot then clear it out
1408 if( Ccb->DirectorySnapshot != NULL)
1411 AFSExFreePool( Ccb->DirectorySnapshot);
1413 Ccb->DirectorySnapshot = NULL;
1416 try_return( ntStatus);
1420 // Allocate our snapshot buffer for this enumeration
1423 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1424 sizeof( AFSSnapshotHdr) +
1425 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1426 sizeof( AFSSnapshotEntry)),
1427 AFS_DIR_SNAPSHOT_TAG);
1429 if( pSnapshotHdr == NULL)
1432 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1435 RtlZeroMemory( pSnapshotHdr,
1436 sizeof( AFSSnapshotHdr) +
1437 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1438 sizeof( AFSSnapshotEntry)));
1440 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1442 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1445 // Populate our snapshot
1448 pSnapshotEntry = pSnapshotHdr->TopEntry;
1450 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1452 while( pDirEntry != NULL)
1455 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1456 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1457 !AFSIsNameInSnapshot( pSnapshotHdr,
1458 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1461 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1462 AFS_TRACE_LEVEL_VERBOSE,
1463 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1464 pSnapshotHdr->EntryCount,
1465 &pDirEntry->NameInformation.FileName,
1466 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1468 Fcb->ObjectInformation->FileId.Cell,
1469 Fcb->ObjectInformation->FileId.Volume,
1470 Fcb->ObjectInformation->FileId.Vnode,
1471 Fcb->ObjectInformation->FileId.Unique);
1473 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1480 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1481 AFS_TRACE_LEVEL_VERBOSE,
1482 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1483 pSnapshotHdr->EntryCount,
1484 &pDirEntry->NameInformation.FileName,
1485 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1487 Fcb->ObjectInformation->FileId.Cell,
1488 Fcb->ObjectInformation->FileId.Volume,
1489 Fcb->ObjectInformation->FileId.Vnode,
1490 Fcb->ObjectInformation->FileId.Unique);
1493 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1496 if( Ccb->DirectorySnapshot != NULL)
1499 AFSExFreePool( Ccb->DirectorySnapshot);
1501 Ccb->DirectorySnapshot = NULL;
1504 Ccb->DirectorySnapshot = pSnapshotHdr;
1515 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1517 IN BOOLEAN WatchTree,
1518 IN ULONG CompletionFilter,
1522 NTSTATUS ntStatus = STATUS_SUCCESS;
1523 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1530 // Build a dir name based on the FID of the file
1533 if( Ccb->NotifyMask.Buffer == NULL)
1536 Ccb->NotifyMask.Length = 0;
1537 Ccb->NotifyMask.MaximumLength = 1024;
1539 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1540 Ccb->NotifyMask.MaximumLength,
1541 AFS_GENERIC_MEMORY_7_TAG);
1543 if( Ccb->NotifyMask.Buffer == NULL)
1546 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1549 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1550 Ccb->NotifyMask.MaximumLength,
1551 L"\\%08lX.%08lX.%08lX.%08lX",
1552 ObjectInfo->FileId.Cell,
1553 ObjectInfo->FileId.Volume,
1554 ObjectInfo->FileId.Vnode,
1555 ObjectInfo->FileId.Unique);
1557 if( !NT_SUCCESS( ntStatus))
1560 try_return( ntStatus);
1563 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1564 (size_t)Ccb->NotifyMask.MaximumLength,
1567 if( !NT_SUCCESS( ntStatus))
1570 try_return( ntStatus);
1573 Ccb->NotifyMask.Length = (USHORT)sztLength;
1576 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1577 AFS_TRACE_LEVEL_VERBOSE,
1578 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1584 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1585 &pDeviceExt->Specific.Control.DirNotifyList,
1587 (PSTRING)&Ccb->NotifyMask,
1598 if( !NT_SUCCESS( ntStatus))
1601 if( Ccb->NotifyMask.Buffer != NULL)
1604 AFSExFreePool( Ccb->NotifyMask.Buffer);
1606 Ccb->NotifyMask.Buffer = NULL;
1615 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1617 IN ULONG NotifyFilter,
1618 IN ULONG NotificationAction)
1621 NTSTATUS ntStatus = STATUS_SUCCESS;
1622 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1623 UNICODE_STRING uniName, uniComponentName;
1625 USHORT usNameOffset = 0;
1630 uniName.Buffer = NULL;
1632 if( ParentObjectInfo == NULL ||
1633 AFSGlobalRoot == NULL)
1636 try_return( ntStatus);
1642 RtlInitUnicodeString( &uniComponentName,
1648 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1652 // Build a dir name based on the FID of the file
1656 uniName.MaximumLength = 1024 + uniComponentName.Length;
1658 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1659 uniName.MaximumLength,
1660 AFS_GENERIC_MEMORY_8_TAG);
1662 if( uniName.Buffer == NULL)
1665 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1668 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1669 uniName.MaximumLength,
1670 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1671 ParentObjectInfo->FileId.Cell,
1672 ParentObjectInfo->FileId.Volume,
1673 ParentObjectInfo->FileId.Vnode,
1674 ParentObjectInfo->FileId.Unique,
1677 if( !NT_SUCCESS( ntStatus))
1680 try_return( ntStatus);
1683 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1684 (size_t)uniName.MaximumLength,
1687 if( !NT_SUCCESS( ntStatus))
1690 try_return( ntStatus);
1693 uniName.Length = (USHORT)sztLength;
1695 usNameOffset = uniName.Length - uniComponentName.Length;
1697 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1698 AFS_TRACE_LEVEL_VERBOSE,
1699 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1705 uniComponentName.Length);
1707 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1708 &pDeviceExt->Specific.Control.DirNotifyList,
1720 if( uniName.Buffer != NULL)
1723 AFSExFreePool( uniName.Buffer);
1730 // For use with FsRtlNotifyFilterChangeDirectory but must
1731 // be implemented in the Framework because the library can
1735 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1736 IN void *FilterContext)
1739 BOOLEAN bReturn = TRUE;
1740 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1741 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1752 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1756 BOOLEAN bIsInSnapshot = FALSE;
1757 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1760 while( ulCount < SnapshotHdr->EntryCount)
1763 if( pSnapshotEntry->NameHash == HashIndex)
1766 bIsInSnapshot = TRUE;
1768 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1769 AFS_TRACE_LEVEL_VERBOSE,
1770 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1775 else if( pSnapshotEntry->NameHash == 0)
1786 return bIsInSnapshot;