Windows: Remove trailing slash on non-root directories
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNameSupport.cpp
index 18c8a3d..6448ded 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;
@@ -258,7 +259,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                                 TRUE);
 
                 ntStatus = AFSVerifyEntry( AuthGroup,
-                                           pDirEntry);
+                                          pDirEntry,
+                                          FALSE);
 
                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
@@ -438,7 +440,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                         //
 
                         ntStatus = AFSVerifyEntry( AuthGroup,
-                                                   pDirEntry);
+                                                  pDirEntry,
+                                                  FALSE);
 
                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
@@ -641,6 +644,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                         pDirEntry = AFSBackupEntry( pNameArray);
 
+                        pCurrentObject = pDirEntry->ObjectInformation;
+
                         //
                         // Increment our reference on this dir entry
                         //
@@ -894,6 +899,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                         pDirEntry = pCurrentVolume->DirectoryCB;
 
+                        pCurrentObject = pDirEntry->ObjectInformation;
+
                         //
                         // Reference the new dir entry
                         //
@@ -1068,6 +1075,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                     pDirEntry = pCurrentVolume->DirectoryCB;
 
+                    pCurrentObject = pDirEntry->ObjectInformation;
+
                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
 
                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
@@ -1114,7 +1123,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                 case AFS_FILE_TYPE_DFSLINK:
                 {
 
-                    if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
+                   if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL) &&
+                       uniRemainingPath.Length == 0)
                     {
 
                         //
@@ -1145,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
                     {
@@ -1432,6 +1444,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
                 }
 
+                pCurrentObject = pDirEntry->ObjectInformation;
+
                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
 
                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
@@ -1535,6 +1549,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
             pDirEntry = NULL;
 
+            pCurrentObject = NULL;
+
             uniSearchName = uniComponentName;
 
             while( pDirEntry == NULL)
@@ -1749,13 +1765,13 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                               AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                                              "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
                                               FileObject,
                                               &uniSearchName,
-                                              pCurrentObject->FileId.Cell,
-                                              pCurrentObject->FileId.Volume,
-                                              pCurrentObject->FileId.Vnode,
-                                              pCurrentObject->FileId.Unique));
+                                              pParentDirEntry->ObjectInformation->FileId.Cell,
+                                              pParentDirEntry->ObjectInformation->FileId.Volume,
+                                              pParentDirEntry->ObjectInformation->FileId.Vnode,
+                                              pParentDirEntry->ObjectInformation->FileId.Unique));
                             }
                             else
                             {
@@ -1764,13 +1780,13 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                               AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                                              "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
                                               FileObject,
                                               &uniSearchName,
-                                              pCurrentObject->FileId.Cell,
-                                              pCurrentObject->FileId.Volume,
-                                              pCurrentObject->FileId.Vnode,
-                                              pCurrentObject->FileId.Unique));
+                                              pParentDirEntry->ObjectInformation->FileId.Cell,
+                                              pParentDirEntry->ObjectInformation->FileId.Volume,
+                                              pParentDirEntry->ObjectInformation->FileId.Vnode,
+                                              pParentDirEntry->ObjectInformation->FileId.Unique));
 
                                 //
                                 // Pass back the directory entries
@@ -1808,6 +1824,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                         // Is more than one link entry for this node then fail the lookup request
                         //
 
+                        pCurrentObject = pDirEntry->ObjectInformation;
+
                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
                             pDirEntry->CaseInsensitiveList.fLink != NULL)
                         {
@@ -1841,6 +1859,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                     // revalidate the parent and search again.
                     //
 
+                    pCurrentObject = pDirEntry->ObjectInformation;
+
                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
                     {
@@ -1865,7 +1885,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                                         TRUE);
 
                         ntStatus = AFSVerifyEntry( AuthGroup,
-                                                   pParentDirEntry);
+                                                  pParentDirEntry,
+                                                  FALSE);
 
                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
@@ -1896,6 +1917,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                         pDirEntry = NULL;
 
+                        pCurrentObject = NULL;
+
                         continue;
                     }
 
@@ -1922,175 +1945,180 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
             // If we have a dirEntry for this component, perform some basic validation on it
             //
 
