Windows: RDR File System Framework driver
authorPeter Scott <pscott@kerneldrivers.com>
Thu, 15 Sep 2011 05:33:20 +0000 (01:33 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Thu, 15 Sep 2011 18:27:42 +0000 (11:27 -0700)
This is the first of two kernel drivers used to implement
the AFS Redirector: AFSRedir.sys.

This driver is registered at boot time and provides the binding
to the Windows kernel infrastructure.  However, it only provides
a framework of a file system driver.  All of the AFS specific
interfaces are actually implemented in a secondary library
driver, AFSRedirLib.sys.  The rationale for this model is that
file system drivers cannot be unloaded on a running system.
By using this approach the library driver can be unloaded which
permits systems to be live updated.

To permit this model to work, all memory allocation is performed
by AFSRedir.sys.  This confuses the driver verifier tool.  When
the library is unloaded all objects are still valid.  Operation
is simply paused until a new library is brought up.  Under the
current configuration the library is loaded as part of afsd_service
initialization of AFSRedir.sys and is automatically unloaded when
afsd_service.exe shuts down.

The framework driver also implements all of the process and
thread tracking logic necessary to support Authentication Groups.

Communication between AFSRedir.sys and afsd_service.exe is
performed via a reverse ioctl model whereby the service contributes
threads to the driver to convey requests for processing.

The original file system was derived from the Kernel Drivers
File System under license from Kernel Drivers, LLC.

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

Change-Id: Ic123cacd868ddde31d66bf17d3ad2a13c22cd1f4
Reviewed-on: http://gerrit.openafs.org/5437
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/fs/AFSAuthGroupSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSCleanup.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSClose.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSData.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSEa.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSInit.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSLockControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSLogSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSNetworkProviderSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSProcessSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSQuota.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSRead.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSRedirInstall.inf [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSSecurity.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSShutdown.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSSystemControl.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSVolumeInfo.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/Filesystem.rc [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/Include/AFSCommon.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/Include/AFSDefines.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/Include/AFSExtern.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/Include/AFSStructs.h [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/MAKEFILE [new file with mode: 0644]
src/WINNT/afsrdr/kernel/fs/sources [new file with mode: 0644]

diff --git a/src/WINNT/afsrdr/kernel/fs/AFSAuthGroupSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSAuthGroupSupport.cpp
new file mode 100644 (file)
index 0000000..4eb31a1
--- /dev/null
@@ -0,0 +1,1736 @@
+/*
+ * 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: AFSAuthGroupSupport.cpp
+//
+
+#include "AFSCommon.h"
+
+void
+AFSRetrieveAuthGroup( IN ULONGLONG ProcessId,
+                      IN ULONGLONG ThreadId,
+                      OUT GUID *AuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSThreadCB *pThreadCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    GUID *pAuthGroup = NULL;
+    UNICODE_STRING uniGUIDString;
+    ULONG ulSessionId = 0;
+    BOOLEAN bImpersonation = FALSE;
+
+    __Enter
+    {
+
+        ulSessionId = AFSGetSessionId( (HANDLE)ProcessId, &bImpersonation);
+
+        if( ulSessionId == (ULONG)-1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to retrieve session ID for PID %I64X\n",
+                          __FUNCTION__,
+                          ProcessId);
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for Session %08lX PID %I64X TID %I64X\n",
+                      __FUNCTION__,
+                      ulSessionId,
+                      ProcessId,
+                      ThreadId);
+
+        ntStatus = AFSCheckThreadDacl( AuthGroup);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            uniGUIDString.Buffer = NULL;
+            uniGUIDString.Length = 0;
+            uniGUIDString.MaximumLength = 0;
+
+            RtlStringFromGUID( *AuthGroup,
+                               &uniGUIDString);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Located AuthGroup %wZ via DACL for Session %08lX PID %I64X TID %I64X\n",
+                          __FUNCTION__,
+                          &uniGUIDString,
+                          ulSessionId,
+                          ProcessId,
+                          ThreadId);
+
+            if( uniGUIDString.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUIDString);
+            }
+
+            try_return( ntStatus = STATUS_SUCCESS);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRetrieveAuthGroup Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n",
+                      pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                      PsGetCurrentThread());
+
+        ntStatus = STATUS_SUCCESS;
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
+                                       (ULONGLONG)ProcessId,
+                                       (AFSBTreeEntry **)&pProcessCB);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            pProcessCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate process entry for Session %08lX PID %I64X TID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ProcessId,
+                          ThreadId);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+            try_return( ntStatus);
+        }
+
+        for ( pThreadCB = pProcessCB->ThreadList;
+              pThreadCB != NULL;
+              pThreadCB = pThreadCB->Next)
+        {
+
+            if( pThreadCB->ThreadId == ThreadId)
+            {
+                break;
+            }
+        }
+
+        if( pThreadCB != NULL &&
+            pThreadCB->ActiveAuthGroup != NULL)
+        {
+            pAuthGroup = pThreadCB->ActiveAuthGroup;
+
+            RtlCopyMemory( AuthGroup,
+                           pAuthGroup,
+                           sizeof( GUID));
+
+            uniGUIDString.Buffer = NULL;
+            uniGUIDString.Length = 0;
+            uniGUIDString.MaximumLength = 0;
+
+            RtlStringFromGUID( *AuthGroup,
+                               &uniGUIDString);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Located AuthGroup %wZ in thread Session %08lX PID %I64X TID %I64X\n",
+                          __FUNCTION__,
+                          &uniGUIDString,
+                          ulSessionId,
+                          ProcessId,
+                          ThreadId);
+
+            if( uniGUIDString.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUIDString);
+            }
+        }
+        else if( pProcessCB->ActiveAuthGroup != NULL)
+        {
+
+            pAuthGroup = pProcessCB->ActiveAuthGroup;
+
+            RtlCopyMemory( AuthGroup,
+                           pAuthGroup,
+                           sizeof( GUID));
+
+            uniGUIDString.Buffer = NULL;
+            uniGUIDString.Length = 0;
+            uniGUIDString.MaximumLength = 0;
+
+            RtlStringFromGUID( *AuthGroup,
+                               &uniGUIDString);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Located AuthGroup %wZ in process Session %08lX PID %I64X TID %I64X\n",
+                          __FUNCTION__,
+                          &uniGUIDString,
+                          ulSessionId,
+                          ProcessId,
+                          ThreadId);
+
+            if( uniGUIDString.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUIDString);
+            }
+        }
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        if( pAuthGroup == NULL ||
+            AFSIsNoPAGAuthGroup( pAuthGroup))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s No AuthGroup located, validating process for Session %08lX PID %I64X TID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ProcessId,
+                          ThreadId);
+
+            pAuthGroup = AFSValidateProcessEntry();
+
+            if( pAuthGroup != NULL)
+            {
+                RtlCopyMemory( AuthGroup,
+                               pAuthGroup,
+                               sizeof( GUID));
+
+                uniGUIDString.Buffer = NULL;
+                uniGUIDString.Length = 0;
+                uniGUIDString.MaximumLength = 0;
+
+                RtlStringFromGUID( *AuthGroup,
+                                   &uniGUIDString);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Located AuthGroup %wZ after validation Session %08lX PID %I64X TID %I64X\n",
+                              __FUNCTION__,
+                              &uniGUIDString,
+                              ulSessionId,
+                              ProcessId,
+                              ThreadId);
+
+                if( uniGUIDString.Buffer != NULL)
+                {
+                    RtlFreeUnicodeString( &uniGUIDString);
+                }
+            }
+            else
+            {
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "%s Failed to locate AuthGroup for Session %08lX PID %I64X TID %I64X\n",
+                              __FUNCTION__,
+                              ulSessionId,
+                              ProcessId,
+                              ThreadId);
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return;
+}
+
+//
+// AFSIsLocalSystemAuthGroup returns TRUE if the AuthGroup matches
+// the AuthGroup associated with the first process that communicates
+// with the redirector which will always be "System" (PID 4).
+//
+
+BOOLEAN
+AFSIsLocalSystemAuthGroup( IN GUID *AuthGroup)
+{
+
+    BOOLEAN bIsLocalSys = FALSE;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    UNICODE_STRING uniGUIDString;
+
+    __Enter
+    {
+
+        uniGUIDString.Length = 0;
+        uniGUIDString.MaximumLength = 0;
+        uniGUIDString.Buffer = NULL;
+
+        RtlStringFromGUID( *AuthGroup,
+                           &uniGUIDString);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "%s Checking AuthGroup %wZ\n",
+                      __FUNCTION__,
+                      &uniGUIDString);
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        pProcessCB = (AFSProcessCB *)pDeviceExt->Specific.Control.ProcessTree.TreeHead;
+
+        if( pProcessCB->ActiveAuthGroup != NULL &&
+            RtlCompareMemory( pProcessCB->ActiveAuthGroup,
+                              AuthGroup,
+                              sizeof( GUID)) == sizeof( GUID))
+        {
+            bIsLocalSys = TRUE;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s AuthGroup %wZ is LOCAL SYSTEM\n",
+                          __FUNCTION__,
+                          &uniGUIDString);
+        }
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        if( uniGUIDString.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUIDString);
+        }
+    }
+
+    return bIsLocalSys;
+}
+
+BOOLEAN
+AFSIsLocalSystemSID( IN UNICODE_STRING *SIDString)
+{
+
+    BOOLEAN bIsLocalSys = FALSE;
+    UNICODE_STRING uniSysLocal;
+
+    __Enter
+    {
+
+        RtlInitUnicodeString( &uniSysLocal,
+                              L"S-1-5-18");
+
+        if( RtlCompareUnicodeString( &uniSysLocal,
+                                     SIDString,
+                                     TRUE) == 0)
+        {
+            bIsLocalSys = TRUE;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "%s AuthGroup SID %wZ is %sLOCAL SYSTEM\n",
+                      __FUNCTION__,
+                      SIDString,
+                      bIsLocalSys ? "" : "not ");
+    }
+
+    return bIsLocalSys;
+}
+
+BOOLEAN
+AFSIsNoPAGAuthGroup( IN GUID *AuthGroup)
+{
+
+    BOOLEAN bIsNoPAG = FALSE;
+    UNICODE_STRING uniGUIDString;
+
+    __Enter
+    {
+
+        uniGUIDString.Length = 0;
+        uniGUIDString.MaximumLength = 0;
+        uniGUIDString.Buffer = NULL;
+
+        RtlStringFromGUID( *AuthGroup,
+                           &uniGUIDString);
+
+        if( RtlCompareMemory( AuthGroup,
+                              &AFSNoPAGAuthGroup,
+                              sizeof( GUID)) == sizeof( GUID))
+        {
+            bIsNoPAG = TRUE;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "%s AuthGroup %wZ is %sNoPAG\n",
+                      __FUNCTION__,
+                      &uniGUIDString,
+                      bIsNoPAG ? "" : "not ");
+
+        if( uniGUIDString.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUIDString);
+        }
+    }
+
+    return bIsNoPAG;
+}
+
+//
+// Creates a new AuthGroup and either activates it for
+// the process or the current thread.  If set as the
+// new process AuthGroup, the prior AuthGroup list is
+// cleared.
+//
+
+NTSTATUS
+AFSCreateSetProcessAuthGroup( AFSAuthGroupRequestCB *CreateSetAuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSThreadCB *pThreadCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId();
+    UNICODE_STRING uniSIDString, uniPassedSIDString;
+    ULONG ulSIDHash = 0;
+    AFSProcessAuthGroupCB *pAuthGroup = NULL, *pLastAuthGroup = NULL;
+    ULONG ulSessionId = 0;
+    ULONGLONG ullTableHash = 0;
+    GUID stAuthGroup;
+    UNICODE_STRING uniCallerSID;
+    BOOLEAN bImpersonation = FALSE;
+
+    __Enter
+    {
+
+        uniCallerSID.Length = 0;
+        uniCallerSID.MaximumLength = 0;
+        uniCallerSID.Buffer = NULL;
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
+                                       (ULONGLONG)ullProcessID,
+                                       (AFSBTreeEntry **)&pProcessCB);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            pProcessCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate process CB for PID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        AFSAcquireExcl( &pProcessCB->Lock,
+                        TRUE);
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        ntStatus = AFSGetCallerSID( &uniCallerSID, &bImpersonation);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate caller SID for PID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Retrieved caller SID %wZ for PID %I64X\n",
+                      __FUNCTION__,
+                      &uniCallerSID,
+                      ullProcessID);
+
+
+        if( CreateSetAuthGroup->SIDLength != 0)
+        {
+
+            uniPassedSIDString.Length = CreateSetAuthGroup->SIDLength;
+            uniPassedSIDString.MaximumLength = uniPassedSIDString.Length;
+
+            uniPassedSIDString.Buffer = CreateSetAuthGroup->SIDString;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Validating passed SID %wZ for PID %I64X\n",
+                          __FUNCTION__,
+                          &uniPassedSIDString,
+                          ullProcessID);
+
+            if( RtlCompareUnicodeString( &uniCallerSID,
+                                         &uniPassedSIDString,
+                                         TRUE) != 0)
+            {
+
+                if( !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "%s Caller specified SID %wZ for PID %I64X but caller is not LOCAL SYSTEM AUTHORITY\n",
+                                  __FUNCTION__,
+                                  &uniPassedSIDString,
+                                  ullProcessID);
+
+                    try_return( ntStatus = STATUS_ACCESS_DENIED);
+                }
+
+                uniSIDString = uniPassedSIDString;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Using passed SID %wZ for PID %I64X\n",
+                              __FUNCTION__,
+                              &uniSIDString,
+                              ullProcessID);
+            }
+            else
+            {
+                uniSIDString = uniCallerSID;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Caller and passed SID are equal SID %wZ for PID %I64X\n",
+                              __FUNCTION__,
+                              &uniSIDString,
+                              ullProcessID);
+            }
+        }
+        else
+        {
+            uniSIDString = uniCallerSID;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s No SID passed, using callers SID %wZ for PID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID);
+        }
+
+        ntStatus = RtlHashUnicodeString( &uniSIDString,
+                                         TRUE,
+                                         HASH_STRING_ALGORITHM_DEFAULT,
+                                         &ulSIDHash);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to hash SID %wZ for PID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation);
+
+        if( ulSessionId == (ULONG)-1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to retrieve SessionID PID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          ntStatus);
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        if( CreateSetAuthGroup->SessionId != (ULONG)-1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Checking passed SessionID %08lX for PID %I64X\n",
+                          __FUNCTION__,
+                          CreateSetAuthGroup->SessionId,
+                          ullProcessID);
+
+            if( ulSessionId != CreateSetAuthGroup->SessionId)
+            {
+
+                if( !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH))
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "%s Passed SessionID %08lX for PID %I64X, failed because caller is not LOCAL SYSTEM AUTHORITY\n",
+                                  __FUNCTION__,
+                                  CreateSetAuthGroup->SessionId,
+                                  ullProcessID);
+
+                    try_return( ntStatus = STATUS_ACCESS_DENIED);
+                }
+
+                ulSessionId = CreateSetAuthGroup->SessionId;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Using passed SessionID %08lX for PID %I64X\n",
+                              __FUNCTION__,
+                              ulSessionId,
+                              ullProcessID);
+            }
+        }
+        else
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Using callers SessionID %08lX for PID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ullProcessID);
+        }
+
+        ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash);
+
+        pAuthGroup = pProcessCB->AuthGroupList;
+
+        while( pAuthGroup != NULL)
+        {
+
+            if( pAuthGroup->AuthGroupHash == ullTableHash)
+            {
+                break;
+            }
+
+            pLastAuthGroup = pAuthGroup;
+
+            pAuthGroup = pAuthGroup->Next;
+        }
+
+        if( pAuthGroup != NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Located AuthGroup for SID %wZ SessionID %08lX for PID %I64X, failing request\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ulSessionId,
+                          ullProcessID);
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        pAuthGroup = (AFSProcessAuthGroupCB *)AFSExAllocatePoolWithTag( NonPagedPool,
+                                                                        sizeof( AFSProcessAuthGroupCB),
+                                                                        AFS_AG_ENTRY_CB_TAG);
+
+        if( pAuthGroup == NULL)
+        {
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pAuthGroup,
+                       sizeof( AFSProcessAuthGroupCB));
+
+        pAuthGroup->AuthGroupHash = (ULONGLONG)ullTableHash;
+
+        while( ExUuidCreate( &pAuthGroup->AuthGroup) == STATUS_RETRY);
+
+        if( pLastAuthGroup == NULL)
+        {
+            pProcessCB->AuthGroupList = pAuthGroup;
+        }
+        else
+        {
+            pLastAuthGroup->Next = pAuthGroup;
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Allocated new AuthGroup for SID %wZ SessionID %08lX for PID %I64X\n",
+                      __FUNCTION__,
+                      &uniSIDString,
+                      ulSessionId,
+                      ullProcessID);
+
+        if( BooleanFlagOn( CreateSetAuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP))
+        {
+
+            pThreadCB = pProcessCB->ThreadList;
+
+            while( pThreadCB != NULL)
+            {
+
+                if( pThreadCB->ThreadId == ullThreadId)
+                {
+                    pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+                    break;
+                }
+
+                pThreadCB = pThreadCB->Next;
+            }
+
+            if( pThreadCB == NULL)
+            {
+
+                pThreadCB = AFSInitializeThreadCB( pProcessCB,
+                                                   ullThreadId);
+
+                if( pThreadCB == NULL)
+                {
+                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+                }
+
+                pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Set new AuthGroup for SID %wZ SessionID %08lX for PID %I64X on thread ID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ulSessionId,
+                          ullProcessID,
+                          ullThreadId);
+        }
+        else if( BooleanFlagOn( CreateSetAuthGroup->Flags, AFS_PAG_FLAGS_SET_AS_ACTIVE))
+        {
+            pProcessCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Set new AuthGroup for SID %wZ SessionID %08lX for PID %I64X on process\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ulSessionId,
+                          ullProcessID);
+        }
+
+try_exit:
+
+        if( pProcessCB != NULL)
+        {
+            AFSReleaseResource( &pProcessCB->Lock);
+        }
+
+        if( uniCallerSID.Length > 0)
+        {
+            RtlFreeUnicodeString( &uniCallerSID);
+        }
+    }
+
+    return ntStatus;
+}
+
+//
+// Returns a list of the AuthGroup GUIDS associated
+// with the current process, the current process GUID,
+// and the current thread GUID.
+//
+
+NTSTATUS
+AFSQueryProcessAuthGroupList( IN GUID *GUIDList,
+                              IN ULONG BufferLength,
+                              OUT ULONG_PTR *ReturnLength)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    ULONG ulRequiredLength = 0;
+    AFSProcessAuthGroupCB *pAuthGroup = NULL;
+    GUID *pCurrentGUID = GUIDList;
+    UNICODE_STRING uniGUIDString;
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for PID %I64X\n",
+                      __FUNCTION__,
+                      ullProcessID);
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
+                                       (ULONGLONG)ullProcessID,
+                                       (AFSBTreeEntry **)&pProcessCB);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            pProcessCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate process entry PID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        AFSAcquireShared( &pProcessCB->Lock,
+                          TRUE);
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        pAuthGroup = pProcessCB->AuthGroupList;
+
+        ulRequiredLength = 0;
+
+        while( pAuthGroup != NULL)
+        {
+            ulRequiredLength += sizeof( GUID);
+            pAuthGroup = pAuthGroup->Next;
+        }
+
+        if( BufferLength == 0 ||
+            BufferLength < ulRequiredLength ||
+            GUIDList == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Buffer too small for query, required %08lX for PID %I64X\n",
+                          __FUNCTION__,
+                          ulRequiredLength,
+                          ullProcessID);
+
+            *ReturnLength = ulRequiredLength;
+            try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
+        }
+
+        pAuthGroup = pProcessCB->AuthGroupList;
+
+        *ReturnLength = 0;
+
+        while( pAuthGroup != NULL)
+        {
+            RtlCopyMemory( pCurrentGUID,
+                           &pAuthGroup->AuthGroup,
+                           sizeof( GUID));
+
+            uniGUIDString.Buffer = NULL;
+            uniGUIDString.Length = 0;
+            uniGUIDString.MaximumLength = 0;
+
+            RtlStringFromGUID( pAuthGroup->AuthGroup,
+                               &uniGUIDString);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Adding AuthGroup %wZ for PID %I64X\n",
+                          __FUNCTION__,
+                          &uniGUIDString,
+                          ullProcessID);
+
+            if( uniGUIDString.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUIDString);
+            }
+
+            pCurrentGUID = (GUID *)((char *)pCurrentGUID + sizeof( GUID));
+
+            *ReturnLength += sizeof( GUID);
+
+            pAuthGroup = pAuthGroup->Next;
+        }
+
+try_exit:
+
+        if( pProcessCB != NULL)
+        {
+            AFSReleaseResource( &pProcessCB->Lock);
+        }
+    }
+
+    return ntStatus;
+}
+
+//
+// Permits the current AuthGroup for the process or
+// thread to be set to the specified GUID.  The GUID
+// must be in the list of current values for the process.
+//
+
+NTSTATUS
+AFSSetActiveProcessAuthGroup( IN AFSAuthGroupRequestCB *ActiveAuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSThreadCB *pThreadCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId();
+    AFSProcessAuthGroupCB *pAuthGroup = NULL;
+    UNICODE_STRING uniGUIDString;
+
+    __Enter
+    {
+
+        uniGUIDString.Length = 0;
+        uniGUIDString.MaximumLength = 0;
+        uniGUIDString.Buffer = NULL;
+
+        RtlStringFromGUID( ActiveAuthGroup->AuthGroup,
+                           &uniGUIDString);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for ProcessID %I64X AuthGroup GUID %wZ\n",
+                      __FUNCTION__,
+                      ullProcessID,
+                      &uniGUIDString);
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
+                                       (ULONGLONG)ullProcessID,
+                                       (AFSBTreeEntry **)&pProcessCB);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            pProcessCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate process entry for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+
+        AFSAcquireExcl( &pProcessCB->Lock,
+                        TRUE);
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        pAuthGroup = pProcessCB->AuthGroupList;
+
+        while( pAuthGroup != NULL)
+        {
+
+            if( RtlCompareMemory( &ActiveAuthGroup->AuthGroup,
+                                  &pAuthGroup->AuthGroup,
+                                  sizeof( GUID)) == sizeof( GUID))
+            {
+                break;
+            }
+            pAuthGroup = pAuthGroup->Next;
+        }
+
+        if( pAuthGroup == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Failed to locate AuthGroup for ProcessID %I64X AuthGroup GUID %wZ\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          &uniGUIDString);
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        if( BooleanFlagOn( ActiveAuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP))
+        {
+
+            pThreadCB = pProcessCB->ThreadList;
+
+            while( pThreadCB != NULL)
+            {
+
+                if( pThreadCB->ThreadId == ullThreadId)
+                {
+                    pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+                    break;
+                }
+
+                pThreadCB = pThreadCB->Next;
+            }
+
+            if( pThreadCB == NULL)
+            {
+
+                pThreadCB = AFSInitializeThreadCB( pProcessCB,
+                                                   ullThreadId);
+
+                if( pThreadCB == NULL)
+                {
+                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+                }
+
+                pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Set active AuthGroup for ProcessID %I64X AuthGroup GUID %wZ on thread %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          &uniGUIDString,
+                          ullThreadId);
+        }
+        else
+        {
+            pProcessCB->ActiveAuthGroup = &pAuthGroup->AuthGroup;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Set active AuthGroup for ProcessID %I64X AuthGroup GUID %wZ on process\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          &uniGUIDString);
+        }
+
+try_exit:
+
+        if( pProcessCB != NULL)
+        {
+            AFSReleaseResource( &pProcessCB->Lock);
+        }
+
+        if( uniGUIDString.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUIDString);
+        }
+    }
+
+    return ntStatus;
+}
+
+//
+// Resets the current AuthGroup for the process or
+// thread to the SID-AuthGroup
+//
+
+NTSTATUS
+AFSResetActiveProcessAuthGroup( IN IN AFSAuthGroupRequestCB *AuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    GUID *pAuthGroup = NULL;
+    AFSProcessCB *pProcessCB = NULL;
+    AFSThreadCB *pThreadCB = NULL;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId();
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for ProcessID %I64X\n",
+                      __FUNCTION__,
+                      ullProcessID);
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
+                                       (ULONGLONG)ullProcessID,
+                                       (AFSBTreeEntry **)&pProcessCB);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            pProcessCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate AuthGroup for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        AFSAcquireExcl( &pProcessCB->Lock,
+                        TRUE);
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
+
+        if( BooleanFlagOn( AuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP))
+        {
+
+            pThreadCB = pProcessCB->ThreadList;
+
+            while( pThreadCB != NULL)
+            {
+
+                if( pThreadCB->ThreadId == ullThreadId)
+                {
+                    pThreadCB->ActiveAuthGroup = NULL;
+                    break;
+                }
+
+                pThreadCB = pThreadCB->Next;
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Reset AuthGroup list on thread %I64X for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullThreadId,
+                          ullProcessID);
+        }
+        else
+        {
+            pProcessCB->ActiveAuthGroup = NULL;
+
+            pThreadCB = pProcessCB->ThreadList;
+
+            while( pThreadCB != NULL)
+            {
+                pThreadCB->ActiveAuthGroup = NULL;
+                pThreadCB = pThreadCB->Next;
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Reset AuthGroup list on process for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+        }
+
+        AFSReleaseResource( &pProcessCB->Lock);
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+//
+// When bLogonSession == FALSE, the SID must not be specified
+// and the SessionId must be -1.  A new AuthGroup GUID is
+// assigned to the SID and SessionId of the calling Process.
+//
+// When bLogonSession == TRUE, the SID must be specified and
+// the SessionId must not be -1.  The SID of the calling process
+// must be LOCAL_SYSTEM and a new AuthGroup GUID is assigned to
+// the specified SID and logon session.
+//
+
+NTSTATUS
+AFSCreateAuthGroupForSIDorLogonSession( IN AFSAuthGroupRequestCB *AuthGroupRequestCB,
+                                        IN BOOLEAN bLogonSession)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId();
+    UNICODE_STRING uniSIDString, uniPassedSIDString;
+    ULONG ulSIDHash = 0;
+    AFSSIDEntryCB *pSIDEntryCB = NULL;
+    ULONG ulSessionId = 0;
+    ULONGLONG ullTableHash = 0;
+    GUID stAuthGroup;
+    UNICODE_STRING uniCallerSID;
+    UNICODE_STRING uniGUID;
+    BOOLEAN bLocalSystem = FALSE;
+    BOOLEAN bImpersonation = FALSE;
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for ProcessID %I64X ThreadID %I64X\n",
+                      __FUNCTION__,
+                      ullProcessID,
+                      ullThreadId);
+
+        ntStatus = AFSGetCallerSID( &uniCallerSID, &bImpersonation);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to retrieve callers SID for ProcessID %I64X ThreadID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          ullThreadId,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        bLocalSystem = AFSIsLocalSystemSID( &uniCallerSID);
+
+        if( bLogonSession == TRUE &&
+            bLocalSystem == FALSE)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s caller is %wZ and LOCAL SYSTEM AUTHORITY required\n",
+                          __FUNCTION__,
+                          uniCallerSID);
+
+            try_return( ntStatus = STATUS_ACCESS_DENIED);
+        }
+
+        if ( bLogonSession == TRUE &&
+             ( AuthGroupRequestCB == NULL ||
+               AuthGroupRequestCB->SIDLength == 0 ||
+               AuthGroupRequestCB->SessionId == (ULONG)-1))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s SID and SessionId are mandatory\n",
+                          __FUNCTION__);
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        if ( bLogonSession == FALSE &&
+             AuthGroupRequestCB != NULL &&
+             ( AuthGroupRequestCB->SIDLength > 0 ||
+               AuthGroupRequestCB->SessionId != (ULONG)-1))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s SID and SessionId must not be specified\n",
+                          __FUNCTION__);
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Retrieved callers SID %wZ for ProcessID %I64X ThreadID %I64X\n",
+                      __FUNCTION__,
+                      &uniCallerSID,
+                      ullProcessID,
+                      ullThreadId);
+
+        if( AuthGroupRequestCB != NULL &&
+            AuthGroupRequestCB->SIDLength != 0)
+        {
+
+            uniPassedSIDString.Length = AuthGroupRequestCB->SIDLength;
+            uniPassedSIDString.MaximumLength = uniPassedSIDString.Length;
+
+            uniPassedSIDString.Buffer = AuthGroupRequestCB->SIDString;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Checking passed SID %wZ for ProcessID %I64X ThreadID %I64X\n",
+                          __FUNCTION__,
+                          &uniPassedSIDString,
+                          ullProcessID,
+                          ullThreadId);
+
+            if( RtlCompareUnicodeString( &uniCallerSID,
+                                         &uniPassedSIDString,
+                                         TRUE) != 0)
+            {
+
+                if( !bLocalSystem)
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "%s Not using passed SID %wZ for ProcessID %I64X ThreadID %I64X caller is not LOCAL SYSTEM AUTHORITY\n",
+                                  __FUNCTION__,
+                                  &uniPassedSIDString,
+                                  ullProcessID,
+                                  ullThreadId);
+
+                    try_return( ntStatus = STATUS_ACCESS_DENIED);
+                }
+
+                uniSIDString = uniPassedSIDString;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Using passed SID %wZ for ProcessID %I64X ThreadID %I64X\n",
+                              __FUNCTION__,
+                              &uniSIDString,
+                              ullProcessID,
+                              ullThreadId);
+            }
+            else
+            {
+                uniSIDString = uniCallerSID;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Both SIDs are equal, using callers SID %wZ for ProcessID %I64X ThreadID %I64X\n",
+                              __FUNCTION__,
+                              &uniSIDString,
+                              ullProcessID,
+                              ullThreadId);
+            }
+        }
+        else
+        {
+            uniSIDString = uniCallerSID;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Using callers SID %wZ for ProcessID %I64X ThreadID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID,
+                          ullThreadId);
+        }
+
+        ntStatus = RtlHashUnicodeString( &uniSIDString,
+                                         TRUE,
+                                         HASH_STRING_ALGORITHM_DEFAULT,
+                                         &ulSIDHash);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to hash SID %wZ for ProcessID %I64X ThreadID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID,
+                          ullThreadId,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation);
+
+        if( ulSessionId == (ULONG)-1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to retrieve session ID for ProcessID %I64X ThreadID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID,
+                          ullThreadId);
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        if( bLogonSession == TRUE &&
+            AuthGroupRequestCB != NULL &&
+            AuthGroupRequestCB->SessionId != (ULONG)-1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Checking passed SessionID %08lX for ProcessID %I64X ThreadID %I64X\n",
+                          __FUNCTION__,
+                          AuthGroupRequestCB->SessionId,
+                          ullProcessID,
+                          ullThreadId);
+
+            if( ulSessionId != AuthGroupRequestCB->SessionId)
+            {
+
+                ulSessionId = AuthGroupRequestCB->SessionId;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Using passed SessionID %08lX for ProcessID %I64X ThreadID %I64X\n",
+                              __FUNCTION__,
+                              AuthGroupRequestCB->SessionId,
+                              ullProcessID,
+                              ullThreadId);
+            }
+        }
+        else
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Using callers SessionID %08lX for ProcessID %I64X ThreadID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ullProcessID,
+                          ullThreadId);
+        }
+
+        ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash);
+
+        AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock,
+                        TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
+                                       (ULONGLONG)ullTableHash,
+                                       (AFSBTreeEntry **)&pSIDEntryCB);
+
+        if( NT_SUCCESS( ntStatus) &&
+            pSIDEntryCB != NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Located SID entry for SID %wZ SessionID %08lX ProcessID %I64X ThreadID %I64X, updating GUID\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ulSessionId,
+                          ullProcessID,
+                          ullThreadId);
+
+            uniGUID.Buffer = NULL;
+
+            RtlStringFromGUID( pSIDEntryCB->AuthGroup,
+                               &uniGUID);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Updating existing AuthGroup GUID %wZ\n",
+                          __FUNCTION__,
+                          &uniGUID);
+
+            if( uniGUID.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUID);
+            }
+
+            while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY);
+
+            uniGUID.Buffer = NULL;
+
+            RtlStringFromGUID( pSIDEntryCB->AuthGroup,
+                               &uniGUID);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Updated existing AuthGroup GUID %wZ\n",
+                          __FUNCTION__,
+                          &uniGUID);
+
+            if( uniGUID.Buffer != NULL)
+            {
+                RtlFreeUnicodeString( &uniGUID);
+            }
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
+            try_return( ntStatus);
+        }
+
+        pSIDEntryCB = (AFSSIDEntryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
+                                                                 sizeof( AFSSIDEntryCB),
+                                                                 AFS_AG_ENTRY_CB_TAG);
+
+        if( pSIDEntryCB == NULL)
+        {
+            AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pSIDEntryCB,
+                       sizeof( AFSSIDEntryCB));
+
+        pSIDEntryCB->TreeEntry.HashIndex = (ULONGLONG)ullTableHash;
+
+        while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY);
+
+        if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL)
+        {
+            pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB;
+        }
+        else
+        {
+            AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
+                                &pSIDEntryCB->TreeEntry);
+        }
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
+
+        uniGUID.Buffer = NULL;
+
+        RtlStringFromGUID( pSIDEntryCB->AuthGroup,
+                           &uniGUID);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Created new AuthGroup GUID %wZ SID %wZ Session %08lX\n",
+                      __FUNCTION__,
+                      &uniGUID,
+                      &uniSIDString,
+                      ulSessionId);
+
+        if( uniGUID.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUID);
+        }
+
+try_exit:
+
+        if( uniCallerSID.Length > 0)
+        {
+            RtlFreeUnicodeString( &uniCallerSID);
+        }
+    }
+
+    return ntStatus;
+}
+
+//
+// Given a SID and SessionId as input, returns the associated AuthGroup GUID.
+// If SID or SessionId are not specified, the current process values are used.
+//
+
+NTSTATUS
+AFSQueryAuthGroup( IN AFSAuthGroupRequestCB *AuthGroup,
+                   OUT GUID *AuthGroupGUID,
+                   OUT ULONG_PTR *ReturnLength)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
+    UNICODE_STRING uniSIDString;
+    ULONG ulSIDHash = 0;
+    AFSSIDEntryCB *pSIDEntryCB = NULL;
+    ULONG ulSessionId = 0;
+    ULONGLONG ullTableHash = 0;
+    BOOLEAN bReleaseSID = FALSE;
+    UNICODE_STRING uniGUID;
+    BOOLEAN bImpersonation = FALSE;
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry for ProcessID %I64X\n",
+                      __FUNCTION__,
+                      ullProcessID);
+
+        if( AuthGroup == NULL ||
+            AuthGroup->SIDLength == 0)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s No SID specified, retrieving callers SID for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "%s Failed to retrieve callers SID for ProcessID %I64X Status %08lX\n",
+                              __FUNCTION__,
+                              ullProcessID,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            bReleaseSID = TRUE;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Retrieved callers SID %wZ for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID);
+        }
+        else
+        {
+
+            uniSIDString.Length = AuthGroup->SIDLength;
+            uniSIDString.MaximumLength = uniSIDString.Length;
+
+            uniSIDString.Buffer = AuthGroup->SIDString;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Using passed SID %wZ for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID);
+        }
+
+        ntStatus = RtlHashUnicodeString( &uniSIDString,
+                                         TRUE,
+                                         HASH_STRING_ALGORITHM_DEFAULT,
+                                         &ulSIDHash);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to hash SID %wZ for ProcessID %I64X Status %08lX\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ullProcessID,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        if( AuthGroup == NULL ||
+            AuthGroup->SessionId == -1)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s No SessionID specified, retrieving callers for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ullProcessID);
+
+            ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation);
+
+            if( ulSessionId == (ULONG)-1)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "%s Failed to retrieve callers Session ID for ProcessID %I64X\n",
+                              __FUNCTION__,
+                              ullProcessID);
+
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Retrieved callers SessionID %08lX for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ullProcessID);
+        }
+        else
+        {
+            ulSessionId = AuthGroup->SessionId;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Using passed SessionID %08lX for ProcessID %I64X\n",
+                          __FUNCTION__,
+                          ulSessionId,
+                          ullProcessID);
+        }
+
+        ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash);
+
+        AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock,
+                          TRUE);
+
+        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
+                                       (ULONGLONG)ullTableHash,
+                                       (AFSBTreeEntry **)&pSIDEntryCB);
+
+        if( pSIDEntryCB == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to locate SID entry for SID %wZ SessionID %08lX ProcessID %I64X\n",
+                          __FUNCTION__,
+                          &uniSIDString,
+                          ulSessionId,
+                          ullProcessID);
+
+            AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
+            try_return( ntStatus = STATUS_NOT_FOUND);
+        }
+
+        RtlCopyMemory( AuthGroupGUID,
+                       &pSIDEntryCB->AuthGroup,
+                       sizeof( GUID));
+
+        *ReturnLength = sizeof( GUID);
+
+        uniGUID.Buffer = NULL;
+
+        RtlStringFromGUID( pSIDEntryCB->AuthGroup,
+                           &uniGUID);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Retrieved AuthGroup GUID %wZ for ProcessID %I64X\n",
+                      __FUNCTION__,
+                      &uniGUID,
+                      ullProcessID);
+
+        if( uniGUID.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUID);
+        }
+
+        AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
+
+try_exit:
+
+        if( bReleaseSID &&
+            uniSIDString.Length > 0)
+        {
+            RtlFreeUnicodeString( &uniSIDString);
+        }
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp
new file mode 100644 (file)
index 0000000..13bb42f
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * 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
+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/fs/AFSCleanup.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCleanup.cpp
new file mode 100644 (file)
index 0000000..5209873
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * 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 DeviceObject,
+            IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __try
+    {
+
+        //
+        // Set some initial variables to make processing easier
+        //
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_CONTROL_INSTANCE))
+            {
+
+                //
+                // This is the process which was registered for the callback pool so cleanup the pool
+                //
+
+                AFSCleanupIrpPool();
+            }
+
+            if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_REDIRECTOR_INSTANCE))
+            {
+
+                //
+                // Close the redirector
+                //
+
+                AFSCloseRedirector();
+            }
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        ntStatus = AFSCommonCleanup( DeviceObject,
+                                     Irp);
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSCleanup\n");
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSCommonCleanup( IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PFILE_OBJECT pFileObject = NULL;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    BOOLEAN bCompleteRequest = TRUE;
+
+    __Enter
+    {
+
+        //
+        // Set some initial variables to make processing easier
+        //
+
+        pFileObject = pIrpSp->FileObject;
+
+        if( pIrpSp->FileObject->FsContext == NULL)
+        {
+
+            //
+            // Root open
+            //
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus == STATUS_PENDING)
+            {
+                bCompleteRequest = FALSE;
+            }
+
+            try_return( ntStatus);
+        }
+
+        bCompleteRequest = FALSE;
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        if( bCompleteRequest)
+        {
+
+            if( pFileObject != NULL)
+            {
+
+                //
+                // Setup the fileobject flags to indicate cleanup is complete.
+                //
+
+                SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
+            }
+
+            //
+            // Complete the request
+            //
+
+            AFSCompleteRequest( Irp, ntStatus);
+        }
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSClose.cpp b/src/WINNT/afsrdr/kernel/fs/AFSClose.cpp
new file mode 100644 (file)
index 0000000..159dd11
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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 DeviceObject,
+          IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        ntStatus = AFSCommonClose( DeviceObject,
+                                   Irp);
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSClose\n");
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSCommonClose( IN PDEVICE_OBJECT DeviceObject,
+                IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulRequestType = 0;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSDeviceExt *pDeviceExt = NULL;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __Enter
+    {
+
+        pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+        if( pIrpSp->FileObject->FsContext == NULL)
+        {
+
+            AFSCompleteRequest( Irp, ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp
new file mode 100644 (file)
index 0000000..f803c7e
--- /dev/null
@@ -0,0 +1,1591 @@
+/*
+ * 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
+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;
+}
+
+NTSTATUS
+AFSProcessRequest( IN ULONG RequestType,
+                   IN ULONG RequestFlags,
+                   IN GUID *AuthGroup,
+                   IN PUNICODE_STRING FileName,
+                   IN AFSFileID *FileId,
+                   IN void  *Data,
+                   IN ULONG DataLength,
+                   IN OUT void *ResultBuffer,
+                   IN OUT PULONG ResultBufferLength)
+{
+
+    NTSTATUS         ntStatus = STATUS_SUCCESS;
+    AFSPoolEntry     stPoolEntry, *pPoolEntry = NULL;
+    AFSCommSrvcCB   *pCommSrvc = NULL;
+    BOOLEAN          bReleasePool = FALSE;
+    AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSDeviceExt    *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    BOOLEAN          bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS);
+    ULONG            ulPoolEntryLength = 0;
+    BOOLEAN          bDecrementCount = FALSE;
+
+    __try
+    {
+
+        if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
+        {
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1)
+        {
+            KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent);
+        }
+
+        bDecrementCount = TRUE;
+
+        pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
+
+        //
+        // Grab the pool resource and check the state
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->IrpPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
+                        TRUE);
+
+        bReleasePool = TRUE;
+
+        if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
+        {
+
+            //
+            // Pool not running so bail.
+            //
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        //
+        // If this is an async request we need to allocate a pool entry for the request
+        //
+
+        pPoolEntry = &stPoolEntry;
+
+        if( !bWait)
+        {
+
+            ASSERT( ResultBuffer == NULL);
+
+            ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength);
+
+            if( FileName != NULL)
+            {
+
+                ulPoolEntryLength += FileName->Length;
+            }
+
+            pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool,
+                                                                   ulPoolEntryLength,
+                                                                   AFS_POOL_ENTRY_TAG);
+
+            if( pPoolEntry == NULL)
+            {
+
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
+
+            RtlZeroMemory( pPoolEntry,
+                           ulPoolEntryLength);
+
+            pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry));
+
+            pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength);
+        }
+        else
+        {
+
+            RtlZeroMemory( pPoolEntry,
+                           sizeof( AFSPoolEntry));
+
+            KeInitializeEvent( &pPoolEntry->Event,
+                               NotificationEvent,
+                               FALSE);
+        }
+
+        pPoolEntry->RequestType = RequestType;
+
+        pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++;
+
+        pPoolEntry->RequestFlags = RequestFlags;
+
+        pPoolEntry->ResultBufferLength = 0;
+
+        if( FileId != NULL)
+        {
+
+            pPoolEntry->FileId = *FileId;
+        }
+
+        pPoolEntry->FileName.Length = 0;
+
+        if( FileName != NULL)
+        {
+
+            if( bWait)
+            {
+
+                pPoolEntry->FileName = *FileName;
+            }
+            else
+            {
+
+                pPoolEntry->FileName.Length = FileName->Length;
+
+                pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length;
+
+                RtlCopyMemory( pPoolEntry->FileName.Buffer,
+                               FileName->Buffer,
+                               pPoolEntry->FileName.Length);
+            }
+        }
+
+        //
+        // Move in the data if there is some
+        //
+
+        pPoolEntry->DataLength = DataLength;
+
+        if( Data != NULL &&
+            DataLength > 0)
+        {
+
+            if( bWait)
+            {
+
+                pPoolEntry->Data = Data;
+            }
+            else
+            {
+
+                RtlCopyMemory( pPoolEntry->Data,
+                               Data,
+                               DataLength);
+            }
+        }
+
+        pPoolEntry->ResultBuffer = ResultBuffer;
+
+        pPoolEntry->ResultBufferLength = ResultBufferLength;
+
+        //
+        // Store off the auth group
+        //
+
+        if( AuthGroup == NULL)
+        {
+            AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(),
+                                  (ULONGLONG)PsGetCurrentThreadId(),
+                                  &pPoolEntry->AuthGroup);
+        }
+        else
+        {
+            RtlCopyMemory( &pPoolEntry->AuthGroup,
+                           AuthGroup,
+                           sizeof( GUID));
+        }
+
+        if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup))
+        {
+            SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG);
+        }
+
+        if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup))
+        {
+            AFSDbgLogMsg( 0,
+                          0,
+                          "AFSProcessRequest NoPAG Auth Group %08lX\n",
+                          PsGetCurrentThread());
+        }
+
+        //
+        // Indicate the type of process
+        //
+
+#ifdef AMD64
+
+        if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId()))
+        {
+            SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64);
+        }
+
+#endif
+
+        //
+        // Insert the entry into the request pool
+        //
+
+        ntStatus = AFSInsertRequest( pCommSrvc,
+                                     pPoolEntry);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( !bWait)
+            {
+
+                ExFreePool( pPoolEntry);
+            }
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Drop the lock on the pool prior to waiting
+        //
+
+        AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+        bReleasePool = FALSE;
+
+        //
+        // Wait for the result if this is NOT an asynchronous request
+        //
+
+        if( bWait)
+        {
+
+            //
+            // Wait for the result of the request. We specify no timeout ...
+            //
+
+            ntStatus = KeWaitForSingleObject( &pPoolEntry->Event,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              NULL);
+
+            //
+            // Process the result of the request
+            //
+
+            if( ntStatus == STATUS_SUCCESS)
+            {
+
+                ntStatus = pPoolEntry->ResultStatus;
+            }
+            else
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+            }
+        }
+
+try_exit:
+
+        if( bReleasePool)
+        {
+
+            AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+        }
+
+        if( bDecrementCount &&
+            InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
+        {
+            KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
+                        0,
+                        FALSE);
+        }
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()))
+    {
+
+        if( bReleasePool)
+        {
+
+            AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+        }
+
+        if( bDecrementCount &&
+            InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
+        {
+            KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
+                        0,
+                        FALSE);
+        }
+
+        if ( ntStatus == STATUS_SUCCESS)
+        {
+
+            ntStatus = STATUS_UNSUCCESSFUL;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSProcessControlRequest( IN PIRP Irp)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    PIO_STACK_LOCATION  pIrpSp;
+    ULONG               ulIoControlCode;
+    BOOLEAN             bCompleteRequest = TRUE;
+    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    ULONG               ulBytesProcessed = 0;
+
+    __try
+    {
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+        ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
+
+        switch( ulIoControlCode)
+        {
+
+            case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
+            {
+
+                //
+                // Go intialize the pool
+                //
+
+                ntStatus = AFSInitIrpPool();
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    //
+                    // Don't initialize
+                    //
+
+                    break;
+                }
+
+                //
+                // Tag this instance as the one to close the irp pool when it is closed
+                //
+
+                pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
+
+                break;
+            }
+
+            case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
+            {
+
+                AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
+
+                //
+                // Extract off the passed in information which contains the
+                // cache file parameters
+                //
+
+                if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
+                                                                                                    pRedirInitInfo->CacheFileNameLength)
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                //
+                // Initialize the Redirector device
+                //
+
+                ntStatus = AFSInitializeRedirector( pRedirInitInfo);
+
+                if( !NT_SUCCESS( ntStatus))
+                {
+
+                    break;
+                }
+
+                //
+                // Stash away context so we know the instance used to initialize the redirector
+                //
+
+                pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
+
+                break;
+            }
+
+            case IOCTL_AFS_PROCESS_IRP_REQUEST:
+            {
+
+                ntStatus = AFSProcessIrpRequest( Irp);
+
+                break;
+            }
+
+            case IOCTL_AFS_PROCESS_IRP_RESULT:
+            {
+
+                ntStatus = AFSProcessIrpResult( Irp);
+
+                break;
+            }
+
+            case IOCTL_AFS_SYSNAME_NOTIFICATION:
+            {
+
+                AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pSysNameInfo == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSSetSysNameInformation( pSysNameInfo,
+                                                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+                break;
+            }
+
+            case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
+            {
+
+                AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pTraceInfo == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSConfigureTrace( pTraceInfo);
+
+                break;
+            }
+
+            case IOCTL_AFS_GET_TRACE_BUFFER:
+            {
+
+                if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
+                                              Irp->AssociatedIrp.SystemBuffer,
+                                              &Irp->IoStatus.Information);
+
+                break;
+            }
+
+            case IOCTL_AFS_FORCE_CRASH:
+            {
+
+#if DBG
+
+                if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
+                {
+
+                    KeBugCheck( (ULONG)-1);
+                }
+#endif
+
+                break;
+            }
+
+#ifdef NOT_IMPLEMENTED
+            case IOCTL_AFS_LOAD_LIBRARY:
+            {
+
+                AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
+                UNICODE_STRING uniServicePath;
+
+                if( pLoadLib == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
+                                                                                                    pLoadLib->LibraryServicePathLength)
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                uniServicePath.Length = pLoadLib->LibraryServicePathLength;
+                uniServicePath.MaximumLength = uniServicePath.Length;
+
+                uniServicePath.Buffer = pLoadLib->LibraryServicePath;
+
+                if( uniServicePath.Length == 0)
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSLoadLibrary( pLoadLib->Flags,
+                                           &uniServicePath);
+
+                if( NT_SUCCESS( ntStatus))
+                {
+
+                    //
+                    // Intialize the library
+                    //
+
+                    ntStatus = AFSInitializeLibrary( NULL,
+                                                     FALSE);
+                }
+
+                break;
+            }
+
+            case IOCTL_AFS_UNLOAD_LIBRARY:
+            {
+
+                //
+                // Try to unload the library we currently have in place
+                //
+
+                ntStatus = AFSUnloadLibrary( FALSE);
+
+                break;
+            }
+#endif
+
+            case IOCTL_AFS_SHUTDOWN:
+            {
+
+                ntStatus = AFSShutdownRedirector();
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
+            {
+
+
+                AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pAuthGroupRequestCB == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_QUERY:
+            {
+
+                ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
+                                                         pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
+                                                         &Irp->IoStatus.Information);
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_SET:
+            {
+
+                AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pAuthGroupRequestCB == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_RESET:
+            {
+
+                AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pAuthGroupRequestCB == NULL ||
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
+            case IOCTL_AFS_AUTHGROUP_SID_CREATE:
+            {
+
+                AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
+
+                if( pAuthGroupRequestCB != NULL &&
+                    pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
+                {
+
+                    ntStatus = STATUS_INVALID_PARAMETER;
+
+                    break;
+                }
+
+                ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
+                                                                   ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
+
+                break;
+            }
+
+            case IOCTL_AFS_AUTHGROUP_SID_QUERY:
+            {
+
+                AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
+
+                if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
+                {
+                    ntStatus = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
+                {
+                    pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
+                }
+
+                ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
+                                              (GUID *)Irp->AssociatedIrp.SystemBuffer,
+                                              &Irp->IoStatus.Information);
+
+                break;
+            }
+
+            default:
+            {
+
+                //
+                // Check the state of the library
+                //
+
+                ntStatus = AFSCheckLibraryState( Irp);
+
+                if( !NT_SUCCESS( ntStatus) ||
+                    ntStatus == STATUS_PENDING)
+                {
+
+                    if( ntStatus == STATUS_PENDING)
+                    {
+                        bCompleteRequest = FALSE;
+                    }
+
+                    break;
+                }
+
+                bCompleteRequest = FALSE;
+
+                IoSkipCurrentIrpStackLocation( Irp);
+
+                ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
+                                         Irp);
+
+                //
+                // Indicate the library is done with the request
+                //
+
+                AFSClearLibraryRequest();
+
+                break;
+            }
+        }
+
+//try_exit:
+
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()))
+    {
+
+        ntStatus = STATUS_UNSUCCESSFUL;
+    }
+
+    if( bCompleteRequest)
+    {
+
+        Irp->IoStatus.Status = ntStatus;
+
+        AFSCompleteRequest( Irp,
+                              ntStatus);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInitIrpPool()
+{
+
+    NTSTATUS       ntStatus = STATUS_SUCCESS;
+    AFSCommSrvcCB *pCommSrvc = NULL;
+    BOOLEAN        bReleasePools = FALSE;
+    AFSDeviceExt  *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __Enter
+    {
+
+        pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
+
+        //
+        // Whenever we change state we must grab both pool locks. On the checking of the state
+        // within the processing routines for these respective pools, we only grab one lock to
+        // minimize serialization. The ordering is always the Irp pool then the result pool
+        // locks. We also do this in the tear down of the pool
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->IrpPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
+                          TRUE);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->ResultPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
+                          TRUE);
+
+        bReleasePools = TRUE;
+
+        //
+        // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
+        // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
+        // shouldn't be getting this request ...
+        //
+
+        if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
+        {
+
+            //
+            // We have already been activated so just fail this request
+            //
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+        else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
+        {
+
+            //
+            // The pool is currently INACTIVE so start it up and ready it to
+            // receive irp requests
+            //
+
+            pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
+
+            pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
+
+            try_return( ntStatus = STATUS_SUCCESS);
+        }
+        else
+        {
+
+            //
+            // The pool is in some mixed state, fail the request.
+            //
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+try_exit:
+
+        if( bReleasePools)
+        {
+
+            AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+            AFSReleaseResource( &pCommSrvc->ResultPoolLock);
+        }
+    }
+
+    return ntStatus;
+}
+
+void
+AFSCleanupIrpPool()
+{
+
+    NTSTATUS        ntStatus = STATUS_SUCCESS;
+    AFSPoolEntry   *pEntry = NULL, *pNextEntry = NULL;
+    AFSDeviceExt   *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSCommSrvcCB  *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
+
+    __Enter
+    {
+
+        //
+        // When we change the state, grab both pool locks exclusive. The order is always the
+        // Irp pool then the result pool lock
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->IrpPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
+                        TRUE);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->ResultPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
+                        TRUE);
+
+        //
+        // Indicate we are pending stop
+        //
+
+        pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
+
+        //
+        // Set the event to release any waiting workers
+        //
+
+        KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
+                    0,
+                    FALSE);
+
+        KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
+                    0,
+                    FALSE);
+
+        //
+        // Go through the pool entries and free up the structures.
+        //
+
+        pEntry = pCommSrvc->RequestPoolHead;
+
+        while( pEntry != NULL)
+        {
+
+            pNextEntry = pEntry->fLink;
+
+            if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
+            {
+
+                //
+                // Here we need to complete the irp, cancelled, and delete the data block
+                //
+
+                pEntry->ResultStatus = STATUS_CANCELLED;
+
+                KeSetEvent( &pEntry->Event,
+                            0,
+                            FALSE);
+            }
+            else
+            {
+
+                ExFreePool( pEntry);
+            }
+
+            pEntry = pNextEntry;
+        }
+
+        //
+        // Cleanup the control structure for the request pool
+        //
+
+        pCommSrvc->RequestPoolHead = NULL;
+
+        pCommSrvc->RequestPoolTail = NULL;
+
+        pCommSrvc->IrpPoolRequestIndex = 1;
+
+        KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
+
+        KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
+
+        //
+        // Release the irp pool lock.
+        //
+
+        AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+        //
+        // Go through the result pool entries and free up the structures.
+        //
+
+        pEntry = pCommSrvc->ResultPoolHead;
+
+        while( pEntry != NULL)
+        {
+
+            pNextEntry = pEntry->fLink;
+
+            pEntry->ResultStatus = STATUS_CANCELLED;
+
+            //
+            // Here we will set the event of the requestor and let the blocked thread
+            // free the data block
+            //
+
+            KeSetEvent( &pEntry->Event,
+                        0,
+                        FALSE);
+
+            //
+            // Go onto the next entry
+            //
+
+            pEntry = pNextEntry;
+        }
+
+        //
+        // Cleanup the control structure for the result pool
+        //
+
+        pCommSrvc->ResultPoolHead = NULL;
+
+        pCommSrvc->ResultPoolTail = NULL;
+
+        //
+        // Release the result pool lock.
+        //
+
+        AFSReleaseResource( &pCommSrvc->ResultPoolLock);
+    }
+
+    return;
+}
+
+NTSTATUS
+AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
+                  IN AFSPoolEntry *Entry)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
+                      &CommSrvc->IrpPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &CommSrvc->IrpPoolLock,
+                        TRUE);
+
+        if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
+        {
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        if( CommSrvc->RequestPoolHead == NULL)
+        {
+
+            CommSrvc->RequestPoolHead = Entry;
+        }
+        else
+        {
+
+            CommSrvc->RequestPoolTail->fLink = Entry;
+
+            Entry->bLink = CommSrvc->RequestPoolTail;
+        }
+
+        CommSrvc->RequestPoolTail = Entry;
+
+        if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
+        {
+
+            KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
+                        0,
+                        FALSE);
+        }
+        else
+        {
+
+            KeSetEvent( &CommSrvc->IrpPoolHasEntries,
+                        0,
+                        FALSE);
+        }
+
+        InterlockedIncrement( &CommSrvc->QueueCount);
+
+try_exit:
+
+        AFSReleaseResource( &CommSrvc->IrpPoolLock);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSProcessIrpRequest( IN PIRP Irp)
+{
+
+    NTSTATUS         ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt    *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSCommSrvcCB   *pCommSrvc = NULL;
+    AFSPoolEntry    *pEntry = NULL, *pPrevEntry = NULL;
+    AFSCommRequest  *pRequest = NULL;
+    BOOLEAN          bReleaseRequestThread = FALSE;
+
+    __Enter
+    {
+
+        pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
+
+        pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->IrpPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
+                        TRUE);
+
+        if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
+        {
+
+            AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+        //
+        // Is this a dedicated flush thread?
+        //
+
+        if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
+        {
+
+            bReleaseRequestThread = TRUE;
+        }
+
+        //
+        // Wait on the 'have items' event until we can retrieve an item
+        //
+
+        while( TRUE)
+        {
+
+            if( bReleaseRequestThread)
+            {
+
+                ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
+                                                  UserRequest,
+                                                  UserMode,
+                                                  TRUE,
+                                                  NULL);
+            }
+            else
+            {
+
+                ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasEntries,
+                                                  UserRequest,
+                                                  UserMode,
+                                                  TRUE,
+                                                  NULL);
+            }
+
+            if( ntStatus != STATUS_SUCCESS)
+            {
+
+                ntStatus = STATUS_DEVICE_NOT_READY;
+
+                break;
+            }
+
+            //
+            // Grab the lock on the request pool
+            //
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
+                          &pCommSrvc->IrpPoolLock,
+                          PsGetCurrentThread());
+
+            AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
+                            TRUE);
+
+            if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
+            {
+
+                AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+
+                try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+            }
+
+            //
+            // If this is a dedicated flush thread only look for a flush request in the queue
+            //
+
+            if( bReleaseRequestThread)
+            {
+
+                pEntry = pCommSrvc->RequestPoolHead;
+
+                pPrevEntry = NULL;
+
+                while( pEntry != NULL)
+                {
+
+                    if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
+                    {
+
+                        if( pPrevEntry == NULL)
+                        {
+
+                            pCommSrvc->RequestPoolHead = pEntry->fLink;
+
+                            if( pCommSrvc->RequestPoolHead == NULL)
+                            {
+
+                                pCommSrvc->RequestPoolTail = NULL;
+                            }
+                        }
+                        else
+                        {
+
+                            pPrevEntry->fLink = pEntry->fLink;
+
+                            if( pPrevEntry->fLink == NULL)
+                            {
+
+                                pCommSrvc->RequestPoolTail = pPrevEntry;
+                            }
+                        }
+
+                        break;
+                    }
+
+                    pPrevEntry = pEntry;
+
+                    pEntry = pEntry->fLink;
+                }
+
+                if( pCommSrvc->RequestPoolHead == NULL)
+                {
+
+                    KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
+                }
+
+                if( pEntry == NULL)
+                {
+
+                    KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
+                }
+
+                //
+                // And release the request pool lock
+                //
+
+                AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+            }
+            else
+            {
+
+                pEntry = pCommSrvc->RequestPoolHead;
+
+                if( pEntry != NULL)
+                {
+
+                    pCommSrvc->RequestPoolHead = pEntry->fLink;
+
+                    pEntry->bLink = NULL;
+
+                    if( pCommSrvc->RequestPoolHead == NULL)
+                    {
+
+                        pCommSrvc->RequestPoolTail = NULL;
+                    }
+                }
+                else
+                {
+
+                    KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
+                }
+
+                //
+                // And release the request pool lock
+                //
+
+                AFSReleaseResource( &pCommSrvc->IrpPoolLock);
+            }
+
+            //
+            // Insert the entry into the result pool, if we have one
+            //
+
+            if( pEntry != NULL)
+            {
+
+                //
+                // Move the request data into the passed in buffer
+                //
+
+                ASSERT( sizeof( AFSCommRequest) +
+                                    pEntry->FileName.Length +
+                                    pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
+
+                RtlCopyMemory( &pRequest->AuthGroup,
+                               &pEntry->AuthGroup,
+                               sizeof( GUID));
+
+                pRequest->FileId = pEntry->FileId;
+
+                pRequest->RequestType = pEntry->RequestType;
+
+                pRequest->RequestIndex = pEntry->RequestIndex;
+
+                pRequest->RequestFlags = pEntry->RequestFlags;
+
+                pRequest->NameLength = pEntry->FileName.Length;
+
+                pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
+
+                if( pRequest->NameLength > 0)
+                {
+
+                    RtlCopyMemory( pRequest->Name,
+                                   pEntry->FileName.Buffer,
+                                   pRequest->NameLength);
+                }
+
+                pRequest->DataOffset = 0;
+
+                pRequest->DataLength = pEntry->DataLength;
+
+                if( pRequest->DataLength > 0)
+                {
+
+                    pRequest->DataOffset = pEntry->FileName.Length;
+
+                    RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
+                                   pEntry->Data,
+                                   pRequest->DataLength);
+                }
+
+                pRequest->ResultBufferLength = 0;
+
+                if( pEntry->ResultBufferLength != NULL)
+                {
+
+                    pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
+                }
+
+                Irp->IoStatus.Information = sizeof( AFSCommRequest) +
+                                                        pEntry->FileName.Length +
+                                                        pEntry->DataLength;
+
+                //
+                // If this is a synchronous request then move the request into the
+                // result pool
+                //
+
+                if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
+                {
+
+                    pEntry->fLink = NULL;
+                    pEntry->bLink = NULL;
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
+                                  &pCommSrvc->ResultPoolLock,
+                                  PsGetCurrentThread());
+
+                    AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
+                                    TRUE);
+
+                    if( pCommSrvc->ResultPoolHead == NULL)
+                    {
+
+                        pCommSrvc->ResultPoolHead = pEntry;
+                    }
+                    else
+                    {
+
+                        pCommSrvc->ResultPoolTail->fLink = pEntry;
+
+                        pEntry->bLink = pCommSrvc->ResultPoolTail;
+                    }
+
+                    pCommSrvc->ResultPoolTail = pEntry;
+
+                    AFSReleaseResource( &pCommSrvc->ResultPoolLock);
+                }
+                else
+                {
+
+                    //
+                    // Free up the pool entry
+                    //
+
+                    ExFreePool( pEntry);
+                }
+
+                break;
+            }
+        }
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSProcessIrpResult( IN PIRP Irp)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    IO_STACK_LOCATION  *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSCommSrvcCB      *pCommSrvc = NULL;
+    AFSPoolEntry       *pCurrentEntry = NULL;
+    AFSCommResult      *pResult = NULL;
+    ULONG               ulCopyLen = 0;
+
+    __Enter
+    {
+
+        pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
+
+        //
+        // Get the request for the incoming result
+        //
+
+        pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
+
+        if( pResult == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // Go look for our entry
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
+                      &pCommSrvc->ResultPoolLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
+                          TRUE);
+
+        pCurrentEntry = pCommSrvc->ResultPoolHead;
+
+        while( pCurrentEntry != NULL)
+        {
+
+            if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
+            {
+
+                //
+                // Found the entry so remove it from the queue
+                //
+
+                if( pCurrentEntry->bLink == NULL)
+                {
+
+                    //
+                    // At the head of the list
+                    //
+
+                    pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
+
+                    if( pCommSrvc->ResultPoolHead != NULL)
+                    {
+
+                        pCommSrvc->ResultPoolHead->bLink = NULL;
+                    }
+                }
+                else
+                {
+
+                    pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
+                }
+
+                if( pCurrentEntry->fLink == NULL)
+                {
+
+                    pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
+
+                    if( pCommSrvc->ResultPoolTail != NULL)
+                    {
+
+                        pCommSrvc->ResultPoolTail->fLink = NULL;
+                    }
+                }
+                else
+                {
+
+                    pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
+                }
+
+                break;
+            }
+
+            pCurrentEntry = pCurrentEntry->fLink;
+        }
+
+        AFSReleaseResource( &pCommSrvc->ResultPoolLock);
+
+        if( pCurrentEntry == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+        }
+
+        //
+        // OK, move in the result information
+        //
+
+        pCurrentEntry->ResultStatus = pResult->ResultStatus;
+
+        if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
+              pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
+            pCurrentEntry->ResultBufferLength != NULL &&
+            pCurrentEntry->ResultBuffer != NULL)
+        {
+
+            ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
+
+            ulCopyLen = pResult->ResultBufferLength;
+
+            if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
+            {
+                ulCopyLen = *(pCurrentEntry->ResultBufferLength);
+            }
+
+            *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
+
+            if( pResult->ResultBufferLength > 0)
+            {
+
+                RtlCopyMemory( pCurrentEntry->ResultBuffer,
+                               pResult->ResultData,
+                               ulCopyLen);
+            }
+        }
+
+        KeSetEvent( &pCurrentEntry->Event,
+                    0,
+                    FALSE);
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+        }
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp
new file mode 100644 (file)
index 0000000..2401b53
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * 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 DeviceObject,
+           IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = AFSControlDeviceCreate( Irp);
+
+            try_return( ntStatus);
+        }
+
+        ntStatus = AFSCommonCreate( DeviceObject,
+                                    Irp);
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSCreate\n");
+
+        ntStatus = STATUS_ACCESS_DENIED;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
+                 IN PIRP Irp)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    FILE_OBJECT        *pFileObject = NULL;
+    IO_STACK_LOCATION  *pIrpSp;
+    AFSDeviceExt       *pDeviceExt = NULL;
+    AFSDeviceExt       *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    GUID               *pAuthGroup = NULL;
+    UNICODE_STRING uniGUIDString;
+
+    __Enter
+    {
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+        pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+        pFileObject = pIrpSp->FileObject;
+
+        uniGUIDString.Buffer = NULL;
+        uniGUIDString.Length = 0;
+        uniGUIDString.MaximumLength = 0;
+
+        //
+        // Validate the process entry
+        //
+
+        pAuthGroup = AFSValidateProcessEntry();
+
+        if( pAuthGroup != NULL)
+        {
+
+            RtlStringFromGUID( *pAuthGroup,
+                               &uniGUIDString);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s (%08lX) Located AuthGroup %wZ after validation\n",
+                          __FUNCTION__,
+                          Irp,
+                          &uniGUIDString);
+
+        }
+        else
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s (%08lX) Failed to locate AuthGroup\n",
+                          __FUNCTION__,
+                          Irp);
+        }
+
+        //
+        // Root open?
+        //
+
+        if( pFileObject == NULL ||
+            pFileObject->FileName.Buffer == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCommonCreate (%08lX) Processing volume open request\n",
+                          Irp);
+
+            ntStatus = AFSOpenRedirector( Irp);
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDevExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        if ( pFileObject) {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s (%08lX) File \"%wZ\" AuthGroup '%wZ' ntStatus %08lX\n",
+                          __FUNCTION__,
+                          Irp,
+                          &pFileObject->FileName,
+                          &uniGUIDString,
+                          ntStatus);
+        }
+
+        if( uniGUIDString.Buffer != NULL)
+        {
+            RtlFreeUnicodeString( &uniGUIDString);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSControlDeviceCreate( IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        //
+        // For now, jsut let the open happen
+        //
+
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        AFSCompleteRequest( Irp, ntStatus);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSOpenRedirector( IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    FILE_OBJECT        *pFileObject = NULL;
+    IO_STACK_LOCATION  *pIrpSp;
+
+    __Enter
+    {
+
+        pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+        pFileObject = pIrpSp->FileObject;
+
+        //
+        // Return the open result for this file
+        //
+
+        Irp->IoStatus.Information = FILE_OPENED;
+
+        Irp->IoStatus.Status = ntStatus;
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSData.cpp b/src/WINNT/afsrdr/kernel/fs/AFSData.cpp
new file mode 100644 (file)
index 0000000..4fd9894
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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: AFSData.cpp
+//
+
+#define NO_EXTERN
+
+#include "AFSCommon.h"
+
+extern "C" {
+
+PDRIVER_OBJECT      AFSDriverObject = NULL;
+
+PDEVICE_OBJECT      AFSDeviceObject = NULL;
+
+PDEVICE_OBJECT      AFSRDRDeviceObject = NULL;
+
+FAST_IO_DISPATCH    AFSFastIoDispatch;
+
+UNICODE_STRING      AFSRegistryPath;
+
+ULONG               AFSDebugFlags = 0;
+
+ULONG               AFSTraceLevel = 0;
+
+ULONG               AFSTraceComponent = 0;
+
+HANDLE              AFSSysProcess = NULL;
+
+HANDLE              AFSMUPHandle = NULL;
+
+UNICODE_STRING      AFSServerName;
+
+UNICODE_STRING      AFSGlobalRootName;
+
+CACHE_MANAGER_CALLBACKS AFSCacheManagerCallbacks;
+
+//
+// Max Length IO (Mb)
+//
+ULONG               AFSMaxDirectIo = 0;
+
+//
+// Maximum dirtiness that a file can get
+//
+ULONG               AFSMaxDirtyFile = 0;
+
+//
+// Dbg log information
+//
+
+ERESOURCE           AFSDbgLogLock;
+
+ULONG               AFSDbgLogRemainingLength = 0;
+
+char               *AFSDbgCurrentBuffer = NULL;
+
+char               *AFSDbgBuffer = NULL;
+
+ULONG               AFSDbgLogCounter = 0;
+
+ULONG               AFSDbgBufferLength = 0;
+
+ULONG               AFSDbgLogFlags = 0;
+
+PAFSDumpTraceFiles  AFSDumpTraceFilesFnc = AFSDumpTraceFiles;
+
+UNICODE_STRING      AFSDumpFileLocation;
+
+KEVENT              AFSDumpFileEvent;
+
+UNICODE_STRING      AFSDumpFileName;
+
+void               *AFSDumpBuffer = NULL;
+
+ULONG               AFSDumpBufferLength = 0;
+
+//
+// Authentication group information
+//
+
+ULONG               AFSAuthGroupFlags = 0;
+
+GUID                AFSActiveAuthGroup;
+
+GUID                AFSNoPAGAuthGroup;
+
+PAFSSetInformationToken AFSSetInformationToken = NULL;
+
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp
new file mode 100644 (file)
index 0000000..31c2957
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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: AFSDevControl.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSDevControl
+//
+// Description:
+//
+//      This is the dipatch handler for the IRP_MJ_DEVICE_CONTROL requests.
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+NTSTATUS
+AFSDevControl( IN PDEVICE_OBJECT DeviceObject,
+               IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    IO_STACK_LOCATION *pIrpSp;
+
+    pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = AFSProcessControlRequest( Irp);
+
+            try_return( ntStatus);
+        }
+
+        ntStatus = AFSRDRDeviceControl( DeviceObject,
+                                        Irp);
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSDevControl\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp
new file mode 100644 (file)
index 0000000..c4e2ff6
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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: AFSDirControl.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSDirControl
+//
+// Description:
+//
+//      This function is the IRP_MJ_DIRECTORY_CONTROL dispatch handler
+//
+// Return:
+//
+//       A status is returned for the handling of this request
+//
+
+NTSTATUS
+AFSDirControl( IN PDEVICE_OBJECT DeviceObject,
+               IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    ULONG ulRequestType = 0;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSDirControl\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSEa.cpp b/src/WINNT/afsrdr/kernel/fs/AFSEa.cpp
new file mode 100644 (file)
index 0000000..adf9066
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * 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: AFSEa.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSQueryEA
+//
+// Description:
+//
+//      This function is the dipatch handler for the IRP_MJ_QUERY_EA request
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+NTSTATUS
+AFSQueryEA( IN PDEVICE_OBJECT DeviceObject,
+            IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSQueryEA\n");
+    }
+
+    return ntStatus;
+}
+
+//
+// Function: AFSSetEA
+//
+// Description:
+//
+//      This function is the dipatch handler for the IRP_MJ_SET_EA request
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+NTSTATUS
+AFSSetEA( IN PDEVICE_OBJECT DeviceObject,
+          IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSSetEA\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp
new file mode 100644 (file)
index 0000000..d2a4868
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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: AFSFSControl.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSFSControl( IN PDEVICE_OBJECT DeviceObject,
+              IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    IO_STACK_LOCATION *pIrpSp;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSFSControl\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp
new file mode 100644 (file)
index 0000000..9fe9436
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * 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: AFSFastIoSupport.cpp
+//
+
+#include "AFSCommon.h"
+
+BOOLEAN
+AFSFastIoCheckIfPossible( IN struct _FILE_OBJECT *FileObject,
+                          IN PLARGE_INTEGER FileOffset,
+                          IN ULONG Length,
+                          IN BOOLEAN Wait,
+                          IN ULONG LockKey,
+                          IN BOOLEAN CheckForReadOperation,
+                          OUT PIO_STATUS_BLOCK IoStatus,
+                          IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoRead( IN struct _FILE_OBJECT *FileObject,
+               IN PLARGE_INTEGER FileOffset,
+               IN ULONG Length,
+               IN BOOLEAN Wait,
+               IN ULONG LockKey,
+               OUT PVOID Buffer,
+               OUT PIO_STATUS_BLOCK IoStatus,
+               IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoWrite( IN struct _FILE_OBJECT *FileObject,
+                IN PLARGE_INTEGER FileOffset,
+                IN ULONG Length,
+                IN BOOLEAN Wait,
+                IN ULONG LockKey,
+                IN PVOID Buffer,
+                OUT PIO_STATUS_BLOCK IoStatus,
+                IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoQueryBasicInfo( IN struct _FILE_OBJECT *FileObject,
+                         IN BOOLEAN Wait,
+                         OUT PFILE_BASIC_INFORMATION Buffer,
+                         OUT PIO_STATUS_BLOCK IoStatus,
+                         IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoQueryStandardInfo( IN struct _FILE_OBJECT *FileObject,
+                            IN BOOLEAN Wait,
+                            OUT PFILE_STANDARD_INFORMATION Buffer,
+                            OUT PIO_STATUS_BLOCK IoStatus,
+                            IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoLock( IN struct _FILE_OBJECT *FileObject,
+               IN PLARGE_INTEGER FileOffset,
+               IN PLARGE_INTEGER Length,
+               IN PEPROCESS ProcessId,
+               IN ULONG Key,
+               IN BOOLEAN FailImmediately,
+               IN BOOLEAN ExclusiveLock,
+               OUT PIO_STATUS_BLOCK IoStatus,
+               IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoUnlockSingle( IN struct _FILE_OBJECT *FileObject,
+                       IN PLARGE_INTEGER FileOffset,
+                       IN PLARGE_INTEGER Length,
+                       IN PEPROCESS ProcessId,
+                       IN ULONG Key,
+                       OUT PIO_STATUS_BLOCK IoStatus,
+                       IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoUnlockAll( IN struct _FILE_OBJECT *FileObject,
+                    IN PEPROCESS ProcessId,
+                    OUT PIO_STATUS_BLOCK IoStatus,
+                    IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoUnlockAllByKey( IN struct _FILE_OBJECT *FileObject,
+                         IN PVOID ProcessId,
+                         IN ULONG Key,
+                         OUT PIO_STATUS_BLOCK IoStatus,
+                         IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoDevCtrl( IN struct _FILE_OBJECT *FileObject,
+                  IN BOOLEAN Wait,
+                  IN PVOID InputBuffer OPTIONAL,
+                  IN ULONG InputBufferLength,
+                  OUT PVOID OutputBuffer OPTIONAL,
+                  IN ULONG OutputBufferLength,
+                  IN ULONG IoControlCode,
+                  OUT PIO_STATUS_BLOCK IoStatus,
+                  IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+void
+AFSFastIoAcquireFile( IN struct _FILE_OBJECT *FileObject)
+{
+
+    AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext;
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSFastIoAcquireFile Acquiring Fcb lock %08lX EXCL %08lX\n",
+                  &pFcb->NPFcb->Resource,
+                  PsGetCurrentThread());
+
+    AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                    TRUE);
+
+    return;
+}
+
+void
+AFSFastIoReleaseFile( IN struct _FILE_OBJECT *FileObject)
+{
+
+    AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext;
+
+    if( ExIsResourceAcquiredExclusiveLite( &pFcb->NPFcb->Resource))
+    {
+
+        AFSReleaseResource( &pFcb->NPFcb->Resource);
+    }
+
+    return;
+}
+
+VOID
+AFSFastIoDetachDevice( IN struct _DEVICE_OBJECT *SourceDevice,
+                       IN struct _DEVICE_OBJECT *TargetDevice)
+{
+
+    return;
+}
+
+BOOLEAN
+AFSFastIoQueryNetworkOpenInfo( IN struct _FILE_OBJECT *FileObject,
+                               IN BOOLEAN Wait,
+                               OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer,
+                               OUT struct _IO_STATUS_BLOCK *IoStatus,
+                               IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoMdlRead( IN struct _FILE_OBJECT *FileObject,
+                  IN PLARGE_INTEGER FileOffset,
+                  IN ULONG Length,
+                  IN ULONG LockKey,
+                  OUT PMDL *MdlChain,
+                  OUT PIO_STATUS_BLOCK IoStatus,
+                  IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoMdlReadComplete( IN struct _FILE_OBJECT *FileObject,
+                          IN PMDL MdlChain,
+                          IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoPrepareMdlWrite( IN struct _FILE_OBJECT *FileObject,
+                          IN PLARGE_INTEGER FileOffset,
+                          IN ULONG Length,
+                          IN ULONG LockKey,
+                          OUT PMDL *MdlChain,
+                          OUT PIO_STATUS_BLOCK IoStatus,
+                          IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoMdlWriteComplete( IN struct _FILE_OBJECT *FileObject,
+                           IN PLARGE_INTEGER FileOffset,
+                           IN PMDL MdlChain,
+                           IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+NTSTATUS
+AFSFastIoAcquireForModWrite( IN struct _FILE_OBJECT *FileObject,
+                             IN PLARGE_INTEGER EndingOffset,
+                             OUT struct _ERESOURCE **ResourceToRelease,
+                             IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    NTSTATUS ntStatus = STATUS_FILE_LOCK_CONFLICT;
+    AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext;
+
+    __Enter
+    {
+
+        if( AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                            BooleanFlagOn( FileObject->Flags, FO_SYNCHRONOUS_IO)))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSFastIoAcquireForModWrite Acquired Fcb lock %08lX EXCL %08lX\n",
+                          &pFcb->NPFcb->Resource,
+                          PsGetCurrentThread());
+
+            ntStatus = STATUS_SUCCESS;
+
+            *ResourceToRelease = &pFcb->NPFcb->Resource;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSFastIoReleaseForModWrite( IN struct _FILE_OBJECT *FileObject,
+                             IN struct _ERESOURCE *ResourceToRelease,
+                             IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    AFSReleaseResource( ResourceToRelease);
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSFastIoAcquireForCCFlush( IN struct _FILE_OBJECT *FileObject,
+                            IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    NTSTATUS ntStatus = STATUS_FILE_LOCK_CONFLICT;
+    AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext;
+
+    if( !ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->Resource))
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSFastIoAcquireForCCFlush Acquiring Fcb lock %08lX EXCL %08lX\n",
+                      &pFcb->NPFcb->Resource,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                        TRUE);
+    }
+    else
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSFastIoAcquireForCCFlush Acquiring Fcb lock %08lX SHARED %08lX\n",
+                      &pFcb->NPFcb->Resource,
+                      PsGetCurrentThread());
+
+        AFSAcquireShared( &pFcb->NPFcb->Resource,
+                          TRUE);
+    }
+
+    ntStatus = STATUS_SUCCESS;
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSFastIoAcquireForCCFlush Acquiring Fcb PagingIo lock %08lX SHARED %08lX\n",
+                  &pFcb->NPFcb->PagingResource,
+                  PsGetCurrentThread());
+
+    AFSAcquireShared( &pFcb->NPFcb->PagingResource,
+                      TRUE);
+
+    //
+    // Set the TopLevelIrp field for this caller
+    //
+
+    if( IoGetTopLevelIrp() == NULL)
+    {
+
+        IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSFastIoReleaseForCCFlush( IN struct _FILE_OBJECT *FileObject,
+                            IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext;
+
+    if( IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
+    {
+
+        IoSetTopLevelIrp( NULL);
+    }
+
+    if( ExIsResourceAcquiredExclusiveLite( &pFcb->NPFcb->Resource) ||
+        ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->Resource))
+    {
+
+        AFSReleaseResource( &pFcb->NPFcb->Resource);
+    }
+    else
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_ERROR,
+                      "AFSFastIoReleaseForCCFlush Called for non-acquired main resource Fcb\n");
+    }
+
+    if( ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->PagingResource))
+    {
+
+        AFSReleaseResource( &pFcb->NPFcb->PagingResource);
+    }
+    else
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_ERROR,
+                      "AFSFastIoReleaseForCCFlush Called for non-acquired paging resource Fcb\n");
+    }
+
+    return ntStatus;
+}
+
+BOOLEAN
+AFSFastIoReadCompressed( IN struct _FILE_OBJECT *FileObject,
+                         IN PLARGE_INTEGER FileOffset,
+                         IN ULONG Length,
+                         IN ULONG LockKey,
+                         OUT PVOID Buffer,
+                         OUT PMDL *MdlChain,
+                         OUT PIO_STATUS_BLOCK IoStatus,
+                         OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
+                         IN ULONG CompressedDataInfoLength,
+                         IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoWriteCompressed( IN struct _FILE_OBJECT *FileObject,
+                          IN PLARGE_INTEGER FileOffset,
+                          IN ULONG Length,
+                          IN ULONG LockKey,
+                          IN PVOID Buffer,
+                          OUT PMDL *MdlChain,
+                          OUT PIO_STATUS_BLOCK IoStatus,
+                          IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo,
+                          IN ULONG CompressedDataInfoLength,
+                          IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoMdlReadCompleteCompressed( IN struct _FILE_OBJECT *FileObject,
+                                    IN PMDL MdlChain,
+                                    IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoMdlWriteCompleteCompressed( IN struct _FILE_OBJECT *FileObject,
+                                     IN PLARGE_INTEGER FileOffset,
+                                     IN PMDL MdlChain,
+                                     IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSFastIoQueryOpen( IN struct _IRP *Irp,
+                    OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
+                    IN struct _DEVICE_OBJECT *DeviceObject)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    return bStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp
new file mode 100644 (file)
index 0000000..74bbad3
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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: AFSFileInfo.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSQueryFileInfo
+//
+// Description:
+//
+//      This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+NTSTATUS
+AFSQueryFileInfo( IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        if( pIrpSp->FileObject->FsContext == NULL)
+        {
+
+            //
+            // Root open
+            //
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSQueryFileInfo\n");
+
+        ntStatus = STATUS_UNSUCCESSFUL;
+    }
+
+    return ntStatus;
+}
+
+//
+// Function: AFSSetFileInfo
+//
+// Description:
+//
+//      This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+NTSTATUS
+AFSSetFileInfo( IN PDEVICE_OBJECT DeviceObject,
+                IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __try
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        if( pIrpSp->FileObject->FsContext == NULL)
+        {
+
+            //
+            // Root open
+            //
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSSetFileInfo\n");
+
+        ntStatus = STATUS_UNSUCCESSFUL;
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp
new file mode 100644 (file)
index 0000000..aecc04c
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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: AFSFlushBuffers.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSFlushBuffers( IN PDEVICE_OBJECT DeviceObject,
+                 IN PIRP Irp)
+{
+
+    NTSTATUS      ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __Enter
+    {
+
+        if( DeviceObject == AFSDeviceObject)
+        {
+
+            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+            AFSCompleteRequest( Irp,
+                                ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check the state of the library
+        //
+
+        ntStatus = AFSCheckLibraryState( Irp);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            ntStatus == STATUS_PENDING)
+        {
+
+            if( ntStatus != STATUS_PENDING)
+            {
+                AFSCompleteRequest( Irp, ntStatus);
+            }
+
+            try_return( ntStatus);
+        }
+
+        IoSkipCurrentIrpStackLocation( Irp);
+
+        ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject,
+                                 Irp);
+
+        //
+        // Indicate the library is done with the request
+        //
+
+        AFSClearLibraryRequest();
+
+try_exit:
+
+        NOTHING;
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp b/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp
new file mode 100644 (file)
index 0000000..bd01b56
--- /dev/null
@@ -0,0 +1,2050 @@
+/*
+ * 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: AFSGeneric.cpp
+//
+
+#include "AFSCommon.h"
+
+//
+// Function: AFSExceptionFilter
+//
+// Description:
+//
+//      This function is the exception handler
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+ULONG
+AFSExceptionFilter( IN ULONG Code,
+                    IN PEXCEPTION_POINTERS ExceptPtrs)
+{
+
+    PEXCEPTION_RECORD ExceptRec;
+    PCONTEXT Context;
+
+    __try
+    {
+
+        ExceptRec = ExceptPtrs->ExceptionRecord;
+
+        Context = ExceptPtrs->ContextRecord;
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "AFSExceptionFilter (Framework) - EXR %p CXR %p Code %08lX Address %p\n",
+                      ExceptRec,
+                      Context,
+                      ExceptRec->ExceptionCode,
+                      ExceptRec->ExceptionAddress);
+
+        DbgPrint("**** Exception Caught in AFS Redirector ****\n");
+
+        DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
+        DbgPrint("\n\t.exr %p ;  .cxr %p\n\n", ExceptRec, Context);
+
+        DbgPrint("**** Exception Complete from AFS Redirector ****\n");
+
+        if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
+        {
+
+            KeBugCheck( (ULONG)-2);
+        }
+        else
+        {
+
+            AFSBreakPoint();
+        }
+    }
+    __except( EXCEPTION_EXECUTE_HANDLER)
+    {
+
+        NOTHING;
+    }
+
+    return EXCEPTION_EXECUTE_HANDLER;
+}
+
+//
+// Function: AFSAcquireExcl()
+//
+// Purpose: Called to acquire a resource exclusive with optional wait
+//
+// Parameters:
+//                PERESOURCE Resource - Resource to acquire
+//                BOOLEAN Wait - Whether to block
+//
+// Return:
+//                BOOLEAN - Whether the mask was acquired
+//
+
+BOOLEAN
+AFSAcquireExcl( IN PERESOURCE Resource,
+                IN BOOLEAN wait)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    //
+    // Normal kernel APCs must be disabled before calling
+    // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
+    //
+
+    KeEnterCriticalRegion();
+
+    bStatus = ExAcquireResourceExclusiveLite( Resource,
+                                              wait);
+
+    if( !bStatus)
+    {
+
+        KeLeaveCriticalRegion();
+    }
+
+    return bStatus;
+}
+
+BOOLEAN
+AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
+                                 IN BOOLEAN Wait)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    KeEnterCriticalRegion();
+
+    bStatus = ExAcquireSharedStarveExclusive( Resource,
+                                              Wait);
+
+    if( !bStatus)
+    {
+
+        KeLeaveCriticalRegion();
+    }
+
+    return bStatus;
+}
+
+//
+// Function: AFSAcquireShared()
+//
+// Purpose: Called to acquire a resource shared with optional wait
+//
+// Parameters:
+//                PERESOURCE Resource - Resource to acquire
+//                BOOLEAN Wait - Whether to block
+//
+// Return:
+//                BOOLEAN - Whether the mask was acquired
+//
+
+BOOLEAN
+AFSAcquireShared( IN PERESOURCE Resource,
+                  IN BOOLEAN wait)
+{
+
+    BOOLEAN bStatus = FALSE;
+
+    KeEnterCriticalRegion();
+
+    bStatus = ExAcquireResourceSharedLite( Resource,
+                                           wait);
+
+    if( !bStatus)
+    {
+
+        KeLeaveCriticalRegion();
+    }
+
+    return bStatus;
+}
+
+//
+// Function: AFSReleaseResource()
+//
+// Purpose: Called to release a resource
+//
+// Parameters:
+//                PERESOURCE Resource - Resource to release
+//
+// Return:
+//                None
+//
+
+void
+AFSReleaseResource( IN PERESOURCE Resource)
+{
+
+    if( Resource != &AFSDbgLogLock)
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
+                      Resource,
+                      PsGetCurrentThread());
+    }
+
+    ExReleaseResourceLite( Resource);
+
+    KeLeaveCriticalRegion();
+
+    return;
+}
+
+void
+AFSConvertToShared( IN PERESOURCE Resource)
+{
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
+                  Resource,
+                  PsGetCurrentThread());
+
+    ExConvertExclusiveToSharedLite( Resource);
+
+    return;
+}
+
+//
+// Function: AFSCompleteRequest
+//
+// Description:
+//
+//      This function completes irps
+//
+// Return:
+//
+//      A status is returned for the function
+//
+
+void
+AFSCompleteRequest( IN PIRP Irp,
+                    IN ULONG Status)
+{
+
+    Irp->IoStatus.Status = Status;
+
+    IoCompleteRequest( Irp,
+                       IO_NO_INCREMENT);
+
+    return;
+}
+
+NTSTATUS
+AFSReadRegistry( IN PUNICODE_STRING RegistryPath)
+{
+
+    NTSTATUS ntStatus        = STATUS_SUCCESS;
+    ULONG Default            = 0;
+    UNICODE_STRING paramPath;
+    ULONG Value                = 0;
+    RTL_QUERY_REGISTRY_TABLE paramTable[2];
+    UNICODE_STRING defaultUnicodeName;
+    WCHAR SubKeyString[]    = L"\\Parameters";
+
+    //
+    // Setup the paramPath buffer.
+    //
+
+    paramPath.MaximumLength = RegistryPath->Length + sizeof( SubKeyString);
+    paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
+                                                        paramPath.MaximumLength,
+                                                        AFS_GENERIC_MEMORY_15_TAG);
+
+    RtlInitUnicodeString( &defaultUnicodeName,
+                          L"NO NAME");
+
+    //
+    // If it exists, setup the path.
+    //
+
+    if( paramPath.Buffer != NULL)
+    {
+
+        //
+        // Move in the paths
+        //
+
+        RtlCopyMemory( &paramPath.Buffer[ 0],
+                       &RegistryPath->Buffer[ 0],
+                       RegistryPath->Length);
+
+        RtlCopyMemory( &paramPath.Buffer[ RegistryPath->Length / 2],
+                       SubKeyString,
+                       sizeof( SubKeyString));
+
+        paramPath.Length = paramPath.MaximumLength;
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        Value = 0;
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_DEBUG_FLAGS;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            AFSDebugFlags = Value;
+        }
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        Value = 0;
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_TRACE_SUBSYSTEM;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            AFSTraceComponent = Value;
+        }
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        Value = 0;
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_TRACE_BUFFER_LENGTH;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG);
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus) &&
+            Value > 0)
+        {
+
+            AFSDbgBufferLength = Value;
+
+            //
+            // Let's limit things a bit ...
+            //
+
+            if( AFSDbgBufferLength > 10240)
+            {
+
+                AFSDbgBufferLength = 1024;
+            }
+        }
+        else
+        {
+
+            AFSDbgBufferLength = 0;
+        }
+
+        //
+        // Make it bytes
+        //
+
+        AFSDbgBufferLength *= 1024;
+
+        //
+        // Now get ready to set up for MaxServerDirty
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_MAX_DIRTY;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            AFSMaxDirtyFile = Value;
+        }
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        Value = 0;
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_TRACE_LEVEL;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            AFSTraceLevel = Value;
+        }
+
+        //
+        // MaxIO
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_MAX_IO;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            AFSMaxDirectIo = Value;
+        }
+
+        //
+        // Now set up for ShutdownStatus query
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_SHUTDOWN_STATUS;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            Value != (ULONG)-1)
+        {
+
+            SetFlag( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN);
+        }
+
+        //
+        // Now set up for RequireCleanShutdown query
+        //
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_REQUIRE_CLEAN_SHUTDOWN;
+        paramTable[0].EntryContext = &Value;
+
+        paramTable[0].DefaultType = REG_DWORD;
+        paramTable[0].DefaultData = &Default;
+        paramTable[0].DefaultLength = sizeof (ULONG) ;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if( !NT_SUCCESS( ntStatus) ||
+            Value != 0L)
+        {
+
+            SetFlag( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN);
+        }
+
+        //
+        // Free up the buffer
+        //
+
+        ExFreePool( paramPath.Buffer);
+
+        ntStatus = STATUS_SUCCESS;
+    }
+    else
+    {
+        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSUpdateRegistryParameter( IN PUNICODE_STRING ValueName,
+                            IN ULONG ValueType,
+                            IN void *ValueData,
+                            IN ULONG ValueDataLength)
+{
+
+    NTSTATUS ntStatus        = STATUS_SUCCESS;
+    UNICODE_STRING paramPath, uniParamKey;
+    HANDLE hParameters = 0;
+    ULONG ulDisposition = 0;
+    OBJECT_ATTRIBUTES stObjectAttributes;
+
+    __Enter
+    {
+
+        RtlInitUnicodeString( &uniParamKey,
+                              L"\\Parameters");
+
+        //
+        // Setup the paramPath buffer.
+        //
+
+        paramPath.MaximumLength = AFSRegistryPath.Length + uniParamKey.Length;
+        paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
+                                                            paramPath.MaximumLength,
+                                                            AFS_GENERIC_MEMORY_16_TAG);
+
+        if( paramPath.Buffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Move in the paths
+        //
+
+        RtlCopyMemory( paramPath.Buffer,
+                       AFSRegistryPath.Buffer,
+                       AFSRegistryPath.Length);
+
+        paramPath.Length = AFSRegistryPath.Length;
+
+        RtlCopyMemory( &paramPath.Buffer[ paramPath.Length / 2],
+                       uniParamKey.Buffer,
+                       uniParamKey.Length);
+
+        paramPath.Length += uniParamKey.Length;
+
+        InitializeObjectAttributes( &stObjectAttributes,
+                                    &paramPath,
+                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                                    NULL,
+                                    NULL);
+
+        ntStatus = ZwOpenKey( &hParameters,
+                              KEY_ALL_ACCESS,
+                              &stObjectAttributes);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Set the value
+        //
+
+        ntStatus = ZwSetValueKey( hParameters,
+                                  ValueName,
+                                  0,
+                                  ValueType,
+                                  ValueData,
+                                  ValueDataLength);
+
+        ZwClose( hParameters);
+
+try_exit:
+
+        if( paramPath.Buffer != NULL)
+        {
+
+            //
+            // Free up the buffer
+            //
+
+            ExFreePool( paramPath.Buffer);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSInitializeControlDevice()
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSProcessCB *pProcessCB = NULL;
+
+    __Enter
+    {
+
+        //
+        // Initialize the comm pool resources
+        //
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolLock);
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.ResultPoolLock);
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.ExtentReleaseResource);
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.SysName32ListLock);
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.SysName64ListLock);
+
+        //
+        // And the events
+        //
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolHasEntries,
+                           NotificationEvent,
+                           FALSE);
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolHasReleaseEntries,
+                           NotificationEvent,
+                           FALSE);
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.ExtentReleaseEvent,
+                           NotificationEvent,
+                           FALSE);
+
+        pDeviceExt->Specific.Control.ExtentReleaseSequence = 0;
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
+                           NotificationEvent,
+                           TRUE);
+
+        //
+        // Library support information
+        //
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.LoadLibraryEvent,
+                           SynchronizationEvent,
+                           TRUE);
+
+        //
+        // Initialize the library queued as cancelled
+        //
+
+        pDeviceExt->Specific.Control.LibraryState = AFS_LIBRARY_QUEUE_CANCELLED;
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.LibraryStateLock);
+
+        pDeviceExt->Specific.Control.InflightLibraryRequests = 0;
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.InflightLibraryEvent,
+                           NotificationEvent,
+                           FALSE);
+
+        pDeviceExt->Specific.Control.ExtentCount = 0;
+        pDeviceExt->Specific.Control.ExtentsHeldLength = 0;
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.ExtentsHeldEvent,
+                           NotificationEvent,
+                           TRUE);
+
+        pDeviceExt->Specific.Control.OutstandingServiceRequestCount = 0;
+
+        KeInitializeEvent( &pDeviceExt->Specific.Control.OutstandingServiceRequestEvent,
+                           NotificationEvent,
+                           TRUE);
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.LibraryQueueLock);
+
+        pDeviceExt->Specific.Control.LibraryQueueHead = NULL;
+
+        pDeviceExt->Specific.Control.LibraryQueueTail = NULL;
+
+        //
+        // Set the initial state of the irp pool
+        //
+
+        pDeviceExt->Specific.Control.CommServiceCB.IrpPoolControlFlag = POOL_INACTIVE;
+
+        //
+        // Initialize our process and sid tree information
+        //
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.ProcessTreeLock);
+
+        pDeviceExt->Specific.Control.ProcessTree.TreeLock = &pDeviceExt->Specific.Control.ProcessTreeLock;
+
+        pDeviceExt->Specific.Control.ProcessTree.TreeHead = NULL;
+
+        ExInitializeResourceLite( &pDeviceExt->Specific.Control.AuthGroupTreeLock);
+
+        pDeviceExt->Specific.Control.AuthGroupTree.TreeLock = &pDeviceExt->Specific.Control.AuthGroupTreeLock;
+
+        pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = NULL;
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSRemoveControlDevice()
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSProcessCB *pProcessCB = NULL;
+
+    __Enter
+    {
+
+        //
+        // Initialize the comm pool resources
+        //
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.IrpPoolLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.CommServiceCB.ResultPoolLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.ExtentReleaseResource);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.SysName32ListLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.SysName64ListLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.ProcessTreeLock);
+
+        if( pDeviceExt->Specific.Control.ProcessTree.TreeHead != NULL)
+        {
+            ExFreePool( pDeviceExt->Specific.Control.ProcessTree.TreeHead);
+        }
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.AuthGroupTreeLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.LibraryStateLock);
+
+        ExDeleteResourceLite( &pDeviceExt->Specific.Control.LibraryQueueLock);
+    }
+
+    return ntStatus;
+}
+
+void
+AFSInitServerStrings()
+{
+
+    UNICODE_STRING uniFullName;
+    WCHAR wchBuffer[ 50];
+
+    //
+    // Add the server name into the list of resources
+    //
+
+    uniFullName.Length = (2 * sizeof( WCHAR)) + AFSServerName.Length;
+    uniFullName.MaximumLength = uniFullName.Length + sizeof( WCHAR);
+
+    uniFullName.Buffer = wchBuffer;
+
+    wchBuffer[ 0] = L'\\';
+    wchBuffer[ 1] = L'\\';
+
+    RtlCopyMemory( &wchBuffer[ 2],
+                   AFSServerName.Buffer,
+                   AFSServerName.Length);
+
+    AFSAddConnectionEx( &uniFullName,
+                        RESOURCEDISPLAYTYPE_SERVER,
+                        0);
+
+    //
+    // Add in the global share name
+    //
+
+    wchBuffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
+
+    uniFullName.Length += sizeof( WCHAR);
+
+    RtlCopyMemory( &wchBuffer[ uniFullName.Length/sizeof( WCHAR)],
+                   AFSGlobalRootName.Buffer,
+                   AFSGlobalRootName.Length);
+
+    uniFullName.Length += AFSGlobalRootName.Length;
+
+    AFSAddConnectionEx( &uniFullName,
+                        RESOURCEDISPLAYTYPE_SHARE,
+                        AFS_CONNECTION_FLAG_GLOBAL_SHARE);
+
+    return;
+}
+
+NTSTATUS
+AFSReadServerName()
+{
+
+    NTSTATUS ntStatus        = STATUS_SUCCESS;
+    ULONG Default            = 0;
+    UNICODE_STRING paramPath;
+    RTL_QUERY_REGISTRY_TABLE paramTable[2];
+
+    __Enter
+    {
+
+        //
+        // Setup the paramPath buffer.
+        //
+
+        paramPath.MaximumLength = PAGE_SIZE;
+        paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
+                                                            paramPath.MaximumLength,
+                                                            AFS_GENERIC_MEMORY_17_TAG);
+
+        //
+        // If it exists, setup the path.
+        //
+
+        if( paramPath.Buffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Move in the paths
+        //
+
+        RtlZeroMemory( paramPath.Buffer,
+                       paramPath.MaximumLength);
+
+        RtlCopyMemory( &paramPath.Buffer[ 0],
+                       L"\\TransarcAFSDaemon\\Parameters",
+                       58);
+
+        paramPath.Length = 58;
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        AFSServerName.Length = 0;
+        AFSServerName.MaximumLength = 0;
+        AFSServerName.Buffer = NULL;
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_NETBIOS_NAME;
+        paramTable[0].EntryContext = &AFSServerName;
+
+        paramTable[0].DefaultType = REG_NONE;
+        paramTable[0].DefaultData = NULL;
+        paramTable[0].DefaultLength = 0;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_SERVICES,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        //
+        // Free up the buffer
+        //
+
+        ExFreePool( paramPath.Buffer);
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            RtlInitUnicodeString( &AFSServerName,
+                                  L"AFS");
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo,
+                          IN ULONG SysNameInfoBufferLength)
+{
+
+    NTSTATUS         ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSSysNameCB    *pSysName = NULL;
+    ERESOURCE       *pSysNameLock = NULL;
+    AFSSysNameCB   **pSysNameListHead = NULL, **pSysNameListTail = NULL;
+    ULONG            ulIndex = 0;
+    __Enter
+    {
+
+        //
+        // Depending on the architecture of the information, set up the lsit
+        //
+
+        if( SysNameInfo->Architecture == AFS_SYSNAME_ARCH_32BIT)
+        {
+
+            pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
+
+            pSysNameListHead = &pControlDevExt->Specific.Control.SysName32ListHead;
+
+            pSysNameListTail = &pControlDevExt->Specific.Control.SysName32ListTail;
+        }
+        else
+        {
+
+#if defined(_WIN64)
+
+            pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
+
+            pSysNameListHead = &pControlDevExt->Specific.Control.SysName64ListHead;
+
+            pSysNameListTail = &pControlDevExt->Specific.Control.SysName64ListTail;
+
+#else
+
+            try_return( ntStatus = STATUS_INVALID_PARAMETER);
+#endif
+        }
+
+        //
+        // Process the request
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSSetSysNameInformation Acquiring SysName lock %08lX EXCL %08lX\n",
+                      pSysNameLock,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( pSysNameLock,
+                        TRUE);
+
+        //
+        // If we already have a list, then tear it down
+        //
+
+        if( *pSysNameListHead != NULL)
+        {
+
+            AFSResetSysNameList( *pSysNameListHead);
+
+            *pSysNameListHead = NULL;
+        }
+
+        //
+        // Loop through the entries adding in a node for each
+        //
+
+        while( ulIndex < SysNameInfo->NumberOfNames)
+        {
+
+            pSysName = (AFSSysNameCB *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                 sizeof( AFSSysNameCB) +
+                                                                 SysNameInfo->SysNames[ ulIndex].Length +
+                                                                 sizeof( WCHAR),
+                                                                 AFS_SYS_NAME_NODE_TAG);
+
+            if( pSysName == NULL)
+            {
+
+                //
+                // Reset the current list
+                //
+
+                AFSResetSysNameList( *pSysNameListHead);
+
+                *pSysNameListHead = NULL;
+
+                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            }
+
+            RtlZeroMemory( pSysName,
+                           sizeof( AFSSysNameCB) +
+                                   SysNameInfo->SysNames[ ulIndex].Length +
+                                   sizeof( WCHAR));
+
+            pSysName->SysName.Length = (USHORT)SysNameInfo->SysNames[ ulIndex].Length;
+
+            pSysName->SysName.MaximumLength = pSysName->SysName.Length + sizeof( WCHAR);
+
+            pSysName->SysName.Buffer = (WCHAR *)((char *)pSysName + sizeof( AFSSysNameCB));
+
+            RtlCopyMemory( pSysName->SysName.Buffer,
+                           SysNameInfo->SysNames[ ulIndex].String,
+                           pSysName->SysName.Length);
+
+            if( *pSysNameListHead == NULL)
+            {
+
+                *pSysNameListHead = pSysName;
+            }
+            else
+            {
+
+                (*pSysNameListTail)->fLink = pSysName;
+            }
+
+            *pSysNameListTail = pSysName;
+
+            ulIndex++;
+        }
+
+try_exit:
+
+        AFSReleaseResource( pSysNameLock);
+    }
+
+    return ntStatus;
+}
+
+void
+AFSResetSysNameList( IN AFSSysNameCB *SysNameList)
+{
+
+    AFSSysNameCB *pNextEntry = NULL, *pCurrentEntry = SysNameList;
+
+    while( pCurrentEntry != NULL)
+    {
+
+        pNextEntry = pCurrentEntry->fLink;
+
+        ExFreePool( pCurrentEntry);
+
+        pCurrentEntry = pNextEntry;
+    }
+
+    return;
+}
+
+NTSTATUS
+AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp)
+{
+
+    NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+    PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    AFSCompleteRequest( Irp,
+                        ntStatus);
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSSendDeviceIoControl( IN DEVICE_OBJECT *TargetDeviceObject,
+                        IN ULONG IOControl,
+                        IN void *InputBuffer,
+                        IN ULONG InputBufferLength,
+                        IN OUT void *OutputBuffer,
+                        IN ULONG OutputBufferLength,
+                        OUT ULONG *ResultLength)
+{
+
+    NTSTATUS            ntStatus = STATUS_SUCCESS;
+    PIRP                pIrp = NULL;
+    KEVENT              kEvent;
+    PIO_STACK_LOCATION  pIoStackLocation = NULL;
+
+    __Enter
+    {
+
+        //
+        // Initialize the event
+        //
+
+        KeInitializeEvent( &kEvent,
+                           SynchronizationEvent,
+                           FALSE);
+
+        //
+        // Allocate an irp for this request.  This could also come from a
+        // private pool, for instance.
+        //
+
+        pIrp = IoAllocateIrp( TargetDeviceObject->StackSize,
+                              FALSE);
+
+        if( pIrp == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Build the IRP's main body
+        //
+
+        pIrp->RequestorMode = KernelMode;
+
+        //
+        // Set up the I/O stack location.
+        //
+
+        pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
+        pIoStackLocation->MajorFunction = IRP_MJ_DEVICE_CONTROL;
+        pIoStackLocation->DeviceObject = TargetDeviceObject;
+
+        pIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOControl;
+
+        pIrp->AssociatedIrp.SystemBuffer = (void *)InputBuffer;
+        pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
+
+        //
+        // Set the completion routine.
+        //
+
+        IoSetCompletionRoutine( pIrp,
+                                AFSIrpComplete,
+                                &kEvent,
+                                TRUE,
+                                TRUE,
+                                TRUE);
+
+        //
+        // Send it to the FSD
+        //
+
+        ntStatus = IoCallDriver( TargetDeviceObject,
+                                 pIrp);
+
+        if( NT_SUCCESS( ntStatus))
+        {
+
+            //
+            // Wait for the I/O
+            //
+
+            ntStatus = KeWaitForSingleObject( &kEvent,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              0);
+
+            if( NT_SUCCESS( ntStatus))
+            {
+
+                ntStatus = pIrp->IoStatus.Status;
+
+                if( ResultLength != NULL)
+                {
+                    *ResultLength = (ULONG)pIrp->IoStatus.Information;
+                }
+            }
+        }
+
+try_exit:
+
+        if( pIrp != NULL)
+        {
+
+            if( pIrp->MdlAddress != NULL)
+            {
+
+                if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
+                {
+
+                    MmUnlockPages( pIrp->MdlAddress);
+                }
+
+                IoFreeMdl( pIrp->MdlAddress);
+            }
+
+            pIrp->MdlAddress = NULL;
+
+            //
+            // Free the Irp
+            //
+
+            IoFreeIrp( pIrp);
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
+                IN PIRP           Irp,
+                IN PVOID          Context)
+{
+
+    KEVENT *pEvent = (KEVENT *)Context;
+
+    KeSetEvent( pEvent,
+                0,
+                FALSE);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+void *
+AFSExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
+                          IN SIZE_T  NumberOfBytes,
+                          IN ULONG  Tag)
+{
+
+    void *pBuffer = NULL;
+
+    pBuffer = ExAllocatePoolWithTag( PoolType,
+                                     NumberOfBytes,
+                                     Tag);
+
+    if( pBuffer == NULL)
+    {
+
+        if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
+        {
+
+            KeBugCheck( (ULONG)-2);
+        }
+        else
+        {
+
+            AFSDbgLogMsg( 0,
+                          0,
+                          "AFSExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
+                          PoolType,
+                          NumberOfBytes,
+                          Tag,
+                          PsGetCurrentThread());
+
+            switch ( Tag ) {
+
+            case AFS_GENERIC_MEMORY_21_TAG:
+            case AFS_GENERIC_MEMORY_22_TAG:
+                // AFSDumpTraceFiles -- do nothing;
+                break;
+
+            default:
+                AFSBreakPoint();
+            }
+        }
+    }
+
+    return pBuffer;
+}
+
+void
+AFSExFreePool( IN void *Buffer)
+{
+
+    ExFreePool( Buffer);
+
+    return;
+}
+
+NTSTATUS
+AFSShutdownRedirector()
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    LARGE_INTEGER liTimeout;
+
+    __Enter
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Shutting down redirector Extent count %08lX Request count %08lX\n",
+                                __FUNCTION__,
+                                pControlDevExt->Specific.Control.ExtentCount,
+                                pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
+
+        //
+        // Set the shutdown flag so the worker is more agressive in tearing down extents
+        //
+
+        SetFlag( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
+
+        //
+        // Wait on any outstanding service requests
+        //
+
+        liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
+
+        ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          &liTimeout);
+
+        if( ntStatus == STATUS_TIMEOUT)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                              "AFSShutdownRedirector Failed to complete all service requests Remaining count %08lX\n",
+                                                    pControlDevExt->Specific.Control.OutstandingServiceRequestCount);
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        AFSProcessQueuedResults( TRUE);
+
+        //
+        // Wait for all extents to be released
+        //
+
+        liTimeout.QuadPart = -(30 *AFS_ONE_SECOND);
+
+        ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          &liTimeout);
+
+        if( ntStatus == STATUS_TIMEOUT)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_WARNING,
+                              "AFSShutdownRedirector Failed to purge all extents Remaining count %08lX\n",
+                                                    pControlDevExt->Specific.Control.ExtentCount);
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        ntStatus = AFSUnloadLibrary( TRUE);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            try_return( ntStatus);
+        }
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Completed shut down of redirector Extent count %08lX Request count %08lX Status %08lX\n",
+                                __FUNCTION__,
+                                pControlDevExt->Specific.Control.ExtentCount,
+                                pControlDevExt->Specific.Control.OutstandingServiceRequestCount,
+                                ntStatus);
+    }
+
+    return ntStatus;
+}
+
+//
+// Cache manager callback routines
+//
+
+BOOLEAN
+AFSAcquireFcbForLazyWrite( IN PVOID Fcb,
+                           IN BOOLEAN Wait)
+{
+
+    BOOLEAN bStatus = FALSE;
+    AFSFcb *pFcb = (AFSFcb *)Fcb;
+    BOOLEAN bReleaseMain = FALSE, bReleasePaging = FALSE;
+
+    //
+    // Try and acquire the Fcb resource
+    //
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSAcquireFcbForLazyWrite Acquiring Fcb %08lX\n",
+                  Fcb);
+
+    ASSERT( NULL == pFcb->Specific.File.LazyWriterThread);
+
+    pFcb->Specific.File.LazyWriterThread = PsGetCurrentThread();
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
+                  &pFcb->NPFcb->Resource,
+                  PsGetCurrentThread());
+
+    if( AFSAcquireShared( &pFcb->NPFcb->Resource,
+                          Wait))
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSAcquireFcbForLazyWrite Acquired Fcb lock %08lX SHARED %08lX\n",
+                      &pFcb->NPFcb->Resource,
+                      PsGetCurrentThread());
+
+        bReleaseMain = TRUE;
+
+        //
+        // Try and grab the paging
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSAcquireFcbForLazyWrite Attempt to acquire Fcb PagingIo lock %08lX SHARED %08lX\n",
+                      &pFcb->NPFcb->PagingResource,
+                      PsGetCurrentThread());
+
+        if( AFSAcquireShared( &pFcb->NPFcb->PagingResource,
+                              Wait))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSAcquireFcbForLazyWrite Acquired Fcb PagingIo lock %08lX SHARED %08lX\n",
+                          &pFcb->NPFcb->PagingResource,
+                          PsGetCurrentThread());
+
+            bReleasePaging = TRUE;
+
+            //
+            // All is well ...
+            //
+
+            bStatus = TRUE;
+
+            IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+        }
+    }
+
+    if( !bStatus)
+    {
+
+        if( bReleaseMain)
+        {
+
+            AFSReleaseResource( &pFcb->NPFcb->Resource);
+        }
+
+        if( bReleasePaging)
+        {
+
+            AFSReleaseResource( &pFcb->NPFcb->PagingResource);
+        }
+    }
+
+    return bStatus;
+}
+
+VOID
+AFSReleaseFcbFromLazyWrite( IN PVOID Fcb)
+{
+
+    AFSFcb *pFcb = (AFSFcb *)Fcb;
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSReleaseFcbFromLazyWrite Releasing Fcb %08lX\n",
+                  Fcb);
+
+    IoSetTopLevelIrp( NULL);
+
+    ASSERT( PsGetCurrentThread() == pFcb->Specific.File.LazyWriterThread);
+
+    pFcb->Specific.File.LazyWriterThread = NULL;
+
+
+    AFSReleaseResource( &pFcb->NPFcb->PagingResource);
+
+    AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+    return;
+}
+
+BOOLEAN
+AFSAcquireFcbForReadAhead( IN PVOID Fcb,
+                           IN BOOLEAN Wait)
+{
+
+    BOOLEAN bStatus = FALSE;
+    AFSFcb *pFcb = (AFSFcb *)Fcb;
+
+    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                  AFS_TRACE_LEVEL_VERBOSE,
+                  "AFSAcquireFcbForReadAhead Attempt to acquire Fcb lock %08lX SHARED %08lX\n",
+                  &pFcb->NPFcb->Resource,
+                  PsGetCurrentThread());
+
+    if( AFSAcquireShared( &pFcb->NPFcb->Resource,
+                          Wait))
+    {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSAcquireFcbForReadAhead Acquired Fcb lock %08lX SHARED %08lX\n",
+                      &pFcb->NPFcb->Resource,
+                      PsGetCurrentThread());
+
+        bStatus = TRUE;
+
+        IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+    }
+
+    return bStatus;
+}
+
+VOID
+AFSReleaseFcbFromReadAhead( IN PVOID Fcb)
+{
+
+    AFSFcb *pFcb = (AFSFcb *)Fcb;
+
+    IoSetTopLevelIrp( NULL);
+
+    AFSReleaseResource( &pFcb->NPFcb->Resource);
+
+    return;
+}
+
+NTSTATUS
+AFSGetCallerSID( OUT UNICODE_STRING *SIDString, OUT BOOLEAN *pbImpersonation)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    PACCESS_TOKEN hToken = NULL;
+    TOKEN_USER *pTokenInfo = NULL;
+    BOOLEAN bCopyOnOpen = FALSE;
+    BOOLEAN bEffectiveOnly = FALSE;
+    BOOLEAN bPrimaryToken = FALSE;
+    SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
+    UNICODE_STRING uniSIDString;
+
+    __Enter
+    {
+
+        hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
+                                                &bCopyOnOpen,
+                                                &bEffectiveOnly,
+                                                &stImpersonationLevel);
+
+        if( hToken == NULL)
+        {
+
+            hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
+
+            if( hToken == NULL)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSGetCallerSID Failed to retrieve impersonation or primary token\n");
+
+                try_return( ntStatus);
+            }
+
+            bPrimaryToken = TRUE;
+        }
+
+        ntStatus = SeQueryInformationToken( hToken,
+                                            TokenUser,
+                                            (PVOID *)&pTokenInfo);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSGetCallerSID Failed to retrieve information Status %08lX\n", ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        uniSIDString.Length = 0;
+        uniSIDString.MaximumLength = 0;
+        uniSIDString.Buffer = NULL;
+
+        ntStatus = RtlConvertSidToUnicodeString( &uniSIDString,
+                                                 pTokenInfo->User.Sid,
+                                                 TRUE);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSGetCallerSID Failed to convert sid to string Status %08lX\n", ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        *SIDString = uniSIDString;
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "AFSGetCallerSID Successfully retrieved SID %wZ\n",
+                      SIDString);
+
+        if ( bPrimaryToken == FALSE &&
+             pbImpersonation)
+        {
+            *pbImpersonation = TRUE;
+        }
+
+try_exit:
+
+        if( hToken != NULL)
+        {
+            if( bPrimaryToken)
+            {
+                PsDereferencePrimaryToken( hToken);
+            }
+            else
+            {
+                PsDereferenceImpersonationToken( hToken);
+            }
+        }
+
+        if( pTokenInfo != NULL)
+        {
+            AFSExFreePool( pTokenInfo);
+        }
+    }
+
+    return ntStatus;
+}
+
+ULONG
+AFSGetSessionId( IN HANDLE ProcessId, OUT BOOLEAN *pbImpersonation)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    PACCESS_TOKEN hToken = NULL;
+    ULONG ulSessionId = (ULONG)-1;
+    BOOLEAN bCopyOnOpen = FALSE;
+    BOOLEAN bEffectiveOnly = FALSE;
+    BOOLEAN bPrimaryToken = FALSE;
+    SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
+
+    __Enter
+    {
+
+        hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
+                                                &bCopyOnOpen,
+                                                &bEffectiveOnly,
+                                                &stImpersonationLevel);
+
+        if( hToken == NULL)
+        {
+
+            hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
+
+            if( hToken == NULL)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSGetSessionId Failed to retrieve impersonation or primary token\n");
+
+                try_return( ntStatus);
+            }
+
+            bPrimaryToken = TRUE;
+        }
+
+        ntStatus = SeQueryInformationToken( hToken,
+                                            TokenSessionId,
+                                            (PVOID *)&ulSessionId);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+            ulSessionId = (ULONG)-1;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSGetSessionId Failed to retrieve session id Status %08lX\n",
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE_2,
+                      "AFSGetSessionId found %08lX\n",
+                      ulSessionId);
+
+        if ( bPrimaryToken == FALSE &&
+             pbImpersonation)
+        {
+            *pbImpersonation = TRUE;
+        }
+
+try_exit:
+
+        if( hToken != NULL)
+        {
+            if( bPrimaryToken)
+            {
+                PsDereferencePrimaryToken( hToken);
+            }
+            else
+            {
+                PsDereferenceImpersonationToken( hToken);
+            }
+        }
+    }
+
+    return ulSessionId;
+}
+
+NTSTATUS
+AFSCheckThreadDacl( OUT GUID *AuthGroup)
+{
+
+    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+    ULONG idx;
+    PACCESS_TOKEN token = NULL;
+    PTOKEN_DEFAULT_DACL defDacl = NULL;
+    PACE_HEADER ace;
+    PACCESS_ALLOWED_ACE adace;
+    BOOLEAN bCopyOnOpen = FALSE, bEffectiveOnly = FALSE;
+    SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
+    BOOLEAN bLocatedACE = FALSE;
+
+    __Enter
+    {
+
+        token = PsReferenceImpersonationToken( PsGetCurrentThread(),
+                                               &bCopyOnOpen,
+                                               &bEffectiveOnly,
+                                               &stImpersonationLevel);
+
+        if( token == NULL)
+        {
+           try_return( ntStatus);
+        }
+
+        ntStatus = SeQueryInformationToken( token,
+                                            TokenDefaultDacl,
+                                            (PVOID *)&defDacl);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+           try_return( ntStatus);
+        }
+
+        // scan through all ACEs in the DACL
+        for (idx = 0, ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL)); idx < defDacl->DefaultDacl->AceCount; idx++)
+        {
+           if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
+           {
+              adace = (PACCESS_ALLOWED_ACE)ace;
+
+              if (adace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
+              {
+                 if (RtlCompareMemory( RtlSubAuthoritySid((PSID)&adace->SidStart, 0), &AFSSidGuid, sizeof(GUID)) == sizeof(GUID))
+                 {
+
+                    RtlCopyMemory( AuthGroup,
+                                   RtlSubAuthoritySid((PSID)&adace->SidStart, 4),
+                                   sizeof( GUID));
+
+                    bLocatedACE = TRUE;
+
+                    break;
+                 }
+              }
+           }
+
+           // go to next ace
+           ace = (PACE_HEADER)((char *)ace + ace->AceSize);
+        }
+
+try_exit:
+
+        if( token != NULL)
+        {
+            PsDereferenceImpersonationToken( token);
+        }
+
+        if (defDacl != NULL)
+        {
+           ExFreePool(defDacl);
+        }
+
+        if( !bLocatedACE)
+        {
+            ntStatus = STATUS_UNSUCCESSFUL;
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB)
+{
+
+    PTOKEN_DEFAULT_DACL defDacl = NULL;
+    HANDLE hToken = NULL;
+    PACE_HEADER ace = NULL;
+    SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
+    PACCESS_ALLOWED_ACE aaace;
+    ULONG bytesNeeded;
+    ULONG bytesReturned;
+    ULONG idx;
+    PSID psid;
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+
+    __Enter
+    {
+
+        ntStatus = ZwOpenProcessTokenEx( NtCurrentProcess(),
+                                         GENERIC_ALL,
+                                         OBJ_KERNEL_HANDLE,
+                                         &hToken);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+            try_return( ntStatus);
+        }
+
+        // get the size of the current DACL
+        ntStatus = ZwQueryInformationToken( hToken,
+                                            TokenDefaultDacl,
+                                            NULL,
+                                            0,
+                                            &bytesNeeded);
+
+        // if we failed to get the buffer size needed
+        if ((ntStatus != STATUS_SUCCESS) && (ntStatus != STATUS_BUFFER_TOO_SMALL))
+        {
+            try_return( ntStatus);
+        }
+
+        // tack on enough space for our ACE if we need to add it...
+        bytesNeeded += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH;
+
+        // allocate space for the DACL
+        defDacl = (PTOKEN_DEFAULT_DACL)ExAllocatePoolWithTag( PagedPool, bytesNeeded, AFS_GENERIC_MEMORY_26_TAG);
+
+        if (defDacl == NULL)
+        {
+           try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        // get the DACL
+        ntStatus = ZwQueryInformationToken( hToken,
+                                            TokenDefaultDacl,
+                                            defDacl,
+                                            bytesNeeded,
+                                            &bytesReturned);
+
+        if( ntStatus != STATUS_SUCCESS)
+        {
+            try_return( ntStatus);
+        }
+
+        // scan through DACL to see if we have the SID set already...
+        ace = (PACE_HEADER)((char *)defDacl->DefaultDacl + sizeof(ACL));
+        for (idx = 0; idx < defDacl->DefaultDacl->AceCount; idx++)
+        {
+            if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
+            {
+                aaace = (PACCESS_ALLOWED_ACE)ace;
+
+                if (aaace->Header.AceSize == (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + AFS_DACL_SID_LENGTH))
+                {
+                    // if the GUID part matches
+                    if( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 0),
+                                          &AFSSidGuid,
+                                          sizeof(GUID)) == sizeof(GUID))
+                    {
+
+                        if ( RtlCompareMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
+                                               ProcessCB->ActiveAuthGroup,
+                                               sizeof( GUID)) != sizeof( GUID))
+                        {
+
+                            RtlCopyMemory( RtlSubAuthoritySid((PSID)&aaace->SidStart, 4),
+                                           ProcessCB->ActiveAuthGroup,
+                                           sizeof( GUID));
+
+                            if( AFSSetInformationToken != NULL)
+                            {
+                                ntStatus = AFSSetInformationToken( hToken,
+                                                                   TokenDefaultDacl,
+                                                                   defDacl,
+                                                                   bytesReturned);
+                            }
+                        }
+
+                        try_return( ntStatus);
+                    }
+                }
+            }
+
+            // go to next ace
+            ace = (PACE_HEADER)((char *)ace + ace->AceSize);
+        }
+
+        //
+        // if we made it here we need to add a new ACE to the DACL
+        //
+
+        aaace = (ACCESS_ALLOWED_ACE *)ace;
+        aaace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+        aaace->Header.AceFlags = 0;
+        aaace->Mask = GENERIC_ALL;
+        psid = (PSID)&aaace->SidStart;
+        RtlInitializeSid( psid, &sia, 8);
+
+        RtlCopyMemory( RtlSubAuthoritySid(psid, 0),
+                       &AFSSidGuid,
+                       sizeof(GUID));
+
+        RtlCopyMemory( RtlSubAuthoritySid(psid, 4),
+                       ProcessCB->ActiveAuthGroup,
+                       sizeof( GUID));
+
+        aaace->Header.AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid( psid));
+
+        defDacl->DefaultDacl->AclSize += aaace->Header.AceSize;
+        defDacl->DefaultDacl->AceCount++;
+
+        if( AFSSetInformationToken != NULL)
+        {
+            ntStatus = AFSSetInformationToken( hToken,
+                                              TokenDefaultDacl,
+                                              defDacl,
+                                              defDacl->DefaultDacl->AclSize + sizeof(PTOKEN_DEFAULT_DACL));
+        }
+
+try_exit:
+
+        if( hToken != NULL)
+        {
+            ZwClose( hToken);
+        }
+
+        if (defDacl != NULL)
+        {
+           ExFreePool( defDacl);
+        }
+    }
+
+    return ntStatus;
+}
+
+
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSInit.cpp b/src/WINNT/afsrdr/kernel/fs/AFSInit.cpp
new file mode 100644 (file)
index 0000000..770de37
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * 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: AFSInit.cpp
+//
+
+#include "AFSCommon.h"
+
+#ifndef AMD64
+extern "C"
+{
+extern void                   *KeServiceDescriptorTable;
+};
+#endif
+
+//
+// DriverEntry
+//
+// This is the initial entry point for the driver.
+//
+// Inputs:
+//  DriverObject        Pointer to Driver Object created by I/O manager
+//  RegistryPath        Pointer to registry path representing this Driver
+//
+// Returns:
+//  Success             To indicate Driver's inituaialization processing
+//                      was successful
+//  NT ERROR STATUS     Otherwise -- Driver does not remain loaded
+//
+
+NTSTATUS
+DriverEntry( PDRIVER_OBJECT DriverObject,
+             PUNICODE_STRING RegistryPath)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt    *pDeviceExt;
+    ULONG ulTimeIncrement = 0;
+    UNICODE_STRING uniSymLinkName;
+    UNICODE_STRING uniDeviceName;
+    ULONG ulIndex = 0;
+    ULONG ulValue = 0;
+    UNICODE_STRING uniValueName;
+    BOOLEAN bExit = FALSE;
+    UNICODE_STRING uniRoutine;
+    RTL_OSVERSIONINFOW sysVersion;
+
+    __try
+    {
+
+        DbgPrint("AFSRedirFs DriverEntry Initialization build %s:%s\n", __DATE__, __TIME__);
+
+        //
+        // Initialize some local variables for easier processing
+        //
+
+        uniSymLinkName.Buffer = NULL;
+
+        AFSDumpFileLocation.Length = 0;
+        AFSDumpFileLocation.MaximumLength = 0;
+        AFSDumpFileLocation.Buffer = NULL;
+
+        AFSDumpFileName.Length = 0;
+        AFSDumpFileName.Buffer = NULL;
+        AFSDumpFileName.MaximumLength = 0;
+
+        ExInitializeResourceLite( &AFSDbgLogLock);
+
+        //
+        // Initialize the server name
+        //
+
+        AFSReadServerName();
+
+        RtlZeroMemory( &sysVersion,
+                       sizeof( RTL_OSVERSIONINFOW));
+
+        sysVersion.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW);
+
+        RtlGetVersion( &sysVersion);
+
+        RtlInitUnicodeString( &uniRoutine,
+                              L"ZwSetInformationToken");
+
+        AFSSetInformationToken = (PAFSSetInformationToken)MmGetSystemRoutineAddress( &uniRoutine);
+
+        if( AFSSetInformationToken == NULL)
+        {
+#ifndef AMD64
+            AFSSrvcTableEntry *pServiceTable = NULL;
+
+            pServiceTable = (AFSSrvcTableEntry *)KeServiceDescriptorTable;
+
+            //
+            // Only perform this lookup for Windows XP.
+            //
+
+            if( pServiceTable != NULL &&
+                sysVersion.dwMajorVersion == 5 &&
+                sysVersion.dwMinorVersion == 1)
+            {
+                AFSSetInformationToken = (PAFSSetInformationToken)pServiceTable->ServiceTable[ 0xE6];
+            }
+#endif
+        }
+
+        //
+        // And the global root share name
+        //
+
+        RtlInitUnicodeString( &AFSGlobalRootName,
+                              AFS_GLOBAL_ROOT_SHARE_NAME);
+
+        RtlZeroMemory( &AFSNoPAGAuthGroup,
+                       sizeof( GUID));
+
+        //
+        // Our backdoor to not let the driver load
+        //
+
+        if( bExit)
+        {
+            try_return( ntStatus);
+        }
+
+        //
+        // Perform some initialization
+        //
+
+        AFSDriverObject = DriverObject;
+
+        ntStatus = AFSReadRegistry( RegistryPath);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            DbgPrint("AFS DriverEntry: Failed to read registry Status %08lX\n", ntStatus);
+
+            ntStatus = STATUS_SUCCESS;
+        }
+
+        //
+        // Initialize the debug log and dump file interface
+        //
+
+        AFSInitializeDbgLog();
+
+        AFSInitializeDumpFile();
+
+#if DBG
+
+        if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_BREAK_ON_ENTRY))
+        {
+
+            DbgPrint("AFSRedirFs DriverEntry - Break on entry\n");
+
+            AFSBreakPoint();
+
+            if ( bExit)
+            {
+                //
+                // Just as above
+                //
+                try_return( ntStatus = STATUS_UNSUCCESSFUL);
+            }
+        }
+#endif
+
+        if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN) &&
+            !BooleanFlagOn( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN))
+        {
+
+            AFSPrint("AFS DriverEntry: Failed to shutdown clean, exiting\n");
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        //
+        // Setup the registry string
+        //
+
+        AFSRegistryPath.MaximumLength = RegistryPath->MaximumLength;
+        AFSRegistryPath.Length        = RegistryPath->Length;
+
+        AFSRegistryPath.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool,
+                                                               AFSRegistryPath.Length,
+                                                               AFS_GENERIC_MEMORY_18_TAG);
+
+        if( AFSRegistryPath.Buffer == NULL)
+        {
+
+            DbgPrint("AFSRedirFs DriverEntry Failed to allocate registry path buffer\n");
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlCopyMemory( AFSRegistryPath.Buffer,
+                       RegistryPath->Buffer,
+                       RegistryPath->Length);
+
+        if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN))
+        {
+
+            //
+            // Update the shutdown flag
+            //
+
+            ulValue = (ULONG)-1;
+
+            RtlInitUnicodeString( &uniValueName,
+                                  AFS_REG_SHUTDOWN_STATUS);
+
+            AFSUpdateRegistryParameter( &uniValueName,
+                                        REG_DWORD,
+                                        &ulValue,
+                                        sizeof( ULONG));
+        }
+
+        RtlInitUnicodeString( &uniDeviceName,
+                              AFS_CONTROL_DEVICE_NAME);
+
+        ntStatus = IoCreateDeviceSecure( DriverObject,
+                                         sizeof( AFSDeviceExt),
+                                         &uniDeviceName,
+                                         FILE_DEVICE_NETWORK_FILE_SYSTEM,
+                                         0,
+                                         FALSE,
+                                         &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX,
+                                         (LPCGUID)&GUID_SD_AFS_REDIRECTOR_CONTROL_OBJECT,
+                                         &AFSDeviceObject);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            DbgPrint("AFS DriverEntry - Failed to allocate device control object Status %08lX\n", ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Setup the device extension
+        //
+
+        pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+        InitializeListHead( &pDeviceExt->Specific.Control.DirNotifyList);
+        FsRtlNotifyInitializeSync( &pDeviceExt->Specific.Control.NotifySync);
+
+        //
+        // Now initialize the control device
+        //
+
+        ntStatus = AFSInitializeControlDevice();
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Allocate our symbolic link for service communication
+        //
+
+        RtlInitUnicodeString( &uniSymLinkName,
+                              AFS_SYMLINK_NAME);
+
+        ntStatus = IoCreateSymbolicLink( &uniSymLinkName,
+                                         &uniDeviceName);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            DbgPrint("AFS DriverEntry - Failed to create symbolic link Status %08lX\n", ntStatus);
+
+            //
+            // OK, no one can communicate with us so fail
+            //
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Fill in the dispatch table
+        //
+
+        for( ulIndex = 0; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++)
+        {
+
+            DriverObject->MajorFunction[ ulIndex] = AFSDefaultDispatch;
+        }
+
+        DriverObject->MajorFunction[IRP_MJ_CREATE] =                    AFSCreate;
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] =                     AFSClose;
+        DriverObject->MajorFunction[IRP_MJ_READ] =                      AFSRead;
+        DriverObject->MajorFunction[IRP_MJ_WRITE] =                     AFSWrite;
+        DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =         AFSQueryFileInfo;
+        DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =           AFSSetFileInfo;
+        DriverObject->MajorFunction[IRP_MJ_QUERY_EA] =                  AFSQueryEA;
+        DriverObject->MajorFunction[IRP_MJ_SET_EA] =                    AFSSetEA;
+        DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] =             AFSFlushBuffers;
+        DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =  AFSQueryVolumeInfo;
+        DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =    AFSSetVolumeInfo;
+        DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =         AFSDirControl;
+        DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =       AFSFSControl;
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =            AFSDevControl;
+        DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =   AFSInternalDevControl;
+        DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] =                  AFSShutdown;
+        DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] =              AFSLockControl;
+        DriverObject->MajorFunction[IRP_MJ_CLEANUP] =                   AFSCleanup;
+        DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =            AFSQuerySecurity;
+        DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =              AFSSetSecurity;
+        DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =            AFSSystemControl;
+        //DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] =               AFSQueryQuota;
+        //DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] =                 AFSSetQuota;
+
+        //
+        // Since we are not a true FSD then we are not controlling a device and hence these will not be needed
+        //
+
+#ifdef FSD_NOT_USED
+
+        DriverObject->MajorFunction[IRP_MJ_POWER] =                     AFSPower;
+        DriverObject->MajorFunction[IRP_MJ_PNP] =                       AFSPnP;
+
+#endif
+
+        //
+        // Fast IO Dispatch table
+        //
+
+        DriverObject->FastIoDispatch = &AFSFastIoDispatch;
+
+        RtlZeroMemory( &AFSFastIoDispatch,
+                       sizeof( AFSFastIoDispatch));
+
+        //
+        // Again, since we are not a registered FSD many of these are not going to be called. They are here
+        // for completeness.
+        //
+
+        AFSFastIoDispatch.SizeOfFastIoDispatch         = sizeof(FAST_IO_DISPATCH);
+        AFSFastIoDispatch.FastIoCheckIfPossible        = AFSFastIoCheckIfPossible;  //  CheckForFastIo
+        AFSFastIoDispatch.FastIoRead                   = AFSFastIoRead;             //  Read
+        AFSFastIoDispatch.FastIoWrite                  = AFSFastIoWrite;            //  Write
+        AFSFastIoDispatch.FastIoQueryBasicInfo         = AFSFastIoQueryBasicInfo;     //  QueryBasicInfo
+        AFSFastIoDispatch.FastIoQueryStandardInfo      = AFSFastIoQueryStandardInfo;       //  QueryStandardInfo
+        AFSFastIoDispatch.FastIoLock                   = AFSFastIoLock;               //  Lock
+        AFSFastIoDispatch.FastIoUnlockSingle           = AFSFastIoUnlockSingle;       //  UnlockSingle
+        AFSFastIoDispatch.FastIoUnlockAll              = AFSFastIoUnlockAll;          //  UnlockAll
+        AFSFastIoDispatch.FastIoUnlockAllByKey         = AFSFastIoUnlockAllByKey;     //  UnlockAllByKey
+        AFSFastIoDispatch.FastIoQueryNetworkOpenInfo   = AFSFastIoQueryNetworkOpenInfo;
+        AFSFastIoDispatch.AcquireForCcFlush            = AFSFastIoAcquireForCCFlush;
+        AFSFastIoDispatch.ReleaseForCcFlush            = AFSFastIoReleaseForCCFlush;
+        AFSFastIoDispatch.FastIoDeviceControl          = AFSFastIoDevCtrl;
+        AFSFastIoDispatch.AcquireFileForNtCreateSection = AFSFastIoAcquireFile;
+        AFSFastIoDispatch.ReleaseFileForNtCreateSection = AFSFastIoReleaseFile;
+        AFSFastIoDispatch.FastIoDetachDevice           = AFSFastIoDetachDevice;
+        //AFSFastIoDispatch.AcquireForModWrite           = AFSFastIoAcquireForModWrite;
+        //AFSFastIoDispatch.ReleaseForModWrite           = AFSFastIoReleaseForModWrite;
+        AFSFastIoDispatch.MdlRead                      = AFSFastIoMdlRead;
+        AFSFastIoDispatch.MdlReadComplete              = AFSFastIoMdlReadComplete;
+        AFSFastIoDispatch.PrepareMdlWrite              = AFSFastIoPrepareMdlWrite;
+        AFSFastIoDispatch.MdlWriteComplete             = AFSFastIoMdlWriteComplete;
+        AFSFastIoDispatch.FastIoReadCompressed         = AFSFastIoReadCompressed;
+        AFSFastIoDispatch.FastIoWriteCompressed        = AFSFastIoWriteCompressed;
+        AFSFastIoDispatch.MdlReadCompleteCompressed    = AFSFastIoMdlReadCompleteCompressed;
+        AFSFastIoDispatch.MdlWriteCompleteCompressed   = AFSFastIoMdlWriteCompleteCompressed;
+        AFSFastIoDispatch.FastIoQueryOpen              = AFSFastIoQueryOpen;
+
+        //
+        //  Cache manager callback routines.
+        //
+
+        AFSCacheManagerCallbacks.AcquireForLazyWrite  = &AFSAcquireFcbForLazyWrite;
+        AFSCacheManagerCallbacks.ReleaseFromLazyWrite = &AFSReleaseFcbFromLazyWrite;
+        AFSCacheManagerCallbacks.AcquireForReadAhead  = &AFSAcquireFcbForReadAhead;
+        AFSCacheManagerCallbacks.ReleaseFromReadAhead = &AFSReleaseFcbFromReadAhead;
+
+        //
+        //  System process.
+        //
+
+        AFSSysProcess = PsGetCurrentProcessId();
+
+        //
+        // Register for shutdown notification
+        //
+
+        IoRegisterShutdownNotification( AFSDeviceObject);
+
+        //
+        // Initialize the system process cb
+        //
+
+        AFSInitializeProcessCB( 0,
+                                (ULONGLONG)AFSSysProcess);
+
+        //
+        // Initialize the redirector device
+        //
+
+        ntStatus = AFSInitRDRDevice();
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            DbgPrint("AFS DriverEntry Failed to initialize redirector device Status %08lX\n");
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Initialize some server name based strings
+        //
+
+        AFSInitServerStrings();
+
+        //
+        // Register the call back for process creation and tear down
+        //
+
+        PsSetCreateProcessNotifyRoutine( AFSProcessNotify,
+                                         FALSE);
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            DbgPrint("AFSRedirFs DriverEntry failed to initialize %08lX\n", ntStatus);
+
+            if( AFSRegistryPath.Buffer != NULL)
+            {
+
+                ExFreePool( AFSRegistryPath.Buffer);
+            }
+
+            if( uniSymLinkName.Buffer != NULL)
+            {
+
+                IoDeleteSymbolicLink( &uniSymLinkName);
+            }
+
+            if( AFSDeviceObject != NULL)
+            {
+
+                AFSRemoveControlDevice();
+
+                FsRtlNotifyUninitializeSync( &pDeviceExt->Specific.Control.NotifySync);
+
+                IoUnregisterShutdownNotification( AFSDeviceObject);
+
+                IoDeleteDevice( AFSDeviceObject);
+            }
+
+            AFSTearDownDbgLog();
+
+            ExDeleteResourceLite( &AFSDbgLogLock);
+        }
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSRedirFs DriverEntry\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp
new file mode 100644 (file)
index 0000000..1853912
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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: AFSInternalDevControl.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSInternalDevControl( IN PDEVICE_OBJECT DeviceObject,
+                       IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_NOT_IMPLEMENTED;
+    IO_STACK_LOCATION *pIrpSp;
+
+    pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __try
+    {
+
+        AFSCompleteRequest( Irp,
+                            ntStatus);
+
+    }
+    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    {
+
+        AFSDbgLogMsg( 0,
+                      0,
+                      "EXCEPTION - AFSInternalDevControl\n");
+    }
+
+    return ntStatus;
+}
diff --git a/src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp
new file mode 100644 (file)
index 0000000..23320ba
--- /dev/null
@@ -0,0 +1,923 @@
+/*
+ * 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: AFSLibrarySupport.cpp
+//
+
+#include "AFSCommon.h"
+
+NTSTATUS
+AFSLoadLibrary( IN ULONG Flags,
+                IN UNICODE_STRING *ServicePath)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    UNICODE_STRING uniLibraryName;
+    AFSDeviceExt *pLibDevExt = NULL;
+    PFILE_OBJECT pLibraryFileObject = NULL;
+    PDEVICE_OBJECT pLibraryDeviceObject = NULL;
+
+    __Enter
+    {
+
+        //
+        // Wait on the load library event so we don't race with any
+        // other requests coming through
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Start load library\n",
+                      __FUNCTION__);
+
+        ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          NULL);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSLoadLibrary Wait for LoadLibraryEvent failure %08lX\n",
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Check our current state to ensure we currently do not have a library loaded
+        //
+
+        if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Library already loaded\n",
+                          __FUNCTION__);
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        pDevExt->Specific.Control.LibraryServicePath.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                                                 ServicePath->Length,
+                                                                                                 AFS_GENERIC_MEMORY_25_TAG);
+
+        if( pDevExt->Specific.Control.LibraryServicePath.Buffer == NULL)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSLoadLibrary AFS_GENERIC_MEMORY_25_TAG allocation error\n");
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        RtlZeroMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer,
+                       ServicePath->Length);
+
+        pDevExt->Specific.Control.LibraryServicePath.Length = ServicePath->Length;
+        pDevExt->Specific.Control.LibraryServicePath.MaximumLength = pDevExt->Specific.Control.LibraryServicePath.Length;
+
+        RtlCopyMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer,
+                       ServicePath->Buffer,
+                       pDevExt->Specific.Control.LibraryServicePath.Length);
+
+        //
+        // Load the library
+        //
+
+        ntStatus = ZwLoadDriver( ServicePath);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "%s Failed to load library Status %08lX\n",
+                          __FUNCTION__,
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // Open up the control device and grab teh entry points for the library
+        //
+
+        RtlInitUnicodeString( &uniLibraryName,
+                              AFS_LIBRARY_CONTROL_DEVICE_NAME);
+
+        ntStatus = IoGetDeviceObjectPointer( &uniLibraryName,
+                                             FILE_ALL_ACCESS,
+                                             &pLibraryFileObject,
+                                             &pLibraryDeviceObject);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSLoadLibrary IoGetDeviceObjectPointer failure %08lX\n",
+                          ntStatus);
+
+            try_return( ntStatus);
+        }
+
+        //
+        // We have our reference to the library device object. Grab the
+        // device extension and setup our callbacks
+        //
+
+        pLibDevExt = (AFSDeviceExt *)pLibraryDeviceObject->DeviceExtension;
+
+        //
+        // Save off our references
+        //
+
+        pDevExt->Specific.Control.LibraryFileObject = pLibraryFileObject;
+
+        pDevExt->Specific.Control.LibraryDeviceObject = pLibraryDeviceObject;
+
+        //
+        // Reset the state for our library
+        //
+
+        AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock,
+                        TRUE);
+
+        SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED);
+
+        ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Completed load library, processing queued requests\n",
+                      __FUNCTION__);
+
+        AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);
+
+        //
+        // Process the queued requests
+        //
+
+        AFSProcessQueuedResults( FALSE);
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Library load complete Status %08lX\n",
+                      __FUNCTION__,
+                      ntStatus);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            if( pDevExt->Specific.Control.LibraryServicePath.Buffer != NULL)
+            {
+
+                ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath);
+
+                ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer);
+
+                pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL;
+                pDevExt->Specific.Control.LibraryServicePath.Length = 0;
+                pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0;
+            }
+        }
+
+        KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent,
+                    0,
+                    FALSE);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSUnloadLibrary( IN BOOLEAN CancelQueue)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    LARGE_INTEGER       liTimeout;
+
+    __Enter
+    {
+
+        //
+        // Wait on the load library event so we don't race with any
+        // other requests coming through
+        //
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Start unload library\n",
+                      __FUNCTION__);
+
+        ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent,
+                                          Executive,
+                                          KernelMode,
+                                          FALSE,
+                                          NULL);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+            try_return( ntStatus);
+        }
+
+        if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED))
+        {
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        //
+        // Clear all outstanding requests
+        //
+
+        AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock,
+                        TRUE);
+
+        ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED);
+
+        if( CancelQueue)
+        {
+            SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED);
+        }
+
+        //
+        // We'll wait on the inflight event to be set, checking for the inflight
+        // request count to reach zero
+        //
+
+        while( pDevExt->Specific.Control.InflightLibraryRequests > 0)
+        {
+
+            liTimeout.QuadPart = -(AFS_ONE_SECOND);
+
+            //
+            // If the count is non-zero make sure the event is cleared
+            //
+
+            KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent);
+
+            AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);
+
+            ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.InflightLibraryEvent,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              &liTimeout);
+
+            AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock,
+                            TRUE);
+
+            if( ntStatus != STATUS_TIMEOUT &&
+                ntStatus != STATUS_SUCCESS)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Failed request event Status %08lX\n",
+                              __FUNCTION__,
+                              ntStatus);
+
+                SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED);
+
+                AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);
+
+                AFSProcessQueuedResults( TRUE);
+
+                try_return( ntStatus);
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "%s Wait for inflight requests to complete %08lX\n",
+                          __FUNCTION__,
+                          pDevExt->Specific.Control.InflightLibraryRequests);
+        }
+
+        AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Processing queued results\n",
+                      __FUNCTION__);
+
+        AFSProcessQueuedResults( TRUE);
+
+        //
+        // Unload the current library implementation
+        //
+
+        if( pDevExt->Specific.Control.LibraryFileObject != NULL)
+        {
+            ObDereferenceObject( pDevExt->Specific.Control.LibraryFileObject);
+        }
+
+        pDevExt->Specific.Control.LibraryFileObject = NULL;
+
+        pDevExt->Specific.Control.LibraryDeviceObject = NULL;
+
+        ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath);
+
+        ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer);
+
+        pDevExt->Specific.Control.LibraryServicePath.Length = 0;
+
+        pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0;
+
+        pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL;
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Library unload complete Status %08lX\n",
+                      __FUNCTION__,
+                      ntStatus);
+
+        KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent,
+                    0,
+                    FALSE);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSCheckLibraryState( IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __Enter
+    {
+
+        AFSAcquireShared( &pDevExt->Specific.Control.LibraryStateLock,
+                          TRUE);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Entry State %08lX Irp %p Function %08lX\n",
+                      __FUNCTION__,
+                      pRDRDevExt->DeviceFlags,
+                      Irp,
+                      pIrpSp->MajorFunction);
+
+        if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
+        {
+
+            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
+        }
+
+        if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED))
+        {
+
+            if( Irp != NULL)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Queuing request %p\n",
+                              __FUNCTION__,
+                              Irp);
+
+                ntStatus = AFSQueueLibraryRequest( Irp);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Queued request %p Status %08lX\n",
+                              __FUNCTION__,
+                              Irp,
+                              ntStatus);
+            }
+            else
+            {
+
+                ntStatus = STATUS_TOO_LATE;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "%s Failing request %p\n",
+                              __FUNCTION__,
+                              Irp);
+            }
+
+            try_return( ntStatus);
+        }
+
+        if( InterlockedIncrement( &pDevExt->Specific.Control.InflightLibraryRequests) == 1)
+        {
+            KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent);
+        }
+
+try_exit:
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Completed Irp %p Status %08lX Inflight Count %08lX\n",
+                      __FUNCTION__,
+                      Irp,
+                      ntStatus,
+                      pDevExt->Specific.Control.InflightLibraryRequests);
+
+        AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSClearLibraryRequest()
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+
+    __Enter
+    {
+
+        if( InterlockedDecrement( &pDevExt->Specific.Control.InflightLibraryRequests) == 0)
+        {
+
+            KeSetEvent( &pDevExt->Specific.Control.InflightLibraryEvent,
+                        0,
+                        FALSE);
+        }
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "%s Inflight Count %08lX\n",
+                      __FUNCTION__,
+                      pDevExt->Specific.Control.InflightLibraryRequests);
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
+AFSQueueLibraryRequest( IN PIRP Irp)
+{
+
+    NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
+    AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
+    AFSLibraryQueueRequestCB *pRequest = NULL;
+    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+
+    __Enter
+    {
+
+        AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock,