Windows: Obtain File Attribs for DFS Link target
authorpete scott <pscott@kerneldrivers.com>
Wed, 13 Aug 2014 19:28:49 +0000 (15:28 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Wed, 20 Aug 2014 16:54:09 +0000 (12:54 -0400)
The AFSRetrieveFileAttributes() function is used to acquire the
attributes for an AFS symlink.  The result is either returned directly
to the application or used internally to determine the attributes
to be exposed by reparse points.

If the evaluated symlink crosses a DFS Link the redirector cannot
return the request to IO Manager to evaluate the target.  Instead
the redirector must handle the request internally and attempt to
read the attributes of the target object.

Change-Id: If14df8dc41e13fd59b524fdb575c46abab1dfc2f
Reviewed-on: http://gerrit.openafs.org/11399
Reviewed-by: Peter Scott <pscott@kerneldrivers.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp
src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp
src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp
src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h

index 71d18fb..9ce2635 100644 (file)
@@ -464,7 +464,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                                               &NewVolumeReferenceReason,
                                               &pNewParentDirectoryCB,
                                               &pDirectoryCB,
-                                              &uniComponentName);
+                                              &uniComponentName,
+                                              NULL);
 
                if ( pNewVolumeCB != NULL)
                {
@@ -697,7 +698,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                                               &NewVolumeReferenceReason,
                                               &pNewParentDirectoryCB,
                                               &pDirectoryCB,
-                                              &uniComponentName);
+                                              &uniComponentName,
+                                              NULL);
 
                if ( ntStatus == STATUS_SUCCESS ||
                     ntStatus == STATUS_OBJECT_NAME_NOT_FOUND ||
@@ -815,7 +817,8 @@ AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
                                                       &NewVolumeReferenceReason,
                                                       &pNewParentDirectoryCB,
                                                       &pDirectoryCB,
-                                                      &uniComponentName);
+                                                      &uniComponentName,
+                                                      NULL);
                    }
                }
                else
index abf4bfd..ffb96c4 100644 (file)
@@ -5683,11 +5683,16 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
     ULONG ulNameDifference = 0;
     LONG lCount;
+    UNICODE_STRING uniDFSTargetName;
 
     __Enter
     {
 
-        //
+       uniDFSTargetName.Length = 0;
+       uniDFSTargetName.MaximumLength = 0;
+       uniDFSTargetName.Buffer = NULL;
+
+       //
         // Retrieve a target name for the entry
         //
 
@@ -5964,7 +5969,8 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
                                        &NewVolumeReferenceReason,
                                        &pNewParentDirEntry,
                                        &pDirectoryEntry,
-                                       NULL);
+                                       NULL,
+                                      &uniDFSTargetName);
 
         if ( pNewVolumeCB != NULL)
         {
@@ -6014,10 +6020,21 @@ AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
 
         pNewParentDirEntry = NULL;
 
-        if( !NT_SUCCESS( ntStatus) ||
-            ntStatus == STATUS_REPARSE)
+       if( !NT_SUCCESS( ntStatus))
+       {
+           try_return( ntStatus);
+       }
+
+       //
+       // If the status is STATUS_REPARSE then attempt to retrieve the attributes from the target name returned
+       //
+
+       if( ntStatus == STATUS_REPARSE)
         {
 
+           ntStatus = AFSRetrieveTargetFileInfo( &uniDFSTargetName,
+                                                 FileInfo);
+
             try_return( ntStatus);
         }
 
@@ -6144,6 +6161,13 @@ try_exit:
 
             AFSExFreePoolWithTag( pwchBuffer, 0);
         }
+
+       if ( uniDFSTargetName.Buffer != NULL)
+       {
+
+           AFSExFreePoolWithTag( uniDFSTargetName.Buffer,
+                                 AFS_REPARSE_NAME_TAG);
+       }
     }
 
     return ntStatus;
@@ -6808,7 +6832,8 @@ AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
                                        &VolumeReferenceReason,
                                        &pNewParentDirEntry,
                                        &pDirectoryEntry,
-                                       NULL);
+                                       NULL,
+                                      NULL);
 
         if ( pNewVolumeCB != NULL)
         {
@@ -8402,7 +8427,8 @@ AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
                                            &NewVolumeReferenceReason,
                                            &pNewParentDirEntry,
                                            &pDirectoryEntry,
-                                           NULL);
+                                           NULL,
+                                          NULL);
 
             if ( pNewVolumeCB != NULL)
             {
@@ -9901,3 +9927,78 @@ AFSIgnoreReparsePointToFile( void)
 
     return bIgnoreReparsePoint;
 }