-            if( pDirEntry != NULL &&
-                BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
+            if( pDirEntry != NULL)
             {
 
                 pCurrentObject = pDirEntry->ObjectInformation;
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
-                              FileObject,
-                              &pDirEntry->NameInformation.FileName,
-                              pCurrentObject->FileId.Cell,
-                              pCurrentObject->FileId.Volume,
-                              pCurrentObject->FileId.Vnode,
-                              pCurrentObject->FileId.Unique));
-
-                //
-                // This entry was deleted through the invalidation call back so perform cleanup
-                // on the entry
-                //
-
-                if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
+                if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
                 {
 
-                    pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
-                                                           &pCurrentObject->ParentFileId,
-                                                           FALSE);
-                }
+                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                                  FileObject,
+                                  &pDirEntry->NameInformation.FileName,
+                                  pCurrentObject->FileId.Cell,
+                                  pCurrentObject->FileId.Volume,
+                                  pCurrentObject->FileId.Vnode,
+                                  pCurrentObject->FileId.Unique));
 
-                ASSERT( pParentObjectInfo != NULL);
+                    //
+                    // This entry was deleted through the invalidation call back so perform cleanup
+                    // on the entry
+                    //
 
-                AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                TRUE);
+                    if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
+                    {
 
-                AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
-                                TRUE);
+                        pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
+                                                               &pCurrentObject->ParentFileId,
+                                                               FALSE);
+                    }
 
-                lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
+                    ASSERT( pParentObjectInfo != NULL);
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
-                              &pDirEntry->NameInformation.FileName,
-                              pDirEntry,
-                              NULL,
-                              lCount));
+                    AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                    TRUE);
 
-                ASSERT( lCount >= 0);
+                    AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
+                                    TRUE);
 
-                if( lCount == 0 &&
-                    pDirEntry->NameArrayReferenceCount <= 0)
-                {
+                    lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                    AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                   AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
+                                  "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pDirEntry->NameInformation.FileName,
                                   pDirEntry,
-                                  pCurrentObject,
-                                  &pDirEntry->NameInformation.FileName));
+                                  NULL,
+                                  lCount));
 
-                    //
-                    // Remove and delete the directory entry from the parent list
-                    //
+                    ASSERT( lCount >= 0);
 
-                    AFSDeleteDirEntry( pParentObjectInfo,
-                                       &pDirEntry);
+                    if( lCount == 0 &&
+                        pDirEntry->NameArrayReferenceCount <= 0)
+                    {
 
-                    AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
-                                      TRUE);
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
+                                      pDirEntry,
+                                      pCurrentObject,
+                                      &pDirEntry->NameInformation.FileName));
 
-                    if( pCurrentObject->ObjectReferenceCount <= 0)
-                    {
+                        //
+                        // Remove and delete the directory entry from the parent list
+                        //
+
+                        AFSDeleteDirEntry( pParentObjectInfo,
+                                           &pDirEntry);
+
+                        AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
+                                          TRUE);
 
-                        if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
+                        if( pCurrentObject->ObjectReferenceCount <= 0)
                         {
 
-                            AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSLocateNameEntry Removing object %p from volume tree\n",
-                                          pCurrentObject));
+                            if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
+                            {
 
-                            AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
-                                                &pCurrentObject->TreeEntry);
+                                AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSLocateNameEntry Removing object %p from volume tree\n",
+                                              pCurrentObject));
+
+                                AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
+                                                    &pCurrentObject->TreeEntry);
 
-                            ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
+                                ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
+                            }
                         }
+
+                        AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
                     }
+                    else
+                    {
 
-                    AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
-                }
-                else
-                {
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
+                                      pDirEntry,
+                                      &pDirEntry->NameInformation.FileName));
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
-                                  pDirEntry,
-                                  &pDirEntry->NameInformation.FileName));
+                        SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
 
-                    SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
+                        AFSRemoveNameEntry( pParentObjectInfo,
+                                            pDirEntry);
+                    }
 
-                    AFSRemoveNameEntry( pParentObjectInfo,
-                                        pDirEntry);
-                }
+                    AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
-                AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                    AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
 
-                AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
+                    //
+                    // We deleted the dir entry so check if there is any remaining portion
+                    // of the name to process.
+                    //
 
-                AFSReleaseObjectInfo( &pParentObjectInfo);
+                    if( uniRemainingPath.Length > 0)
+                    {
 
-                //
-                // We deleted the dir entry so check if there is any remaining portion
-                // of the name to process.
-                //
+                        ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
 
-                if( uniRemainingPath.Length > 0)
-                {
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                      FileObject,
+                                      &uniComponentName,
+                                      pParentObjectInfo->FileId.Cell,
+                                      pParentObjectInfo->FileId.Volume,
+                                      pParentObjectInfo->FileId.Vnode,
+                                      pParentObjectInfo->FileId.Unique));
 
