diff --git a/src/WINNT/afsrdr/kernel/fs/AFSAuthGroupSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSAuthGroupSupport.cpp new file mode 100644 index 0000000000..4eb31a1160 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSAuthGroupSupport.cpp @@ -0,0 +1,1736 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSAuthGroupSupport.cpp +// + +#include "AFSCommon.h" + +void +AFSRetrieveAuthGroup( IN ULONGLONG ProcessId, + IN ULONGLONG ThreadId, + OUT GUID *AuthGroup) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL; + AFSThreadCB *pThreadCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + GUID *pAuthGroup = NULL; + UNICODE_STRING uniGUIDString; + ULONG ulSessionId = 0; + BOOLEAN bImpersonation = FALSE; + + __Enter + { + + ulSessionId = AFSGetSessionId( (HANDLE)ProcessId, &bImpersonation); + + if( ulSessionId == (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve session ID for PID %I64X\n", + __FUNCTION__, + ProcessId); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + ulSessionId, + ProcessId, + ThreadId); + + ntStatus = AFSCheckThreadDacl( AuthGroup); + + if( NT_SUCCESS( ntStatus)) + { + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located AuthGroup %wZ via DACL for Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + &uniGUIDString, + ulSessionId, + ProcessId, + ThreadId); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + + try_return( ntStatus = STATUS_SUCCESS); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSRetrieveAuthGroup Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n", + pDeviceExt->Specific.Control.ProcessTree.TreeLock, + PsGetCurrentThread()); + + ntStatus = STATUS_SUCCESS; + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ProcessId, + (AFSBTreeEntry **)&pProcessCB); + + if( !NT_SUCCESS( ntStatus) || + pProcessCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate process entry for Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + ulSessionId, + ProcessId, + ThreadId); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus); + } + + for ( pThreadCB = pProcessCB->ThreadList; + pThreadCB != NULL; + pThreadCB = pThreadCB->Next) + { + + if( pThreadCB->ThreadId == ThreadId) + { + break; + } + } + + if( pThreadCB != NULL && + pThreadCB->ActiveAuthGroup != NULL) + { + pAuthGroup = pThreadCB->ActiveAuthGroup; + + RtlCopyMemory( AuthGroup, + pAuthGroup, + sizeof( GUID)); + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located AuthGroup %wZ in thread Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + &uniGUIDString, + ulSessionId, + ProcessId, + ThreadId); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + else if( pProcessCB->ActiveAuthGroup != NULL) + { + + pAuthGroup = pProcessCB->ActiveAuthGroup; + + RtlCopyMemory( AuthGroup, + pAuthGroup, + sizeof( GUID)); + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located AuthGroup %wZ in process Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + &uniGUIDString, + ulSessionId, + ProcessId, + ThreadId); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + if( pAuthGroup == NULL || + AFSIsNoPAGAuthGroup( pAuthGroup)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s No AuthGroup located, validating process for Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + ulSessionId, + ProcessId, + ThreadId); + + pAuthGroup = AFSValidateProcessEntry(); + + if( pAuthGroup != NULL) + { + RtlCopyMemory( AuthGroup, + pAuthGroup, + sizeof( GUID)); + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located AuthGroup %wZ after validation Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + &uniGUIDString, + ulSessionId, + ProcessId, + ThreadId); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + else + { + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate AuthGroup for Session %08lX PID %I64X TID %I64X\n", + __FUNCTION__, + ulSessionId, + ProcessId, + ThreadId); + } + } + +try_exit: + + NOTHING; + } + + return; +} + +// +// AFSIsLocalSystemAuthGroup returns TRUE if the AuthGroup matches +// the AuthGroup associated with the first process that communicates +// with the redirector which will always be "System" (PID 4). +// + +BOOLEAN +AFSIsLocalSystemAuthGroup( IN GUID *AuthGroup) +{ + + BOOLEAN bIsLocalSys = FALSE; + AFSProcessCB *pProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + UNICODE_STRING uniGUIDString; + + __Enter + { + + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + uniGUIDString.Buffer = NULL; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "%s Checking AuthGroup %wZ\n", + __FUNCTION__, + &uniGUIDString); + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + pProcessCB = (AFSProcessCB *)pDeviceExt->Specific.Control.ProcessTree.TreeHead; + + if( pProcessCB->ActiveAuthGroup != NULL && + RtlCompareMemory( pProcessCB->ActiveAuthGroup, + AuthGroup, + sizeof( GUID)) == sizeof( GUID)) + { + bIsLocalSys = TRUE; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s AuthGroup %wZ is LOCAL SYSTEM\n", + __FUNCTION__, + &uniGUIDString); + } + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + + return bIsLocalSys; +} + +BOOLEAN +AFSIsLocalSystemSID( IN UNICODE_STRING *SIDString) +{ + + BOOLEAN bIsLocalSys = FALSE; + UNICODE_STRING uniSysLocal; + + __Enter + { + + RtlInitUnicodeString( &uniSysLocal, + L"S-1-5-18"); + + if( RtlCompareUnicodeString( &uniSysLocal, + SIDString, + TRUE) == 0) + { + bIsLocalSys = TRUE; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "%s AuthGroup SID %wZ is %sLOCAL SYSTEM\n", + __FUNCTION__, + SIDString, + bIsLocalSys ? "" : "not "); + } + + return bIsLocalSys; +} + +BOOLEAN +AFSIsNoPAGAuthGroup( IN GUID *AuthGroup) +{ + + BOOLEAN bIsNoPAG = FALSE; + UNICODE_STRING uniGUIDString; + + __Enter + { + + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + uniGUIDString.Buffer = NULL; + + RtlStringFromGUID( *AuthGroup, + &uniGUIDString); + + if( RtlCompareMemory( AuthGroup, + &AFSNoPAGAuthGroup, + sizeof( GUID)) == sizeof( GUID)) + { + bIsNoPAG = TRUE; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE_2, + "%s AuthGroup %wZ is %sNoPAG\n", + __FUNCTION__, + &uniGUIDString, + bIsNoPAG ? "" : "not "); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + + return bIsNoPAG; +} + +// +// Creates a new AuthGroup and either activates it for +// the process or the current thread. If set as the +// new process AuthGroup, the prior AuthGroup list is +// cleared. +// + +NTSTATUS +AFSCreateSetProcessAuthGroup( AFSAuthGroupRequestCB *CreateSetAuthGroup) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL; + AFSThreadCB *pThreadCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId(); + UNICODE_STRING uniSIDString, uniPassedSIDString; + ULONG ulSIDHash = 0; + AFSProcessAuthGroupCB *pAuthGroup = NULL, *pLastAuthGroup = NULL; + ULONG ulSessionId = 0; + ULONGLONG ullTableHash = 0; + GUID stAuthGroup; + UNICODE_STRING uniCallerSID; + BOOLEAN bImpersonation = FALSE; + + __Enter + { + + uniCallerSID.Length = 0; + uniCallerSID.MaximumLength = 0; + uniCallerSID.Buffer = NULL; + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ullProcessID, + (AFSBTreeEntry **)&pProcessCB); + + if( !NT_SUCCESS( ntStatus) || + pProcessCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate process CB for PID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + AFSAcquireExcl( &pProcessCB->Lock, + TRUE); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + ntStatus = AFSGetCallerSID( &uniCallerSID, &bImpersonation); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate caller SID for PID %I64X Status %08lX\n", + __FUNCTION__, + ullProcessID, + ntStatus); + + try_return( ntStatus); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved caller SID %wZ for PID %I64X\n", + __FUNCTION__, + &uniCallerSID, + ullProcessID); + + + if( CreateSetAuthGroup->SIDLength != 0) + { + + uniPassedSIDString.Length = CreateSetAuthGroup->SIDLength; + uniPassedSIDString.MaximumLength = uniPassedSIDString.Length; + + uniPassedSIDString.Buffer = CreateSetAuthGroup->SIDString; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Validating passed SID %wZ for PID %I64X\n", + __FUNCTION__, + &uniPassedSIDString, + ullProcessID); + + if( RtlCompareUnicodeString( &uniCallerSID, + &uniPassedSIDString, + TRUE) != 0) + { + + if( !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Caller specified SID %wZ for PID %I64X but caller is not LOCAL SYSTEM AUTHORITY\n", + __FUNCTION__, + &uniPassedSIDString, + ullProcessID); + + try_return( ntStatus = STATUS_ACCESS_DENIED); + } + + uniSIDString = uniPassedSIDString; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SID %wZ for PID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID); + } + else + { + uniSIDString = uniCallerSID; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Caller and passed SID are equal SID %wZ for PID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID); + } + } + else + { + uniSIDString = uniCallerSID; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s No SID passed, using callers SID %wZ for PID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID); + } + + ntStatus = RtlHashUnicodeString( &uniSIDString, + TRUE, + HASH_STRING_ALGORITHM_DEFAULT, + &ulSIDHash); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to hash SID %wZ for PID %I64X Status %08lX\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ntStatus); + + try_return( ntStatus); + } + + ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation); + + if( ulSessionId == (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve SessionID PID %I64X Status %08lX\n", + __FUNCTION__, + ullProcessID, + ntStatus); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + if( CreateSetAuthGroup->SessionId != (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Checking passed SessionID %08lX for PID %I64X\n", + __FUNCTION__, + CreateSetAuthGroup->SessionId, + ullProcessID); + + if( ulSessionId != CreateSetAuthGroup->SessionId) + { + + if( !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Passed SessionID %08lX for PID %I64X, failed because caller is not LOCAL SYSTEM AUTHORITY\n", + __FUNCTION__, + CreateSetAuthGroup->SessionId, + ullProcessID); + + try_return( ntStatus = STATUS_ACCESS_DENIED); + } + + ulSessionId = CreateSetAuthGroup->SessionId; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SessionID %08lX for PID %I64X\n", + __FUNCTION__, + ulSessionId, + ullProcessID); + } + } + else + { + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using callers SessionID %08lX for PID %I64X\n", + __FUNCTION__, + ulSessionId, + ullProcessID); + } + + ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); + + pAuthGroup = pProcessCB->AuthGroupList; + + while( pAuthGroup != NULL) + { + + if( pAuthGroup->AuthGroupHash == ullTableHash) + { + break; + } + + pLastAuthGroup = pAuthGroup; + + pAuthGroup = pAuthGroup->Next; + } + + if( pAuthGroup != NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Located AuthGroup for SID %wZ SessionID %08lX for PID %I64X, failing request\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID); + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + pAuthGroup = (AFSProcessAuthGroupCB *)AFSExAllocatePoolWithTag( NonPagedPool, + sizeof( AFSProcessAuthGroupCB), + AFS_AG_ENTRY_CB_TAG); + + if( pAuthGroup == NULL) + { + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pAuthGroup, + sizeof( AFSProcessAuthGroupCB)); + + pAuthGroup->AuthGroupHash = (ULONGLONG)ullTableHash; + + while( ExUuidCreate( &pAuthGroup->AuthGroup) == STATUS_RETRY); + + if( pLastAuthGroup == NULL) + { + pProcessCB->AuthGroupList = pAuthGroup; + } + else + { + pLastAuthGroup->Next = pAuthGroup; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Allocated new AuthGroup for SID %wZ SessionID %08lX for PID %I64X\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID); + + if( BooleanFlagOn( CreateSetAuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP)) + { + + pThreadCB = pProcessCB->ThreadList; + + while( pThreadCB != NULL) + { + + if( pThreadCB->ThreadId == ullThreadId) + { + pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + break; + } + + pThreadCB = pThreadCB->Next; + } + + if( pThreadCB == NULL) + { + + pThreadCB = AFSInitializeThreadCB( pProcessCB, + ullThreadId); + + if( pThreadCB == NULL) + { + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Set new AuthGroup for SID %wZ SessionID %08lX for PID %I64X on thread ID %I64X\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID, + ullThreadId); + } + else if( BooleanFlagOn( CreateSetAuthGroup->Flags, AFS_PAG_FLAGS_SET_AS_ACTIVE)) + { + pProcessCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Set new AuthGroup for SID %wZ SessionID %08lX for PID %I64X on process\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID); + } + +try_exit: + + if( pProcessCB != NULL) + { + AFSReleaseResource( &pProcessCB->Lock); + } + + if( uniCallerSID.Length > 0) + { + RtlFreeUnicodeString( &uniCallerSID); + } + } + + return ntStatus; +} + +// +// Returns a list of the AuthGroup GUIDS associated +// with the current process, the current process GUID, +// and the current thread GUID. +// + +NTSTATUS +AFSQueryProcessAuthGroupList( IN GUID *GUIDList, + IN ULONG BufferLength, + OUT ULONG_PTR *ReturnLength) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + ULONG ulRequiredLength = 0; + AFSProcessAuthGroupCB *pAuthGroup = NULL; + GUID *pCurrentGUID = GUIDList; + UNICODE_STRING uniGUIDString; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for PID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ullProcessID, + (AFSBTreeEntry **)&pProcessCB); + + if( !NT_SUCCESS( ntStatus) || + pProcessCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate process entry PID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + AFSAcquireShared( &pProcessCB->Lock, + TRUE); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + pAuthGroup = pProcessCB->AuthGroupList; + + ulRequiredLength = 0; + + while( pAuthGroup != NULL) + { + ulRequiredLength += sizeof( GUID); + pAuthGroup = pAuthGroup->Next; + } + + if( BufferLength == 0 || + BufferLength < ulRequiredLength || + GUIDList == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Buffer too small for query, required %08lX for PID %I64X\n", + __FUNCTION__, + ulRequiredLength, + ullProcessID); + + *ReturnLength = ulRequiredLength; + try_return( ntStatus = STATUS_BUFFER_OVERFLOW); + } + + pAuthGroup = pProcessCB->AuthGroupList; + + *ReturnLength = 0; + + while( pAuthGroup != NULL) + { + RtlCopyMemory( pCurrentGUID, + &pAuthGroup->AuthGroup, + sizeof( GUID)); + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + RtlStringFromGUID( pAuthGroup->AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Adding AuthGroup %wZ for PID %I64X\n", + __FUNCTION__, + &uniGUIDString, + ullProcessID); + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + + pCurrentGUID = (GUID *)((char *)pCurrentGUID + sizeof( GUID)); + + *ReturnLength += sizeof( GUID); + + pAuthGroup = pAuthGroup->Next; + } + +try_exit: + + if( pProcessCB != NULL) + { + AFSReleaseResource( &pProcessCB->Lock); + } + } + + return ntStatus; +} + +// +// Permits the current AuthGroup for the process or +// thread to be set to the specified GUID. The GUID +// must be in the list of current values for the process. +// + +NTSTATUS +AFSSetActiveProcessAuthGroup( IN AFSAuthGroupRequestCB *ActiveAuthGroup) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL; + AFSThreadCB *pThreadCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId(); + AFSProcessAuthGroupCB *pAuthGroup = NULL; + UNICODE_STRING uniGUIDString; + + __Enter + { + + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + uniGUIDString.Buffer = NULL; + + RtlStringFromGUID( ActiveAuthGroup->AuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for ProcessID %I64X AuthGroup GUID %wZ\n", + __FUNCTION__, + ullProcessID, + &uniGUIDString); + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ullProcessID, + (AFSBTreeEntry **)&pProcessCB); + + if( !NT_SUCCESS( ntStatus) || + pProcessCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate process entry for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + + AFSAcquireExcl( &pProcessCB->Lock, + TRUE); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + pAuthGroup = pProcessCB->AuthGroupList; + + while( pAuthGroup != NULL) + { + + if( RtlCompareMemory( &ActiveAuthGroup->AuthGroup, + &pAuthGroup->AuthGroup, + sizeof( GUID)) == sizeof( GUID)) + { + break; + } + pAuthGroup = pAuthGroup->Next; + } + + if( pAuthGroup == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Failed to locate AuthGroup for ProcessID %I64X AuthGroup GUID %wZ\n", + __FUNCTION__, + ullProcessID, + &uniGUIDString); + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + if( BooleanFlagOn( ActiveAuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP)) + { + + pThreadCB = pProcessCB->ThreadList; + + while( pThreadCB != NULL) + { + + if( pThreadCB->ThreadId == ullThreadId) + { + pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + break; + } + + pThreadCB = pThreadCB->Next; + } + + if( pThreadCB == NULL) + { + + pThreadCB = AFSInitializeThreadCB( pProcessCB, + ullThreadId); + + if( pThreadCB == NULL) + { + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + pThreadCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Set active AuthGroup for ProcessID %I64X AuthGroup GUID %wZ on thread %I64X\n", + __FUNCTION__, + ullProcessID, + &uniGUIDString, + ullThreadId); + } + else + { + pProcessCB->ActiveAuthGroup = &pAuthGroup->AuthGroup; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Set active AuthGroup for ProcessID %I64X AuthGroup GUID %wZ on process\n", + __FUNCTION__, + ullProcessID, + &uniGUIDString); + } + +try_exit: + + if( pProcessCB != NULL) + { + AFSReleaseResource( &pProcessCB->Lock); + } + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + + return ntStatus; +} + +// +// Resets the current AuthGroup for the process or +// thread to the SID-AuthGroup +// + +NTSTATUS +AFSResetActiveProcessAuthGroup( IN IN AFSAuthGroupRequestCB *AuthGroup) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + GUID *pAuthGroup = NULL; + AFSProcessCB *pProcessCB = NULL; + AFSThreadCB *pThreadCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId(); + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ullProcessID, + (AFSBTreeEntry **)&pProcessCB); + + if( !NT_SUCCESS( ntStatus) || + pProcessCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate AuthGroup for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + AFSAcquireExcl( &pProcessCB->Lock, + TRUE); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + if( BooleanFlagOn( AuthGroup->Flags, AFS_PAG_FLAGS_THREAD_AUTH_GROUP)) + { + + pThreadCB = pProcessCB->ThreadList; + + while( pThreadCB != NULL) + { + + if( pThreadCB->ThreadId == ullThreadId) + { + pThreadCB->ActiveAuthGroup = NULL; + break; + } + + pThreadCB = pThreadCB->Next; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Reset AuthGroup list on thread %I64X for ProcessID %I64X\n", + __FUNCTION__, + ullThreadId, + ullProcessID); + } + else + { + pProcessCB->ActiveAuthGroup = NULL; + + pThreadCB = pProcessCB->ThreadList; + + while( pThreadCB != NULL) + { + pThreadCB->ActiveAuthGroup = NULL; + pThreadCB = pThreadCB->Next; + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Reset AuthGroup list on process for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + } + + AFSReleaseResource( &pProcessCB->Lock); + +try_exit: + + NOTHING; + } + + return ntStatus; +} + +// +// When bLogonSession == FALSE, the SID must not be specified +// and the SessionId must be -1. A new AuthGroup GUID is +// assigned to the SID and SessionId of the calling Process. +// +// When bLogonSession == TRUE, the SID must be specified and +// the SessionId must not be -1. The SID of the calling process +// must be LOCAL_SYSTEM and a new AuthGroup GUID is assigned to +// the specified SID and logon session. +// + +NTSTATUS +AFSCreateAuthGroupForSIDorLogonSession( IN AFSAuthGroupRequestCB *AuthGroupRequestCB, + IN BOOLEAN bLogonSession) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + ULONGLONG ullThreadId = (ULONGLONG)PsGetCurrentThreadId(); + UNICODE_STRING uniSIDString, uniPassedSIDString; + ULONG ulSIDHash = 0; + AFSSIDEntryCB *pSIDEntryCB = NULL; + ULONG ulSessionId = 0; + ULONGLONG ullTableHash = 0; + GUID stAuthGroup; + UNICODE_STRING uniCallerSID; + UNICODE_STRING uniGUID; + BOOLEAN bLocalSystem = FALSE; + BOOLEAN bImpersonation = FALSE; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + ullProcessID, + ullThreadId); + + ntStatus = AFSGetCallerSID( &uniCallerSID, &bImpersonation); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve callers SID for ProcessID %I64X ThreadID %I64X Status %08lX\n", + __FUNCTION__, + ullProcessID, + ullThreadId, + ntStatus); + + try_return( ntStatus); + } + + bLocalSystem = AFSIsLocalSystemSID( &uniCallerSID); + + if( bLogonSession == TRUE && + bLocalSystem == FALSE) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s caller is %wZ and LOCAL SYSTEM AUTHORITY required\n", + __FUNCTION__, + uniCallerSID); + + try_return( ntStatus = STATUS_ACCESS_DENIED); + } + + if ( bLogonSession == TRUE && + ( AuthGroupRequestCB == NULL || + AuthGroupRequestCB->SIDLength == 0 || + AuthGroupRequestCB->SessionId == (ULONG)-1)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s SID and SessionId are mandatory\n", + __FUNCTION__); + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + if ( bLogonSession == FALSE && + AuthGroupRequestCB != NULL && + ( AuthGroupRequestCB->SIDLength > 0 || + AuthGroupRequestCB->SessionId != (ULONG)-1)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s SID and SessionId must not be specified\n", + __FUNCTION__); + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved callers SID %wZ for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + &uniCallerSID, + ullProcessID, + ullThreadId); + + if( AuthGroupRequestCB != NULL && + AuthGroupRequestCB->SIDLength != 0) + { + + uniPassedSIDString.Length = AuthGroupRequestCB->SIDLength; + uniPassedSIDString.MaximumLength = uniPassedSIDString.Length; + + uniPassedSIDString.Buffer = AuthGroupRequestCB->SIDString; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Checking passed SID %wZ for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + &uniPassedSIDString, + ullProcessID, + ullThreadId); + + if( RtlCompareUnicodeString( &uniCallerSID, + &uniPassedSIDString, + TRUE) != 0) + { + + if( !bLocalSystem) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Not using passed SID %wZ for ProcessID %I64X ThreadID %I64X caller is not LOCAL SYSTEM AUTHORITY\n", + __FUNCTION__, + &uniPassedSIDString, + ullProcessID, + ullThreadId); + + try_return( ntStatus = STATUS_ACCESS_DENIED); + } + + uniSIDString = uniPassedSIDString; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SID %wZ for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ullThreadId); + } + else + { + uniSIDString = uniCallerSID; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Both SIDs are equal, using callers SID %wZ for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ullThreadId); + } + } + else + { + uniSIDString = uniCallerSID; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using callers SID %wZ for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ullThreadId); + } + + ntStatus = RtlHashUnicodeString( &uniSIDString, + TRUE, + HASH_STRING_ALGORITHM_DEFAULT, + &ulSIDHash); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to hash SID %wZ for ProcessID %I64X ThreadID %I64X Status %08lX\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ullThreadId, + ntStatus); + + try_return( ntStatus); + } + + ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation); + + if( ulSessionId == (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve session ID for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + ullProcessID, + ullThreadId); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + if( bLogonSession == TRUE && + AuthGroupRequestCB != NULL && + AuthGroupRequestCB->SessionId != (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Checking passed SessionID %08lX for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + AuthGroupRequestCB->SessionId, + ullProcessID, + ullThreadId); + + if( ulSessionId != AuthGroupRequestCB->SessionId) + { + + ulSessionId = AuthGroupRequestCB->SessionId; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SessionID %08lX for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + AuthGroupRequestCB->SessionId, + ullProcessID, + ullThreadId); + } + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using callers SessionID %08lX for ProcessID %I64X ThreadID %I64X\n", + __FUNCTION__, + ulSessionId, + ullProcessID, + ullThreadId); + } + + ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); + + AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + (ULONGLONG)ullTableHash, + (AFSBTreeEntry **)&pSIDEntryCB); + + if( NT_SUCCESS( ntStatus) && + pSIDEntryCB != NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located SID entry for SID %wZ SessionID %08lX ProcessID %I64X ThreadID %I64X, updating GUID\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID, + ullThreadId); + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Updating existing AuthGroup GUID %wZ\n", + __FUNCTION__, + &uniGUID); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY); + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Updated existing AuthGroup GUID %wZ\n", + __FUNCTION__, + &uniGUID); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + try_return( ntStatus); + } + + pSIDEntryCB = (AFSSIDEntryCB *)AFSExAllocatePoolWithTag( NonPagedPool, + sizeof( AFSSIDEntryCB), + AFS_AG_ENTRY_CB_TAG); + + if( pSIDEntryCB == NULL) + { + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pSIDEntryCB, + sizeof( AFSSIDEntryCB)); + + pSIDEntryCB->TreeEntry.HashIndex = (ULONGLONG)ullTableHash; + + while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY); + + if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL) + { + pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB; + } + else + { + AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + &pSIDEntryCB->TreeEntry); + } + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Created new AuthGroup GUID %wZ SID %wZ Session %08lX\n", + __FUNCTION__, + &uniGUID, + &uniSIDString, + ulSessionId); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + +try_exit: + + if( uniCallerSID.Length > 0) + { + RtlFreeUnicodeString( &uniCallerSID); + } + } + + return ntStatus; +} + +// +// Given a SID and SessionId as input, returns the associated AuthGroup GUID. +// If SID or SessionId are not specified, the current process values are used. +// + +NTSTATUS +AFSQueryAuthGroup( IN AFSAuthGroupRequestCB *AuthGroup, + OUT GUID *AuthGroupGUID, + OUT ULONG_PTR *ReturnLength) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + UNICODE_STRING uniSIDString; + ULONG ulSIDHash = 0; + AFSSIDEntryCB *pSIDEntryCB = NULL; + ULONG ulSessionId = 0; + ULONGLONG ullTableHash = 0; + BOOLEAN bReleaseSID = FALSE; + UNICODE_STRING uniGUID; + BOOLEAN bImpersonation = FALSE; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + if( AuthGroup == NULL || + AuthGroup->SIDLength == 0) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s No SID specified, retrieving callers SID for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve callers SID for ProcessID %I64X Status %08lX\n", + __FUNCTION__, + ullProcessID, + ntStatus); + + try_return( ntStatus); + } + + bReleaseSID = TRUE; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved callers SID %wZ for ProcessID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID); + } + else + { + + uniSIDString.Length = AuthGroup->SIDLength; + uniSIDString.MaximumLength = uniSIDString.Length; + + uniSIDString.Buffer = AuthGroup->SIDString; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SID %wZ for ProcessID %I64X\n", + __FUNCTION__, + &uniSIDString, + ullProcessID); + } + + ntStatus = RtlHashUnicodeString( &uniSIDString, + TRUE, + HASH_STRING_ALGORITHM_DEFAULT, + &ulSIDHash); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to hash SID %wZ for ProcessID %I64X Status %08lX\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ntStatus); + + try_return( ntStatus); + } + + if( AuthGroup == NULL || + AuthGroup->SessionId == -1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s No SessionID specified, retrieving callers for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation); + + if( ulSessionId == (ULONG)-1) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to retrieve callers Session ID for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved callers SessionID %08lX for ProcessID %I64X\n", + __FUNCTION__, + ulSessionId, + ullProcessID); + } + else + { + ulSessionId = AuthGroup->SessionId; + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Using passed SessionID %08lX for ProcessID %I64X\n", + __FUNCTION__, + ulSessionId, + ullProcessID); + } + + ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); + + AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + (ULONGLONG)ullTableHash, + (AFSBTreeEntry **)&pSIDEntryCB); + + if( pSIDEntryCB == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate SID entry for SID %wZ SessionID %08lX ProcessID %I64X\n", + __FUNCTION__, + &uniSIDString, + ulSessionId, + ullProcessID); + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + try_return( ntStatus = STATUS_NOT_FOUND); + } + + RtlCopyMemory( AuthGroupGUID, + &pSIDEntryCB->AuthGroup, + sizeof( GUID)); + + *ReturnLength = sizeof( GUID); + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved AuthGroup GUID %wZ for ProcessID %I64X\n", + __FUNCTION__, + &uniGUID, + ullProcessID); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + +try_exit: + + if( bReleaseSID && + uniSIDString.Length > 0) + { + RtlFreeUnicodeString( &uniSIDString); + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp new file mode 100644 index 0000000000..13bb42f711 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSBTreeSupport.cpp @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSBTreeSupport.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSLocateHashEntry( IN AFSBTreeEntry *TopNode, + IN ULONGLONG HashIndex, + IN OUT AFSBTreeEntry **TreeEntry) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSBTreeEntry *pEntry = NULL; + AFSBTreeEntry *pCurrentEntry = NULL; + + pCurrentEntry = TopNode; + + __Enter + { + + // + // If the rootnode passed is null then the directory is empty + // + + if( TopNode == NULL) + { + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // + // If the requestor is looking for the root node itself, then return it. + // + + if( TopNode->HashIndex == HashIndex) + { + + *TreeEntry = TopNode; + + try_return( ntStatus); + } + + // + // Loop through the nodes in the tree + // + + while( pCurrentEntry != NULL) + { + + // + // Greater values are to the right link. + // + + if( HashIndex > pCurrentEntry->HashIndex) + { + + // + // Go to the next RIGHT entry, if there is one + // + + if( pCurrentEntry->rightLink != NULL) + { + + pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink; + } + else + { + + // + // Came to the end of the branch so bail + // + + pCurrentEntry = NULL; + + break; + } + } + else if( HashIndex < pCurrentEntry->HashIndex) + { + + // + // Go to the next LEFT entry, if one exists + // + + if( pCurrentEntry->leftLink != NULL) + { + + pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink; + } + else + { + + // + // End of the branch ... + // + + pCurrentEntry = NULL; + + break; + } + } + else + { + + // + // Found the entry. + // + + *TreeEntry = pCurrentEntry; + + break; + } + } + +try_exit: + + NOTHING; + } + + return ntStatus; +} + +NTSTATUS +AFSInsertHashEntry( IN AFSBTreeEntry *TopNode, + IN AFSBTreeEntry *FileIDEntry) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSBTreeEntry *pCurrentEntry = NULL; + + pCurrentEntry = TopNode; + + __Enter + { + + // + // If we have no root node then we can;t start the search. + // + + if( pCurrentEntry == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSInsertHashEntry Invalid root node\n"); + + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + // + // Locate the branch end to insert the node + // + + while( pCurrentEntry != NULL) + { + + // + // Greater vlued indices are to the right link + // + + if( FileIDEntry->HashIndex > pCurrentEntry->HashIndex) + { + + // + // Go to the next RIGHT entry, if it exists + // + + if( pCurrentEntry->rightLink != NULL) + { + pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink; + } + else + { + + // + // Located the end of the branch line so insert the node + // + + pCurrentEntry->rightLink = (void *)FileIDEntry; + + FileIDEntry->parentLink = (void *)pCurrentEntry; + + break; + } + } + else if( FileIDEntry->HashIndex < pCurrentEntry->HashIndex) + { + + // + // Go to the next LEFT entry, if it exists + // + + if( pCurrentEntry->leftLink != NULL) + { + pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink; + } + else + { + + // + // Located the branch line end so insert the node here + // + + pCurrentEntry->leftLink = (void *)FileIDEntry; + + FileIDEntry->parentLink = (void *)pCurrentEntry; + + break; + } + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSInsertHashEntry Attempt to re-insert a CRC %I64X\n", + FileIDEntry->HashIndex); + + ASSERT( FALSE); + + ntStatus = STATUS_UNSUCCESSFUL; + + break; + } + } + +try_exit: + + NOTHING; + } + + return ntStatus; +} + +NTSTATUS +AFSRemoveHashEntry( IN AFSBTreeEntry **TopNode, + IN AFSBTreeEntry *FileIDEntry) +{ + + NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; + AFSBTreeEntry *pRightNode = NULL; + AFSBTreeEntry *pLeftNode = NULL; + AFSBTreeEntry *pCurrentNode = NULL; + AFSBTreeEntry *pParentNode = NULL; + + pRightNode = (AFSBTreeEntry *)FileIDEntry->rightLink; + pLeftNode = (AFSBTreeEntry *)FileIDEntry->leftLink; + pParentNode = (AFSBTreeEntry *)FileIDEntry->parentLink; + + __Enter + { + + if( (pRightNode == NULL) && (pLeftNode == NULL)) + { + + if( pParentNode != NULL) + { + + if( pParentNode->leftLink == FileIDEntry) + { + + pParentNode->leftLink = NULL; + } + else + { + + pParentNode->rightLink = NULL; + } + } + else + { + + // + // Removing the top node + // + + *TopNode = NULL; + } + } + else + { + + if( pRightNode != NULL) + { + + if( pParentNode != NULL) + { + + // Replace the parent node where this entry was. + if( pParentNode->rightLink == FileIDEntry) + { + + pParentNode->rightLink = pRightNode; + } + else + { + + pParentNode->leftLink = pRightNode; + } + } + else + { + + *TopNode = pRightNode; + + pRightNode->parentLink = NULL; + } + + pRightNode->parentLink = pParentNode; + } + + if( pLeftNode != NULL) + { + + // To connect the left node, we must walk the chain of the + // right nodes left side until we reach the end. + // At the end attach the leftNode + if( pRightNode != NULL) + { + + pCurrentNode = pRightNode; + + while( pCurrentNode->leftLink != NULL) + { + + pCurrentNode = (AFSBTreeEntry *)pCurrentNode->leftLink; + } + + pCurrentNode->leftLink = pLeftNode; + + pLeftNode->parentLink = pCurrentNode; + } + else + { + + if( pParentNode != NULL) + { + + // This is where we have a left node with no right node. + // So, attach the left node to the parent of + // the removed nodes branch + if( pParentNode->rightLink == FileIDEntry) + { + + pParentNode->rightLink = pLeftNode; + } + else + { + + pParentNode->leftLink = pLeftNode; + } + + pLeftNode->parentLink = pParentNode; + } + else + { + + *TopNode = pLeftNode; + + pLeftNode->parentLink = NULL; + } + } + } + } + + // + // Cleanup the just removed node + // + + FileIDEntry->leftLink = NULL; + FileIDEntry->parentLink = NULL; + FileIDEntry->rightLink = NULL; + + ntStatus = STATUS_SUCCESS; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCleanup.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCleanup.cpp new file mode 100644 index 0000000000..5209873b0e --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSCleanup.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSCleanup.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSCleanup +// +// Description: +// +// This function is the IRP_MJ_CLEANUP dispatch handler +// +// Return: +// +// A status is returned for the handling of this request +// + +NTSTATUS +AFSCleanup( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + // + // Set some initial variables to make processing easier + // + + if( DeviceObject == AFSDeviceObject) + { + + if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_CONTROL_INSTANCE)) + { + + // + // This is the process which was registered for the callback pool so cleanup the pool + // + + AFSCleanupIrpPool(); + } + + if( FlagOn( (ULONG_PTR)pIrpSp->FileObject->FsContext, AFS_REDIRECTOR_INSTANCE)) + { + + // + // Close the redirector + // + + AFSCloseRedirector(); + } + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + ntStatus = AFSCommonCleanup( DeviceObject, + Irp); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSCleanup\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSCommonCleanup( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + PFILE_OBJECT pFileObject = NULL; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + BOOLEAN bCompleteRequest = TRUE; + + __Enter + { + + // + // Set some initial variables to make processing easier + // + + pFileObject = pIrpSp->FileObject; + + if( pIrpSp->FileObject->FsContext == NULL) + { + + // + // Root open + // + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus == STATUS_PENDING) + { + bCompleteRequest = FALSE; + } + + try_return( ntStatus); + } + + bCompleteRequest = FALSE; + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + if( bCompleteRequest) + { + + if( pFileObject != NULL) + { + + // + // Setup the fileobject flags to indicate cleanup is complete. + // + + SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE); + } + + // + // Complete the request + // + + AFSCompleteRequest( Irp, ntStatus); + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSClose.cpp b/src/WINNT/afsrdr/kernel/fs/AFSClose.cpp new file mode 100644 index 0000000000..159dd115f4 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSClose.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSClose.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSClose +// +// Description: +// +// This function is the IRP_MJ_CLOSE dispatch handler +// +// Return: +// +// A status is returned for the handling of this request +// + +NTSTATUS +AFSClose( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + ntStatus = AFSCommonClose( DeviceObject, + Irp); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSClose\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSCommonClose( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG ulRequestType = 0; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + AFSDeviceExt *pDeviceExt = NULL; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + if( pIrpSp->FileObject->FsContext == NULL) + { + + AFSCompleteRequest( Irp, ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp new file mode 100644 index 0000000000..f803c7ef38 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSCommSupport.cpp @@ -0,0 +1,1591 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSCommSupport.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSReleaseFid( IN AFSFileID *FileId) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __Enter + { + + ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID, + 0, + NULL, + NULL, + FileId, + NULL, + 0, + NULL, + NULL); + } + + return ntStatus; +} + +NTSTATUS +AFSProcessRequest( IN ULONG RequestType, + IN ULONG RequestFlags, + IN GUID *AuthGroup, + IN PUNICODE_STRING FileName, + IN AFSFileID *FileId, + IN void *Data, + IN ULONG DataLength, + IN OUT void *ResultBuffer, + IN OUT PULONG ResultBufferLength) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSPoolEntry stPoolEntry, *pPoolEntry = NULL; + AFSCommSrvcCB *pCommSrvc = NULL; + BOOLEAN bReleasePool = FALSE; + AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + BOOLEAN bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS); + ULONG ulPoolEntryLength = 0; + BOOLEAN bDecrementCount = FALSE; + + __try + { + + if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) + { + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1) + { + KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent); + } + + bDecrementCount = TRUE; + + pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB; + + // + // Grab the pool resource and check the state + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->IrpPoolLock, + TRUE); + + bReleasePool = TRUE; + + if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) + { + + // + // Pool not running so bail. + // + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + // + // If this is an async request we need to allocate a pool entry for the request + // + + pPoolEntry = &stPoolEntry; + + if( !bWait) + { + + ASSERT( ResultBuffer == NULL); + + ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength); + + if( FileName != NULL) + { + + ulPoolEntryLength += FileName->Length; + } + + pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool, + ulPoolEntryLength, + AFS_POOL_ENTRY_TAG); + + if( pPoolEntry == NULL) + { + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pPoolEntry, + ulPoolEntryLength); + + pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry)); + + pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength); + } + else + { + + RtlZeroMemory( pPoolEntry, + sizeof( AFSPoolEntry)); + + KeInitializeEvent( &pPoolEntry->Event, + NotificationEvent, + FALSE); + } + + pPoolEntry->RequestType = RequestType; + + pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++; + + pPoolEntry->RequestFlags = RequestFlags; + + pPoolEntry->ResultBufferLength = 0; + + if( FileId != NULL) + { + + pPoolEntry->FileId = *FileId; + } + + pPoolEntry->FileName.Length = 0; + + if( FileName != NULL) + { + + if( bWait) + { + + pPoolEntry->FileName = *FileName; + } + else + { + + pPoolEntry->FileName.Length = FileName->Length; + + pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length; + + RtlCopyMemory( pPoolEntry->FileName.Buffer, + FileName->Buffer, + pPoolEntry->FileName.Length); + } + } + + // + // Move in the data if there is some + // + + pPoolEntry->DataLength = DataLength; + + if( Data != NULL && + DataLength > 0) + { + + if( bWait) + { + + pPoolEntry->Data = Data; + } + else + { + + RtlCopyMemory( pPoolEntry->Data, + Data, + DataLength); + } + } + + pPoolEntry->ResultBuffer = ResultBuffer; + + pPoolEntry->ResultBufferLength = ResultBufferLength; + + // + // Store off the auth group + // + + if( AuthGroup == NULL) + { + AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(), + (ULONGLONG)PsGetCurrentThreadId(), + &pPoolEntry->AuthGroup); + } + else + { + RtlCopyMemory( &pPoolEntry->AuthGroup, + AuthGroup, + sizeof( GUID)); + } + + if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup)) + { + SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG); + } + + if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup)) + { + AFSDbgLogMsg( 0, + 0, + "AFSProcessRequest NoPAG Auth Group %08lX\n", + PsGetCurrentThread()); + } + + // + // Indicate the type of process + // + +#ifdef AMD64 + + if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId())) + { + SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64); + } + +#endif + + // + // Insert the entry into the request pool + // + + ntStatus = AFSInsertRequest( pCommSrvc, + pPoolEntry); + + if( !NT_SUCCESS( ntStatus)) + { + + if( !bWait) + { + + ExFreePool( pPoolEntry); + } + + try_return( ntStatus); + } + + // + // Drop the lock on the pool prior to waiting + // + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + bReleasePool = FALSE; + + // + // Wait for the result if this is NOT an asynchronous request + // + + if( bWait) + { + + // + // Wait for the result of the request. We specify no timeout ... + // + + ntStatus = KeWaitForSingleObject( &pPoolEntry->Event, + Executive, + KernelMode, + FALSE, + NULL); + + // + // Process the result of the request + // + + if( ntStatus == STATUS_SUCCESS) + { + + ntStatus = pPoolEntry->ResultStatus; + } + else + { + + ntStatus = STATUS_DEVICE_NOT_READY; + } + } + +try_exit: + + if( bReleasePool) + { + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + } + + if( bDecrementCount && + InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0) + { + KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent, + 0, + FALSE); + } + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation())) + { + + if( bReleasePool) + { + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + } + + if( bDecrementCount && + InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0) + { + KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent, + 0, + FALSE); + } + + if ( ntStatus == STATUS_SUCCESS) + { + + ntStatus = STATUS_UNSUCCESSFUL; + } + } + + return ntStatus; +} + +NTSTATUS +AFSProcessControlRequest( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + PIO_STACK_LOCATION pIrpSp; + ULONG ulIoControlCode; + BOOLEAN bCompleteRequest = TRUE; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONG ulBytesProcessed = 0; + + __try + { + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode; + + switch( ulIoControlCode) + { + + case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE: + { + + // + // Go intialize the pool + // + + ntStatus = AFSInitIrpPool(); + + if( !NT_SUCCESS( ntStatus)) + { + + // + // Don't initialize + // + + break; + } + + // + // Tag this instance as the one to close the irp pool when it is closed + // + + pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE); + + break; + } + + case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE: + { + + AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer; + + // + // Extract off the passed in information which contains the + // cache file parameters + // + + if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) + + pRedirInitInfo->CacheFileNameLength) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + // + // Initialize the Redirector device + // + + ntStatus = AFSInitializeRedirector( pRedirInitInfo); + + if( !NT_SUCCESS( ntStatus)) + { + + break; + } + + // + // Stash away context so we know the instance used to initialize the redirector + // + + pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE); + + break; + } + + case IOCTL_AFS_PROCESS_IRP_REQUEST: + { + + ntStatus = AFSProcessIrpRequest( Irp); + + break; + } + + case IOCTL_AFS_PROCESS_IRP_RESULT: + { + + ntStatus = AFSProcessIrpResult( Irp); + + break; + } + + case IOCTL_AFS_SYSNAME_NOTIFICATION: + { + + AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pSysNameInfo == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSSetSysNameInformation( pSysNameInfo, + pIrpSp->Parameters.DeviceIoControl.InputBufferLength); + + break; + } + + case IOCTL_AFS_CONFIGURE_DEBUG_TRACE: + { + + AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pTraceInfo == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSConfigureTrace( pTraceInfo); + + break; + } + + case IOCTL_AFS_GET_TRACE_BUFFER: + { + + if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, + Irp->AssociatedIrp.SystemBuffer, + &Irp->IoStatus.Information); + + break; + } + + case IOCTL_AFS_FORCE_CRASH: + { + +#if DBG + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH)) + { + + KeBugCheck( (ULONG)-1); + } +#endif + + break; + } + +#ifdef NOT_IMPLEMENTED + case IOCTL_AFS_LOAD_LIBRARY: + { + + AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer; + UNICODE_STRING uniServicePath; + + if( pLoadLib == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) + + pLoadLib->LibraryServicePathLength) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + uniServicePath.Length = pLoadLib->LibraryServicePathLength; + uniServicePath.MaximumLength = uniServicePath.Length; + + uniServicePath.Buffer = pLoadLib->LibraryServicePath; + + if( uniServicePath.Length == 0) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSLoadLibrary( pLoadLib->Flags, + &uniServicePath); + + if( NT_SUCCESS( ntStatus)) + { + + // + // Intialize the library + // + + ntStatus = AFSInitializeLibrary( NULL, + FALSE); + } + + break; + } + + case IOCTL_AFS_UNLOAD_LIBRARY: + { + + // + // Try to unload the library we currently have in place + // + + ntStatus = AFSUnloadLibrary( FALSE); + + break; + } +#endif + + case IOCTL_AFS_SHUTDOWN: + { + + ntStatus = AFSShutdownRedirector(); + + break; + } + + case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET: + { + + + AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pAuthGroupRequestCB == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB); + + break; + } + + case IOCTL_AFS_AUTHGROUP_QUERY: + { + + ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer, + pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, + &Irp->IoStatus.Information); + + break; + } + + case IOCTL_AFS_AUTHGROUP_SET: + { + + AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pAuthGroupRequestCB == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB); + + break; + } + + case IOCTL_AFS_AUTHGROUP_RESET: + { + + AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pAuthGroupRequestCB == NULL || + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB); + + break; + } + + case IOCTL_AFS_AUTHGROUP_LOGON_CREATE: + case IOCTL_AFS_AUTHGROUP_SID_CREATE: + { + + AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer; + + if( pAuthGroupRequestCB != NULL && + pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB)) + { + + ntStatus = STATUS_INVALID_PARAMETER; + + break; + } + + ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB, + ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE); + + break; + } + + case IOCTL_AFS_AUTHGROUP_SID_QUERY: + { + + AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL; + + if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID)) + { + ntStatus = STATUS_INVALID_PARAMETER; + break; + } + + if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB)) + { + pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer; + } + + ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB, + (GUID *)Irp->AssociatedIrp.SystemBuffer, + &Irp->IoStatus.Information); + + break; + } + + default: + { + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus == STATUS_PENDING) + { + bCompleteRequest = FALSE; + } + + break; + } + + bCompleteRequest = FALSE; + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + + break; + } + } + +//try_exit: + + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation())) + { + + ntStatus = STATUS_UNSUCCESSFUL; + } + + if( bCompleteRequest) + { + + Irp->IoStatus.Status = ntStatus; + + AFSCompleteRequest( Irp, + ntStatus); + } + + return ntStatus; +} + +NTSTATUS +AFSInitIrpPool() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSCommSrvcCB *pCommSrvc = NULL; + BOOLEAN bReleasePools = FALSE; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; + + // + // Whenever we change state we must grab both pool locks. On the checking of the state + // within the processing routines for these respective pools, we only grab one lock to + // minimize serialization. The ordering is always the Irp pool then the result pool + // locks. We also do this in the tear down of the pool + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->IrpPoolLock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->ResultPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->ResultPoolLock, + TRUE); + + bReleasePools = TRUE; + + // + // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we + // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we + // shouldn't be getting this request ... + // + + if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE) + { + + // + // We have already been activated so just fail this request + // + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE) + { + + // + // The pool is currently INACTIVE so start it up and ready it to + // receive irp requests + // + + pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE; + + pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess(); + + try_return( ntStatus = STATUS_SUCCESS); + } + else + { + + // + // The pool is in some mixed state, fail the request. + // + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + +try_exit: + + if( bReleasePools) + { + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + AFSReleaseResource( &pCommSrvc->ResultPoolLock); + } + } + + return ntStatus; +} + +void +AFSCleanupIrpPool() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB; + + __Enter + { + + // + // When we change the state, grab both pool locks exclusive. The order is always the + // Irp pool then the result pool lock + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->IrpPoolLock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->ResultPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->ResultPoolLock, + TRUE); + + // + // Indicate we are pending stop + // + + pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE; + + // + // Set the event to release any waiting workers + // + + KeSetEvent( &pCommSrvc->IrpPoolHasEntries, + 0, + FALSE); + + KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries, + 0, + FALSE); + + // + // Go through the pool entries and free up the structures. + // + + pEntry = pCommSrvc->RequestPoolHead; + + while( pEntry != NULL) + { + + pNextEntry = pEntry->fLink; + + if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS)) + { + + // + // Here we need to complete the irp, cancelled, and delete the data block + // + + pEntry->ResultStatus = STATUS_CANCELLED; + + KeSetEvent( &pEntry->Event, + 0, + FALSE); + } + else + { + + ExFreePool( pEntry); + } + + pEntry = pNextEntry; + } + + // + // Cleanup the control structure for the request pool + // + + pCommSrvc->RequestPoolHead = NULL; + + pCommSrvc->RequestPoolTail = NULL; + + pCommSrvc->IrpPoolRequestIndex = 1; + + KeClearEvent( &pCommSrvc->IrpPoolHasEntries); + + KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries); + + // + // Release the irp pool lock. + // + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + // + // Go through the result pool entries and free up the structures. + // + + pEntry = pCommSrvc->ResultPoolHead; + + while( pEntry != NULL) + { + + pNextEntry = pEntry->fLink; + + pEntry->ResultStatus = STATUS_CANCELLED; + + // + // Here we will set the event of the requestor and let the blocked thread + // free the data block + // + + KeSetEvent( &pEntry->Event, + 0, + FALSE); + + // + // Go onto the next entry + // + + pEntry = pNextEntry; + } + + // + // Cleanup the control structure for the result pool + // + + pCommSrvc->ResultPoolHead = NULL; + + pCommSrvc->ResultPoolTail = NULL; + + // + // Release the result pool lock. + // + + AFSReleaseResource( &pCommSrvc->ResultPoolLock); + } + + return; +} + +NTSTATUS +AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc, + IN AFSPoolEntry *Entry) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", + &CommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &CommSrvc->IrpPoolLock, + TRUE); + + if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE) + { + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + if( CommSrvc->RequestPoolHead == NULL) + { + + CommSrvc->RequestPoolHead = Entry; + } + else + { + + CommSrvc->RequestPoolTail->fLink = Entry; + + Entry->bLink = CommSrvc->RequestPoolTail; + } + + CommSrvc->RequestPoolTail = Entry; + + if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS) + { + + KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries, + 0, + FALSE); + } + else + { + + KeSetEvent( &CommSrvc->IrpPoolHasEntries, + 0, + FALSE); + } + + InterlockedIncrement( &CommSrvc->QueueCount); + +try_exit: + + AFSReleaseResource( &CommSrvc->IrpPoolLock); + } + + return ntStatus; +} + +NTSTATUS +AFSProcessIrpRequest( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + AFSCommSrvcCB *pCommSrvc = NULL; + AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL; + AFSCommRequest *pRequest = NULL; + BOOLEAN bReleaseRequestThread = FALSE; + + __Enter + { + + pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; + + pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->IrpPoolLock, + TRUE); + + if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) + { + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + // + // Is this a dedicated flush thread? + // + + if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD)) + { + + bReleaseRequestThread = TRUE; + } + + // + // Wait on the 'have items' event until we can retrieve an item + // + + while( TRUE) + { + + if( bReleaseRequestThread) + { + + ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries, + UserRequest, + UserMode, + TRUE, + NULL); + } + else + { + + ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasEntries, + UserRequest, + UserMode, + TRUE, + NULL); + } + + if( ntStatus != STATUS_SUCCESS) + { + + ntStatus = STATUS_DEVICE_NOT_READY; + + break; + } + + // + // Grab the lock on the request pool + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n", + &pCommSrvc->IrpPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->IrpPoolLock, + TRUE); + + if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE) + { + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + // + // If this is a dedicated flush thread only look for a flush request in the queue + // + + if( bReleaseRequestThread) + { + + pEntry = pCommSrvc->RequestPoolHead; + + pPrevEntry = NULL; + + while( pEntry != NULL) + { + + if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS) + { + + if( pPrevEntry == NULL) + { + + pCommSrvc->RequestPoolHead = pEntry->fLink; + + if( pCommSrvc->RequestPoolHead == NULL) + { + + pCommSrvc->RequestPoolTail = NULL; + } + } + else + { + + pPrevEntry->fLink = pEntry->fLink; + + if( pPrevEntry->fLink == NULL) + { + + pCommSrvc->RequestPoolTail = pPrevEntry; + } + } + + break; + } + + pPrevEntry = pEntry; + + pEntry = pEntry->fLink; + } + + if( pCommSrvc->RequestPoolHead == NULL) + { + + KeClearEvent( &pCommSrvc->IrpPoolHasEntries); + } + + if( pEntry == NULL) + { + + KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries); + } + + // + // And release the request pool lock + // + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + } + else + { + + pEntry = pCommSrvc->RequestPoolHead; + + if( pEntry != NULL) + { + + pCommSrvc->RequestPoolHead = pEntry->fLink; + + pEntry->bLink = NULL; + + if( pCommSrvc->RequestPoolHead == NULL) + { + + pCommSrvc->RequestPoolTail = NULL; + } + } + else + { + + KeClearEvent( &pCommSrvc->IrpPoolHasEntries); + } + + // + // And release the request pool lock + // + + AFSReleaseResource( &pCommSrvc->IrpPoolLock); + } + + // + // Insert the entry into the result pool, if we have one + // + + if( pEntry != NULL) + { + + // + // Move the request data into the passed in buffer + // + + ASSERT( sizeof( AFSCommRequest) + + pEntry->FileName.Length + + pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength); + + RtlCopyMemory( &pRequest->AuthGroup, + &pEntry->AuthGroup, + sizeof( GUID)); + + pRequest->FileId = pEntry->FileId; + + pRequest->RequestType = pEntry->RequestType; + + pRequest->RequestIndex = pEntry->RequestIndex; + + pRequest->RequestFlags = pEntry->RequestFlags; + + pRequest->NameLength = pEntry->FileName.Length; + + pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount); + + if( pRequest->NameLength > 0) + { + + RtlCopyMemory( pRequest->Name, + pEntry->FileName.Buffer, + pRequest->NameLength); + } + + pRequest->DataOffset = 0; + + pRequest->DataLength = pEntry->DataLength; + + if( pRequest->DataLength > 0) + { + + pRequest->DataOffset = pEntry->FileName.Length; + + RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset), + pEntry->Data, + pRequest->DataLength); + } + + pRequest->ResultBufferLength = 0; + + if( pEntry->ResultBufferLength != NULL) + { + + pRequest->ResultBufferLength = *(pEntry->ResultBufferLength); + } + + Irp->IoStatus.Information = sizeof( AFSCommRequest) + + pEntry->FileName.Length + + pEntry->DataLength; + + // + // If this is a synchronous request then move the request into the + // result pool + // + + if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS)) + { + + pEntry->fLink = NULL; + pEntry->bLink = NULL; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->ResultPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->ResultPoolLock, + TRUE); + + if( pCommSrvc->ResultPoolHead == NULL) + { + + pCommSrvc->ResultPoolHead = pEntry; + } + else + { + + pCommSrvc->ResultPoolTail->fLink = pEntry; + + pEntry->bLink = pCommSrvc->ResultPoolTail; + } + + pCommSrvc->ResultPoolTail = pEntry; + + AFSReleaseResource( &pCommSrvc->ResultPoolLock); + } + else + { + + // + // Free up the pool entry + // + + ExFreePool( pEntry); + } + + break; + } + } + +try_exit: + + NOTHING; + } + + return ntStatus; +} + +NTSTATUS +AFSProcessIrpResult( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + AFSCommSrvcCB *pCommSrvc = NULL; + AFSPoolEntry *pCurrentEntry = NULL; + AFSCommResult *pResult = NULL; + ULONG ulCopyLen = 0; + + __Enter + { + + pCommSrvc = &pDevExt->Specific.Control.CommServiceCB; + + // + // Get the request for the incoming result + // + + pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer; + + if( pResult == NULL) + { + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // + // Go look for our entry + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n", + &pCommSrvc->ResultPoolLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pCommSrvc->ResultPoolLock, + TRUE); + + pCurrentEntry = pCommSrvc->ResultPoolHead; + + while( pCurrentEntry != NULL) + { + + if( pCurrentEntry->RequestIndex == pResult->RequestIndex) + { + + // + // Found the entry so remove it from the queue + // + + if( pCurrentEntry->bLink == NULL) + { + + // + // At the head of the list + // + + pCommSrvc->ResultPoolHead = pCurrentEntry->fLink; + + if( pCommSrvc->ResultPoolHead != NULL) + { + + pCommSrvc->ResultPoolHead->bLink = NULL; + } + } + else + { + + pCurrentEntry->bLink->fLink = pCurrentEntry->fLink; + } + + if( pCurrentEntry->fLink == NULL) + { + + pCommSrvc->ResultPoolTail = pCurrentEntry->bLink; + + if( pCommSrvc->ResultPoolTail != NULL) + { + + pCommSrvc->ResultPoolTail->fLink = NULL; + } + } + else + { + + pCurrentEntry->fLink->bLink = pCurrentEntry->bLink; + } + + break; + } + + pCurrentEntry = pCurrentEntry->fLink; + } + + AFSReleaseResource( &pCommSrvc->ResultPoolLock); + + if( pCurrentEntry == NULL) + { + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // + // OK, move in the result information + // + + pCurrentEntry->ResultStatus = pResult->ResultStatus; + + if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS || + pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) && + pCurrentEntry->ResultBufferLength != NULL && + pCurrentEntry->ResultBuffer != NULL) + { + + ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength)); + + ulCopyLen = pResult->ResultBufferLength; + + if( ulCopyLen > *(pCurrentEntry->ResultBufferLength)) + { + ulCopyLen = *(pCurrentEntry->ResultBufferLength); + } + + *(pCurrentEntry->ResultBufferLength) = ulCopyLen; + + if( pResult->ResultBufferLength > 0) + { + + RtlCopyMemory( pCurrentEntry->ResultBuffer, + pResult->ResultData, + ulCopyLen); + } + } + + KeSetEvent( &pCurrentEntry->Event, + 0, + FALSE); + +try_exit: + + if( !NT_SUCCESS( ntStatus)) + { + + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp b/src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp new file mode 100644 index 0000000000..2401b53663 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSCreate.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSCreate.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSCreate +// +// Description: +// +// This function is the dispatch handler for the IRP_MJ_CREATE requests. It makes the determination to +// which interface this request is destined. +// +// Return: +// +// A status is returned for the function. The Irp completion processing is handled in the specific +// interface handler. +// + +NTSTATUS +AFSCreate( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = AFSControlDeviceCreate( Irp); + + try_return( ntStatus); + } + + ntStatus = AFSCommonCreate( DeviceObject, + Irp); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSCreate\n"); + + ntStatus = STATUS_ACCESS_DENIED; + } + + return ntStatus; +} + +NTSTATUS +AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + FILE_OBJECT *pFileObject = NULL; + IO_STACK_LOCATION *pIrpSp; + AFSDeviceExt *pDeviceExt = NULL; + AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + GUID *pAuthGroup = NULL; + UNICODE_STRING uniGUIDString; + + __Enter + { + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + pFileObject = pIrpSp->FileObject; + + uniGUIDString.Buffer = NULL; + uniGUIDString.Length = 0; + uniGUIDString.MaximumLength = 0; + + // + // Validate the process entry + // + + pAuthGroup = AFSValidateProcessEntry(); + + if( pAuthGroup != NULL) + { + + RtlStringFromGUID( *pAuthGroup, + &uniGUIDString); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s (%08lX) Located AuthGroup %wZ after validation\n", + __FUNCTION__, + Irp, + &uniGUIDString); + + } + else + { + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s (%08lX) Failed to locate AuthGroup\n", + __FUNCTION__, + Irp); + } + + // + // Root open? + // + + if( pFileObject == NULL || + pFileObject->FileName.Buffer == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSCommonCreate (%08lX) Processing volume open request\n", + Irp); + + ntStatus = AFSOpenRedirector( Irp); + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDevExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + if ( pFileObject) { + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s (%08lX) File \"%wZ\" AuthGroup '%wZ' ntStatus %08lX\n", + __FUNCTION__, + Irp, + &pFileObject->FileName, + &uniGUIDString, + ntStatus); + } + + if( uniGUIDString.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUIDString); + } + } + + return ntStatus; +} + +NTSTATUS +AFSControlDeviceCreate( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __Enter + { + + // + // For now, jsut let the open happen + // + + Irp->IoStatus.Information = FILE_OPENED; + + AFSCompleteRequest( Irp, ntStatus); + } + + return ntStatus; +} + +NTSTATUS +AFSOpenRedirector( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + FILE_OBJECT *pFileObject = NULL; + IO_STACK_LOCATION *pIrpSp; + + __Enter + { + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + pFileObject = pIrpSp->FileObject; + + // + // Return the open result for this file + // + + Irp->IoStatus.Information = FILE_OPENED; + + Irp->IoStatus.Status = ntStatus; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSData.cpp b/src/WINNT/afsrdr/kernel/fs/AFSData.cpp new file mode 100644 index 0000000000..4fd9894e44 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSData.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSData.cpp +// + +#define NO_EXTERN + +#include "AFSCommon.h" + +extern "C" { + +PDRIVER_OBJECT AFSDriverObject = NULL; + +PDEVICE_OBJECT AFSDeviceObject = NULL; + +PDEVICE_OBJECT AFSRDRDeviceObject = NULL; + +FAST_IO_DISPATCH AFSFastIoDispatch; + +UNICODE_STRING AFSRegistryPath; + +ULONG AFSDebugFlags = 0; + +ULONG AFSTraceLevel = 0; + +ULONG AFSTraceComponent = 0; + +HANDLE AFSSysProcess = NULL; + +HANDLE AFSMUPHandle = NULL; + +UNICODE_STRING AFSServerName; + +UNICODE_STRING AFSGlobalRootName; + +CACHE_MANAGER_CALLBACKS AFSCacheManagerCallbacks; + +// +// Max Length IO (Mb) +// +ULONG AFSMaxDirectIo = 0; + +// +// Maximum dirtiness that a file can get +// +ULONG AFSMaxDirtyFile = 0; + +// +// Dbg log information +// + +ERESOURCE AFSDbgLogLock; + +ULONG AFSDbgLogRemainingLength = 0; + +char *AFSDbgCurrentBuffer = NULL; + +char *AFSDbgBuffer = NULL; + +ULONG AFSDbgLogCounter = 0; + +ULONG AFSDbgBufferLength = 0; + +ULONG AFSDbgLogFlags = 0; + +PAFSDumpTraceFiles AFSDumpTraceFilesFnc = AFSDumpTraceFiles; + +UNICODE_STRING AFSDumpFileLocation; + +KEVENT AFSDumpFileEvent; + +UNICODE_STRING AFSDumpFileName; + +void *AFSDumpBuffer = NULL; + +ULONG AFSDumpBufferLength = 0; + +// +// Authentication group information +// + +ULONG AFSAuthGroupFlags = 0; + +GUID AFSActiveAuthGroup; + +GUID AFSNoPAGAuthGroup; + +PAFSSetInformationToken AFSSetInformationToken = NULL; + +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp new file mode 100644 index 0000000000..31c29572fa --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSDevControl.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSDevControl.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSDevControl +// +// Description: +// +// This is the dipatch handler for the IRP_MJ_DEVICE_CONTROL requests. +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSDevControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = AFSProcessControlRequest( Irp); + + try_return( ntStatus); + } + + ntStatus = AFSRDRDeviceControl( DeviceObject, + Irp); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSDevControl\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp new file mode 100644 index 0000000000..c4e2ff6dc3 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSDirControl.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSDirControl.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSDirControl +// +// Description: +// +// This function is the IRP_MJ_DIRECTORY_CONTROL dispatch handler +// +// Return: +// +// A status is returned for the handling of this request +// + +NTSTATUS +AFSDirControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG ulRequestType = 0; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSDirControl\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSEa.cpp b/src/WINNT/afsrdr/kernel/fs/AFSEa.cpp new file mode 100644 index 0000000000..adf90666ca --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSEa.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSEa.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSQueryEA +// +// Description: +// +// This function is the dipatch handler for the IRP_MJ_QUERY_EA request +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSQueryEA( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSQueryEA\n"); + } + + return ntStatus; +} + +// +// Function: AFSSetEA +// +// Description: +// +// This function is the dipatch handler for the IRP_MJ_SET_EA request +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSSetEA( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_EAS_NOT_SUPPORTED; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSSetEA\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp new file mode 100644 index 0000000000..d2a486800e --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSFSControl.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSFSControl.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSFSControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STACK_LOCATION *pIrpSp; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSFSControl\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp new file mode 100644 index 0000000000..9fe9436906 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSFastIoSupport.cpp @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSFastIoSupport.cpp +// + +#include "AFSCommon.h" + +BOOLEAN +AFSFastIoCheckIfPossible( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN BOOLEAN CheckForReadOperation, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoRead( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoWrite( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoQueryBasicInfo( IN struct _FILE_OBJECT *FileObject, + IN BOOLEAN Wait, + OUT PFILE_BASIC_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoQueryStandardInfo( IN struct _FILE_OBJECT *FileObject, + IN BOOLEAN Wait, + OUT PFILE_STANDARD_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoLock( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS ProcessId, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoUnlockSingle( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS ProcessId, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoUnlockAll( IN struct _FILE_OBJECT *FileObject, + IN PEPROCESS ProcessId, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoUnlockAllByKey( IN struct _FILE_OBJECT *FileObject, + IN PVOID ProcessId, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoDevCtrl( IN struct _FILE_OBJECT *FileObject, + IN BOOLEAN Wait, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength, + IN ULONG IoControlCode, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +void +AFSFastIoAcquireFile( IN struct _FILE_OBJECT *FileObject) +{ + + AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSFastIoAcquireFile Acquiring Fcb lock %08lX EXCL %08lX\n", + &pFcb->NPFcb->Resource, + PsGetCurrentThread()); + + AFSAcquireExcl( &pFcb->NPFcb->Resource, + TRUE); + + return; +} + +void +AFSFastIoReleaseFile( IN struct _FILE_OBJECT *FileObject) +{ + + AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext; + + if( ExIsResourceAcquiredExclusiveLite( &pFcb->NPFcb->Resource)) + { + + AFSReleaseResource( &pFcb->NPFcb->Resource); + } + + return; +} + +VOID +AFSFastIoDetachDevice( IN struct _DEVICE_OBJECT *SourceDevice, + IN struct _DEVICE_OBJECT *TargetDevice) +{ + + return; +} + +BOOLEAN +AFSFastIoQueryNetworkOpenInfo( IN struct _FILE_OBJECT *FileObject, + IN BOOLEAN Wait, + OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, + OUT struct _IO_STATUS_BLOCK *IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoMdlRead( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoMdlReadComplete( IN struct _FILE_OBJECT *FileObject, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoPrepareMdlWrite( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoMdlWriteComplete( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +NTSTATUS +AFSFastIoAcquireForModWrite( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT struct _ERESOURCE **ResourceToRelease, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + NTSTATUS ntStatus = STATUS_FILE_LOCK_CONFLICT; + AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext; + + __Enter + { + + if( AFSAcquireExcl( &pFcb->NPFcb->Resource, + BooleanFlagOn( FileObject->Flags, FO_SYNCHRONOUS_IO))) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSFastIoAcquireForModWrite Acquired Fcb lock %08lX EXCL %08lX\n", + &pFcb->NPFcb->Resource, + PsGetCurrentThread()); + + ntStatus = STATUS_SUCCESS; + + *ResourceToRelease = &pFcb->NPFcb->Resource; + } + } + + return ntStatus; +} + +NTSTATUS +AFSFastIoReleaseForModWrite( IN struct _FILE_OBJECT *FileObject, + IN struct _ERESOURCE *ResourceToRelease, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + AFSReleaseResource( ResourceToRelease); + + return ntStatus; +} + +NTSTATUS +AFSFastIoAcquireForCCFlush( IN struct _FILE_OBJECT *FileObject, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + NTSTATUS ntStatus = STATUS_FILE_LOCK_CONFLICT; + AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext; + + if( !ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->Resource)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSFastIoAcquireForCCFlush Acquiring Fcb lock %08lX EXCL %08lX\n", + &pFcb->NPFcb->Resource, + PsGetCurrentThread()); + + AFSAcquireExcl( &pFcb->NPFcb->Resource, + TRUE); + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSFastIoAcquireForCCFlush Acquiring Fcb lock %08lX SHARED %08lX\n", + &pFcb->NPFcb->Resource, + PsGetCurrentThread()); + + AFSAcquireShared( &pFcb->NPFcb->Resource, + TRUE); + } + + ntStatus = STATUS_SUCCESS; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSFastIoAcquireForCCFlush Acquiring Fcb PagingIo lock %08lX SHARED %08lX\n", + &pFcb->NPFcb->PagingResource, + PsGetCurrentThread()); + + AFSAcquireShared( &pFcb->NPFcb->PagingResource, + TRUE); + + // + // Set the TopLevelIrp field for this caller + // + + if( IoGetTopLevelIrp() == NULL) + { + + IoSetTopLevelIrp( (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + } + + return ntStatus; +} + +NTSTATUS +AFSFastIoReleaseForCCFlush( IN struct _FILE_OBJECT *FileObject, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSFcb *pFcb = (AFSFcb *)FileObject->FsContext; + + if( IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) + { + + IoSetTopLevelIrp( NULL); + } + + if( ExIsResourceAcquiredExclusiveLite( &pFcb->NPFcb->Resource) || + ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->Resource)) + { + + AFSReleaseResource( &pFcb->NPFcb->Resource); + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSFastIoReleaseForCCFlush Called for non-acquired main resource Fcb\n"); + } + + if( ExIsResourceAcquiredSharedLite( &pFcb->NPFcb->PagingResource)) + { + + AFSReleaseResource( &pFcb->NPFcb->PagingResource); + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSFastIoReleaseForCCFlush Called for non-acquired paging resource Fcb\n"); + } + + return ntStatus; +} + +BOOLEAN +AFSFastIoReadCompressed( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoWriteCompressed( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoMdlReadCompleteCompressed( IN struct _FILE_OBJECT *FileObject, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoMdlWriteCompleteCompressed( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} + +BOOLEAN +AFSFastIoQueryOpen( IN struct _IRP *Irp, + OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + IN struct _DEVICE_OBJECT *DeviceObject) +{ + + BOOLEAN bStatus = FALSE; + + return bStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp new file mode 100644 index 0000000000..74bbad3176 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSFileInfo.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSFileInfo.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSQueryFileInfo +// +// Description: +// +// This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSQueryFileInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + if( pIrpSp->FileObject->FsContext == NULL) + { + + // + // Root open + // + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSQueryFileInfo\n"); + + ntStatus = STATUS_UNSUCCESSFUL; + } + + return ntStatus; +} + +// +// Function: AFSSetFileInfo +// +// Description: +// +// This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSSetFileInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + if( pIrpSp->FileObject->FsContext == NULL) + { + + // + // Root open + // + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSSetFileInfo\n"); + + ntStatus = STATUS_UNSUCCESSFUL; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp b/src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp new file mode 100644 index 0000000000..aecc04c2a5 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSFlushBuffers.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSFlushBuffers.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSFlushBuffers( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + if( DeviceObject == AFSDeviceObject) + { + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + AFSCompleteRequest( Irp, + ntStatus); + + try_return( ntStatus); + } + + // + // Check the state of the library + // + + ntStatus = AFSCheckLibraryState( Irp); + + if( !NT_SUCCESS( ntStatus) || + ntStatus == STATUS_PENDING) + { + + if( ntStatus != STATUS_PENDING) + { + AFSCompleteRequest( Irp, ntStatus); + } + + try_return( ntStatus); + } + + IoSkipCurrentIrpStackLocation( Irp); + + ntStatus = IoCallDriver( pControlDeviceExt->Specific.Control.LibraryDeviceObject, + Irp); + + // + // Indicate the library is done with the request + // + + AFSClearLibraryRequest(); + +try_exit: + + NOTHING; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp b/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp new file mode 100644 index 0000000000..bd01b56560 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp @@ -0,0 +1,2050 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSGeneric.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSExceptionFilter +// +// Description: +// +// This function is the exception handler +// +// Return: +// +// A status is returned for the function +// + +ULONG +AFSExceptionFilter( IN ULONG Code, + IN PEXCEPTION_POINTERS ExceptPtrs) +{ + + PEXCEPTION_RECORD ExceptRec; + PCONTEXT Context; + + __try + { + + ExceptRec = ExceptPtrs->ExceptionRecord; + + Context = ExceptPtrs->ContextRecord; + + AFSDbgLogMsg( 0, + 0, + "AFSExceptionFilter (Framework) - EXR %p CXR %p Code %08lX Address %p\n", + ExceptRec, + Context, + ExceptRec->ExceptionCode, + ExceptRec->ExceptionAddress); + + DbgPrint("**** Exception Caught in AFS Redirector ****\n"); + + DbgPrint("\n\nPerform the following WnDbg Cmds:\n"); + DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context); + + DbgPrint("**** Exception Complete from AFS Redirector ****\n"); + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION)) + { + + KeBugCheck( (ULONG)-2); + } + else + { + + AFSBreakPoint(); + } + } + __except( EXCEPTION_EXECUTE_HANDLER) + { + + NOTHING; + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +// +// Function: AFSAcquireExcl() +// +// Purpose: Called to acquire a resource exclusive with optional wait +// +// Parameters: +// PERESOURCE Resource - Resource to acquire +// BOOLEAN Wait - Whether to block +// +// Return: +// BOOLEAN - Whether the mask was acquired +// + +BOOLEAN +AFSAcquireExcl( IN PERESOURCE Resource, + IN BOOLEAN wait) +{ + + BOOLEAN bStatus = FALSE; + + // + // Normal kernel APCs must be disabled before calling + // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs. + // + + KeEnterCriticalRegion(); + + bStatus = ExAcquireResourceExclusiveLite( Resource, + wait); + + if( !bStatus) + { + + KeLeaveCriticalRegion(); + } + + return bStatus; +} + +BOOLEAN +AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource, + IN BOOLEAN Wait) +{ + + BOOLEAN bStatus = FALSE; + + KeEnterCriticalRegion(); + + bStatus = ExAcquireSharedStarveExclusive( Resource, + Wait); + + if( !bStatus) + { + + KeLeaveCriticalRegion(); + } + + return bStatus; +} + +// +// Function: AFSAcquireShared() +// +// Purpose: Called to acquire a resource shared with optional wait +// +// Parameters: +// PERESOURCE Resource - Resource to acquire +// BOOLEAN Wait - Whether to block +// +// Return: +// BOOLEAN - Whether the mask was acquired +// + +BOOLEAN +AFSAcquireShared( IN PERESOURCE Resource, + IN BOOLEAN wait) +{ + + BOOLEAN bStatus = FALSE; + + KeEnterCriticalRegion(); + + bStatus = ExAcquireResourceSharedLite( Resource, + wait); + + if( !bStatus) + { + + KeLeaveCriticalRegion(); + } + + return bStatus; +} + +// +// Function: AFSReleaseResource() +// +// Purpose: Called to release a resource +// +// Parameters: +// PERESOURCE Resource - Resource to release +// +// Return: +// None +// + +void +AFSReleaseResource( IN PERESOURCE Resource) +{ + + if( Resource != &AFSDbgLogLock) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSReleaseResource Releasing lock %08lX Thread %08lX\n", + Resource, + PsGetCurrentThread()); + } + + ExReleaseResourceLite( Resource); + + KeLeaveCriticalRegion(); + + return; +} + +void +AFSConvertToShared( IN PERESOURCE Resource) +{ + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSConvertToShared Converting lock %08lX Thread %08lX\n", + Resource, + PsGetCurrentThread()); + + ExConvertExclusiveToSharedLite( Resource); + + return; +} + +// +// Function: AFSCompleteRequest +// +// Description: +// +// This function completes irps +// +// Return: +// +// A status is returned for the function +// + +void +AFSCompleteRequest( IN PIRP Irp, + IN ULONG Status) +{ + + Irp->IoStatus.Status = Status; + + IoCompleteRequest( Irp, + IO_NO_INCREMENT); + + return; +} + +NTSTATUS +AFSReadRegistry( IN PUNICODE_STRING RegistryPath) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG Default = 0; + UNICODE_STRING paramPath; + ULONG Value = 0; + RTL_QUERY_REGISTRY_TABLE paramTable[2]; + UNICODE_STRING defaultUnicodeName; + WCHAR SubKeyString[] = L"\\Parameters"; + + // + // Setup the paramPath buffer. + // + + paramPath.MaximumLength = RegistryPath->Length + sizeof( SubKeyString); + paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool, + paramPath.MaximumLength, + AFS_GENERIC_MEMORY_15_TAG); + + RtlInitUnicodeString( &defaultUnicodeName, + L"NO NAME"); + + // + // If it exists, setup the path. + // + + if( paramPath.Buffer != NULL) + { + + // + // Move in the paths + // + + RtlCopyMemory( ¶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; +} + + diff --git a/src/WINNT/afsrdr/kernel/fs/AFSInit.cpp b/src/WINNT/afsrdr/kernel/fs/AFSInit.cpp new file mode 100644 index 0000000000..770de37934 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSInit.cpp @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSInit.cpp +// + +#include "AFSCommon.h" + +#ifndef AMD64 +extern "C" +{ +extern void *KeServiceDescriptorTable; +}; +#endif + +// +// DriverEntry +// +// This is the initial entry point for the driver. +// +// Inputs: +// DriverObject Pointer to Driver Object created by I/O manager +// RegistryPath Pointer to registry path representing this Driver +// +// Returns: +// Success To indicate Driver's inituaialization processing +// was successful +// NT ERROR STATUS Otherwise -- Driver does not remain loaded +// + +NTSTATUS +DriverEntry( PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt; + ULONG ulTimeIncrement = 0; + UNICODE_STRING uniSymLinkName; + UNICODE_STRING uniDeviceName; + ULONG ulIndex = 0; + ULONG ulValue = 0; + UNICODE_STRING uniValueName; + BOOLEAN bExit = FALSE; + UNICODE_STRING uniRoutine; + RTL_OSVERSIONINFOW sysVersion; + + __try + { + + DbgPrint("AFSRedirFs DriverEntry Initialization build %s:%s\n", __DATE__, __TIME__); + + // + // Initialize some local variables for easier processing + // + + uniSymLinkName.Buffer = NULL; + + AFSDumpFileLocation.Length = 0; + AFSDumpFileLocation.MaximumLength = 0; + AFSDumpFileLocation.Buffer = NULL; + + AFSDumpFileName.Length = 0; + AFSDumpFileName.Buffer = NULL; + AFSDumpFileName.MaximumLength = 0; + + ExInitializeResourceLite( &AFSDbgLogLock); + + // + // Initialize the server name + // + + AFSReadServerName(); + + RtlZeroMemory( &sysVersion, + sizeof( RTL_OSVERSIONINFOW)); + + sysVersion.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW); + + RtlGetVersion( &sysVersion); + + RtlInitUnicodeString( &uniRoutine, + L"ZwSetInformationToken"); + + AFSSetInformationToken = (PAFSSetInformationToken)MmGetSystemRoutineAddress( &uniRoutine); + + if( AFSSetInformationToken == NULL) + { +#ifndef AMD64 + AFSSrvcTableEntry *pServiceTable = NULL; + + pServiceTable = (AFSSrvcTableEntry *)KeServiceDescriptorTable; + + // + // Only perform this lookup for Windows XP. + // + + if( pServiceTable != NULL && + sysVersion.dwMajorVersion == 5 && + sysVersion.dwMinorVersion == 1) + { + AFSSetInformationToken = (PAFSSetInformationToken)pServiceTable->ServiceTable[ 0xE6]; + } +#endif + } + + // + // And the global root share name + // + + RtlInitUnicodeString( &AFSGlobalRootName, + AFS_GLOBAL_ROOT_SHARE_NAME); + + RtlZeroMemory( &AFSNoPAGAuthGroup, + sizeof( GUID)); + + // + // Our backdoor to not let the driver load + // + + if( bExit) + { + try_return( ntStatus); + } + + // + // Perform some initialization + // + + AFSDriverObject = DriverObject; + + ntStatus = AFSReadRegistry( RegistryPath); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFS DriverEntry: Failed to read registry Status %08lX\n", ntStatus); + + ntStatus = STATUS_SUCCESS; + } + + // + // Initialize the debug log and dump file interface + // + + AFSInitializeDbgLog(); + + AFSInitializeDumpFile(); + +#if DBG + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_BREAK_ON_ENTRY)) + { + + DbgPrint("AFSRedirFs DriverEntry - Break on entry\n"); + + AFSBreakPoint(); + + if ( bExit) + { + // + // Just as above + // + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + } +#endif + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN) && + !BooleanFlagOn( AFSDebugFlags, AFS_DBG_CLEAN_SHUTDOWN)) + { + + AFSPrint("AFS DriverEntry: Failed to shutdown clean, exiting\n"); + + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + // + // Setup the registry string + // + + AFSRegistryPath.MaximumLength = RegistryPath->MaximumLength; + AFSRegistryPath.Length = RegistryPath->Length; + + AFSRegistryPath.Buffer = (PWSTR)ExAllocatePoolWithTag( PagedPool, + AFSRegistryPath.Length, + AFS_GENERIC_MEMORY_18_TAG); + + if( AFSRegistryPath.Buffer == NULL) + { + + DbgPrint("AFSRedirFs DriverEntry Failed to allocate registry path buffer\n"); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlCopyMemory( AFSRegistryPath.Buffer, + RegistryPath->Buffer, + RegistryPath->Length); + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN)) + { + + // + // Update the shutdown flag + // + + ulValue = (ULONG)-1; + + RtlInitUnicodeString( &uniValueName, + AFS_REG_SHUTDOWN_STATUS); + + AFSUpdateRegistryParameter( &uniValueName, + REG_DWORD, + &ulValue, + sizeof( ULONG)); + } + + RtlInitUnicodeString( &uniDeviceName, + AFS_CONTROL_DEVICE_NAME); + + ntStatus = IoCreateDeviceSecure( DriverObject, + sizeof( AFSDeviceExt), + &uniDeviceName, + FILE_DEVICE_NETWORK_FILE_SYSTEM, + 0, + FALSE, + &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX, + (LPCGUID)&GUID_SD_AFS_REDIRECTOR_CONTROL_OBJECT, + &AFSDeviceObject); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFS DriverEntry - Failed to allocate device control object Status %08lX\n", ntStatus); + + try_return( ntStatus); + } + + // + // Setup the device extension + // + + pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + InitializeListHead( &pDeviceExt->Specific.Control.DirNotifyList); + FsRtlNotifyInitializeSync( &pDeviceExt->Specific.Control.NotifySync); + + // + // Now initialize the control device + // + + ntStatus = AFSInitializeControlDevice(); + + if( !NT_SUCCESS( ntStatus)) + { + + try_return( ntStatus); + } + + // + // Allocate our symbolic link for service communication + // + + RtlInitUnicodeString( &uniSymLinkName, + AFS_SYMLINK_NAME); + + ntStatus = IoCreateSymbolicLink( &uniSymLinkName, + &uniDeviceName); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFS DriverEntry - Failed to create symbolic link Status %08lX\n", ntStatus); + + // + // OK, no one can communicate with us so fail + // + + try_return( ntStatus); + } + + // + // Fill in the dispatch table + // + + for( ulIndex = 0; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++) + { + + DriverObject->MajorFunction[ ulIndex] = AFSDefaultDispatch; + } + + DriverObject->MajorFunction[IRP_MJ_CREATE] = AFSCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = AFSClose; + DriverObject->MajorFunction[IRP_MJ_READ] = AFSRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = AFSWrite; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = AFSQueryFileInfo; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = AFSSetFileInfo; + DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = AFSQueryEA; + DriverObject->MajorFunction[IRP_MJ_SET_EA] = AFSSetEA; + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = AFSFlushBuffers; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = AFSQueryVolumeInfo; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = AFSSetVolumeInfo; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = AFSDirControl; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = AFSFSControl; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AFSDevControl; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = AFSInternalDevControl; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = AFSShutdown; + DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = AFSLockControl; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AFSCleanup; + DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = AFSQuerySecurity; + DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = AFSSetSecurity; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AFSSystemControl; + //DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = AFSQueryQuota; + //DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = AFSSetQuota; + + // + // Since we are not a true FSD then we are not controlling a device and hence these will not be needed + // + +#ifdef FSD_NOT_USED + + DriverObject->MajorFunction[IRP_MJ_POWER] = AFSPower; + DriverObject->MajorFunction[IRP_MJ_PNP] = AFSPnP; + +#endif + + // + // Fast IO Dispatch table + // + + DriverObject->FastIoDispatch = &AFSFastIoDispatch; + + RtlZeroMemory( &AFSFastIoDispatch, + sizeof( AFSFastIoDispatch)); + + // + // Again, since we are not a registered FSD many of these are not going to be called. They are here + // for completeness. + // + + AFSFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); + AFSFastIoDispatch.FastIoCheckIfPossible = AFSFastIoCheckIfPossible; // CheckForFastIo + AFSFastIoDispatch.FastIoRead = AFSFastIoRead; // Read + AFSFastIoDispatch.FastIoWrite = AFSFastIoWrite; // Write + AFSFastIoDispatch.FastIoQueryBasicInfo = AFSFastIoQueryBasicInfo; // QueryBasicInfo + AFSFastIoDispatch.FastIoQueryStandardInfo = AFSFastIoQueryStandardInfo; // QueryStandardInfo + AFSFastIoDispatch.FastIoLock = AFSFastIoLock; // Lock + AFSFastIoDispatch.FastIoUnlockSingle = AFSFastIoUnlockSingle; // UnlockSingle + AFSFastIoDispatch.FastIoUnlockAll = AFSFastIoUnlockAll; // UnlockAll + AFSFastIoDispatch.FastIoUnlockAllByKey = AFSFastIoUnlockAllByKey; // UnlockAllByKey + AFSFastIoDispatch.FastIoQueryNetworkOpenInfo = AFSFastIoQueryNetworkOpenInfo; + AFSFastIoDispatch.AcquireForCcFlush = AFSFastIoAcquireForCCFlush; + AFSFastIoDispatch.ReleaseForCcFlush = AFSFastIoReleaseForCCFlush; + AFSFastIoDispatch.FastIoDeviceControl = AFSFastIoDevCtrl; + AFSFastIoDispatch.AcquireFileForNtCreateSection = AFSFastIoAcquireFile; + AFSFastIoDispatch.ReleaseFileForNtCreateSection = AFSFastIoReleaseFile; + AFSFastIoDispatch.FastIoDetachDevice = AFSFastIoDetachDevice; + //AFSFastIoDispatch.AcquireForModWrite = AFSFastIoAcquireForModWrite; + //AFSFastIoDispatch.ReleaseForModWrite = AFSFastIoReleaseForModWrite; + AFSFastIoDispatch.MdlRead = AFSFastIoMdlRead; + AFSFastIoDispatch.MdlReadComplete = AFSFastIoMdlReadComplete; + AFSFastIoDispatch.PrepareMdlWrite = AFSFastIoPrepareMdlWrite; + AFSFastIoDispatch.MdlWriteComplete = AFSFastIoMdlWriteComplete; + AFSFastIoDispatch.FastIoReadCompressed = AFSFastIoReadCompressed; + AFSFastIoDispatch.FastIoWriteCompressed = AFSFastIoWriteCompressed; + AFSFastIoDispatch.MdlReadCompleteCompressed = AFSFastIoMdlReadCompleteCompressed; + AFSFastIoDispatch.MdlWriteCompleteCompressed = AFSFastIoMdlWriteCompleteCompressed; + AFSFastIoDispatch.FastIoQueryOpen = AFSFastIoQueryOpen; + + // + // Cache manager callback routines. + // + + AFSCacheManagerCallbacks.AcquireForLazyWrite = &AFSAcquireFcbForLazyWrite; + AFSCacheManagerCallbacks.ReleaseFromLazyWrite = &AFSReleaseFcbFromLazyWrite; + AFSCacheManagerCallbacks.AcquireForReadAhead = &AFSAcquireFcbForReadAhead; + AFSCacheManagerCallbacks.ReleaseFromReadAhead = &AFSReleaseFcbFromReadAhead; + + // + // System process. + // + + AFSSysProcess = PsGetCurrentProcessId(); + + // + // Register for shutdown notification + // + + IoRegisterShutdownNotification( AFSDeviceObject); + + // + // Initialize the system process cb + // + + AFSInitializeProcessCB( 0, + (ULONGLONG)AFSSysProcess); + + // + // Initialize the redirector device + // + + ntStatus = AFSInitRDRDevice(); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFS DriverEntry Failed to initialize redirector device Status %08lX\n"); + + try_return( ntStatus); + } + + // + // Initialize some server name based strings + // + + AFSInitServerStrings(); + + // + // Register the call back for process creation and tear down + // + + PsSetCreateProcessNotifyRoutine( AFSProcessNotify, + FALSE); + +try_exit: + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFSRedirFs DriverEntry failed to initialize %08lX\n", ntStatus); + + if( AFSRegistryPath.Buffer != NULL) + { + + ExFreePool( AFSRegistryPath.Buffer); + } + + if( uniSymLinkName.Buffer != NULL) + { + + IoDeleteSymbolicLink( &uniSymLinkName); + } + + if( AFSDeviceObject != NULL) + { + + AFSRemoveControlDevice(); + + FsRtlNotifyUninitializeSync( &pDeviceExt->Specific.Control.NotifySync); + + IoUnregisterShutdownNotification( AFSDeviceObject); + + IoDeleteDevice( AFSDeviceObject); + } + + AFSTearDownDbgLog(); + + ExDeleteResourceLite( &AFSDbgLogLock); + } + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSRedirFs DriverEntry\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp new file mode 100644 index 0000000000..1853912e5b --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSInternalDevControl.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSInternalDevControl.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSInternalDevControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_IMPLEMENTED; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSCompleteRequest( Irp, + ntStatus); + + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSInternalDevControl\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp new file mode 100644 index 0000000000..23320baa20 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSLibrarySupport.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSLoadLibrary( IN ULONG Flags, + IN UNICODE_STRING *ServicePath) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + UNICODE_STRING uniLibraryName; + AFSDeviceExt *pLibDevExt = NULL; + PFILE_OBJECT pLibraryFileObject = NULL; + PDEVICE_OBJECT pLibraryDeviceObject = NULL; + + __Enter + { + + // + // Wait on the load library event so we don't race with any + // other requests coming through + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Start load library\n", + __FUNCTION__); + + ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent, + Executive, + KernelMode, + FALSE, + NULL); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSLoadLibrary Wait for LoadLibraryEvent failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + // + // Check our current state to ensure we currently do not have a library loaded + // + + if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Library already loaded\n", + __FUNCTION__); + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + pDevExt->Specific.Control.LibraryServicePath.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + ServicePath->Length, + AFS_GENERIC_MEMORY_25_TAG); + + if( pDevExt->Specific.Control.LibraryServicePath.Buffer == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSLoadLibrary AFS_GENERIC_MEMORY_25_TAG allocation error\n"); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, + ServicePath->Length); + + pDevExt->Specific.Control.LibraryServicePath.Length = ServicePath->Length; + pDevExt->Specific.Control.LibraryServicePath.MaximumLength = pDevExt->Specific.Control.LibraryServicePath.Length; + + RtlCopyMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, + ServicePath->Buffer, + pDevExt->Specific.Control.LibraryServicePath.Length); + + // + // Load the library + // + + ntStatus = ZwLoadDriver( ServicePath); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to load library Status %08lX\n", + __FUNCTION__, + ntStatus); + + try_return( ntStatus); + } + + // + // Open up the control device and grab teh entry points for the library + // + + RtlInitUnicodeString( &uniLibraryName, + AFS_LIBRARY_CONTROL_DEVICE_NAME); + + ntStatus = IoGetDeviceObjectPointer( &uniLibraryName, + FILE_ALL_ACCESS, + &pLibraryFileObject, + &pLibraryDeviceObject); + + if( !NT_SUCCESS( ntStatus)) + { + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSLoadLibrary IoGetDeviceObjectPointer failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + // + // We have our reference to the library device object. Grab the + // device extension and setup our callbacks + // + + pLibDevExt = (AFSDeviceExt *)pLibraryDeviceObject->DeviceExtension; + + // + // Save off our references + // + + pDevExt->Specific.Control.LibraryFileObject = pLibraryFileObject; + + pDevExt->Specific.Control.LibraryDeviceObject = pLibraryDeviceObject; + + // + // Reset the state for our library + // + + AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, + TRUE); + + SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); + + ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Completed load library, processing queued requests\n", + __FUNCTION__); + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); + + // + // Process the queued requests + // + + AFSProcessQueuedResults( FALSE); + +try_exit: + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Library load complete Status %08lX\n", + __FUNCTION__, + ntStatus); + + if( !NT_SUCCESS( ntStatus)) + { + + if( pDevExt->Specific.Control.LibraryServicePath.Buffer != NULL) + { + + ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath); + + ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer); + + pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL; + pDevExt->Specific.Control.LibraryServicePath.Length = 0; + pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0; + } + } + + KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent, + 0, + FALSE); + } + + return ntStatus; +} + +NTSTATUS +AFSUnloadLibrary( IN BOOLEAN CancelQueue) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + LARGE_INTEGER liTimeout; + + __Enter + { + + // + // Wait on the load library event so we don't race with any + // other requests coming through + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Start unload library\n", + __FUNCTION__); + + ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent, + Executive, + KernelMode, + FALSE, + NULL); + + if( !NT_SUCCESS( ntStatus)) + { + try_return( ntStatus); + } + + if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) + { + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + // + // Clear all outstanding requests + // + + AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, + TRUE); + + ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); + + if( CancelQueue) + { + SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED); + } + + // + // We'll wait on the inflight event to be set, checking for the inflight + // request count to reach zero + // + + while( pDevExt->Specific.Control.InflightLibraryRequests > 0) + { + + liTimeout.QuadPart = -(AFS_ONE_SECOND); + + // + // If the count is non-zero make sure the event is cleared + // + + KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent); + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); + + ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.InflightLibraryEvent, + Executive, + KernelMode, + FALSE, + &liTimeout); + + AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, + TRUE); + + if( ntStatus != STATUS_TIMEOUT && + ntStatus != STATUS_SUCCESS) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Failed request event Status %08lX\n", + __FUNCTION__, + ntStatus); + + SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); + + AFSProcessQueuedResults( TRUE); + + try_return( ntStatus); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Wait for inflight requests to complete %08lX\n", + __FUNCTION__, + pDevExt->Specific.Control.InflightLibraryRequests); + } + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Processing queued results\n", + __FUNCTION__); + + AFSProcessQueuedResults( TRUE); + + // + // Unload the current library implementation + // + + if( pDevExt->Specific.Control.LibraryFileObject != NULL) + { + ObDereferenceObject( pDevExt->Specific.Control.LibraryFileObject); + } + + pDevExt->Specific.Control.LibraryFileObject = NULL; + + pDevExt->Specific.Control.LibraryDeviceObject = NULL; + + ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath); + + ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer); + + pDevExt->Specific.Control.LibraryServicePath.Length = 0; + + pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0; + + pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL; + +try_exit: + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Library unload complete Status %08lX\n", + __FUNCTION__, + ntStatus); + + KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent, + 0, + FALSE); + } + + return ntStatus; +} + +NTSTATUS +AFSCheckLibraryState( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __Enter + { + + AFSAcquireShared( &pDevExt->Specific.Control.LibraryStateLock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry State %08lX Irp %p Function %08lX\n", + __FUNCTION__, + pRDRDevExt->DeviceFlags, + Irp, + pIrpSp->MajorFunction); + + if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) + { + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + if( !BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) + { + + if( Irp != NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Queuing request %p\n", + __FUNCTION__, + Irp); + + ntStatus = AFSQueueLibraryRequest( Irp); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Queued request %p Status %08lX\n", + __FUNCTION__, + Irp, + ntStatus); + } + else + { + + ntStatus = STATUS_TOO_LATE; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Failing request %p\n", + __FUNCTION__, + Irp); + } + + try_return( ntStatus); + } + + if( InterlockedIncrement( &pDevExt->Specific.Control.InflightLibraryRequests) == 1) + { + KeClearEvent( &pDevExt->Specific.Control.InflightLibraryEvent); + } + +try_exit: + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Completed Irp %p Status %08lX Inflight Count %08lX\n", + __FUNCTION__, + Irp, + ntStatus, + pDevExt->Specific.Control.InflightLibraryRequests); + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); + } + + return ntStatus; +} + +NTSTATUS +AFSClearLibraryRequest() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + if( InterlockedDecrement( &pDevExt->Specific.Control.InflightLibraryRequests) == 0) + { + + KeSetEvent( &pDevExt->Specific.Control.InflightLibraryEvent, + 0, + FALSE); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Inflight Count %08lX\n", + __FUNCTION__, + pDevExt->Specific.Control.InflightLibraryRequests); + } + + return ntStatus; +} + +NTSTATUS +AFSQueueLibraryRequest( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + AFSLibraryQueueRequestCB *pRequest = NULL; + PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __Enter + { + + AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for Irp %p Function %08lX\n", + __FUNCTION__, + Irp, + pIrpSp->MajorFunction); + + // + // Has the load processing timed out and we are no longer + // queuing requests? + // + + if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED) || + BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_ERROR, + "%s Library not loaded for Irp %p\n", + __FUNCTION__, + Irp); + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + pRequest = (AFSLibraryQueueRequestCB *)AFSExAllocatePoolWithTag( PagedPool, + sizeof( AFSLibraryQueueRequestCB), + AFS_LIBRARY_QUEUE_TAG); + + if( pRequest == NULL) + { + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pRequest, + sizeof( AFSLibraryQueueRequestCB)); + + pRequest->Irp = Irp; + + if( pDevExt->Specific.Control.LibraryQueueHead == NULL) + { + pDevExt->Specific.Control.LibraryQueueHead = pRequest; + } + else + { + pDevExt->Specific.Control.LibraryQueueTail->fLink = pRequest; + } + + pDevExt->Specific.Control.LibraryQueueTail = pRequest; + + IoMarkIrpPending( Irp); + + ntStatus = STATUS_PENDING; + +try_exit: + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Completed for Irp %p Status %08lX\n", + __FUNCTION__, + Irp, + ntStatus); + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); + } + + return ntStatus; +} + +NTSTATUS +AFSProcessQueuedResults( IN BOOLEAN CancelRequest) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSLibraryQueueRequestCB *pRequest = NULL; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry\n", + __FUNCTION__); + + // + // Loop through the queue either resubmitting requests or cancelling them + // + + while( TRUE) + { + + AFSAcquireExcl( &pDevExt->Specific.Control.LibraryQueueLock, + TRUE); + + if( pDevExt->Specific.Control.LibraryQueueHead == NULL) + { + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); + + break; + } + + pRequest = pDevExt->Specific.Control.LibraryQueueHead; + + pDevExt->Specific.Control.LibraryQueueHead = pRequest->fLink; + + if( pDevExt->Specific.Control.LibraryQueueHead == NULL) + { + + pDevExt->Specific.Control.LibraryQueueTail = NULL; + } + + AFSReleaseResource( &pDevExt->Specific.Control.LibraryQueueLock); + + if( CancelRequest) + { + + pRequest->Irp->IoStatus.Status = STATUS_CANCELLED; + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Cancelling request Irp %p\n", + __FUNCTION__, + pRequest->Irp); + + IoCompleteRequest( pRequest->Irp, + IO_NO_INCREMENT); + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Resubmitting request Irp %p\n", + __FUNCTION__, + pRequest->Irp); + + AFSSubmitLibraryRequest( pRequest->Irp); + } + + ExFreePool( pRequest); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Completed\n", + __FUNCTION__); + } + + return ntStatus; +} + +NTSTATUS +AFSSubmitLibraryRequest( IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY, + AFS_TRACE_LEVEL_VERBOSE, + "%s Submitting Irp %p Function %08lX\n", + __FUNCTION__, + Irp, + pIrpSp->MajorFunction); + + switch( pIrpSp->MajorFunction) + { + + case IRP_MJ_CREATE: + { + AFSCreate( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_CLOSE: + { + AFSClose( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_READ: + { + AFSRead( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_WRITE: + { + AFSWrite( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_QUERY_INFORMATION: + { + AFSQueryFileInfo( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SET_INFORMATION: + { + AFSSetFileInfo( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_QUERY_EA: + { + AFSQueryEA( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SET_EA: + { + AFSSetEA( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_FLUSH_BUFFERS: + { + AFSFlushBuffers( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + { + AFSQueryVolumeInfo( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SET_VOLUME_INFORMATION: + { + AFSSetVolumeInfo( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_DIRECTORY_CONTROL: + { + AFSDirControl( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_FILE_SYSTEM_CONTROL: + { + AFSFSControl( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_DEVICE_CONTROL: + { + AFSDevControl( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + { + AFSInternalDevControl( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SHUTDOWN: + { + AFSShutdown( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_LOCK_CONTROL: + { + AFSLockControl( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_CLEANUP: + { + AFSCleanup( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_QUERY_SECURITY: + { + AFSQuerySecurity( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SET_SECURITY: + { + AFSSetSecurity( AFSRDRDeviceObject, + Irp); + break; + } + + case IRP_MJ_SYSTEM_CONTROL: + { + AFSSystemControl( AFSRDRDeviceObject, + Irp); + break; + } + + default: + { + AFSDefaultDispatch( AFSRDRDeviceObject, + Irp); + break; + } + } + } + + return ntStatus; +} + +NTSTATUS +AFSInitializeLibrary( IN AFSFileID *GlobalRootFid, + IN BOOLEAN QueueRootEnumeration) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSLibraryInitCB stInitLib; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + + __Enter + { + + RtlZeroMemory( &stInitLib, + sizeof( AFSLibraryInitCB)); + + // + // Initialize the parameters to pass to the library + // + + stInitLib.AFSControlDeviceObject = AFSDeviceObject; + + stInitLib.AFSRDRDeviceObject = AFSRDRDeviceObject; + + stInitLib.AFSServerName = AFSServerName; + + stInitLib.AFSDebugFlags = AFSDebugFlags; + + if( GlobalRootFid != NULL) + { + stInitLib.GlobalRootFid = *GlobalRootFid; + } + + stInitLib.AFSCacheManagerCallbacks = &AFSCacheManagerCallbacks; + + stInitLib.AFSCacheBaseAddress = pRDRDevExt->Specific.RDR.CacheBaseAddress; + + stInitLib.AFSCacheLength = pRDRDevExt->Specific.RDR.CacheLength; + + // + // Initialize the callback functions for the library + // + + stInitLib.AFSProcessRequest = AFSProcessRequest; + + stInitLib.AFSDbgLogMsg = AFSDbgLogMsg; + + stInitLib.AFSAddConnectionEx = AFSAddConnectionEx; + + stInitLib.AFSExAllocatePoolWithTag = AFSExAllocatePoolWithTag; + + stInitLib.AFSExFreePool = AFSExFreePool; + + stInitLib.AFSDumpTraceFiles = AFSDumpTraceFiles; + + stInitLib.AFSRetrieveAuthGroup = AFSRetrieveAuthGroup; + + ntStatus = AFSSendDeviceIoControl( pDevExt->Specific.Control.LibraryDeviceObject, + IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE, + &stInitLib, + sizeof( AFSLibraryInitCB), + NULL, + 0, + NULL); + + if ( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeLibrary AFSSendDeviceIoControl failure %08lX\n", + ntStatus); + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSLockControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSLockControl.cpp new file mode 100644 index 0000000000..c4a6184289 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSLockControl.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// File: AFSLockControl.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSLockControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + 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( (ntStatus = GetExceptionCode()), GetExceptionInformation())) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSLockControl\n"); + + AFSCompleteRequest( Irp, + ntStatus); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSLogSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSLogSupport.cpp new file mode 100644 index 0000000000..549b57f65d --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSLogSupport.cpp @@ -0,0 +1,756 @@ +/* + * 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. + */ + +#include "AFSCommon.h" + +NTSTATUS +AFSDbgLogMsg( IN ULONG Subsystem, + IN ULONG Level, + IN PCCH Format, + ...) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + va_list va_args; + ULONG ulBytesWritten = 0; + BOOLEAN bReleaseLock = FALSE; + char *pCurrentTrace = NULL; + + __Enter + { + + if( AFSDbgBuffer == NULL) + { + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + if( Subsystem > 0 && + (Subsystem & AFSTraceComponent) == 0) + { + + // + // Not tracing this subsystem + // + + try_return( ntStatus); + } + + if( Level > 0 && + Level > AFSTraceLevel) + { + + // + // Not tracing this level + // + + try_return( ntStatus); + } + + AFSAcquireExcl( &AFSDbgLogLock, + TRUE); + + bReleaseLock = TRUE; + + // + // Check again under lock + // + + if( AFSDbgBuffer == NULL) + { + + try_return( ntStatus = STATUS_DEVICE_NOT_READY); + } + + if( AFSDbgLogRemainingLength < 255) + { + + AFSDbgLogRemainingLength = AFSDbgBufferLength; + + AFSDbgCurrentBuffer = AFSDbgBuffer; + + SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); + } + + pCurrentTrace = AFSDbgCurrentBuffer; + + RtlStringCchPrintfA( AFSDbgCurrentBuffer, + 10, + "%08lX:", + AFSDbgLogCounter++); + + AFSDbgCurrentBuffer += 9; + + AFSDbgLogRemainingLength -= 9; + + va_start( va_args, Format); + + ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer, + AFSDbgLogRemainingLength, + Format, + va_args); + + if( ntStatus == STATUS_BUFFER_OVERFLOW) + { + + RtlZeroMemory( AFSDbgCurrentBuffer, + AFSDbgLogRemainingLength); + + AFSDbgLogRemainingLength = AFSDbgBufferLength; + + AFSDbgCurrentBuffer = AFSDbgBuffer; + + SetFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); + + pCurrentTrace = AFSDbgCurrentBuffer; + + RtlStringCchPrintfA( AFSDbgCurrentBuffer, + 10, + "%08lX:", + AFSDbgLogCounter++); + + AFSDbgCurrentBuffer += 9; + + AFSDbgLogRemainingLength -= 9; + + ntStatus = RtlStringCbVPrintfA( AFSDbgCurrentBuffer, + AFSDbgLogRemainingLength, + Format, + va_args); + } + + if( NT_SUCCESS( ntStatus)) + { + + RtlStringCbLengthA( AFSDbgCurrentBuffer, + AFSDbgLogRemainingLength, + (size_t *)&ulBytesWritten); + + AFSDbgCurrentBuffer += ulBytesWritten; + + AFSDbgLogRemainingLength -= ulBytesWritten; + } + + va_end( va_args); + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_TRACE_TO_DEBUGGER) && + pCurrentTrace != NULL) + { + + DbgPrint( pCurrentTrace); + } + +try_exit: + + if( bReleaseLock) + { + + AFSReleaseResource( &AFSDbgLogLock); + } + } + + return ntStatus; +} + +NTSTATUS +AFSInitializeDbgLog() +{ + + NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES; + + AFSAcquireExcl( &AFSDbgLogLock, + TRUE); + + if( AFSDbgBufferLength > 0) + { + + AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool, + AFSDbgBufferLength, + AFS_GENERIC_MEMORY_19_TAG); + + if( AFSDbgBuffer != NULL) + { + + AFSDbgCurrentBuffer = AFSDbgBuffer; + + AFSDbgLogRemainingLength = AFSDbgBufferLength; + + ntStatus = STATUS_SUCCESS; + } + } + + AFSReleaseResource( &AFSDbgLogLock); + + if( NT_SUCCESS( ntStatus)) + { + AFSTagInitialLogEntry(); + } + + return ntStatus; +} + +NTSTATUS +AFSTearDownDbgLog() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + AFSAcquireExcl( &AFSDbgLogLock, + TRUE); + + if( AFSDbgBuffer != NULL) + { + + ExFreePool( AFSDbgBuffer); + } + + AFSDbgBuffer = NULL; + + AFSDbgCurrentBuffer = NULL; + + AFSDbgLogRemainingLength = 0; + + AFSReleaseResource( &AFSDbgLogLock); + + return ntStatus; +} + +NTSTATUS +AFSConfigureTrace( IN AFSTraceConfigCB *TraceInfo) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + UNICODE_STRING uniString; + + __Enter + { + + AFSAcquireExcl( &AFSDbgLogLock, + TRUE); + + if( TraceInfo->TraceLevel == AFSTraceLevel && + TraceInfo->TraceBufferLength == AFSDbgBufferLength && + TraceInfo->Subsystem == AFSTraceComponent) + { + + // + // Nothing to do + // + + try_return( ntStatus); + } + + // + // Go update the registry with the new entries + // + + if( TraceInfo->TraceLevel != (ULONG)-1 && + TraceInfo->TraceLevel != AFSTraceLevel) + { + + AFSTraceLevel = TraceInfo->TraceLevel; + + RtlInitUnicodeString( &uniString, + AFS_REG_TRACE_LEVEL); + + ntStatus = AFSUpdateRegistryParameter( &uniString, + REG_DWORD, + &TraceInfo->TraceLevel, + sizeof( ULONG)); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFSConfigureTrace Failed to set debug level in registry Status %08lX\n", ntStatus); + } + } + + if( TraceInfo->Subsystem != (ULONG)-1 && + TraceInfo->Subsystem != AFSTraceComponent) + { + + AFSTraceComponent = TraceInfo->Subsystem; + + RtlInitUnicodeString( &uniString, + AFS_REG_TRACE_SUBSYSTEM); + + ntStatus = AFSUpdateRegistryParameter( &uniString, + REG_DWORD, + &TraceInfo->Subsystem, + sizeof( ULONG)); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFSConfigureTrace Failed to set debug subsystem in registry Status %08lX\n", ntStatus); + } + } + + if( TraceInfo->DebugFlags != (ULONG)-1 && + TraceInfo->DebugFlags != AFSDebugFlags) + { + + AFSDebugFlags = TraceInfo->DebugFlags; + + RtlInitUnicodeString( &uniString, + AFS_REG_DEBUG_FLAGS); + + ntStatus = AFSUpdateRegistryParameter( &uniString, + REG_DWORD, + &TraceInfo->DebugFlags, + sizeof( ULONG)); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFSConfigureTrace Failed to set debug flags in registry Status %08lX\n", ntStatus); + } + } + + if( TraceInfo->TraceBufferLength != (ULONG)-1 && + TraceInfo->TraceBufferLength != AFSDbgBufferLength) + { + + RtlInitUnicodeString( &uniString, + AFS_REG_TRACE_BUFFER_LENGTH); + + ntStatus = AFSUpdateRegistryParameter( &uniString, + REG_DWORD, + &TraceInfo->TraceBufferLength, + sizeof( ULONG)); + + if( !NT_SUCCESS( ntStatus)) + { + + DbgPrint("AFSConfigureTrace Failed to set debug buffer length in registry Status %08lX\n", ntStatus); + } + + AFSDbgBufferLength = TraceInfo->TraceBufferLength * 1024; + + ClearFlag( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED); + + if( AFSDbgBuffer != NULL) + { + + ExFreePool( AFSDbgBuffer); + + AFSDbgBuffer = NULL; + + AFSDbgCurrentBuffer = NULL; + + AFSDbgLogRemainingLength = 0; + } + + if( AFSDbgBufferLength > 0) + { + + AFSDbgBuffer = (char *)AFSExAllocatePoolWithTag( NonPagedPool, + AFSDbgBufferLength, + AFS_GENERIC_MEMORY_20_TAG); + + if( AFSDbgBuffer == NULL) + { + + AFSDbgBufferLength = 0; + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + AFSDbgCurrentBuffer = AFSDbgBuffer; + + AFSDbgLogRemainingLength = AFSDbgBufferLength; + + AFSTagInitialLogEntry(); + } + } + +try_exit: + + AFSReleaseResource( &AFSDbgLogLock); + } + + return ntStatus; +} + +NTSTATUS +AFSGetTraceBuffer( IN ULONG TraceBufferLength, + OUT void *TraceBuffer, + OUT ULONG_PTR *CopiedLength) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG ulCopyLength = 0; + char *pCurrentLocation = NULL; + + __Enter + { + + AFSAcquireShared( &AFSDbgLogLock, + TRUE); + + if( TraceBufferLength < AFSDbgBufferLength) + { + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // + // If we have wrapped then copy in the remaining portion + // + + pCurrentLocation = (char *)TraceBuffer; + + *CopiedLength = 0; + + if( BooleanFlagOn( AFSDbgLogFlags, AFS_DBG_LOG_WRAPPED)) + { + + ulCopyLength = AFSDbgLogRemainingLength; + + RtlCopyMemory( pCurrentLocation, + AFSDbgCurrentBuffer, + ulCopyLength); + + pCurrentLocation[ 0] = '0'; // The buffer is NULL terminated ... + + pCurrentLocation += ulCopyLength; + + *CopiedLength = ulCopyLength; + } + + ulCopyLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; + + if( ulCopyLength > 0) + { + + RtlCopyMemory( pCurrentLocation, + AFSDbgBuffer, + ulCopyLength); + + *CopiedLength += ulCopyLength; + } + +try_exit: + + AFSReleaseResource( &AFSDbgLogLock); + } + + return ntStatus; +} + +void +AFSTagInitialLogEntry() +{ + + LARGE_INTEGER liTime, liLocalTime; + TIME_FIELDS timeFields; + + KeQuerySystemTime( &liTime); + + ExSystemTimeToLocalTime( &liTime, + &liLocalTime); + + RtlTimeToTimeFields( &liLocalTime, + &timeFields); + + AFSDbgLogMsg( 0, + 0, + "AFS Log Initialized %d-%d-%d %d:%d Level %d Subsystems %08lX\n", + timeFields.Month, + timeFields.Day, + timeFields.Year, + timeFields.Hour, + timeFields.Minute, + AFSTraceLevel, + AFSTraceComponent); + + return; +} + +void +AFSDumpTraceFiles() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + HANDLE hDirectory = NULL; + OBJECT_ATTRIBUTES stObjectAttribs; + IO_STATUS_BLOCK stIoStatus; + LARGE_INTEGER liTime, liLocalTime; + TIME_FIELDS timeFields; + ULONG ulBytesWritten = 0; + HANDLE hDumpFile = NULL; + ULONG ulBytesProcessed, ulCopyLength; + LARGE_INTEGER liOffset; + ULONG ulDumpLength = 0; + BOOLEAN bSetEvent = FALSE; + + __Enter + { + + AFSAcquireShared( &AFSDbgLogLock, + TRUE); + + ulDumpLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; + + AFSReleaseResource( &AFSDbgLogLock); + + if( AFSDumpFileLocation.Length == 0 || + AFSDumpFileLocation.Buffer == NULL || + AFSDbgBufferLength == 0 || + ulDumpLength == 0 || + AFSDumpFileName.MaximumLength == 0 || + AFSDumpFileName.Buffer == NULL || + AFSDumpBuffer == NULL) + { + try_return( ntStatus); + } + + // + // Go open the cache file + // + + InitializeObjectAttributes( &stObjectAttribs, + &AFSDumpFileLocation, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + ntStatus = ZwCreateFile( &hDirectory, + GENERIC_READ | GENERIC_WRITE, + &stObjectAttribs, + &stIoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if( !NT_SUCCESS( ntStatus)) + { + + try_return( ntStatus); + } + + ntStatus = KeWaitForSingleObject( &AFSDumpFileEvent, + Executive, + KernelMode, + FALSE, + NULL); + + if( !NT_SUCCESS( ntStatus)) + { + + try_return( ntStatus); + } + + bSetEvent = TRUE; + + AFSDumpFileName.Length = 0; + + RtlZeroMemory( AFSDumpFileName.Buffer, + AFSDumpFileName.MaximumLength); + + KeQuerySystemTime( &liTime); + + ExSystemTimeToLocalTime( &liTime, + &liLocalTime); + + RtlTimeToTimeFields( &liLocalTime, + &timeFields); + + ntStatus = RtlStringCchPrintfW( AFSDumpFileName.Buffer, + AFSDumpFileName.MaximumLength/sizeof( WCHAR), + L"AFSDumpFile %d.%d.%d %d.%d.%d.log", + timeFields.Month, + timeFields.Day, + timeFields.Year, + timeFields.Hour, + timeFields.Minute, + timeFields.Second); + + if( !NT_SUCCESS( ntStatus)) + { + try_return( ntStatus); + } + + RtlStringCbLengthW( AFSDumpFileName.Buffer, + AFSDumpFileName.MaximumLength, + (size_t *)&ulBytesWritten); + + AFSDumpFileName.Length = (USHORT)ulBytesWritten; + + InitializeObjectAttributes( &stObjectAttribs, + &AFSDumpFileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + hDirectory, + NULL); + + ntStatus = ZwCreateFile( &hDumpFile, + GENERIC_READ | GENERIC_WRITE, + &stObjectAttribs, + &stIoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if( !NT_SUCCESS( ntStatus)) + { + try_return( ntStatus); + } + + // + // Write out the trace buffer + // + + liOffset.QuadPart = 0; + + ulBytesProcessed = 0; + + while( ulBytesProcessed < ulDumpLength) + { + + ulCopyLength = AFSDumpBufferLength; + + if( ulCopyLength > ulDumpLength - ulBytesProcessed) + { + ulCopyLength = ulDumpLength - ulBytesProcessed; + } + + RtlCopyMemory( AFSDumpBuffer, + (void *)((char *)AFSDbgBuffer + ulBytesProcessed), + ulCopyLength); + + ntStatus = ZwWriteFile( hDumpFile, + NULL, + NULL, + NULL, + &stIoStatus, + AFSDumpBuffer, + ulCopyLength, + &liOffset, + NULL); + + if( !NT_SUCCESS( ntStatus)) + { + break; + } + + liOffset.QuadPart += ulCopyLength; + + ulBytesProcessed += ulCopyLength; + } + +try_exit: + + if( hDumpFile != NULL) + { + ZwClose( hDumpFile); + } + + if( hDirectory != NULL) + { + ZwClose( hDirectory); + } + + if( bSetEvent) + { + KeSetEvent( &AFSDumpFileEvent, + 0, + FALSE); + } + } + + return; +} + +NTSTATUS +AFSInitializeDumpFile() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + __Enter + { + + KeInitializeEvent( &AFSDumpFileEvent, + SynchronizationEvent, + TRUE); + + AFSDumpFileName.Length = 0; + AFSDumpFileName.Buffer = NULL; + AFSDumpFileName.MaximumLength = PAGE_SIZE; + + AFSDumpFileName.Buffer = (WCHAR *)ExAllocatePoolWithTag( PagedPool, + AFSDumpFileName.MaximumLength, + AFS_GENERIC_MEMORY_28_TAG); + + if( AFSDumpFileName.Buffer == NULL) + { + AFSDumpFileName.MaximumLength = 0; + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + AFSDumpBufferLength = 64 * 1024; + + AFSDumpBuffer = ExAllocatePoolWithTag( PagedPool, + AFSDumpBufferLength, + AFS_GENERIC_MEMORY_28_TAG); + + if( AFSDumpBuffer == NULL) + { + + ExFreePool( AFSDumpFileName.Buffer); + + AFSDumpFileName.Buffer = NULL; + AFSDumpFileName.MaximumLength = 0; + + AFSDumpBufferLength = 0; + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + +try_exit: + + NOTHING; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSNetworkProviderSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSNetworkProviderSupport.cpp new file mode 100644 index 0000000000..2611259b5e --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSNetworkProviderSupport.cpp @@ -0,0 +1,456 @@ +/* + * 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: AFSNetworkProviderSupport.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSAddConnectionEx( IN UNICODE_STRING *RemoteName, + IN ULONG DisplayType, + IN ULONG Flags) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProviderConnectionCB *pConnection = NULL, *pLastConnection = NULL, *pServerConnection = NULL; + UNICODE_STRING uniRemoteName; + AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSAddConnectionEx Acquiring AFSProviderListLock lock %08lX EXCL %08lX\n", + &pRDRDevExt->Specific.RDR.ProviderListLock, + PsGetCurrentThread()); + + AFSAcquireExcl( &pRDRDevExt->Specific.RDR.ProviderListLock, + TRUE); + + + AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER, + AFS_TRACE_LEVEL_VERBOSE, + "AFSAddConnectionEx remote name %wZ display type %08lX flags %08lX\n", + RemoteName, + DisplayType, + Flags); + + // + // If this is a server, start in the enum list, otherwise + // locate the server node + // + + if( DisplayType == RESOURCEDISPLAYTYPE_SERVER) + { + + pConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList; + } + else + { + + pServerConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList; // For now we have only one server ... + + if( pServerConnection == NULL) + { + + try_return( ntStatus); + } + + pConnection = pServerConnection->EnumerationList; + } + + // + // Look for the connection + // + + uniRemoteName.Length = RemoteName->Length; + uniRemoteName.MaximumLength = RemoteName->Length; + + uniRemoteName.Buffer = RemoteName->Buffer; + + while( pConnection != NULL) + { + + if( RtlCompareUnicodeString( &uniRemoteName, + &pConnection->RemoteName, + TRUE) == 0) + { + + break; + } + + pConnection = pConnection->fLink; + } + + if( pConnection != NULL) + { + + try_return( ntStatus); + } + + // + // Strip off any trailing slashes + // + + if( uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] == L'\\') + { + + uniRemoteName.Buffer[ (uniRemoteName.Length/sizeof( WCHAR)) - 1] = L'\0'; + + uniRemoteName.Length -= sizeof( WCHAR); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER, + AFS_TRACE_LEVEL_VERBOSE, + "AFSAddConnectionEx Inserting remote name %wZ\n", &uniRemoteName); + + // + // Allocate a new node and add it to our list + // + + pConnection = (AFSProviderConnectionCB *)AFSExAllocatePoolWithTag( PagedPool, + sizeof( AFSProviderConnectionCB) + + uniRemoteName.Length, + AFS_PROVIDER_CB); + + if( pConnection == NULL) + { + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory( pConnection, + sizeof( AFSProviderConnectionCB) + uniRemoteName.Length); + + pConnection->LocalName = L'\0'; + + pConnection->RemoteName.Length = uniRemoteName.Length; + pConnection->RemoteName.MaximumLength = pConnection->RemoteName.Length; + + pConnection->RemoteName.Buffer = (WCHAR *)((char *)pConnection + sizeof( AFSProviderConnectionCB)); + + RtlCopyMemory( pConnection->RemoteName.Buffer, + uniRemoteName.Buffer, + pConnection->RemoteName.Length); + + // + // Point to the component portion of the name + // + + pConnection->ComponentName.Length = 0; + pConnection->ComponentName.MaximumLength = 0; + + pConnection->ComponentName.Buffer = &pConnection->RemoteName.Buffer[ (pConnection->RemoteName.Length/sizeof( WCHAR)) - 1]; + + while( pConnection->ComponentName.Length <= pConnection->RemoteName.Length) + { + + if( pConnection->ComponentName.Buffer[ 0] == L'\\') + { + + pConnection->ComponentName.Buffer++; + + break; + } + + pConnection->ComponentName.Length += sizeof( WCHAR); + pConnection->ComponentName.MaximumLength += sizeof( WCHAR); + + pConnection->ComponentName.Buffer--; + } + + // + // Go initialize the information about the connection + // + + AFSInitializeConnectionInfo( pConnection, + DisplayType); + + // + // Store away the flags for the connection + // + + pConnection->Flags = Flags; + + // + // Insert the entry into our list. If this is a server + // connection then add it to the enumeration list, otherwise + // find the server name for this connection + // + + if( DisplayType == RESOURCEDISPLAYTYPE_SERVER) + { + + if( pRDRDevExt->Specific.RDR.ProviderEnumerationList == NULL) + { + + pRDRDevExt->Specific.RDR.ProviderEnumerationList = pConnection; + } + else + { + + // + // Get the end of the list + // + + pLastConnection = pRDRDevExt->Specific.RDR.ProviderEnumerationList; + + while( pLastConnection->fLink != NULL) + { + + pLastConnection = pLastConnection->fLink; + } + + pLastConnection->fLink = pConnection; + } + } + else if( pServerConnection != NULL) + { + + if( pServerConnection->EnumerationList == NULL) + { + + pServerConnection->EnumerationList = pConnection; + } + else + { + + // + // Get the end of the list + // + + pLastConnection = pServerConnection->EnumerationList; + + while( pLastConnection->fLink != NULL) + { + + pLastConnection = pLastConnection->fLink; + } + + pLastConnection->fLink = pConnection; + } + } + +try_exit: + + AFSReleaseResource( &pRDRDevExt->Specific.RDR.ProviderListLock); + } + + return ntStatus; +} + +void +AFSInitializeConnectionInfo( IN AFSProviderConnectionCB *Connection, + IN ULONG DisplayType) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + UNICODE_STRING uniName, uniComponentName, uniRemainingName; + + __Enter + { + + uniName = Connection->RemoteName; + + // + // Strip of the double leading slash if there is one + // + + if( uniName.Buffer[ 0] == L'\\' && + uniName.Buffer[ 1] == L'\\') + { + + uniName.Buffer = &uniName.Buffer[ 1]; + + uniName.Length -= sizeof( WCHAR); + } + + + FsRtlDissectName( uniName, + &uniComponentName, + &uniRemainingName); + + // + // Initialize the information for the connection + // First, if this is the server only then mark it accordingly + // + + if( uniRemainingName.Length == 0 || + DisplayType == RESOURCEDISPLAYTYPE_SERVER) + { + + Connection->Type = RESOURCETYPE_DISK; + + Connection->Scope = RESOURCE_GLOBALNET; + + Connection->DisplayType = RESOURCEDISPLAYTYPE_SERVER; + + Connection->Usage = RESOURCEUSAGE_CONTAINER; + + Connection->Comment.Length = 20; + Connection->Comment.MaximumLength = 22; + + Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + Connection->Comment.MaximumLength, + AFS_NETWORK_PROVIDER_7_TAG); + + if( Connection->Comment.Buffer != NULL) + { + + RtlZeroMemory( Connection->Comment.Buffer, + Connection->Comment.MaximumLength); + + RtlCopyMemory( Connection->Comment.Buffer, + L"AFS Root", + 16); + } + else + { + + Connection->Comment.Length = 0; + Connection->Comment.MaximumLength = 0; + } + + try_return( ntStatus); + } + + uniName = uniRemainingName; + + FsRtlDissectName( uniName, + &uniComponentName, + &uniRemainingName); + + if( uniRemainingName.Length == 0 || + uniRemainingName.Buffer == NULL || + DisplayType == RESOURCEDISPLAYTYPE_SHARE) + { + + Connection->Type = RESOURCETYPE_DISK; + + Connection->DisplayType = RESOURCEDISPLAYTYPE_SHARE; + + Connection->Usage = RESOURCEUSAGE_CONNECTABLE; + + if( Connection->LocalName != L'\0') + { + + Connection->Usage |= RESOURCEUSAGE_ATTACHED; + + Connection->Scope = RESOURCE_CONNECTED; + } + else + { + + Connection->Scope = RESOURCE_GLOBALNET; + } + + Connection->Comment.Length = 18; + Connection->Comment.MaximumLength = 20; + + Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + Connection->Comment.MaximumLength, + AFS_NETWORK_PROVIDER_8_TAG); + + if( Connection->Comment.Buffer != NULL) + { + + RtlZeroMemory( Connection->Comment.Buffer, + Connection->Comment.MaximumLength); + + RtlCopyMemory( Connection->Comment.Buffer, + L"AFS Share", + 18); + } + else + { + + Connection->Comment.Length = 0; + Connection->Comment.MaximumLength = 0; + } + + try_return( ntStatus); + } + + // + // This is a sub directory within a share + // + + Connection->Type = RESOURCETYPE_DISK; + + Connection->DisplayType = RESOURCEDISPLAYTYPE_DIRECTORY; + + Connection->Usage = RESOURCEUSAGE_CONNECTABLE; + + if( Connection->LocalName != L'\0') + { + + Connection->Usage |= RESOURCEUSAGE_ATTACHED; + } + + Connection->Scope = RESOURCE_CONNECTED; + + Connection->Comment.Length = 26; + Connection->Comment.MaximumLength = 28; + + Connection->Comment.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + Connection->Comment.MaximumLength, + AFS_NETWORK_PROVIDER_9_TAG); + + if( Connection->Comment.Buffer != NULL) + { + + RtlZeroMemory( Connection->Comment.Buffer, + Connection->Comment.MaximumLength); + + RtlCopyMemory( Connection->Comment.Buffer, + L"AFS Directory", + 26); + } + else + { + + Connection->Comment.Length = 0; + Connection->Comment.MaximumLength = 0; + } + +try_exit: + + NOTHING; + } + + return; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSProcessSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSProcessSupport.cpp new file mode 100644 index 0000000000..5c8e82e17d --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSProcessSupport.cpp @@ -0,0 +1,812 @@ +/* + * 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: AFSProcessSupport.cpp +// + +#include "AFSCommon.h" + +void +AFSProcessNotify( IN HANDLE ParentId, + IN HANDLE ProcessId, + IN BOOLEAN Create) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + AFSProcessAuthGroupCB *pProcessAuthGroup = NULL, *pLastAuthGroup = NULL; + AFSThreadCB *pThreadCB = NULL, *pNextThreadCB = NULL; + + __Enter + { + + // + // If this is a create notification then update our tree, otherwise remove the + // entry + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessNotify Acquiring Control ProcessTree.TreeLock lock %08lX EXCL %08lX\n", + pDeviceExt->Specific.Control.ProcessTree.TreeLock, + PsGetCurrentThread()); + + AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + if( Create) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessNotify CREATE Parent %08lX Process %08lX %08lX\n", + ParentId, + ProcessId, + PsGetCurrentThread()); + + pProcessCB = AFSInitializeProcessCB( (ULONGLONG)ParentId, + (ULONGLONG)ProcessId); + + if( pProcessCB != NULL) + { + pProcessCB->CreatingThread = (ULONGLONG)PsGetCurrentThreadId(); + } + + try_return( ntStatus); + } + + // + // It's a remove so pull the entry + // + + AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSProcessNotify DESTROY Process %08lX %08lX\n", + ProcessId, + PsGetCurrentThread()); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ProcessId, + (AFSBTreeEntry **)&pProcessCB); + + if( NT_SUCCESS( ntStatus) && + pProcessCB != NULL) + { + + AFSRemoveHashEntry( &pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (AFSBTreeEntry *)pProcessCB); + + pProcessAuthGroup = pProcessCB->AuthGroupList; + + while( pProcessAuthGroup != NULL) + { + + pLastAuthGroup = pProcessAuthGroup->Next; + + ExFreePool( pProcessAuthGroup); + + pProcessAuthGroup = pLastAuthGroup; + } + + pThreadCB = pProcessCB->ThreadList; + + while( pThreadCB != NULL) + { + + pNextThreadCB = pThreadCB->Next; + + ExFreePool( pThreadCB); + + pThreadCB = pNextThreadCB; + } + + ExDeleteResourceLite( &pProcessCB->Lock); + + ExFreePool( pProcessCB); + } + else + { + AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSProcessNotify Process %08lX not found in ProcessTree Status %08lX %08lX\n", + ProcessId, + ntStatus, + PsGetCurrentThread()); + } + +try_exit: + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + } + + return; +} + +// +// AFSValidateProcessEntry verifies the consistency of the current process +// entry which includes assigning an authentication group ACE if one is not +// present. A reference to the active authentication group GUID is returned. +// + +GUID * +AFSValidateProcessEntry( void) +{ + + GUID *pAuthGroup = NULL; + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId(); + UNICODE_STRING uniSIDString; + ULONG ulSIDHash = 0; + AFSSIDEntryCB *pSIDEntryCB = NULL; + ULONG ulSessionId = 0; + ULONGLONG ullTableHash = 0; + AFSThreadCB *pParentThreadCB = NULL; + UNICODE_STRING uniGUID; + BOOLEAN bImpersonation = FALSE; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSValidateProcessEntry Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n", + pDeviceExt->Specific.Control.ProcessTree.TreeLock, + PsGetCurrentThread()); + + uniSIDString.Length = 0; + uniSIDString.MaximumLength = 0; + uniSIDString.Buffer = NULL; + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Entry for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + 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); + + ASSERT( FALSE); + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + try_return( ntStatus = STATUS_UNSUCCESSFUL); + } + + // + // Locate and lock the ParentProcessCB if we have one + // + + if( pProcessCB->ParentProcessId != 0) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Locating process entry for Parent ProcessID %I64X\n", + __FUNCTION__, + pProcessCB->ParentProcessId); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)pProcessCB->ParentProcessId, + (AFSBTreeEntry **)&pParentProcessCB); + + if( NT_SUCCESS( ntStatus) && + pParentProcessCB != NULL) + { + AFSAcquireExcl( &pParentProcessCB->Lock, + TRUE); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located process entry for Parent ProcessID %I64X\n", + __FUNCTION__, + pProcessCB->ParentProcessId); + } + } + else + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s No parent ID for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + } + + AFSAcquireExcl( &pProcessCB->Lock, + TRUE); + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + + // + // Locate the SID for the caller + // + + ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "%s Failed to locate callers SID for ProcessID %I64X\n", + __FUNCTION__, + ullProcessID); + + 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\n", + __FUNCTION__, + ullProcessID); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Retrieved callers SID %wZ for ProcessID %I64X Session %08lX\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ulSessionId); + + // + // If there is an Auth Group for the current process, + // our job is finished. + // + + if ( bImpersonation == FALSE) + { + pAuthGroup = pProcessCB->ActiveAuthGroup; + + if( pAuthGroup != NULL && + !AFSIsNoPAGAuthGroup( pAuthGroup)) + { + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( *pAuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Located valid AuthGroup GUID %wZ for SID %wZ ProcessID %I64X Session %08lX\n", + __FUNCTION__, + &uniGUID, + &uniSIDString, + ullProcessID, + ulSessionId); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + try_return( ntStatus = STATUS_SUCCESS); + } + + // + // The current process does not yet have an Auth Group. Try to inherit + // one from the parent process thread that created this process. + // + + if( pParentProcessCB != NULL) + { + + for ( pParentThreadCB = pParentProcessCB->ThreadList; + pParentThreadCB != NULL; + pParentThreadCB = pParentThreadCB->Next) + { + + if( pParentThreadCB->ThreadId == pProcessCB->CreatingThread) + { + break; + } + } + + // + // If the creating thread was found and it has a thread specific + // Auth Group, use that even if it is the No PAG + // + + if( pParentThreadCB != NULL && + pParentThreadCB->ActiveAuthGroup != NULL && + !AFSIsNoPAGAuthGroup( pParentThreadCB->ActiveAuthGroup)) + { + pProcessCB->ActiveAuthGroup = pParentThreadCB->ActiveAuthGroup; + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s PID %08lX Session %08lX inherited Active AuthGroup %wZ from thread %I64X\n", + __FUNCTION__, + ullProcessID, + ulSessionId, + &uniGUID, + pParentThreadCB->ThreadId); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + } + + // + // If the parent thread was not found or does not have an auth group + // + + else if( pParentProcessCB->ActiveAuthGroup != NULL && + !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) + { + pProcessCB->ActiveAuthGroup = pParentProcessCB->ActiveAuthGroup; + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s PID %08lX Session %08lX inherited Active AuthGroup %wZ from parent PID %I64X\n", + __FUNCTION__, + ullProcessID, + ulSessionId, + &uniGUID, + pParentProcessCB->TreeEntry.HashIndex); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + } + + // + // If an Auth Group was inherited, set it to be the active group + // + + if( pProcessCB->ActiveAuthGroup != NULL && + !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup)) + { + pAuthGroup = pProcessCB->ActiveAuthGroup; + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Returning(1) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", + __FUNCTION__, + &uniGUID, + &uniSIDString, + ullProcessID, + ulSessionId); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + try_return( ntStatus); + } + } + } + + // + // If no Auth Group was inherited, assign one based upon the Session and SID + // + + 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 Session %08lX Status %08lX\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ulSessionId, + ntStatus); + + try_return( ntStatus); + } + + ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash); + + AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + (ULONGLONG)ullTableHash, + (AFSBTreeEntry **)&pSIDEntryCB); + + if( !NT_SUCCESS( ntStatus) || + pSIDEntryCB == NULL) + { + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + + AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + (ULONGLONG)ullTableHash, + (AFSBTreeEntry **)&pSIDEntryCB); + + if( !NT_SUCCESS( ntStatus) || + pSIDEntryCB == NULL) + { + + 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); + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s SID %wZ PID %I64X Session %08lX generated NEW AG %wZ\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ulSessionId, + &uniGUID); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL) + { + pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB; + } + else + { + AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead, + &pSIDEntryCB->TreeEntry); + } + } + + AFSConvertToShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + } + + + AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock); + + // + // Store the auth group into the process cb + // + + pProcessCB->ActiveAuthGroup = &pSIDEntryCB->AuthGroup; + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( pSIDEntryCB->AuthGroup, + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s SID %wZ PID %I64X Session %08lX assigned AG %wZ\n", + __FUNCTION__, + &uniSIDString, + ullProcessID, + ulSessionId, + &uniGUID); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + + // + // Set the AFS_PROCESS_LOCAL_SYSTEM_AUTH flag if the process SID + // is LOCAL_SYSTEM + // + + if( AFSIsLocalSystemSID( &uniSIDString)) + { + SetFlag( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Setting PID %I64X Session %08lX with LOCAL SYSTEM AUTHORITY\n", + __FUNCTION__, + ullProcessID, + ulSessionId); + } + + // + // Return the auth group + // + + pAuthGroup = pProcessCB->ActiveAuthGroup; + + uniGUID.Buffer = NULL; + + RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup), + &uniGUID); + + AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "%s Returning(2) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n", + __FUNCTION__, + &uniGUID, + &uniSIDString, + ullProcessID, + ulSessionId); + + if( uniGUID.Buffer != NULL) + { + RtlFreeUnicodeString( &uniGUID); + } + +try_exit: + + if( pProcessCB != NULL) + { + + if( bImpersonation == FALSE && + !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET) && + NT_SUCCESS( ntStatus)) + { + ntStatus = AFSProcessSetProcessDacl( pProcessCB); + + if( !NT_SUCCESS( ntStatus)) + { + pAuthGroup = NULL; + } + else + { + SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET); + } + } + + AFSReleaseResource( &pProcessCB->Lock); + } + + if( pParentProcessCB != NULL) + { + AFSReleaseResource( &pParentProcessCB->Lock); + } + + if( uniSIDString.Length > 0) + { + RtlFreeUnicodeString( &uniSIDString); + } + } + + return pAuthGroup; +} + +BOOLEAN +AFSIs64BitProcess( IN ULONGLONG ProcessId) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + BOOLEAN bIs64Bit = FALSE; + AFSProcessCB *pProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSIs64BitProcess Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n", + pDeviceExt->Specific.Control.ProcessTree.TreeLock, + PsGetCurrentThread()); + + AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock, + TRUE); + + ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + (ULONGLONG)ProcessId, + (AFSBTreeEntry **)&pProcessCB); + + if( pProcessCB != NULL) + { + bIs64Bit = BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); + } + + AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock); + } + + return bIs64Bit; +} + +AFSProcessCB * +AFSInitializeProcessCB( IN ULONGLONG ParentProcessId, + IN ULONGLONG ProcessId) +{ + + AFSProcessCB *pProcessCB = NULL; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + __Enter + { + + pProcessCB = (AFSProcessCB *)AFSExAllocatePoolWithTag( NonPagedPool, + sizeof( AFSProcessCB), + AFS_PROCESS_CB_TAG); + + if( pProcessCB == NULL) + { + try_return( pProcessCB); + } + + RtlZeroMemory( pProcessCB, + sizeof( AFSProcessCB)); + + pProcessCB->TreeEntry.HashIndex = (ULONGLONG)ProcessId; + + pProcessCB->ParentProcessId = (ULONGLONG)ParentProcessId; + +#if defined(_WIN64) + + if( !IoIs32bitProcess( NULL)) + { + SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT); + } + +#endif + + if( pDeviceExt->Specific.Control.ProcessTree.TreeHead == NULL) + { + pDeviceExt->Specific.Control.ProcessTree.TreeHead = (AFSBTreeEntry *)pProcessCB; + } + else + { + AFSInsertHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead, + &pProcessCB->TreeEntry); + } + + ExInitializeResourceLite( &pProcessCB->Lock); + + pProcessCB->ActiveAuthGroup = &AFSNoPAGAuthGroup; + +try_exit: + + NOTHING; + } + + return pProcessCB; +} + +AFSThreadCB * +AFSInitializeThreadCB( IN AFSProcessCB *ProcessCB, + IN ULONGLONG ThreadId) +{ + + AFSThreadCB *pThreadCB = NULL, *pCurrentThreadCB = NULL; + + __Enter + { + + pThreadCB = (AFSThreadCB *)AFSExAllocatePoolWithTag( NonPagedPool, + sizeof( AFSThreadCB), + AFS_PROCESS_CB_TAG); + + if( pThreadCB == NULL) + { + try_return( pThreadCB); + } + + RtlZeroMemory( pThreadCB, + sizeof( AFSThreadCB)); + + pThreadCB->ThreadId = ThreadId; + + if( ProcessCB->ThreadList == NULL) + { + ProcessCB->ThreadList = pThreadCB; + } + else + { + + pCurrentThreadCB = ProcessCB->ThreadList; + + while( pCurrentThreadCB != NULL) + { + + if( pCurrentThreadCB->Next == NULL) + { + pCurrentThreadCB->Next = pThreadCB; + break; + } + + pCurrentThreadCB = pCurrentThreadCB->Next; + } + } + +try_exit: + + NOTHING; + } + + return pThreadCB; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSQuota.cpp b/src/WINNT/afsrdr/kernel/fs/AFSQuota.cpp new file mode 100644 index 0000000000..423f200b60 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSQuota.cpp @@ -0,0 +1,104 @@ +/* + * 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: AFSQuota.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSQueryQuota( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSQueryQuota Entry for FO %08lX\n", + pIrpSp->FileObject); + + AFSCompleteRequest( Irp, + ntStatus); + + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSQueryQuota\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSSetQuota( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSSetQuota Entry for FO %08lX\n", + pIrpSp->FileObject); + + AFSCompleteRequest( Irp, + ntStatus); + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSSetQuota\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp b/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp new file mode 100644 index 0000000000..93354a82fc --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSRDRSupport.cpp @@ -0,0 +1,793 @@ +/* + * 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: AFSRDRSupport.cpp +// +#include "AFSCommon.h" + +typedef NTSTATUS (*FsRtlRegisterUncProviderEx_t)( PHANDLE MupHandle, PUNICODE_STRING RedirDevName, PDEVICE_OBJECT DeviceObject, ULONG Flags); + +NTSTATUS +AFSInitRDRDevice() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + UNICODE_STRING uniDeviceName; + ULONG ulIndex = 0; + AFSDeviceExt *pDeviceExt = NULL; + AFSFileID stRootFid; + UNICODE_STRING uniFsRtlRegisterUncProviderEx; + FsRtlRegisterUncProviderEx_t pFsRtlRegisterUncProviderEx = NULL; + + __Enter + { + + RtlInitUnicodeString( &uniDeviceName, + AFS_RDR_DEVICE_NAME); + + RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx, + L"FsRtlRegisterUncProviderEx"); + + pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx); + + ntStatus = IoCreateDevice( AFSDriverObject, + sizeof( AFSDeviceExt), + pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName, + FILE_DEVICE_NETWORK_FILE_SYSTEM, + FILE_REMOTE_DEVICE, + FALSE, + &AFSRDRDeviceObject); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitRDRDevice IoCreateDevice failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + + RtlZeroMemory( pDeviceExt, + sizeof( AFSDeviceExt)); + + // + // Initialize resources + // + + pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock; + + ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); + + pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL; + + ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); + + pDeviceExt->Specific.RDR.VolumeListHead = NULL; + + pDeviceExt->Specific.RDR.VolumeListTail = NULL; + + KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent, + NotificationEvent, + TRUE); + + ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); + + pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock; + + pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL; + + ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); + + // + // Clear the initializing bit + // + + AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + // + // Register this device with MUP with FilterMgr if Vista or above + // + + if( pFsRtlRegisterUncProviderEx) + { + + ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle, + &uniDeviceName, + AFSRDRDeviceObject, + 0); + if ( !NT_SUCCESS( ntStatus)) + { + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", + ntStatus); + } + } + else + { + + ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle, + &uniDeviceName, + FALSE); + + if ( NT_SUCCESS( ntStatus)) + { + + IoRegisterFileSystem( AFSRDRDeviceObject); + } + else + { + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n", + ntStatus); + } + } + + if( !NT_SUCCESS( ntStatus)) + { + + // + // Delete our device and bail + // + + ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock); + + ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock); + + ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock); + + ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock); + + IoDeleteDevice( AFSRDRDeviceObject); + + AFSRDRDeviceObject = NULL; + + try_return( ntStatus); + } + + // + // Good to go, all registered and ready to start receiving requests + // + +try_exit: + + if( !NT_SUCCESS( ntStatus)) + { + + } + } + + return ntStatus; +} + +NTSTATUS +AFSRDRDeviceControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp); + PFILE_OBJECT pFileObject = pIrpSp->FileObject; + BOOLEAN bCompleteIrp = TRUE; + + __Enter + { + + switch( pIrpSp->Parameters.DeviceIoControl.IoControlCode) + { + + case IOCTL_REDIR_QUERY_PATH: + { + + QUERY_PATH_REQUEST *pPathRequest = (QUERY_PATH_REQUEST *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer; + UNICODE_STRING uniPathName; + + ntStatus = STATUS_BAD_NETWORK_PATH; + + uniPathName.Length = (USHORT)pPathRequest->PathNameLength; + uniPathName.MaximumLength = uniPathName.Length; + + uniPathName.Buffer = pPathRequest->FilePathName; + + if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR)) + { + + USHORT usLength = uniPathName.Length; + + uniPathName.Length = AFSServerName.Length; + + // + // Skip over the first slash in the name + // + + uniPathName.Buffer = &uniPathName.Buffer[ 1]; + + + // + // Check to see if the first (or only) component + // of the path matches the server name + // + + if( RtlCompareUnicodeString( &AFSServerName, + &uniPathName, + TRUE) == 0 && + ( usLength == AFSServerName.Length + sizeof( WCHAR) || + uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\')) + { + + ntStatus = STATUS_SUCCESS; + + pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR); + } + } + + break; + } + + case IOCTL_REDIR_QUERY_PATH_EX: + { + + QUERY_PATH_REQUEST_EX *pPathRequest = (QUERY_PATH_REQUEST_EX *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer; + UNICODE_STRING uniPathName; + + ntStatus = STATUS_BAD_NETWORK_PATH; + + uniPathName.Length = pPathRequest->PathName.Length; + uniPathName.MaximumLength = uniPathName.Length; + + uniPathName.Buffer = pPathRequest->PathName.Buffer; + + if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR)) + { + + USHORT usLength = uniPathName.Length; + + uniPathName.Length = AFSServerName.Length; + + // + // Skip over the first slash in the name + // + + uniPathName.Buffer = &uniPathName.Buffer[ 1]; + + + // + // Check to see if the first (or only) component + // of the path matches the server name + // + + if( RtlCompareUnicodeString( &AFSServerName, + &uniPathName, + TRUE) == 0 && + ( usLength == AFSServerName.Length + sizeof( WCHAR) || + uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\')) + { + + ntStatus = STATUS_SUCCESS; + + pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR); + } + } + + break; + } + + default: + + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + break; + } + + if (bCompleteIrp) + { + // + // Complete the request + // + + AFSCompleteRequest( Irp, + ntStatus); + } + } + + return ntStatus; +} + +NTSTATUS +AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + LARGE_INTEGER cacheSizeBytes; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + OBJECT_ATTRIBUTES stObjectAttribs; + IO_STATUS_BLOCK stIoStatus; + UNICODE_STRING uniServiceName; + + __Enter + { + + // + // First this is to load the library + // + + RtlInitUnicodeString( &uniServiceName, + AFS_REDIR_LIBRARY_SERVICE_ENTRY); + + ntStatus = AFSLoadLibrary( 0, + &uniServiceName); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + // + // Save off the cache file information + // + + pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; + + pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; + + pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; + + cacheSizeBytes = RedirInitInfo->ExtentCount; + cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; + + AFSDumpFileLocation.Length = 0; + + AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); + + AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + AFSDumpFileLocation.MaximumLength, + AFS_GENERIC_MEMORY_23_TAG); + + if( AFSDumpFileLocation.Buffer == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlCopyMemory( AFSDumpFileLocation.Buffer, + L"\\??\\", + 4 * sizeof( WCHAR)); + + AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); + + RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], + (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), + RedirInitInfo->DumpFileLocationLength); + + AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; + + // + // Be sure the shutdown flag is not set + // + + ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); + + // + // Set up the Throttles. + // + // Max IO is 10% of the cache, or the value in the registry, + // with a minimum of 5Mb (and a maximum of 50% cache size) + // + if( AFSMaxDirectIo) + { + // + // collect what the user + // + pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; + pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); + + } + else + { + + pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; + } + + if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) + { + + pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; + + } + + // + // For small cache configurations ... + // + + if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) + { + + pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; + } + + // + // Maximum Dirty is 50% of the cache, or the value in the + // registry. No minimum, maximum of 90% of cache size. + // + if (AFSMaxDirtyFile) + { + + pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; + pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); + + } + else + { + + pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; + + } + + cacheSizeBytes.QuadPart *= 9; + cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; + + if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) + { + pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; + } + + // + // Store off any flags for the file system + // + + if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) + { + + // + // Hide files which begin with . + // + + SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); + } + + if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && + RedirInitInfo->MemoryCacheLength.QuadPart != 0) + { + + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + +#ifdef AMD64 + pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, + (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, + RedirInitInfo->MemoryCacheLength.QuadPart); +#else + pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, + (void *)RedirInitInfo->MemoryCacheOffset.LowPart, + RedirInitInfo->MemoryCacheLength.LowPart); +#endif + + if( pDevExt->Specific.RDR.CacheMdl != NULL) + { + + __try + { + + MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, + KernelMode, + IoModifyAccess); + + pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, + NormalPagePriority); + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); + pDevExt->Specific.RDR.CacheMdl = NULL; + } + + if( pDevExt->Specific.RDR.CacheMdl != NULL) + { + pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; + ntStatus = STATUS_SUCCESS; + } + + } + } + + if( !NT_SUCCESS( ntStatus) && + RedirInitInfo->CacheFileNameLength == 0) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector Unable to initialize cache file %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + if( pDevExt->Specific.RDR.CacheMdl == NULL) + { + + if( RedirInitInfo->CacheFileNameLength == 0) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector CacheMdl == NULL\n"); + + try_return( ntStatus = STATUS_INVALID_PARAMETER); + } + + // + // Go open the cache file + // + + pDevExt->Specific.RDR.CacheFile.Length = 0; + pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR)); + + pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, + pDevExt->Specific.RDR.CacheFile.MaximumLength, + AFS_GENERIC_MEMORY_24_TAG); + + if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n"); + + try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); + } + + RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer, + L"\\??\\", + 4 * sizeof( WCHAR)); + + pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR); + + RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)], + RedirInitInfo->CacheFileName, + RedirInitInfo->CacheFileNameLength); + + pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength; + + InitializeObjectAttributes( &stObjectAttribs, + &pDevExt->Specific.RDR.CacheFile, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle, + GENERIC_READ | GENERIC_WRITE, + &stObjectAttribs, + &stIoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector ZwOpenFile failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + + // + // Map to the fileobject + // + + ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle, + SYNCHRONIZE, + NULL, + KernelMode, + (void **)&pDevExt->Specific.RDR.CacheFileObject, + NULL); + + if( !NT_SUCCESS( ntStatus)) + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n", + ntStatus); + + try_return( ntStatus); + } + } + + pDevExt->Specific.RDR.MaxLinkCount = RedirInitInfo->MaxPathLinkCount; + + pDevExt->Specific.RDR.NameArrayLength = RedirInitInfo->NameArrayLength; + + // + // Intialize the library + // + + ntStatus = AFSInitializeLibrary( &RedirInitInfo->GlobalFileId, + TRUE); + + if ( !NT_SUCCESS( ntStatus)) + { + AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, + AFS_TRACE_LEVEL_ERROR, + "AFSInitializeRedirector AFSInitializeLibrary failure %08lX\n", + ntStatus); + } + +try_exit: + + if( !NT_SUCCESS( ntStatus)) + { + + if( pDevExt->Specific.RDR.CacheMdl != NULL) + { + + MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress, + pDevExt->Specific.RDR.CacheMdl); + + MmUnlockPages( pDevExt->Specific.RDR.CacheMdl); + + ExFreePool( pDevExt->Specific.RDR.CacheMdl); + + pDevExt->Specific.RDR.CacheMdl = NULL; + pDevExt->Specific.RDR.CacheBaseAddress = NULL; + pDevExt->Specific.RDR.CacheLength.QuadPart = 0; + } + + if( pDevExt->Specific.RDR.CacheFileHandle != NULL) + { + + ZwClose( pDevExt->Specific.RDR.CacheFileHandle); + + pDevExt->Specific.RDR.CacheFileHandle = NULL; + } + + if( pDevExt->Specific.RDR.CacheFileObject != NULL) + { + + ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject); + + pDevExt->Specific.RDR.CacheFileObject = NULL; + } + + if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL) + { + + ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer); + + pDevExt->Specific.RDR.CacheFile.Buffer = NULL; + } + + if( AFSDumpFileLocation.Buffer != NULL) + { + ExFreePool( AFSDumpFileLocation.Buffer); + + AFSDumpFileLocation.Buffer = NULL; + } + + AFSUnloadLibrary( TRUE); + } + } + + return ntStatus; +} + +NTSTATUS +AFSCloseRedirector() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; + + __Enter + { + + // + // Unload the library first so we close off any accesses to the cache or underlying + // shared memory + // + + AFSUnloadLibrary( TRUE); + + // + // Close off the cache file or mapping + // + + if( pDevExt->Specific.RDR.CacheMdl != NULL) + { + + MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress, + pDevExt->Specific.RDR.CacheMdl); + + MmUnlockPages( pDevExt->Specific.RDR.CacheMdl); + + ExFreePool( pDevExt->Specific.RDR.CacheMdl); + + pDevExt->Specific.RDR.CacheMdl = NULL; + pDevExt->Specific.RDR.CacheBaseAddress = NULL; + pDevExt->Specific.RDR.CacheLength.QuadPart = 0; + } + + if( pDevExt->Specific.RDR.CacheFileHandle != NULL) + { + + ZwClose( pDevExt->Specific.RDR.CacheFileHandle); + + pDevExt->Specific.RDR.CacheFileHandle = NULL; + } + + if( pDevExt->Specific.RDR.CacheFileObject != NULL) + { + + ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject); + + pDevExt->Specific.RDR.CacheFileObject = NULL; + } + + if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL) + { + + ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer); + + pDevExt->Specific.RDR.CacheFile.Buffer = NULL; + } + + if( AFSDumpFileLocation.Buffer != NULL) + { + ExFreePool( AFSDumpFileLocation.Buffer); + + AFSDumpFileLocation.Buffer = NULL; + } + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSRead.cpp b/src/WINNT/afsrdr/kernel/fs/AFSRead.cpp new file mode 100644 index 0000000000..877813eb10 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSRead.cpp @@ -0,0 +1,111 @@ +/* + * 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: AFSRead.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSRead +// +// Description: +// +// A shim around AFSCommonRead +// + +NTSTATUS +AFSRead( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + 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()) ) + { + + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSRedirInstall.inf b/src/WINNT/afsrdr/kernel/fs/AFSRedirInstall.inf new file mode 100644 index 0000000000..85e2a06436 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSRedirInstall.inf @@ -0,0 +1,84 @@ +;;; +;;; AFS Redirector Installation file +;;; + +[Version] +signature = "$Windows NT$" +Class = "AFSRedirector" +ClassGuid = {63EA509E-71F9-42ec-9C5E-1ECC95E3A1A0} +Provider = %AFS% +DriverVer = 04/20/2006,1.0.0.0 + +[DestinationDirs] +DefaultDestDir = 12 +AFS.DriverFiles = 12 + +;; +;; Default install sections +;; + +[DefaultInstall] +CopyFiles = AFS.DriverFiles + +[SourceDisksNames] +1 = %Disk1% + +[SourceDisksFiles] +AFSRedir.sys = 1 + +[DefaultInstall.Services] +AddService = %AFSServiceName%,,AFS.Service + +;; +;; Default uninstall sections +;; + +[DefaultUninstall] +DelFiles = AFS.DriverFiles +DelReg = AFS.DelRegistry + +; +; Services Section +; + +[AFS.Service] +DisplayName = %AFSServiceName% +Description = %AFSServiceDesc% +ServiceBinary = %12%\AFSRedir.sys +ServiceType = 2 +StartType = 1 +ErrorControl = 1 +LoadOrderGroup = "Filesystem" +AddReg = AFS.AddRegistry + +; +; Registry Modifications +; + +[AFS.AddRegistry] +HKLM,%AFSRegistry%,%AFSTraceLevel%,0x00010001 ,0x0001 +HKLM,%AFSRegistry%,%AFSDebugFlags%,0x00010001 ,0x0000 + +[AFS.DelRegistry] +HKLM,%AFSRegistry%,%AFSTraceLevel% +HKLM,%AFSRegistry%,%AFSDebugFlags% + +; +; Copy Files +; + +[AFS.DriverFiles] +AFSRedir.sys + +;; +;; String Section +;; + +[Strings] +AFS = "OpenAFS" +AFSServiceDesc = "OpenAFS Redirector" +AFSServiceName = "AFSRedirector" +AFSRegistry = "system\currentcontrolset\services\AFSRedirector\Parameters" +AFSTraceLevel = "TraceLevel" +AFSDebugFlags = "DebugFlags" +Disk1 = "OpenAFS Media" diff --git a/src/WINNT/afsrdr/kernel/fs/AFSSecurity.cpp b/src/WINNT/afsrdr/kernel/fs/AFSSecurity.cpp new file mode 100644 index 0000000000..bb43806442 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSSecurity.cpp @@ -0,0 +1,217 @@ +/* + * 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: AFSSecurity.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSSetSecurity( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + IO_STACK_LOCATION *pIrpSp; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSSetSecurity Entry for FO %08lX\n", + pIrpSp->FileObject); + + 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 - AFSSetSecurity\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSQuerySecurity( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; + IO_STACK_LOCATION *pIrpSp; + AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_VERBOSE, + "AFSQuerySecurity Entry for FO %08lX\n", + pIrpSp->FileObject); + + 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 - AFSQuerySecurity\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSShutdown.cpp b/src/WINNT/afsrdr/kernel/fs/AFSShutdown.cpp new file mode 100644 index 0000000000..4fb66bf781 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSShutdown.cpp @@ -0,0 +1,100 @@ +/* + * 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: AFSShutdown.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSShutdown( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STACK_LOCATION *pIrpSp; + UNICODE_STRING uniValueName; + ULONG ulValue = 0; + + __try + { + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_REQUIRE_CLEAN_SHUTDOWN)) + { + + ulValue = 1; + + RtlInitUnicodeString( &uniValueName, + AFS_REG_SHUTDOWN_STATUS); + + AFSUpdateRegistryParameter( &uniValueName, + REG_DWORD, + &ulValue, + sizeof( ULONG)); + } + + ntStatus = AFSShutdownFilesystem(); + + if( !NT_SUCCESS( ntStatus)) + { + + ntStatus = STATUS_SUCCESS; + } + + AFSCompleteRequest( Irp, + ntStatus); + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSShutdown\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSShutdownFilesystem() +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSSystemControl.cpp b/src/WINNT/afsrdr/kernel/fs/AFSSystemControl.cpp new file mode 100644 index 0000000000..b80c2adc12 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSSystemControl.cpp @@ -0,0 +1,72 @@ +/* + * 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: AFSSystemControl.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSSystemControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_NOT_IMPLEMENTED; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSSystemControl Entry for FO %08lX\n", + pIrpSp->FileObject); + + AFSCompleteRequest( Irp, + ntStatus); + + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSSystemControl\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSVolumeInfo.cpp b/src/WINNT/afsrdr/kernel/fs/AFSVolumeInfo.cpp new file mode 100644 index 0000000000..9abf890ce2 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSVolumeInfo.cpp @@ -0,0 +1,141 @@ +/* + * 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: AFSVolumeInfo.cpp +// + +#include "AFSCommon.h" + +NTSTATUS +AFSQueryVolumeInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension; + 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 - AFSQueryVolumeInfo\n"); + } + + return ntStatus; +} + +NTSTATUS +AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + IO_STACK_LOCATION *pIrpSp; + + pIrpSp = IoGetCurrentIrpStackLocation( Irp); + + __try + { + + AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSSetVolumeInfo Entry for FO %08lX\n", pIrpSp->FileObject); + + AFSCompleteRequest( Irp, + ntStatus); + + } + __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) + { + + AFSDbgLogMsg( 0, + 0, + "EXCEPTION - AFSSetVolumeInfo\n"); + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp b/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp new file mode 100644 index 0000000000..d2cfeadb92 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/AFSWrite.cpp @@ -0,0 +1,115 @@ +/* + * 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: AFSWrite.cpp +// + +#include "AFSCommon.h" + +// +// Function: AFSWrite +// +// Description: +// +// This is the dispatch handler for the IRP_MJ_WRITE request +// +// Return: +// +// A status is returned for the function +// + +NTSTATUS +AFSWrite( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + + NTSTATUS ntStatus = STATUS_SUCCESS; + 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()) ) + { + + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + return ntStatus; +} diff --git a/src/WINNT/afsrdr/kernel/fs/Filesystem.rc b/src/WINNT/afsrdr/kernel/fs/Filesystem.rc new file mode 100644 index 0000000000..8c00a71bd2 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/Filesystem.rc @@ -0,0 +1,15 @@ +/* + * Copyright 2010, Secure Endpoints Inc. + * All Rights Reserved. + * + * This software has been released under the terms of the MIT License. + */ + +/* Define VERSIONINFO resource */ + +#define AFS_VERINFO_FILE_DESCRIPTION "AFS Redirector File System" +#define AFS_VERINFO_NAME "AFSRedir" +#define AFS_VERINFO_FILENAME "AFSRedir.sys" + +#include "..\..\AFS_component_version_number.h" +#include "..\..\..\..\config\NTVersioninfo.rc" diff --git a/src/WINNT/afsrdr/kernel/fs/Include/AFSCommon.h b/src/WINNT/afsrdr/kernel/fs/Include/AFSCommon.h new file mode 100644 index 0000000000..6ab3472a99 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/Include/AFSCommon.h @@ -0,0 +1,809 @@ +/* + * 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. + */ + +#ifndef _AFS_COMMON_H +#define _AFS_COMMON_H + +// +// File: AFSCommon.h +// + +extern "C" +{ + +#define AFS_KERNEL_MODE + +#include +#include // for IoCreateDeviceSecure +#include + +#include "AFSDefines.h" + +#include "AFSUserDefines.h" + +#include "AFSUserIoctl.h" + +#include "AFSUserStructs.h" + +#include "AFSRedirCommonDefines.h" + +#include "AFSRedirCommonStructs.h" + +#include "AFSStructs.h" + +#include "AFSProvider.h" + +#ifndef NO_EXTERN +#include "AFSExtern.h" +#endif + +#define NTSTRSAFE_LIB +#include "ntstrsafe.h" + +NTSTATUS +ZwQueryInformationProcess( + __in HANDLE ProcessHandle, + __in PROCESSINFOCLASS ProcessInformationClass, + __out PVOID ProcessInformation, + __in ULONG ProcessInformationLength, + __out_opt PULONG ReturnLength +); + +// +// AFSInit.cpp Prototypes +// + +NTSTATUS +DriverEntry( IN PDRIVER_OBJECT DriverObj, + IN PUNICODE_STRING RegPath); + +void +AFSUnload( IN PDRIVER_OBJECT DriverObject); + +// +// AFSAuthGroupSupport.cpp +// + +void +AFSRetrieveAuthGroup( IN ULONGLONG ProcessId, + IN ULONGLONG ThreadId, + OUT GUID *AuthGroup); + +BOOLEAN +AFSIsLocalSystemAuthGroup( IN GUID *AuthGroup); + +BOOLEAN +AFSIsLocalSystemSID( IN UNICODE_STRING *SIDString); + +BOOLEAN +AFSIsNoPAGAuthGroup( IN GUID *AuthGroup); + +NTSTATUS +AFSCreateSetProcessAuthGroup( AFSAuthGroupRequestCB *CreateSetAuthGroup); + +NTSTATUS +AFSQueryProcessAuthGroupList( IN GUID *GUIDList, + IN ULONG BufferLength, + OUT ULONG_PTR *ReturnLength); + +NTSTATUS +AFSSetActiveProcessAuthGroup( IN AFSAuthGroupRequestCB *ActiveAuthGroup); + +NTSTATUS +AFSResetActiveProcessAuthGroup( IN AFSAuthGroupRequestCB *ActiveAuthGroup); + +NTSTATUS +AFSCreateAuthGroupForSIDorLogonSession( IN AFSAuthGroupRequestCB *AuthGroupRequestCB, + IN BOOLEAN bLogonSession); + +NTSTATUS +AFSQueryAuthGroup( IN AFSAuthGroupRequestCB *AuthGroupRequestCB, + OUT GUID *AuthGroupGUID, + OUT ULONG_PTR *ReturnLength); + +// +// AFSBTreeSupport.cpp Prototypes +// + +NTSTATUS +AFSLocateHashEntry( IN AFSBTreeEntry *TopNode, + IN ULONGLONG HashIndex, + IN OUT AFSBTreeEntry **TreeEntry); + +NTSTATUS +AFSInsertHashEntry( IN AFSBTreeEntry *TopNode, + IN AFSBTreeEntry *FileIDEntry); + +NTSTATUS +AFSRemoveHashEntry( IN AFSBTreeEntry **TopNode, + IN AFSBTreeEntry *FileIDEntry); + +// +// AFSCommSupport.cpp Prototypes +// + +NTSTATUS +AFSReleaseFid( IN AFSFileID *FileId); + +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 +AFSProcessControlRequest( IN PIRP Irp); + +NTSTATUS +AFSInitIrpPool( void); + +void +AFSCleanupIrpPool( void); + +NTSTATUS +AFSProcessIrpRequest( IN PIRP Irp); + +NTSTATUS +AFSProcessIrpResult( IN PIRP Irp); + +NTSTATUS +AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc, + IN AFSPoolEntry *Entry); + +// +// AFSCreate.cpp Prototypes +// + +NTSTATUS +AFSCreate( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSControlDeviceCreate( IN PIRP Irp); + +NTSTATUS +AFSOpenRedirector( IN PIRP Irp); + +// +// AFSClose.cpp Prototypes +// + +NTSTATUS +AFSClose( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSCommonClose( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSNetworkProviderSupport.cpp +// + +NTSTATUS +AFSAddConnectionEx( IN UNICODE_STRING *RemoteName, + IN ULONG DisplayType, + IN ULONG Flags); + +void +AFSInitializeConnectionInfo( IN AFSProviderConnectionCB *Connection, + IN ULONG DisplayType); + +// +// AFSRead.cpp Prototypes +// + +NTSTATUS +AFSRead( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSWrite.cpp Prototypes +// + +NTSTATUS +AFSWrite( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSFileInfo.cpp Prototypes +// + +NTSTATUS +AFSQueryFileInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetFileInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSEa.cpp Prototypes +// + +NTSTATUS +AFSQueryEA( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetEA( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSFlushBuffers.cpp Prototypes +// + +NTSTATUS +AFSFlushBuffers( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSVolumeInfo.cpp Prototypes +// + +NTSTATUS +AFSQueryVolumeInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSDirControl.cpp Prototypes +// + +NTSTATUS +AFSDirControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSFSControl.cpp Prototypes +// + +NTSTATUS +AFSFSControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSDevControl.cpp Prototypes +// + +NTSTATUS +AFSDevControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSInternalDevControl.cpp Prototypes +// + +NTSTATUS +AFSInternalDevControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSShutdown.cpp Prototypes +// + +NTSTATUS +AFSShutdown( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +NTSTATUS +AFSShutdownFilesystem( void); + +// +// AFSLockControl.cpp Prototypes +// + +NTSTATUS +AFSLockControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSCleanup.cpp Prototypes +// + +NTSTATUS +AFSCleanup( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSCommonCleanup( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSSecurity.cpp Prototypes +// + +NTSTATUS +AFSQuerySecurity( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetSecurity( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSSystemControl.cpp Prototypes +// + +NTSTATUS +AFSSystemControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSQuota.cpp Prototypes +// + +NTSTATUS +AFSQueryQuota( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSSetQuota( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// +// AFSGeneric.cpp Prototypes +// + +ULONG +AFSExceptionFilter( IN ULONG Code, + IN PEXCEPTION_POINTERS ExceptPtrs); + +BOOLEAN +AFSAcquireExcl( IN PERESOURCE Resource, + IN BOOLEAN wait); + +BOOLEAN +AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource, + IN BOOLEAN Wait); + +BOOLEAN +AFSAcquireShared( IN PERESOURCE Resource, + IN BOOLEAN wait); + +void +AFSReleaseResource( IN PERESOURCE Resource); + +void +AFSConvertToShared( IN PERESOURCE Resource); + +void +AFSCompleteRequest( IN PIRP Irp, + IN ULONG Status); + +NTSTATUS +AFSReadRegistry( IN PUNICODE_STRING RegistryPath); + +NTSTATUS +AFSUpdateRegistryParameter( IN PUNICODE_STRING ValueName, + IN ULONG ValueType, + IN void *ValueData, + IN ULONG ValueDataLength); + +NTSTATUS +AFSInitializeControlDevice( void); + +NTSTATUS +AFSRemoveControlDevice( void); + +NTSTATUS +AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + +void +AFSInitServerStrings( void); + +NTSTATUS +AFSReadServerName( void); + +NTSTATUS +AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo, + IN ULONG SysNameInfoBufferLength); + +void +AFSResetSysNameList( IN AFSSysNameCB *SysNameList); + +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); + +void * +AFSExAllocatePoolWithTag( IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag); + +void +AFSExFreePool( IN void *Buffer); + +NTSTATUS +AFSShutdownRedirector( void); + +BOOLEAN +AFSAcquireFcbForLazyWrite( IN PVOID Fcb, + IN BOOLEAN Wait); + +VOID +AFSReleaseFcbFromLazyWrite( IN PVOID Fcb); + +BOOLEAN +AFSAcquireFcbForReadAhead( IN PVOID Fcb, + IN BOOLEAN Wait); + +VOID +AFSReleaseFcbFromReadAhead( IN PVOID Fcb); + +NTSTATUS +AFSGetCallerSID( OUT UNICODE_STRING *SIDString, + OUT BOOLEAN *pbImpersonation); + +ULONG +AFSGetSessionId( IN HANDLE ProcessId, + OUT BOOLEAN *pbImpersonation); + +NTSTATUS +AFSCheckThreadDacl( OUT GUID *AuthGroup); + +NTSTATUS +AFSProcessSetProcessDacl( IN AFSProcessCB *ProcessCB); + +// +// Prototypes in AFSFastIoSupprt.cpp +// + +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 +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 +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 +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 +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 +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 +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 +AFSFastIoUnlockAll( IN struct _FILE_OBJECT *FileObject, + IN PEPROCESS ProcessId, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject); + +BOOLEAN +AFSFastIoUnlockAllByKey( IN struct _FILE_OBJECT *FileObject, + IN PVOID ProcessId, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject); + +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); + +VOID +AFSFastIoAcquireFile( IN struct _FILE_OBJECT *FileObject); + +VOID +AFSFastIoReleaseFile( IN struct _FILE_OBJECT *FileObject); + +VOID +AFSFastIoDetachDevice( IN struct _DEVICE_OBJECT *SourceDevice, + IN struct _DEVICE_OBJECT *TargetDevice); + +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 +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 +AFSFastIoMdlReadComplete( IN struct _FILE_OBJECT *FileObject, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject); + +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 +AFSFastIoMdlWriteComplete( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject); + +NTSTATUS +AFSFastIoAcquireForModWrite( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT struct _ERESOURCE **ResourceToRelease, + IN struct _DEVICE_OBJECT *DeviceObject); + +NTSTATUS +AFSFastIoReleaseForModWrite( IN struct _FILE_OBJECT *FileObject, + IN struct _ERESOURCE *ResourceToRelease, + IN struct _DEVICE_OBJECT *DeviceObject); + +NTSTATUS +AFSFastIoAcquireForCCFlush( IN struct _FILE_OBJECT *FileObject, + IN struct _DEVICE_OBJECT *DeviceObject); + +NTSTATUS +AFSFastIoReleaseForCCFlush( IN struct _FILE_OBJECT *FileObject, + IN struct _DEVICE_OBJECT *DeviceObject); + +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 +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 +AFSFastIoMdlReadCompleteCompressed( IN struct _FILE_OBJECT *FileObject, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject); + +BOOLEAN +AFSFastIoMdlWriteCompleteCompressed( IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN struct _DEVICE_OBJECT *DeviceObject); + +BOOLEAN +AFSFastIoQueryOpen( IN struct _IRP *Irp, + OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + IN struct _DEVICE_OBJECT *DeviceObject); + +// +// AFSLibrarySupport.cpp Prototypes +// + +NTSTATUS +AFSLoadLibrary( IN ULONG Flags, + IN UNICODE_STRING *ServicePath); + +NTSTATUS +AFSUnloadLibrary( IN BOOLEAN CancelQueue); + +NTSTATUS +AFSCheckLibraryState( IN PIRP Irp); + +NTSTATUS +AFSClearLibraryRequest( void); + +NTSTATUS +AFSQueueLibraryRequest( IN PIRP Irp); + +NTSTATUS +AFSProcessQueuedResults( IN BOOLEAN CancelRequest); + +NTSTATUS +AFSSubmitLibraryRequest( IN PIRP Irp); + +NTSTATUS +AFSInitializeLibrary( IN AFSFileID *GlobalRootFid, + IN BOOLEAN QueueRootEnumeration); + +// +// AFSRDRSupport.cpp Prototypes +// + +NTSTATUS +AFSInitRDRDevice( void); + +NTSTATUS +AFSRDRDeviceControl( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +AFSInitializeRedirector( IN AFSRedirectorInitInfo *CacheFileInfo); + +NTSTATUS +AFSCloseRedirector( void); + +// +// AFSLogSupport.cpp +// + +NTSTATUS +AFSDbgLogMsg( IN ULONG Subsystem, + IN ULONG Level, + IN PCCH Format, + ...); + +NTSTATUS +AFSInitializeDbgLog( void); + +NTSTATUS +AFSTearDownDbgLog( void); + +NTSTATUS +AFSConfigureTrace( IN AFSTraceConfigCB *TraceInfo); + +NTSTATUS +AFSGetTraceBuffer( IN ULONG TraceBufferLength, + OUT void *TraceBuffer, + OUT ULONG_PTR *CopiedLength); + +void +AFSTagInitialLogEntry( void); + +void +AFSDumpTraceFiles( void); + +NTSTATUS +AFSInitializeDumpFile( void); + +// +// AFSProcessSupport.cpp Prototypes +// + +void +AFSProcessNotify( IN HANDLE ParentId, + IN HANDLE ProcessId, + IN BOOLEAN Create); + +GUID * +AFSValidateProcessEntry( void); + +BOOLEAN +AFSIs64BitProcess( IN ULONGLONG ProcessId); + +AFSProcessCB * +AFSInitializeProcessCB( IN ULONGLONG ParentProcessId, + IN ULONGLONG ProcessId); + +AFSThreadCB * +AFSInitializeThreadCB( IN AFSProcessCB *ProcessCB, + IN ULONGLONG ThreadId); + +}; + +#endif /* _AFS_COMMON_H */ diff --git a/src/WINNT/afsrdr/kernel/fs/Include/AFSDefines.h b/src/WINNT/afsrdr/kernel/fs/Include/AFSDefines.h new file mode 100644 index 0000000000..88851b4e7a --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/Include/AFSDefines.h @@ -0,0 +1,348 @@ +/* + * 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. + */ + +#ifndef _AFS_DEFINES_H +#define _AFS_DEFINES_H +// +// File: AFSDefines.h +// + +// +// Registry names +// + +#define AFS_REG_DEBUG_FLAGS L"DebugFlags" +#define AFS_REG_TRACE_LEVEL L"TraceLevel" +#define AFS_REG_TRACE_SUBSYSTEM L"TraceSubsystem" +#define AFS_REG_TRACE_BUFFER_LENGTH L"TraceBufferSize" // in KB +#define AFS_REG_MAX_DIRTY L"MaxDirtyMb" +#define AFS_REG_MAX_IO L"MaxIOMb" +#define AFS_NETBIOS_NAME L"NetbiosName" +#define AFS_REG_SHUTDOWN_STATUS L"ShutdownStatus" +#define AFS_REG_REQUIRE_CLEAN_SHUTDOWN L"RequireCleanShutdown" + +// +// Control Device name +// + +#define AFS_CONTROL_DEVICE_NAME L"\\Device\\AFSControlDevice" +#define AFS_SYMLINK_NAME L"\\??\\AFSRedirector" + +// +// How big to make the runs +// +#define AFS_MAX_STACK_IO_RUNS 5 + +#ifndef FlagOn +#define FlagOn(_F,_SF) ((_F) & (_SF)) +#endif + +#ifndef BooleanFlagOn +#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0)) +#endif + +#ifndef SetFlag +#define SetFlag(_F,_SF) ((_F) |= (_SF)) +#endif + +#ifndef ClearFlag +#define ClearFlag(_F,_SF) ((_F) &= ~(_SF)) +#endif + +#define QuadAlign(Ptr) ( \ + ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \ + ) + +#define CRC32_POLYNOMIAL 0xEDB88320L; + +// +// Define one second in terms of 100 nS units +// + +#define AFS_ONE_SECOND 10000000 + +#define AFS_SERVER_FLUSH_DELAY 30 +#define AFS_SERVER_PURGE_DELAY 60 +// +// PURGE_SLEEP is the number of PURGE_DELAYS we wait before we will unilaterally +// give back extents. +// +// If the Service asks us, we will start at PURGE_SLEEP of delays and then work back +// +#define AFS_SERVER_PURGE_SLEEP 6 + +// +// Read ahead granularity +// + +#define READ_AHEAD_GRANULARITY 0x10000 // 64KB + +#define AFS_DIR_ENUM_BUFFER_LEN (16 * 1024) + +// +// IS_BYTE_OFFSET_WRITE_TO_EOF +// liOffset - should be from Irp.StackLocation.Parameters.Write.ByteOffset +// this macro checks to see if the Offset Large_Integer points to the +// special constant value which denotes to start the write at EndOfFile +// +#define IS_BYTE_OFFSET_WRITE_TO_EOF(liOffset) \ + (((liOffset).LowPart == FILE_WRITE_TO_END_OF_FILE) \ + && ((liOffset).HighPart == 0xFFFFFFFF)) + +// +// Ccb Directory enum flags +// + +#define CCB_FLAG_DIR_OF_DIRS_ONLY 0x00000001 +#define CCB_FLAG_FULL_DIRECTORY_QUERY 0x00000002 +#define CCB_FLAG_MASK_CONTAINS_WILD_CARDS 0x00000004 +#define CCB_FLAG_FREE_FULL_PATHNAME 0x00000008 +#define CCB_FLAG_RETURN_RELATIVE_ENTRIES 0x00000010 +#define CCB_FLAGS_DIRECTORY_QUERY_MAPPED 0x00000020 + +// +// DirEntry flags +// + +#define AFS_DIR_RELEASE_NAME_BUFFER 0x00000001 +#define AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD 0x00000004 +#define AFS_DIR_ENTRY_NOT_IN_PARENT_TREE 0x00000008 +// Use this entry +#define AFS_DIR_ENTRY_FAKE 0x00000020 +#define AFS_DIR_RELEASE_TARGET_NAME_BUFFER 0x00000040 +#define AFS_DIR_ENTRY_VALID 0x00000080 +#define AFS_DIR_ENTRY_PENDING_DELETE 0x00000100 +#define AFS_DIR_ENTRY_DELETED 0x00000200 +#define AFS_DIR_ENTRY_SERVER_SERVICE 0x00000400 +#define AFS_DIR_ENTRY_WORKSTATION_SERVICE 0x00000800 +#define AFS_DIR_ENTRY_IPC 0x00001000 + +// +// Network provider errors +// + +#define WN_SUCCESS 0L +#define WN_ALREADY_CONNECTED 85L +#define WN_OUT_OF_MEMORY 8L +#define WN_NOT_CONNECTED 2250L +#define WN_BAD_NETNAME 67L + +#define RESOURCE_CONNECTED 0x00000001 +#define RESOURCE_GLOBALNET 0x00000002 +#define RESOURCE_REMEMBERED 0x00000003 +#define RESOURCE_RECENT 0x00000004 +#define RESOURCE_CONTEXT 0x00000005 + +#define RESOURCETYPE_ANY 0x00000000 +#define RESOURCETYPE_DISK 0x00000001 +#define RESOURCETYPE_PRINT 0x00000002 +#define RESOURCETYPE_RESERVED 0x00000008 +#define RESOURCETYPE_UNKNOWN 0xFFFFFFFF + +#define RESOURCEUSAGE_CONNECTABLE 0x00000001 +#define RESOURCEUSAGE_CONTAINER 0x00000002 +#define RESOURCEUSAGE_NOLOCALDEVICE 0x00000004 +#define RESOURCEUSAGE_SIBLING 0x00000008 +#define RESOURCEUSAGE_ATTACHED 0x00000010 +#define RESOURCEUSAGE_ALL (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED) +#define RESOURCEUSAGE_RESERVED 0x80000000 + +#define RESOURCEDISPLAYTYPE_GENERIC 0x00000000 +#define RESOURCEDISPLAYTYPE_DOMAIN 0x00000001 +#define RESOURCEDISPLAYTYPE_SERVER 0x00000002 +#define RESOURCEDISPLAYTYPE_SHARE 0x00000003 +#define RESOURCEDISPLAYTYPE_FILE 0x00000004 +#define RESOURCEDISPLAYTYPE_GROUP 0x00000005 +#define RESOURCEDISPLAYTYPE_NETWORK 0x00000006 +#define RESOURCEDISPLAYTYPE_ROOT 0x00000007 +#define RESOURCEDISPLAYTYPE_SHAREADMIN 0x00000008 +#define RESOURCEDISPLAYTYPE_DIRECTORY 0x00000009 +#define RESOURCEDISPLAYTYPE_TREE 0x0000000A +#define RESOURCEDISPLAYTYPE_NDSCONTAINER 0x0000000B + +// +// Method for determining the different control device open requests +// + +#define AFS_CONTROL_INSTANCE 0x00000001 +#define AFS_REDIRECTOR_INSTANCE 0x00000002 + +// +// Extent flags +// + +#define AFS_EXTENT_DIRTY 0x00000001 + +// +// Extent skip list sizes +// +#define AFS_NUM_EXTENT_LISTS 3 + +// +// Extents skip lists +// +// We use constant sizes. +// +#define AFS_EXTENT_SIZE (4*1024) +#define AFS_EXTENTS_LIST 0 +// +// A max of 64 extents in ther first skip list +#define AFS_EXTENT_SKIP1_BITS 6 + +// +// Then 128 bits in the second skip list +#define AFS_EXTENT_SKIP2_BITS 7 + +// +// This means that the top list skips in steps of 2^25 (=12+6+7) which +// is 32 Mb. It is to be expected that files which are massively +// larger that this will not be fully mapped. +// +#define AFS_EXTENT_SKIP1_SIZE (AFS_EXTENT_SIZE << AFS_EXTENT_SKIP1_BITS) +#define AFS_EXTENT_SKIP2_SIZE (AFS_EXTENT_SKIP1_SIZE << AFS_EXTENT_SKIP2_BITS) + +#define AFS_EXTENTS_MASKS { (AFS_EXTENT_SIZE-1), \ + (AFS_EXTENT_SKIP1_SIZE-1), \ + (AFS_EXTENT_SKIP2_SIZE-1) } + +// +// Maximum count to release at a time +// + +#define AFS_MAXIMUM_EXTENT_RELEASE_COUNT 100 + +// {41966169-3FD7-4392-AFE4-E6A9D0A92C72} - generated using guidgen.exe +DEFINE_GUID (GUID_SD_AFS_REDIRECTOR_CONTROL_OBJECT, + 0x41966169, 0x3fd7, 0x4392, 0xaf, 0xe4, 0xe6, 0xa9, 0xd0, 0xa9, 0x2c, 0x72); + +// +// Debug log length +// + +#define AFS_DBG_LOG_LENGTH 256 + +// +// Debug log flags +// + +#define AFS_DBG_LOG_WRAPPED 0x00000001 + +// +// Connection flags +// + +#define AFS_CONNECTION_FLAG_GLOBAL_SHARE 0x00000001 + +// +// Process CB flags +// + +#define AFS_PROCESS_FLAG_IS_64BIT 0x00000001 +#define AFS_PROCESS_FLAG_ACE_SET 0x00000002 +#define AFS_PROCESS_LOCAL_SYSTEM_AUTH 0x00000004 + +// +// Auth group flags +// + +#define AFS_AUTHGROUP_ACTIVE_SESSION 0x00000001 + +// +// Maximum number of special share names +// + +#define AFS_SPECIAL_SHARE_NAME_COUNT_MAX 10 + +// +// Device flags +// + +#define AFS_DEVICE_FLAG_HIDE_DOT_NAMES 0x00000001 +#define AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN 0x00000002 + +// +// Reparse tag information +// + +// +// Tag allocated to OpenAFS for DFS by Microsoft +// GUID: EF21A155-5C92-4470-AB3B-370403D96369 +// + +#ifndef IO_REPARSE_TAG_OPENAFS_DFS +#define IO_REPARSE_TAG_OPENAFS_DFS 0x00000037L +#endif + +// {EF21A155-5C92-4470-AB3B-370403D96369} +DEFINE_GUID (GUID_AFS_REPARSE_GUID, + 0xEF21A155, 0x5C92, 0x4470, 0xAB, 0x3B, 0x37, 0x04, 0x03, 0xD9, 0x63, 0x69); + +// +// Enumeration constants +// + +#define AFS_DIR_ENTRY_INITIAL_DIR_INDEX (ULONG)-3 +#define AFS_DIR_ENTRY_INITIAL_ROOT_INDEX (ULONG)-1 + +#define AFS_DIR_ENTRY_DOT_INDEX (ULONG)-2 +#define AFS_DIR_ENTRY_DOT_DOT_INDEX (ULONG)-1 + +// +// Library flags +// + +#define AFS_LIBRARY_LOADED 0x00000001 +#define AFS_LIBRARY_QUEUE_CANCELLED 0x00000002 + +// +// Custom ACE Information +// + +// {7E5D0E2F-7500-45df-857A-C0C8A2CC6BE8} +static const GUID AFSSidGuid = { 0x7f5d0e2f, 0x7500, 0x45df, { 0x85, 0x7a, 0xc0, 0xc8, 0xa2, 0xcc, 0x6b, 0xe8 } }; + +// size of our special DACL SID... S-1-8-GuidDword1-GuidDword2-GuidDword3-GuidDword4-AuthGroupGUIDDword1-AuthGroupGUIDDword2-AuthGroupGUIDDword3-AuthGroupGUIDDword4 +// Revision (1) + SubAuthorityCount (1) + IdentifierAuthority (6) + GUID (16) + AuthGruopGUID( 16) +#define AFS_DACL_SID_LENGTH 40 + +typedef +NTSTATUS +(*PAFSSetInformationToken) ( + __in HANDLE TokenHandle, + __in TOKEN_INFORMATION_CLASS TokenInformationClass, + __in_bcount(TokenInformationLength) PVOID TokenInformation, + __in ULONG TokenInformationLength + ); + +#endif /* _AFS_DEFINES_H */ diff --git a/src/WINNT/afsrdr/kernel/fs/Include/AFSExtern.h b/src/WINNT/afsrdr/kernel/fs/Include/AFSExtern.h new file mode 100644 index 0000000000..9197d584dc --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/Include/AFSExtern.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC. + * Copyright (c) 2009, 2010, 2011 Your File System, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, + * this list of conditions and the following disclaimer in the + * documentation + * and/or other materials provided with the distribution. + * - Neither the names of Kernel Drivers, LLC and Your File System, Inc. + * nor the names of their contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission from Kernel Drivers, LLC and Your File System, Inc. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AFS_EXTERN_H +#define _AFS_EXTERN_H +// +// File: AFSExtern.h +// +// + +extern "C" { + +extern PDRIVER_OBJECT AFSDriverObject; + +extern PDEVICE_OBJECT AFSDeviceObject; + +extern PDEVICE_OBJECT AFSRDRDeviceObject; + +extern FAST_IO_DISPATCH AFSFastIoDispatch; + +extern UNICODE_STRING AFSRegistryPath; + +extern ULONG AFSDebugFlags; + +extern ULONG AFSTraceLevel; + +extern ULONG AFSTraceComponent; + +extern ULONG AFSMaxDirectIo; + +extern ULONG AFSMaxDirtyFile; + +extern HANDLE AFSSysProcess; + +extern HANDLE AFSMUPHandle; + +extern UNICODE_STRING AFSServerName; + +extern UNICODE_STRING AFSGlobalRootName; + +extern ERESOURCE AFSDbgLogLock; + +extern ULONG AFSDbgLogRemainingLength; + +extern char *AFSDbgCurrentBuffer; + +extern char *AFSDbgBuffer; + +extern ULONG AFSDbgLogCounter; + +extern ULONG AFSDbgBufferLength; + +extern ULONG AFSDbgLogFlags; + +extern UNICODE_STRING AFSDumpFileLocation; + +extern CACHE_MANAGER_CALLBACKS AFSCacheManagerCallbacks; + +extern ULONG AFSAuthGroupFlags; + +extern GUID AFSActiveAuthGroup; + +extern GUID AFSNoPAGAuthGroup; + +extern PAFSSetInformationToken AFSSetInformationToken; + +extern KEVENT AFSDumpFileEvent; + +extern UNICODE_STRING AFSDumpFileName; + +extern void *AFSDumpBuffer; + +extern ULONG AFSDumpBufferLength; + +} + +#endif /* _AFS_EXTERN_H */ diff --git a/src/WINNT/afsrdr/kernel/fs/Include/AFSStructs.h b/src/WINNT/afsrdr/kernel/fs/Include/AFSStructs.h new file mode 100644 index 0000000000..65d64135b9 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/Include/AFSStructs.h @@ -0,0 +1,137 @@ +/* + * 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. + */ + +#ifndef _AFS_STRUCTS_H +#define _AFS_STRUCTS_H + +// +// File: AFSStructs.h +// + +// +// Library queue request cb +// + +typedef struct _AFS_LIBRARY_QUEUE_REQUEST_CB +{ + + struct _AFS_LIBRARY_QUEUE_REQUEST_CB *fLink; + + PIRP Irp; + +} AFSLibraryQueueRequestCB; + +typedef struct AFS_PROCESS_CB +{ + + AFSBTreeEntry TreeEntry; // HashIndex = ProcessId + + ERESOURCE Lock; + + ULONG Flags; + + ULONGLONG ParentProcessId; + + ULONGLONG CreatingThread; + + GUID *ActiveAuthGroup; + + struct _AFS_PROCESS_AUTH_GROUP_CB *AuthGroupList; + + struct AFS_THREAD_CB *ThreadList; + +} AFSProcessCB; + +typedef struct AFS_THREAD_CB +{ + + struct AFS_THREAD_CB *Next; + + ULONGLONG ThreadId; + + ULONG Flags; + + GUID *ActiveAuthGroup; + +} AFSThreadCB; + +typedef struct _AFS_SID_ENTRY_CB +{ + + AFSBTreeEntry TreeEntry; + + ULONG Flags; + + GUID AuthGroup; + +} AFSSIDEntryCB; + +typedef struct _AFS_PROCESS_AUTH_GROUP_CB +{ + + struct _AFS_PROCESS_AUTH_GROUP_CB *Next; + + ULONG Flags; + + ULONGLONG AuthGroupHash; + + GUID AuthGroup; + +} AFSProcessAuthGroupCB; + +typedef struct _AFS_SET_DACL_CB +{ + + AFSProcessCB *ProcessCB; + + NTSTATUS RequestStatus; + + KEVENT Event; + +} AFSSetDaclRequestCB; + +typedef struct _AFS_SRVTABLE_ENTRY +{ + + PVOID *ServiceTable; + + ULONG LowCall; + + ULONG HiCall; + + PVOID *ArgTable; + +} AFSSrvcTableEntry; + +#endif /* _AFS_STRUCTS_H */ diff --git a/src/WINNT/afsrdr/kernel/fs/MAKEFILE b/src/WINNT/afsrdr/kernel/fs/MAKEFILE new file mode 100644 index 0000000000..6ee4f43fa4 --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/MAKEFILE @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/src/WINNT/afsrdr/kernel/fs/sources b/src/WINNT/afsrdr/kernel/fs/sources new file mode 100644 index 0000000000..7a612392ab --- /dev/null +++ b/src/WINNT/afsrdr/kernel/fs/sources @@ -0,0 +1,46 @@ + +TARGETNAME=AFSRedir +TARGETPATH=..\..\Build +TARGETTYPE=DRIVER + +DRIVERTYPE=FS +USE_MAPSYM=1 + +INCLUDES=Include;..\..\Common; + +TARGETLIBS=$(DDK_LIB_PATH)\ntstrsafe.lib \ + $(DDK_LIB_PATH)\wdmsec.lib + +TARGETTYPE=DRIVER + +SOURCES= AFSInit.cpp \ + AFSAuthGroupSupport.cpp \ + AFSBTreeSupport.cpp \ + AFSCleanup.cpp \ + AFSClose.cpp \ + AFSCommSupport.cpp \ + AFSCreate.cpp \ + AFSData.cpp \ + AFSDevControl.cpp \ + AFSDirControl.cpp \ + AFSEa.cpp \ + AFSFastIoSupport.cpp \ + AFSFileInfo.cpp \ + AFSFlushBuffers.cpp \ + AFSFSControl.cpp \ + AFSGeneric.cpp \ + AFSInternalDevControl.cpp \ + AFSLibrarySupport.cpp \ + AFSLockControl.cpp \ + AFSLogSupport.cpp \ + AFSNetworkProviderSupport.cpp \ + AFSProcessSupport.cpp \ + AFSQuota.cpp \ + AFSRDRSupport.cpp \ + AFSRead.cpp \ + AFSSecurity.cpp \ + AFSShutdown.cpp \ + AFSSystemControl.cpp \ + AFSVolumeInfo.cpp \ + AFSWrite.cpp \ + FileSystem.rc