2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 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
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSFSControl.cpp
37 #include "AFSCommon.h"
40 AFSFSControl( IN PDEVICE_OBJECT LibDeviceObject,
44 UNREFERENCED_PARAMETER(LibDeviceObject);
45 NTSTATUS ntStatus = STATUS_SUCCESS;
46 IO_STACK_LOCATION *pIrpSp;
48 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
53 switch( pIrpSp->MinorFunction)
56 case IRP_MN_USER_FS_REQUEST:
58 ntStatus = AFSProcessUserFsRequest( Irp);
62 case IRP_MN_MOUNT_VOLUME:
66 case IRP_MN_VERIFY_VOLUME:
75 AFSCompleteRequest( Irp,
79 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
84 "EXCEPTION - AFSFSControl\n");
86 AFSDumpTraceFilesFnc();
93 AFSParseMountPointTarget( IN UNICODE_STRING *Target,
95 OUT UNICODE_STRING *Volume,
96 OUT UNICODE_STRING *Cell)
98 // Targets are of the form <type>[<cell>:]<volume>
100 *Type = Target->Buffer[ 0];
102 // Extract the cell name (if any)
104 Cell->Buffer = &Target->Buffer[ 1];
106 // Search for colon separator or end of counted string
108 for ( Cell->Length = 0; Cell->Length < Target->Length - sizeof( WCHAR); Cell->Length += sizeof( WCHAR))
111 if ( Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
117 // If a colon is not found, it means there is no cell
119 if ( Cell->Length < Target->Length - sizeof( WCHAR) &&
120 Cell->Buffer[ Cell->Length / sizeof( WCHAR)] == L':')
123 Cell->MaximumLength = Cell->Length;
125 if ( Cell->Length > Target->Length - 2 * sizeof( WCHAR))
127 // Invalid target string if there is no room for
133 Volume->Length = Volume->MaximumLength = (Target->Length - Cell->Length - 2 * sizeof( WCHAR));
135 Volume->Buffer = &Target->Buffer[ Cell->Length / sizeof( WCHAR) + 2];
141 Volume->Length = Volume->MaximumLength = Cell->Length;
143 Volume->Buffer = Cell->Buffer;
145 Cell->Length = Cell->MaximumLength = 0;
154 AFSProcessUserFsRequest( IN PIRP Irp)
157 NTSTATUS ntStatus = STATUS_SUCCESS;
158 ULONG ulFsControlCode;
160 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
162 ULONG ulOutputBufferLen, ulInputBufferLen;
167 ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
169 pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
171 pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
175 pCcb->DirectoryCB == NULL)
178 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
179 AFS_TRACE_LEVEL_VERBOSE_2,
180 "AFSProcessUserFsRequest Invalid Fcb\n");
182 try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
185 if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
188 ntStatus = AFSProcessShareFsCtrl( Irp,
192 try_return( ntStatus);
195 ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
196 ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
199 // Process the request
202 switch( ulFsControlCode )
205 case FSCTL_REQUEST_OPLOCK_LEVEL_1:
206 case FSCTL_REQUEST_OPLOCK_LEVEL_2:
207 case FSCTL_REQUEST_BATCH_OPLOCK:
208 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
209 case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
210 case FSCTL_OPLOCK_BREAK_NOTIFY:
211 case FSCTL_OPLOCK_BREAK_ACK_NO_2:
212 case FSCTL_REQUEST_FILTER_OPLOCK :
215 // Note that implementing this call will probably need us
216 // to call the server as well as adding code in read and
217 // write and caching. Also that it is unlikely that
218 // anyone will ever call us at this point - RDR doesn't
222 ntStatus = STATUS_NOT_IMPLEMENTED;
227 case FSCTL_LOCK_VOLUME:
229 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
230 AFS_TRACE_LEVEL_VERBOSE_2,
231 "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n");
233 ntStatus = STATUS_NOT_IMPLEMENTED;
238 case FSCTL_UNLOCK_VOLUME:
240 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
241 AFS_TRACE_LEVEL_VERBOSE_2,
242 "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n");
244 ntStatus = STATUS_NOT_IMPLEMENTED;
249 case FSCTL_DISMOUNT_VOLUME:
251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
252 AFS_TRACE_LEVEL_VERBOSE_2,
253 "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n");
255 ntStatus = STATUS_NOT_IMPLEMENTED;
260 case FSCTL_MARK_VOLUME_DIRTY:
262 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
263 AFS_TRACE_LEVEL_VERBOSE_2,
264 "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n");
266 ntStatus = STATUS_NOT_IMPLEMENTED;
271 case FSCTL_IS_VOLUME_DIRTY:
273 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
274 AFS_TRACE_LEVEL_VERBOSE_2,
275 "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n");
277 ntStatus = STATUS_NOT_IMPLEMENTED;
282 case FSCTL_IS_VOLUME_MOUNTED:
284 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
285 AFS_TRACE_LEVEL_VERBOSE_2,
286 "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n");
288 ntStatus = STATUS_NOT_IMPLEMENTED;
293 case FSCTL_IS_PATHNAME_VALID:
295 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
296 AFS_TRACE_LEVEL_VERBOSE_2,
297 "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n");
299 ntStatus = STATUS_SUCCESS;
304 #ifndef FSCTL_CSC_INTERNAL
305 #define FSCTL_CSC_INTERNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
307 case FSCTL_CSC_INTERNAL:
309 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
310 AFS_TRACE_LEVEL_VERBOSE_2,
311 "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n");
313 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
318 case FSCTL_GET_REPARSE_POINT:
321 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
322 ULONG ulRemainingLen = ulOutputBufferLen;
323 AFSReparseTagInfo *pReparseInfo = NULL;
325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
326 AFS_TRACE_LEVEL_VERBOSE_2,
327 "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
328 &pCcb->DirectoryCB->NameInformation.FileName,
329 pCcb->DirectoryCB->ObjectInformation->FileType,
330 pCcb->DirectoryCB->ObjectInformation->FileAttributes);
333 // Check if we have the reparse entry set on the entry
336 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
339 ntStatus = STATUS_NOT_A_REPARSE_POINT;
344 if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
347 ntStatus = STATUS_BUFFER_TOO_SMALL;
349 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
354 ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
357 // Populate the data in the reparse buffer
360 pReparseBuffer->ReparseDataLength = 0;
362 AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
365 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
369 // We'll reset the DV to ensure we validate the metadata content
372 pCcb->DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
374 SetFlag( pCcb->DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
376 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
377 AFS_TRACE_LEVEL_VERBOSE,
378 "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
379 &pCcb->DirectoryCB->NameInformation.FileName,
380 pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
381 pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
382 pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
383 pCcb->DirectoryCB->ObjectInformation->FileId.Unique);
385 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
388 if( !NT_SUCCESS( ntStatus))
391 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
392 AFS_TRACE_LEVEL_ERROR,
393 "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
394 &pCcb->DirectoryCB->NameInformation.FileName,
395 pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
396 pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
397 pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
398 pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
401 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
407 pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];
409 switch( pCcb->DirectoryCB->ObjectInformation->FileType)
412 case AFS_FILE_TYPE_SYMLINK:
415 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
418 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
423 if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
426 ntStatus = STATUS_BUFFER_TOO_SMALL;
428 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
429 FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
430 pCcb->DirectoryCB->NameInformation.TargetName.Length;
435 pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK;
437 pReparseInfo->AFSSymLink.RelativeLink = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
439 pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
441 RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer,
442 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
443 pCcb->DirectoryCB->NameInformation.TargetName.Length);
445 pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
450 case AFS_FILE_TYPE_MOUNTPOINT:
452 UNICODE_STRING Cell, Volume;
455 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
457 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
462 if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
467 ntStatus = STATUS_INVALID_PARAMETER;
472 if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
475 ntStatus = STATUS_BUFFER_TOO_SMALL;
477 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
478 FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
479 Volume.Length + Cell.Length;
484 pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;
486 pReparseInfo->AFSMountPoint.Type = Type;
488 pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;
490 pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;
492 RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
496 RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
500 pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);
505 case AFS_FILE_TYPE_DFSLINK:
508 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
511 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
516 if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
519 ntStatus = STATUS_BUFFER_TOO_SMALL;
521 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
522 FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
523 pCcb->DirectoryCB->NameInformation.TargetName.Length;
528 pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC;
530 pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
532 RtlCopyMemory( pReparseInfo->UNCReferral.Buffer,
533 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
534 pCcb->DirectoryCB->NameInformation.TargetName.Length);
536 pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);
543 ntStatus = STATUS_NOT_A_REPARSE_POINT;
548 if ( ntStatus == STATUS_SUCCESS)
551 ulRemainingLen -= pReparseBuffer->ReparseDataLength;
553 pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
555 RtlCopyMemory( &pReparseBuffer->ReparseGuid,
556 &GUID_AFS_REPARSE_GUID,
559 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
560 pReparseBuffer->ReparseDataLength;
563 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
568 case FSCTL_SET_REPARSE_POINT:
571 REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
572 REPARSE_DATA_BUFFER *pReparseBuffer = NULL;
573 AFSReparseTagInfo *pReparseInfo = NULL;
574 AFSObjectInfoCB *pParentObjectInfo = NULL;
575 UNICODE_STRING uniTargetName;
576 ULONGLONG ullIndex = 0;
579 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
580 AFS_TRACE_LEVEL_VERBOSE,
581 "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
582 &pCcb->DirectoryCB->NameInformation.FileName,
583 pCcb->DirectoryCB->ObjectInformation->FileType,
584 pCcb->DirectoryCB->ObjectInformation->FileAttributes);
586 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
589 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
594 if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS)
597 if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid,
598 &GUID_AFS_REPARSE_GUID,
599 sizeof( GUID)) != sizeof( GUID))
602 ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
607 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
608 sizeof( AFSReparseTagInfo))
611 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
616 pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer;
618 switch( pReparseInfo->SubTag)
621 case OPENAFS_SUBTAG_SYMLINK:
624 if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
625 FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
626 pReparseInfo->AFSSymLink.SymLinkTargetLength))
629 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
634 uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength;
635 uniTargetName.MaximumLength = uniTargetName.Length;
637 uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer;
642 case OPENAFS_SUBTAG_UNC:
645 if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
646 FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
647 pReparseInfo->UNCReferral.UNCTargetLength))
650 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
655 uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength;
656 uniTargetName.MaximumLength = uniTargetName.Length;
658 uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer;
663 case OPENAFS_SUBTAG_MOUNTPOINT:
670 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
679 // Handle Microsoft Reparse Tags
682 switch( pReparseGUIDBuffer->ReparseTag)
685 case IO_REPARSE_TAG_MOUNT_POINT:
688 pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
690 uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength;
691 uniTargetName.MaximumLength = uniTargetName.Length;
693 uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer +
694 pReparseBuffer->MountPointReparseBuffer.PrintNameOffset);
696 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
697 AFS_TRACE_LEVEL_VERBOSE_2,
698 "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n",
701 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
706 case IO_REPARSE_TAG_SYMLINK:
709 pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
711 uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
712 uniTargetName.MaximumLength = uniTargetName.Length;
714 uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer +
715 pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset);
717 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
718 AFS_TRACE_LEVEL_VERBOSE_2,
719 "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n",
727 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
734 if( !NT_SUCCESS( ntStatus))
741 // First thing is to locate/create our object information block
745 AFSAcquireExcl( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
748 ullIndex = AFSCreateLowIndex( &pCcb->DirectoryCB->ObjectInformation->ParentFileId);
750 ntStatus = AFSLocateHashEntry( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead,
752 (AFSBTreeEntry **)&pParentObjectInfo);
754 if ( NT_SUCCESS( ntStatus) &&
758 lCount = AFSObjectInfoIncrement( pParentObjectInfo,
759 AFS_OBJECT_REFERENCE_DIRENTRY);
761 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
762 AFS_TRACE_LEVEL_VERBOSE,
763 "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n",
768 AFSReleaseResource( pCcb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
771 // Extract out the information to the call to the service
774 ntStatus = AFSCreateSymlink( &pCcb->AuthGroup,
776 &pCcb->DirectoryCB->NameInformation.FileName,
777 pCcb->DirectoryCB->ObjectInformation,
780 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
781 AFS_TRACE_LEVEL_VERBOSE_2,
782 "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n",
783 &pCcb->DirectoryCB->NameInformation.FileName,
784 pCcb->DirectoryCB->ObjectInformation->FileType,
785 pCcb->DirectoryCB->ObjectInformation->FileAttributes,
788 lCount = AFSObjectInfoDecrement( pParentObjectInfo,
789 AFS_OBJECT_REFERENCE_DIRENTRY);
791 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
792 AFS_TRACE_LEVEL_VERBOSE,
793 "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n",
800 case FSCTL_DELETE_REPARSE_POINT:
803 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
805 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
806 AFS_TRACE_LEVEL_VERBOSE_2,
807 "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
808 &pCcb->DirectoryCB->NameInformation.FileName,
809 pCcb->DirectoryCB->ObjectInformation->FileType,
810 pCcb->DirectoryCB->ObjectInformation->FileAttributes);
813 // Check if we have the reparse entry set on the entry
816 if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
819 ntStatus = STATUS_NOT_A_REPARSE_POINT;
824 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
827 ntStatus = STATUS_INVALID_PARAMETER;
832 if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
835 ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
840 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
841 &GUID_AFS_REPARSE_GUID,
842 sizeof( GUID)) != sizeof( GUID))
845 ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
851 // Claim success. The typical usage is setting delete on close
852 // as the next operation on the reparse point before closing
856 ntStatus = STATUS_SUCCESS;
861 #ifndef FSCTL_SET_PURGE_FAILURE_MODE
862 #define FSCTL_SET_PURGE_FAILURE_MODE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS)
865 case FSCTL_SET_PURGE_FAILURE_MODE:
869 // For the time being just succeed this call
872 ntStatus = STATUS_SUCCESS;
880 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
881 AFS_TRACE_LEVEL_VERBOSE_2,
882 "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode);
884 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
899 AFSProcessShareFsCtrl( IN IRP *Irp,
904 UNREFERENCED_PARAMETER(Fcb);
905 NTSTATUS ntStatus = STATUS_SUCCESS;
906 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
907 ULONG ulOutputBufferLen = 0, ulInputBufferLen;
908 ULONG ulFsControlCode;
913 ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
915 ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
916 ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
918 switch( ulFsControlCode)
921 case FSCTL_PIPE_TRANSCEIVE:
924 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
925 AFS_TRACE_LEVEL_VERBOSE,
926 "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n",
927 &Ccb->DirectoryCB->NameInformation.FileName);
929 ntStatus = AFSNotifyPipeTransceive( Ccb,
932 pIrpSp->Parameters.FileSystemControl.Type3InputBuffer,
934 (ULONG *)&Irp->IoStatus.Information);
936 if( !NT_SUCCESS( ntStatus))
939 AFSDbgLogMsg( AFS_SUBSYSTEM_PIPE_PROCESSING,
940 AFS_TRACE_LEVEL_VERBOSE,
941 "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n",
942 &Ccb->DirectoryCB->NameInformation.FileName,
952 AFSPrint( "AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n",