-                    ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
+                        AFSReleaseObjectInfo( &pParentObjectInfo);
+                    }
+                    else
+                    {
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
-                                  FileObject,
-                                  &uniComponentName,
-                                  pCurrentObject->FileId.Cell,
-                                  pCurrentObject->FileId.Volume,
-                                  pCurrentObject->FileId.Vnode,
-                                  pCurrentObject->FileId.Unique));
-                }
-                else
-                {
+                        ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
 
-                    ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
+                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                      FileObject,
+                                      &uniComponentName,
+                                      pParentObjectInfo->FileId.Cell,
+                                      pParentObjectInfo->FileId.Volume,
+                                      pParentObjectInfo->FileId.Vnode,
+                                      pParentObjectInfo->FileId.Unique));
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
-                                  FileObject,
-                                  &uniComponentName,
-                                  pCurrentObject->FileId.Cell,
-                                  pCurrentObject->FileId.Volume,
-                                  pCurrentObject->FileId.Vnode,
-                                  pCurrentObject->FileId.Unique));
+                        AFSReleaseObjectInfo( &pParentObjectInfo);
 
-                    //
-                    // Pass back the directory entries
-                    //
+                        //
+                        // Pass back the directory entries
+                        //
 
-                    *OutParentDirectoryCB = pParentDirEntry;
+                        *OutParentDirectoryCB = pParentDirEntry;
 
-                    pParentDirEntry = NULL;
+                        pParentDirEntry = NULL;
 
-                    *OutDirectoryCB = NULL;
+                        *OutDirectoryCB = NULL;
 
-                    *OutVolumeCB = pCurrentVolume;
+                        *OutVolumeCB = pCurrentVolume;
 
-                    *OutVolumeReferenceReason = VolumeReferenceReason;
+                        *OutVolumeReferenceReason = VolumeReferenceReason;
 
-                    bReleaseCurrentVolume = FALSE;
+                        bReleaseCurrentVolume = FALSE;
 
-                    if( ComponentName != NULL)
-                    {
+                        if( ComponentName != NULL)
+                        {
 
-                        *ComponentName = uniComponentName;
-                    }
+                            *ComponentName = uniComponentName;
+                        }
 
-                    *RootPathName = uniFullPathName;
+                        *RootPathName = uniFullPathName;
+                    }
                 }
             }
 
@@ -2430,7 +2458,8 @@ AFSCreateDirEntry( IN GUID            *AuthGroup,
                           ParentObjectInfo->FileId.Unique));
 
             ntStatus = AFSVerifyEntry( AuthGroup,
-                                       ParentDirCB);
+                                      ParentDirCB,
+                                      FALSE);
 
             if( !NT_SUCCESS( ntStatus))
             {
@@ -2777,7 +2806,7 @@ AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSDeletepDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
+                     "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
                       ParentObjectInfo,
                       pDirEntry,
                       pDirEntry->ObjectInformation,
@@ -2828,7 +2857,7 @@ AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSDeletepDirEntry Decrement count on object %p Cnt %d\n",
+                         "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
                           pDirEntry->ObjectInformation,
                           lCount));
 
@@ -2845,7 +2874,7 @@ AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSDeletepDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
+                     "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
                       pDirEntry));
 
         AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
@@ -3051,370 +3080,453 @@ AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
     return ntStatus;
 }
 
