--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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( ¶mPath.Buffer[ 0],
+ &RegistryPath->Buffer[ 0],
+ RegistryPath->Length);
+
+ RtlCopyMemory( ¶mPath.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( ¶mPath.Buffer[ paramPath.Length / 2],
+ uniParamKey.Buffer,
+ uniParamKey.Length);
+
+ paramPath.Length += uniParamKey.Length;
+
+ InitializeObjectAttributes( &stObjectAttributes,
+ ¶mPath,
+ 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( ¶mPath.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;
+}
+
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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,