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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 AFSDbgTrace(( 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 REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
323 ULONG ulRemainingLen = ulOutputBufferLen;
324 AFSReparseTagInfo *pReparseInfo = NULL;
325 BOOLEAN bRelative = FALSE;
326 BOOLEAN bDriveLetter = FALSE;
327 WCHAR * PathBuffer = NULL;
329 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
330 AFS_TRACE_LEVEL_VERBOSE_2,
331 "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
332 &pCcb->DirectoryCB->NameInformation.FileName,
333 pFcb->ObjectInformation->FileType,
334 pFcb->ObjectInformation->FileAttributes));
337 // Check if we have the reparse entry set on the entry
340 if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
343 ntStatus = STATUS_NOT_A_REPARSE_POINT;
349 switch ( pFcb->ObjectInformation->FileType) {
350 case AFS_FILE_TYPE_MOUNTPOINT:
352 if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
355 ntStatus = STATUS_BUFFER_TOO_SMALL;
357 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
362 ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
368 if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
371 ntStatus = STATUS_BUFFER_TOO_SMALL;
373 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
378 ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
384 // Populate the data in the reparse buffer
387 pReparseBuffer->ReparseDataLength = 0;
389 AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
392 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
396 // We'll reset the DV to ensure we validate the metadata content
399 pFcb->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
401 SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
403 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
404 AFS_TRACE_LEVEL_VERBOSE,
405 "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
406 &pCcb->DirectoryCB->NameInformation.FileName,
407 pFcb->ObjectInformation->FileId.Cell,
408 pFcb->ObjectInformation->FileId.Volume,
409 pFcb->ObjectInformation->FileId.Vnode,
410 pFcb->ObjectInformation->FileId.Unique));
412 ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
416 if( !NT_SUCCESS( ntStatus))
419 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
420 AFS_TRACE_LEVEL_ERROR,
421 "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
422 &pCcb->DirectoryCB->NameInformation.FileName,
423 pFcb->ObjectInformation->FileId.Cell,
424 pFcb->ObjectInformation->FileId.Volume,
425 pFcb->ObjectInformation->FileId.Vnode,
426 pFcb->ObjectInformation->FileId.Unique,
429 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
435 pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];
437 switch( pFcb->ObjectInformation->FileType)
440 case AFS_FILE_TYPE_SYMLINK:
443 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
446 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
451 bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
456 if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
457 pCcb->DirectoryCB->NameInformation.TargetName.Length)
460 ntStatus = STATUS_BUFFER_TOO_SMALL;
462 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
463 pCcb->DirectoryCB->NameInformation.TargetName.Length;
468 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
470 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
471 pCcb->DirectoryCB->NameInformation.TargetName.Length;
473 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
474 pCcb->DirectoryCB->NameInformation.TargetName.Length;
476 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
478 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
480 PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
482 RtlCopyMemory( PathBuffer,
483 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
484 pCcb->DirectoryCB->NameInformation.TargetName.Length);
486 pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
487 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
488 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
493 if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
495 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
496 /* Substitute Name */
497 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
500 ntStatus = STATUS_BUFFER_TOO_SMALL;
502 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
503 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
504 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
509 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
511 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
512 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
514 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
515 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);
517 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
518 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
520 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
522 PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
525 *PathBuffer++ = L'\\';
527 RtlCopyMemory( PathBuffer,
528 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
529 pCcb->DirectoryCB->NameInformation.TargetName.Length);
531 PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
533 /* Substitute Name */
534 *PathBuffer++ = L'\\';
535 *PathBuffer++ = L'?';
536 *PathBuffer++ = L'?';
537 *PathBuffer++ = L'\\';
538 *PathBuffer++ = L'U';
539 *PathBuffer++ = L'N';
540 *PathBuffer++ = L'C';
542 RtlCopyMemory( PathBuffer,
543 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
544 pCcb->DirectoryCB->NameInformation.TargetName.Length);
546 pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
547 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
548 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
549 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
555 case AFS_FILE_TYPE_MOUNTPOINT:
557 UNICODE_STRING Cell, Volume;
560 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
562 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
567 if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
572 ntStatus = STATUS_INVALID_PARAMETER;
577 if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
580 ntStatus = STATUS_BUFFER_TOO_SMALL;
582 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
583 FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
584 Volume.Length + Cell.Length;
589 pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;
591 pReparseInfo->AFSMountPoint.Type = Type;
593 pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;
595 pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;
597 RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
601 RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
605 pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);
610 case AFS_FILE_TYPE_DFSLINK:
613 if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
616 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
621 bRelative = ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\');
623 bDriveLetter = (bRelative == FALSE && pCcb->DirectoryCB->NameInformation.TargetName.Buffer[1] == L':');
628 if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
629 pCcb->DirectoryCB->NameInformation.TargetName.Length)
632 ntStatus = STATUS_BUFFER_TOO_SMALL;
634 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
635 pCcb->DirectoryCB->NameInformation.TargetName.Length;
640 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
642 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
643 pCcb->DirectoryCB->NameInformation.TargetName.Length;
645 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
646 pCcb->DirectoryCB->NameInformation.TargetName.Length;
648 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
650 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
652 PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
654 RtlCopyMemory( PathBuffer,
655 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
656 pCcb->DirectoryCB->NameInformation.TargetName.Length);
658 pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
659 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
660 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
662 else if ( bDriveLetter)
665 if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
667 pCcb->DirectoryCB->NameInformation.TargetName.Length +
668 /* Substitute Name */
669 pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR))
672 ntStatus = STATUS_BUFFER_TOO_SMALL;
674 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
675 pCcb->DirectoryCB->NameInformation.TargetName.Length +
676 pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);
681 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
683 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
684 pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);
686 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
687 pCcb->DirectoryCB->NameInformation.TargetName.Length;
689 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
690 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
692 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
694 PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
697 RtlCopyMemory( PathBuffer,
698 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
699 pCcb->DirectoryCB->NameInformation.TargetName.Length);
701 PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
703 /* Substitute Name */
704 *PathBuffer++ = L'\\';
705 *PathBuffer++ = L'?';
706 *PathBuffer++ = L'?';
707 *PathBuffer++ = L'\\';
709 RtlCopyMemory( PathBuffer,
710 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
711 pCcb->DirectoryCB->NameInformation.TargetName.Length);
713 pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
714 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
715 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
716 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
721 if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
723 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
724 /* Substitute Name */
725 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
728 ntStatus = STATUS_BUFFER_TOO_SMALL;
730 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
731 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
732 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
737 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
739 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
740 pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);
742 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
743 pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);
745 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
746 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;
748 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
750 PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
753 *PathBuffer++ = L'\\';
755 RtlCopyMemory( PathBuffer,
756 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
757 pCcb->DirectoryCB->NameInformation.TargetName.Length);
759 PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);
761 /* Substitute Name */
762 *PathBuffer++ = L'\\';
763 *PathBuffer++ = L'?';
764 *PathBuffer++ = L'?';
765 *PathBuffer++ = L'\\';
766 *PathBuffer++ = L'U';
767 *PathBuffer++ = L'N';
768 *PathBuffer++ = L'C';
770 RtlCopyMemory( PathBuffer,
771 pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
772 pCcb->DirectoryCB->NameInformation.TargetName.Length);
774 pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
775 FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
776 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
777 pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
785 ntStatus = STATUS_NOT_A_REPARSE_POINT;
790 if ( ntStatus == STATUS_SUCCESS)
793 ulRemainingLen -= pReparseBuffer->ReparseDataLength;
795 if ( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
798 pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
800 RtlCopyMemory( &pReparseBuffer->ReparseGuid,
801 &GUID_AFS_REPARSE_GUID,
804 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
805 + pReparseBuffer->ReparseDataLength;
810 pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
812 Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
813 + pReparseBuffer->ReparseDataLength;
817 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
822 case FSCTL_SET_REPARSE_POINT:
825 REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
826 REPARSE_DATA_BUFFER *pReparseBuffer = NULL;
827 AFSReparseTagInfo *pReparseInfo = NULL;
828 AFSObjectInfoCB *pParentObjectInfo = NULL;
829 UNICODE_STRING uniTargetName;
830 ULONGLONG ullIndex = 0;
833 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
834 AFS_TRACE_LEVEL_VERBOSE,
835 "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
836 &pCcb->DirectoryCB->NameInformation.FileName,
837 pFcb->ObjectInformation->FileType,
838 pFcb->ObjectInformation->FileAttributes));
840 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
843 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
848 if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS)
851 if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid,
852 &GUID_AFS_REPARSE_GUID,
853 sizeof( GUID)) != sizeof( GUID))
856 ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
861 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
862 sizeof( AFSReparseTagInfo))
865 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
870 pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer;
872 switch( pReparseInfo->SubTag)
875 case OPENAFS_SUBTAG_SYMLINK:
878 if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
879 FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
880 pReparseInfo->AFSSymLink.SymLinkTargetLength))
883 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
888 uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength;
889 uniTargetName.MaximumLength = uniTargetName.Length;
891 uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer;
896 case OPENAFS_SUBTAG_UNC:
899 if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
900 FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
901 pReparseInfo->UNCReferral.UNCTargetLength))
904 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
909 uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength;
910 uniTargetName.MaximumLength = uniTargetName.Length;
912 uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer;
917 case OPENAFS_SUBTAG_MOUNTPOINT:
924 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
933 // Handle Microsoft Reparse Tags
936 switch( pReparseGUIDBuffer->ReparseTag)
939 case IO_REPARSE_TAG_MOUNT_POINT:
942 pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
944 uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength;
945 uniTargetName.MaximumLength = uniTargetName.Length;
947 uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer +
948 pReparseBuffer->MountPointReparseBuffer.PrintNameOffset);
950 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
951 AFS_TRACE_LEVEL_VERBOSE_2,
952 "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n",
955 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
960 case IO_REPARSE_TAG_SYMLINK:
963 pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
965 uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
966 uniTargetName.MaximumLength = uniTargetName.Length;
968 uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer +
969 pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset);
971 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
972 AFS_TRACE_LEVEL_VERBOSE_2,
973 "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n",
981 ntStatus = STATUS_IO_REPARSE_DATA_INVALID;
988 if( !NT_SUCCESS( ntStatus))
995 // First thing is to locate/create our object information block
999 AFSAcquireExcl( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
1002 if ( AFSIsVolumeFID( &pFcb->ObjectInformation->ParentFileId))
1005 pParentObjectInfo = &pFcb->ObjectInformation->VolumeCB->ObjectInformation;
1009 ullIndex = AFSCreateLowIndex( &pFcb->ObjectInformation->ParentFileId);
1011 ntStatus = AFSLocateHashEntry( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead,
1013 (AFSBTreeEntry **)&pParentObjectInfo);
1016 if ( NT_SUCCESS( ntStatus))
1019 lCount = AFSObjectInfoIncrement( pParentObjectInfo,
1020 AFS_OBJECT_REFERENCE_FS_REQ);
1022 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1023 AFS_TRACE_LEVEL_VERBOSE,
1024 "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n",
1028 KeQueryTickCount( &pParentObjectInfo->LastAccessCount);
1031 AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
1033 if ( NT_SUCCESS( ntStatus))
1037 // Extract out the information to the call to the service
1040 ntStatus = AFSCreateSymlink( &pCcb->AuthGroup,
1042 &pCcb->DirectoryCB->NameInformation.FileName,
1043 pFcb->ObjectInformation,
1046 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1047 AFS_TRACE_LEVEL_VERBOSE_2,
1048 "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n",
1049 &pCcb->DirectoryCB->NameInformation.FileName,
1050 pFcb->ObjectInformation->FileType,
1051 pFcb->ObjectInformation->FileAttributes,
1054 AFSAcquireShared( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
1057 lCount = AFSObjectInfoDecrement( pParentObjectInfo,
1058 AFS_OBJECT_REFERENCE_FS_REQ);
1060 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1061 AFS_TRACE_LEVEL_VERBOSE,
1062 "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n",
1066 AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
1072 case FSCTL_DELETE_REPARSE_POINT:
1075 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
1077 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1078 AFS_TRACE_LEVEL_VERBOSE_2,
1079 "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
1080 &pCcb->DirectoryCB->NameInformation.FileName,
1081 pFcb->ObjectInformation->FileType,
1082 pFcb->ObjectInformation->FileAttributes));
1085 // Check if we have the reparse entry set on the entry
1088 if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1091 ntStatus = STATUS_NOT_A_REPARSE_POINT;
1096 if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
1099 ntStatus = STATUS_INVALID_PARAMETER;
1104 if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
1107 ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;
1112 if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
1113 &GUID_AFS_REPARSE_GUID,
1114 sizeof( GUID)) != sizeof( GUID))
1117 ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
1123 // Claim success. The typical usage is setting delete on close
1124 // as the next operation on the reparse point before closing
1128 ntStatus = STATUS_SUCCESS;
1133 #ifndef FSCTL_SET_PURGE_FAILURE_MODE
1134 #define FSCTL_SET_PURGE_FAILURE_MODE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS)
1137 case FSCTL_SET_PURGE_FAILURE_MODE:
1141 // For the time being just succeed this call
1144 ntStatus = STATUS_SUCCESS;
1152 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1153 AFS_TRACE_LEVEL_VERBOSE_2,
1154 "AFSProcessUserFsRequest Processing default (%08lX) request\n",
1157 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1172 AFSProcessShareFsCtrl( IN IRP *Irp,
1177 UNREFERENCED_PARAMETER(Fcb);
1178 NTSTATUS ntStatus = STATUS_SUCCESS;
1179 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1180 ULONG ulOutputBufferLen = 0, ulInputBufferLen;
1181 ULONG ulFsControlCode;
1186 ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;
1188 ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
1189 ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;
1191 switch( ulFsControlCode)
1194 case FSCTL_PIPE_TRANSCEIVE:
1197 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1198 AFS_TRACE_LEVEL_VERBOSE,
1199 "AFSProcessShareFsCtrl On pipe %wZ Class FSCTL_PIPE_TRANSCEIVE\n",
1200 &Ccb->DirectoryCB->NameInformation.FileName));
1202 ntStatus = AFSNotifyPipeTransceive( Ccb,
1205 pIrpSp->Parameters.FileSystemControl.Type3InputBuffer,
1207 (ULONG *)&Irp->IoStatus.Information);
1209 if( !NT_SUCCESS( ntStatus))
1212 AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1213 AFS_TRACE_LEVEL_VERBOSE,
1214 "AFSProcessShareFsCtrl Failure on pipe %wZ Class FSCTL_PIPE_TRANSCEIVE Status %08lX\n",
1215 &Ccb->DirectoryCB->NameInformation.FileName,
1225 AFSPrint( "AFSProcessShareFsCtrl (%08lX) For IPC$ input %08lX output %08lX\n",