-NTSTATUS
-AFSParseName( IN PIRP Irp,
-              IN GUID *AuthGroup,
-              OUT PUNICODE_STRING FileName,
-              OUT PUNICODE_STRING ParsedFileName,
-              OUT PUNICODE_STRING RootFileName,
-              OUT ULONG *ParseFlags,
-              OUT AFSVolumeCB   **VolumeCB,
-              OUT AFSDirectoryCB **ParentDirectoryCB,
-              OUT AFSNameArrayHdr **NameArray)
+static NTSTATUS
+AFSParseRelatedName( IN PIRP Irp,
+                    IN GUID *AuthGroup,
+                    OUT PUNICODE_STRING FileName,
+                    OUT PUNICODE_STRING ParsedFileName,
+                    OUT PUNICODE_STRING RootFileName,
+                    OUT ULONG *ParseFlags,
+                    OUT AFSVolumeCB   **VolumeCB,
+                    OUT AFSDirectoryCB **ParentDirectoryCB,
+                    OUT AFSNameArrayHdr **NameArray)
 {
-
     NTSTATUS            ntStatus = STATUS_SUCCESS;
     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
-    UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
-    ULONG               ulCRC = 0;
-    AFSDirectoryCB     *pDirEntry = NULL;
-    USHORT              usIndex = 0, usDriveIndex = 0;
     AFSCcb             *pRelatedCcb = NULL;
-    AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
+    AFSFcb             *pRelatedFcb = NULL;
+    AFSNameArrayHdr    *pRelatedNameArray = NULL;
+    UNICODE_STRING      uniFullName;
+    AFSDirectoryCB     *pDirEntry = NULL;
+    AFSNameArrayHdr    *pNameArray = NULL;
     USHORT              usComponentIndex = 0;
     USHORT              usComponentLength = 0;
     AFSVolumeCB        *pVolumeCB = NULL;
-    AFSFcb             *pRelatedFcb = NULL;
-    BOOLEAN             bReleaseTreeLock = FALSE;
-    BOOLEAN             bIsAllShare = FALSE;
-    LONG                lCount;
+     LONG                lCount;
 
-    __Enter
-    {
+     __Enter
+     {
 
-        //
-        // Indicate we are opening a root ...
-        //
+        pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
 
-        *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
+        pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
 
-        *ParentDirectoryCB = NULL;
+        pRelatedNameArray = pRelatedCcb->NameArray;
 
-        if( pIrpSp->FileObject->RelatedFileObject != NULL)
-        {
+        uniFullName = pIrpSp->FileObject->FileName;
 
-            pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
+        ASSERT( pRelatedFcb != NULL);
 
-            pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
+        //
+        // On error, FileName indicates the path on which the failure occurred.
+        //
 
-            pRelatedNameArray = pRelatedCcb->NameArray;
+        *FileName = pRelatedCcb->FullFileName;
 
-            uniFullName = pIrpSp->FileObject->FileName;
+        //
+        // No wild cards in the name
+        //
 
-            ASSERT( pRelatedFcb != NULL);
+        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "AFSParseRelatedName (%p) %wZ FID %08lX-%08lX-%08lX-%08lX %wZ\n",
+                      Irp,
+                      &pRelatedCcb->DirectoryCB->NameInformation.FileName,
+                      pRelatedFcb->ObjectInformation->FileId.Cell,
+                      pRelatedFcb->ObjectInformation->FileId.Volume,
+                      pRelatedFcb->ObjectInformation->FileId.Vnode,
+                      pRelatedFcb->ObjectInformation->FileId.Unique,
+                      &pRelatedCcb->FullFileName));
 
-            //
-            // No wild cards in the name
-            //
+        if( FsRtlDoesNameContainWildCards( &pRelatedCcb->FullFileName))
+        {
 
-            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_VERBOSE_2,
-                          "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
-                          Irp,
-                          &pRelatedCcb->DirectoryCB->NameInformation.FileName,
-                          pRelatedFcb->ObjectInformation->FileId.Cell,
-                          pRelatedFcb->ObjectInformation->FileId.Volume,
-                          pRelatedFcb->ObjectInformation->FileId.Vnode,
-                          pRelatedFcb->ObjectInformation->FileId.Unique,
-                          &uniFullName));
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSParseNameRelated (%p) Component %wZ contains wild cards\n",
+                          Irp,
+                          &pRelatedCcb->FullFileName));
 
-            if( FsRtlDoesNameContainWildCards( &uniFullName))
-            {
+            try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
+        }
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSParseName (%p) Component %wZ contains wild cards\n",
-                              Irp,
-                              &uniFullName));
+        pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
 
-                try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
-            }
+        pDirEntry = pRelatedCcb->DirectoryCB;
 
-            pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
+        //
+        // Grab the root node while checking state
+        //
 
-            pDirEntry = pRelatedCcb->DirectoryCB;
+        AFSAcquireShared( pVolumeCB->VolumeLock,
+                          TRUE);
 
-            *FileName = pIrpSp->FileObject->FileName;
+        if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
+            BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
+        {
 
-            //
-            // Grab the root node while checking state
-            //
+            //
+            // The volume has been taken off line so fail the access
+            //
 
-            AFSAcquireShared( pVolumeCB->VolumeLock,
-                              TRUE);
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSParseNameRelated (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
+                          Irp,
+                          pVolumeCB->ObjectInformation.FileId.Cell,
+                          pVolumeCB->ObjectInformation.FileId.Volume));
 
