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);
832 case FileIdFullDirectoryInformation:
833 case FileFullDirectoryInformation:
835 pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
836 pFullDirInfo->EaSize = 0;
838 case FileDirectoryInformation:
840 pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
845 pDirInfo->CreationTime = stFileInfo.CreationTime;
846 pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
847 pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
848 pDirInfo->ChangeTime = stFileInfo.ChangeTime;
850 pDirInfo->EndOfFile = stFileInfo.EndOfFile;
851 pDirInfo->AllocationSize = stFileInfo.AllocationSize;
853 pDirInfo->FileAttributes = stFileInfo.FileAttributes;
855 else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
858 pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
859 pDirInfo->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
860 pDirInfo->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
861 pDirInfo->ChangeTime = pFcb->ObjectInformation->ChangeTime;
863 pDirInfo->EndOfFile = pFcb->ObjectInformation->EndOfFile;
864 pDirInfo->AllocationSize = pFcb->ObjectInformation->AllocationSize;
866 if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
868 pDirInfo->FileAttributes = pObjectInfo->FileAttributes;
872 pDirInfo->FileAttributes = pFcb->ObjectInformation->FileAttributes;
878 pDirInfo->CreationTime = pObjectInfo->CreationTime;
879 pDirInfo->LastWriteTime = pObjectInfo->LastWriteTime;
880 pDirInfo->LastAccessTime = pObjectInfo->LastAccessTime;
881 pDirInfo->ChangeTime = pObjectInfo->ChangeTime;
883 pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
884 pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
886 pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
890 // Check if the name begins with a . and we are hiding them
893 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
894 pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
895 BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
898 pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
901 pDirInfo->FileIndex = pDirEntry->FileIndex;
902 pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
906 case FileNamesInformation:
908 pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
909 pNamesInfo->FileIndex = pDirEntry->FileIndex;
910 pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
916 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
917 AFS_TRACE_LEVEL_ERROR,
918 "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
920 FileInformationClass);
922 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
924 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
929 ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
930 pDirEntry->NameInformation.FileName.Length :
931 ulBytesRemainingInBuffer - ulBaseLength;
933 RtlCopyMemory( &pBuffer[ ulNextEntry + ulBaseLength],
934 pDirEntry->NameInformation.FileName.Buffer,
937 // Set up the previous next entry offset
938 *((PULONG)(&pBuffer[ ulLastEntry])) = ulNextEntry - ulLastEntry;
940 // And indicate how much of the user buffer we have currently
942 Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information) + ulBaseLength + ulBytesConverted;
944 // Check for the case that a single entry doesn't fit.
945 // This should only get this far on the first entry.
946 if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
949 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
951 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
954 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
956 dStatus = STATUS_SUCCESS;
958 // Set ourselves up for the next iteration
959 ulLastEntry = ulNextEntry;
960 ulNextEntry += (ULONG)QuadAlign( ulBaseLength + ulBytesConverted);
968 AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
974 AFSClearEnumerationEvent( pFcb);
982 AFSNotifyChangeDirectory( IN PIRP Irp)
985 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
986 PIO_STACK_LOCATION pIrpSp;
989 ULONG ulCompletionFilter;
991 BOOLEAN bReleaseLock = FALSE;
996 // Get the current Stack location
997 pIrpSp = IoGetCurrentIrpStackLocation( Irp );
999 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1000 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1005 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1006 AFS_TRACE_LEVEL_ERROR,
1007 "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
1010 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1013 if( pFcb->Header.NodeTypeCode != AFS_DIRECTORY_FCB &&
1014 pFcb->Header.NodeTypeCode != AFS_ROOT_FCB &&
1015 pFcb->Header.NodeTypeCode != AFS_ROOT_ALL)
1018 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1019 AFS_TRACE_LEVEL_ERROR,
1020 "AFSNotifyChangeDirectory NodeTypeCode !AFS_DIRECTORY_FCB && !AFS_ROOT_FCB %wZ NodeTypeCode 0x%x\n",
1021 &pCcb->DirectoryCB->NameInformation.FileName,
1022 pFcb->Header.NodeTypeCode);
1024 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1027 // Reference our input parameter to make things easier
1028 ulCompletionFilter = pIrpSp->Parameters.NotifyDirectory.CompletionFilter;
1029 bWatchTree = BooleanFlagOn( pIrpSp->Flags, SL_WATCH_TREE);
1031 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1032 AFS_TRACE_LEVEL_VERBOSE,
1033 "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
1034 &pFcb->NPFcb->Resource,
1035 PsGetCurrentThread());
1037 AFSAcquireExcl( &pFcb->NPFcb->Resource,
1040 bReleaseLock = TRUE;
1043 // Check if the node has already been deleted
1046 if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1049 try_return( ntStatus = STATUS_FILE_DELETED);
1051 else if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
1054 try_return( ntStatus = STATUS_DELETE_PENDING);
1057 // Call the Fsrtl package to process the request.
1058 ntStatus = AFSFsRtlNotifyFullChangeDirectory( pFcb->ObjectInformation,
1064 if( !NT_SUCCESS( ntStatus))
1066 try_return( ntStatus);
1069 ntStatus = STATUS_PENDING;
1076 AFSReleaseResource( &pFcb->NPFcb->Resource);
1084 AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
1088 AFSDirectoryCB *pDirEntry = NULL;
1089 NTSTATUS ntStatus = STATUS_SUCCESS;
1090 AFSSnapshotHdr *pSnapshotHdr = NULL;
1091 AFSSnapshotEntry *pSnapshotEntry = NULL;
1098 // Is this a PIOCtl query
1101 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
1104 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_DIR_INDEX ||
1105 Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_INITIAL_ROOT_INDEX)
1108 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
1110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1111 AFS_TRACE_LEVEL_VERBOSE,
1112 "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1113 &pDirEntry->NameInformation.FileName,
1114 ObjectInfo->FileId.Cell,
1115 ObjectInfo->FileId.Volume,
1116 ObjectInfo->FileId.Vnode,
1117 ObjectInfo->FileId.Unique);
1120 Ccb->CurrentDirIndex++;
1122 try_return( ntStatus);
1125 Ccb->CurrentDirIndex++;
1127 if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1131 // Return the .. entry
1134 pDirEntry = AFSGlobalDotDirEntry;
1136 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1137 AFS_TRACE_LEVEL_VERBOSE,
1138 "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1139 &pDirEntry->NameInformation.FileName,
1140 ObjectInfo->FileId.Cell,
1141 ObjectInfo->FileId.Volume,
1142 ObjectInfo->FileId.Vnode,
1143 ObjectInfo->FileId.Unique);
1145 else if( Ccb->CurrentDirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1149 // Return the .. entry
1152 pDirEntry = AFSGlobalDotDotDirEntry;
1154 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1157 &pDirEntry->NameInformation.FileName,
1158 ObjectInfo->FileId.Cell,
1159 ObjectInfo->FileId.Volume,
1160 ObjectInfo->FileId.Vnode,
1161 ObjectInfo->FileId.Unique);
1166 pSnapshotHdr = Ccb->DirectorySnapshot;
1168 if( pSnapshotHdr == NULL ||
1169 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1172 try_return( ntStatus);
1175 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1177 ulCount = Ccb->CurrentDirIndex;
1179 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1180 AFS_TRACE_LEVEL_VERBOSE,
1181 "AFSLocateNextDirEntry CurrentDirIndex %08lX\n",
1185 // Get to a valid entry
1188 AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1191 while( ulCount < pSnapshotHdr->EntryCount)
1196 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1197 AFS_TRACE_LEVEL_VERBOSE,
1198 "AFSLocateNextDirEntry Searching for hash %08lX\n",
1199 pSnapshotEntry->NameHash);
1201 if( pSnapshotEntry->NameHash == 0)
1207 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1208 pSnapshotEntry->NameHash,
1211 if( !NT_SUCCESS( ntStatus) ||
1215 if( pDirEntry != NULL)
1218 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1219 AFS_TRACE_LEVEL_VERBOSE,
1220 "AFSLocateNextDirEntry Returning3 snapshot entry %wZ (%08lX) in parent FID %08lX-%08lX-%08lX-%08lX\n",
1221 &pDirEntry->NameInformation.FileName,
1222 (ULONG)pDirEntry->CaseInsensitiveTreeEntry.HashIndex,
1223 ObjectInfo->FileId.Cell,
1224 ObjectInfo->FileId.Volume,
1225 ObjectInfo->FileId.Vnode,
1226 ObjectInfo->FileId.Unique);
1228 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSLocateNextDirEntry Returning3 NO snapshot entry in parent FID %08lX-%08lX-%08lX-%08lX\n",
1237 ObjectInfo->FileId.Cell,
1238 ObjectInfo->FileId.Volume,
1239 ObjectInfo->FileId.Vnode,
1240 ObjectInfo->FileId.Unique);
1246 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1247 AFS_TRACE_LEVEL_VERBOSE,
1248 "AFSLocateNextDirEntry Entry %08lX not found in parent FID %08lX-%08lX-%08lX-%08lX\n",
1249 pSnapshotEntry->NameHash,
1250 ObjectInfo->FileId.Cell,
1251 ObjectInfo->FileId.Volume,
1252 ObjectInfo->FileId.Vnode,
1253 ObjectInfo->FileId.Unique);
1259 Ccb->CurrentDirIndex++;
1262 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1274 AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
1279 AFSDirectoryCB *pDirEntry = NULL;
1280 NTSTATUS ntStatus = STATUS_SUCCESS;
1281 AFSSnapshotHdr *pSnapshotHdr = NULL;
1282 AFSSnapshotEntry *pSnapshotEntry = NULL;
1288 Ccb->CurrentDirIndex = DirIndex;
1290 if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
1294 // Return the .. entry
1297 pDirEntry = AFSGlobalDotDirEntry;
1299 else if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX)
1303 // Return the .. entry
1306 pDirEntry = AFSGlobalDotDotDirEntry;
1311 pSnapshotHdr = Ccb->DirectorySnapshot;
1313 if( pSnapshotHdr == NULL ||
1314 Ccb->CurrentDirIndex >= pSnapshotHdr->EntryCount)
1317 try_return( ntStatus);
1320 pSnapshotEntry = &pSnapshotHdr->TopEntry[ Ccb->CurrentDirIndex];
1322 ulCount = Ccb->CurrentDirIndex;
1325 // Get to a valid entry
1328 while( ulCount < pSnapshotHdr->EntryCount)
1333 ntStatus = AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1334 pSnapshotEntry->NameHash,
1337 if( !NT_SUCCESS( ntStatus) ||
1338 ( pDirEntry != NULL &&
1339 pDirEntry->FileIndex == DirIndex))
1350 if( pDirEntry != NULL)
1353 Ccb->CurrentDirIndex = ulCount;
1366 AFSSnapshotDirectory( IN AFSFcb *Fcb,
1368 IN BOOLEAN ResetIndex)
1371 NTSTATUS ntStatus = STATUS_SUCCESS;
1372 AFSSnapshotHdr *pSnapshotHdr = NULL;
1373 AFSSnapshotEntry *pSnapshotEntry = NULL;
1374 AFSDirectoryCB *pDirEntry = NULL;
1383 // Set it up so we still get the . and .. entries for empty directories
1386 if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
1389 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
1394 Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
1398 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
1402 // If we have a snapshot then clear it out
1405 if( Ccb->DirectorySnapshot != NULL)
1408 AFSExFreePool( Ccb->DirectorySnapshot);
1410 Ccb->DirectorySnapshot = NULL;
1413 try_return( ntStatus);
1417 // Allocate our snapshot buffer for this enumeration
1420 pSnapshotHdr = (AFSSnapshotHdr *)AFSExAllocatePoolWithTag( PagedPool,
1421 sizeof( AFSSnapshotHdr) +
1422 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1423 sizeof( AFSSnapshotEntry)),
1424 AFS_DIR_SNAPSHOT_TAG);
1426 if( pSnapshotHdr == NULL)
1429 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1432 RtlZeroMemory( pSnapshotHdr,
1433 sizeof( AFSSnapshotHdr) +
1434 ( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount *
1435 sizeof( AFSSnapshotEntry)));
1437 pSnapshotHdr->EntryCount = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount;
1439 pSnapshotHdr->TopEntry = (AFSSnapshotEntry *)((char *)pSnapshotHdr + sizeof( AFSSnapshotHdr));
1442 // Populate our snapshot
1445 pSnapshotEntry = pSnapshotHdr->TopEntry;
1447 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
1449 while( pDirEntry != NULL)
1452 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
1453 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE) &&
1454 !AFSIsNameInSnapshot( pSnapshotHdr,
1455 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex))
1458 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1459 AFS_TRACE_LEVEL_VERBOSE,
1460 "AFSSnapshotDirectory Snapshot (%08lX) Inserting entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1461 pSnapshotHdr->EntryCount,
1462 &pDirEntry->NameInformation.FileName,
1463 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1465 Fcb->ObjectInformation->FileId.Cell,
1466 Fcb->ObjectInformation->FileId.Volume,
1467 Fcb->ObjectInformation->FileId.Vnode,
1468 Fcb->ObjectInformation->FileId.Unique);
1470 pSnapshotEntry->NameHash = (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex;
1477 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1478 AFS_TRACE_LEVEL_VERBOSE,
1479 "AFSSnapshotDirectory Snapshot (%08lX) Skipping entry %wZ (%08lX) Flags %08lX in parent FID %08lX-%08lX-%08lX-%08lX\n",
1480 pSnapshotHdr->EntryCount,
1481 &pDirEntry->NameInformation.FileName,
1482 (ULONG)pDirEntry->CaseSensitiveTreeEntry.HashIndex,
1484 Fcb->ObjectInformation->FileId.Cell,
1485 Fcb->ObjectInformation->FileId.Volume,
1486 Fcb->ObjectInformation->FileId.Vnode,
1487 Fcb->ObjectInformation->FileId.Unique);
1490 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
1493 if( Ccb->DirectorySnapshot != NULL)
1496 AFSExFreePool( Ccb->DirectorySnapshot);
1498 Ccb->DirectorySnapshot = NULL;
1501 Ccb->DirectorySnapshot = pSnapshotHdr;
1512 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
1514 IN BOOLEAN WatchTree,
1515 IN ULONG CompletionFilter,
1519 NTSTATUS ntStatus = STATUS_SUCCESS;
1520 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1527 // Build a dir name based on the FID of the file
1530 if( Ccb->NotifyMask.Buffer == NULL)
1533 Ccb->NotifyMask.Length = 0;
1534 Ccb->NotifyMask.MaximumLength = 1024;
1536 Ccb->NotifyMask.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1537 Ccb->NotifyMask.MaximumLength,
1538 AFS_GENERIC_MEMORY_7_TAG);
1540 if( Ccb->NotifyMask.Buffer == NULL)
1543 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1546 ntStatus = RtlStringCbPrintfW( Ccb->NotifyMask.Buffer,
1547 Ccb->NotifyMask.MaximumLength,
1548 L"\\%08lX.%08lX.%08lX.%08lX",
1549 ObjectInfo->FileId.Cell,
1550 ObjectInfo->FileId.Volume,
1551 ObjectInfo->FileId.Vnode,
1552 ObjectInfo->FileId.Unique);
1554 if( !NT_SUCCESS( ntStatus))
1557 try_return( ntStatus);
1560 ntStatus = RtlStringCbLengthW( Ccb->NotifyMask.Buffer,
1561 (size_t)Ccb->NotifyMask.MaximumLength,
1564 if( !NT_SUCCESS( ntStatus))
1567 try_return( ntStatus);
1570 Ccb->NotifyMask.Length = (USHORT)sztLength;
1573 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1574 AFS_TRACE_LEVEL_VERBOSE,
1575 "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
1581 FsRtlNotifyFilterChangeDirectory( pDeviceExt->Specific.Control.NotifySync,
1582 &pDeviceExt->Specific.Control.DirNotifyList,
1584 (PSTRING)&Ccb->NotifyMask,
1595 if( !NT_SUCCESS( ntStatus))
1598 if( Ccb->NotifyMask.Buffer != NULL)
1601 AFSExFreePool( Ccb->NotifyMask.Buffer);
1603 Ccb->NotifyMask.Buffer = NULL;
1612 AFSFsRtlNotifyFullReportChange( IN AFSObjectInfoCB *ParentObjectInfo,
1614 IN ULONG NotifyFilter,
1615 IN ULONG NotificationAction)
1618 NTSTATUS ntStatus = STATUS_SUCCESS;
1619 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1620 UNICODE_STRING uniName, uniComponentName;
1622 USHORT usNameOffset = 0;
1627 uniName.Buffer = NULL;
1629 if( ParentObjectInfo == NULL ||
1630 AFSGlobalRoot == NULL)
1633 try_return( ntStatus);
1639 RtlInitUnicodeString( &uniComponentName,
1645 uniComponentName = Ccb->DirectoryCB->NameInformation.FileName;
1649 // Build a dir name based on the FID of the file
1653 uniName.MaximumLength = 1024 + uniComponentName.Length;
1655 uniName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
1656 uniName.MaximumLength,
1657 AFS_GENERIC_MEMORY_8_TAG);
1659 if( uniName.Buffer == NULL)
1662 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1665 ntStatus = RtlStringCbPrintfW( uniName.Buffer,
1666 uniName.MaximumLength,
1667 L"\\%08lX.%08lX.%08lX.%08lX\\%wZ",
1668 ParentObjectInfo->FileId.Cell,
1669 ParentObjectInfo->FileId.Volume,
1670 ParentObjectInfo->FileId.Vnode,
1671 ParentObjectInfo->FileId.Unique,
1674 if( !NT_SUCCESS( ntStatus))
1677 try_return( ntStatus);
1680 ntStatus = RtlStringCbLengthW( uniName.Buffer,
1681 (size_t)uniName.MaximumLength,
1684 if( !NT_SUCCESS( ntStatus))
1687 try_return( ntStatus);
1690 uniName.Length = (USHORT)sztLength;
1692 usNameOffset = uniName.Length - uniComponentName.Length;
1694 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
1695 AFS_TRACE_LEVEL_VERBOSE,
1696 "AFSFsRtlNotifyFullReportChange Notification call for %wZ Filter %08lX Action %08lX Offset %08lX Len %08lX CompLen %08lX\n",
1702 uniComponentName.Length);
1704 FsRtlNotifyFilterReportChange( pDeviceExt->Specific.Control.NotifySync,
1705 &pDeviceExt->Specific.Control.DirNotifyList,
1717 if( uniName.Buffer != NULL)
1720 AFSExFreePool( uniName.Buffer);
1727 // For use with FsRtlNotifyFilterChangeDirectory but must
1728 // be implemented in the Framework because the library can
1732 AFSNotifyReportChangeCallback( IN void *NotifyContext,
1733 IN void *FilterContext)
1736 BOOLEAN bReturn = TRUE;
1737 AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
1738 AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
1749 AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
1753 BOOLEAN bIsInSnapshot = FALSE;
1754 AFSSnapshotEntry *pSnapshotEntry = SnapshotHdr->TopEntry;
1757 while( ulCount < SnapshotHdr->EntryCount)
1760 if( pSnapshotEntry->NameHash == HashIndex)
1763 bIsInSnapshot = TRUE;
1765 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSIsNameInSnapshot Hash index %08lX already in snapshot\n",
1772 else if( pSnapshotEntry->NameHash == 0)
1783 return bIsInSnapshot;