+
+NTSTATUS
+AFSRetrieveTargetFileInfo( IN PUNICODE_STRING TargetName,
+                          OUT AFSFileInfoCB *FileInfo)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    OBJECT_ATTRIBUTES stObjectAttribs;
+    HANDLE hFile = NULL;
+    IO_STATUS_BLOCK stIoStatus;
+    FILE_NETWORK_OPEN_INFORMATION stFileInfo;
+
+    __Enter
+    {
+
+       InitializeObjectAttributes( &stObjectAttribs,
+                                   TargetName,
+                                   OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+
+       ntStatus = ZwCreateFile( &hFile,
+                                FILE_READ_ATTRIBUTES,
+                                &stObjectAttribs,
+                                &stIoStatus,
+                                NULL,
+                                0,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                FILE_OPEN,
+                                FILE_SYNCHRONOUS_IO_NONALERT,
+                                NULL,
+                                0);
+
+       if( !NT_SUCCESS( ntStatus))
+       {
+
+           try_return( ntStatus);
+       }
+
+       ntStatus = ZwQueryInformationFile( hFile,
+                                          &stIoStatus,
+                                          &stFileInfo,
+                                          sizeof( FILE_NETWORK_OPEN_INFORMATION),
+                                          FileNetworkOpenInformation);
+
+       if( !NT_SUCCESS( ntStatus))
+       {
+
+           try_return( ntStatus);
+       }
+
+       FileInfo->FileAttributes = stFileInfo.FileAttributes;
+
+       FileInfo->AllocationSize = stFileInfo.AllocationSize;
+
+       FileInfo->EndOfFile = stFileInfo.EndOfFile;
+
+       FileInfo->CreationTime = stFileInfo.CreationTime;
+
+       FileInfo->LastAccessTime = stFileInfo.LastAccessTime;
+
+       FileInfo->LastWriteTime = stFileInfo.LastWriteTime;
+
+       FileInfo->ChangeTime = stFileInfo.ChangeTime;
+
+try_exit:
+
+       if( hFile != NULL)
+       {
+           ZwClose( hFile);
+       }
+    }
+
+    return ntStatus;
+}
index bf78512..7a70e1a 100644 (file)
@@ -65,7 +65,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                     OUT LONG *OutVolumeReferenceReason,
                     OUT AFSDirectoryCB **OutParentDirectoryCB,
                     OUT AFSDirectoryCB **OutDirectoryCB,
-                    OUT PUNICODE_STRING ComponentName)
+                    OUT PUNICODE_STRING ComponentName,
+                   OUT PUNICODE_STRING TargetName)
 {
 
     NTSTATUS          ntStatus = STATUS_SUCCESS;
@@ -1154,13 +1155,15 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                     // system for it to reevaluate it
                     //
 
-                    if( FileObject != NULL)
+                    if( FileObject != NULL ||
+                       TargetName != NULL)
                     {
 
                         ntStatus = AFSProcessDFSLink( pDirEntry,
                                                       FileObject,
                                                       &uniRemainingPath,
-                                                      AuthGroup);
+                                                      AuthGroup,
+                                                     TargetName);
                     }
                     else
                     {
@@ -4992,7 +4995,8 @@ NTSTATUS
 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
                    IN PFILE_OBJECT FileObject,
                    IN UNICODE_STRING *RemainingPath,
-                   IN GUID *AuthGroup)
+                   IN GUID *AuthGroup,
+                  OUT PUNICODE_STRING TargetName)
 {
 
     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
@@ -5004,7 +5008,14 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
     __Enter
     {
 
-        //
+       if ( FileObject != NULL && TargetName != NULL ||
+            FileObject == NULL && TargetName == NULL)
+       {
+
+           try_return( ntStatus = STATUS_INVALID_PARAMETER);
+       }
+
+       //
         // Build up the name to reparse
         //
 
@@ -5103,8 +5114,8 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
         }
 
         //
-        // Allocate the reparse buffer
-        //
+       // Allocate the reparse buffer (from FS because might be returned in FileObject)
+       //
 
         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
                                                                    uniReparseName.MaximumLength,
@@ -5188,17 +5199,29 @@ AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
             uniReparseName.Length += RemainingPath->Length;
         }
 
-        //
-        // Update the name in the file object
-        //
-
-        if( FileObject->FileName.Buffer != NULL)
+       if( FileObject != NULL)
         {
+           //
+           // Update the name in the file object
+           //
+
+           if( FileObject->FileName.Buffer != NULL)
+           {
 
-            AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
+               //
+               // original FileObject buffer was not allocated by AFS
+               //
+
+               ExFreePoolWithTag( FileObject->FileName.Buffer, 0);
+           }
+
+           FileObject->FileName = uniReparseName;
         }
+       else
+       {
 
-        FileObject->FileName = uniReparseName;
+           *TargetName = uniReparseName;
+       }
 
         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
index 0725527..f853960 100644 (file)
@@ -574,7 +574,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                     OUT LONG *OutVolumeReferenceReason,
                     OUT AFSDirectoryCB **OutParentDirectoryCB,
                     OUT AFSDirectoryCB **OutDirectoryCB,
-                    OUT PUNICODE_STRING ComponentName);
+                    OUT PUNICODE_STRING ComponentName,
+                   OUT PUNICODE_STRING TargetName);
 
 NTSTATUS
 AFSCreateDirEntry( IN GUID            *AuthGroup,
@@ -632,8 +633,9 @@ AFSBuildRootVolume( IN GUID *AuthGroup,
 NTSTATUS
 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
                    IN PFILE_OBJECT FileObject,
-                   IN UNICODE_STRING *RemainingPath,
-                   IN GUID *AuthGroup);
+                   IN PUNICODE_STRING RemainingPath,
+                   IN GUID *AuthGroup,
+                  OUT PUNICODE_STRING TargetName);
 
 //
 // AFSNetworkProviderSupport.cpp
@@ -1456,6 +1458,10 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
 BOOLEAN
 AFSIgnoreReparsePointToFile( void);
 
+NTSTATUS
+AFSRetrieveTargetFileInfo( IN PUNICODE_STRING TargetName,
+                          OUT AFSFileInfoCB *FileInfo);
+
 //
 // AFSNameArray.cpp Prototypes
 //