-            if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
-                BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
-            {
+            AFSReleaseResource( pVolumeCB->VolumeLock);
 
-                //
-                // The volume has been taken off line so fail the access
-                //
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
-                              Irp,
-                              pVolumeCB->ObjectInformation.FileId.Cell,
-                              pVolumeCB->ObjectInformation.FileId.Volume));
+        if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
+        {
 
-                AFSReleaseResource( pVolumeCB->VolumeLock);
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSParseNameRelated (%p) Verifying root of volume %08lX:%08lX\n",
+                          Irp,
+                          pVolumeCB->ObjectInformation.FileId.Cell,
+                          pVolumeCB->ObjectInformation.FileId.Volume));
 
-                try_return( ntStatus = STATUS_DEVICE_NOT_READY);
-            }
+            ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
+                                        pVolumeCB);
 
-            if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
-            {
+            if( !NT_SUCCESS( ntStatus))
+            {
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
-                              Irp,
-                              pVolumeCB->ObjectInformation.FileId.Cell,
-                              pVolumeCB->ObjectInformation.FileId.Volume));
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSParseNameRelated (%p) Failed verification of root Status %08lX\n",
+                              Irp,
+                              ntStatus));
 
-                ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
-                                            pVolumeCB);
+                AFSReleaseResource( pVolumeCB->VolumeLock);
 
-                if( !NT_SUCCESS( ntStatus))
-                {
+                try_return( ntStatus);
+            }
+        }
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_ERROR,
-                                  "AFSParseName (%p) Failed verification of root Status %08lX\n",
-                                  Irp,
-                                  ntStatus));
+        AFSReleaseResource( pVolumeCB->VolumeLock);
 
-                    AFSReleaseResource( pVolumeCB->VolumeLock);
+        if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
+        {
 
-                    try_return( ntStatus);
-                }
-            }
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSParseNameRelated (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                          Irp,
+                          &pDirEntry->NameInformation.FileName,
+                          pDirEntry->ObjectInformation->FileId.Cell,
+                          pDirEntry->ObjectInformation->FileId.Volume,
+                          pDirEntry->ObjectInformation->FileId.Vnode,
+                          pDirEntry->ObjectInformation->FileId.Unique));
 
-            AFSReleaseResource( pVolumeCB->VolumeLock);
+            //
+            // Directory TreeLock should be exclusively held
+            //
 
-            if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
-            {
+            AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            TRUE);
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
-                              Irp,
-                              &pDirEntry->NameInformation.FileName,
-                              pDirEntry->ObjectInformation->FileId.Cell,
-                              pDirEntry->ObjectInformation->FileId.Volume,
-                              pDirEntry->ObjectInformation->FileId.Vnode,
-                              pDirEntry->ObjectInformation->FileId.Unique));
+            ntStatus = AFSVerifyEntry( AuthGroup,
+                                       pDirEntry,
+                                       FALSE);
 
-                //
-                // Directory TreeLock should be exclusively held
-                //
+            AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
-                AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                TRUE);
+            if( !NT_SUCCESS( ntStatus))
+            {
 
-                ntStatus = AFSVerifyEntry( AuthGroup,
-                                           pDirEntry);
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSParseNameRelated (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                              Irp,
+                              &pDirEntry->NameInformation.FileName,
+                              pDirEntry->ObjectInformation->FileId.Cell,
+                              pDirEntry->ObjectInformation->FileId.Volume,
+                              pDirEntry->ObjectInformation->FileId.Vnode,
+                              pDirEntry->ObjectInformation->FileId.Unique,
+                              ntStatus));
 
-                AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                try_return( ntStatus);
+            }
+        }
 
-                if( !NT_SUCCESS( ntStatus))
-                {
+        //
+        // Create our full path name buffer
+        //
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
-                                  Irp,
-                                  &pDirEntry->NameInformation.FileName,
-                                  pDirEntry->ObjectInformation->FileId.Cell,
-                                  pDirEntry->ObjectInformation->FileId.Volume,
-                                  pDirEntry->ObjectInformation->FileId.Vnode,
-                                  pDirEntry->ObjectInformation->FileId.Unique,
-                                  ntStatus));
+        uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length
+            + sizeof( WCHAR) + pIrpSp->FileObject->FileName.Length
+            + sizeof( WCHAR);
 
-                    try_return( ntStatus);
-                }
-            }
+        uniFullName.Length = 0;
 
-            //
-            // Create our full path name buffer
-            //
+        uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                uniFullName.MaximumLength,
+                                                                AFS_NAME_BUFFER_THREE_TAG);
 
-            uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
-                                                    sizeof( WCHAR) +
-                                                    pIrpSp->FileObject->FileName.Length +
-                                                    sizeof( WCHAR);
+        if( uniFullName.Buffer == NULL)
+        {
 
-            uniFullName.Length = 0;
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSParseNameRelated (%p) Failed to allocate full name buffer\n",
+                          Irp));
 
