Windows: Use Microsoft IO_REPARSE_TAG_SYMLINK tag
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 8 Mar 2013 06:41:22 +0000 (01:41 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Tue, 12 Mar 2013 00:47:10 +0000 (17:47 -0700)
For symlinks and DFS Links use Microsoft's NTFS Symlink tag,
IO_REPARSE_TAG_SYMLINK, instead of the OpenAFS assigned tag.

The DeleteFile() and RemoveDirectory() Win32 APIs do not delete
non-Microsoft reparse points and instead delete the target object.
While it is possible for Take Command and potentially Cygwin to
alter their behavior with AFS specific knowlege, it is not possible
to alter the Explorer Shell, cmd.exe and powershell.

Using the Microsoft tag is a violation of Microsoft policy.

Change-Id: I90a419fe21637bb871d08528463d1178078a9947
Reviewed-on: http://gerrit.openafs.org/9497
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp
src/WINNT/afsrdr/kernel/lib/AFSFileInfo.cpp

index ec0acf5..9950fa1 100644 (file)
@@ -160,7 +160,6 @@ AFSProcessUserFsRequest( IN PIRP Irp)
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
     AFSCcb *pCcb = NULL;
     ULONG ulOutputBufferLen, ulInputBufferLen;
-    BOOLEAN bRelative = FALSE;
 
     __Enter
     {
@@ -320,8 +319,11 @@ AFSProcessUserFsRequest( IN PIRP Irp)
             {
 
                 REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
+                REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
                 ULONG ulRemainingLen = ulOutputBufferLen;
                 AFSReparseTagInfo *pReparseInfo = NULL;
+                BOOLEAN bRelative = FALSE;
+                WCHAR * PathBuffer = NULL;
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE_2,
@@ -342,17 +344,40 @@ AFSProcessUserFsRequest( IN PIRP Irp)
                     break;
                 }
 
-                if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
-                {
 
-                    ntStatus = STATUS_BUFFER_TOO_SMALL;
+                switch ( pCcb->DirectoryCB->ObjectInformation->FileType) {
+                case AFS_FILE_TYPE_MOUNTPOINT:
+
+                    if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
+                    {
+
+                        ntStatus = STATUS_BUFFER_TOO_SMALL;
+
+                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
 
-                    Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+                        break;
+                    }
+
+                    ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
 
                     break;
-                }
 
-                ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+                default:
+
+                    if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
+                    {
+
+                        ntStatus = STATUS_BUFFER_TOO_SMALL;
+
+                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+
+                        break;
+                    }
+
+                    ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);
+
+                    break;
+                }
 
                 //
                 // Populate the data in the reparse buffer
@@ -423,47 +448,56 @@ AFSProcessUserFsRequest( IN PIRP Irp)
 
                         bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);
 
-                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
+                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                             pCcb->DirectoryCB->NameInformation.TargetName.Length + (bRelative ? 0 : sizeof( WCHAR)))
                         {
 
                             ntStatus = STATUS_BUFFER_TOO_SMALL;
 
-                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
-                                                        FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
-                                                        pCcb->DirectoryCB->NameInformation.TargetName.Length +
-                                                        (bRelative ? 0 : sizeof( WCHAR));
+                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
+                                pCcb->DirectoryCB->NameInformation.TargetName.Length + (bRelative ? 0 : sizeof( WCHAR));
 
                             break;
                         }
 
-                        pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK;
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = (bRelative ? SYMLINK_FLAG_RELATIVE : 0);
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
+                            pCcb->DirectoryCB->NameInformation.TargetName.Length;
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
+                            pCcb->DirectoryCB->NameInformation.TargetName.Length;
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
 
-                        pReparseInfo->AFSSymLink.RelativeLink = bRelative;
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
 
-                        pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
+                        PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
 
