Windows: AFSRedirLib.sys file system library driver
authorPeter Scott <pscott@kerneldrivers.com>
Thu, 15 Sep 2011 05:48:59 +0000 (01:48 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Thu, 15 Sep 2011 18:28:12 +0000 (11:28 -0700)
This patchset implements the AFS Redirector Library driver.
This driver contains all of the AFS specific implementation
details for service communication, network provider support,
directory management, extent management, metadata management,
callback invaldation, volume management, file locking, etc.

Rod Widdowson <rdw@steadingsoftware.com> and Jeffrey Altman
<jaltman@your-file-system.com> contributed to the development
of this driver.

Change-Id: Icc18c26b81b96a92096c20e01360007815ca1acb
Reviewed-on: http://gerrit.openafs.org/5438
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Rod Widdowson <rdw@steadingsoftware.com>
Tested-by: Rod Widdowson <rdw@steadingsoftware.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

38 files changed:
src/WINNT/afsrdr/kernel/lib/AFSBTreeSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSCleanup.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSClose.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSCommSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSData.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSDevControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSEa.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSExtentsSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSFSControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSFcbSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSFileInfo.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSFlushBuffers.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSInit.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSInternalDevControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSIoSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSLockControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSMD5Support.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSNetworkProviderSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSQuota.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSRead.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSRedirLibInstall.inf [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSSecurity.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSShutdown.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSSystemControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSVolumeInfo.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSWorker.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/Filesystem.rc [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/Include/AFSExtern.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/Include/AFSStructs.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/MAKEFILE [new file with mode: 0644]
src/WINNT/afsrdr/kernel/lib/sources [new file with mode: 0644]

diff --git a/src/WINNT/afsrdr/kernel/lib/AFSBTreeSupport.cpp b/src/WINNT/afsrdr/kernel/lib/AFSBTreeSupport.cpp
new file mode 100644 (file)
index 0000000..107e53b
--- /dev/null
@@ -0,0 +1,1611 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice,
+ *   this list of conditions and the following disclaimer in the
+ *   documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ *   nor the names of their contributors may be used to endorse or promote
+ *   products derived from this software without specific prior written
+ *   permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// File: AFSBTreeSupport.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSLocateCaseSensitiveDirEntry( IN AFSDirectoryCB *RootNode,
+                                IN ULONG Index,
+                                IN OUT AFSDirectoryCB **DirEntry)
+{
+
+    NTSTATUS    ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB   *pEntry = NULL;
+    AFSDirectoryCB   *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        *DirEntry = NULL;
+
+        //
+        // If the rootnode passed is null then the directory is empty
+        //
+
+        if( RootNode == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // If the requestor is looking for the root node itself, then return it.
+        //
+
+        if( RootNode->CaseSensitiveTreeEntry.HashIndex == Index)
+        {
+
+            *DirEntry = RootNode;
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Loop through the nodes in the tree
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater values are to the right link.
+            //
+
+            if( Index > pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if there is one
+                //
+
+                if( pCurrentEntry->CaseSensitiveTreeEntry.rightLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Came to the end of the branch so bail
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else if( Index < pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if one exists
+                //
+
+                if( pCurrentEntry->CaseSensitiveTreeEntry.leftLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // End of the branch ...
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                //
+                // Found the entry.
+                //
+
+                *DirEntry = pCurrentEntry;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSLocateCaseInsensitiveDirEntry( IN AFSDirectoryCB *RootNode,
+                                  IN ULONG Index,
+                                  IN OUT AFSDirectoryCB **DirEntry)
+{
+
+    NTSTATUS    ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB   *pEntry = NULL;
+    AFSDirectoryCB   *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        *DirEntry = NULL;
+
+        //
+        // If the rootnode passed is null then the directory is empty
+        //
+
+        if( RootNode == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // If the requestor is looking for the root node itself, then return it.
+        //
+
+        if( RootNode->CaseInsensitiveTreeEntry.HashIndex == Index)
+        {
+
+            *DirEntry = RootNode;
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Loop through the nodes in the tree
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater values are to the right link.
+            //
+
+            if( Index > pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if there is one
+                //
+
+                if( pCurrentEntry->CaseInsensitiveTreeEntry.rightLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Came to the end of the branch so bail
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else if( Index < pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if one exists
+                //
+
+                if( pCurrentEntry->CaseInsensitiveTreeEntry.leftLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // End of the branch ...
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                //
+                // Found the entry.
+                //
+
+                *DirEntry = pCurrentEntry;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInsertCaseSensitiveDirEntry( IN AFSDirectoryCB *RootNode,
+                                IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        //
+        // If we have no root node then we can;t start the search.
+        //
+
+        if( pCurrentEntry == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInsertCaseSensitiveDirEntry Invalid root node\n");
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Locate the branch end to insert the node
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater vlued indices are to the right link
+            //
+
+            if( DirEntry->CaseSensitiveTreeEntry.HashIndex > pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if it exists
+                //
+
+                if( pCurrentEntry->CaseSensitiveTreeEntry.rightLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the end of the branch line so insert the node
+                    //
+
+                    pCurrentEntry->CaseSensitiveTreeEntry.rightLink = (void *)DirEntry;
+
+                    DirEntry->CaseSensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else if( DirEntry->CaseSensitiveTreeEntry.HashIndex < pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if it exists
+                //
+
+                if( pCurrentEntry->CaseSensitiveTreeEntry.leftLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the branch line end so insert the node here
+                    //
+
+                    pCurrentEntry->CaseSensitiveTreeEntry.leftLink = (void *)DirEntry;
+
+                    DirEntry->CaseSensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_WARNING,
+                              "AFSInsertCaseSensitiveDirEntry Attempt to re-insert a CRC %I64X\n",
+                              DirEntry->CaseSensitiveTreeEntry.HashIndex);
+
+                ASSERT( FALSE);
+
+                ntStatus = STATUS_UNSUCCESSFUL;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInsertCaseInsensitiveDirEntry( IN AFSDirectoryCB *RootNode,
+                                  IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        //
+        // If we have no root node then we can;t start the search.
+        //
+
+        if( pCurrentEntry == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInsertCaseInsensitiveDirEntry Invalid root node\n");
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Locate the branch end to insert the node
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater vlued indices are to the right link
+            //
+
+            if( DirEntry->CaseInsensitiveTreeEntry.HashIndex > pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if it exists
+                //
+
+                if( pCurrentEntry->CaseInsensitiveTreeEntry.rightLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the end of the branch line so insert the node
+                    //
+
+                    pCurrentEntry->CaseInsensitiveTreeEntry.rightLink = (void *)DirEntry;
+
+                    DirEntry->CaseInsensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+
+                    break;
+                }
+            }
+            else if( DirEntry->CaseInsensitiveTreeEntry.HashIndex < pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if it exists
+                //
+
+                if( pCurrentEntry->CaseInsensitiveTreeEntry.leftLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the branch line end so insert the node here
+                    //
+
+                    pCurrentEntry->CaseInsensitiveTreeEntry.leftLink = (void *)DirEntry;
+
+                    DirEntry->CaseInsensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+
+                    break;
+                }
+            }
+            else
+            {
+
+                //
+                // Inser the the entry at the end of the insensitive list
+                //
+
+                while( pCurrentEntry->CaseInsensitiveList.fLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveList.fLink;
+                }
+
+                pCurrentEntry->CaseInsensitiveList.fLink = (void *)DirEntry;
+
+                DirEntry->CaseInsensitiveList.bLink = (void *)pCurrentEntry;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRemoveCaseSensitiveDirEntry( IN AFSDirectoryCB **RootNode,
+                                IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    AFSDirectoryCB *pRightNode = NULL;
+    AFSDirectoryCB *pLeftNode = NULL;
+    AFSDirectoryCB *pCurrentNode = NULL;
+    AFSDirectoryCB *pParentNode = NULL;
+
+    pRightNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.rightLink;
+    pLeftNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.leftLink;
+    pParentNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.parentLink;
+
+    __Enter
+    {
+
+        if( (pRightNode == NULL) && (pLeftNode == NULL))
+        {
+
+            if( pParentNode != NULL)
+            {
+
+                if( pParentNode->CaseSensitiveTreeEntry.leftLink == DirEntry)
+                {
+
+                    pParentNode->CaseSensitiveTreeEntry.leftLink = NULL;
+                }
+                else
+                {
+
+                    pParentNode->CaseSensitiveTreeEntry.rightLink = NULL;
+                }
+            }
+            else
+            {
+
+                //
+                // Removing the top node
+                //
+
+                *RootNode = NULL;
+            }
+        }
+        else
+        {
+
+            if( pRightNode != NULL)
+            {
+
+                if( pParentNode != NULL)
+                {
+
+                    // Replace the parent node where this entry was.
+                    if( pParentNode->CaseSensitiveTreeEntry.rightLink == DirEntry)
+                    {
+
+                        pParentNode->CaseSensitiveTreeEntry.rightLink = pRightNode;
+                    }
+                    else
+                    {
+
+                        pParentNode->CaseSensitiveTreeEntry.leftLink = pRightNode;
+                    }
+                }
+                else
+                {
+
+                    *RootNode = pRightNode;
+
+                    pRightNode->CaseSensitiveTreeEntry.parentLink = NULL;
+                }
+
+                pRightNode->CaseSensitiveTreeEntry.parentLink = pParentNode;
+            }
+
+            if( pLeftNode != NULL)
+            {
+
+                // To connect the left node, we must walk the chain of the
+                // right nodes left side until we reach the end.
+                // At the end attach the leftNode
+                if( pRightNode != NULL)
+                {
+
+                    pCurrentNode = pRightNode;
+
+                    while( pCurrentNode->CaseSensitiveTreeEntry.leftLink != NULL)
+                    {
+
+                        pCurrentNode = (AFSDirectoryCB *)pCurrentNode->CaseSensitiveTreeEntry.leftLink;
+                    }
+
+                    pCurrentNode->CaseSensitiveTreeEntry.leftLink = pLeftNode;
+
+                    pLeftNode->CaseSensitiveTreeEntry.parentLink = pCurrentNode;
+                }
+                else
+                {
+
+                    if( pParentNode != NULL)
+                    {
+
+                        // This is where we have a left node with no right node.
+                        // So, attach the left node to the parent of
+                        // the removed nodes branch
+                        if( pParentNode->CaseSensitiveTreeEntry.rightLink == DirEntry)
+                        {
+
+                            pParentNode->CaseSensitiveTreeEntry.rightLink = pLeftNode;
+                        }
+                        else
+                        {
+
+                            pParentNode->CaseSensitiveTreeEntry.leftLink = pLeftNode;
+                        }
+
+                        pLeftNode->CaseSensitiveTreeEntry.parentLink = pParentNode;
+                    }
+                    else
+                    {
+
+                        *RootNode = pLeftNode;
+
+                        pLeftNode->CaseSensitiveTreeEntry.parentLink = NULL;
+                    }
+                }
+            }
+        }
+
+        //
+        // Cleanup the just removed node
+        //
+
+        DirEntry->CaseSensitiveTreeEntry.leftLink = NULL;
+        DirEntry->CaseSensitiveTreeEntry.parentLink = NULL;
+        DirEntry->CaseSensitiveTreeEntry.rightLink = NULL;
+
+        ntStatus = STATUS_SUCCESS;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRemoveCaseInsensitiveDirEntry( IN AFSDirectoryCB **RootNode,
+                                  IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    AFSDirectoryCB *pRightNode = NULL;
+    AFSDirectoryCB *pLeftNode = NULL;
+    AFSDirectoryCB *pCurrentNode = NULL;
+    AFSDirectoryCB *pParentNode = NULL;
+    AFSDirectoryCB *pNewHeadEntry = NULL;
+
+    pRightNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.rightLink;
+    pLeftNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.leftLink;
+    pParentNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.parentLink;
+
+    __Enter
+    {
+
+        //
+        // If this is not a head of list entry then just update the pointers for it
+        //
+
+        if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD))
+        {
+
+            ((AFSDirectoryCB *)DirEntry->CaseInsensitiveList.bLink)->CaseInsensitiveList.fLink = DirEntry->CaseInsensitiveList.fLink;
+
+            if( DirEntry->CaseInsensitiveList.fLink != NULL)
+            {
+
+                ((AFSDirectoryCB *)DirEntry->CaseInsensitiveList.fLink)->CaseInsensitiveList.bLink = DirEntry->CaseInsensitiveList.bLink;
+            }
+
+            try_return( ntStatus);
+        }
+        else if( DirEntry->CaseInsensitiveList.fLink != NULL)
+        {
+
+            //
+            // Removing the head of a list of entries so just update pointers
+            //
+
+            pNewHeadEntry = (AFSDirectoryCB *)DirEntry->CaseInsensitiveList.fLink;
+
+            if( pParentNode != NULL)
+            {
+
+                if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
+                {
+                    pParentNode->CaseInsensitiveTreeEntry.rightLink = (void *)pNewHeadEntry;
+                }
+                else
+                {
+                    pParentNode->CaseInsensitiveTreeEntry.leftLink = (void *)pNewHeadEntry;
+                }
+            }
+
+            if( pRightNode != NULL)
+            {
+
+                pRightNode->CaseInsensitiveTreeEntry.parentLink = (void *)pNewHeadEntry;
+            }
+
+            if( pLeftNode != NULL)
+            {
+
+                pLeftNode->CaseInsensitiveTreeEntry.parentLink = (void *)pNewHeadEntry;
+            }
+
+            pNewHeadEntry->CaseInsensitiveList.bLink = NULL;
+
+            pNewHeadEntry->CaseInsensitiveTreeEntry.parentLink = pParentNode;
+
+            pNewHeadEntry->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
+
+            pNewHeadEntry->CaseInsensitiveTreeEntry.rightLink = pRightNode;
+
+            SetFlag( ((AFSDirectoryCB *)DirEntry->CaseInsensitiveList.fLink)->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+
+            try_return( ntStatus);
+        }
+
+        if( (pRightNode == NULL) && (pLeftNode == NULL))
+        {
+
+            if( pParentNode != NULL)
+            {
+
+                if( pParentNode->CaseInsensitiveTreeEntry.leftLink == DirEntry)
+                {
+
+                    pParentNode->CaseInsensitiveTreeEntry.leftLink = NULL;
+                }
+                else
+                {
+
+                    pParentNode->CaseInsensitiveTreeEntry.rightLink = NULL;
+                }
+            }
+            else
+            {
+
+                //
+                // Removing the top node
+                //
+
+                *RootNode = NULL;
+            }
+        }
+        else
+        {
+
+            if( pRightNode != NULL)
+            {
+
+                if( pParentNode != NULL)
+                {
+
+                    // Replace the parent node where this entry was.
+                    if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
+                    {
+
+                        pParentNode->CaseInsensitiveTreeEntry.rightLink = pRightNode;
+                    }
+                    else
+                    {
+
+                        pParentNode->CaseInsensitiveTreeEntry.leftLink = pRightNode;
+                    }
+                }
+                else
+                {
+
+                    *RootNode = pRightNode;
+
+                    pRightNode->CaseInsensitiveTreeEntry.parentLink = NULL;
+                }
+
+                pRightNode->CaseInsensitiveTreeEntry.parentLink = pParentNode;
+            }
+
+            if( pLeftNode != NULL)
+            {
+
+                // To connect the left node, we must walk the chain of the
+                // right nodes left side until we reach the end.
+                // At the end attach the leftNode
+                if( pRightNode != NULL)
+                {
+
+                    pCurrentNode = pRightNode;
+
+                    while( pCurrentNode->CaseInsensitiveTreeEntry.leftLink != NULL)
+                    {
+
+                        pCurrentNode = (AFSDirectoryCB *)pCurrentNode->CaseInsensitiveTreeEntry.leftLink;
+                    }
+
+                    pCurrentNode->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
+
+                    pLeftNode->CaseInsensitiveTreeEntry.parentLink = pCurrentNode;
+                }
+                else
+                {
+
+                    if( pParentNode != NULL)
+                    {
+
+                        // This is where we have a left node with no right node.
+                        // So, attach the left node to the parent of
+                        // the removed nodes branch
+                        if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
+                        {
+
+                            pParentNode->CaseInsensitiveTreeEntry.rightLink = pLeftNode;
+                        }
+                        else
+                        {
+
+                            pParentNode->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
+                        }
+
+                        pLeftNode->CaseInsensitiveTreeEntry.parentLink = pParentNode;
+                    }
+                    else
+                    {
+
+                        *RootNode = pLeftNode;
+
+                        pLeftNode->CaseInsensitiveTreeEntry.parentLink = NULL;
+                    }
+                }
+            }
+        }
+
+try_exit:
+
+        //
+        // Cleanup the just removed node
+        //
+
+        DirEntry->CaseInsensitiveTreeEntry.leftLink = NULL;
+        DirEntry->CaseInsensitiveTreeEntry.parentLink = NULL;
+        DirEntry->CaseInsensitiveTreeEntry.rightLink = NULL;
+
+        DirEntry->CaseInsensitiveList.bLink = NULL;
+        DirEntry->CaseInsensitiveList.fLink = NULL;
+
+        ntStatus = STATUS_SUCCESS;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSLocateShortNameDirEntry( IN AFSDirectoryCB *RootNode,
+                            IN ULONG Index,
+                            IN OUT AFSDirectoryCB **DirEntry)
+{
+
+    NTSTATUS    ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB   *pEntry = NULL;
+    AFSDirectoryCB   *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        *DirEntry = NULL;
+
+        //
+        // If the rootnode passed is null then the directory is empty
+        //
+
+        if( RootNode == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // If the requestor is looking for the root node itself, then return it.
+        //
+
+        if( RootNode->Type.Data.ShortNameTreeEntry.HashIndex == Index)
+        {
+
+            *DirEntry = RootNode;
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Loop through the nodes in the tree
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater values are to the right link.
+            //
+
+            if( Index > pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if there is one
+                //
+
+                if( pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Came to the end of the branch so bail
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else if( Index < pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if one exists
+                //
+
+                if( pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // End of the branch ...
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                //
+                // Found the entry.
+                //
+
+                *DirEntry = pCurrentEntry;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInsertShortNameDirEntry( IN AFSDirectoryCB *RootNode,
+                            IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDirectoryCB *pCurrentEntry = NULL;
+
+    pCurrentEntry = RootNode;
+
+    __Enter
+    {
+
+        //
+        // If we have no root node then we can;t start the search.
+        //
+
+        if( pCurrentEntry == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInsertShortNameDirEntry Invalid root node\n");
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Locate the branch end to insert the node
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater valued indices are to the right link
+            //
+
+            if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex > pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if it exists
+                //
+
+                if( pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the end of the branch line so insert the node
+                    //
+
+                    pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink = (void *)DirEntry;
+
+                    DirEntry->Type.Data.ShortNameTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex < pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if it exists
+                //
+
+                if( pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink != NULL)
+                {
+                    pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the branch line end so insert the node here
+                    //
+
+                    pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink = (void *)DirEntry;
+
+                    DirEntry->Type.Data.ShortNameTreeEntry.parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRemoveShortNameDirEntry( IN AFSDirectoryCB **RootNode,
+                            IN AFSDirectoryCB *DirEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    AFSDirectoryCB *pRightNode = NULL;
+    AFSDirectoryCB *pLeftNode = NULL;
+    AFSDirectoryCB *pCurrentNode = NULL;
+    AFSDirectoryCB *pParentNode = NULL;
+
+    pRightNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.rightLink;
+    pLeftNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.leftLink;
+    pParentNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.parentLink;
+
+    __Enter
+    {
+
+        if( (pRightNode == NULL) && (pLeftNode == NULL))
+        {
+
+            if( pParentNode != NULL)
+            {
+
+                if( pParentNode->Type.Data.ShortNameTreeEntry.leftLink == DirEntry)
+                {
+
+                    pParentNode->Type.Data.ShortNameTreeEntry.leftLink = NULL;
+                }
+                else
+                {
+
+                    pParentNode->Type.Data.ShortNameTreeEntry.rightLink = NULL;
+                }
+            }
+            else
+            {
+
+                //
+                // Removing the top node
+                //
+
+                *RootNode = NULL;
+            }
+        }
+        else
+        {
+
+            if( pRightNode != NULL)
+            {
+
+                if( pParentNode != NULL)
+                {
+
+                    // Replace the parent node where this entry was.
+                    if( pParentNode->Type.Data.ShortNameTreeEntry.rightLink == DirEntry)
+                    {
+
+                        pParentNode->Type.Data.ShortNameTreeEntry.rightLink = pRightNode;
+                    }
+                    else
+                    {
+
+                        pParentNode->Type.Data.ShortNameTreeEntry.leftLink = pRightNode;
+                    }
+                }
+                else
+                {
+
+                    *RootNode = pRightNode;
+
+                    pRightNode->Type.Data.ShortNameTreeEntry.parentLink = NULL;
+                }
+
+                pRightNode->Type.Data.ShortNameTreeEntry.parentLink = pParentNode;
+            }
+
+            if( pLeftNode != NULL)
+            {
+
+                // To connect the left node, we must walk the chain of the
+                // right nodes left side until we reach the end.
+                // At the end attach the leftNode
+                if( pRightNode != NULL)
+                {
+
+                    pCurrentNode = pRightNode;
+
+                    while( pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink != NULL)
+                    {
+
+                        pCurrentNode = (AFSDirectoryCB *)pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink;
+                    }
+
+                    pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink = pLeftNode;
+
+                    pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = pCurrentNode;
+                }
+                else
+                {
+
+                    if( pParentNode != NULL)
+                    {
+
+                        // This is where we have a left node with no right node.
+                        // So, attach the left node to the parent of
+                        // the removed nodes branch
+                        if( pParentNode->Type.Data.ShortNameTreeEntry.rightLink == DirEntry)
+                        {
+
+                            pParentNode->Type.Data.ShortNameTreeEntry.rightLink = pLeftNode;
+                        }
+                        else
+                        {
+
+                            pParentNode->Type.Data.ShortNameTreeEntry.leftLink = pLeftNode;
+                        }
+
+                        pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = pParentNode;
+                    }
+                    else
+                    {
+
+                        *RootNode = pLeftNode;
+
+                        pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = NULL;
+                    }
+                }
+            }
+        }
+
+        //
+        // Cleanup the just removed node
+        //
+
+        DirEntry->Type.Data.ShortNameTreeEntry.leftLink = NULL;
+        DirEntry->Type.Data.ShortNameTreeEntry.parentLink = NULL;
+        DirEntry->Type.Data.ShortNameTreeEntry.rightLink = NULL;
+
+        ntStatus = STATUS_SUCCESS;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSLocateHashEntry( IN AFSBTreeEntry *TopNode,
+                    IN ULONGLONG HashIndex,
+                    IN OUT AFSBTreeEntry **TreeEntry)
+{
+
+    NTSTATUS         ntStatus = STATUS_SUCCESS;
+    AFSBTreeEntry   *pEntry = NULL;
+    AFSBTreeEntry   *pCurrentEntry = NULL;
+
+    pCurrentEntry = TopNode;
+
+    __Enter
+    {
+
+        //
+        // If the rootnode passed is null then the directory is empty
+        //
+
+        if( TopNode == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // If the requestor is looking for the root node itself, then return it.
+        //
+
+        if( TopNode->HashIndex == HashIndex)
+        {
+
+            *TreeEntry = TopNode;
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Loop through the nodes in the tree
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater values are to the right link.
+            //
+
+            if( HashIndex > pCurrentEntry->HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if there is one
+                //
+
+                if( pCurrentEntry->rightLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Came to the end of the branch so bail
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else if( HashIndex < pCurrentEntry->HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if one exists
+                //
+
+                if( pCurrentEntry->leftLink != NULL)
+                {
+
+                    pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
+                }
+                else
+                {
+
+                    //
+                    // End of the branch ...
+                    //
+
+                    pCurrentEntry = NULL;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                //
+                // Found the entry.
+                //
+
+                *TreeEntry = pCurrentEntry;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInsertHashEntry( IN AFSBTreeEntry *TopNode,
+                    IN AFSBTreeEntry *FileIDEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSBTreeEntry *pCurrentEntry = NULL;
+
+    pCurrentEntry = TopNode;
+
+    __Enter
+    {
+
+        //
+        // If we have no root node then we can;t start the search.
+        //
+
+        if( pCurrentEntry == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSInsertHashEntry Invalid root node\n");
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Locate the branch end to insert the node
+        //
+
+        while( pCurrentEntry != NULL)
+        {
+
+            //
+            // Greater vlued indices are to the right link
+            //
+
+            if( FileIDEntry->HashIndex > pCurrentEntry->HashIndex)
+            {
+
+                //
+                // Go to the next RIGHT entry, if it exists
+                //
+
+                if( pCurrentEntry->rightLink != NULL)
+                {
+                    pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the end of the branch line so insert the node
+                    //
+
+                    pCurrentEntry->rightLink = (void *)FileIDEntry;
+
+                    FileIDEntry->parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else if( FileIDEntry->HashIndex < pCurrentEntry->HashIndex)
+            {
+
+                //
+                // Go to the next LEFT entry, if it exists
+                //
+
+                if( pCurrentEntry->leftLink != NULL)
+                {
+                    pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
+                }
+                else
+                {
+
+                    //
+                    // Located the branch line end so insert the node here
+                    //
+
+                    pCurrentEntry->leftLink = (void *)FileIDEntry;
+
+                    FileIDEntry->parentLink = (void *)pCurrentEntry;
+
+                    break;
+                }
+            }
+            else
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_WARNING,
+                              "AFSInsertHashEntry Attempt to re-insert a CRC %I64X\n",
+                              FileIDEntry->HashIndex);
+
+                ASSERT( FALSE);
+
+                ntStatus = STATUS_UNSUCCESSFUL;
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRemoveHashEntry( IN AFSBTreeEntry **TopNode,
+                    IN AFSBTreeEntry *FileIDEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    AFSBTreeEntry *pRightNode = NULL;
+    AFSBTreeEntry *pLeftNode = NULL;
+    AFSBTreeEntry *pCurrentNode = NULL;
+    AFSBTreeEntry *pParentNode = NULL;
+
+    pRightNode = (AFSBTreeEntry *)FileIDEntry->rightLink;
+    pLeftNode = (AFSBTreeEntry *)FileIDEntry->leftLink;
+    pParentNode = (AFSBTreeEntry *)FileIDEntry->parentLink;
+
+    __Enter
+    {
+
+        if( (pRightNode == NULL) && (pLeftNode == NULL))
+        {
+
+            if( pParentNode != NULL)
+            {
+
+                if( pParentNode->leftLink == FileIDEntry)
+                {
+
+                    pParentNode->leftLink = NULL;
+                }
+                else
+                {
+
+                    pParentNode->rightLink = NULL;
+                }
+            }
+            else
+            {
+
+                //
+                // Removing the top node
+                //
+
+                *TopNode = NULL;
+            }
+        }
+        else
+        {
+
+            if( pRightNode != NULL)
+            {
+
+                if( pParentNode != NULL)
+                {
+
+                    // Replace the parent node where this entry was.
+                    if( pParentNode->rightLink == FileIDEntry)
+                    {
+
+                        pParentNode->rightLink = pRightNode;
+                    }
+                    else
+                    {
+
+                        pParentNode->leftLink = pRightNode;
+                    }
+                }
+                else
+                {
+
+                    *TopNode = pRightNode;
+
+                    pRightNode->parentLink = NULL;
+                }
+
+                pRightNode->parentLink = pParentNode;
+            }
+
+            if( pLeftNode != NULL)
+            {
+
+                // To connect the left node, we must walk the chain of the
+                // right nodes left side until we reach the end.
+                // At the end attach the leftNode
+                if( pRightNode != NULL)
+                {
+
+                    pCurrentNode = pRightNode;
+
+                    while( pCurrentNode->leftLink != NULL)
+                    {
+
+                        pCurrentNode = (AFSBTreeEntry *)pCurrentNode->leftLink;
+                    }
+
+                    pCurrentNode->leftLink = pLeftNode;
+
+                    pLeftNode->parentLink = pCurrentNode;
+                }
+                else
+                {
+
+                    if( pParentNode != NULL)
+                    {
+
+                        // This is where we have a left node with no right node.
+                        // So, attach the left node to the parent of
+                        // the removed nodes branch
+                        if( pParentNode->rightLink == FileIDEntry)
+                        {
+
+                            pParentNode->rightLink = pLeftNode;
+                        }
+                        else
+                        {
+
+                            pParentNode->leftLink = pLeftNode;
+                        }
+
+                        pLeftNode->parentLink = pParentNode;
+                    }
+                    else
+                    {
+
+                        *TopNode = pLeftNode;
+
+                        pLeftNode->parentLink = NULL;
+                    }
+                }
+            }
+        }
+
+        //
+        // Cleanup the just removed node
+        //
+
+        FileIDEntry->leftLink = NULL;
+        FileIDEntry->parentLink = NULL;
+        FileIDEntry->rightLink = NULL;
+
+        ntStatus = STATUS_SUCCESS;
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/lib/AFSCleanup.cpp b/src/WINNT/afsrdr/kernel/lib/AFSCleanup.cpp
new file mode 100644 (file)
index 0000000..be8fedd
--- /dev/null
@@ -0,0 +1,1151 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice,
+ *   this list of conditions and the following disclaimer in the
+ *   documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ *   nor the names of their contributors may be used to endorse or promote
+ *   products derived from this software without specific prior written
+ *   permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// File: AFSCleanup.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSCleanup
+//
+// Description:
+//
+//      This function is the IRP_MJ_CLEANUP dispatch handler
+//
+// Return:
+//
+//       A status is returned for the handling of this request
+//
+
+NTSTATUS
+AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
+            IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = NULL;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSFcb *pFcb = NULL;
+    AFSCcb *pCcb = NULL;
+    PFILE_OBJECT pFileObject = NULL;
+    AFSFcb *pRootFcb = NULL;
+    AFSDeviceExt *pControlDeviceExt = NULL;
+    IO_STATUS_BLOCK stIoSB;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+    AFSFileCleanupCB stFileCleanup;
+    ULONG   ulNotificationFlags = 0;
+
+    __try
+    {
+
+        if( AFSRDRDeviceObject == NULL)
+        {
+
+            //
+            // Let this through, it's a cleanup on the library control device
+            //
+
+            try_return( ntStatus);
+        }
+
+        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+        pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+
+        //
+        // Set some initial variables to make processing easier
+        //
+
+        pFileObject = pIrpSp->FileObject;
+
+        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
+
+        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
+
+        if( pFcb == NULL)
+        {
+            try_return( ntStatus);
+        }
+
+        pObjectInfo = pFcb->ObjectInformation;
+
+        pRootFcb = pObjectInfo->VolumeCB->RootFcb;
+
+        RtlZeroMemory( &stFileCleanup,
+                       sizeof( AFSFileCleanupCB));
+
+        stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
+
+        //
+        // Perform the cleanup functionality depending on the type of node it is
+        //
+
+        switch( pFcb->Header.NodeTypeCode)
+        {
+
+            case AFS_ROOT_ALL:
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                  TRUE);
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
+                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
+                                    pCcb);
+
+                break;
+            }
+
+            case AFS_IOCTL_FCB:
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                  TRUE);
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                //
+                // Decrement the open child handle count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL &&
+                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+                {
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                }
+
+                //
+                // And finally, release the Fcb if we acquired it.
+                //
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                break;
+            }
+
+            //
+            // This Fcb represents a file
+            //
+
+            case AFS_FILE_FCB:
+            {
+
+                //
+                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                TRUE);
+
+                //
+                // Uninitialize the cache map. This call is unconditional.
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
+                              pFcb,
+                              pFileObject);
+
+                CcUninitializeCacheMap( pFileObject,
+                                        NULL,
+                                        NULL);
+
+                //
+                // Unlock all outstanding locks on the file, again, unconditionally
+                //
+
+                (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
+                                           pFileObject,
+                                           IoGetRequestorProcess( Irp),
+                                           NULL);
+
+                //
+                // Tell the service to unlock all on the file
+                //
+
+                ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;
+
+                //
+                // Perform some final common processing
+                //
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                {
+
+                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                }
+
+                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                {
+
+                    stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;
+
+                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
+                    {
+
+                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
+                    {
+
+                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
+                    {
+
+                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
+                    {
+
+                        stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
+                    }
+                }
+
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
+                {
+
+                    stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
+                }
+
+                //
+                // If the count has dropped to zero and there is a pending delete
+                // then delete the node
+                //
+
+                if( pFcb->OpenHandleCount == 0 &&
+                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
+                {
+
+                    //
+                    // Stop anything possibly in process
+                    //
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
+                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                  PsGetCurrentThread());
+
+                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                    TRUE);
+
+                    pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
+
+                    KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
+                                0,
+                                FALSE);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
+                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                  PsGetCurrentThread());
+
+                    AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
+
+                    //
+                    // Before telling the server about the deleted file, tear down all extents for
+                    // the file
+                    //
+
+                    AFSTearDownFcbExtents( pFcb);
+
+                    ntStatus = STATUS_SUCCESS;
+
+                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
+
+                    //
+                    // Push the request to the service
+                    //
+
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pFcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  NULL,
+                                                  NULL);
+
+                    if( !NT_SUCCESS( ntStatus) &&
+                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
+                                      &pCcb->FullFileName,
+                                      ntStatus);
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
+                    }
+                    else
+                    {
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
+                                      &pCcb->FullFileName,
+                                      pCcb->DirectoryCB);
+
+                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
+
+                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
+                        //
+                        // Now that the service has the entry has deleted we need to remove it from the parent
+                        // tree so another lookup on the node will fail
+                        //
+
+                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
+
+                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                                                pCcb->DirectoryCB);
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+                }
+                else
+                {
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    {
+
+                        ULONG ulNotifyFilter = 0;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+
+                        ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)ulNotifyFilter,
+                                                        (ULONG)FILE_ACTION_MODIFIED);
+                    }
+
+                    //
+                    // Flush out any dirty pages on every handle close to reduce strain on the afs cache
+                    //
+
+                    if( CcIsFileCached( pIrpSp->FileObject))
+                    {
+
+                        __try
+                        {
+
+                            CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
+                                          NULL,
+                                          0,
+                                          &stIoSB);
+
+                            if( !NT_SUCCESS( stIoSB.Status))
+                            {
+
+                                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                                              AFS_TRACE_LEVEL_ERROR,
+                                              "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
+                                              &pCcb->FullFileName,
+                                              pObjectInfo->FileId.Cell,
+                                              pObjectInfo->FileId.Volume,
+                                              pObjectInfo->FileId.Vnode,
+                                              pObjectInfo->FileId.Unique,
+                                              stIoSB.Status,
+                                              stIoSB.Information);
+
+                                ntStatus = stIoSB.Status;
+                            }
+                        }
+                        __except( EXCEPTION_EXECUTE_HANDLER)
+                        {
+
+                            ntStatus = GetExceptionCode();
+                        }
+                    }
+
+                    //
+                    // Attempt to flush any dirty extents to the server. This may be a little
+                    // aggressive, to flush whenever the handle is closed, but it ensures
+                    // coherency.
+                    //
+
+                    if( pFcb->Specific.File.ExtentsDirtyCount)
+                    {
+
+                        AFSFlushExtents( pFcb);
+                    }
+
+                    if( pFcb->OpenHandleCount == 0)
+                    {
+
+                        //
+                        // Wait for any outstanding queued flushes to complete
+                        //
+
+                        AFSWaitOnQueuedFlushes( pFcb);
+
+                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
+                    }
+
+                    //
+                    // Push the request to the service
+                    //
+
+                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                       &pFcb->AuthGroup,
+                                       &pCcb->DirectoryCB->NameInformation.FileName,
+                                       &pObjectInfo->FileId,
+                                       &stFileCleanup,
+                                       sizeof( AFSFileCleanupCB),
+                                       NULL,
+                                       NULL);
+                }
+
+                //
+                // Remove the share access at this time since we may not get the close for sometime on this FO.
+                //
+
+                IoRemoveShareAccess( pFileObject,
+                                     &pFcb->ShareAccess);
+
+                //
+                // We don't need the name array after the user closes the handle on the file
+                //
+
+                if( pCcb->NameArray != NULL)
+                {
+
+                    AFSFreeNameArray( pCcb->NameArray);
+
+                    pCcb->NameArray = NULL;
+                }
+
+                //
+                // Decrement the open child handle count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL)
+                {
+
+                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                }
+
+                //
+                // And finally, release the Fcb if we acquired it.
+                //
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                break;
+            }
+
+            //
+            // Root or directory node
+            //
+
+            case AFS_ROOT_FCB:
+            {
+
+                //
+                // Set the root Fcb to this node
+                //
+
+                pRootFcb = pFcb;
+
+                //
+                // Fall through to below
+                //
+            }
+
+            case AFS_DIRECTORY_FCB:
+            {
+
+                //
+                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                  TRUE);
+
+                //
+                // Perform some final common processing
+                //
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                {
+
+                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                }
+
+                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                {
+
+                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
+                    {
+
+                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
+                    {
+
+                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
+                    {
+
+                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
+                    }
+                }
+
+                //
+                // If the count has dropped to zero and there is a pending delete
+                // then delete the node
+                //
+
+                if( pFcb->OpenHandleCount == 0 &&
+                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
+                {
+
+                    //
+                    // Try to notify the service about the delete
+                    //
+
+                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
+
+                    //
+                    // Push the request to the service
+                    //
+
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pFcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  NULL,
+                                                  NULL);
+
+                    if( !NT_SUCCESS( ntStatus) &&
+                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
+                                      &pCcb->FullFileName,
+                                      ntStatus);
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
+                    }
+                    else
+                    {
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
+                                      &pCcb->FullFileName,
+                                      pCcb->DirectoryCB);
+
+                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
+
+                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
+                        //
+                        // Now that the service has the entry has deleted we need to remove it from the parent
+                        // tree so another lookup on the node will fail
+                        //
+
+                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
+
+                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                                                pCcb->DirectoryCB);
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+                }
+
+                //
+                // If there have been any updates to the node then push it to
+                // the service
+                //
+
+                else
+                {
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    {
+
+                        ULONG ulNotifyFilter = 0;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+
+                        if(  pObjectInfo->ParentObjectInformation != NULL)
+                        {
+
+                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
+
+                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                            pCcb,
+                                                            (ULONG)ulNotifyFilter,
+                                                            (ULONG)FILE_ACTION_MODIFIED);
+                        }
+                    }
+
+                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                       &pFcb->AuthGroup,
+                                       &pCcb->DirectoryCB->NameInformation.FileName,
+                                       &pObjectInfo->FileId,
+                                       &stFileCleanup,
+                                       sizeof( AFSFileCleanupCB),
+                                       NULL,
+                                       NULL);
+                }
+
+                //
+                // Release the notification for this directory if there is one
+                //
+
+                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
+                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
+                                    pCcb);
+
+                //
+                // Remove the share access at this time since we may not get the close for sometime on this FO.
+                //
+
+                IoRemoveShareAccess( pFileObject,
+                                     &pFcb->ShareAccess);
+
+                //
+                // We don't need the name array after the user closes the handle on the file
+                //
+
+                if( pCcb->NameArray != NULL)
+                {
+
+                    AFSFreeNameArray( pCcb->NameArray);
+
+                    pCcb->NameArray = NULL;
+                }
+
+                //
+                // Decrement the open child handle count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL)
+                {
+
+                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                }
+
+                //
+                // And finally, release the Fcb if we acquired it.
+                //
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                break;
+            }
+
+            case AFS_SYMBOLIC_LINK_FCB:
+            case AFS_MOUNT_POINT_FCB:
+            case AFS_DFS_LINK_FCB:
+            {
+
+                //
+                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                  TRUE);
+
+                //
+                // Perform some final common processing
+                //
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
+                {
+
+                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
+                }
+
+                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                {
+
+                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
+                    {
+
+                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
+                    {
+
+                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
+                    }
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
+                    {
+
+                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
+                    }
+                }
+
+                //
+                // If the count has dropped to zero and there is a pending delete
+                // then delete the node
+                //
+
+                if( pFcb->OpenHandleCount == 0 &&
+                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
+                {
+
+                    //
+                    // Try to notify the service about the delete
+                    //
+
+                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;
+
+                    //
+                    // Push the request to the service
+                    //
+
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                                  &pFcb->AuthGroup,
+                                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                                  &pObjectInfo->FileId,
+                                                  &stFileCleanup,
+                                                  sizeof( AFSFileCleanupCB),
+                                                  NULL,
+                                                  NULL);
+
+                    if( !NT_SUCCESS( ntStatus) &&
+                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
+                                      &pCcb->FullFileName,
+                                      ntStatus);
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
+                    }
+                    else
+                    {
+
+                        ntStatus = STATUS_SUCCESS;
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
+                                      &pCcb->FullFileName,
+                                      pCcb->DirectoryCB);
+
+                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);
+
+                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);
+
+                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                        pCcb,
+                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                        (ULONG)FILE_ACTION_REMOVED);
+
+                        //
+                        // Now that the service has the entry has deleted we need to remove it from the parent
+                        // tree so another lookup on the node will fail
+                        //
+
+                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+                        {
+
+                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                            TRUE);
+
+                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
+                                                pCcb->DirectoryCB);
+
+                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                        }
+                    }
+                }
+
+                //
+                // If there have been any updates to the node then push it to
+                // the service
+                //
+
+                else
+                {
+
+                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
+                    {
+
+                        ULONG ulNotifyFilter = 0;
+
+                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
+
+                        if(  pObjectInfo->ParentObjectInformation != NULL)
+                        {
+
+                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);
+
+                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
+                                                            pCcb,
+                                                            (ULONG)ulNotifyFilter,
+                                                            (ULONG)FILE_ACTION_MODIFIED);
+                        }
+                    }
+
+                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
+                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                       &pFcb->AuthGroup,
+                                       &pCcb->DirectoryCB->NameInformation.FileName,
+                                       &pObjectInfo->FileId,
+                                       &stFileCleanup,
+                                       sizeof( AFSFileCleanupCB),
+                                       NULL,
+                                       NULL);
+                }
+
+                //
+                // Remove the share access at this time since we may not get the close for sometime on this FO.
+                //
+
+                IoRemoveShareAccess( pFileObject,
+                                     &pFcb->ShareAccess);
+
+                //
+                // We don't need the name array after the user closes the handle on the file
+                //
+
+                if( pCcb->NameArray != NULL)
+                {
+
+                    AFSFreeNameArray( pCcb->NameArray);
+
+                    pCcb->NameArray = NULL;
+                }
+
+                //
+                // Decrement the open child handle count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL)
+                {
+
+                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                }
+
+                //
+                // And finally, release the Fcb if we acquired it.
+                //
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                break;
+            }
+
+            case AFS_SPECIAL_SHARE_FCB:
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                TRUE);
+
+                ASSERT( pFcb->OpenHandleCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenHandleCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenHandleCount);
+
+                //
+                // Decrement the open child handle count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL &&
+                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+                {
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+                }
+
+                //
+                // And finally, release the Fcb if we acquired it.
+                //
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                break;
+            }
+
+            default:
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_WARNING,
+                              "AFSCleanup Processing unknown node type %d\n",
+                              pFcb->Header.NodeTypeCode);
+
+                break;
+        }
+
+
+try_exit:
+
+        if( pFileObject != NULL)
+        {
+
+            //
+            // Setup the fileobject flags to indicate cleanup is complete.
+            //
+
+            SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
+        }
+
+        //
+        // Complete the request
+        //
+
+        AFSCompleteRequest( Irp, ntStatus);
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSCleanup\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/lib/AFSClose.cpp b/src/WINNT/afsrdr/kernel/lib/AFSClose.cpp
new file mode 100644 (file)
index 0000000..b97d64f
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice,
+ *   this list of conditions and the following disclaimer in the
+ *   documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ *   nor the names of their contributors may be used to endorse or promote
+ *   products derived from this software without specific prior written
+ *   permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// File: AFSClose.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSClose
+//
+// Description:
+//
+//      This function is the IRP_MJ_CLOSE dispatch handler
+//
+// Return:
+//
+//       A status is returned for the handling of this request
+//
+
+NTSTATUS
+AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
+          IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulRequestType = 0;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSFcb *pFcb = NULL;
+    AFSDeviceExt *pDeviceExt = NULL;
+    AFSCcb *pCcb = NULL;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+    AFSDirectoryCB *pDirCB = NULL;
+
+    __try
+    {
+
+        if( AFSRDRDeviceObject == NULL)
+        {
+
+            //
+            // Let this through, it's an close on the library control device
+            //
+
+            try_return( ntStatus);
+        }
+
+        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
+
+        if( pFcb == NULL)
+        {
+            try_return( ntStatus);
+        }
+
+        pObjectInfo = pFcb->ObjectInformation;
+
+        //
+        // Perform the close functionality depending on the type of node it is
+        //
+
+        switch( pFcb->Header.NodeTypeCode)
+        {
+
+            case AFS_IOCTL_FCB:
+            {
+
+                AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
+                AFSFileID stParentFileId;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                  TRUE);
+
+                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
+
+                //
+                // Send the close to the CM
+                //
+
+                RtlZeroMemory( &stPIOCtlClose,
+                               sizeof( AFSPIOCtlOpenCloseRequestCB));
+
+                stPIOCtlClose.RequestId = pCcb->RequestID;
+
+                stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
+
+                RtlZeroMemory( &stParentFileId,
+                               sizeof( AFSFileID));
+
+                stParentFileId = pObjectInfo->ParentObjectInformation->FileId;
+
+                //
+                // Issue the close request to the service
+                //
+
+                AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
+                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                   &pFcb->AuthGroup,
+                                   NULL,
+                                   &stParentFileId,
+                                   (void *)&stPIOCtlClose,
+                                   sizeof( AFSPIOCtlOpenCloseRequestCB),
+                                   NULL,
+                                   NULL);
+
+                pDirCB = pCcb->DirectoryCB;
+
+                //
+                // Remove the Ccb and de-allocate it
+                //
+
+                ntStatus = AFSRemoveCcb( pCcb);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_WARNING,
+                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
+
+                    //
+                    // We can't actually fail a close operation so reset the status
+                    //
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+
+                ASSERT( pDirCB->OpenReferenceCount > 0);
+
+                InterlockedDecrement( &pDirCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirCB->NameInformation.FileName,
+                              pDirCB,
+                              pCcb,
+                              pDirCB->OpenReferenceCount);
+
+                //
+                // If this is not the root then decrement the open child reference count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL &&
+                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
+                {
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSClose (IOCtl) Decrement child open ref count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+                }
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                ASSERT( pFcb->OpenReferenceCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose (IOCtl) Decrement count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenReferenceCount);
+
+                break;
+            }
+
+            case AFS_ROOT_ALL:
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Acquiring Special Root ALL lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                TRUE);
+
+                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
+
+                pDirCB = pCcb->DirectoryCB;
+
+                //
+                // Remove the Ccb and de-allocate it
+                //
+
+                ntStatus = AFSRemoveCcb( pCcb);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_WARNING,
+                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
+
+                    //
+                    // We can't actually fail a close operation so reset the status
+                    //
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+
+                ASSERT( pDirCB->OpenReferenceCount > 0);
+
+                InterlockedDecrement( &pDirCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirCB->NameInformation.FileName,
+                              pDirCB,
+                              pCcb,
+                              pDirCB->OpenReferenceCount);
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                ASSERT( pFcb->OpenReferenceCount > 0);
+
+                InterlockedDecrement( &pFcb->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose (RootAll) Decrement count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenReferenceCount);
+
+                break;
+            }
+
+            //
+            // Root, file or directory node
+            //
+
+            case AFS_FILE_FCB:
+            case AFS_ROOT_FCB:
+            case AFS_DIRECTORY_FCB:
+            case AFS_SYMBOLIC_LINK_FCB:
+            case AFS_MOUNT_POINT_FCB:
+            case AFS_DFS_LINK_FCB:
+            {
+
+                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
+
+                //
+                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Acquiring Dcb lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                TRUE);
+
+                KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);
+
+                pDirCB = pCcb->DirectoryCB;
+
+                //
+                // Remove the Ccb and de-allocate it
+                //
+
+                ntStatus = AFSRemoveCcb( pCcb);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_WARNING,
+                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n",
+                                  ntStatus);
+
+                    //
+                    // We can't actually fail a close operation so reset the status
+                    //
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+
+                //
+                // If this entry is deleted then remove the object from the volume tree
+                //
+
+                if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
+                {
+
+                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
+                    {
+
+                        //
+                        // Stop anything possibly in process
+                        //
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSClose Acquiring Fcb extents lock %08lX EXCL %08lX\n",
+                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                      PsGetCurrentThread());
+
+                        AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                        TRUE);
+
+                        pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
+
+                        KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
+                                    0,
+                                    FALSE);
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSClose Releasing Fcb extents lock %08lX EXCL %08lX\n",
+                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
+                                      PsGetCurrentThread());
+
+                        AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
+                    }
+
+                    AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                    TRUE);
+
+                    AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
+                                    TRUE);
+
+                    if ( pDirCB->OpenReferenceCount == 0)
+                    {
+                        AFSDbgLogMsg( 0,
+                                      0,
+                                      "AFSClose (Other) OpenReferenceCount is Zero on DE %08lX Ccb %08lX FileName %wZ\n",
+                                      pDirCB,
+                                      pCcb,
+                                      &pDirCB->NameInformation.FileName);
+                    }
+
+                    ASSERT( pDirCB->OpenReferenceCount > 0);
+
+                    InterlockedDecrement( &pDirCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pDirCB->NameInformation.FileName,
+                                  pDirCB,
+                                  pCcb,
+                                  pDirCB->OpenReferenceCount);
+
+                    if( pDirCB->OpenReferenceCount == 0)
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSClose Deleting dir etry %08lX (%08lX) for %wZ\n",
+                                      pDirCB,
+                                      pObjectInfo,
+                                      &pDirCB->NameInformation.FileName);
+
+                        //
+                        // Remove and delete the directory entry from the parent list
+                        //
+
+                        AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation,
+                                           pDirCB);
+
+                        if( pObjectInfo->ObjectReferenceCount == 0)
+                        {
+
+                            if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
+                            {
+
+                                AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSClose Removing object %08lX from volume tree\n",
+                                              pObjectInfo);
+
+                                AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
+                                                    &pObjectInfo->TreeEntry);
+
+                                ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
+                            }
+
+                            SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
+                        }
+                    }
+
+                    AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                    AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
+                }
+                else
+                {
+
+                    ASSERT( pDirCB->OpenReferenceCount > 0);
+
+                    InterlockedDecrement( &pDirCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pDirCB->NameInformation.FileName,
+                                  pDirCB,
+                                  pCcb,
+                                  pDirCB->OpenReferenceCount);
+                }
+
+                //
+                // If this is not the root then decrement the open child reference count
+                //
+
+                if( pObjectInfo != NULL &&
+                    pObjectInfo->ParentObjectInformation != NULL &&
+                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
+                {
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSClose Decrement child open ref count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+                }
+
+                if( pFcb->OpenReferenceCount == 1 &&
+                    pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
+                {
+
+                    SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
+
+                    //
+                    // Attempt to tear down our extent list for the file
+                    // If there are remaining dirty extents then attempt to
+                    // flush them as well
+                    //
+
+                    if( pFcb->Specific.File.ExtentsDirtyCount)
+                    {
+
+                        AFSFlushExtents( pFcb);
+                    }
+
+                    //
+                    // Wait for any outstanding queued flushes to complete
+                    //
+
+                    AFSWaitOnQueuedFlushes( pFcb);
+
+                    ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
+                            pFcb->Specific.File.QueuedFlushCount == 0);
+
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                    //
+                    // Tear 'em down, we'll not be needing them again
+                    //
+
+                    if( AFSTearDownFcbExtents( pFcb))
+                    {
+
+                        //
+                        // Indicate to the service that the file required complete flushing to the
+                        // server.
+                        //
+
+                        AFSProcessRequest( AFS_REQUEST_TYPE_FLUSH_FILE,
+                                           AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                           &pFcb->AuthGroup,
+                                           NULL,
+                                           &pFcb->ObjectInformation->FileId,
+                                           NULL,
+                                           0,
+                                           NULL,
+                                           NULL);
+                    }
+                }
+                else
+                {
+
+                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
+                    {
+
+                        if( pFcb->Specific.File.ExtentsDirtyCount)
+                        {
+
+                            AFSFlushExtents( pFcb);
+                        }
+                    }
+
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
+                }
+
+                //
+                // Decrement the reference count on the Fcb. this is protecting it from teardown.
+                //
+
+                ASSERT( pFcb->OpenReferenceCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Decrement count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenReferenceCount);
+
+                break;
+            }
+
+            case AFS_SPECIAL_SHARE_FCB:
+            {
+
+                AFSPipeOpenCloseRequestCB stPipeClose;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose Acquiring Special Share lock %08lX EXCL %08lX\n",
+                              &pFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                TRUE);
+
+                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
+
+                pDirCB = pCcb->DirectoryCB;
+
+                RtlZeroMemory( &stPipeClose,
+                               sizeof( AFSPipeOpenCloseRequestCB));
+
+                stPipeClose.RequestId = pCcb->RequestID;
+
+                stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;
+
+                //
+                // Issue the open request to the service
+                //
+
+                /*
+                AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
+                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                   &pFcb->AuthGroup,
+                                   &pDirCB->NameInformation.FileName,
+                                   NULL,
+                                   (void *)&stPipeClose,
+                                   sizeof( AFSPipeOpenCloseRequestCB),
+                                   NULL,
+                                   NULL);
+                */
+
+                //
+                // Remove the Ccb and de-allocate it
+                //
+
+                ntStatus = AFSRemoveCcb( pCcb);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_WARNING,
+                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);
+
+                    //
+                    // We can't actually fail a close operation so reset the status
+                    //
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+
+                ASSERT( pDirCB->OpenReferenceCount > 0);
+
+                InterlockedDecrement( &pDirCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirCB->NameInformation.FileName,
+                              pDirCB,
+                              pCcb,
+                              pDirCB->OpenReferenceCount);
+
+                //
+                // If this is not the root then decrement the open child reference count
+                //
+
+                if( pObjectInfo->ParentObjectInformation != NULL &&
+                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
+                {
+
+                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSClose (Share) Decrement child open ref count on Parent object %08lX Cnt %d\n",
+                                  pObjectInfo->ParentObjectInformation,
+                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+                }
+
+                AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+                ASSERT( pFcb->OpenReferenceCount != 0);
+
+                InterlockedDecrement( &pFcb->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSClose (Share) Decrement count on Fcb %08lX Cnt %d\n",
+                              pFcb,
+                              pFcb->OpenReferenceCount);
+
+                break;
+            }
+
+            default:
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSClose Processing unknown node type %d\n",
+                              pFcb->Header.NodeTypeCode);
+
+                break;
+        }
+
+try_exit:
+
+        //
+        // Complete the request
+        //
+
+        AFSCompleteRequest( Irp,
+                            ntStatus);
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSClose\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/lib/AFSCommSupport.cpp b/src/WINNT/afsrdr/kernel/lib/AFSCommSupport.cpp
new file mode 100644 (file)
index 0000000..90e500e
--- /dev/null
@@ -0,0 +1,2067 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice,
+ *   this list of conditions and the following disclaimer in the
+ *   documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ *   nor the names of their contributors may be used to endorse or promote
+ *   products derived from this software without specific prior written
+ *   permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// File: AFSCommSupport.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSEnumerateDirectory( IN GUID *AuthGroup,
+                       IN AFSObjectInfoCB *ObjectInfoCB,
+                       IN BOOLEAN   FastQuery)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    void *pBuffer = NULL;
+    ULONG ulResultLen = 0;
+    AFSDirQueryCB *pDirQueryCB;
+    AFSDirEnumEntry *pCurrentDirEntry = NULL;
+    AFSDirectoryCB *pDirNode = NULL;
+    ULONG  ulEntryLength = 0;
+    AFSDirEnumResp *pDirEnumResponse = NULL;
+    UNICODE_STRING uniDirName, uniTargetName;
+    ULONG   ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+    ULONG ulCRC = 0;
+    UNICODE_STRING uniGUID;
+
+    __Enter
+    {
+
+        uniGUID.Length = 0;
+        uniGUID.MaximumLength = 0;
+        uniGUID.Buffer = NULL;
+
+        if( AuthGroup != NULL)
+        {
+            RtlStringFromGUID( *AuthGroup,
+                               &uniGUID);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
+                      ObjectInfoCB->FileId.Cell,
+                      ObjectInfoCB->FileId.Volume,
+                      ObjectInfoCB->FileId.Vnode,
+                      ObjectInfoCB->FileId.Unique,
+                      &uniGUID);
+
+        if( AuthGroup != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUID);
+        }
+
+        //
+        // Initialize the directory enumeration buffer for the directory
+        //
+
+        pBuffer = AFSExAllocatePoolWithTag( PagedPool,
+                                            AFS_DIR_ENUM_BUFFER_LEN,
+                                            AFS_DIR_BUFFER_TAG);
+
+        if( pBuffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pBuffer,
+                       AFS_DIR_ENUM_BUFFER_LEN);
+
+        ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
+
+        //
+        // Use the payload buffer for information we will pass to the service
+        //
+
+        pDirQueryCB = (AFSDirQueryCB *)pBuffer;
+
+        pDirQueryCB->EnumHandle = 0;
+
+        if( FastQuery)
+        {
+
+            ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
+        }
+
+        //
+        // Loop on the information
+        //
+
+        while( TRUE)
+        {
+
+            //
+            // Go and retrieve the directory contents
+            //
+
+            ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
+                                          ulRequestFlags,
+                                          AuthGroup,
+                                          NULL,
+                                          &ObjectInfoCB->FileId,
+                                          (void *)pDirQueryCB,
+                                          sizeof( AFSDirQueryCB),
+                                          pBuffer,
+                                          &ulResultLen);
+
+            if( ntStatus != STATUS_SUCCESS ||
+                ulResultLen == 0)
+            {
+
+                if( ntStatus == STATUS_NO_MORE_FILES ||
+                    ntStatus == STATUS_NO_MORE_ENTRIES)
+                {
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+                else
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSEnumerateDirectory Failed to enumerate directory Status %08lX\n",
+                                  ntStatus);
+                }
+
+                break;
+            }
+
+            pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
+
+            pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
+
+            //
+            // Remove the leading header from the processed length
+            //
+
+            ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
+
+            while( ulResultLen > 0)
+            {
+
+                uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
+
+                uniDirName.MaximumLength = uniDirName.Length;
+
+                uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
+
+                uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
+
+                uniTargetName.MaximumLength = uniTargetName.Length;
+
+                uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
+
+                //
+                // Be sure we don't have this entry in the case sensitive tree
+                //
+
+                ulCRC = AFSGenerateCRC( &uniDirName,
+                                        FALSE);
+
+                AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                ulCRC,
+                                                &pDirNode);
+
+                if( pDirNode != NULL)
+                {
+
+                    //
+                    // Duplicate entry, skip it
+                    //
+
+                    ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
+                                                    uniDirName.Length +
+                                                    uniTargetName.Length);
+
+                    pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                    if( ulResultLen >= ulEntryLength)
+                    {
+                        ulResultLen -= ulEntryLength;
+                    }
+                    else
+                    {
+                        ulResultLen = 0;
+                    }
+
+                    continue;
+                }
+
+                pDirNode = AFSInitDirEntry( ObjectInfoCB,
+                                            &uniDirName,
+                                            &uniTargetName,
+                                            pCurrentDirEntry,
+                                            (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
+
+                if( pDirNode == NULL)
+                {
+
+                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+                    break;
+                }
+
+                //
+                // Set up the entry length
+                //
+
+                ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
+                                                    pCurrentDirEntry->FileNameLength +
+                                                    pCurrentDirEntry->TargetNameLength);
+
+                //
+                // Init the short name if we have one
+                //
+
+                if( pCurrentDirEntry->ShortNameLength > 0)
+                {
+
+                    UNICODE_STRING uniShortName;
+
+                    pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
+
+                    RtlCopyMemory( pDirNode->NameInformation.ShortName,
+                                   pCurrentDirEntry->ShortName,
+                                   pDirNode->NameInformation.ShortNameLength);
+
+                    //
+                    // Generate the short name index
+                    //
+
+                    uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
+                    uniShortName.Buffer = pDirNode->NameInformation.ShortName;
+
+                    pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
+                                                                                       TRUE);
+                }
+
+                //
+                // Insert the node into the name tree
+                //
+
+                ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
+                }
+                else
+                {
+
+                    AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                    pDirNode);
+                }
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
+
+                    SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+                }
+                else
+                {
+
+                    AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
+                                                      pDirNode);
+                }
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
+                }
+                else
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
+
+                    pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
+                }
+
+                ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
+
+                SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
+
+                InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                  &pDirNode->NameInformation.FileName,
+                                  ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
+                                  ObjectInfoCB->FileId.Cell,
+                                  ObjectInfoCB->FileId.Volume,
+                                  ObjectInfoCB->FileId.Vnode,
+                                  ObjectInfoCB->FileId.Unique);
+
+                if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
+                {
+
+                    //
+                    // Insert the short name entry if we have a valid short name
+                    //
+
+                    if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
+                    {
+
+                        ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
+                    }
+                    else
+                    {
+
+                        AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
+                                                    pDirNode);
+                    }
+                }
+
+                //
+                // Next dir entry
+                //
+
+                pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                if( ulResultLen >= ulEntryLength)
+                {
+                    ulResultLen -= ulEntryLength;
+                }
+                else
+                {
+                    ulResultLen = 0;
+                }
+            }
+
+            ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
+
+            //
+            // Reset the information in the request buffer since it got trampled
+            // above
+            //
+
+            pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSEnumerateDirectory EnumHandle %08lX\n",
+                          pDirQueryCB->EnumHandle);
+
+            //
+            // If the enumeration handle is -1 then we are done
+            //
+
+            if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
+            {
+
+                break;
+            }
+        }
+
+try_exit:
+
+        //
+        // Cleanup
+        //
+
+        if( pBuffer != NULL)
+        {
+
+            AFSExFreePool( pBuffer);
+        }
+
+        //
+        // If the processing failed then we should reset the directory content in the event
+        // it is re-enumerated
+        //
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                                      ObjectInfoCB->FileId.Cell,
+                                      ObjectInfoCB->FileId.Volume,
+                                      ObjectInfoCB->FileId.Vnode,
+                                      ObjectInfoCB->FileId.Unique,
+                                      ntStatus);
+
+            AFSResetDirectoryContent( ObjectInfoCB);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
+                                 IN AFSFileID *FileId)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDirQueryCB stDirQueryCB;
+    ULONG   ulRequestFlags = 0;
+
+    __Enter
+    {
+
+        //
+        // Use the payload buffer for information we will pass to the service
+        //
+
+        stDirQueryCB.EnumHandle = 0;
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
+                                      ulRequestFlags,
+                                      AuthGroup,
+                                      NULL,
+                                      FileId,
+                                      (void *)&stDirQueryCB,
+                                      sizeof( AFSDirQueryCB),
+                                      NULL,
+                                      NULL);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            if( ntStatus == STATUS_NO_MORE_FILES ||
+                ntStatus == STATUS_NO_MORE_ENTRIES)
+            {
+
+                ntStatus = STATUS_SUCCESS;
+            }
+            else
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
+                              ntStatus);
+            }
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
+                           IN GUID *AuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    void *pBuffer = NULL;
+    ULONG ulResultLen = 0;
+    AFSDirQueryCB *pDirQueryCB;
+    AFSDirEnumEntry *pCurrentDirEntry = NULL;
+    AFSDirectoryCB *pDirNode = NULL;
+    ULONG  ulEntryLength = 0;
+    AFSDirEnumResp *pDirEnumResponse = NULL;
+    UNICODE_STRING uniDirName, uniTargetName;
+    ULONG   ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
+    ULONG ulCRC = 0;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+    ULONGLONG ullIndex = 0;
+    UNICODE_STRING uniGUID;
+
+    __Enter
+    {
+
+        uniGUID.Length = 0;
+        uniGUID.MaximumLength = 0;
+        uniGUID.Buffer = NULL;
+
+        if( AuthGroup != NULL)
+        {
+            RtlStringFromGUID( *AuthGroup,
+                               &uniGUID);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
+                      ObjectInfoCB->FileId.Cell,
+                      ObjectInfoCB->FileId.Volume,
+                      ObjectInfoCB->FileId.Vnode,
+                      ObjectInfoCB->FileId.Unique,
+                      &uniGUID);
+
+        if( AuthGroup != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUID);
+        }
+
+        //
+        // Initialize the directory enumeration buffer for the directory
+        //
+
+        pBuffer = AFSExAllocatePoolWithTag( PagedPool,
+                                            AFS_DIR_ENUM_BUFFER_LEN,
+                                            AFS_DIR_BUFFER_TAG);
+
+        if( pBuffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pBuffer,
+                       AFS_DIR_ENUM_BUFFER_LEN);
+
+        ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
+
+        //
+        // Use the payload buffer for information we will pass to the service
+        //
+
+        pDirQueryCB = (AFSDirQueryCB *)pBuffer;
+
+        pDirQueryCB->EnumHandle = 0;
+
+        //
+        // Loop on the information
+        //
+
+        while( TRUE)
+        {
+
+            //
+            // Go and retrieve the directory contents
+            //
+
+            ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
+                                          ulRequestFlags,
+                                          AuthGroup,
+                                          NULL,
+                                          &ObjectInfoCB->FileId,
+                                          (void *)pDirQueryCB,
+                                          sizeof( AFSDirQueryCB),
+                                          pBuffer,
+                                          &ulResultLen);
+
+            if( ntStatus != STATUS_SUCCESS ||
+                ulResultLen == 0)
+            {
+
+                if( ntStatus == STATUS_NO_MORE_FILES ||
+                    ntStatus == STATUS_NO_MORE_ENTRIES)
+                {
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+                else
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSVerifyDirectoryContent Failed to enumerate directory Status %08lX\n",
+                                  ntStatus);
+                }
+
+                break;
+            }
+
+            pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
+
+            pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
+
+            //
+            // Remove the leading header from the processed length
+            //
+
+            ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
+
+            while( ulResultLen > 0)
+            {
+
+                uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
+
+                uniDirName.MaximumLength = uniDirName.Length;
+
+                uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
+
+                uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
+
+                uniTargetName.MaximumLength = uniTargetName.Length;
+
+                uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
+
+                //
+                // Does this entry already exist in the directory?
+                //
+
+                ulCRC = AFSGenerateCRC( &uniDirName,
+                                        FALSE);
+
+                ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
+
+                AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                ulCRC,
+                                                &pDirNode);
+
+                //
+                //
+                // Set up the entry length
+                //
+
+                ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
+                                           pCurrentDirEntry->FileNameLength +
+                                           pCurrentDirEntry->TargetNameLength);
+
+                if( pDirNode != NULL)
+                {
+
+                    //
+                    // Check that the FIDs are the same
+                    //
+
+                    if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
+                                       &pDirNode->ObjectInformation->FileId))
+                    {
+
+                        AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
+                                          TRUE);
+
+                        ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
+
+                        ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
+                                                       ullIndex,
+                                                       (AFSBTreeEntry **)&pObjectInfo);
+
+                        AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
+
+                        if( NT_SUCCESS( ntStatus) &&
+                            pObjectInfo != NULL)
+                        {
+
+                            //
+                            // Indicate this is a valid entry
+                            //
+
+                            SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSVerifyDirectoryContent Verified entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                                      &uniDirName,
+                                                      ObjectInfoCB->FileId.Cell,
+                                                      ObjectInfoCB->FileId.Volume,
+                                                      ObjectInfoCB->FileId.Vnode,
+                                                      ObjectInfoCB->FileId.Unique);
+
+
+                            //
+                            // Update the metadata for the entry
+                            //
+
+                            if( pObjectInfo->DataVersion.QuadPart == 0 ||
+                                pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
+                            {
+
+                                AFSUpdateMetaData( pDirNode,
+                                                   pCurrentDirEntry);
+
+                                if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
+                                {
+
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
+                                                              &uniDirName,
+                                                              ObjectInfoCB->FileId.Cell,
+                                                              ObjectInfoCB->FileId.Volume,
+                                                              ObjectInfoCB->FileId.Vnode,
+                                                              ObjectInfoCB->FileId.Unique);
+
+                                    SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                                    pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                                    pObjectInfo->Expiration.QuadPart = 0;
+                                }
+                            }
+
+                            //
+                            // Next dir entry
+                            //
+
+                            pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                            if( ulResultLen >= ulEntryLength)
+                            {
+                                ulResultLen -= ulEntryLength;
+                            }
+                            else
+                            {
+                                ulResultLen = 0;
+                            }
+
+                            continue;
+                        }
+                    }
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSVerifyDirectoryContent Processing dir entry %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                  &pDirNode->NameInformation.FileName,
+                                  ObjectInfoCB->FileId.Cell,
+                                  ObjectInfoCB->FileId.Volume,
+                                  ObjectInfoCB->FileId.Vnode,
+                                  ObjectInfoCB->FileId.Unique);
+
+                    //
+                    // Need to tear down this entry and rebuild it below
+                    //
+
+                    if( pDirNode->OpenReferenceCount == 0)
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSVerifyDirectoryContent Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                      &pDirNode->NameInformation.FileName,
+                                      ObjectInfoCB->FileId.Cell,
+                                      ObjectInfoCB->FileId.Volume,
+                                      ObjectInfoCB->FileId.Vnode,
+                                      ObjectInfoCB->FileId.Unique);
+
+                        AFSDeleteDirEntry( ObjectInfoCB,
+                                           pDirNode);
+                    }
+                    else
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSVerifyDirectoryContent Setting dir entry %p name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                      pDirNode,
+                                      &pDirNode->NameInformation.FileName,
+                                      ObjectInfoCB->FileId.Cell,
+                                      ObjectInfoCB->FileId.Volume,
+                                      ObjectInfoCB->FileId.Vnode,
+                                      ObjectInfoCB->FileId.Unique);
+
+                        SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
+
+                        AFSRemoveNameEntry( ObjectInfoCB,
+                                            pDirNode);
+                    }
+                }
+
+                pDirNode = AFSInitDirEntry( ObjectInfoCB,
+                                            &uniDirName,
+                                            &uniTargetName,
+                                            pCurrentDirEntry,
+                                            (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
+
+                if( pDirNode == NULL)
+                {
+
+                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+                    break;
+                }
+
+                //
+                // Init the short name if we have one
+                //
+
+                if( pCurrentDirEntry->ShortNameLength > 0)
+                {
+
+                    UNICODE_STRING uniShortName;
+
+                    pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
+
+                    RtlCopyMemory( pDirNode->NameInformation.ShortName,
+                                   pCurrentDirEntry->ShortName,
+                                   pDirNode->NameInformation.ShortNameLength);
+
+                    //
+                    // Generate the short name index
+                    //
+
+                    uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
+                    uniShortName.Buffer = pDirNode->NameInformation.ShortName;
+
+                    pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
+                                                                                       TRUE);
+                }
+
+                //
+                // Insert the node into the name tree
+                //
+
+                ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
+                }
+                else
+                {
+
+                    AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                    pDirNode);
+                }
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
+
+                    SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+                }
+                else
+                {
+
+                    AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
+                                                      pDirNode);
+                }
+
+                if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
+                {
+
+                    ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
+                }
+                else
+                {
+
+                    (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
+
+                    pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
+                }
+
+                ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
+
+                SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
+
+                InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                  &pDirNode->NameInformation.FileName,
+                                  ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
+                                  ObjectInfoCB->FileId.Cell,
+                                  ObjectInfoCB->FileId.Volume,
+                                  ObjectInfoCB->FileId.Vnode,
+                                  ObjectInfoCB->FileId.Unique);
+
+                if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
+                {
+
+                    //
+                    // Insert the short name entry if we have a valid short name
+                    //
+
+                    if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
+                    {
+
+                        ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
+                    }
+                    else
+                    {
+
+                        AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
+                                                    pDirNode);
+                    }
+                }
+
+                //
+                // Next dir entry
+                //
+
+                pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                if( ulResultLen >= ulEntryLength)
+                {
+                    ulResultLen -= ulEntryLength;
+                }
+                else
+                {
+                    ulResultLen = 0;
+                }
+            }
+
+            ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
+
+            //
+            // Reset the information in the request buffer since it got trampled
+            // above
+            //
+
+            pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
+
+            //
+            // If the enumeration handle is -1 then we are done
+            //
+
+            if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
+            {
+
+                break;
+            }
+        }
+
+try_exit:
+
+        //
+        // Cleanup
+        //
+
+        if( pBuffer != NULL)
+        {
+
+            AFSExFreePool( pBuffer);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifyFileCreate( IN GUID            *AuthGroup,
+                     IN AFSObjectInfoCB *ParentObjectInfo,
+                     IN PLARGE_INTEGER FileSize,
+                     IN ULONG FileAttributes,
+                     IN UNICODE_STRING *FileName,
+                     OUT AFSDirectoryCB **DirNode)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFileCreateCB stCreateCB;
+    AFSFileCreateResultCB *pResultCB = NULL;
+    ULONG ulResultLen = 0;
+    UNICODE_STRING uniTargetName;
+    AFSDirectoryCB *pDirNode = NULL;
+    ULONG     ulCRC = 0;
+    LARGE_INTEGER liOldDataVersion;
+
+    __Enter
+    {
+
+        //
+        // Init the control block for the request
+        //
+
+        RtlZeroMemory( &stCreateCB,
+                       sizeof( AFSFileCreateCB));
+
+        stCreateCB.ParentId = ParentObjectInfo->FileId;
+
+        stCreateCB.AllocationSize = *FileSize;
+
+        stCreateCB.FileAttributes = FileAttributes;
+
+        stCreateCB.EaSize = 0;
+
+        liOldDataVersion = ParentObjectInfo->DataVersion;
+
+        //
+        // Allocate our return buffer
+        //
+
+        pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                       PAGE_SIZE,
+                                                                       AFS_GENERIC_MEMORY_1_TAG);
+
+        if( pResultCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pResultCB,
+                       PAGE_SIZE);
+
+        ulResultLen = PAGE_SIZE;
+
+        //
+        // Send the call to the service
+        //
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
+                                      AuthGroup,
+                                      FileName,
+                                      NULL,
+                                      &stCreateCB,
+                                      sizeof( AFSFileCreateCB),
+                                      pResultCB,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            if( NT_SUCCESS( ntStatus))
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
+        // and though we created the node, it is already in our list. If this is the case then
+        // look up the entry rather than create a new entry
+        // The check is to ensure the DV has been modified
+        //
+
+        if( liOldDataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1 ||
+            liOldDataVersion.QuadPart != ParentObjectInfo->DataVersion.QuadPart)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSNotifyFileCreate Raced with an invalidate call and a re-enumeration for entry %wZ\n",
+                          FileName);
+
+            //
+            // We raced so go and lookup the directory entry in the parent
+            //
+
+            ulCRC = AFSGenerateCRC( FileName,
+                                    FALSE);
+
+            AFSAcquireShared( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                              TRUE);
+
+            AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                            ulCRC,
+                                            &pDirNode);
+
+            AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+            if( pDirNode != NULL)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSNotifyFileCreate Located dir entry for file %wZ\n",
+                              FileName);
+
+                *DirNode = pDirNode;
+
+                try_return( ntStatus = STATUS_REPARSE);
+            }
+
+            //
+            // We are unsure of our current data so set the verify flag. It may already be set
+            // but no big deal to reset it
+            //
+
+            SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+
+            ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+        }
+        else
+        {
+
+            //
+            // Update the parent data version
+            //
+
+            ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSNotifyFileCreate Creating new entry %wZ\n",
+                      FileName);
+
+        //
+        // Initialize the directory entry
+        //
+
+        uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
+
+        uniTargetName.MaximumLength = uniTargetName.Length;
+
+        uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
+
+        pDirNode = AFSInitDirEntry( ParentObjectInfo,
+                                    FileName,
+                                    &uniTargetName,
+                                    &pResultCB->DirEnum,
+                                    (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
+
+        if( pDirNode == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Init the short name if we have one
+        //
+
+        if( pResultCB->DirEnum.ShortNameLength > 0)
+        {
+
+            UNICODE_STRING uniShortName;
+
+            pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
+
+            RtlCopyMemory( pDirNode->NameInformation.ShortName,
+                           pResultCB->DirEnum.ShortName,
+                           pDirNode->NameInformation.ShortNameLength);
+
+            //
+            // Generate the short name index
+            //
+
+            uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
+            uniShortName.Buffer = pDirNode->NameInformation.ShortName;
+
+            pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
+                                                                               TRUE);
+        }
+
+        //
+        // Return the directory node
+        //
+
+        *DirNode = pDirNode;
+
+try_exit:
+
+        if( pResultCB != NULL)
+        {
+
+            AFSExFreePool( pResultCB);
+        }
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSUpdateFileInformation( IN AFSFileID *ParentFid,
+                          IN AFSObjectInfoCB *ObjectInfo,
+                          IN GUID *AuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    AFSFileUpdateCB stUpdateCB;
+    ULONG ulResultLen = 0;
+    AFSFileUpdateResultCB *pUpdateResultCB = NULL;
+
+    __Enter
+    {
+
+        //
+        // Init the control block for the request
+        //
+
+        RtlZeroMemory( &stUpdateCB,
+                       sizeof( AFSFileUpdateCB));
+
+        stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
+
+        stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
+
+        stUpdateCB.EaSize = ObjectInfo->EaSize;
+
+        stUpdateCB.ParentId = *ParentFid;
+
+        stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
+
+        stUpdateCB.CreateTime = ObjectInfo->CreationTime;
+
+        stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
+
+        stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
+
+        pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                             PAGE_SIZE,
+                                                                             AFS_UPDATE_RESULT_TAG);
+
+        if( pUpdateResultCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        ulResultLen = PAGE_SIZE;
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      AuthGroup,
+                                      NULL,
+                                      &ObjectInfo->FileId,
+                                      &stUpdateCB,
+                                      sizeof( AFSFileUpdateCB),
+                                      pUpdateResultCB,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          ObjectInfo->FileId.Cell,
+                          ObjectInfo->FileId.Volume,
+                          ObjectInfo->FileId.Vnode,
+                          ObjectInfo->FileId.Unique,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Update the data version
+        //
+
+        ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
+
+try_exit:
+
+        if( pUpdateResultCB != NULL)
+        {
+
+            AFSExFreePool( pUpdateResultCB);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
+                 IN BOOLEAN CheckOnly)
+{
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulResultLen = 0;
+    AFSFileDeleteCB stDelete;
+    AFSFileDeleteResultCB stDeleteResult;
+    ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+    GUID *pAuthGroup = NULL;
+
+    __Enter
+    {
+
+        stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
+
+        stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
+
+        ulResultLen = sizeof( AFSFileDeleteResultCB);
+
+        if( CheckOnly)
+        {
+            ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
+        }
+
+        if( DirectoryCB->ObjectInformation->Fcb != NULL)
+        {
+            pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
+        }
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
+                                      ulRequestFlags,
+                                      pAuthGroup,
+                                      &DirectoryCB->NameInformation.FileName,
+                                      &DirectoryCB->ObjectInformation->FileId,
+                                      &stDelete,
+                                      sizeof( AFSFileDeleteCB),
+                                      &stDeleteResult,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          &DirectoryCB->ObjectInformation->FileId.Cell,
+                          &DirectoryCB->ObjectInformation->FileId.Volume,
+                          &DirectoryCB->ObjectInformation->FileId.Vnode,
+                          &DirectoryCB->ObjectInformation->FileId.Unique,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        if( !CheckOnly)
+        {
+
+            //
+            // Update the parent data version
+            //
+
+            if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
+            {
+
+                DirectoryCB->ObjectInformation->ParentObjectInformation->Flags |= AFS_OBJECT_FLAGS_VERIFY;
+
+                DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
+                 IN AFSObjectInfoCB *ParentObjectInfo,
+                 IN AFSObjectInfoCB *TargetParentObjectInfo,
+                 IN AFSDirectoryCB *DirectoryCB,
+                 IN UNICODE_STRING *TargetName,
+                 OUT AFSFileID  *UpdatedFID)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFileRenameCB *pRenameCB = NULL;
+    AFSFileRenameResultCB *pRenameResultCB = NULL;
+    ULONG ulResultLen = 0;
+    GUID *pAuthGroup = NULL;
+
+    __Enter
+    {
+
+        //
+        // Init the control block for the request
+        //
+
+        pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                 PAGE_SIZE,
+                                                                 AFS_RENAME_REQUEST_TAG);
+
+        if( pRenameCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pRenameCB,
+                       PAGE_SIZE);
+
+        pRenameCB->SourceParentId = ParentObjectInfo->FileId;
+
+        pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
+
+        pRenameCB->TargetNameLength = TargetName->Length;
+
+        RtlCopyMemory( pRenameCB->TargetName,
+                       TargetName->Buffer,
+                       TargetName->Length);
+
+        if( ObjectInfo->Fcb != NULL)
+        {
+            pAuthGroup = &ObjectInfo->Fcb->AuthGroup;
+        }
+
+        //
+        // Use the same buffer for the result control block
+        //
+
+        pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
+
+        ulResultLen = PAGE_SIZE;
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      pAuthGroup,
+                                      &DirectoryCB->NameInformation.FileName,
+                                      &ObjectInfo->FileId,
+                                      pRenameCB,
+                                      sizeof( AFSFileRenameCB) + TargetName->Length,
+                                      pRenameResultCB,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          ObjectInfo->FileId.Cell,
+                          ObjectInfo->FileId.Volume,
+                          ObjectInfo->FileId.Vnode,
+                          ObjectInfo->FileId.Unique,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Update the information from the returned data
+        //
+
+        ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
+
+        TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
+
+        //
+        // Move over the short name
+        //
+
+        DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
+
+        if( DirectoryCB->NameInformation.ShortNameLength > 0)
+        {
+
+            RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
+                           pRenameResultCB->DirEnum.ShortName,
+                           DirectoryCB->NameInformation.ShortNameLength);
+        }
+
+        if( UpdatedFID != NULL)
+        {
+
+            *UpdatedFID = pRenameResultCB->DirEnum.FileId;
+        }
+
+try_exit:
+
+        if( pRenameCB != NULL)
+        {
+
+            AFSExFreePool( pRenameCB);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
+                       IN GUID *AuthGroup,
+                       IN BOOLEAN FastCall,
+                       OUT AFSDirEnumEntry **DirEnumEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSEvalTargetCB stTargetID;
+    ULONG ulResultBufferLength;
+    AFSDirEnumEntry *pDirEnumCB = NULL;
+    ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+
+    __Enter
+    {
+
+        RtlZeroMemory( &stTargetID,
+                       sizeof( AFSEvalTargetCB));
+
+        if( ObjectInfo->ParentObjectInformation != NULL)
+        {
+
+            stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
+        }
+
+        //
+        // Allocate our response buffer
+        //
+
+        pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                  PAGE_SIZE,
+                                                                  AFS_GENERIC_MEMORY_2_TAG);
+
+        if( pDirEnumCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Call to the service to evaluate the fid
+        //
+
+        ulResultBufferLength = PAGE_SIZE;
+
+        if( FastCall)
+        {
+
+            ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
+        }
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
+                                      ulRequestFlags,
+                                      AuthGroup,
+                                      NULL,
+                                      &ObjectInfo->FileId,
+                                      &stTargetID,
+                                      sizeof( AFSEvalTargetCB),
+                                      pDirEnumCB,
+                                      &ulResultBufferLength);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            //
+            // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
+            // verification
+            //
+
+            if( ntStatus == STATUS_INVALID_HANDLE)
+            {
+
+                if( ObjectInfo->ParentObjectInformation != NULL)
+                {
+
+                    SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                }
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Pass back the dir enum entry
+        //
+
+        if( DirEnumEntry != NULL)
+        {
+
+            *DirEnumEntry = pDirEnumCB;
+        }
+        else
+        {
+
+            AFSExFreePool( pDirEnumCB);
+        }
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( pDirEnumCB != NULL)
+            {
+
+                AFSExFreePool( pDirEnumCB);
+            }
+
+            *DirEnumEntry = NULL;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSEvaluateTargetByName( IN GUID *AuthGroup,
+                         IN AFSFileID *ParentFileId,
+                         IN PUNICODE_STRING SourceName,
+                         OUT AFSDirEnumEntry **DirEnumEntry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSEvalTargetCB stTargetID;
+    ULONG ulResultBufferLength;
+    AFSDirEnumEntry *pDirEnumCB = NULL;
+
+    __Enter
+    {
+
+        stTargetID.ParentId = *ParentFileId;
+
+        //
+        // Allocate our response buffer
+        //
+
+        pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                  PAGE_SIZE,
+                                                                  AFS_GENERIC_MEMORY_3_TAG);
+
+        if( pDirEnumCB == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Call to the service to evaluate the fid
+        //
+
+        ulResultBufferLength = PAGE_SIZE;
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      AuthGroup,
+                                      SourceName,
+                                      NULL,
+                                      &stTargetID,
+                                      sizeof( AFSEvalTargetCB),
+                                      pDirEnumCB,
+                                      &ulResultBufferLength);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Pass back the dir enum entry
+        //
+
+        *DirEnumEntry = pDirEnumCB;
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( pDirEnumCB != NULL)
+            {
+
+                AFSExFreePool( pDirEnumCB);
+            }
+
+            *DirEnumEntry = NULL;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
+                              IN AFSFileID *FileID,
+                              OUT AFSVolumeInfoCB *VolumeInformation)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulResultLen = 0;
+
+    __Enter
+    {
+
+        ulResultLen = sizeof( AFSVolumeInfoCB);
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      AuthGroup,
+                                      NULL,
+                                      FileID,
+                                      NULL,
+                                      0,
+                                      VolumeInformation,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            try_return( ntStatus);
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
+                         IN ULONG InputLength,
+                         IN ULONG OutputLength,
+                         IN void *InputDataBuffer,
+                         OUT void *OutputDataBuffer,
+                         OUT ULONG *BytesReturned)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulResultLen = 0;
+    MDL *pInputMdl = NULL, *pOutputMdl = NULL;
+    void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
+    ULONG ulBufferLength = OutputLength;
+    AFSPipeIORequestCB *pIoRequest = NULL;
+    GUID *pAuthGroup = NULL;
+
+    __Enter
+    {
+
+        //
+        // Map the user buffer to a system address
+        //
+
+        pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
+                                                InputLength,
+                                                &pInputMdl);
+
+        if( pInputSystemBuffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                     sizeof( AFSPipeIORequestCB) +
+                                                                                InputLength,
+                                                                     AFS_GENERIC_MEMORY_4_TAG);
+
+        if( pIoRequest == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pIoRequest,
+                       sizeof( AFSPipeIORequestCB) + InputLength);
+
+        pIoRequest->RequestId = Ccb->RequestID;
+
+        pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
+
+        pIoRequest->BufferLength = InputLength;
+
+        RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
+                       pInputSystemBuffer,
+                       InputLength);
+
+        pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
+                                                 OutputLength,
+                                                 &pOutputMdl);
+
+        if( pOutputSystemBuffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
+        {
+            pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
+        }
+
+        //
+        // Send the call to the service
+        //
+
+        ulResultLen = OutputLength;
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      pAuthGroup,
+                                      &Ccb->DirectoryCB->NameInformation.FileName,
+                                      NULL,
+                                      pIoRequest,
+                                      sizeof( AFSPipeIORequestCB) + InputLength,
+                                      pOutputSystemBuffer,
+                                      &ulResultLen);
+
+        if( ntStatus != STATUS_SUCCESS &&
+            ntStatus != STATUS_BUFFER_OVERFLOW)
+        {
+
+            if( NT_SUCCESS( ntStatus))
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Return the bytes processed
+        //
+
+        *BytesReturned = ulResultLen;
+
+try_exit:
+
+        if( pInputMdl != NULL)
+        {
+
+            MmUnlockPages( pInputMdl);
+
+            IoFreeMdl( pInputMdl);
+        }
+
+        if( pOutputMdl != NULL)
+        {
+
+            MmUnlockPages( pOutputMdl);
+
+            IoFreeMdl( pOutputMdl);
+        }
+
+        if( pIoRequest != NULL)
+        {
+
+            AFSExFreePool( pIoRequest);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
+                      IN ULONG InformationClass,
+                      IN ULONG InputLength,
+                      IN void *DataBuffer)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSPipeInfoRequestCB *pInfoRequest = NULL;
+    GUID *pAuthGroup = NULL;
+
+    __Enter
+    {
+
+        pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                         sizeof( AFSPipeInfoRequestCB) +
+                                                                                InputLength,
+                                                                         AFS_GENERIC_MEMORY_5_TAG);
+
+        if( pInfoRequest == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pInfoRequest,
+                       sizeof( AFSPipeInfoRequestCB) + InputLength);
+
+        pInfoRequest->RequestId = Ccb->RequestID;
+
+        pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
+
+        pInfoRequest->BufferLength = InputLength;
+
+        pInfoRequest->InformationClass = InformationClass;
+
+        RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
+                       DataBuffer,
+                       InputLength);
+
+        if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
+        {
+            pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
+        }
+
+        //
+        // Send the call to the service
+        //
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      pAuthGroup,
+                                      &Ccb->DirectoryCB->NameInformation.FileName,
+                                      NULL,
+                                      pInfoRequest,
+                                      sizeof( AFSPipeInfoRequestCB) + InputLength,
+                                      NULL,
+                                      NULL);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            if( NT_SUCCESS( ntStatus))
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+            }
+
+            try_return( ntStatus);
+        }
+
+try_exit:
+
+        if( pInfoRequest != NULL)
+        {
+
+            AFSExFreePool( pInfoRequest);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
+                        IN ULONG InformationClass,
+                        IN ULONG OutputLength,
+                        IN void *DataBuffer,
+                        OUT ULONG *BytesReturned)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSPipeInfoRequestCB stInfoRequest;
+    ULONG ulBytesProcessed = 0;
+    GUID *pAuthGroup = NULL;
+
+    __Enter
+    {
+
+        RtlZeroMemory( &stInfoRequest,
+                       sizeof( AFSPipeInfoRequestCB));
+
+        stInfoRequest.RequestId = Ccb->RequestID;
+
+        stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
+
+        stInfoRequest.BufferLength = OutputLength;
+
+        stInfoRequest.InformationClass = InformationClass;
+
+        ulBytesProcessed = OutputLength;
+
+        if( Ccb->DirectoryCB->ObjectInformation->Fcb != NULL)
+        {
+            pAuthGroup = &Ccb->DirectoryCB->ObjectInformation->Fcb->AuthGroup;
+        }
+
+        //
+        // Send the call to the service
+        //
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                      pAuthGroup,
+                                      &Ccb->DirectoryCB->NameInformation.FileName,
+                                      NULL,
+                                      &stInfoRequest,
+                                      sizeof( AFSPipeInfoRequestCB),
+                                      DataBuffer,
+                                      &ulBytesProcessed);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+
+            if( NT_SUCCESS( ntStatus))
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+            }
+
+            try_return( ntStatus);
+        }
+
+        *BytesReturned = ulBytesProcessed;
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSReleaseFid( IN AFSFileID *FileId)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
+                                      0,
+                                      NULL,
+                                      NULL,
+                                      FileId,
+                                      NULL,
+                                      0,
+                                      NULL,
+                                      NULL);
+    }
+
+    return ntStatus;
+}
+
+BOOLEAN
+AFSIsExtentRequestQueued( IN AFSFileID *FileID,
+                          IN LARGE_INTEGER *ExtentOffset,
+                          IN ULONG Length)
+{
+
+    BOOLEAN bRequestQueued = FALSE;
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    AFSCommSrvcCB   *pCommSrvc = NULL;
+    AFSPoolEntry    *pPoolEntry = NULL;
+    AFSRequestExtentsCB *pRequestExtents = NULL;
+
+    __Enter
+    {
+
+
+        pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
+
+        AFSAcquireShared( &pCommSrvc->IrpPoolLock,
+                          TRUE);
+
+        pPoolEntry = pCommSrvc->RequestPoolHead;
+
+        while( pPoolEntry != NULL)
+        {
+
+            if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
+            {
+
+                if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
+                {
+
+                    pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
+
+                    if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
+                        pRequestExtents->Length == Length)
+                    {
+
+                        bRequestQueued = TRUE;
+                    }
+                }
+            }
+
+            pPoolEntry = pPoolEntry->fLink;
+        }
+
+        AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+    }
+
+    return bRequestQueued;
+}
diff --git a/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp b/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp
new file mode 100644 (file)
index 0000000..72343c6
--- /dev/null
@@ -0,0 +1,3714 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
+ * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice,
+ *   this list of conditions and the following disclaimer in the
+ *   documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
+ *   nor the names of their contributors may be used to endorse or promote
+ *   products derived from this software without specific prior written
+ *   permission from Kernel Drivers, LLC and Your File System, Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// File: AFSCreate.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSCreate
+//
+// Description:
+//
+//      This function is the dispatch handler for the IRP_MJ_CREATE requests. It makes the determination to
+//      which interface this request is destined.
+//
+// Return:
+//
+//      A status is returned for the function. The Irp completion processing is handled in the specific
+//      interface handler.
+//
+
+NTSTATUS
+AFSCreate( IN PDEVICE_OBJECT LibDeviceObject,
+           IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    IO_STACK_LOCATION  *pIrpSp;
+    FILE_OBJECT        *pFileObject = NULL;
+
+    __try
+    {
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+        pFileObject = pIrpSp->FileObject;
+
+        if( pFileObject == NULL ||
+            pFileObject->FileName.Buffer == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCreate (%08lX) Processing control device open request\n",
+                          Irp);
+
+            ntStatus = AFSControlDeviceCreate( Irp);
+
+            try_return( ntStatus);
+        }
+
+        if( AFSRDRDeviceObject == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCreate (%08lX) Invalid request to open before library is initialized\n",
+                          Irp);
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        ntStatus = AFSCommonCreate( AFSRDRDeviceObject,
+                                    Irp);
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSCreate\n");
+
+        ntStatus = STATUS_ACCESS_DENIED;
+    }
+
+    //
+    // Complete the request
+    //
+
+    AFSCompleteRequest( Irp,
+                          ntStatus);
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
+                 IN PIRP Irp)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    UNICODE_STRING      uniFileName;
+    ULONG               ulCreateDisposition = 0;
+    ULONG               ulOptions = 0;
+    BOOLEAN             bNoIntermediateBuffering = FALSE;
+    FILE_OBJECT        *pFileObject = NULL;
+    IO_STACK_LOCATION  *pIrpSp;
+    AFSFcb             *pFcb = NULL;
+    AFSCcb             *pCcb = NULL;
+    AFSDeviceExt       *pDeviceExt = NULL;
+    BOOLEAN             bOpenTargetDirectory = FALSE, bReleaseVolume = FALSE;
+    PACCESS_MASK        pDesiredAccess = NULL;
+    UNICODE_STRING      uniComponentName, uniPathName, uniRootFileName, uniParsedFileName;
+    UNICODE_STRING      uniSubstitutedPathName;
+    UNICODE_STRING      uniRelativeName;
+    AFSNameArrayHdr    *pNameArray = NULL;
+    AFSVolumeCB        *pVolumeCB = NULL;
+    AFSDirectoryCB     *pParentDirectoryCB = NULL, *pDirectoryCB = NULL;
+    ULONG               ulParseFlags = 0;
+    GUID                stAuthGroup;
+    ULONG               ulNameProcessingFlags = 0;
+
+    __Enter
+    {
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+        pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+        ulCreateDisposition = (pIrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
+        ulOptions = pIrpSp->Parameters.Create.Options;
+        bNoIntermediateBuffering = BooleanFlagOn( ulOptions, FILE_NO_INTERMEDIATE_BUFFERING);
+        bOpenTargetDirectory = BooleanFlagOn( pIrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
+        pFileObject = pIrpSp->FileObject;
+        pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+
+        uniFileName.Length = uniFileName.MaximumLength = 0;
+        uniFileName.Buffer = NULL;
+
+        uniRootFileName.Length = uniRootFileName.MaximumLength = 0;
+        uniRootFileName.Buffer = NULL;
+
+        uniParsedFileName.Length = uniParsedFileName.MaximumLength = 0;
+        uniParsedFileName.Buffer = NULL;
+
+        uniSubstitutedPathName.Buffer = NULL;
+        uniSubstitutedPathName.Length = 0;
+
+        uniRelativeName.Buffer = NULL;
+        uniRelativeName.Length = 0;
+
+        if( AFSGlobalRoot == NULL)
+        {
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        RtlZeroMemory( &stAuthGroup,
+                       sizeof( GUID));
+
+        AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
+                                 (ULONGLONG)PsGetCurrentThreadId(),
+                                  &stAuthGroup);
+
+        if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
+        {
+
+            ntStatus = AFSEnumerateGlobalRoot( &stAuthGroup);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed to enumerate global root Status %08lX\n",
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+        }
+
+        //
+        // If we are in shutdown mode then fail the request
+        //
+
+        if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                          "AFSCommonCreate (%08lX) Open request after shutdown\n",
+                          Irp);
+
+            try_return( ntStatus = STATUS_TOO_LATE);
+        }
+
+        //
+        // Go and parse the name for processing.
+        // If ulParseFlags is returned with AFS_PARSE_FLAG_FREE_FILE_BUFFER set,
+        // then we are responsible for releasing the uniRootFileName.Buffer.
+        //
+
+        ntStatus = AFSParseName( Irp,
+                                 &stAuthGroup,
+                                 &uniFileName,
+                                 &uniParsedFileName,
+                                 &uniRootFileName,
+                                 &ulParseFlags,
+                                 &pVolumeCB,
+                                 &pParentDirectoryCB,
+                                 &pNameArray);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          uniFileName.Length > 0 ? AFS_TRACE_LEVEL_ERROR : AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCommonCreate (%08lX) Failed to parse name \"%wZ\" Status %08lX\n",
+                          Irp,
+                          &uniFileName,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check for STATUS_REPARSE
+        //
+
+        if( ntStatus == STATUS_REPARSE)
+        {
+
+            //
+            // Update the information and return
+            //
+
+            Irp->IoStatus.Information = IO_REPARSE;
+
+            try_return( ntStatus);
+        }
+
+        //
+        // If the returned volume cb is NULL then we are dealing with the \\Server\GlobalRoot
+        // name
+        //
+
+        if( pVolumeCB == NULL)
+        {
+
+            //
+            // Remove any leading or trailing slashes
+            //
+
+            if( uniFileName.Length >= sizeof( WCHAR) &&
+                uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
+            {
+
+                uniFileName.Length -= sizeof( WCHAR);
+            }
+
+            if( uniFileName.Length >= sizeof( WCHAR) &&
+                uniFileName.Buffer[ 0] == L'\\')
+            {
+
+                uniFileName.Buffer = &uniFileName.Buffer[ 1];
+
+                uniFileName.Length -= sizeof( WCHAR);
+            }
+
+            //
+            // If there is a remaining portion returned for this request then
+            // check if it is for the PIOCtl interface
+            //
+
+            if( uniFileName.Length > 0)
+            {
+
+                //
+                // We don't accept any other opens off of the AFS Root
+                //
+
+                ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
+
+                //
+                // If this is an open on "_._AFS_IOCTL_._" then perform handling on it accordingly
+                //
+
+                if( RtlCompareUnicodeString( &AFSPIOCtlName,
+                                             &uniFileName,
+                                             TRUE) == 0)
+                {
+
+                    ntStatus = AFSOpenIOCtlFcb( Irp,
+                                                &stAuthGroup,
+                                                AFSGlobalRoot->DirectoryCB,
+                                                &pFcb,
+                                                &pCcb);
+
+                    if( !NT_SUCCESS( ntStatus))
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSCommonCreate Failed to open root IOCtl Fcb Status %08lX\n",
+                                      ntStatus);
+                    }
+                }
+                else if( pParentDirectoryCB != NULL &&
+                         pParentDirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
+                {
+
+                    ntStatus = AFSOpenSpecialShareFcb( Irp,
+                                                       &stAuthGroup,
+                                                       pParentDirectoryCB,
+                                                       &pFcb,
+                                                       &pCcb);
+
+                    if( !NT_SUCCESS( ntStatus))
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_ERROR,
+                                      "AFSCommonCreate Failed to open special share Fcb Status %08lX\n",
+                                      ntStatus);
+                    }
+                }
+
+                try_return( ntStatus);
+            }
+
+            ntStatus = AFSOpenAFSRoot( Irp,
+                                       &pFcb,
+                                       &pCcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed to open root Status %08lX\n",
+                              ntStatus);
+
+                InterlockedDecrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement1 count on &wZ DE %p Ccb %p Cnt %d\n",
+                              &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
+                              AFSGlobalRoot->DirectoryCB,
+                              NULL,
+                              AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // We have our root node shared
+        //
+
+        bReleaseVolume = TRUE;
+
+        //
+        // Attempt to locate the node in the name tree if this is not a target
+        // open and the target is not the root
+        //
+
+        uniComponentName.Length = 0;
+        uniComponentName.Buffer = NULL;
+
+        if( uniFileName.Length > sizeof( WCHAR) ||
+            uniFileName.Buffer[ 0] != L'\\')
+        {
+
+            if( !AFSValidNameFormat( &uniFileName))
+            {
+
+                ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate (%08lX) Invalid name %wZ Status %08lX\n",
+                              Irp,
+                              &uniFileName,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            //
+            // Opening a reparse point directly?
+            //
+
+            ulNameProcessingFlags = AFS_LOCATE_FLAGS_SUBSTITUTE_NAME;
+
+            if( BooleanFlagOn( ulOptions, FILE_OPEN_REPARSE_POINT))
+            {
+                ulNameProcessingFlags |= (AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
+                                          AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL |
+                                          AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL);
+            }
+
+            uniSubstitutedPathName = uniRootFileName;
+
+            ntStatus = AFSLocateNameEntry( &stAuthGroup,
+                                           pFileObject,
+                                           &uniRootFileName,
+                                           &uniParsedFileName,
+                                           pNameArray,
+                                           ulNameProcessingFlags,
+                                           &pVolumeCB,
+                                           &pParentDirectoryCB,
+                                           &pDirectoryCB,
+                                           &uniComponentName);
+
+            if( !NT_SUCCESS( ntStatus) &&
+                ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
+            {
+
+                if ( uniSubstitutedPathName.Buffer == uniRootFileName.Buffer)
+                {
+                    uniSubstitutedPathName.Buffer = NULL;
+                }
+
+                //
+                // The routine above released the root while walking the
+                // branch
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate (%08lX) Failed to locate name entry for %wZ Status %08lX\n",
+                              Irp,
+                              &uniFileName,
+                              ntStatus);
+
+                //
+                // We released any root volume locks in the above on failure
+                //
+
+                bReleaseVolume = FALSE;
+
+                try_return( ntStatus);
+            }
+
+            //
+            // Check for STATUS_REPARSE
+            //
+
+            if( ntStatus == STATUS_REPARSE)
+            {
+
+                uniSubstitutedPathName.Buffer = NULL;
+
+                //
+                // Update the information and return
+                //
+
+                Irp->IoStatus.Information = IO_REPARSE;
+
+                //
+                // We released the volume lock above
+                //
+
+                bReleaseVolume = FALSE;
+
+                try_return( ntStatus);
+            }
+
+            //
+            // If we re-allocated the name, then update our substitute name
+            //
+
+            if( uniSubstitutedPathName.Buffer != uniRootFileName.Buffer)
+            {
+
+                uniSubstitutedPathName = uniRootFileName;
+            }
+            else
+            {
+
+                uniSubstitutedPathName.Buffer = NULL;
+            }
+
+            //
+            // Check for a symlink access
+            //
+
+            if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND &&
+                pParentDirectoryCB != NULL)
+            {
+
+                UNICODE_STRING uniFinalComponent;
+
+                uniFinalComponent.Length = 0;
+                uniFinalComponent.MaximumLength = 0;
+                uniFinalComponent.Buffer = NULL;
+
+                AFSRetrieveFinalComponent( &uniFileName,
+                                           &uniFinalComponent);
+
+                ntStatus = AFSCheckSymlinkAccess( pParentDirectoryCB,
+                                                  &uniFinalComponent);
+
+                if( !NT_SUCCESS( ntStatus) &&
+                    ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCommonCreate (%08lX) Failing access to symlink %wZ Status %08lX\n",
+                                  Irp,
+                                  &uniFileName,
+                                  ntStatus);
+
+                    try_return( ntStatus);
+                }
+            }
+        }
+
+        //
+        // If we have no parent then this is a root open, be sure there is a directory entry
+        // for the root
+        //
+
+        else if( pParentDirectoryCB == NULL &&
+                 pDirectoryCB == NULL)
+        {
+
+            pDirectoryCB = pVolumeCB->DirectoryCB;
+        }
+
+        if( bOpenTargetDirectory)
+        {
+
+            //
+            // If we have a directory cb for the entry then dereference it and reference the parent
+            //
+
+            if( pDirectoryCB != NULL)
+            {
+
+                //
+                // Perform in this order to prevent thrashing
+                //
+
+                InterlockedIncrement( &pParentDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pParentDirectoryCB->NameInformation.FileName,
+                              pParentDirectoryCB,
+                              NULL,
+                              pParentDirectoryCB->OpenReferenceCount);
+
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+
+                //
+                // The name array also contains a reference to the pDirectoryCB so we need to remove it
+                // Note that this could decrement the count to zero allowing it to be deleted, hence
+                // don't access the pointer contents beyond here.
+                //
+
+                AFSBackupEntry( pNameArray);
+            }
+
+            //
+            // OK, open the target directory
+            //
+
+            if( uniComponentName.Length == 0)
+            {
+                AFSRetrieveFinalComponent( &uniFileName,
+                                           &uniComponentName);
+            }
+
+            ntStatus = AFSOpenTargetDirectory( Irp,
+                                               pVolumeCB,
+                                               pParentDirectoryCB,
+                                               pDirectoryCB,
+                                               &uniComponentName,
+                                               &pFcb,
+                                               &pCcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed to open target directory %wZ Status %08lX\n",
+                              &pParentDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+
+                //
+                // Decrement the reference on the parent
+                //
+
+                InterlockedDecrement( &pParentDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pParentDirectoryCB->NameInformation.FileName,
+                              pParentDirectoryCB,
+                              NULL,
+                              pParentDirectoryCB->OpenReferenceCount);
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Based on the options passed in, process the file accordingly.
+        //
+
+        if( ulCreateDisposition == FILE_CREATE ||
+            ( ( ulCreateDisposition == FILE_OPEN_IF ||
+                ulCreateDisposition == FILE_OVERWRITE_IF) &&
+              pDirectoryCB == NULL))
+        {
+
+            if( uniComponentName.Length == 0 ||
+                pDirectoryCB != NULL)
+            {
+
+                //
+                // We traversed the entire path so we found each entry,
+                // fail with collision
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate Object name collision on create of %wZ Status %08lX\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+
+                if( pDirectoryCB != NULL)
+                {
+
+                    InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCreate Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pDirectoryCB->NameInformation.FileName,
+                                  pDirectoryCB,
+                                  NULL,
+                                  pDirectoryCB->OpenReferenceCount);
+                }
+                else
+                {
+
+                    InterlockedDecrement( &pParentDirectoryCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCreate Decrement5 count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pParentDirectoryCB->NameInformation.FileName,
+                                  pParentDirectoryCB,
+                                  NULL,
+                                  pParentDirectoryCB->OpenReferenceCount);
+                }
+
+                try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
+            }
+
+            //
+            // OK, go and create the node
+            //
+
+            ntStatus = AFSProcessCreate( Irp,
+                                         &stAuthGroup,
+                                         pVolumeCB,
+                                         pParentDirectoryCB,
+                                         &uniFileName,
+                                         &uniComponentName,
+                                         &uniRootFileName,
+                                         &pFcb,
+                                         &pCcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed to create of %wZ in directory %wZ Status %08lX\n",
+                              &uniComponentName,
+                              &pParentDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+            }
+            else
+            {
+
+                //
+                // Reference the new dir entry
+                //
+
+                InterlockedIncrement( &pCcb->DirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Increment (Create) count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pCcb->DirectoryCB->NameInformation.FileName,
+                              pCcb->DirectoryCB,
+                              pCcb,
+                              pCcb->DirectoryCB->OpenReferenceCount);
+            }
+
+            //
+            // Dereference the parent entry
+            //
+
+            InterlockedDecrement( &pParentDirectoryCB->OpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCreate Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pParentDirectoryCB->NameInformation.FileName,
+                          pParentDirectoryCB,
+                          NULL,
+                          pParentDirectoryCB->OpenReferenceCount);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // We should not have an extra component except for PIOCtl opens
+        //
+
+        if( uniComponentName.Length > 0)
+        {
+
+            //
+            // If this is an open on "_._AFS_IOCTL_._" then perform handling on it accordingly
+            //
+
+            if( RtlCompareUnicodeString( &AFSPIOCtlName,
+                                         &uniComponentName,
+                                         TRUE) == 0)
+            {
+
+                ntStatus = AFSOpenIOCtlFcb( Irp,
+                                            &stAuthGroup,
+                                            pParentDirectoryCB,
+                                            &pFcb,
+                                            &pCcb);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSCommonCreate Failed to IOCtl open on %wZ Status %08lX\n",
+                                  &uniComponentName,
+                                  ntStatus);
+                }
+            }
+            else
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCommonCreate (%08lX) File %wZ name not found\n",
+                              Irp,
+                              &uniFileName);
+
+                ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
+            }
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                //
+                // Dereference the parent entry
+                //
+
+                if( pDirectoryCB != NULL)
+                {
+
+                    InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCreate Decrement7a count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pDirectoryCB->NameInformation.FileName,
+                                  pDirectoryCB,
+                                  NULL,
+                                  pDirectoryCB->OpenReferenceCount);
+                }
+                else
+                {
+
+                    InterlockedDecrement( &pParentDirectoryCB->OpenReferenceCount);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSCreate Decrement7b count on %wZ DE %p Ccb %p Cnt %d\n",
+                                  &pParentDirectoryCB->NameInformation.FileName,
+                                  pParentDirectoryCB,
+                                  NULL,
+                                  pParentDirectoryCB->OpenReferenceCount);
+                }
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // For root opens the parent will be NULL
+        //
+
+        if( pParentDirectoryCB == NULL)
+        {
+
+            //
+            // Check for the delete on close flag for the root
+            //
+
+            if( BooleanFlagOn( ulOptions, FILE_DELETE_ON_CLOSE ))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate (%08lX) Attempt to open root as delete on close\n",
+                              Irp);
+
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement8 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+
+                try_return( ntStatus = STATUS_CANNOT_DELETE);
+            }
+
+            //
+            // If this is the target directory, then bail
+            //
+
+            if( bOpenTargetDirectory)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate (%08lX) Attempt to open root as target directory\n",
+                              Irp);
+
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement9 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+
+                try_return( ntStatus = STATUS_INVALID_PARAMETER);
+            }
+
+            //
+            // Go and open the root of the volume
+            //
+
+            ntStatus = AFSOpenRoot( Irp,
+                                    pVolumeCB,
+                                    &stAuthGroup,
+                                    &pFcb,
+                                    &pCcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed to open root (2) Status %08lX\n",
+                              ntStatus);
+
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement10 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // At this point if we have no pDirectoryCB it was not found.
+        //
+
+        if( pDirectoryCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSCommonCreate Failing access to %wZ\n",
+                          &uniFileName);
+
+            try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
+        }
+
+        if( ulCreateDisposition == FILE_OVERWRITE ||
+            ulCreateDisposition == FILE_SUPERSEDE ||
+            ulCreateDisposition == FILE_OVERWRITE_IF)
+        {
+
+            //
+            // Go process a file for overwrite or supersede.
+            //
+
+            ntStatus = AFSProcessOverwriteSupersede( DeviceObject,
+                                                     Irp,
+                                                     pVolumeCB,
+                                                     &stAuthGroup,
+                                                     pParentDirectoryCB,
+                                                     pDirectoryCB,
+                                                     &pFcb,
+                                                     &pCcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate Failed overwrite/supersede on %wZ Status %08lX\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+
+                InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Decrement11 count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirectoryCB->NameInformation.FileName,
+                              pDirectoryCB,
+                              NULL,
+                              pDirectoryCB->OpenReferenceCount);
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Trying to open the file
+        //
+
+        ntStatus = AFSProcessOpen( Irp,
+                                   &stAuthGroup,
+                                   pVolumeCB,
+                                   pParentDirectoryCB,
+                                   pDirectoryCB,
+                                   &pFcb,
+                                   &pCcb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSCommonCreate Failed open on %wZ Status %08lX\n",
+                          &pDirectoryCB->NameInformation.FileName,
+                          ntStatus);
+
+            InterlockedDecrement( &pDirectoryCB->OpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCreate Decrement12 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirectoryCB->NameInformation.FileName,
+                          pDirectoryCB,
+                          NULL,
+                          pDirectoryCB->OpenReferenceCount);
+        }
+
+try_exit:
+
+        if( NT_SUCCESS( ntStatus) &&
+            ntStatus != STATUS_REPARSE)
+        {
+
+            if( pCcb != NULL)
+            {
+
+                //
+                // If we have a substitute name, then use it
+                //
+
+                if( uniSubstitutedPathName.Buffer != NULL)
+                {
+
+                    pCcb->FullFileName = uniSubstitutedPathName;
+
+                    SetFlag( pCcb->Flags, CCB_FLAG_FREE_FULL_PATHNAME);
+
+                    ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
+                }
+                else
+                {
+
+                    pCcb->FullFileName = uniRootFileName;
+
+                    if( BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER))
+                    {
+
+                        SetFlag( pCcb->Flags, CCB_FLAG_FREE_FULL_PATHNAME);
+
+                        ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
+                    }
+                }
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSCreate Count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pCcb->DirectoryCB->NameInformation.FileName,
+                              pCcb->DirectoryCB,
+                              pCcb,
+                              pCcb->DirectoryCB->OpenReferenceCount);
+
+                ASSERT( pCcb->DirectoryCB->OpenReferenceCount > 0);
+
+                pCcb->CurrentDirIndex = 0;
+
+                if( !BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS))
+                {
+
+                    SetFlag( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES);
+                }
+
+                //
+                // Save off the name array for this instance
+                //
+
+                pCcb->NameArray = pNameArray;
+
+                pNameArray = NULL;
+            }
+
+            //
+            // If we make it here then init the FO for the request.
+            //
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE_2,
+                          "AFSCommonCreate (%08lX) FileObject %08lX FsContext %08lX FsContext2 %08lX\n",
+                          Irp,
+                          pFileObject,
+                          pFcb,
+                          pCcb);
+
+            pFileObject->FsContext = (void *)pFcb;
+
+            pFileObject->FsContext2 = (void *)pCcb;
+
+            if( pFcb != NULL)
+            {
+
+                ASSERT( pFcb->OpenHandleCount > 0);
+
+                ClearFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
+
+                RtlCopyMemory( &pFcb->AuthGroup,
+                               &stAuthGroup,
+                               sizeof( GUID));
+
+                //
+                // For files perform additional processing
+                //
+
+                if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
+                {
+                    pFileObject->SectionObjectPointer = &pFcb->NPFcb->SectionObjectPointers;
+                }
+
+                //
+                // If the user did not request nobuffering then mark the FO as cacheable
+                //
+
+                if( bNoIntermediateBuffering)
+                {
+
+                    pFileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+                }
+                else
+                {
+
+                    pFileObject->Flags |= FO_CACHE_SUPPORTED;
+                }
+
+                //
+                // If the file was opened for execution then we need to set the bit in the FO
+                //
+
+                if( BooleanFlagOn( *pDesiredAccess,
+                                   FILE_EXECUTE))
+                {
+
+                    SetFlag( pFileObject->Flags, FO_FILE_FAST_IO_READ);
+                }
+
+                //
+                // Update the last access time
+                //
+
+                KeQuerySystemTime( &pFcb->ObjectInformation->LastAccessTime);
+            }
+            else
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate (%08lX) Returning with NULL Fcb FileObject %08lX FsContext %08lX FsContext2 %08lX\n",
+                              Irp,
+                              pFileObject,
+                              pFcb,
+                              pCcb);
+            }
+        }
+        else
+        {
+            if( NT_SUCCESS( ntStatus) &&
+                ntStatus == STATUS_REPARSE)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCommonCreate (%08lX) STATUS_REPARSE FileObject %08lX FsContext %08lX FsContext2 %08lX\n",
+                              Irp,
+                              pFileObject,
+                              pFcb,
+                              pCcb);
+            }
+
+            //
+            // Free up the sub name if we have one
+            //
+
+            if( uniSubstitutedPathName.Buffer != NULL)
+            {
+
+                AFSExFreePool( uniSubstitutedPathName.Buffer);
+
+                ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
+            }
+        }
+
+        //
+        // Free up the name array ...
+        //
+
+        if( pNameArray != NULL)
+        {
+
+            AFSFreeNameArray( pNameArray);
+        }
+
+        if( BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER))
+        {
+
+            AFSExFreePool( uniRootFileName.Buffer);
+        }
+
+        if( bReleaseVolume)
+        {
+
+            InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCommonCreate Decrement count on Volume %08lX Cnt %d\n",
+                          pVolumeCB,
+                          pVolumeCB->VolumeReferenceCount);
+
+            AFSReleaseResource( pVolumeCB->VolumeLock);
+        }
+
+        //
+        // Setup the Irp for completion, the Information has been set previously
+        //
+
+        Irp->IoStatus.Status = ntStatus;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSOpenRedirector( IN PIRP Irp,
+                   IN AFSFcb **Fcb,
+                   IN AFSCcb **Ccb)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        //
+        // Initialize the Ccb for the file.
+        //
+
+        ntStatus = AFSInitCcb( Ccb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenRedirector (%08lX) Failed to allocate Ccb\n",
+                          Irp);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Setup the Ccb
+        //
+
+        (*Ccb)->DirectoryCB = AFSRedirectorRoot->DirectoryCB;
+
+        //
+        // Increment the open count on this Fcb
+        //
+
+        InterlockedIncrement( &AFSRedirectorRoot->RootFcb->OpenReferenceCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenRedirector Increment count on Fcb %08lX Cnt %d\n",
+                      AFSRedirectorRoot->RootFcb,
+                      AFSRedirectorRoot->RootFcb->OpenReferenceCount);
+
+        InterlockedIncrement( &AFSRedirectorRoot->RootFcb->OpenHandleCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenRedirector Increment handle count on Fcb %08lX Cnt %d\n",
+                      AFSRedirectorRoot->RootFcb,
+                      AFSRedirectorRoot->RootFcb->OpenHandleCount);
+
+        *Fcb = AFSRedirectorRoot->RootFcb;
+
+        InterlockedIncrement( &(*Ccb)->DirectoryCB->OpenReferenceCount);
+
+        //
+        // Return the open result for this file
+        //
+
+        Irp->IoStatus.Information = FILE_OPENED;
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSOpenAFSRoot( IN PIRP Irp,
+                IN AFSFcb **Fcb,
+                IN AFSCcb **Ccb)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        //
+        // Initialize the Ccb for the file.
+        //
+
+        ntStatus = AFSInitCcb( Ccb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenAFSRoot (%08lX) Failed to allocate Ccb\n",
+                          Irp);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Setup the Ccb
+        //
+
+        (*Ccb)->DirectoryCB = AFSGlobalRoot->DirectoryCB;
+
+        //
+        // Increment the open count on this Fcb
+        //
+
+        InterlockedIncrement( &AFSGlobalRoot->RootFcb->OpenReferenceCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenAFSRoot Increment count on Fcb %08lX Cnt %d\n",
+                      AFSGlobalRoot->RootFcb,
+                      AFSGlobalRoot->RootFcb->OpenReferenceCount);
+
+        InterlockedIncrement( &AFSGlobalRoot->RootFcb->OpenHandleCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenAFSRoot Increment handle count on Fcb %08lX Cnt %d\n",
+                      AFSGlobalRoot->RootFcb,
+                      AFSGlobalRoot->RootFcb->OpenHandleCount);
+
+        *Fcb = AFSGlobalRoot->RootFcb;
+
+        //
+        // Return the open result for this file
+        //
+
+        Irp->IoStatus.Information = FILE_OPENED;
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSOpenRoot( IN PIRP Irp,
+             IN AFSVolumeCB *VolumeCB,
+             IN GUID *AuthGroup,
+             OUT AFSFcb **RootFcb,
+             OUT AFSCcb **Ccb)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    PFILE_OBJECT pFileObject = NULL;
+    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PACCESS_MASK pDesiredAccess = NULL;
+    USHORT usShareAccess;
+    BOOLEAN bAllocatedCcb = FALSE;
+    BOOLEAN bReleaseFcb = FALSE;
+    AFSFileOpenCB   stOpenCB;
+    AFSFileOpenResultCB stOpenResultCB;
+    ULONG       ulResultLen = 0;
+
+    __Enter
+    {
+
+        pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+        usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
+
+        pFileObject = pIrpSp->FileObject;
+
+        //
+        // Check if we should go and retrieve updated information for the node
+        //
+
+        ntStatus = AFSValidateEntry( VolumeCB->DirectoryCB,
+                                     AuthGroup,
+                                     TRUE,
+                                     FALSE);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenRoot (%08lX) Failed to validate root entry Status %08lX\n",
+                          Irp,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check with the service that we can open the file
+        //
+
+        RtlZeroMemory( &stOpenCB,
+                       sizeof( AFSFileOpenCB));
+
+        stOpenCB.DesiredAccess = *pDesiredAccess;
+
+        stOpenCB.ShareAccess = usShareAccess;
+
+        stOpenResultCB.GrantedAccess = 0;
+
+        ulResultLen = sizeof( AFSFileOpenResultCB);
+
+        ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_OPEN_FILE,
+                                      AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
+                                      AuthGroup,
+                                      NULL,
+                                      &VolumeCB->ObjectInformation.FileId,
+                                      (void *)&stOpenCB,
+                                      sizeof( AFSFileOpenCB),
+                                      (void *)&stOpenResultCB,
+                                      &ulResultLen);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenRoot (%08lX) Failed to open file in service Status %08lX\n",
+                          Irp,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // If the entry is not initialized then do it now
+        //
+
+        if( !BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
+        {
+
+            AFSAcquireExcl( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            TRUE);
+
+            if( !BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
+            {
+
+                ntStatus = AFSEnumerateDirectory( AuthGroup,
+                                                  &VolumeCB->ObjectInformation,
+                                                  TRUE);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSOpenRoot (%08lX) Failed to enumerate directory Status %08lX\n",
+                                  Irp,
+                                  ntStatus);
+
+                    try_return( ntStatus);
+                }
+
+                SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
+            }
+
+            AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
+        }
+
+        //
+        // If the root fcb has been initialized then check access otherwise
+        // init the volume fcb
+        //
+
+        if( VolumeCB->RootFcb == NULL)
+        {
+
+            ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
+                                       VolumeCB);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                try_return( ntStatus);
+            }
+        }
+        else
+        {
+
+            AFSAcquireExcl( VolumeCB->RootFcb->Header.Resource,
+                            TRUE);
+        }
+
+        bReleaseFcb = TRUE;
+
+        //
+        // If there are current opens on the Fcb, check the access.
+        //
+
+        if( VolumeCB->RootFcb->OpenHandleCount > 0)
+        {
+
+            ntStatus = IoCheckShareAccess( *pDesiredAccess,
+                                           usShareAccess,
+                                           pFileObject,
+                                           &VolumeCB->RootFcb->ShareAccess,
+                                           FALSE);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSOpenRoot (%08lX) Access check failure Status %08lX\n",
+                              Irp,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+        }
+
+        //
+        // Initialize the Ccb for the file.
+        //
+
+        ntStatus = AFSInitCcb( Ccb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenRoot (%08lX) Failed to allocate Ccb Status %08lX\n",
+                          Irp,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        bAllocatedCcb = TRUE;
+
+        //
+        // Setup the ccb
+        //
+
+        (*Ccb)->DirectoryCB = VolumeCB->DirectoryCB;
+
+        //
+        // OK, update the share access on the fileobject
+        //
+
+        if( VolumeCB->RootFcb->OpenHandleCount > 0)
+        {
+
+            IoUpdateShareAccess( pFileObject,
+                                 &VolumeCB->RootFcb->ShareAccess);
+        }
+        else
+        {
+
+            //
+            // Set the access
+            //
+
+            IoSetShareAccess( *pDesiredAccess,
+                              usShareAccess,
+                              pFileObject,
+                              &VolumeCB->RootFcb->ShareAccess);
+        }
+
+        //
+        // Increment the open count on this Fcb
+        //
+
+        InterlockedIncrement( &VolumeCB->RootFcb->OpenReferenceCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenRoot Increment count on Fcb %08lX Cnt %d\n",
+                      VolumeCB->RootFcb,
+                      VolumeCB->RootFcb->OpenReferenceCount);
+
+        InterlockedIncrement( &VolumeCB->RootFcb->OpenHandleCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenRoot Increment handle count on Fcb %08lX Cnt %d\n",
+                      VolumeCB->RootFcb,
+                      VolumeCB->RootFcb->OpenHandleCount);
+
+        //
+        // Indicate the object is held
+        //
+
+        SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE);
+
+        //
+        // Return the open result for this file
+        //
+
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        *RootFcb = VolumeCB->RootFcb;
+
+try_exit:
+
+        if( bReleaseFcb)
+        {
+
+            AFSReleaseResource( VolumeCB->RootFcb->Header.Resource);
+        }
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( bAllocatedCcb)
+            {
+
+                AFSRemoveCcb( *Ccb);
+
+                *Ccb = NULL;
+            }
+
+            Irp->IoStatus.Information = 0;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSProcessCreate( IN PIRP               Irp,
+                  IN GUID              *AuthGroup,
+                  IN AFSVolumeCB       *VolumeCB,
+                  IN AFSDirectoryCB    *ParentDirCB,
+                  IN PUNICODE_STRING    FileName,
+                  IN PUNICODE_STRING    ComponentName,
+                  IN PUNICODE_STRING    FullFileName,
+                  OUT AFSFcb          **Fcb,
+                  OUT AFSCcb          **Ccb)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    PFILE_OBJECT pFileObject = NULL;
+    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    ULONG ulOptions = 0;
+    ULONG ulShareMode = 0;
+    ULONG ulAccess = 0;
+    ULONG ulAttributes = 0;
+    LARGE_INTEGER   liAllocationSize = {0,0};
+    BOOLEAN bFileCreated = FALSE, bReleaseFcb = FALSE, bAllocatedCcb = FALSE;
+    BOOLEAN bAllocatedFcb = FALSE;
+    PACCESS_MASK pDesiredAccess = NULL;
+    USHORT usShareAccess;
+    AFSDirectoryCB *pDirEntry = NULL;
+    AFSObjectInfoCB *pParentObjectInfo = NULL;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+
+    __Enter
+    {
+
+        pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+        usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
+
+        pFileObject = pIrpSp->FileObject;
+
+        //
+        // Extract out the options
+        //
+
+        ulOptions = pIrpSp->Parameters.Create.Options;
+
+        //
+        // We pass all attributes they want to apply to the file to the create
+        //
+
+        ulAttributes = pIrpSp->Parameters.Create.FileAttributes;
+
+        //
+        // If this is a directory create then set the attribute correctly
+        //
+
+        if( ulOptions & FILE_DIRECTORY_FILE)
+        {
+
+            ulAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessCreate (%08lX) Creating file %wZ Attributes %08lX\n",
+                      Irp,
+                      FullFileName,
+                      ulAttributes);
+
+        if( BooleanFlagOn( VolumeCB->VolumeInformation.Characteristics, FILE_READ_ONLY_DEVICE))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSProcessCreate Request failed due to read only volume %wZ\n",
+                          FullFileName);
+
+            try_return( ntStatus = STATUS_ACCESS_DENIED);
+        }
+
+        pParentObjectInfo = ParentDirCB->ObjectInformation;
+
+        //
+        // Allocate and insert the direntry into the parent node
+        //
+
+        ntStatus = AFSCreateDirEntry( AuthGroup,
+                                      pParentObjectInfo,
+                                      ParentDirCB,
+                                      FileName,
+                                      ComponentName,
+                                      ulAttributes,
+                                      &pDirEntry);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSProcessCreate (%08lX) Failed to create directory entry %wZ Status %08lX\n",
+                          Irp,
+                          FullFileName,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        bFileCreated = TRUE;
+
+        pObjectInfo = pDirEntry->ObjectInformation;
+
+        //
+        // We may have raced and the Fcb is already created
+        //
+
+        if( pObjectInfo->Fcb != NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSProcessCreate (%08lX) Not allocating Fcb for file %wZ\n",
+                          Irp,
+                          FullFileName);
+
+            *Fcb = pObjectInfo->Fcb;
+
+            AFSAcquireExcl( &(*Fcb)->NPFcb->Resource,
+                            TRUE);
+        }
+        else
+        {
+
+            //
+            // Allocate and initialize the Fcb for the file.
+            //
+
+            ntStatus = AFSInitFcb( pDirEntry,
+                                   Fcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessCreate (%08lX) Failed to initialize fcb %wZ Status %08lX\n",
+                              Irp,
+                              FullFileName,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            bAllocatedFcb = TRUE;
+        }
+
+        bReleaseFcb = TRUE;
+
+        //
+        // Initialize the Ccb for the file.
+        //
+
+        ntStatus = AFSInitCcb( Ccb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSProcessCreate (%08lX) Failed to initialize ccb %wZ Status %08lX\n",
+                          Irp,
+                          FullFileName,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        bAllocatedCcb = TRUE;
+
+        //
+        // Initialize the Ccb
+        //
+
+        (*Ccb)->DirectoryCB = pDirEntry;
+
+        //
+        // If this is a file, update the headers filesizes.
+        //
+
+        if( (*Fcb)->Header.NodeTypeCode == AFS_FILE_FCB)
+        {
+
+            //
+            // Update the sizes with the information passed in
+            //
+
+            (*Fcb)->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
+            (*Fcb)->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
+            (*Fcb)->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
+
+            //
+            // Notify the system of the addition
+            //
+
+            AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                            *Ccb,
+                                                                               (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                                               (ULONG)FILE_ACTION_ADDED);
+
+            (*Fcb)->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
+        }
+        else if( (*Fcb)->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
+        {
+
+            //
+            // This is a new directory node so indicate it has been enumerated
+            //
+
+            SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
+
+            //
+            // And the parent directory entry
+            //
+
+            KeQuerySystemTime( &pParentObjectInfo->ChangeTime);
+
+            //
+            // Notify the system of the addition
+            //
+
+            AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                            *Ccb,
+                                                                               (ULONG)FILE_NOTIFY_CHANGE_DIR_NAME,
+                                                                               (ULONG)FILE_ACTION_ADDED);
+        }
+        else if( (*Fcb)->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
+                 (*Fcb)->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
+                 (*Fcb)->Header.NodeTypeCode == AFS_DFS_LINK_FCB)
+        {
+
+            //
+            // And the parent directory entry
+            //
+
+            KeQuerySystemTime( &pParentObjectInfo->ChangeTime);
+
+            //
+            // Notify the system of the addition
+            //
+
+            AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
+                                            *Ccb,
+                                                                               (ULONG)FILE_NOTIFY_CHANGE_DIR_NAME,
+                                                                               (ULONG)FILE_ACTION_ADDED);
+        }
+
+        //
+        // Save off the access for the open
+        //
+
+        IoSetShareAccess( *pDesiredAccess,
+                          usShareAccess,
+                          pFileObject,
+                          &(*Fcb)->ShareAccess);
+
+        //
+        // Increment the open count on this Fcb
+        //
+
+        InterlockedIncrement( &(*Fcb)->OpenReferenceCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessCreate Increment count on Fcb %08lX Cnt %d\n",
+                                                    *Fcb,
+                                                    (*Fcb)->OpenReferenceCount);
+
+        InterlockedIncrement( &(*Fcb)->OpenHandleCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessCreate Increment handle count on Fcb %08lX Cnt %d\n",
+                                                    (*Fcb),
+                                                    (*Fcb)->OpenHandleCount);
+
+        //
+        // Increment the open reference and handle on the parent node
+        //
+
+        InterlockedIncrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessCreate Increment child open handle count on Parent object %08lX Cnt %d\n",
+                      pObjectInfo->ParentObjectInformation,
+                      pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+
+        InterlockedIncrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessCreate Increment child open ref count on Parent object %08lX Cnt %d\n",
+                      pObjectInfo->ParentObjectInformation,
+                      pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+
+        if( ulOptions & FILE_DELETE_ON_CLOSE)
+        {
+
+            //
+            // Mark it for delete on close
+            //
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSProcessCreate (%08lX) Setting PENDING_DELETE flag in DirEntry %p Name %wZ\n",
+                          Irp,
+                          pDirEntry,
+                          FullFileName);
+
+            SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
+        }
+
+        //
+        // Indicate the object is locked in the service
+        //
+
+        SetFlag( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
+
+        //
+        // Return the open result for this file
+        //
+
+        Irp->IoStatus.Information = FILE_CREATED;
+
+try_exit:
+
+        //
+        // If we created the Fcb we need to release the resources
+        //
+
+        if( bReleaseFcb)
+        {
+
+            AFSReleaseResource( &(*Fcb)->NPFcb->Resource);
+        }
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( bFileCreated)
+            {
+
+                //
+                // Remove the dir entry from the parent
+                //
+
+                AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                TRUE);
+
+                AFSDeleteDirEntry( pParentObjectInfo,
+                                   pDirEntry);
+
+                AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+            }
+
+            if( bAllocatedCcb)
+            {
+
+                AFSRemoveCcb( *Ccb);
+            }
+
+            if( bAllocatedFcb)
+            {
+
+                AFSRemoveFcb( pObjectInfo->Fcb);
+
+                pObjectInfo->Fcb = NULL;
+            }
+
+            *Fcb = NULL;
+
+            *Ccb = NULL;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSOpenTargetDirectory( IN PIRP Irp,
+                        IN AFSVolumeCB *VolumeCB,
+                        IN AFSDirectoryCB *ParentDirectoryCB,
+                        IN AFSDirectoryCB *TargetDirectoryCB,
+                        IN UNICODE_STRING *TargetName,
+                        OUT AFSFcb **Fcb,
+                        OUT AFSCcb **Ccb)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    PFILE_OBJECT pFileObject = NULL;
+    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PACCESS_MASK pDesiredAccess = NULL;
+    USHORT usShareAccess;
+    BOOLEAN bRemoveAccess = FALSE;
+    BOOLEAN bAllocatedCcb = FALSE;
+    BOOLEAN bReleaseFcb = FALSE, bAllocatedFcb = FALSE;
+    AFSObjectInfoCB *pParentObject = NULL, *pTargetObject = NULL;
+    UNICODE_STRING uniTargetName;
+
+    __Enter
+    {
+
+        pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+        usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
+
+        pFileObject = pIrpSp->FileObject;
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSOpenTargetDirectory (%08lX) Processing file %wZ\n",
+                      Irp,
+                      TargetName);
+
+        pParentObject = ParentDirectoryCB->ObjectInformation;
+
+        if( pParentObject->FileType != AFS_FILE_TYPE_DIRECTORY)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // Make sure we have an Fcb for the access
+        //
+
+        if( pParentObject->Fcb != NULL)
+        {
+
+            *Fcb = pParentObject->Fcb;
+
+            AFSAcquireExcl( &(*Fcb)->NPFcb->Resource,
+                            TRUE);
+        }
+        else
+        {
+
+            //
+            // Allocate and initialize the Fcb for the file.
+            //
+
+            ntStatus = AFSInitFcb( ParentDirectoryCB,
+                                   Fcb);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessCreate (%08lX) Failed to initialize fcb %wZ Status %08lX\n",
+                              Irp,
+                              &ParentDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            bAllocatedFcb = TRUE;
+        }
+
+        bReleaseFcb = TRUE;
+
+        //
+        // If there are current opens on the Fcb, check the access.
+        //
+
+        if( pParentObject->Fcb->OpenHandleCount > 0)
+        {
+
+            ntStatus = IoCheckShareAccess( *pDesiredAccess,
+                                           usShareAccess,
+                                           pFileObject,
+                                           &pParentObject->Fcb->ShareAccess,
+                                           FALSE);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSOpenTargetDirectory (%08lX) Access check failure %wZ Status %08lX\n",
+                              Irp,
+                              &ParentDirectoryCB->NameInformation.FileName,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+        }
+
+        //
+        // Initialize the Ccb for the file.
+        //
+
+        ntStatus = AFSInitCcb( Ccb);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSOpenTargetDirectory (%08lX) Failed to initialize ccb %wZ Status %08lX\n",
+                        &nbs