-            uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
-                                                                    uniFullName.MaximumLength,
-                                                                    AFS_NAME_BUFFER_THREE_TAG);
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
 
-            if( uniFullName.Buffer == NULL)
-            {
+        SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSParseName (%p) Failed to allocate full name buffer\n",
-                              Irp));
+        RtlZeroMemory( uniFullName.Buffer,
+                       uniFullName.MaximumLength);
 
-                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-            }
+        RtlCopyMemory( uniFullName.Buffer,
+                       pRelatedCcb->FullFileName.Buffer,
+                       pRelatedCcb->FullFileName.Length);
 
-            RtlZeroMemory( uniFullName.Buffer,
-                           uniFullName.MaximumLength);
+        uniFullName.Length = pRelatedCcb->FullFileName.Length;
 
-            RtlCopyMemory( uniFullName.Buffer,
-                           pRelatedCcb->FullFileName.Buffer,
-                           pRelatedCcb->FullFileName.Length);
+        usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
 
-            uniFullName.Length = pRelatedCcb->FullFileName.Length;
+        usComponentLength = pIrpSp->FileObject->FileName.Length;
 
-            usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
+        if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
+            pIrpSp->FileObject->FileName.Length > 0 &&
+            pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
+            pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
+        {
 
-            usComponentLength = pIrpSp->FileObject->FileName.Length;
+            uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
 
-            if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
-                pIrpSp->FileObject->FileName.Length > 0 &&
-                pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
-                pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
-            {
+            uniFullName.Length += sizeof( WCHAR);
 
-                uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
+            usComponentLength += sizeof( WCHAR);
+        }
 
-                uniFullName.Length += sizeof( WCHAR);
+        if( pIrpSp->FileObject->FileName.Length > 0)
+        {
 
-                usComponentLength += sizeof( WCHAR);
-            }
+            RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
+                           pIrpSp->FileObject->FileName.Buffer,
+                           pIrpSp->FileObject->FileName.Length);
 
-            if( pIrpSp->FileObject->FileName.Length > 0)
-            {
+            uniFullName.Length += pIrpSp->FileObject->FileName.Length;
+        }
 
-                RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
-                               pIrpSp->FileObject->FileName.Buffer,
-                               pIrpSp->FileObject->FileName.Length);
+        *RootFileName = uniFullName;
 
-                uniFullName.Length += pIrpSp->FileObject->FileName.Length;
-            }
+        //
+        // We populate up to the current parent
+        //
 
-            *RootFileName = uniFullName;
+        if( pRelatedNameArray == NULL)
+        {
 
-            //
-            // We populate up to the current parent
-            //
+            //
+            // Init and populate our name array
+            //
 
-            if( pRelatedNameArray == NULL)
-            {
+            pNameArray = AFSInitNameArray( NULL,
+                                           0);
 
-                //
-                // Init and populate our name array
-                //
+            if( pNameArray == NULL)
+            {
 
-                pNameArray = AFSInitNameArray( NULL,
-                                               0);
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSParseNameRelated (%p) Failed to initialize name array\n",
+                              Irp));
 
-                if( pNameArray == NULL)
-                {
+                AFSExFreePoolWithTag( uniFullName.Buffer, 0);
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSParseName (%p) Failed to initialize name array\n",
-                                  Irp));
+                ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
 
-                    AFSExFreePoolWithTag( uniFullName.Buffer, 0);
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
 
-                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-                }
+            ntStatus = AFSPopulateNameArray( pNameArray,
+                                             NULL,
+                                             pRelatedCcb->DirectoryCB);
+        }
+        else
+        {
 
-                ntStatus = AFSPopulateNameArray( pNameArray,
-                                                 NULL,
-                                                 pRelatedCcb->DirectoryCB);
-            }
-            else
-            {
+            //
+            // Init and populate our name array
+            //
 
-                //
-                // Init and populate our name array
-                //
+            pNameArray = AFSInitNameArray( NULL,
+                                           pRelatedNameArray->MaxElementCount);
 
-                pNameArray = AFSInitNameArray( NULL,
-                                               pRelatedNameArray->MaxElementCount);
+            if( pNameArray == NULL)
+            {
 
-                if( pNameArray == NULL)
-                {
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSParseNameRelated (%p) Failed to initialize name array\n",
+                              Irp));
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSParseName (%p) Failed to initialize name array\n",
-                                  Irp));
+                AFSExFreePoolWithTag( uniFullName.Buffer, 0);
 