-                        if ( pReparseInfo->AFSSymLink.RelativeLink == FALSE)
+                        if ( bRelative == FALSE)
                         {
 
-                            pReparseInfo->AFSSymLink.Buffer[0] = L'\\';
+                            *PathBuffer++ = L'\\';
 
-                            RtlCopyMemory( &pReparseInfo->AFSSymLink.Buffer[ 1],
+                            RtlCopyMemory( PathBuffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
 
-                            pReparseInfo->AFSSymLink.SymLinkTargetLength += sizeof( WCHAR);
+                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength += sizeof( WCHAR);
+
+                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength += sizeof( WCHAR);
                         }
                         else
                         {
 
-                            RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer,
+                            RtlCopyMemory( PathBuffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
                         }
 
-                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer)
-                                                              + pReparseInfo->AFSSymLink.SymLinkTargetLength);
+                        pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer)
+                            - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
+                            + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
 
                         break;
                     }
@@ -534,46 +568,58 @@ AFSProcessUserFsRequest( IN PIRP Irp)
                             break;
                         }
 
-                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
+                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                             pCcb->DirectoryCB->NameInformation.TargetName.Length +
                             (pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\' ? sizeof( WCHAR) : 0))
                         {
 
                             ntStatus = STATUS_BUFFER_TOO_SMALL;
 
-                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
-                                                        FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
-                                                        pCcb->DirectoryCB->NameInformation.TargetName.Length +
-                                                        (pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\' ? sizeof( WCHAR) : 0);
+                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
+                                pCcb->DirectoryCB->NameInformation.TargetName.Length +
+                                (pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\' ? sizeof( WCHAR) : 0);
 
                             break;
                         }
 
-                        pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC;
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
+                            pCcb->DirectoryCB->NameInformation.TargetName.Length;
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
+                            pCcb->DirectoryCB->NameInformation.TargetName.Length;
+
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
 
-                        pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;
+                        pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
+
+                        PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;
 
                         if ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\')
                         {
 
-                            pReparseInfo->UNCReferral.Buffer[0] = L'\\';
+                            *PathBuffer++ = L'\\';
 
-                            RtlCopyMemory( &pReparseInfo->UNCReferral.Buffer[ 1],
+                            RtlCopyMemory( PathBuffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
 
-                            pReparseInfo->UNCReferral.UNCTargetLength += sizeof( WCHAR);
+                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength += sizeof( WCHAR);
+
+                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength += sizeof( WCHAR);
                         }
                         else
                         {
 
-                            RtlCopyMemory( pReparseInfo->UNCReferral.Buffer,
+                            RtlCopyMemory( PathBuffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                            pCcb->DirectoryCB->NameInformation.TargetName.Length);
                         }
 
-                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer)
-                                                              + pReparseInfo->UNCReferral.UNCTargetLength);
+                        pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer)
+                            - FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
+                            + pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
 
                         break;
                     }
@@ -590,14 +636,26 @@ AFSProcessUserFsRequest( IN PIRP Irp)
 
                     ulRemainingLen -= pReparseBuffer->ReparseDataLength;
 
-                    pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
+                    if ( pCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
+                    {
 
-                    RtlCopyMemory( &pReparseBuffer->ReparseGuid,
-                                   &GUID_AFS_REPARSE_GUID,
-                                   sizeof( GUID));
+                        pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
 
-                    Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
-                                                              pReparseBuffer->ReparseDataLength;
+                        RtlCopyMemory( &pReparseBuffer->ReparseGuid,
+                                       &GUID_AFS_REPARSE_GUID,
+                                       sizeof( GUID));
+
+                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
+                            + pReparseBuffer->ReparseDataLength;
+                    }
+                    else
+                    {
+
+                        pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
+
+                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
+                            + pReparseBuffer->ReparseDataLength;
+                    }
                 }
 
                 AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);
index 75de0a3..e1f3d99 100644 (file)
@@ -1724,10 +1724,16 @@ AFSQueryAttribTagInfo( IN PIRP Irp,
             }
         }
 
-        if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
+        if ( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
         {
+
             Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
         }
+        else if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
+        {
+
+            Buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
+        }
 
         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);