-                    AFSExFreePoolWithTag( uniFullName.Buffer, 0);
+                ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
 
-                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-                }
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
 
-                ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
-                                                                 pRelatedNameArray,
-                                                                 pRelatedCcb->DirectoryCB);
-            }
+            ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
+                                                             pRelatedNameArray,
+                                                             pRelatedCcb->DirectoryCB);
+        }
 
-            if( !NT_SUCCESS( ntStatus))
-            {
+        if( !NT_SUCCESS( ntStatus))
+        {
 
-                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSParseName (%p) Failed to populate name array\n",
-                              Irp));
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSParseNameRelated (%p) Failed to populate name array\n",
+                          Irp));
 
-                AFSExFreePoolWithTag( uniFullName.Buffer, 0);
+            AFSExFreePoolWithTag( uniFullName.Buffer, 0);
 
-                try_return( ntStatus);
-            }
+            ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
 
-            ParsedFileName->Length = usComponentLength;
-            ParsedFileName->MaximumLength = uniFullName.MaximumLength;
+            try_return( ntStatus);
+        }
 
-            ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
+        ParsedFileName->Length = usComponentLength;
 
-            //
-            // Indicate to caller that RootFileName must be freed
-            //
+        ParsedFileName->MaximumLength = uniFullName.MaximumLength;
 
-            SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
+        ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
 
-            *NameArray = pNameArray;
+        *NameArray = pNameArray;
 
-            //
-            // Increment our volume reference count
-            //
+        //
+        // Increment our volume reference count
+        //
 
-            lCount = AFSVolumeIncrement( pVolumeCB,
-                                         AFS_VOLUME_REFERENCE_PARSE_NAME);
+        lCount = AFSVolumeIncrement( pVolumeCB,
+                                     AFS_VOLUME_REFERENCE_PARSE_NAME);
 
-            AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
-                          AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSParseName Increment count on volume %p Cnt %d\n",
-                          pVolumeCB,
-                          lCount));
+        AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSParseNameRelated Increment count on volume %p Cnt %d\n",
+                      pVolumeCB,
+                      lCount));
 
-            *VolumeCB = pVolumeCB;
+        *VolumeCB = pVolumeCB;
 
-            *ParentDirectoryCB = pDirEntry;
+        *ParentDirectoryCB = pDirEntry;
 
-            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_VERBOSE_2,
-                          "AFSParseName (%p) Returning full name %wZ\n",
-                          Irp,
-                          &uniFullName));
+        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "AFSParseNameRelated (%p) Returning full name %wZ\n",
+                      Irp,
+                      &uniFullName));
 
-            try_return( ntStatus);
+        try_return( ntStatus);
+
+try_exit:
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            if( *ParentDirectoryCB != NULL)
+            {
+
+                lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
+
+                AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSParseRelatedName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &(*ParentDirectoryCB)->NameInformation.FileName,
+                              (*ParentDirectoryCB),
+                              NULL,
+                              lCount));
+            }
+        }
+
+        if( *VolumeCB != NULL)
+        {
+            ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
+        }
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            if( pNameArray != NULL)
+            {
+
+                AFSFreeNameArray( pNameArray);
+            }
+        }
+     }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSParseName( IN PIRP Irp,
+             IN GUID *AuthGroup,
+             OUT PUNICODE_STRING FileName,
+             OUT PUNICODE_STRING ParsedFileName,
+             OUT PUNICODE_STRING RootFileName,
+             OUT ULONG *ParseFlags,
+             OUT AFSVolumeCB   **VolumeCB,
+             OUT AFSDirectoryCB **ParentDirectoryCB,
+             OUT AFSNameArrayHdr **NameArray)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
+    ULONG               ulCRC = 0;
+    AFSDirectoryCB     *pDirEntry = NULL;
+    USHORT              usIndex = 0, usDriveIndex = 0;
+    AFSNameArrayHdr    *pNameArray = NULL;
+    USHORT              usComponentIndex = 0;
+    USHORT              usComponentLength = 0;
+    AFSVolumeCB        *pVolumeCB = NULL;
+    BOOLEAN             bReleaseTreeLock = FALSE;
+    BOOLEAN             bIsAllShare = FALSE;
+    LONG                lCount;
+
+    __Enter
+    {
+
+       if( pIrpSp->FileObject->RelatedFileObject != NULL)
+       {
+
+           return AFSParseRelatedName( Irp, AuthGroup, FileName,
+                                       ParsedFileName, RootFileName,
+                                       ParseFlags, VolumeCB,
+                                       ParentDirectoryCB, NameArray);
         }
 
-        //
-        // No wild cards in the name
-        //
+       //
+       // Indicate we are opening a root ...
+       //
+
+       *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
+
+       *ParentDirectoryCB = NULL;
+
+       //
+       // On error, FileName indicates the path on which the failure occurred
+       //
+
+       *FileName = pIrpSp->FileObject->FileName;
+
+       //
+       // No wild cards in the name
+       //
 
         uniFullName = pIrpSp->FileObject->FileName;
 
@@ -4883,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;
@@ -4895,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
         //
 
@@ -4994,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,
@@ -5079,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)
+           {
+
+               //
+               // original FileObject buffer was not allocated by AFS
+               //
 
-            AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
+               ExFreePoolWithTag( FileObject->FileName.Buffer, 0);
+           }
+
+           FileObject->FileName = uniReparseName;
         }
+       else
+       {
 
-        FileObject->FileName = uniReparseName;
+           *TargetName = uniReparseName;
+       }
 
         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -5118,3 +5250,111 @@ try_exit:
 
     return ntStatus;
 }
+
+NTSTATUS
+AFSGetFullFileName( IN AFSFcb *Fcb,
+                   IN AFSCcb *Ccb,
+                   OUT ULONG *FileNameLength,
+                   OUT WCHAR *FileName,
+                   IN OUT LONG *RemainingLength)
+{
+
+    NTSTATUS    ntStatus = STATUS_SUCCESS;
+    ULONG       ulCopyLength = 0;
+    ULONG       cchCopied = 0;
+    BOOLEAN     bAddTrailingSlash = FALSE;
+    USHORT      usFullNameLength = 0;
+
+    __Enter
+    {
+
+       //
+       // Add a trailing slash for anything which is of the form \server\share
+       //
+
+       if( ( Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY ||
+             Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT) &&
+           Ccb->FullFileName.Length > sizeof( WCHAR) &&
+           Ccb->FullFileName.Buffer[ (Ccb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
+           AFSIsShareName( &Ccb->FullFileName))
+       {
+           bAddTrailingSlash = TRUE;
+       }
+
+       usFullNameLength = sizeof( WCHAR) +
+                                   AFSServerName.Length +
+                                   Ccb->FullFileName.Length;
+
+       if( bAddTrailingSlash)
+       {
+           usFullNameLength += sizeof( WCHAR);
+       }
+
+       if( *RemainingLength >= (LONG)usFullNameLength)
+       {
+           ulCopyLength = (LONG)usFullNameLength;
+       }
+       else
+       {
+
+           ulCopyLength = *RemainingLength;
+
+           ntStatus = STATUS_BUFFER_OVERFLOW;
+       }
+
+       *FileNameLength = (ULONG)usFullNameLength;
+
+       if( ulCopyLength > 0)
+       {
+
+           FileName[ 0] = L'\\';
+           ulCopyLength -= sizeof( WCHAR);
+
+           *RemainingLength -= sizeof( WCHAR);
+           cchCopied += 1;
+
+           if( ulCopyLength >= AFSServerName.Length)
+           {
+
+               RtlCopyMemory( &FileName[ 1],
+                              AFSServerName.Buffer,
+                              AFSServerName.Length);
+
+               ulCopyLength -= AFSServerName.Length;
+               *RemainingLength -= AFSServerName.Length;
+               cchCopied += AFSServerName.Length/sizeof( WCHAR);
+
+               if( ulCopyLength >= Ccb->FullFileName.Length)
+               {
+
+                   RtlCopyMemory( &FileName[ cchCopied],
+                                  Ccb->FullFileName.Buffer,
+                                  Ccb->FullFileName.Length);
+
+                   ulCopyLength -= Ccb->FullFileName.Length;
+                   *RemainingLength -= Ccb->FullFileName.Length;
+                   cchCopied += Ccb->FullFileName.Length/sizeof( WCHAR);
+
+                   if( ulCopyLength > 0 &&
+                       bAddTrailingSlash)
+                   {
+                       FileName[ cchCopied] = L'\\';
+
+                       *RemainingLength -= sizeof( WCHAR);
+                   }
+               }
+               else
+               {
+
+                   RtlCopyMemory( &FileName[ cchCopied],
+                                  Ccb->FullFileName.Buffer,
+                                  ulCopyLength);
+
+                   *RemainingLength -= ulCopyLength;
+               }
+           }
+       }
+    }
+
+    return ntStatus;
+}